PathItems generates Undefined is not an object in photoshop scripting

Viewed 185

I managed to write a VB script that I am trying running on Photoshop CS4 Extended using the ExtendScript ToolKit. It opens an (all black) .png file and places a small line on it.

I said I managed because I sure am not a programmer, just by reading online about the subject, using some (very basic) knowledge of VBA from Microsoft Access, and copying pasting.

The code I am trying getting going:

//Save preferences2
var originalUnit=app.preferences.rulerUnits
preferences.rulerUnits=Units.PIXELS   

var fileName = 1;// Typically this is just a number 1.

var fileNameSeries = "/D/" + fileName

//Open .png to imprint upon
var fileRef=new File(fileNameSeries + ".png")
var docRef = app.open(fileRef)   

var lineArray1 = new PathPointInfo
lineArray1.Kind = 2 ;// for PsPointKind --> 2 (psCornerPoint)
lineArray1.Anchor = Array(100, 100)
lineArray1.LeftDirection = lineArray1.Anchor
lineArray1.RightDirection = lineArray1.Anchor
var lineArray2 = new PathPointInfo
lineArray2.Kind = 2
lineArray2.Anchor = Array(150, 200)
lineArray2.LeftDirection = lineArray2.Anchor
lineArray2.RightDirection = lineArray2.Anchor
//Next create a SubPathInfo object, which will hold the line array
//in its EntireSubPath property.
var lineSubPathArray = new SubPathInfo
lineSubPathArray.Operation = 2 ;// for PsShapeOperation --> 2 (psShapeXOR)
lineSubPathArray.Closed = false
lineSubPathArray.EntireSubPath = lineArray1
//create the PathItem object using Add. This method takes the SubPathInfo object
//and returns a PathItem object, which is added to the pathItems collection
//for the document.
//var myPathItem = new PathItem
myPathItem = docRef.PathItems.Add("A Line", lineSubPathArray)
// stroke it so we can see something
myPathItem.StrokePath(2) //'for PsToolType --> 2 (psBrush)
}
fileName++

fileNameSeries = "/D/ " + fileName


pngFile = new File(fileNameSeries)

pngSaveOptions = new PNGSaveOptions()
pngSaveOptions.interlaced = false
app.activeDocument.saveAs(pngFile, pngSaveOptions, true)


//dispose 
  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES)


//Retrieve original preferences
preferences.rulerUnits=originalUnit

I'm stuck on a syntax error. The line: myPathItem = docRef.PathItems.Add("A Line", lineSubPathArray) produces an "undefined is not an object".

Can anyone tell me what am I doing wrong.

1 Answers

Coding paths in Photoshop isn't fun. it's not well documented and unlike illustrator is quite an effort to get very little.

You were close, but possibly confused with JavaScript and VB.

Essentially a path is an array, and then you push path info onto that array. Hence constructing the path the old fashioned way, starting with the first element at zero, with lineArray[0].anchor = new Array(100, 100); and so forth...

Oddly, I couldn't construct the path with lineSubPathArray[0].operation = 2; and had to use this instead. lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;

One thing of note is Photoshop path items must have unique names. Unlike layers, so that may have not been helping you.

To construct your path you'll want:

// create the array of PathPointInfo objects
// Declare a new array called lineArray
var lineArray = new Array();

// Firstly, add PathPointInfo() constructor to the array
lineArray.push(new PathPointInfo());

// declare various components to the array
// of which there are four types
// .kind - determines what type of corner
// .anchor - these are path points
// in order to given them x,y co-orrdinates we have to declare
// another new array with them
// and lastly
// direction - specifically leftDirection and rightDirection
// these are tangents to the bezier curve.
// Truthfully, don't understand how the numbers relate to how
// the tangents look in Photoshop
// by declaring a tangent as as anchor ie = lineArray[0].anchor
// the tangents are tucked away and are at the same point as
// the path point


lineArray[0].kind = 2 ;// for PsPointKind --> 2 (psCornerPoint)
lineArray[0].anchor = new Array(100, 100);
lineArray[0].leftDirection  = lineArray[0].anchor;
lineArray[0].rightDirection = lineArray[0].anchor;

// For the second point (and every subsequent point) 
// we need to push PathPointInfo() to the line array

lineArray.push(new PathPointInfo());

//  Since arrays are zero based, the first element
// of the lineArray is lineArray[0]
// the next point is lineArray[1]

lineArray[1].kind = 2
lineArray[1].anchor = new Array(150, 200);
lineArray[1].leftDirection   = lineArray[1].anchor;
lineArray[1].rightDirection =  lineArray[1].anchor;


// Next create a SubPathInfo object, which will hold the line array
// in its EntireSubPath property.
// It's similar to the above, but why it's needed is beyond me

var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
// operation, not kind and therefore needs to be declared with ShapeOperation
// Uning an int just didn't work for me in PS CC 2018
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;


// create the path item, giving a unique name, 
// passing subpath to the add method
var myPathItem = docRef.pathItems.add("A Line", lineSubPathArray);

// stroke it so we can see something using the preset brush tool
myPathItem.strokePath(ToolType.BRUSH); 

Also after the script is run, the path is still selected. Which may get to be a pain after a while. You can deselect it with this function:

function deselectPath()
{
  // =======================================================
  var id630 = charIDToTypeID( "Dslc" );
  var desc154 = new ActionDescriptor();
  var id631 = charIDToTypeID( "null" );
  var ref127 = new ActionReference();
  var id632 = charIDToTypeID( "Path" );
  ref127.putClass( id632 );
  desc154.putReference( id631, ref127 );
  executeAction( id630, desc154, DialogModes.NO );
}
Related