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

Passing a Layer Object to AM code

Explorer ,
Apr 02, 2018 Apr 02, 2018

Copy link to clipboard

Copied

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

Views

1.0K

Translate

Translate

Report

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();

           

...

Votes

Translate

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

Copy link to clipboard

Copied

Does that code written by helps you?

Re: Getting layer reference by ID

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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; }

    }

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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;

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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?

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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; }

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

LATEST

jonnyr39056025

That's perfect, ....

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

Votes

Translate

Translate

Report

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