Skip to content

Instantly share code, notes, and snippets.

@creold
Created April 25, 2023 04:06
Show Gist options
  • Save creold/78122b9867525b9813c353d861ce1c62 to your computer and use it in GitHub Desktop.
Save creold/78122b9867525b9813c353d861ce1c62 to your computer and use it in GitHub Desktop.
/*
ExcludeByColor.jsx for Adobe Illustrator
Description: The script excludes overlapping paths by matching fill color via Pathfinder > Exclude
Date: April, 2023
Author: Sergey Osokin, email: hi@sergosokin.ru
Installation: https://github.com/creold/illustrator-scripts#how-to-run-scripts
Release notes:
0.1 Initial version
Donate (optional):
If you find this script helpful, you can buy me a coffee
- via Buymeacoffee: https://www.buymeacoffee.com/osokin
- via FanTalks https://fantalks.io/r/sergey
- via DonatePay https://new.donatepay.ru/en/@osokin
- via YooMoney https://yoomoney.ru/to/410011149615582
NOTICE:
Tested with Adobe Illustrator CC 2019-2023 (Mac/Win).
This script is provided "as is" without warranty of any kind.
Free to use, not for sale
Released under the MIT license
http://opensource.org/licenses/mit-license.php
Check my other scripts: https://github.com/creold
*/
//@target illustrator
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false); // Fix drag and drop a .jsx file
// Main function
function main() {
var actSet = 'ExcludeByColor',
actName = 'Pathfinder-Exclude',
actPath = Folder.myDocuments + '/Adobe Scripts/';
if (!isCorrectEnv('version:16')) return;
var doc = app.activeDocument,
srcLyrs = get(doc.layers),
paths = getLayersPaths(srcLyrs),
tgt = doc.layers.add();
tgt.name = 'Merged';
addPathfinder(actSet, actName, actPath);
selection = null;
while (paths.length) {
uniteAndMove(paths[0], doc, tgt, actSet, actName);
paths = getLayersPaths(srcLyrs);
}
tgt.visible = true;
rmvEmptyLayers(doc);
try {
app.unloadAction(actSet, '');
} catch (err) {}
}
// Check the script environment
function isCorrectEnv() {
var args = ['app', 'document'];
args.push.apply(args, arguments);
for (var i = 0; i < args.length; i++) {
var arg = args[i].toString().toLowerCase();
switch (true) {
case /app/g.test(arg):
if (!/illustrator/i.test(app.name)) {
alert('Wrong application\nRun script from Adobe Illustrator', 'Script error');
return false;
}
break;
case /version/g.test(arg):
var rqdVers = parseFloat(arg.split(':')[1]);
if (parseFloat(app.version) < rqdVers) {
alert('Wrong app version\nSorry, script only works in Illustrator v.' + rqdVers + ' and later', 'Script error');
return false;
}
break;
case /document/g.test(arg):
if (!documents.length) {
alert('No documents\nOpen a document and try again', 'Script error');
return false;
}
break;
case /selection/g.test(arg):
if (!selection.length || selection.typename === 'TextRange') {
alert('Few objects are selected\nPlease, select two or more paths', 'Script error');
return false;
}
break;
}
}
return true;
}
// Pathfinder > Exclude action
function addPathfinder(set, name, path) {
var str = [
'/version 3',
'/name [' + set.length + ' ' + ascii2Hex(set) + ']',
'/isOpen 1',
'/actionCount 1',
'/action-1 {',
'/name [' + name.length + ' ' + ascii2Hex(name) + ']',
' /keyIndex 0',
' /colorIndex 0',
' /isOpen 1',
' /eventCount 1',
' /event-1 {',
' /useRulersIn1stQuadrant 0',
' /internalName (ai_plugin_pathfinder)',
' /localizedName [ 10',
' 5061746866696e646572',
' ]',
' /isOpen 0',
' /isOn 1',
' /hasDialog 0',
' /parameterCount 1',
' /parameter-1 {',
' /key 1851878757',
' /showInPalette 4294967295',
' /type (enumerated)',
' /name [ 7',
' 4578636c756465',
' ]',
' /value 2',
' }',
' }',
'}'].join('');
try {
app.unloadAction(set, '');
} catch (err) {}
createAction(str, set, path);
}
// Load action
function createAction(str, set, path) {
if (!Folder(path).exists) Folder(path).create();
var f = new File('' + path + '/' + set + '.aia');
f.open('w');
f.write(str);
f.close();
app.loadAction(f);
f.remove();
}
// Convert string to hex
function ascii2Hex(hex) {
return hex.replace(/./g, function(a) {
return a.charCodeAt(0).toString(16)
});
}
function uniteAndMove(item, doc, tgt, actSet, actName) {
tgt.visible = false;
if (/compound/i.test(item.typename) && item.pathItems.length) {
item = item.pathItems[0];
}
if (item.filled) {
doc.defaultFillColor = item.fillColor;
app.executeMenuCommand('Find Fill Color menu item');
}
if (selection.length > 1) {
app.doScript(actName, actSet);
app.redraw();
}
tgt.visible = true;
for (var i = selection.length - 1; i >= 0; i--) {
selection[i].move(tgt, ElementPlacement.PLACEATEND);
}
selection = null;
}
// Convert collection into standard Array
function get(coll) {
var out = [];
for (var i = 0, len = coll.length; i < len; i++) {
out.push(coll[i]);
}
return out;
}
// Get items in editable Layers & Sublayers
function getLayersPaths(layers) {
var out = [];
for (var i = 0, len = layers.length; i < len; i++) {
var layer = layers[i];
if (layer.visible && !layer.locked) {
out = [].concat(out, getPaths(layer.pageItems));
if (layer.layers.length) out = [].concat(out, getPaths(layer.layers));
}
}
return out;
}
// Get single items
function getPaths(coll) {
var out = [];
for (var i = 0, len = coll.length; i < len; i++) {
var item = coll[i];
if (item.pageItems && item.pageItems.length) {
out = [].concat(out, getPaths(item.pageItems));
} else if (/path/i.test(item.typename) && item.editable) {
out.push(item);
}
}
return out;
}
function rmvEmptyLayers(doc) {
for (var i = doc.layers.length - 1; i >= 0; i--) {
var lyr = doc.layers[i];
if (lyr.visible && !lyr.locked && !lyr.pageItems.length) {
lyr.remove();
}
}
}
// Run script
try {
main();
} catch (err) {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment