Search code examples
javascriptphotoshopphotoshop-script

Photoshop script select all layers with same name as current layer


I need a photoshop script that selects all layers with the same name as the currently selected layer. The following code does the job:


if (app.documents.length > 0) {

activeDocument.suspendHistory('stuff', 'main()');

function main(){

if(!documents.length) return;

var myDoc = app.activeDocument;

var theName = myDoc.activeLayer.name;

var theResults = new Array;

selectAllLayers();

var selectedLayers = getSelectedLayersIdx();

for(var a = 0; a < selectedLayers.length; a++){

var thisName = layerName(Number(selectedLayers[a]));

if (thisName == theName) {

          theResults.push(Number(selectedLayers[a]))

          };

};

selectLayerByIndex(theResults[0], false);

for (var m = 1; m < theResults.length; m++) {

selectLayerByIndex(theResults[m], true);

};

}

};

function getSelectedLayersIdx(){

           var selectedLayers = new Array;

           var ref = new ActionReference();

           ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

           var desc = executeActionGet(ref);

           if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){

                     desc = desc.getList( stringIDToTypeID( 'targetLayers' ));

                      var c = desc.count

                      var selectedLayers = new Array();

                      for(var i=0;i<c;i++){

                               try{

                                         activeDocument.backgroundLayer;

                                         selectedLayers.push(  desc.getReference( i ).getIndex() );

                               }catch(e){

                                         selectedLayers.push(  desc.getReference( i ).getIndex()+1 );

                               }

                      }

            }else{

                     var ref = new ActionReference();

                     ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));

                     ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

                     try{

                               activeDocument.backgroundLayer;

                               selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);

                     }catch(e){

                               selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));

                     }

           }

           return selectedLayers;

};

function selectAllLayers() {

var desc29 = new ActionDescriptor();

          var ref23 = new ActionReference();

          ref23.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

desc29.putReference( charIDToTypeID('null'), ref23 );

executeAction( stringIDToTypeID('selectAllLayers'), desc29, DialogModes.NO );

};

function layerName(idx){

var ref = new ActionReference();

ref.putIndex( charIDToTypeID( "Lyr " ), idx);

var desc = executeActionGet(ref);

return desc.getString(stringIDToTypeID("name"));

};

function selectLayerByIndex(index,add){

add = undefined ? add = false:add

var ref = new ActionReference();

    ref.putIndex(charIDToTypeID("Lyr "), index);

    var desc = new ActionDescriptor();

    desc.putReference(charIDToTypeID("null"), ref );

       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );

      desc.putBoolean( charIDToTypeID( "MkVs" ), false );

   try{

    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );

}catch(e){

alert(e.message);

}

};

BUT, there is one problem, my files have a ton of layers and so it appears that this code must iterate through them all, as such each time i need to run this script it takes 7minutes to execute. Is there a way to optimize this such that it will be faster even in files with VERY HIGH layer counts? Thanks


Solution

  • Each Photoshop layer is given a unique ID - (generated at creation in numerical order - I think - don't quote me on that) So you can access each layer by the ID instead of layer.getByname. The code below will show you the ID of the currently selected layer. - The upshot being, if you know the ID, you can get by layerID. :)

    To select more than one layer at a time: reuse the select_layer_by_ID with layer and true to add to the current selection.

    Get layer by ID:

    // Switch off any dialog boxes
    displayDialogs = DialogModes.NO; // OFF
    
    var srcDoc = app.activeDocument;
    var theLayer = srcDoc.activeLayer;
    var myLayerID = get_layer_id(theLayer);
    
    srcDoc.activeLayer = srcDoc.layers[0]; //top layer
    
    // now go back to original layer via layer ID!
    
    // select by layer ID
    select_layer_by_ID(myLayerID);
    alert("Layer ID: " + myLayerID + "\n" + srcDoc.activeLayer.name);
    
    // Switch off any dialog boxes
    displayDialogs = DialogModes.ALL; // ON
    
    // function SELECT LAYER BY ID(int, boolean)
    // --------------------------------------------------------
    function select_layer_by_ID(id, add)
    {
      if (add == undefined) add = false;
    
      var desc1 = new ActionDescriptor();
      var ref1 = new ActionReference();
      ref1.putIdentifier(charIDToTypeID('Lyr '), id);
      desc1.putReference(charIDToTypeID('null'), ref1);
      if (add) desc1.putEnumerated(stringIDToTypeID("selectionModifier"), stringIDToTypeID("selectionModifierType"), stringIDToTypeID("addToSelection"));
      executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
    } 
    
    // function GET LAYER ID(obj)
    // --------------------------------------------------------
    function get_layer_id(alayer)
    {
      return alayer.id;
    }