Reputation: 361
This script works perfectly apart from one aspect: it doesn't loop through layers that are nested within folders. I've tried changing layers
to layerSets
as per this question, but then it stops working on folder names. I'm using Photoshop 2020 on Mac Catalina.
// JavaScript Document
var doc = app.activeDocument;
// name indexed object
var layernames = {
'Products':'Working',
'Product':'Working',
'Notes':'Note',
'Background color':'Background Colour',
'White background':'White Background'
};
// loop through all layers
for (var i = 0; i < doc.layers.length; i++)
{
//Set up Variable to access layer name
var currentLayer = app.activeDocument.layers;
if (layernames[currentLayer.name]) {
currentLayer.name = layernames[currentLayer.name];
}
}
Upvotes: 1
Views: 446
Reputation: 25042
Consider the following solution that utilizes a recursive function called renameLayers
to traverse all layer nodes in the document layers tree structure.
A layers typename
property may be set to either ArtLayer
or LayerSet
. Essentially when a layers typename
is a LayerSet
(i.e. a Folder) we recursively call the function again.
var doc = app.activeDocument;
/**
* Rename layers in a Photoshop document.
*
* @param {Object} doc A reference to the document to change.
* @param {Object} layerName Each property key name indicates the original layer
* name, and its corresponding value indicates the new layer name.
* @param {Object} options The configuration options.
* @param {Boolean} [options.includeTextLayers=false] Whether to rename text layers.
* @param {Boolean} [options.includeLayerSets=false] Whether to rename LayerSets.
*/
function renameLayers(doc, layerNames, options) {
// Default options
var opts = {
includeTextLayers: false,
includeLayerSets: false
};
// Overwrite properties in the default `opts` object by properties in the
// user defined `options` object if they have the same key. Shallow copy only.
if (typeof options === 'object') {
for (var key in opts) {
if (options.hasOwnProperty(key)) {
opts[key] = options[key];
}
}
}
// Iterate each layer in the document.
for (var i = 0, max = doc.layers.length; i < max; i++) {
var currentLayer = doc.layers[i];
if (currentLayer.typename === 'ArtLayer') {
if (layerNames[currentLayer.name]
&& (opts.includeTextLayers || currentLayer.kind !== LayerKind.TEXT)) {
currentLayer.name = layerNames[currentLayer.name];
}
} else { // The layers `typename` is a `LayerSet`
if (layerNames[currentLayer.name] && opts.includeLayerSets) {
currentLayer.name = layerNames[currentLayer.name];
}
renameLayers(currentLayer, layerNames, options); // Resursive call
}
}
}
// Demo Usage
var layerNames = {
'Products': 'Working',
'Product': 'Working',
'Notes': 'Note',
'Background color': 'Background Colour',
'White background': 'White Background'
};
renameLayers(doc, layerNames);
As you can see in the last line of code (above) we invoke the renameLayers
function as follows:
renameLayers(doc, layerNames);
Here we pass in the doc
variable, i.e. a reference to the document to change, and the layerNames
object that defines the mappings for the original layer name and the new layer name.
Running the code shown above (as is) will rename any layer in accordance with the mappings specified in the layerNames
object. However it currently does not rename any Text Layer(s) or LayerSet(s).
How can I also rename Text Layers and/or LayerSets?
The renameLayers
function lists a third optional parameter, named options
to allow a custom configuration to be defined.
The following three function invocations demonstrate how different configurations can be achieved by passing in the optional options
argument:
Invoking the function as follows with includeLayerSets
set to true
renames LayerSets too:
renameLayers(doc, layerNames, { includeLayerSets: true });
Invoking the function as follows with includeTextLayers
set to true
renames Text Layers too:
renameLayers(doc, layerNames, { includeTextLayers: true });
Invoking the function as follows with includeLayerSets
and includeTextLayers
set to true
renames both LayerSets and Text Layers too:
renameLayers(doc, layerNames, {
includeLayerSets: true,
includeTextLayers: true
});
Upvotes: 1
Reputation: 325
From what I understand from the doc (https://www.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/photoshop-scripting-guide-2020.pdf), layers may contain ArtLayers or LayerSets. The LayerSets contain other nested layers...
You could create a function to rename every Layer (what you did), but when it encounters a LayerSet, also recursively call the function on currentLayer.layers
.
To know if a specific Layer is a LayerSet, try if (currentLayer.layers) ...
.
Upvotes: 0