• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

script for distributing smart object instances along path for testing

Community Expert ,
May 30, 2015 May 30, 2015

Copy link to clipboard

Copied

If someone wants to test this Script please let me know if you notice issues.

It is supposed to distribute the selected Layers along the selected Path as Smart Object instances.

Not that much use for that, I guess, but what the hey …

pathLayersDistrTestScr.png

// distribute selected layers as smart object instances along selected path, if no path is selected use the first one;

// additional points are calculated along the path to use for positioning the instances;

// 2015, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

if (myDocument.pathItems.length > 0) {

// get id, center and half-dimensions of selected layers;

var theLayers = smartifyAndGetSelectedLayersIdxEtc();

// get selected path;

var thePath = selectedPath ();

if (thePath == undefined) {var thePath = myDocument.pathItems[0]};

////////////////////////////////////

if (theLayers.length > 0) {

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var originalResolution = myDocument.resolution;

myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);

// create a layerset to hold the copies;

var myLayerSet = myDocument.layerSets.add();

myLayerSet.name = "copies on "+thePath.name;

var theGroupIndex = getLayerIndex(myLayerSet)-1;

// collect path info, array of points, angle, distance from last point;

var thePath = getPointsOnPath2015a (myDocument, thePath);

////////////////////////////////////

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

  var theCounter = 0;

  var thisSubPath = thePath;

  var thisLayer = theNextInTheArray(theLayers, theCounter);

  var nextLayer = theNextInTheArray(theLayers, theCounter+1);

  var theDistanceCovered = 0;

  var theTargetLength = thisLayer[3];

// perform on each sub path array;

  for (var n = 0; n < thisSubPath.length; n++) {

  theDistanceCovered = theDistanceCovered + Number(thisSubPath[2]);

// if the length is met place instance at position of point with angle;

  if (theDistanceCovered >= theTargetLength) {

  theTargetLength = thisLayer[3] + nextLayer[3];

  duplicateMoveAndScale (myDocument, thisLayer[0], theGroupIndex, thisSubPath[1], thisSubPath[0][0]-thisLayer[1], thisSubPath[0][1]-thisLayer[2], 100, 100);

  theCounter++;

  var thisLayer = theNextInTheArray(theLayers, theCounter);

  var nextLayer = theNextInTheArray(theLayers, theCounter+1);

  theDistanceCovered = 0;

  }

  }

  };

////////////////////////////////////

// reset;

app.preferences.rulerUnits = originalRulerUnits;

myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);

};

////////////////////////////////////

}

};

////////////////////////////////////

////////////////////////////////////

////////////////////////////////////

////// based on code by mike hale and paul riggott //////

function selectLayerByID(index,add){

add = undefined ? add = false:add

var ref = new ActionReference();

    ref.putIdentifier(charIDToTypeID("Lyr "), index);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID("null"), ref );

       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );

      desc.putBoolean( charIDToTypeID( "MkVs" ), false );

   try{

    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );

}catch(e){

alert(e.message);

}

};

// by mike hale, via paul riggott;

function selectLayerByIndex(index,add){

// http://forums.adobe.com/message/1944754#1944754

add = undefined ? add = false:add

var ref = new ActionReference();

    ref.putIndex(charIDToTypeID("Lyr "), index);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID("null"), ref );

       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );

      desc.putBoolean( charIDToTypeID( "MkVs" ), false );

   try{

    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );

}catch(e){

alert(e.message);

}

};

// by mike hale, via paul riggott;

function getLayerIndex(theLayer){

// http://forums.adobe.com/message/1944754#1944754

app.activeDocument.activeLayer = theLayer;

//Assumes activeDocument and activeLayer

    var ref = new ActionReference();

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

    d = executeActionGet(ref);

return d.getInteger(stringIDToTypeID('itemIndex'));

};

// by mike hale, via paul riggott;

function getLayerId(theLayer){

// http://forums.adobe.com/message/1944754#1944754

app.activeDocument.activeLayer = theLayer;

//Assumes activeDocument and activeLayer

    var ref = new ActionReference();

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

    d = executeActionGet(ref);

return d.getInteger(charIDToTypeID('LyrI'));

};

////// get array of arrays of smart objects witrh index, center and half-dimensions //////

function smartifyAndGetSelectedLayersIdxEtc(){

  var selectedLayers = new Array;

  var ref = new ActionReference();

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

  var desc = executeActionGet(ref);

  if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){

  desc = desc.getList( stringIDToTypeID( 'targetLayers' ));

  var c = desc.count;

  var selectedLayers = new Array();

  for(var i=0;i<c;i++){

  try{

  activeDocument.backgroundLayer;

  selectedLayers.push(  desc.getReference( i ).getIndex() );

  }catch(e){

  selectedLayers.push(  desc.getReference( i ).getIndex()+1 );

  };

  }

  }else{

  var ref = new ActionReference();

  ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));

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

  try{

  activeDocument.backgroundLayer;

  selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);

  }catch(e){

  selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));

  };

  };

////////////////////////////////////

var theArray = new Array;

var theIDs = new Array;

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

var thisIndex = selectedLayers;

var ref = new ActionReference();

ref.putIndex( charIDToTypeID("Lyr "), thisIndex);

var layerDesc = executeActionGet(ref);

var thisID = layerDesc.getInteger(stringIDToTypeID("layerID"));

var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));

var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;

var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;

var theX = theBounds.getUnitDoubleValue(stringIDToTypeID("left")) + halfWidth;

var theY = theBounds.getUnitDoubleValue(stringIDToTypeID("top")) + halfHeight;

theIDs.push ([thisID, theX, theY, halfWidth, halfHeight])

};

////////////////////////////////////

for (var n = 0; n < theIDs.length; n++) {

if (hasSmartObject(theIDs[0]) == false) {

  try {

  selectLayerByID(theIDs[0], false);

  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 );

  theArray.push([getLayerId(app.activeDocument.activeLayer), theIDs[1], theIDs[2], theIDs[3], theIDs[4]]);

  } catch (e) {}

  }

else {theArray.push(theIDs)};

};

////////////////////////////////////

return theArray

////////////////////////////////////

//return selectedLayers;

};

////// smart object or not //////

function hasSmartObject(idx){

var ref = new ActionReference();

ref.putProperty( charIDToTypeID("Prpr") , stringIDToTypeID( "smartObject" ));

//ref.putIndex( charIDToTypeID( "Lyr " ), idx);

ref.putIdentifier( charIDToTypeID( "Lyr " ), idx);

var desc = executeActionGet(ref);

if(desc.hasKey(stringIDToTypeID('smartObject'))) {return true}

else {return false};

};

////// determine selected path, updated 08.2011 //////

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

  }

};

////// collect path info from actiondescriptor, smooth added //////

function collectPathInfoFromDesc2012 (myDocument, thePath) {

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.POINTS;

// based of functions from xbytor’s stdlib;

var ref = new ActionReference();

for (var l = 0; l < myDocument.pathItems.length; l++) {

  var thisPath = myDocument.pathItems;

  if (thisPath == thePath && thisPath.name == "Work Path") {

  ref.putProperty(cTID("Path"), cTID("WrPt"));

  };

  if (thisPath == thePath && thisPath.name != "Work Path" && thisPath.kind != PathKind.VECTORMASK) {

  ref.putIndex(cTID("Path"), l + 1);

  };

  if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {

        var idPath = charIDToTypeID( "Path" );

        var idPath = charIDToTypeID( "Path" );

        var idvectorMask = stringIDToTypeID( "vectorMask" );

        ref.putEnumerated( idPath, idPath, idvectorMask );

  };

  };

var desc = app.executeActionGet(ref);

var pname = desc.getString(cTID('PthN'));

// create new array;

var theArray = new Array;

var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));

// for subpathitems;

for (var m = 0; m < pathComponents.count; m++) {

  var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));

  var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));

  switch (operation1) {

  case 1097098272:

  var operation = 1097098272 //cTID('Add ');

  break;

  case 1398961266:

  var operation = 1398961266 //cTID('Sbtr');

  break;

  case 1231975538:

  var operation = 1231975538 //cTID('Intr');

  break;

  default:

// case 1102:

  var operation = sTID('xor') //ShapeOperation.SHAPEXOR;

  break;

  };

// for subpathitem’s count;

  for (var n = 0; n < listKey.count; n++) {

  theArray.push(new Array);

  var points = listKey.getObjectValue(n).getList(sTID('points'));

  try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}

  catch (e) {var closed = false};

// for subpathitem’s segment’s number of points;

  for (var o = 0; o < points.count; o++) {

  var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));

  var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];

  var thisPoint = [anchor];

  try {

  var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));

  var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];

  thisPoint.push(leftDirection)

  }

  catch (e) {

  thisPoint.push(anchor)

  };

  try {

  var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));

  var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];

  thisPoint.push(rightDirection)

  }

  catch (e) {

  thisPoint.push(anchor)

  };

  try {

  var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));

  thisPoint.push(smoothOr)

  }

  catch (e) {thisPoint.push(false)};

  theArray[theArray.length - 1].push(thisPoint);

  };

  theArray[theArray.length - 1].push(closed);

  theArray[theArray.length - 1].push(operation);

  };

  };

// by xbytor, thanks to him;

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

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

// reset;

app.preferences.rulerUnits = originalRulerUnits;

return theArray;

};

////// determine length of path by creating additional points, by SATO Hiroyuki //////

function getLength(q, div_num){

////// from //////

// Path Length.js;

// Copyright(c) 2009 SATO Hiroyuki

// http://park12.wakwak.com/~shp/lc/et/en_aics_script.html

// ------------------------------------------------

// return the segment length

// segment = part of a path between 2 anchors

// q = [Q0[x,y],Q1,Q2,Q3], div_num = division number

// Simpson's method : with simplified coefficients to speed-up

  var div_unit = 1 / div_num;

  var m = [q[3][0] - q[0][0] + 3 * (q[1][0] - q[2][0]),

           q[0][0] - 2 * q[1][0] + q[2][0],

           q[1][0] - q[0][0]];

  var n = [q[3][1] - q[0][1] + 3 * (q[1][1] - q[2][1]),

           q[0][1] - 2 * q[1][1] + q[2][1],

           q[1][1] - q[0][1]];

  var k = [m[0] * m[0] + n[0] * n[0],

           4 * (m[0] * m[1] + n[0] * n[1]),

           2 * ((m[0] * m[2] + n[0] * n[2]) + 2 * (m[1] * m[1] + n[1] * n[1])),

           4 * (m[1] * m[2] + n[1] * n[2]),

           m[2] * m[2] + n[2] * n[2]];

  var fc = function(t, k){

    return Math.sqrt(t * ( t * ( t * ( t * k[0] + k[1]) + k[2]) + k[3]) + k[4]) || 0;

  };

  var total = 0;

  var i;

  for(i = 1; i < div_num; i += 2){

    total += fc(i * div_unit, k);

  };

  total *= 2;

  for(i = 2; i < div_num; i += 2){

    total += fc(i * div_unit, k);

  };

  return (fc(0, k) + fc(1, k) + total * 2) * div_unit;

};

////// function to get array of points on a path; with the direction and distance to previous point //////

function getPointsOnPath2015a (myDocument, thePath) {

/*var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var originalResolution = app.activeDocument.resolution;

app.activeDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);*/

////////////////////////////////////

// get path info;

var theArray = collectPathInfoFromDesc2012(myDocument, thePath);

////////////////////////////////////

// create a high number of new points along the subpaths;

var hypotheticalPoints = new Array;

// and collect the distances;

var theDistances = new Array;

// work through the original array;

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

  var theSubArray = theArray;

  var oneSubPath = new Array;

  var closed = theSubArray[theSubArray.length - 2];

// change sub array;

  theSubArray = theSubArray.slice(0, theSubArray.length - 2);

  theSubArray.push(theArray[0]);

  theSubArray.push(theArray[1]);

  theSubArray.push(theArray[theArray.length-2]);

  theSubArray.push(theArray[theArray.length-1]);

// if closed;

  if (closed == true) {

  var theSegments = theSubArray.length - 4

  }

// if not closed;

  else {

  var theSegments = theSubArray.length - 5;

  };

// add first point;

  var pointA = theArray[0][0];

  var handleA = theArray[0][1];

  var pointB = theArray[1][0];

  var handleB = theArray[1][2];

// add angle to ne next point;

  if (pointA == handleA) {var theAngle = getAngle(pointA, handleB)}

  else {var theAngle = getAngle(pointA, handleA)};

  oneSubPath.push([pointA, theAngle, 0]);

// add points;

  for (var n = 1; n <= theSegments; n++) {

// the in-between points;

  var theNumberOfPoints = Math.round(getLength([pointA, handleA, handleB, pointB], 100)) * 3;

  for (var o = 1; o < theNumberOfPoints; o++) {

  var theFragment = 1 / theNumberOfPoints * o;

  oneSubPath.push(bezierPoint (theFragment, pointA, handleA, pointB, handleB));

  var theDist = getDistance (oneSubPath[oneSubPath.length-2][0], oneSubPath[oneSubPath.length-1][0])

  oneSubPath[oneSubPath.length-1].push(theDist)

  };

// the next point;

  var pointA = theSubArray[0];

  var handleA = theSubArray[1];

  var theNext = n + 1;

  var pointB = theSubArray[theNext][0];

  var handleB = theSubArray[theNext][2];

// get angle;

  if (pointA != handleB) {var theAngle = getAngle(pointA, handleB)}

  else {var theAngle = getAngle(theSubArray[n-1][1], pointA)};

// angle for the last point;

  if (n == theSegments) {

  var theAngle = getAngle(pointA, theSubArray[1])

  };

// add point;

  var theDist = getDistance (theSubArray[0], oneSubPath[oneSubPath.length-1][0])

  oneSubPath.push([theSubArray[0], theAngle, theDist])

  };

  hypotheticalPoints.push(oneSubPath);

  };

return hypotheticalPoints

};

////// get point on bezier curve and angle //////

function bezierPoint (theFragment, pointA, handleA, pointB, handleB) {

// the horizontal;

  var theOne = (handleA[0] - pointA[0]) * theFragment + pointA[0];

  var theTwo = (handleB[0] - handleA[0]) * theFragment + handleA[0];

  var theThree = (pointB[0] - handleB[0]) * theFragment + handleB[0];

  var theOneTwoH = (theTwo - theOne) * theFragment + theOne;

  var theTwoThreeH = (theThree - theTwo) * theFragment + theTwo;

  var theX = (theTwoThreeH - theOneTwoH) * theFragment + theOneTwoH;

// the vertical;

  var theOne = (handleA[1] - pointA[1]) * theFragment + pointA[1];

  var theTwo = (handleB[1] - handleA[1]) * theFragment + handleA[1];

  var theThree = (pointB[1] - handleB[1]) * theFragment + handleB[1];

  var theOneTwoV = (theTwo - theOne) * theFragment + theOne;

  var theTwoThreeV = (theThree - theTwo) * theFragment + theTwo;

  var theY = (theTwoThreeV - theOneTwoV) * theFragment + theOneTwoV;

// the point;

  var thePoint = [[theX, theY], getAngle ([theOneTwoH, theOneTwoV], [theTwoThreeH, theTwoThreeV])];

// var thePoint = [[theX, theY],;

  return thePoint

  };

////// radians //////

function radiansOf (theAngle) {

  return theAngle * Math.PI / 180

  };

////// angle from radians //////

function angleFromRadians (theRad) {

  return theRad / Math.PI * 180

  };

////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////

function getAngle (pointOne, pointTwo) {

// calculate the triangle sides;

  var width = pointTwo[0] - pointOne[0];

  var height = pointTwo[1] - pointOne[1];

  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));

// calculate the angles;

  if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}

  else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};

  if (theAngle < 0) {theAngle = (360 + theAngle)};

// if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};

  return theAngle

  };

////// get a distance between two points //////

function getDistance (pointOne, pointTwo) {

// calculate the triangle sides;

  var width = pointTwo[0] - pointOne[0];

  var height = pointTwo[1] - pointOne[1];

  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));

  return sideC

  };

////// rotate and move //////

function duplicateMoveAndScale (myDocument, theIndex, theGroupIndex, thisAngle, horizontalOffset, verticalOffset, horScale, verScale) {

// duplicate by index;

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

var idmove = charIDToTypeID( "move" );

    var desc8 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref8 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        ref8.putIdentifier( charIDToTypeID( "Lyr " ), theIndex );

    desc8.putReference( idnull, ref8 );

    var idT = charIDToTypeID( "T   " );

        var ref9 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        ref9.putIndex( idLyr, theGroupIndex );

    desc8.putReference( idT, ref9 );

    var idDplc = charIDToTypeID( "Dplc" );

    desc8.putBoolean( idDplc, true );

    var idAdjs = charIDToTypeID( "Adjs" );

    desc8.putBoolean( idAdjs, false );

    var idVrsn = charIDToTypeID( "Vrsn" );

    desc8.putInteger( idVrsn, 5 );

executeAction( idmove, desc8, DialogModes.NO );

// do the transformations;

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

var idTrnf = charIDToTypeID( "Trnf" );

    var desc3 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref2 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref2.putEnumerated( idLyr, idOrdn, idTrgt );

    desc3.putReference( idnull, ref2 );

    var idFTcs = charIDToTypeID( "FTcs" );

    var idQCSt = charIDToTypeID( "QCSt" );

    var idQcsa = charIDToTypeID( "Qcsa" );

    desc3.putEnumerated( idFTcs, idQCSt, idQcsa );

    var idOfst = charIDToTypeID( "Ofst" );

        var desc4 = new ActionDescriptor();

        var idHrzn = charIDToTypeID( "Hrzn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc4.putUnitDouble( idHrzn, idPxl, horizontalOffset );

        var idVrtc = charIDToTypeID( "Vrtc" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc4.putUnitDouble( idVrtc, idPxl, verticalOffset );

    var idOfst = charIDToTypeID( "Ofst" );

    desc3.putObject( idOfst, idOfst, desc4 );

    var idWdth = charIDToTypeID( "Wdth" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc3.putUnitDouble( idWdth, idPrc, horScale );

    var idHght = charIDToTypeID( "Hght" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc3.putUnitDouble( idHght, idPrc, verScale );

if (thisAngle != 0) {

    var idAngl = charIDToTypeID( "Angl" );

    var idAng = charIDToTypeID( "#Ang" );

    desc3.putUnitDouble( idAngl, idAng, thisAngle );

  };

executeAction( idTrnf, desc3, DialogModes.NO );

};

////// get netx in an array circularly //////

function theNextInTheArray (theArray, theNumber) {

if (theNumber < theArray.length - 1) {return theArray[theNumber]}

else {

  var theNumber = theNumber - (Math.floor(theNumber / theArray.length )) * theArray.length;

  return theArray[theNumber]

  }

};

TOPICS
Actions and scripting

Views

4.3K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
May 30, 2015 May 30, 2015

Copy link to clipboard

Copied

Nice play thing

capture.jpg

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Thanks for taking the time.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

I Added a toggle pallets at the beginning and end to speed execution up my processors are onle 2GHz. 

Atom.gif

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

I Added a toggle pallets at the beginning and end to speed execution up

Good point.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Another point:

If the language of PS is not english && the pathItems[0] is a "Workpath", than the script fails.

Perhaps is could be better to use the pathItems[0].kind instead of the pathItems[0].name for "Workpaths".

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Perhaps is could be better to use the pathItems[0].kind instead of the pathItems[0].name for "Workpaths".

Very much so!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Very nice!

path-script.jpg

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Hi c.pfaffenbichler‌,

I do not have the latest versions here.

And I get no result because of

line 148: var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2; 

seems not compatible with older versions.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Which Photoshop version do you use?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

I use my own PS CS3 and have now tested in addition with the PS CS5 (64 bit) of my son.

--> the same result: error in line 148

»Allgemeiner Photoshop-Fehler. Die Funktion steht in dieser Version von Photoship möglicherweise nicht zur Verfügung«

Translation:  General Photoshop error occured. This functionality may not be available in this version of Photoshop.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

What do you get when you run this?

#target photoshop

if (app.documents.length > 0) {

var ref = new ActionReference();

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

var layerDesc = executeActionGet(ref);

var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));

checkDesc2 (theBounds)

};

////// based on code by michael l hale //////

function checkDesc2 (theDesc) {

var c = theDesc.count;

var str = '';

for(var i=0;i<c;i++){ //enumerate descriptor's keys

  str = str + 'Key '+i+' = '+typeIDToStringID(theDesc.getKey(i))+': '+theDesc.getType(theDesc.getKey(i))+'\n'+getValues (theDesc, i)+'\n';

  };

alert("desc\n\n"+str);

};

////// check //////

function getValues (theDesc, theNumber) {

switch (theDesc.getType(theDesc.getKey(theNumber))) {

case DescValueType.BOOLEANTYPE:

return theDesc.getBoolean(theDesc.getKey(theNumber));

break;

case DescValueType.CLASSTYPE:

return theDesc.getClass(theDesc.getKey(theNumber));

break;

case DescValueType.DOUBLETYPE:

return theDesc.getDouble(theDesc.getKey(theNumber));

break;

case DescValueType.ENUMERATEDTYPE:

return (typeIDToStringID(theDesc.getEnumerationValue(theDesc.getKey(theNumber)))+"_"+typeIDToStringID(theDesc.getEnumerationType(theDesc.getKey(theNumber))));

break;

case DescValueType.INTEGERTYPE:

return theDesc.getInteger(theDesc.getKey(theNumber));

break;

case DescValueType.LISTTYPE:

return theDesc.getList(theDesc.getKey(theNumber));

break;

case DescValueType.OBJECTTYPE:

return (theDesc.getObjectValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getObjectType(theDesc.getKey(theNumber))));

break;

case DescValueType.REFERENCETYPE:

return theDesc.getReference(theDesc.getKey(theNumber));

break;

case DescValueType.STRINGTYPE:

return theDesc.getString(theDesc.getKey(theNumber));

break;

case DescValueType.UNITDOUBLE:

return (theDesc.getUnitDoubleValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getUnitDoubleType(theDesc.getKey(theNumber))));

break;

default:

break;

};

};

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

In CS3 I get this:

desc

Key 0 = top: DescValueType.UNITDOUBLE

188_pixelsUnit

Key 1 = left: DescValueType.UNITDOUBLE

238_pixelsUnit

Key 2 = bottom: DescValueType.UNITDOUBLE

222_pixelsUnit

Key 3 = right: DescValueType.UNITDOUBLE

276_pixelsUnit

and in CS5 I get:

desc

Key 0 = top: DescValueType.UNITDOUBLE

416_pixelsUnit

Key 1 = left: DescValueType.UNITDOUBLE

642_pixelsUnit

Key 2 = bottom: DescValueType.UNITDOUBLE

467_pixelsUnit

Key 3 = right: DescValueType.UNITDOUBLE

692_pixelsUnit

It seems to be the same in both versions.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

On Photoshop CC I get

Key 0 = top: DescValueType.UNITDOUBLE

1647_pixelsUnit

Key 1 = left: DescValueType.UNITDOUBLE

1510_pixelsUnit

Key 2 = bottom: DescValueType.UNITDOUBLE

2440_pixelsUnit

Key 3 = right: DescValueType.UNITDOUBLE

2561_pixelsUnit

Key 4 = width: DescValueType.UNITDOUBLE

1051_pixelsUnit

Key 5 = height: DescValueType.UNITDOUBLE

793_pixelsUnit

Amending the lines

var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;

var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;

to

var halfWidth = (theBounds.getUnitDoubleValue(stringIDToTypeID("right")) - theBounds.getUnitDoubleValue(stringIDToTypeID("left"))) / 2;

var halfHeight = (theBounds.getUnitDoubleValue(stringIDToTypeID("bottom")) - theBounds.getUnitDoubleValue(stringIDToTypeID("top"))) / 2;

should solve that issue.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

This works with CS3:

replace these two lines:

var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;

var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;

with this:

var halfWidth = (theBounds.getUnitDoubleValue(stringIDToTypeID("right")) - theBounds.getUnitDoubleValue(stringIDToTypeID("left")) ) / 2;

var halfHeight = (theBounds.getUnitDoubleValue(stringIDToTypeID("bottom")) - theBounds.getUnitDoubleValue(stringIDToTypeID("top")) ) / 2;

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

I see you just posted the solution yourself.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

Two brains - one thought.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 31, 2015 May 31, 2015

Copy link to clipboard

Copied

It seems, that earlier versions of PS don't know the value for width and height.

But now your script runs also with CS3

c_pfaffenbichler2.png

Perhaps You could built in neverinteract with all (to suppress this message - convert to Smart object)

c_pfaffenbichler3.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 01, 2015 Jun 01, 2015

Copy link to clipboard

Copied

Thank you all for your posts.

I wondered if I just can’t remember or figure out how to assign posts the "helpful" label but it seems the OP does not have that option anymore:

How to mark a post/reply as helpful?

So, despite thus bloating the "like"-count of a thread I started myself, I just "like"-d a couple of them.

I suppose the Script could (apart from the performance- and language-related issues JJMack and pixel schubser have pointed out) do with some more checks to avoid tripping it up (like deselecting if a Selection is active), but I do not intend to publish it "professionally" anyway …

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 25, 2016 Aug 25, 2016

Copy link to clipboard

Copied

two years ago I wrote a script to design the wave pattern of the Copacabana pathway (just for fun).

Unfortunately I didn't find out yet how to fill the solid B&W pattern with the typical mosaic stone pieces.

Now your script is raising hope to solve this problem distributing layers along the wavelike paths.

I'll take a new run asap.

Thanks for this inspiring script!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

HI, I'm new here, and I'm very interested in this script.  Not sure if you think it needs more testing, but I would like to exercise your script over the next few days.  Can I rely on the script as posted above, or should I download a different version - and if so, from where?  I'm very much a javascript novice, so I have to rely on extensive coding experience that is now very old.  Amazing to me how much of today's world relies on an interpreted language that permits self-modification, but I guess nothing stays the same.

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

This is the last version I did, but I may not have included all improvements mentioned by the others:

// distribute selected layers as smart object instances along selected path, if no path is selected use the first one;

// additional points are calculated along the path to use for positioning the instances;

// 2015, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

if (myDocument.pathItems.length > 0) {

// get id, center and half-dimensions of selected layers;

var theLayers = smartifyAndGetSelectedLayersIdxEtc();

// get selected path;

var thePath = selectedPath2015 ();

if (thePath == undefined) {var thePath = myDocument.pathItems[0]};

////////////////////////////////////

if (theLayers.length > 0) {

app.togglePalettes();

myDocument.selection.deselect();

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var originalResolution = myDocument.resolution;

myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);

// create a layerset to hold the copies;

var myLayerSet = myDocument.layerSets.add();

myLayerSet.name = "copies on "+thePath.name;

var theGroupIndex = getLayerIndex(myLayerSet)-1;

// collect path info, array of points, angle, distance from last point;

var thePath = getPointsOnPath2015a (myDocument, thePath);

////////////////////////////////////

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

  var theCounter = 0;

  var thisSubPath = thePath;

  var thisLayer = theNextInTheArray(theLayers, theCounter);

  var nextLayer = theNextInTheArray(theLayers, theCounter+1);

  var theDistanceCovered = 0;

  var theTargetLength = thisLayer[3];

// perform on each sub path array;

  for (var n = 0; n < thisSubPath.length; n++) {

  theDistanceCovered = theDistanceCovered + Number(thisSubPath[2]);

// if the length is met place instance at position of point with angle;

  if (theDistanceCovered >= theTargetLength) {

  theTargetLength = thisLayer[3] + nextLayer[3];

  duplicateMoveAndScale (myDocument, thisLayer[0], theGroupIndex, thisSubPath[1], thisSubPath[0][0]-thisLayer[1], thisSubPath[0][1]-thisLayer[2], 100, 100);

  theCounter++;

  var thisLayer = theNextInTheArray(theLayers, theCounter);

  var nextLayer = theNextInTheArray(theLayers, theCounter+1);

  theDistanceCovered = 0;

  }

  }

  };

////////////////////////////////////

// reset;

app.preferences.rulerUnits = originalRulerUnits;

myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);

app.togglePalettes();

};

////////////////////////////////////

}

};

////////////////////////////////////

////////////////////////////////////

////////////////////////////////////

////// based on code by mike hale and paul riggott //////

function selectLayerByID(index,add){

add = undefined ? add = false:add

var ref = new ActionReference();

    ref.putIdentifier(charIDToTypeID("Lyr "), index);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID("null"), ref );

       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );

      desc.putBoolean( charIDToTypeID( "MkVs" ), false );

   try{

    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );

}catch(e){

alert(e.message);

}

};

// by mike hale, via paul riggott;

function selectLayerByIndex(index,add){

// http://forums.adobe.com/message/1944754#1944754

add = undefined ? add = false:add

var ref = new ActionReference();

    ref.putIndex(charIDToTypeID("Lyr "), index);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID("null"), ref );

       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );

      desc.putBoolean( charIDToTypeID( "MkVs" ), false );

   try{

    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );

}catch(e){

alert(e.message);

}

};

// by mike hale, via paul riggott;

function getLayerIndex(theLayer){

// http://forums.adobe.com/message/1944754#1944754

app.activeDocument.activeLayer = theLayer;

//Assumes activeDocument and activeLayer

    var ref = new ActionReference();

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

    d = executeActionGet(ref);

return d.getInteger(stringIDToTypeID('itemIndex'));

};

// by mike hale, via paul riggott;

function getLayerId(theLayer){

// http://forums.adobe.com/message/1944754#1944754

app.activeDocument.activeLayer = theLayer;

//Assumes activeDocument and activeLayer

    var ref = new ActionReference();

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

    d = executeActionGet(ref);

return d.getInteger(charIDToTypeID('LyrI'));

};

////// get array of arrays of smart objects witrh index, center and half-dimensions //////

function smartifyAndGetSelectedLayersIdxEtc(){

  var selectedLayers = new Array;

  var ref = new ActionReference();

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

  var desc = executeActionGet(ref);

  if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){

  desc = desc.getList( stringIDToTypeID( 'targetLayers' ));

  var c = desc.count;

  var selectedLayers = new Array();

  for(var i=0;i<c;i++){

  try{

  activeDocument.backgroundLayer;

  selectedLayers.push(  desc.getReference( i ).getIndex() );

  }catch(e){

  selectedLayers.push(  desc.getReference( i ).getIndex()+1 );

  };

  }

  }else{

  var ref = new ActionReference();

  ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));

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

  try{

  activeDocument.backgroundLayer;

  selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);

  }catch(e){

  selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));

  };

  };

////////////////////////////////////

var theArray = new Array;

var theIDs = new Array;

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

var thisIndex = selectedLayers;

var ref = new ActionReference();

ref.putIndex( charIDToTypeID("Lyr "), thisIndex);

var layerDesc = executeActionGet(ref);

var thisID = layerDesc.getInteger(stringIDToTypeID("layerID"));

var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));

var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;

var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;

var theX = theBounds.getUnitDoubleValue(stringIDToTypeID("left")) + halfWidth;

var theY = theBounds.getUnitDoubleValue(stringIDToTypeID("top")) + halfHeight;

theIDs.push ([thisID, theX, theY, halfWidth, halfHeight])

};

////////////////////////////////////

for (var n = 0; n < theIDs.length; n++) {

if (hasSmartObject(theIDs[0]) == false) {

  try {

  selectLayerByID(theIDs[0], false);

  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 );

  theArray.push([getLayerId(app.activeDocument.activeLayer), theIDs[1], theIDs[2], theIDs[3], theIDs[4]]);

  } catch (e) {}

  }

else {theArray.push(theIDs)};

};

////////////////////////////////////

return theArray

////////////////////////////////////

//return selectedLayers;

};

////// smart object or not //////

function hasSmartObject(idx){

var ref = new ActionReference();

ref.putProperty( charIDToTypeID("Prpr") , stringIDToTypeID( "smartObject" ));

//ref.putIndex( charIDToTypeID( "Lyr " ), idx);

ref.putIdentifier( charIDToTypeID( "Lyr " ), idx);

var desc = executeActionGet(ref);

if(desc.hasKey(stringIDToTypeID('smartObject'))) {return true}

else {return false};

};

////// determine selected path, updated 09.2015 //////

function selectedPath2015 () {

try {

var ref = new ActionReference();

ref.putProperty (stringIDToTypeID("property"), stringIDToTypeID("targetPathIndex"));

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

var docDesc = executeActionGet(ref);

return app.activeDocument.pathItems[docDesc.getInteger(stringIDToTypeID("targetPathIndex"))]

}

catch (e) {return undefined}

};

////// collect path info from actiondescriptor, smooth added //////

function collectPathInfoFromDesc2012 (myDocument, thePath) {

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.POINTS;

// based of functions from xbytor’s stdlib;

var ref = new ActionReference();

for (var l = 0; l < myDocument.pathItems.length; l++) {

  var thisPath = myDocument.pathItems;

  if (thisPath == thePath && thisPath.kind == PathKind.WORKPATH) {

  ref.putProperty(cTID("Path"), cTID("WrPt"));

  };

  if (thisPath == thePath && thisPath.kind != PathKind.WORKPATH && thisPath.kind != PathKind.VECTORMASK) {

  ref.putIndex(cTID("Path"), l + 1);

  };

  if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {

        var idPath = charIDToTypeID( "Path" );

        var idPath = charIDToTypeID( "Path" );

        var idvectorMask = stringIDToTypeID( "vectorMask" );

        ref.putEnumerated( idPath, idPath, idvectorMask );

  };

  };

var desc = app.executeActionGet(ref);

var pname = desc.getString(cTID('PthN'));

// create new array;

var theArray = new Array;

var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));

// for subpathitems;

for (var m = 0; m < pathComponents.count; m++) {

  var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));

  var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));

  switch (operation1) {

  case 1097098272:

  var operation = 1097098272 //cTID('Add ');

  break;

  case 1398961266:

  var operation = 1398961266 //cTID('Sbtr');

  break;

  case 1231975538:

  var operation = 1231975538 //cTID('Intr');

  break;

  default:

// case 1102:

  var operation = sTID('xor') //ShapeOperation.SHAPEXOR;

  break;

  };

// for subpathitem’s count;

  for (var n = 0; n < listKey.count; n++) {

  theArray.push(new Array);

  var points = listKey.getObjectValue(n).getList(sTID('points'));

  try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}

  catch (e) {var closed = false};

// for subpathitem’s segment’s number of points;

  for (var o = 0; o < points.count; o++) {

  var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));

  var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];

  var thisPoint = [anchor];

  try {

  var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));

  var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];

  thisPoint.push(leftDirection)

  }

  catch (e) {

  thisPoint.push(anchor)

  };

  try {

  var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));

  var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];

  thisPoint.push(rightDirection)

  }

  catch (e) {

  thisPoint.push(anchor)

  };

  try {

  var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));

  thisPoint.push(smoothOr)

  }

  catch (e) {thisPoint.push(false)};

  theArray[theArray.length - 1].push(thisPoint);

  };

  theArray[theArray.length - 1].push(closed);

  theArray[theArray.length - 1].push(operation);

  };

  };

// by xbytor, thanks to him;

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

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

// reset;

app.preferences.rulerUnits = originalRulerUnits;

return theArray;

};

////// determine length of path by creating additional points, by SATO Hiroyuki //////

function getLength(q, div_num){

////// from //////

// Path Length.js;

// Copyright(c) 2009 SATO Hiroyuki

// http://park12.wakwak.com/~shp/lc/et/en_aics_script.html

// ------------------------------------------------

// return the segment length

// segment = part of a path between 2 anchors

// q = [Q0[x,y],Q1,Q2,Q3], div_num = division number

// Simpson's method : with simplified coefficients to speed-up

  var div_unit = 1 / div_num;

  var m = [q[3][0] - q[0][0] + 3 * (q[1][0] - q[2][0]),

           q[0][0] - 2 * q[1][0] + q[2][0],

           q[1][0] - q[0][0]];

  var n = [q[3][1] - q[0][1] + 3 * (q[1][1] - q[2][1]),

           q[0][1] - 2 * q[1][1] + q[2][1],

           q[1][1] - q[0][1]];

  var k = [m[0] * m[0] + n[0] * n[0],

           4 * (m[0] * m[1] + n[0] * n[1]),

           2 * ((m[0] * m[2] + n[0] * n[2]) + 2 * (m[1] * m[1] + n[1] * n[1])),

           4 * (m[1] * m[2] + n[1] * n[2]),

           m[2] * m[2] + n[2] * n[2]];

  var fc = function(t, k){

    return Math.sqrt(t * ( t * ( t * ( t * k[0] + k[1]) + k[2]) + k[3]) + k[4]) || 0;

  };

  var total = 0;

  var i;

  for(i = 1; i < div_num; i += 2){

    total += fc(i * div_unit, k);

  };

  total *= 2;

  for(i = 2; i < div_num; i += 2){

    total += fc(i * div_unit, k);

  };

  return (fc(0, k) + fc(1, k) + total * 2) * div_unit;

};

////// function to get array of points on a path; with the direction and distance to previous point //////

function getPointsOnPath2015a (myDocument, thePath) {

/*var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var originalResolution = app.activeDocument.resolution;

app.activeDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);*/

////////////////////////////////////

// get path info;

var theArray = collectPathInfoFromDesc2012(myDocument, thePath);

////////////////////////////////////

// create a high number of new points along the subpaths;

var hypotheticalPoints = new Array;

// and collect the distances;

var theDistances = new Array;

// work through the original array;

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

  var theSubArray = theArray;

  var oneSubPath = new Array;

  var closed = theSubArray[theSubArray.length - 2];

// change sub array;

  theSubArray = theSubArray.slice(0, theSubArray.length - 2);

  theSubArray.push(theArray[0]);

  theSubArray.push(theArray[1]);

  theSubArray.push(theArray[theArray.length-2]);

  theSubArray.push(theArray[theArray.length-1]);

// if closed;

  if (closed == true) {

  var theSegments = theSubArray.length - 4

  }

// if not closed;

  else {

  var theSegments = theSubArray.length - 5;

  };

// add first point;

  var pointA = theArray[0][0];

  var handleA = theArray[0][1];

  var pointB = theArray[1][0];

  var handleB = theArray[1][2];

// add angle to ne next point;

  if (pointA == handleA) {var theAngle = getAngle(pointA, handleB)}

  else {var theAngle = getAngle(pointA, handleA)};

  oneSubPath.push([pointA, theAngle, 0]);

// add points;

  for (var n = 1; n <= theSegments; n++) {

// the in-between points;

  var theNumberOfPoints = Math.round(getLength([pointA, handleA, handleB, pointB], 100)) * 3;

  for (var o = 1; o < theNumberOfPoints; o++) {

  var theFragment = 1 / theNumberOfPoints * o;

  oneSubPath.push(bezierPoint (theFragment, pointA, handleA, pointB, handleB));

  var theDist = getDistance (oneSubPath[oneSubPath.length-2][0], oneSubPath[oneSubPath.length-1][0])

  oneSubPath[oneSubPath.length-1].push(theDist)

  };

// the next point;

  var pointA = theSubArray[0];

  var handleA = theSubArray[1];

  var theNext = n + 1;

  var pointB = theSubArray[theNext][0];

  var handleB = theSubArray[theNext][2];

// get angle;

  if (pointA != handleB) {var theAngle = getAngle(pointA, handleB)}

  else {var theAngle = getAngle(theSubArray[n-1][1], pointA)};

// angle for the last point;

  if (n == theSegments) {

  var theAngle = getAngle(pointA, theSubArray[1])

  };

// add point;

  var theDist = getDistance (theSubArray[0], oneSubPath[oneSubPath.length-1][0])

  oneSubPath.push([theSubArray[0], theAngle, theDist])

  };

  hypotheticalPoints.push(oneSubPath);

  };

return hypotheticalPoints

};

////// get point on bezier curve and angle //////

function bezierPoint (theFragment, pointA, handleA, pointB, handleB) {

// the horizontal;

  var theOne = (handleA[0] - pointA[0]) * theFragment + pointA[0];

  var theTwo = (handleB[0] - handleA[0]) * theFragment + handleA[0];

  var theThree = (pointB[0] - handleB[0]) * theFragment + handleB[0];

  var theOneTwoH = (theTwo - theOne) * theFragment + theOne;

  var theTwoThreeH = (theThree - theTwo) * theFragment + theTwo;

  var theX = (theTwoThreeH - theOneTwoH) * theFragment + theOneTwoH;

// the vertical;

  var theOne = (handleA[1] - pointA[1]) * theFragment + pointA[1];

  var theTwo = (handleB[1] - handleA[1]) * theFragment + handleA[1];

  var theThree = (pointB[1] - handleB[1]) * theFragment + handleB[1];

  var theOneTwoV = (theTwo - theOne) * theFragment + theOne;

  var theTwoThreeV = (theThree - theTwo) * theFragment + theTwo;

  var theY = (theTwoThreeV - theOneTwoV) * theFragment + theOneTwoV;

// the point;

  var thePoint = [[theX, theY], getAngle ([theOneTwoH, theOneTwoV], [theTwoThreeH, theTwoThreeV])];

// var thePoint = [[theX, theY],;

  return thePoint

  };

////// radians //////

function radiansOf (theAngle) {

  return theAngle * Math.PI / 180

  };

////// angle from radians //////

function angleFromRadians (theRad) {

  return theRad / Math.PI * 180

  };

////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////

function getAngle (pointOne, pointTwo) {

// calculate the triangle sides;

  var width = pointTwo[0] - pointOne[0];

  var height = pointTwo[1] - pointOne[1];

  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));

// calculate the angles;

  if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}

  else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};

  if (theAngle < 0) {theAngle = (360 + theAngle)};

// if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};

  return theAngle

  };

////// get a distance between two points //////

function getDistance (pointOne, pointTwo) {

// calculate the triangle sides;

  var width = pointTwo[0] - pointOne[0];

  var height = pointTwo[1] - pointOne[1];

  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));

  return sideC

  };

////// rotate and move //////

function duplicateMoveAndScale (myDocument, theIndex, theGroupIndex, thisAngle, horizontalOffset, verticalOffset, horScale, verScale) {

// duplicate by index;

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

var idmove = charIDToTypeID( "move" );

    var desc8 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref8 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        ref8.putIdentifier( charIDToTypeID( "Lyr " ), theIndex );

    desc8.putReference( idnull, ref8 );

    var idT = charIDToTypeID( "T   " );

        var ref9 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        ref9.putIndex( idLyr, theGroupIndex );

    desc8.putReference( idT, ref9 );

    var idDplc = charIDToTypeID( "Dplc" );

    desc8.putBoolean( idDplc, true );

    var idAdjs = charIDToTypeID( "Adjs" );

    desc8.putBoolean( idAdjs, false );

    var idVrsn = charIDToTypeID( "Vrsn" );

    desc8.putInteger( idVrsn, 5 );

executeAction( idmove, desc8, DialogModes.NO );

// do the transformations;

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

var idTrnf = charIDToTypeID( "Trnf" );

    var desc3 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref2 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref2.putEnumerated( idLyr, idOrdn, idTrgt );

    desc3.putReference( idnull, ref2 );

    var idFTcs = charIDToTypeID( "FTcs" );

    var idQCSt = charIDToTypeID( "QCSt" );

    var idQcsa = charIDToTypeID( "Qcsa" );

    desc3.putEnumerated( idFTcs, idQCSt, idQcsa );

    var idOfst = charIDToTypeID( "Ofst" );

        var desc4 = new ActionDescriptor();

        var idHrzn = charIDToTypeID( "Hrzn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc4.putUnitDouble( idHrzn, idPxl, horizontalOffset );

        var idVrtc = charIDToTypeID( "Vrtc" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc4.putUnitDouble( idVrtc, idPxl, verticalOffset );

    var idOfst = charIDToTypeID( "Ofst" );

    desc3.putObject( idOfst, idOfst, desc4 );

    var idWdth = charIDToTypeID( "Wdth" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc3.putUnitDouble( idWdth, idPrc, horScale );

    var idHght = charIDToTypeID( "Hght" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc3.putUnitDouble( idHght, idPrc, verScale );

if (thisAngle != 0) {

    var idAngl = charIDToTypeID( "Angl" );

    var idAng = charIDToTypeID( "#Ang" );

    desc3.putUnitDouble( idAngl, idAng, thisAngle );

  };

executeAction( idTrnf, desc3, DialogModes.NO );

};

////// get netx in an array circularly //////

function theNextInTheArray (theArray, theNumber) {

if (theNumber < theArray.length - 1) {return theArray[theNumber]}

else {

  var theNumber = theNumber - (Math.floor(theNumber / theArray.length )) * theArray.length;

  return theArray[theNumber]

  }

};

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 06, 2016 Sep 06, 2016

Copy link to clipboard

Copied

Thank you very much. I will let you know how things turn out.

Regards

Lionel

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Aug 26, 2016 Aug 26, 2016

Copy link to clipboard

Copied

Nice.
I was planning on doing something similar after I wrote a script that distributes smart objects based on Photoshop's blob detection function.
I'll have to dig into this later to modify it for my purposes.

I'd put a suspend history function in there, so you can undo the whole thing in one undo.
And give it a UI similar to the Brush Window: spacing, scattering, color dynamics, shape dynamics, etc.

Anyway, thanks for a potentially useful script.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Sep 07, 2016 Sep 07, 2016

Copy link to clipboard

Copied

Thanks for sharing!

Always interesting to look at your code.

Davide

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines