I'm using ExtendScript for scripting Adobe Illustrator. I was wondering if there was a sneaky way or a script available to programmatically capture and then replicate a path shape, sort of JavaScript's .toSource() equivalent.
Thanks
Try this:
main();
function main(){
var doc = app.activeDocument; // get the active doc
var coords = new Array(); // make a new array for the coords of the path
var directions = new Array();
var sel = doc.selection[0];// get first object in selection
if(sel == null) {
// check if something is slected
alert ("You need to sevlect a path");
return;
}
var points = sel.pathPoints;// isolate pathpoints
// loop points
for (var i = 0; i < points.length; i++) {
// this could be done in one lines
// just to see whats going on line like
//~ coords.push(new Array(points[i].anchor[0],points[i].anchor[1]));
var p = points[i]; // the point
var a = p.anchor; // his anchor
var px = a[0];// x
var py = a[1]; // y
var ldir = p.leftDirection;
var rdir = p.rightDirection;
directions.push(new Array(ldir,rdir));
coords.push(new Array(px,py));// push into new array of array
}
var new_path = doc.pathItems.add(); // add a new pathitem
new_path.setEntirePath(coords);// now build the path
// check if path was closed
if(sel.closed){
new_path.closed = true;
}
// set the left and right directions
for(var j = 0; j < new_path.pathPoints.length;j++){
new_path.pathPoints[j].leftDirection = directions[j][0];
new_path.pathPoints[j].rightDirection = directions[j][1];
}
}
Related
×™ello everybody! I tried to create a script that creats a rectangle of a given size, make a group and a clipping mask and after all that resize it to a diffrent size in mm.
for example I have a graphic with the name "fish400" and I clip it in a rectangle of 400X400 that I create with the script. so far so good. my problem is that I want to resize the clipping with all it's content to 382. when I set the height to be the rec. size-18 it gets the height of 385.1
I'm not a very skilled programmer and the script could be written better but I really don't get my mistake.
here is my code:
var doc = app.activeDocument;
var layers = doc.layers;
var myLayer = layers["Layer 1"]; //this defines the layer that you want to get the selection from
var vals = 0;
var tzim = 0;
var side = 0; //width || height
//mm convertor
function mm(n) {return n * 2.83464566929134;}
doc.selection = null; //ensure there is nothing in the document selected already. this way you only get the selection you want.
var found = false;
for(var a=0 ;a<doc.groupItems.length; a++)
{
if (doc.groupItems[a].name == "fish400") {vals = mm(400); tzim = mm(18); side = 1; found = true;}
}
if (found = true)
{
var rect = doc.pathItems.rectangle(0,0,vals,vals);
app.executeMenuCommand("selectall");
var groupItem = doc.groupItems.add();
var count = selection.length;
for(var i = 0; i < count; i++)
{
var item = selection[selection.length - 1];
item.moveToBeginning(groupItem);
}
groupItem.clipped = true;
item.top = center_point[0] + (item.height/2);
item.left = center_point[1] - (item.width/2);
if (side == 1) {groupItem.height -= tzim;} else if (side == 0) {groupItem.width -= tzim;}
}
If your script works fine for you (it doesn't work for me, though) and all you want is to add resizing for your picture from 400x400 to 382x382 mm you can just to add at the end of your script these lines:
var k = 382/400*100;
groupItem.resize(k,k);
Or:
app.executeMenuCommand("selectall");
var sel = app.selection[0];
var k = 382/400*100;
sel.resize(k,k);
I'm trying to iterate over a create path in Photoshop finding out the anchor points position etc
var srcDoc = app.activeDocument;
// create the array of PathPointInfo objects
var lineArray = new Array();
lineArray.push(new PathPointInfo());
lineArray[0].kind = PointKind.CORNERPOINT;
lineArray[0].anchor = new Array(20, 160);
lineArray[0].leftDirection = [35, 200];
lineArray[0].rightDirection = lineArray[0].anchor;
lineArray.push(new PathPointInfo());
lineArray[1].kind = PointKind.CORNERPOINT;
lineArray[1].anchor = new Array(20, 40);
lineArray[1].leftDirection = lineArray[1].anchor;
lineArray[1].rightDirection = [220, 260];
// create a SubPathInfo object, which holds the line array in its entireSubPath property.
var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;
//create the path item, passing subpath to add method
var myPathItem = srcDoc.pathItems.add("A Line", lineSubPathArray);
for (var i = 0; i < lineSubPathArray[0].entireSubPath.length; i++)
{
var b = lineSubPathArray[0].entireSubPath[i].anchor;
alert(b);
}
This works fine, but instead of creating the path and finding out it's information I want to loop over each path and get the same. This should be the same as the loop above only without explicitly calling lineSubPathArray and its parts.
for (var i = 0; i < srcDoc.pathItems[0].subPathItems.pathPoints.length; i++) // wrong I think
{
var b = srcDoc.pathItems[0].entireSubPath[i].anchor; // wrong
alert(b);
}
Almost: you need to iterate through subPathItems which consist of pathPoints:
var srcDoc = activeDocument;
var workPath = srcDoc.pathItems[0];
var i, k, b;
for (i = 0; i < workPath.subPathItems.length; i++) {
for (k = 0; k < workPath.subPathItems[i].pathPoints.length; k++) {
b = workPath.subPathItems[i].pathPoints[k].anchor;
alert(b);
}
}
This seems like a trivial issue but I'm not sure Photoshop supports this type of functionality:
Is it possible to implement use last script functionality?
That is without having to add a function on each and every script that writes it's filename to a text file.
Well... It's a bit klunky, but I suppose you could read in the scriptlistener in reverse order and find the first mention of a script file:
// Switch off any dialog boxes
displayDialogs = DialogModes.NO; // OFF
var scripts_folder = "D:\\PS_scripts";
var js = "C:\\Users\\GhoulFool\\Desktop\\ScriptingListenerJS.log";
var jsLog = read_file(js);
var lastScript = process_file(jsLog);
// use function to call scripts
callScript(lastScript)
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL
function callScript (ascript)
{
eval('//#include "' + ascript + '";\r');
}
function process_file(afile)
{
var needle = ".jsx";
var msg = "";
// Let's do this backwards
for (var i = afile.length-1; i>=0; i--)
{
var str = afile[i];
if(str.indexOf(needle) > 0)
{
var regEx = str.replace(/(.+new\sFile\(\s")(.+\.jsx)(.+)/gim, "$2");
if (regEx != null)
{
return regEx;
}
}
}
}
function read_file(inFile)
{
var theFile = new File(inFile);
//read in file
var lines = new Array();
var l = 0;
var txtFile = new File(theFile);
txtFile.open('r');
var str = "";
while(!txtFile.eof)
{
var line = txtFile.readln();
if (line != null && line.length >0)
{
lines[l++] = line;
}
}
txtFile.close();
return lines;
}
How can I make the navtitle curve along the path of the slice and wrap the text if it's long.
Image of the wheel above
In long text, use '\n' in the title for wrap.
wheel.createWheel(["Long\ntext"]);
Currently, the navtitle curve along the path is an RC feature, so please use the source code instead of the last release.
You can find the new properties in this CodePen: https://codepen.io/softwaretailoring/pen/RQYzWm
var piemenu = new wheelnav("wheelDiv");
// New properties in wheelnav.js v1.8.0
piemenu.titleCurved = true;
piemenu.titleCurvedClockwise = false;
piemenu.titleCurvedByRotateAngle = false;
Unfortunately, the two above properties don't work together. :(
UPDATE: There is a way to achieve your needs. You can use two wheels on each other.
var piemenu = new wheelnav("wheelDiv");
setMenu(piemenu); // Set common properties
piemenu.titleRadiusPercent = 0.65; // Positioning first title
piemenu.markerEnable = true;
piemenu.slicePathFunction = slicePath().DonutSlice;
piemenu.sliceClickablePathFunction = slicePath().DonutSlice;
piemenu.titleHoverAttr = { fill: "#333" };
piemenu.createWheel(["Hello", "world!", "-------"]);
var piemenu2 = new wheelnav("wheelDiv2", piemenu.raphael);
setMenu(piemenu2); // Set common properties
piemenu2.wheelRadius = 520; // Positioning second title
piemenu2.slicePathFunction = slicePath().NullSlice; // There is no slice, only title
piemenu2.createWheel(["Bello", "space!", "*******"]);
// Link navigateFunctions to each other
for (var i = 0; i < piemenu.navItems.length; i++) {
piemenu.navItems[i].navigateFunction = function () {
piemenu2.navigateWheel(Math.abs(this.itemIndex));
}
}
for (var i = 0; i < piemenu2.navItems.length; i++) {
piemenu2.navItems[i].navigateFunction = function () {
piemenu.navigateWheel(Math.abs(this.itemIndex));
}
}
Here is a new CodePen for wrapped and curved text: https://codepen.io/softwaretailoring/pen/eLNBYz
In Illustrator, I want to create a function in one of my scripts for Bring to Front. In the CS5 Type Library, I find the object, AiZOrderMethod.aiBringToFront, however, I can't figure out how to use it.
Here is what I've come up with so far:
//BringToFront
mySelection = activeDocument.selection;
if (mySelection.length>0){
var doc = app.activeDocument; //current document
var s = doc.selection; //current slection
var sl = s.length; //number of selected objects
s.AiZOrderMethod.aiBringToFront();
//for(var i = 0 ; i < sl; i++) s[i].aibringtofront(); //for each selected element...
app.redraw();
}else{
alert("Nothing selected!")
}
app.activeDocument.selection is an Array
Try this:
var doc = app.activeDocument; //current document
var sel = doc.selection; // array
var sl = sel.length; //number of selected objects
if (sl>0){
for(var i = 0 ; i < sl; i++){
// for every item in selection array
sel[i].zOrder(ZOrderMethod.BRINGTOFRONT);
}
app.redraw();
}else{
alert("Nothing selected!")
}