lic 73
lic 73

Reputation: 3

Adobe ExtendScript layer Processing

I am trying to create a script for processing layers with inversion. In Photoshop, this is done using ctrl +click on the layer. All the layers in my document are divided into groups. Because of this, an error occurs (photoshop is trying to invert the group). How can I skip groups in a loop or how can I fix it?

var doc = app.activeDocument;
var layers =activeDocument.layers;


for (var layerIndex = 0; layerIndex<doc.layers.length; layerIndex++) 
{
    
    var layer = layers [layerIndex];
    doc.activeLayer = layer;
 var idChnl = charIDToTypeID( "Chnl" );

            var actionSelect = new ActionReference();
            actionSelect.putProperty( idChnl, charIDToTypeID( "fsel" ) );

            var actionTransparent = new ActionReference();
            actionTransparent.putEnumerated( idChnl, idChnl, charIDToTypeID( "Trsp" ) );

            var actionDesc = new ActionDescriptor();
            actionDesc.putReference( charIDToTypeID( "null" ), actionSelect );
            actionDesc.putReference( charIDToTypeID( "T   " ), actionTransparent );

            executeAction( charIDToTypeID( "setd" ), actionDesc, DialogModes.NO );
            
            
            var invert = doc.selection.invert(actionSelect);
            var clear = doc.selection.clear(invert);
            var des = doc.selection.deselect(clear);
            
          //При попытке выделить группу возникает ошибка, нужно сделать пропуск группы
  }   


        

Upvotes: 0

Views: 402

Answers (1)

Andrei I. Gere
Andrei I. Gere

Reputation: 91

In Photoshop, for scripting purposes, normal layers are of type "ArtLayer" and groups are of type "LayerSet". A group (LayerSet) can be an array containing multiple layers (ArtLayer) or even multiple groups.

How can I skip groups in a loop?

So in your for loop, you want to know if the current layer is an actual layer or a group, by checking its typename:

...

var layer = layers [layerIndex];

if (layer.typename == "LayerSet") { //if current layer is a group
   continue; //skip to next loop element
}

doc.activeLayer = layer;

...

But, if all the layers in your document are divided into groups, your current for loop will not loop through the layers inside the groups, because your layers variable contains only the top level layers (activeDocument.layers).

Since these top level layers can be either a layer or a group, and the code above skips any groups, your loop will only go through any top level layers,if any, ignoring any layers inside groups (since groups are skipped).

In other words, if your document is structured such that ALL top level layers are groups, your loop will skip them all, and no layers will be processed.

How can I fix it?

You may want to fix your loop by checking whether the layer is a group, and if it is, loop through the group's layers also. There are many ways to go about it, depending on how complex you want to get with recursive functions, but to simplify, just create a nested for loop:

...

var layer = layers [layerIndex];

if (layer.typename == "LayerSet") { //if current layer is a group

    //if group, loop through its layers

    var groupLayers = layer.layers;

    for (var i = 0; i < groupLayers.length; i++) {
        var layer = groupLayers[i];
        doc.activeLayer = layer;

        // do your processing here

    } //end group layers loop
} //end if LayerSet

...

Since your processing code may apply in other cases also, like if you have top level layers outside of groups, it may be a good idea to extract it into its own function, rather than keeping it inside the for loop, and then simply call the function inside the loop or wherever else it may apply. So here's what your entire code could look like:

var doc = app.activeDocument;
var layers = doc.layers;


for (var layerIndex = 0; layerIndex < layers.length; layerIndex++) 
{
    
    var layer = layers[layerIndex];
    
    if (layer.typename == "LayerSet") { //if layer is a group
        
        //if group, loop through its layers
        var groupLayers = layer.layers;
        
        /** Note that a group could also have nested groups, 
        which is not accounted for in this scenario **/
        
        for (var i = 0; i < groupLayers.length; i++) {
            
            var layer = groupLayers[i];
            doc.activeLayer = layer;

            // do your processing here
            processLayer();
            
        } //end group layers loop
        
    } //end if LayerSet
    
} //end doc layers loop   

//Function for inverting active layer (or whatever your function does)
function processLayer(){
    
    var idChnl = charIDToTypeID( "Chnl" );

    var actionSelect = new ActionReference();
    actionSelect.putProperty( idChnl, charIDToTypeID( "fsel" ) );

    var actionTransparent = new ActionReference();
    actionTransparent.putEnumerated( idChnl, idChnl, charIDToTypeID( "Trsp" ) );

    var actionDesc = new ActionDescriptor();
    actionDesc.putReference( charIDToTypeID( "null" ), actionSelect );
    actionDesc.putReference( charIDToTypeID( "T   " ), actionTransparent );

    executeAction( charIDToTypeID( "setd" ), actionDesc, DialogModes.NO );

    var invert = doc.selection.invert(actionSelect);
    var clear = doc.selection.clear(invert);
    var des = doc.selection.deselect(clear);
    
    return;
    
} //end processLayer()

FYI: It is a good idea to have a copy of the Photoshop Javascript Reference when developing Photoshop scripts. You can use the reference pdf to see all the properties and methods available for ArtLayer layers and LayerSets (groups) layers, like the name, opacity, whether it's visible, etc.

Upvotes: 2

Related Questions