index of active layer

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

jay

index of active layer

Post by jay »

Is there a way to find the location of the actively selected layer? I'd like to get it's index number if possible. This layer might also exist in a layerset.

If I run this applescript code I get the index I need, but I'd like to find a similar way in javascript:

Code: Select alltell application "Adobe Photoshop CS"
   tell document 1
      current layer's index
   end tell
end tell

-->  I have the 4th layer down selected so it returns 4


Thanks.

Jay
xbytor

index of active layer

Post by xbytor »

There are two kinds of layer indexes. The DOM index (which indexes you into a collection of layers) has no API support. You have to write your own function for that. Some have been posted. I don't have one.

The internal index, which can be used using the ActionManager APIs, can be found with this:

Code: Select allcTID = function(s) { return app.charIDToTypeID(s); };

Stdlib = function(){};

Stdlib.hasBackground = function(doc) {
  return doc.layers[doc.layers.length-1].isBackgroundLayer;
}

Stdlib.getActiveLayerIndex = function(doc) {
  var desc = Stdlib.getActiveLayerDescriptor(doc);
  var idx = desc.getInteger(cTID('ItmI'));
  return Stdlib.hasBackground(doc) ? idx-1 : idx;
};
Stdlib.getActiveLayerDescriptor = function(doc) {
    var ref = new ActionReference();
    ref.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
    return executeActionGet(ref);
  }
};


Using this index can be a great help with performance when you are dealing with documents with a large number of layers (e.g. 400).

-X
jay

index of active layer

Post by jay »

Hi X,

Thanks again for taking the time to help. I'm running the code on a Mac (OS X 10.3) and can't figure out how to make your code work. If you have time can you expain a little of it?

I came up with this method that seems to do what I need, although I doubt it's very efficient:

Code: Select allvar theDoc = app.activeDocument;
      
var aLayer = theDoc.activeLayer;
var layerList = aLayer.parent.layers;

for (var x = 0; x < layerList.length; x++) {
   if (layerList[x] == aLayer) { break; }
}

alert("Current layer index: " + x);

//If I selected the 3rd layer it returns "Current layer index: 2"


Thanks again for your help X!

Jay
null

index of active layer

Post by null »

xbytor wrote:The internal index, which can be used using the ActionManager APIs
Slightly off topic, but out of curiosity, is there any way to quickly and easily determine the maximum layer index (other than the obvious of catch'ing use of the index and having it fail?)
Mike Hale

index of active layer

Post by Mike Hale »

This function will give the number of layer/layersets in a doc. But Photoshop assigns two index numbers to each layerset so it will be off if there are layersets in the doc.

Code: Select allfunction getNumberOfLayer(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
var numberOfLayer = desc.getInteger(charIDToTypeID("NmbL"));
return numberOfLayer;
} ;
null

index of active layer

Post by null »

Mike Hale wrote:This function will give the number of layer/layersets in a doc. But Photoshop assigns two index numbers to each layerset so it will be off if there are layersets in the doc.
Thanks for the quick reply Mike. I had looked at "NmbL" before (presumably for "Number of Layers"?) but it never was consistent, at least now I know why. Why does everything have to be so complicated? 2 index numbers per layerset? Why Adobe, why?!

Are the "duplicate" index numbers always sequential, such that you could "skip" the next one in some sort of loop?
Mike Hale

index of active layer

Post by Mike Hale »

I think the layersets have one index for the start of the set. That is the one you can use with action manager code. It has another for the end of the set. Using that index wth action manager code throws an error in most cases.

The end index will be offset from the start by the number of nested layers/layersets
Mike Hale

index of active layer

Post by Mike Hale »

You can skip them by checking the layer's name for that index number. The end of layerset index will have the name '</Layer group>'

Code: Select allfunction getLayerDescriptor(idx) {
    var ref = new ActionReference();
    ref.putIndex(charIDToTypeID( "Lyr " ), idx);
    return executeActionGet(ref);
}
function getLayerName(idx) {
    var desc = getLayerDescriptor(idx);
    return desc.getString(charIDToTypeID( "Nm  " ));
}
var cnt = getNumberOfLayer()
for(i=0;i<cnt;i++){
   if(getLayerName(i)!= '</Layer group>'){
      $.writeln(getLayerName(i));
   }
}
null

index of active layer

Post by null »

Thanks again Mike. The two index thing makes sense if PS has an end of layer set layer internally.

It seems getNumberOfLayer() is quite slow when you have even a moderately complex document (another thing I just don't get).
xbytor

index of active layer

Post by xbytor »

It seems getNumberOfLayer() is quite slow when you have even a moderately complex document (another thing I just don't get).

It's that bad, actually. Doing it via Layers/LayerSets would be painfully slow in a doc with a large number of layers.

Also, instead of checking the layer name for the the end-of-layerset, I am now using the layer type:
Code: Select all//
// returns one of:
// sTID('layerSectionStart')     Start of a layer set
// sTID('layerSectionEnd')       End of a layer set
// sTID('layerSectionConent')  A content layer
//
function getLayerType(doc, idx) {
   var desc = getLayerDescriptorByIndex(doc, idx);
   return desc.getEnumerationValue(sTID('layerSection'));
};