Skip to main content
jonathankemp
Inspiring
May 16, 2020
Answered

Best clean way to get number of selected layers within script.

  • May 16, 2020
  • 2 replies
  • 3974 views

So,

I'm looking for the best way to count the number of selected layers in a PS document.

 

I've been looking around and stumbled on this piece of code : https://graphicdesign.stackexchange.com/questions/104786/is-it-possible-to-count-the-number-of-layers-selected-in-photoshop

 

It does work, but it works by creating a new group before counting the layers, then undoing it all.  This fires a "Mk " event.  And since the script has an EventListenner looking out for "Mk " events, well... I get stuck in an endless loop...

 

Isn't there a simple and effective way to count the selected layers ?  Actually... I just need to know if there's more than one selected...

 

Many thanks.

 

J.

This topic has been closed for replies.
Correct answer jazz-y
s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayers'));
r.putEnumerated (s2t ('document'), s2t ('ordinal'), s2t ('targetEnum'));
n =  executeActionGet (r).hasKey(p) ?  executeActionGet (r).getList(p).count : 0;
alert (n)

2 replies

Charu Rajput
Community Expert
Community Expert
May 16, 2020

Hi,

This is another version of the script that you have shared above.

 

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

function getSelectedLayers() {
    var resultLayers = new Array();
    try {
        var idGrp = stringIDToTypeID("groupLayersEvent");
        var descGrp = new ActionDescriptor();
        var refGrp = new ActionReference();
        refGrp.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        descGrp.putReference(charIDToTypeID("null"), refGrp);
        executeAction(idGrp, descGrp, DialogModes.NO);
        for (var i = 0; i < app.activeDocument.activeLayer.layers.length; i++) {
            resultLayers.push(app.activeDocument.activeLayer.layers[i])
        }
        var id8 = charIDToTypeID("slct");
        var desc5 = new ActionDescriptor();
        var id9 = charIDToTypeID("null");
        var ref2 = new ActionReference();
        var id10 = charIDToTypeID("HstS");
        var id11 = charIDToTypeID("Ordn");
        var id12 = charIDToTypeID("Prvs");
        ref2.putEnumerated(id10, id11, id12);
        desc5.putReference(id9, ref2);
        executeAction(id8, desc5, DialogModes.NO);
        return resultLayers;
    } catch (e) {
        alert("No Layer selected or locked layer selected");
        return resultLayers;
    }
}
var selectedLayers = getSelectedLayers();
$.writeln(selectedLayers.length);

 

This will give you an array of selected layers. I hope this helps

 

Thanks

Best regards
Hot amateurs
Participant
November 7, 2020

This helped me a lot, thanks

jazz-yCorrect answer
Legend
May 16, 2020
s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayers'));
r.putEnumerated (s2t ('document'), s2t ('ordinal'), s2t ('targetEnum'));
n =  executeActionGet (r).hasKey(p) ?  executeActionGet (r).getList(p).count : 0;
alert (n)
Charu Rajput
Community Expert
Community Expert
May 16, 2020

Hi, This is a nice solution. Could you please explain me (just want to learn), how exactly it is working.

Highly appreciated!

 

Thanks

Best regards
Legend
May 16, 2020

This is the code for the action manager, the Photoshop subsystem. Action manager objects are stored in ActionDescriptors. The names of properties and methods are encoded by numeric keys, which we can receive and convert using functions like stringIDToTypeID.
In that case, we get access to the ActionDescriptor of the current document using the ActionReference (this is something like a link to the desired object). Using the ActionReference, we describe the property that we need. We need to get a list of selected layers - it is stored as an ActionList named 'targetLayers'. To do that we create a new ActionReference, first put the name of the property we need into it (so as not to request the entire document object):
(r = new ActionReference) .putProperty (s2t ('property'), p = s2t ('targetLayers'));
then we indicate that this property should be taken from the active document:
r.putEnumerated (s2t ('document'), s2t ('ordinal'), s2t ('targetEnum'));
Since layers may or may not be selected, then using executeActionGet and the .hasKey () function, we check if we have the property we need, if so, we write the number of elements in the list of selected layers to a variable
executeActionGet (r) .getList (p) .count , if not, then write to the variable 0.

At the same time, it is not difficult to obtain the index of each layer from the resulting list and with its help obtain all the necessary properties of each selected layer.