Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Passing a Layer Object to AM code

Explorer ,
Apr 02, 2018 Apr 02, 2018

I'm trying to write code that will spit out the layer ID (not index) of a layer, given the layer object.

I'm calling getSelectedLayers() followed by touchUpLayerSelection() (taken from 'delete All Masks.jsx'), which returns an array of layer objects (eg [ [ArtLayer Layer 1] , [ArtLayer Layer 2] ]). I then want to store the unique Layer IDs of each of these selected layers for future use. I'm using layer IDs because the layer index may change, and there could be multiple layers with the same name.

I've found the following code of these forums that can get the layer ID, but it works on the active layer, meaning I have to set each layer in turn as the active, which on a document with a lot of layers is quite slow.

function getLayerID() {

     var ref = new ActionReference();

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

     return executeActionGet(ref).getInteger(stringIDToTypeID( "layerID" ));

};

I want to be able to do:

var selectedLayers = getSelectedLayers();

var arr = [];

touchUpLayerSelection();

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

     arr.push(getLayerID( selectedLayers ));

};

return arr;

But I'm not sure how I should feed a layer object from the selectedLayers array into the AM code.

If it matters I'm targeting Photoshop CS6.

Any help hugely appreciated!

(ps. Not sure why my code isn't formatting correctly, sorry about that!)

TOPICS
Actions and scripting
1.4K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

People's Champ , Apr 02, 2018 Apr 02, 2018

Probably this is what you need

alert(get_selected_layers_id().toSource())

function get_selected_layers_id()

    {

    try {

        var r = new ActionReference();   

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));   

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

        var d = executeActionGet(r);

        if (!d.hasKey(stringIDToTypeID("targetLayers")))

            {

            var r = new ActionReference();

           

...
Translate
Adobe
Community Expert ,
Apr 02, 2018 Apr 02, 2018

Does that code written by helps you?

Re: Getting layer reference by ID

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 02, 2018 Apr 02, 2018

Running that give me the error message

"- The command “Get” is not currently available."

I'm just running it as is, could be doing something wrong

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Apr 02, 2018 Apr 02, 2018

Probably this is what you need

alert(get_selected_layers_id().toSource())

function get_selected_layers_id()

    {

    try {

        var r = new ActionReference();   

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));   

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

        var d = executeActionGet(r);

        if (!d.hasKey(stringIDToTypeID("targetLayers")))

            {

            var r = new ActionReference();

            r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerID"));   

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

            return [ executeActionGet(r).getInteger(stringIDToTypeID("layerID")) ];

            }

        var list = d.getList(stringIDToTypeID("targetLayers"));

        if (!list) return null;

   

        var n = 0;

        try { activeDocument.backgroundLayer } catch (e) { n = 1; }

   

        var len = list.count;

   

        var selected_layers = new Array();

   

        for (var i = 0; i < len; i++)

            {

            try

                {

                var r = new ActionReference();

                r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerID"));   

                r.putIndex( charIDToTypeID("Lyr "), list.getReference(i).getIndex() + n);

                selected_layers.push(executeActionGet(r).getInteger(stringIDToTypeID("layerID")));

                }

            catch (e) { _alert(e); return null; }

            }

   

        return selected_layers;

        }

    catch (e) { alert(e); return null; }

    }

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 02, 2018 Apr 02, 2018

Wow that's perfect, thanks so much! Exactly what I'm looking for

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Apr 03, 2018 Apr 03, 2018

New Photoshop versions have a list of selected layersID by default in document action descriptor. So you don't even need to convert indexes to IDs.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 03, 2018 Apr 03, 2018

Had a chance now to test it out a bit more, and it's so very close to what I need. Is it possible to have this function detect if no layers are selected, and return null if so? I think it does everything I need except this - if no layers are selected it will return the ID of the top most layer in the stack.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Apr 03, 2018 Apr 03, 2018

If I understand correctly, then replace this

if (!d.hasKey(stringIDToTypeID("targetLayers")))

    {

    var r = new ActionReference();

    r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerID"));   

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

    return [ executeActionGet(r).getInteger(stringIDToTypeID("layerID")) ];

    }

with

if (!d.hasKey(stringIDToTypeID("targetLayers")))  return null;

Works only for CS6, for CC2018 does not.

P.S. And even correct the inaccuracy.

if (!list) return null;

to

if (!list.count) return null;

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 03, 2018 Apr 03, 2018

Not quite but very close, though only because I didn't explain myself very well.

I'd like to do different things depending on whether 0, 1, or >1 layers are selected.

var layerIDs = get_selected_layers_ids();

var len = layerIDs.length;

if (len > 1) { //multiple layers selected

     //do something;

} else if (len == 1) { //one layer selected

     //do something else;

} else { //0 or null layers selected

     //do something other;

}

Your original function will always return len of >= 1, whereas the updated code will return null if either 0 or 1 layer is selected. Is there a way to get all three possibilities in one?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Apr 03, 2018 Apr 03, 2018

You can check in this way that nothing is selected

var nothing_selected = false;

try { activeDocument.activeLayer.name = activeDocument.activeLayer.name; } catch (e) { nothing_selected = true; }

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 03, 2018 Apr 03, 2018

That's perfect, thank you so much for all of your help! I really appreciate it

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Apr 03, 2018 Apr 03, 2018
LATEST

jonnyr39056025

That's perfect, ....

.I do not like this method. If I find another, I'll write (maybe)

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines