Copy link to clipboard
Copied
So, as of today I'm new to scripting for Illustrator, I'm using the ExtendScript Toolkit. However I'm not new to scripting my own solutions and I do have some experience with JavaScript already.
What I'm trying to do is this: For all selected Items->Duplicate selected item and make a simple clipping group with it
What I end up with visually doesn't change the picture, but gives me a lot of clipped colored areas which I then can edit in the isolated mode, allowing me far faster and better shading. Doing that by hand takes hours on some pictures, it'd take a second with a script.
The script itself already perfectly works for normal PathItems. As obvious in the title, as soon as I have to apply the same to CompundPathItems things stop working. My issue is somewhat similar to this old thread [Problem with compound path clipping], but I couldn't find a solution there because I get different behavior.
When I run the very same script that perfectly works with the normal PathItems with CompoundPathItems I get this: Error 9046: The top item in the group must be a path item to create a mask
Well that's a problem. In the GUI there is absolutely no difference between making a clipping mask with a simple path and a compound path. The reference guide has frankly not helped me with this issue at all, the only thing I learned from that is that the CompoundPathItem object doesn't have a clipping attribute, but those included PathItems do.
Here's what I have so far:
if ( selected.typename == "PathItem" ) { | |
var newGroup = doc.groupItems.add(); | |
copy = selected.duplicate(newGroup,ElementPlacement.PLACEATEND); | |
selected.moveToBeginning(newGroup); | |
newGroup.clipped = true; | |
} |
As I said, this part perfectly does what it's supposed to do for normal Paths.
For CompoundPaths I use this workaround.
if ( selected.typename == "CompoundPathItem" ) { | |
var newGroup = doc.groupItems.add(); | |
copy = selected.duplicate(newGroup,ElementPlacement.PLACEATEND); | |
selected.moveToBeginning(newGroup); | |
compoundItems = selected.pathItems; | |
compoundIndex = compoundItems.length; | |
for ( f = 0; f < compoundIndex; f++ ) {compoundItems | |
var lineList = new Array(10); | |
for ( l = 0; l < lineList.length; l++ ) {lineList | |
newPath = app.activeDocument.pathItems.add(); | |
newPath.setEntirePath(lineList); | |
newPath.moveToBeginning(newGroup); | |
newGroup.clipped = true; | |
newPath.remove(); |
Mind you, this workaround does work in so far that it bypasses that annoying and wrong error, and the Compound Clipping Path also works, with the only problem being that the Compound Clipping Path created like this is still displayed in its original colors in the Layers section, and is still selectable. When I lock the Compound Clipping Path I can work with it but still...
So the question is, what am I missing here? Surely there must be a proper way to do this.
app.executeMenuCommand()? That one eluded me so far, might be just the right thing. I'll definitely take a look, now just to find a ref on that, as unfortunately the official ref documents I have don't mention that command. Any place with a list of possible commands?
Ah, also of course I'm not only doing it for the isolation mode. If you care to hear the background, here is it:
As I said it's for shading the pictures I'm working on. I've iterated and tried through a bunch of techniques. For exampl
...Copy link to clipboard
Copied
Hmm, can you try to get all the pathPoints of your constituent pathItems, and after concattin' them into one big ole' array, make one single pathItem and unleash a can of .setEntirePath(pathPoints) on it, to create the clip path made of the same lines as your compound path? I am not sure how that'll work out, you may have to change the winding rule if the areas are incorrect.
* after reading my writing: getting all the pathPoints would be an incorrect statement. What I am supposed to mean by pathPoints is not [x,y] coordinates, but the actual array of the object pathPoints (the one with the properties of anchor, leftDirection, rightDirection, etc), and .setEntirePath() would actually need to be your own custom function which adds each pathPoint to your new path. All this, unless your paths are just polygons with no control points, in which case regular setEntirePath would be Ok.
Copy link to clipboard
Copied
Not sure if it might work, after all those compound paths are made up of one main path after which a bunch of subtractive paths follow. It'd be just another workaround as well.
Example: A piece of clothing which includes a few lines that stay within the colored area. The compound path then consists of one big patch that includes the entire colored area, and a bunch of subtractively applied subpaths to cut out the main path and make space for those lines. Any way I think about it, it's not possible to summarize that into one normal path, since you have several closed distinctive areas. Splitting up these paths into many distinct groups would add an unnecessary level of complexity to my pictures, they are complex enough as is.
Thanks for the helping attempt though.
I've tried to scout for the differences between my script created Compound Clipping Mask and the GUI created Clipping Masks. Apart from the visual difference in the thumbnails in the layers I've found that the zOrderPosition Attribute for the GUI created ones is 0, for mine it is 2. I can't manually set this value to 0 though, it'll reset itself back to 2 without throwing me an error.
Further, if I lock my script created Compound Clipping Mask I seem to perfectly get the behavior I would get with the GUI driven way. When I click onto the clipped object I get that below, so it seems my workaround works just fine.
I'm interested whether there's a proper way to do it, without workarounds.
Copy link to clipboard
Copied
Hey, you're right- the pathPoints could only work when it's just a regular closed path.. I was thinking of svg's path definition instead of the AI one.
Well, another workaround could be to select your items and try to do app.executeMenuCommand() , if you are using CS6+
Also, you are doing this for the purpose of using the isolation mode? Correct me if I am misinterpreting your explanation, but if that is true, then why not just go straight to isolation mode via double-click or keyboard shortcut?
Copy link to clipboard
Copied
app.executeMenuCommand()? That one eluded me so far, might be just the right thing. I'll definitely take a look, now just to find a ref on that, as unfortunately the official ref documents I have don't mention that command. Any place with a list of possible commands?
Ah, also of course I'm not only doing it for the isolation mode. If you care to hear the background, here is it:
As I said it's for shading the pictures I'm working on. I've iterated and tried through a bunch of techniques. For example gradient meshes on my first few real works. Now those meshes don't do well with complex shapes, which previously I alleviated by using a simple square or rectangle gradient mesh and using the original colored shape as a clipping mask. That did work, but it was a huge lot of work.
After a bunch of attempts at that I went over to using simple gradients as a background for the shape and then I'm doing the shading freehand with the blob brush tool, using a graphic style and filters to make it look right. That's better, but properly making all the clipping masks takes me much longer than anything else.
Now the problem is that the shading is not supposed to go over the lines, which is impossible to do properly without either messing up the order, or using clipping masks, hence the script. Because you know, if you use a blob brush with a strong Gaussian blur close to the lines you'll end up with stuff on both sides. If you don't start close to the line the shading won't look right if the darkest part of the shade needs to be close to the line. And that's where clipping masks do magic.
And finally here's an example how I work with the script and the result:
After I have traced a sketch, adjusted the line widths and everything to look neat I turn the paths to outline strokes and then make them into a live paint group (which would mess up the line widths, unless you turn the paths into outline strokes first).
With that live paint group it takes me just a few minutes to flat color my piece. Then I expand the live paint group, in case of doubt spend some more minutes to make compound paths from all areas I need to shade in one piece, then I select all the areas and use my script to turn them into neat clipping masks. Then I can click any area, enter the isolation mode and go up one level so I'm in the appropriate group, where I can shade freely without the problem of going over the lines.
At the end that allows me to apply a complex and in-depth shading, without wasting any time to get there.
PS: Well, I just found out that Draw Inside is pretty darn close to what I want to do, and oddly enough it produces the same visual discrepancy with compound paths that my script produces. I'll be taking a closer look at that, though my script does a little more than just the clipping mask stuff, so maybe I'll go for a hybrid solution. Whatever makes for a better workflow.
Copy link to clipboard
Copied
Hey, the documentation that can sometimes help is in the ESTK, under help menu > Object Model Viewer. You can try looking under Application object in the Adobe Illustrator Type Library, to see if it's got that method listed.
Also, thank you for the background on the work at hand. Having read your process, I tried out the draw inside method, and it seems like what you want. I am able to use the direct selection tool (key: A) to select a compound path or single path within any group, and after selecting draw inside, shading is accomplished without the need for isolation. (However, they can still be isolated via double-click or shortcut). The clipping mask which is in front of the shapes it clips and yet has a color attached to it (as opposed to clear as you'd usually expect) isn't that bad, if you are using draw inside, because when you're drawing inside an object, your drawing is auto-concealed within the path you had selected when you decided to draw inside, so you don't have to necessarily worry about selecting the clipping path while you draw. (Unless I am missing something)
Copy link to clipboard
Copied
To at least your first paragraph... https://gist.github.com/moluapple/2719021 might be a start for you. There is a newer and slightly more comprehensive list that I've seen but I can't put my finger on it right now. If I find it quickly I'll post it... -TT
Copy link to clipboard
Copied