5 Replies Latest reply on Aug 16, 2014 2:42 AM by c.pfaffenbichler

    Can scripting do path editing?

    the05

      verctor tool.png

      I used ScriptListener to log what happens when I clicked path editing tool (screenshot above) on the top bar. I clicked every path editing tool on the top bar, however, only Combine generated scripts. This is what I got:

       

      var idcombine = stringIDToTypeID( "combine" );
          var desc143 = new ActionDescriptor();
          var idnull = charIDToTypeID( "null" );
              var ref76 = new ActionReference();
              var idPath = charIDToTypeID( "Path" );
              var idOrdn = charIDToTypeID( "Ordn" );
              var idTrgt = charIDToTypeID( "Trgt" );
              ref76.putEnumerated( idPath, idOrdn, idTrgt );
          desc143.putReference( idnull, ref76 );
      executeAction( idcombine, desc143, DialogModes.NO );
      
      
      
      

       

      I saved these code into a .jsx file and ran from Photoshop. It successfully combined pathes.

       

      I'm wondering why I couldn't get any code for other path editing tools. Is there other way to realize path editing with scripting?

       

      Information:

      Windows 7 64-bit SP1

      Photoshop cc 2014

      Javascript

        • 1. Re: Can scripting do path editing?
          c.pfaffenbichler Level 8

          As far as I can tell the only option is to assess the whole information of the Path, edit that Array and create a new Path.

          One can naturally remove the old Path and name the new one with the old one’s name.

          • 2. Re: Can scripting do path editing?
            the05 Level 1

            Thanks very much for your reply. Could you please provide an example?

            • 3. Re: Can scripting do path editing?
              c.pfaffenbichler Level 8

              This would create paths based on the first path’s subPathItems.

              // make paths from first path’s subpathitems;

              // 2014, use it at your own risk;

              #target "photoshop-70.032"

              if (app.documents.length > 0) {

              var myDocument = app.activeDocument;

              if (myDocument.pathItems.length > 0) {

              var theArray = collectPathInfoFromDesc2012 (myDocument, myDocument.pathItems[0]);

              var theName = myDocument.pathItems[0];

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

              createPath2012([theArray[m]], theName+"_"+m)

              }

              }

              };

              ////// 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[l];

                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[s] || cTID[s] = app.charIDToTypeID(s); };

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

              // reset;

              app.preferences.rulerUnits = originalRulerUnits;

              return theArray;

              };

              ////// create a path from collectPathInfoFromDesc2012-array //////

              function createPath2012(theArray, thePathsName) {

              var originalRulerUnits = app.preferences.rulerUnits;

              app.preferences.rulerUnits = Units.POINTS;

              // thanks to xbytor;

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

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

               

               

                  var desc1 = new ActionDescriptor();

                  var ref1 = new ActionReference();

                  ref1.putProperty(cTID('Path'), cTID('WrPt'));

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

                  var list1 = new ActionList();

               

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

                var thisSubPath = theArray[m];

               

                  var desc2 = new ActionDescriptor();

                  desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);

                  var list2 = new ActionList();

                  var desc3 = new ActionDescriptor();

                  desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);

                  var list3 = new ActionList();

               

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

                var thisPoint = thisSubPath[n];

               

                  var desc4 = new ActionDescriptor();

                  var desc5 = new ActionDescriptor();

                  desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);

                  desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);

                  desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);

                  var desc6 = new ActionDescriptor();

                  desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);

                  desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);

                  desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);

                  var desc7 = new ActionDescriptor();

                  desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);

                  desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);

                  desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);

                  desc4.putBoolean(cTID('Smoo'), thisPoint[3]);

                  list3.putObject(cTID('Pthp'), desc4);

               

                };

               

                  desc3.putList(cTID('Pts '), list3);

                  list2.putObject(cTID('Sbpl'), desc3);

                  desc2.putList(cTID('SbpL'), list2);

                  list1.putObject(cTID('PaCm'), desc2);

                };

               

                  desc1.putList(cTID('T   '), list1);

                  executeAction(cTID('setd'), desc1, DialogModes.NO);

               

               

              if (hasVectorMask() == false) {

              if (thePathsName != undefined) {app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1].name = thePathsName};

              var myPathItem = app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1];

              }

              else {

              if (thePathsName != undefined) {app.activeDocument.pathItems[app.activeDocument.pathItems.length - 2].name = thePathsName};

              var myPathItem = app.activeDocument.pathItems[app.activeDocument.pathItems.length - 2];

              };

              app.preferences.rulerUnits = originalRulerUnits;

              return myPathItem

              };

              // from »Flatten All Masks.jsx« by jeffrey tranberry;

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

              // Function: hasVectorMask

              // Usage: see if there is a vector layer mask

              // Input: <none> Must have an open document

              // Return: true if there is a vector mask

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

              function hasVectorMask() {

                var hasVectorMask = false;

                try {

                var ref = new ActionReference();

                var keyVectorMaskEnabled = app.stringIDToTypeID( 'vectorMask' );

                var keyKind = app.charIDToTypeID( 'Knd ' );

                ref.putEnumerated( app.charIDToTypeID( 'Path' ), app.charIDToTypeID( 'Ordn' ), keyVectorMaskEnabled );

                var desc = executeActionGet( ref );

                if ( desc.hasKey( keyKind ) ) {

                var kindValue = desc.getEnumerationValue( keyKind );

                if (kindValue == keyVectorMaskEnabled) {

                hasVectorMask = true;

                }

                }

                }catch(e) {

                hasVectorMask = false;

                }

                return hasVectorMask;

              };

              • 4. Re: Can scripting do path editing?
                the05 Level 1

                Hey C.pfaffenbichler. Thanks very much for you sharing!

                Your code works on PS CC 2014 (32-bit) but fails on PS CC 2014 (64-bit).

                Anyway, I believe it's helpful to solve my problem. My programing skill is poor and can't understand your code very well now. I'll get back to this after I improve my Javascript knowledge.

                • 5. Re: Can scripting do path editing?
                  c.pfaffenbichler Level 8

                  What exact error does it produce in CC 2014?

                  For me it works (20140508.r.58 x64 on Mac OS 10.8.5) but there may well be some shortcoming I have overlooked …