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!)
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();
Copy link to clipboard
Copied
Does that code written by r-bin helps you?
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
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; }
}
Copy link to clipboard
Copied
Wow that's perfect, thanks so much! Exactly what I'm looking for
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.
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.
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;
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?
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; }
Copy link to clipboard
Copied
That's perfect, thank you so much for all of your help! I really appreciate it
Copy link to clipboard
Copied
That's perfect, ....
.I do not like this method. If I find another, I'll write (maybe)