script to return or restore rotation of multiple selected objects
Copy link to clipboard
Copied
Hello, there will be a script that restores the rotations to zero degrees "0°" of each selected object. I ask Chatgpt but unfortunately he doesn't get it. I have several objects selected with different rotation angles and doing it manually is very laborious.
Explore related tutorials & articles
Copy link to clipboard
Copied
Hi @vectora98504848, to "unrotate" something—back to zero degrees rotation—means you must first derive the item's rotation amount. In Illustrator, page items don't have an absolute rotation amount, however it does (usually!) keep track of rotations in a "BBAccumRotation" tag assigned to the item. The other possibility is if the item is a placed image, or a text frame, then it may also have a matrix, and sometimes it is possible to derive a rotation value from that.
I've written a script to derive the rotation, and then unrotate the selected items. Let me know how it goes, but bear in mind that there will be certain objects for which a rotation value cannot be determined in this way. There are other approaches to the problem, but they are not general—we must know more about the type of item.
- Mark
/**
* @file Unrotate Selected Items.js
*
* Makes an attempt to remove any recorded rotation
* that can be derived from the selected items.
* Finds rotation either in the item's BBAccumRotation
* tag or the item's matrix.
*
* @author m1b
* @version 2025-02-14
* @discussion https://community.adobe.com/t5/illustrator-discussions/script-to-return-or-restore-rotation-of-multiple-selected-objects/m-p/15146692
*/
(function () {
var doc = app.activeDocument;
var items = getItems({
from: doc.selection,
getPageItems: true,
getGroupItems: true,
});
if (0 === items.length)
return alert('Please select some items to rotate and try again.');
for (var i = 0; i < items.length; i++)
unrotate(items[i]);
})();
/**
* Attempt to return a page item to unrotated state.
* Important: will only work if the item has a valid
* BBAccumRotation tag or a matrix that is ammenable
* to derivation of the rotation.
* @author m1b
* @version 2025-02-13
* @param {PageItem} item - the item to unrotate.
* @return {Number} - the amount of rotation, in degrees.
*/
function unrotate(item) {
var accumRotation = undefined,
rotationTag;
if (item.hasOwnProperty('tags')) {
// derive rotation from the BBAccumRotation tag
rotationTag = getThing(item.tags, 'name', 'BBAccumRotation');
if (rotationTag)
accumRotation = rotationTag.value * 180 / Math.PI;
}
if (
undefined == accumRotation
&& item.hasOwnProperty('matrix')
)
// derive rotation from the matrix
accumRotation = getRotationFromMatrix(item.matrix);
if (undefined == accumRotation)
return;
// rotate the item
item.rotate(- accumRotation);
if (rotationTag)
// update tag
rotationTag.value = 0;
return accumRotation;
};
/**
* Returns a thing with matching property.
* If `key` is undefined, evaluate the object itself.
* @author m1b
* @version 2024-04-21
* @param {Array|Collection} things - the things to look through.
* @param {String} [key] - the property name (default: undefined).
* @param {*} value - the value to match.
*/
function getThing(things, key, value) {
for (var i = 0, obj; i < things.length; i++)
if ((undefined == key ? things[i] : things[i][key]) == value)
return things[i];
};
/**
* Returns the rotation amount, in degrees,
* of the given (not skewed) matrix.
* @author m1b
* @version 2023-10-20
* @param {Matrix} matrix - an Illustrator Matrix.
* @returns {Number}
*/
function getRotationFromMatrix(matrix) {
if (!matrix.hasOwnProperty('mValueA'))
throw new Error('getRotationFromMatrix: bad `matrix` supplied.');
// scaling factors
var scaleX = Math.sqrt(matrix.mValueA * matrix.mValueA + matrix.mValueC * matrix.mValueC);
// scaleY = Math.sqrt(matrix.mValueB * matrix.mValueB + matrix.mValueD * matrix.mValueD);
// rotation angle
var radians = Math.acos(matrix.mValueA / scaleX),
degrees = radians * (180 / Math.PI);
return Math.round(degrees * 1000) / 1000;
};
/** ------------------------------------------------------------------- *
* GET ITEMS *
* -------------------------------------------------------------------- *
* @author m1b *
* @version 2024-03-01 *
* -------------------------------------------------------------------- *
* Collects page items from a `from` source, eg. a Document, Layer, *
* GroupItem, or Array. Will look inside group items up to `maxDepth`. *
* Search can be filtered using `filter` function. Note that the *
* filter function is evaluated last in the filtering process. *
* -------------------------------------------------------------------- *
* Example 1. Get all items in document: *
* *
* var myItems = getItems({ from: app.activeDocument }); *
* *
* -------------------------------------------------------------------- *
* Example 2. Get all selected items except groups: *
* *
* var myItems = getItems({ *
* from: app.activeDocument.selection, *
* getGroupItems: false, *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 3. Using `filter` function to choose item type: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: function (item) { *
* return ( *
* 'PathItem' === item.typename *
* || 'CompoundPathItem' === item.typename *
* ); *
* } *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 4. Using `filter` function: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: onlyPngLinks *
* }); *
* *
* function onlyPngLinks(item, depth) { *
* return ( *
* 'PlacedItem' === item.typename *
* && '.png' === item.file.name.slice(-4).toLowerCase() *
* ); *
* }; *
* *
* -------------------------------------------------------------------- *
* Example 4. Using the `filter` function for custom collecting: *
* *
* This example bypasses the normal returned array and instead *
* captures items in an "external" array `itemsByDepth`. *
* *
* var itemsByDepth = []; *
* *
* function getItemsByDepth(item, depth) { *
* if (undefined == itemsByDepth[depth]) *
* itemsByDepth[depth] = []; *
* itemsByDepth[depth].push(item); *
* }; *
* *
* getItems({ *
* from: app.activeDocument, *
* filter: getItemsByDepth *
* }); *
* *
* -------------------------------------------------------------------- *
* @param {Object} options - parameters
* @param {PageItem|Array<PageItem>|Document|Layer} options.from - the thing(s) to look in, eg. a selection.
* @param {Function} [options.filter] - function that, given a found item, must return true (default: no filtering).
* @param {Boolean} [options.getPageItems] - whether to include page items in returned items (default: true).
* @param {Boolean} [options.getGroupItems] - whether to include GroupItems in returned items (default: true).
* @param {Boolean} [options.getLayers] - whether to include Layers in returned items (default: false).
* @param {Boolean} [options.getHiddenItems] - whether to include hidden items in returned items (default: true).
* @param {Boolean} [options.getLockedItems] - whether to include locked items in returned items (default: true).
* @param {Boolean} [options.getGuideItems] - whether to include guide items in returned items (default: false).
* @param {Number} [options.maxDepth] - deepest folder level (recursion depth limit) (default: 99).
* @param {Boolean} [options.returnFirstMatch] - whether to return only the first found item (default: false).
* @param {Number} [depth] - the current depth (private).
* @returns {Array|PageItem} - all the found items in a flat array, or the first found item if `returnFirstMatch`.
*/
function getItems(options, depth) {
// defaults
options = options || {};
var found = [],
depth = depth || 0,
items = options.from;
if (!options.initialized)
// once-off initialization
if (!initialize())
return [];
itemsLoop:
for (var i = 0, item, len = items.length; i < len; i++) {
item = items[i];
if (
false === excludeFilter(item)
&& true === includeFilter(item)
) {
// item found!
found.push(item);
if (options.returnFirstMatch)
break itemsLoop;
}
if (
'GroupItem' !== item.constructor.name
&& 'Layer' !== item.typename
)
// only items with children from here
continue itemsLoop;
if (
excludeHidden(item)
|| excludeLocked(item)
)
// don't look into excluded containers
continue itemsLoop;
if (depth >= options.maxDepth)
// don't go deeper
continue itemsLoop;
// set up for the next depth
options.from = item.pageItems;
// look inside
found = found.concat(getItems(options, depth + 1));
}
// this level done
if (true == options.returnFirstMatch)
return found[0];
else
return found;
/**
* Returns true when the item should be not be found.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeFilter(item) {
return (
isAlreadyFound(item)
// is hidden
|| excludeHidden(item)
// is locked
|| excludeLocked(item)
// is guide
|| (
false === options.getGuideItems
&& true === item.guides
)
// is layer
|| (
false === options.getLayers
&& 'Layer' === item.typename
)
// is group item
|| (
false === options.getGroupItems
&& 'GroupItem' === item.typename
)
// is page item
|| (
false === options.getPageItems
&& 'GroupItem' !== item.typename
&& undefined != item.uuid
)
);
};
/**
* Returns true when the item should be included.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function includeFilter(item) {
return (
undefined == options.filter
|| options.filter(item, depth)
);
};
/**
* Returns true when the item should
* be excluded because it is hidden.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeHidden(item) {
return (
false === options.getHiddenItems
&& (
true === item.hidden
|| false === item.visible
)
);
};
/**
* Returns true when the item should
* be excluded because it is locked.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeLocked(item) {
return (
false === options.getLockedItems
&& true === item.locked
);
};
/**
* Returns true if item was already
* found, and marks item as found,
* to avoid finding same item twice.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function isAlreadyFound(item) {
var uuid = item.hasOwnProperty('uuid')
? item.uuid
: item.typename + item.zOrderPosition,
isFound = !!options.isFound[uuid];
options.isFound[uuid] = true;
return isFound;
}
/**
* Returns the initialised `options` object.
* @returns {Object}
*/
function initialize() {
// make a new object, so we don't pollute the original
options = {
initialized: true,
depth: 0,
isFound: {},
filter: options.filter,
getPageItems: false !== options.getPageItems,
getGroupItems: false !== options.getGroupItems,
getLayers: true === options.getLayers,
getHiddenItems: false !== options.getHiddenItems,
getLockedItems: false !== options.getLockedItems,
getGuideItems: true === options.getGuideItems,
maxDepth: options.maxDepth,
returnFirstMatch: options.returnFirstMatch,
};
if (
undefined == options.maxDepth
|| !options.maxDepth instanceof Number
)
options.maxDepth = 99;
// items is a single layer
if ('Layer' === items.typename)
items = [items];
// items is a document
else if ('Document' === items.constructor.name) {
var layers = items.layers;
items = [];
for (var i = 0; i < layers.length; i++)
items.push(layers[i]);
}
else if ('Array' !== items.constructor.name)
items = [items];
return items.length > 0;
};
};
Edit 2025-02-14: added `getItems` function to recursively search inside groups.
Copy link to clipboard
Copied
Hello @m1b, thank you for providing the script, it works wonders for simple objects, but when they are grouped objects or objects with clipping masks, the same does not happen. Will there be? some way to solve it
Copy link to clipboard
Copied
Oh yes you are right! In that case I need to be a bit more sophisticated about getting the selected objects...
I have updated the script above. Please try it again.
- Mark
P.S. Note that Illustrator does not assign rotation values to GroupItems, per se, so the contents of the groups will (in most cases!) unrotate, but not the groups themselves.
Copy link to clipboard
Copied
but it looks like it's not handling groups and clipping masks correctly. The main issue is that the script is rotating items individually within groups and masks, instead of rotating the entire group or mask as a single object.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi @vectora98504848 @yep that's what I meant in my P.S. above. Sadly groups don't seem to have rotation tags or any way to derive a rotation value.
What do you think of the following idea: that for every group (a clipping group is also a group by the way) I read the rotation of the first path item and then unrotate the group by that amount, not doing anything to the contents beyond that? When I get a chance I'll try it out.
- Mark
Copy link to clipboard
Copied
Bonjour Marc, je me suis permis (hier soir) de modifier votre fonction unrotate().
pour gérer les groupes, tracés transparents et les masques.
Cela semble fonctionner?
function unrotate(item) {
var grp = false, trs = false;
var accumRotation = undefined,
rotationTag;
if (item.hasOwnProperty('tags')) {
if (item.typename == "GroupItem" || item.typename == "CompoundPathItem") {
if (item.typename == "CompoundPathItem") {
rotationTag = getThing(item.pathItems[0].tags, 'name', 'BBAccumRotation');
trs = true;
}
else {
rotationTag = getThing(item.pageItems[0].tags, 'name', 'BBAccumRotation');
grp = true;
}
}
else rotationTag = getThing(item.tags, 'name', 'BBAccumRotation');
if (rotationTag)
accumRotation = rotationTag.value * 180 / Math.PI;
}
if (
undefined == accumRotation
&& item.hasOwnProperty('matrix')
)
// derive rotation from the matrix
accumRotation = getRotationFromMatrix(item.matrix);
if (undefined == accumRotation)
return;
// rotate the item
item.rotate(- accumRotation);
if (rotationTag)
// update tag
var pi;
if (grp)
for (var i = 0; i < item.pageItems.length; i++ ){
pi = item.pageItems[i];
rotationTag = getThing(pi.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) {rotationTag.value = 0;}
}
}
if (trs) {
pi = item.pathItems[0];
rotationTag = getThing(pi.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) {rotationTag.value = 0;}
rotationTag = getThing(item.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) {rotationTag.value = 0;}
}
if (!trs && !grp) rotationTag.value = 0;
};
René
Copy link to clipboard
Copied
@renél80416020 Wonderful! Thanks René! I'll add it in when I get a chance and OP can test it out. I didn't remember that compound path items also don't have BBAccumRotation tags, so that's for including that logic!
- Mark
Copy link to clipboard
Copied
Okay @vectora98504848 here is the script again, now with René's improved function. Let us know how it goes!
- Mark
/**
* @file Unrotate Selected Items 2.js
*
* Makes an attempt to remove any recorded rotation
* that can be derived from the selected items.
* Finds rotation either in the item's BBAccumRotation
* tag or the item's matrix.
*
* @author m1b
* @version 2025-02-17
* @discussion https://community.adobe.com/t5/illustrator-discussions/script-to-return-or-restore-rotation-of-multiple-selected-objects/m-p/15146692
*/
(function () {
var doc = app.activeDocument;
var items = getItems({
from: doc.selection,
getPageItems: true,
getGroupItems: true,
});
if (0 === items.length)
return alert('Please select some items to rotate and try again.');
for (var i = 0; i < items.length; i++)
unrotate2(items[i]);
})();
/**
* Attempt to return a page item to unrotated state.
* Modified by renél80416020 to apply rotation
* to group items and compound path items correctly.
* Important: will only work if the item has a valid
* BBAccumRotation tag or a matrix that is ammenable
* to derivation of the rotation.
* @author m1b and renél80416020
* @version 2025-02-14
* @param {PageItem} item - the item to unrotate.
* @return {Number} - the amount of rotation, in degrees.
*/
function unrotate2(item) {
var grp = false, trs = false;
var accumRotation = undefined,
rotationTag;
if (item.hasOwnProperty('tags')) {
if (item.typename == "GroupItem" || item.typename == "CompoundPathItem") {
if (item.typename == "CompoundPathItem") {
rotationTag = getThing(item.pathItems[0].tags, 'name', 'BBAccumRotation');
trs = true;
}
else {
rotationTag = getThing(item.pageItems[0].tags, 'name', 'BBAccumRotation');
grp = true;
}
}
else rotationTag = getThing(item.tags, 'name', 'BBAccumRotation');
if (rotationTag)
accumRotation = rotationTag.value * 180 / Math.PI;
}
if (
undefined == accumRotation
&& item.hasOwnProperty('matrix')
)
// derive rotation from the matrix
accumRotation = getRotationFromMatrix(item.matrix);
if (undefined == accumRotation)
return;
// rotate the item
item.rotate(- accumRotation);
if (rotationTag) {
// update tag
var pi;
if (grp)
for (var i = 0; i < item.pageItems.length; i++) {
pi = item.pageItems[i];
rotationTag = getThing(pi.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) { rotationTag.value = 0; }
}
if (trs) {
pi = item.pathItems[0];
rotationTag = getThing(pi.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) { rotationTag.value = 0; }
rotationTag = getThing(item.tags, 'name', 'BBAccumRotation');
if (rotationTag != undefined) { rotationTag.value = 0; }
}
if (!trs && !grp)
rotationTag.value = 0;
}
};
/**
* Returns a thing with matching property.
* If `key` is undefined, evaluate the object itself.
* @author m1b
* @version 2024-04-21
* @param {Array|Collection} things - the things to look through.
* @param {String} [key] - the property name (default: undefined).
* @param {*} value - the value to match.
*/
function getThing(things, key, value) {
for (var i = 0, obj; i < things.length; i++)
if ((undefined == key ? things[i] : things[i][key]) == value)
return things[i];
};
/**
* Returns the rotation amount, in degrees,
* of the given (not skewed) matrix.
* @author m1b
* @version 2023-10-20
* @param {Matrix} matrix - an Illustrator Matrix.
* @returns {Number}
*/
function getRotationFromMatrix(matrix) {
if (!matrix.hasOwnProperty('mValueA'))
throw new Error('getRotationFromMatrix: bad `matrix` supplied.');
// scaling factors
var scaleX = Math.sqrt(matrix.mValueA * matrix.mValueA + matrix.mValueC * matrix.mValueC);
// scaleY = Math.sqrt(matrix.mValueB * matrix.mValueB + matrix.mValueD * matrix.mValueD);
// rotation angle
var radians = Math.acos(matrix.mValueA / scaleX),
degrees = radians * (180 / Math.PI);
return Math.round(degrees * 1000) / 1000;
};
/** ------------------------------------------------------------------- *
* GET ITEMS *
* -------------------------------------------------------------------- *
* @author m1b *
* @version 2024-03-01 *
* -------------------------------------------------------------------- *
* Collects page items from a `from` source, eg. a Document, Layer, *
* GroupItem, or Array. Will look inside group items up to `maxDepth`. *
* Search can be filtered using `filter` function. Note that the *
* filter function is evaluated last in the filtering process. *
* -------------------------------------------------------------------- *
* Example 1. Get all items in document: *
* *
* var myItems = getItems({ from: app.activeDocument }); *
* *
* -------------------------------------------------------------------- *
* Example 2. Get all selected items except groups: *
* *
* var myItems = getItems({ *
* from: app.activeDocument.selection, *
* getGroupItems: false, *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 3. Using `filter` function to choose item type: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: function (item) { *
* return ( *
* 'PathItem' === item.typename *
* || 'CompoundPathItem' === item.typename *
* ); *
* } *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 4. Using `filter` function: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: onlyPngLinks *
* }); *
* *
* function onlyPngLinks(item, depth) { *
* return ( *
* 'PlacedItem' === item.typename *
* && '.png' === item.file.name.slice(-4).toLowerCase() *
* ); *
* }; *
* *
* -------------------------------------------------------------------- *
* Example 4. Using the `filter` function for custom collecting: *
* *
* This example bypasses the normal returned array and instead *
* captures items in an "external" array `itemsByDepth`. *
* *
* var itemsByDepth = []; *
* *
* function getItemsByDepth(item, depth) { *
* if (undefined == itemsByDepth[depth]) *
* itemsByDepth[depth] = []; *
* itemsByDepth[depth].push(item); *
* }; *
* *
* getItems({ *
* from: app.activeDocument, *
* filter: getItemsByDepth *
* }); *
* *
* -------------------------------------------------------------------- *
* @param {Object} options - parameters
* @param {PageItem|Array<PageItem>|Document|Layer} options.from - the thing(s) to look in, eg. a selection.
* @param {Function} [options.filter] - function that, given a found item, must return true (default: no filtering).
* @param {Boolean} [options.getPageItems] - whether to include page items in returned items (default: true).
* @param {Boolean} [options.getGroupItems] - whether to include GroupItems in returned items (default: true).
* @param {Boolean} [options.getLayers] - whether to include Layers in returned items (default: false).
* @param {Boolean} [options.getHiddenItems] - whether to include hidden items in returned items (default: true).
* @param {Boolean} [options.getLockedItems] - whether to include locked items in returned items (default: true).
* @param {Boolean} [options.getGuideItems] - whether to include guide items in returned items (default: false).
* @param {Number} [options.maxDepth] - deepest folder level (recursion depth limit) (default: 99).
* @param {Boolean} [options.returnFirstMatch] - whether to return only the first found item (default: false).
* @param {Number} [depth] - the current depth (private).
* @returns {Array|PageItem} - all the found items in a flat array, or the first found item if `returnFirstMatch`.
*/
function getItems(options, depth) {
// defaults
options = options || {};
var found = [],
depth = depth || 0,
items = options.from;
if (!options.initialized)
// once-off initialization
if (!initialize())
return [];
itemsLoop:
for (var i = 0, item, len = items.length; i < len; i++) {
item = items[i];
if (
false === excludeFilter(item)
&& true === includeFilter(item)
) {
// item found!
found.push(item);
if (options.returnFirstMatch)
break itemsLoop;
}
if (
'GroupItem' !== item.constructor.name
&& 'Layer' !== item.typename
)
// only items with children from here
continue itemsLoop;
if (
excludeHidden(item)
|| excludeLocked(item)
)
// don't look into excluded containers
continue itemsLoop;
if (depth >= options.maxDepth)
// don't go deeper
continue itemsLoop;
// set up for the next depth
options.from = item.pageItems;
// look inside
found = found.concat(getItems(options, depth + 1));
}
// this level done
if (true == options.returnFirstMatch)
return found[0];
else
return found;
/**
* Returns true when the item should be not be found.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeFilter(item) {
return (
isAlreadyFound(item)
// is hidden
|| excludeHidden(item)
// is locked
|| excludeLocked(item)
// is guide
|| (
false === options.getGuideItems
&& true === item.guides
)
// is layer
|| (
false === options.getLayers
&& 'Layer' === item.typename
)
// is group item
|| (
false === options.getGroupItems
&& 'GroupItem' === item.typename
)
// is page item
|| (
false === options.getPageItems
&& 'GroupItem' !== item.typename
&& undefined != item.uuid
)
);
};
/**
* Returns true when the item should be included.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function includeFilter(item) {
return (
undefined == options.filter
|| options.filter(item, depth)
);
};
/**
* Returns true when the item should
* be excluded because it is hidden.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeHidden(item) {
return (
false === options.getHiddenItems
&& (
true === item.hidden
|| false === item.visible
)
);
};
/**
* Returns true when the item should
* be excluded because it is locked.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeLocked(item) {
return (
false === options.getLockedItems
&& true === item.locked
);
};
/**
* Returns true if item was already
* found, and marks item as found,
* to avoid finding same item twice.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function isAlreadyFound(item) {
var uuid = item.hasOwnProperty('uuid')
? item.uuid
: item.typename + item.zOrderPosition,
isFound = !!options.isFound[uuid];
options.isFound[uuid] = true;
return isFound;
}
/**
* Returns the initialised `options` object.
* @returns {Object}
*/
function initialize() {
// make a new object, so we don't pollute the original
options = {
initialized: true,
depth: 0,
isFound: {},
filter: options.filter,
getPageItems: false !== options.getPageItems,
getGroupItems: false !== options.getGroupItems,
getLayers: true === options.getLayers,
getHiddenItems: false !== options.getHiddenItems,
getLockedItems: false !== options.getLockedItems,
getGuideItems: true === options.getGuideItems,
maxDepth: options.maxDepth,
returnFirstMatch: options.returnFirstMatch,
};
if (
undefined == options.maxDepth
|| !options.maxDepth instanceof Number
)
options.maxDepth = 99;
// items is a single layer
if ('Layer' === items.typename)
items = [items];
// items is a document
else if ('Document' === items.constructor.name) {
var layers = items.layers;
items = [];
for (var i = 0; i < layers.length; i++)
items.push(layers[i]);
}
else if ('Array' !== items.constructor.name)
items = [items];
return items.length > 0;
};
};
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Oh sorry @vectora98504848 I somehow didn't copy half of the script! I have fixed it now. - Mark
Copy link to clipboard
Copied
Thanks bro, I like Illustrator and even more the scripts help a lot but I'm still not at your level to program. 😉

