Copy link to clipboard
Copied
I have a script which needs to merge paths made up of multiple subpaths into a single path, and sometimes I get the dialog 'This operation will turn a live shape into a regular path'.
Is there a command to convert the paths/subpaths which are live shapes into a regular path (and also to determine which are live shape paths that need to be converted) via Javascript?
A small note )
You can use the dup_to_wrk_path () function instead of the combination
"collectPathInfoFromDesc2012" and "createPath2015". It works instantly, while the proposed functions can suspend photoshop with the number of points in many thousands.
...function dup_to_wrk_path(id)
{
try
{
var d = new ActionDescriptor();
var r = new ActionReference();
if (id == undefined) r.putEnumerated(stringIDToTypeID("path"), charIDToTypeID("Ordn"), charIDToTypeID("
Copy link to clipboard
Copied
Could you please post a screenshot to illustrate the Layer structure (as its is and the result you want to achieve)?
Copy link to clipboard
Copied
Sorry I haven't been able to reply until now.
What I'm doing is merging shape components, the equivalent of this menu in the path dropdown in the interface:
This works, but sometimes there's a live shape in the paths, and this dialog appears:
I'm looking for a solution to allow my script to merge the paths if there is a live shape included.
Copy link to clipboard
Copied
Your script should still merge the paths. Is it not doing that, when you click the OK button? I would also check the "Do not show again" so that doesn't appear.
Copy link to clipboard
Copied
I would like it to do the merge without providing the dialog. This is meant to run somewhat unattended, and I cannot control whether the user will have that option checked or not
Copy link to clipboard
Copied
A possible workaround:
Collect the subPathInfo and create a new Path based on that, remove the Vector Mask, select the newly created Path, add a Vector Mask and remove the intermediate Path.
Edit:
#target photoshop
var myDocument = activeDocument;
var theArray = collectPathInfoFromDesc2012 (myDocument, selectedPath2015 ());
var thePathName = Math.random();
var thePath = createPath2015(theArray, thePathName);
// =======================================================
var idDlt = charIDToTypeID( "Dlt " );
var desc9 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
var idPath = charIDToTypeID( "Path" );
var idvectorMask = stringIDToTypeID( "vectorMask" );
ref2.putEnumerated( idPath, idPath, idvectorMask );
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref2.putEnumerated( idLyr, idOrdn, idTrgt );
desc9.putReference( idnull, ref2 );
executeAction( idDlt, desc9, DialogModes.NO );
myDocument.pathItems[thePathName].select();
// =======================================================
var idMk = charIDToTypeID( "Mk " );
var desc11 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref4 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
ref4.putClass( idPath );
desc11.putReference( idnull, ref4 );
var idAt = charIDToTypeID( "At " );
var ref5 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
var idPath = charIDToTypeID( "Path" );
var idvectorMask = stringIDToTypeID( "vectorMask" );
ref5.putEnumerated( idPath, idPath, idvectorMask );
desc11.putReference( idAt, ref5 );
var idUsng = charIDToTypeID( "Usng" );
var ref6 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref6.putEnumerated( idPath, idOrdn, idTrgt );
desc11.putReference( idUsng, ref6 );
executeAction( idMk, desc11, DialogModes.NO );
// =======================================================
var idcombine = stringIDToTypeID( "combine" );
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref1.putEnumerated( idPath, idOrdn, idTrgt );
desc4.putReference( idnull, ref1 );
executeAction( idcombine, desc4, DialogModes.NO );
myDocument.pathItems[thePathName].remove();
////// collect path info from actiondescriptor, smooth added //////
function collectPathInfoFromDesc2012 (myDocument, thePath) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
//app.preferences.rulerUnits = Units.PIXELS;
// 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;
};
////// create a path from collectPathInfoFromDesc2012-array //////
function createPath2015(theArray, thePathsName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// 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
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
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);
// name work path;
var check = false;
var x = activeDocument.pathItems.length - 1;
while (check == false) {
if (activeDocument.pathItems
app.activeDocument.pathItems
var myPathItem = app.activeDocument.pathItems
check = true
};
x--
};
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
////// 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}
};
Copy link to clipboard
Copied
I forgot to mention one should include a check to verify whether the Vector Mask has Feather and Density settings ā¦
Copy link to clipboard
Copied
A small note )
You can use the dup_to_wrk_path () function instead of the combination
"collectPathInfoFromDesc2012" and "createPath2015". It works instantly, while the proposed functions can suspend photoshop with the number of points in many thousands.
function dup_to_wrk_path(id)
{
try
{
var d = new ActionDescriptor();
var r = new ActionReference();
if (id == undefined) r.putEnumerated(stringIDToTypeID("path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
else if (typeof(id) == "string") r.putName( charIDToTypeID( "Path" ), id);
else r.putIdentifier( charIDToTypeID( "Path" ), id);
var path = executeActionGet(r).getObjectValue(stringIDToTypeID("pathContents"));
var list = path.getList(stringIDToTypeID("pathComponents"));
var r = new ActionReference();
r.putProperty( charIDToTypeID( "Path" ), charIDToTypeID( "WrPt" ) );
d.putReference( stringIDToTypeID( "null" ), r );
d.putList(charIDToTypeID("T "), list);
executeAction(charIDToTypeID("setd"), d, DialogModes.NO);
return true;
}
catch (e) { alert(e); return false; }
}
Copy link to clipboard
Copied
Do you by any chance have a full script? The one OP posted below is erroring out. I'm trying to cobble together a function that converts a live path to a regular path. I'm not sure how to use your dup_to_wrk_path function. What do I pass as the ID? Any chance you could help me out?
Would really appreciate it!
Copy link to clipboard
Copied
There were errors when transferring a topic from the old forum.
You can use nothing as an ID, i.e. empty: dup_to_wrk_path();
In this case, the current selected path will be duplicated.
You can also use the path name: dup_to_wrk_path("Path 1");
Copy link to clipboard
Copied
Thank you both for the examples, I'll look into this further when my workload allows it.
Recreating the path sounds promising, but might be a bit problematic if it has to do that every time the program comes across a path. Depending on how complicated the paths might be, it could cause a very undesired slowdown. And since I don't see any way to determine if the path is/contains a 'live path', I would have to recreate every path.
These are actually clipping paths, not vector masks, so I shouldn't have to worry about any settings other than duplicating the path and applying the existing clipping path properties.
Thanks again.
Copy link to clipboard
Copied
Success!
I used r-bin's solution, and modified it to my needs, attached is the code that I will be using:
var myDocument = activeDocument;
var theClippingPath = getClippingPath (myDocument)
if (theClippingPath != null) {
var pathName = theClippingPath.name
dup_to_wrk_path(pathName )
var thePath = getWorkPath (myDocument)
if (thePath != null) {
theClippingPath.remove()
thePath.name = pathName //'Clipping Path'
thePath.makeClippingPath()
} else {
alert ('Work path not found?')
}
}
function getClippingPath (oDoc) {
var ct = oDoc.pathItems.length;
if (ct > 0) {
for( var i = 0; i< ct; i++) {
var p = oDoc.pathItems;
if (p.kind == PathKind.CLIPPINGPATH) {
return p
}
}
}
return null
}
function getWorkPath (oDoc) {
var ct = oDoc.pathItems.length;
if (ct > 0) {
for( var i = 0; i< ct; i++) {
var p = oDoc.pathItems;
if (p.kind == PathKind.WORKPATH) {
return p
}
}
}
return null
}
function dup_to_wrk_path(id) {
try
{
var d = new ActionDescriptor();
var r = new ActionReference();
if (id == undefined) r.putEnumerated(stringIDToTypeID("path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
else if (typeof(id) == "string") r.putName( charIDToTypeID( "Path" ), id);
else r.putIdentifier( charIDToTypeID( "Path" ), id);
var path = executeActionGet(r).getObjectValue(stringIDToTypeID("pathContents"));
var list = path.getList(stringIDToTypeID("pathComponents"));
var r = new ActionReference();
r.putProperty( charIDToTypeID( "Path" ), charIDToTypeID( "WrPt" ) );
d.putReference( stringIDToTypeID( "null" ), r );
d.putList(charIDToTypeID("T "), list);
executeAction(charIDToTypeID("setd"), d, DialogModes.NO);
return true;
} catch (e) {
alert(e); return false;
}
}