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

Accessing all the layers in all the layer sets

Community Beginner ,
Mar 07, 2019 Mar 07, 2019

Copy link to clipboard

Copied

Hi Everyone,

I am writing a script that searches through all the layers and changes labels and names based on blend mode, layer types, etc.

I can get all the layers not in sets into an array and act upon them.

I can get all the layersets into an array. ( I want to put layersets in an array so I can do things like count them, search, them, rename later)

I can't figure out how to drill down into the layersets so I can get the contained layers pushed into the layer array.

I thought it might be something like this, but this doesn't work.

var layerSetArray = [ ];

// how I got the layers:

for(var i = 0; i < doc.artLayers.length; i++)

//how I got the layersets:

for( var i = doc.layerSets.length-1; 0 <= i; i--){

   var layerSetName = doc.layerSets[i].toString();

   layerSetArray.push(layerSetName)

}

//what I can't figure out: (doesn't work)

for( var i = doc.layerSetArray.length; 0 < ii++){

   var nestedLayer = layerSetArray[i].artLayers.name

   layerSetArray.push(nestedLayer)

}

Any suggestions would be greatly appreciated.

Thanks for reading!

TOPICS
Actions and scripting

Views

6.8K

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
Adobe
Community Expert ,
Mar 07, 2019 Mar 07, 2019

Copy link to clipboard

Copied

/* ==========================================================

// 2017  John J. McAssey (JJMack)

// ======================================================= */

// This script is supplied as is. It is provided as freeware.

// The author accepts no liability for any problems arising from its use.

// enable double-clicking from Mac Finder or Windows Explorer

#target photoshop // this command only works in Photoshop CS2 and higher

// bring application forward for double-click events

app.bringToFront();

// ensure at least one document open

if (!documents.length) alert('There are no documents open.', 'No Document');

else {

// declare Global variables

//main(); // at least one document exists proceed

    app.activeDocument.suspendHistory('Some Process Name','main()');

}

///////////////////////////////////////////////////////////////////////////////

//                            main function                                  //

///////////////////////////////////////////////////////////////////////////////

function main() {

// declare local variables

var orig_ruler_units = app.preferences.rulerUnits;

var orig_type_units = app.preferences.typeUnits;

var orig_display_dialogs = app.displayDialogs;

app.preferences.rulerUnits = Units.PIXELS;  // Set the ruler units to PIXELS

app.preferences.typeUnits = TypeUnits.POINTS;   // Set Type units to POINTS

app.displayDialogs = DialogModes.NO;     // Set Dialogs off

try { code(); }

// display error message if something goes wrong

catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }

app.displayDialogs = orig_display_dialogs;  // Reset display dialogs

app.preferences.typeUnits  = orig_type_units; // Reset ruler units to original settings

app.preferences.rulerUnits = orig_ruler_units; // Reset units to original settings

}

///////////////////////////////////////////////////////////////////////////////

//                           main function end                               //

///////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////

// The real code is embedded into this function so that at any point it can return //

// to the main line function to let it restore users edit environment and end      //

/////////////////////////////////////////////////////////////////////////////////////

function code() {

processArtLayers(activeDocument) 

}

function processArtLayers(obj) { 

    for( var i = obj.artLayers.length-1; 0 <= i; i--) {processLayers(obj.artLayers);} 

    for( var i = obj.layerSets.length-1; 0 <= i; i--) {processArtLayers(obj.layerSets); } // Process Layer Set Layers 

}

function processLayers(layer) {

switch (layer.kind){

case LayerKind.SMARTOBJECT : processSmartObj(layer); break;

default : break; // none process layer types catch all

}

}

//////////////////////////////////////////////////////////////////////////////////

// Layer Type Functions //

//////////////////////////////////////////////////////////////////////////////////

function processSmartObj(obj) {

var localFilePath = "";

var ref = new ActionReference();   

    ref.putIdentifier(charIDToTypeID('Lyr '), obj.id );   

    var desc = executeActionGet(ref);   

    var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));  

try {

var localFilePath = smObj.getPath(stringIDToTypeID('link'));  

alert("Layer " + obj.name + ' linked file is"' +  localFilePath + '"');

}

catch(e) {}

return localFilePath;

}

recursion is required for nested groups Layer name need not be unique all layers could have the same name I have seen an Adobe template PSD with 60+ independent smart object layers  and all those smart object layers had the same name "Your Image Here". You can push all layer into an array Id do not know the order the layer would be in the array. I believe layers have an index number that is unique I have never need to use the index numbers. I mostly add layer   to  the top  of the stack or above a required background layer.  Don't have any experience scripting layer groups.

JJMack

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 ,
Mar 08, 2019 Mar 08, 2019

Copy link to clipboard

Copied

var layers = new Array();

var sets = new Array();

get_layers_and_sets(activeDocument, layers, sets);

alert(layers);

alert(sets);

function get_layers_and_sets(set, l, s)

    {

    function scan(layers, sets)

        {

        for (var i = 0; i < layers.length; i++) l.push(layers);           

        var length = sets.length;

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

            {  

            var set = sets;

            s.push(set);

            scan(set.artLayers, set.layerSets);

            }

        }

    scan(set.artLayers, set.layerSets);

    }

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 ,
Mar 10, 2019 Mar 10, 2019

Copy link to clipboard

Copied

You don't need to create additional arrays. The document collections for layers, layer sets, etc., are already arrays. Just access them. You need to anyway, if you want to change anything. Having a separate array of the layer/layer set names is just that, only their names. That won't let you change what the name is -- you need a reference to the actual layer object to do that.

 

Here is a basic example of how to walk through all layers in a document, and dive deeper when it's a layer set. Which also handles layer sets inside layer sets.

 

processLayers(app.activeDocument);

function processLayers(o) {
    var i;
    var layer;
    for (i = 0; i < o.layers.length; i++) {
        layer = o.layers[i];
        if (layer instanceof LayerSet) {
            // If layer set, recurse (call self).
            processLayers(layer);
        }
        changeLayer(layer);
        //
        // If you only want to affect art layers, not layer sets,
        // move call to changeLayer into else, then it will not
        // happen to layer sets, only art layers.
        // } else {
        //    changeLayer(layer)
        // }
    }
}

function changeLayer(layer) {
    layer.name = "x-" + layer.name;
    // Simple change prefix layer name with "x-" to demonstrate.
    // Change to whatever code you want done to each layer.
}

 

William Campbell

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
Community Expert ,
Mar 11, 2019 Mar 11, 2019

Copy link to clipboard

Copied

Yes the layers array is a set of layeres and layers Set a top level view of you document.  I normally use only this array for  I normally only deal with layers that are not in any group.  My scripts deal with Layers on the top and bottom on the layers stack not in any group.   Adobe's layers array is what I normally use to address them. Many of the Template PSD I deal with may have no groups at all. So All I need to use in Adobe's layers array.

JJMack

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
Community Beginner ,
Aug 07, 2019 Aug 07, 2019

Copy link to clipboard

Copied

This code is working. I have some issues thought because I can't seem to do some things in the changeLayer function.

I understand how to change the name, like you listed: layer.name = "Some Text" + layer.name;

for some operations though I think I need to make the layer active so I can do things like give it a color label ( in this case green)

I made a function from the Script Listener code that works to label a layer , but this function made from Script Listener doesn't work.

Do I need to make the layer active first ( and if so then how) or do I need to remove something from my Script Listener code?

function GREEN(){

  

   var idsetd = charIDToTypeID( "setd" );

   var desc5653 = new ActionDescriptor();

   var idnull = charIDToTypeID( "null" );

   var ref1531 = new ActionReference();

   var idLyr = charIDToTypeID( "Lyr " );

   var idOrdn = charIDToTypeID( "Ordn" );

   var idTrgt = charIDToTypeID( "Trgt" );

   ref1531.putEnumerated( idLyr, idOrdn, idTrgt );

   desc5653.putReference( idnull, ref1531 );

   var idT = charIDToTypeID( "T " );

   var desc5654 = new ActionDescriptor();

   var idClr = charIDToTypeID( "Clr " );

   var idClr = charIDToTypeID( "Clr " );

   var idGrn = charIDToTypeID( "Grn " );

   desc5654.putEnumerated( idClr, idClr, idGrn );

   var idLyr = charIDToTypeID( "Lyr " );

   desc5653.putObject( idT, idLyr, desc5654 );

   executeAction( idsetd, desc5653, DialogModes.NO );

  

  

  }

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
Community Expert ,
Aug 07, 2019 Aug 07, 2019

Copy link to clipboard

Copied

You pass the layer object you want to rename to changeLayer function  If you want to rename the active layer you would pass the active layer object to the function

changeLayer(app.activeDocument.activeLayer);

function changeLayer(layer) { 

    layer.name = "x-" + layer.name; 

     // Simple change prefix layer name with "x-" to demonstrate. 

    // Change to whatever code you want done to each layer. 

If you want to make the layer you are currently processing the active layer you would set the active layer to the late being processed,

app.activeDocument.activeLayer = layer;

you may want to first save that current active layer in the beginning of the script and restore the active layer when the script is ending.

The action manager code you have in the GREEN function may be setting the active layer color green in the layer palette.  Is do not see a layer ID or name in the function code just idTrgt and idT which are set to  "Trgt" and "T" If I have not record the action manager code via Scriptlistener I can not always decipher what some action manager code does as far the setting go in the actions descriptors and action references.

JJMack

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 ,
Aug 08, 2019 Aug 08, 2019

Copy link to clipboard

Copied

1. Yes, each time another layer is selected and passed to the 'changeLayer()' function (the passed argument, 'layer'), there are manipulations that do require the layer in question be the active layer. My example of simply modifying the name is an example that doesn't require the layer be the active layer. Tagging with a color, however, does require the layer be the active layer. It seems any call to executeAction on a layer wants it to be active, so I've got in the habit of making sure the layer I want changed is active.

2. There is a flaw in your code example. The line...

var idT = charIDToTypeID( "T " );

Should be...

var idT = charIDToTypeID( "T   " );

(three spaces after T; your code has only one)

As well, the code to tag the layer green can be simplified. It does work once above is fixed, but I found less lines will get the same done. See below, a working example of revised 'changeLayer()' function.

function changeLayer(layer) {

    layer.name = "x-" + layer.name;

    // Simple change prefix layer name with "x-" to demonstrate.

    // Change to whatever code you want done to each layer.

    // Select the current layer, which was passed as argument 'layer'.

    app.activeDocument.activeLayer = layer;

    // Tag the active layer 'Grn ' (green color).

    var desc1 = new ActionDescriptor();

    var ref1 = new ActionReference();

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

    desc1.putReference(charIDToTypeID('null'), ref1);

    var desc2 = new ActionDescriptor();

    desc2.putEnumerated(charIDToTypeID('Clr '), charIDToTypeID('Clr '), charIDToTypeID('Grn ')); // <---- NOTE: here is where color 'green' is set.

    desc1.putObject(charIDToTypeID('T   '), charIDToTypeID('Lyr '), desc2);

    executeAction(charIDToTypeID('setd'), desc1, DialogModes.NO);

}

Furthermore, if you want a function that can tag different colors besides green, put the code above in a function and pass a 'color' argument that can replace 'Grn ' in the code above, put that portion of the function into another, call it 'tagLayer(color') for example. You'll have to study somewhere to determine (or guess and test) the string values for the various colors (green = 'Grn ', we know that much). Pay attention to spaces!  Set up for executeAction the arguments are very specific, 4 characters so any that are less pad the right with spaces.

William Campbell

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
Advocate ,
Mar 24, 2020 Mar 24, 2020

Copy link to clipboard

Copied

Thats is way shorter indeed, doing that nested loop and calling the function from within it self is so much simpler. Nice!

How do i add selected layers when i got an array of layer selection from the start?
I got this script for an animation panel and i would like to add some functionality to it. Im using a function to get all selected layers, this returns an array of layer index. Then a second function is used to get the name. But i need to make that short because currently I'm running a loop twice. Your code shows it can be done in a single loop.

So i get back an Array of these layers. I tried doing a loop to make a layer selected, but this is not additive. This loop is like this;

for (var i = 0; i < layerInfo.length; i++) {
   docRef.layers[layerInfo[i].name].selected = true;
   // alert(layerInfo[i].name) // take 0 into account
}

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 ,
Mar 24, 2020 Mar 24, 2020

Copy link to clipboard

Copied

I noticed an error in my code example and updated it. In the for loop the index was missing. Was just 'layer = o.layers'. Should be 'layer = o.layers[i]'. I've updated the earlier post.

 

About your new question, it is unclear just what you are asking. The for loop in your last message seems odd. I am guessing the variable 'layerInfo' is an array of layers. If so, the code within the loop seems excess, and I don't think it will work as written. If the variable 'layerInfo' is indeed an array of layers, simply act on each element of that array, one by one in the loop. But if the variable 'layerInfo' is an array of layer names, that's different. But your example is still not how to get there.

 

If 'layerInfo' is an array of layer objects:

for (var i = 0; i < layerInfo.length; i++) {
   layerInfo[i].selected = true;
}

If 'layerInfo' is an array of objects, but not actual layer objects, and these objects each have a propery 'name':

for (var i = 0; i < layerInfo.length; i++) {
   // Assuming 'docRef' is a reference to the active document.
   docRef.layers.getByName(layerInfo[i].name).selected = true;
}

Finally, if 'layerInfo' is simply an array of layer names (array of strings):

for (var i = 0; i < layerInfo.length; i++) {
   // Assuming 'docRef' is a reference to the active document.
   docRef.layers.getByName(layerInfo[i]).selected = true;
}

It might be helpful to see more code, then we can better understand what 'layerInfo' is precisely.

 

William Campbell

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 ,
Aug 17, 2022 Aug 17, 2022

Copy link to clipboard

Copied

Can you modify this to simply output a list of the name of every smart object in the current document?

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 ,
Aug 17, 2022 Aug 17, 2022

Copy link to clipboard

Copied

This will make an array "names" that can be used however you decide.

var names = walkLayers(app.activeDocument);

alert(names);

function walkLayers(o) {
    var a = [];
    for (var i = 0; i < o.layers.length; i++) {
        var layer = o.layers[i];
        if (layer instanceof LayerSet) {
            // Recurse (call self)
            a = a.concat(walkLayers(layer));
        } else if (layer.kind == LayerKind.SMARTOBJECT) {
            a.push(layer.name);
        }
    }
    return a;
}
William Campbell

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 ,
Aug 17, 2022 Aug 17, 2022

Copy link to clipboard

Copied

LATEST

Amazing, I've been struggling to modify the previous code but the recursive nature of this was causing me issues. How would you modify this to exclude repeating names? I tried adding a line to this but I can't get a.includes to work as an AND NOT expression:

 

} else if (layer.kind == LayerKind.SMARTOBJECT && !a.includes(layer.name)) {

 

 

This fails and I can't figure out why: ("a.includes is not a function")

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
Guide ,
Mar 24, 2020 Mar 24, 2020

Copy link to clipboard

Copied

I like getting the list of layers through AM - it's fast and it's one loop:

 

var AM = new ActionManager,
    layerSetArray = app.documents.length ? getAllLayers() : []

function getAllLayers() {
    var output = [],
        from = AM.getDocProperty('hasBackgroundLayer') ? 0 : 1,
        len = AM.getDocProperty('numberOfLayers')

    for (var i = from; i <= len; i++) {
        if (AM.getLayerProperty('layerSection', i) == 'layerSectionEnd') continue;

        var id = AM.getLayerProperty('layerID', i),
            title = AM.getLayerProperty('name', i)

        output.push({ id: id, name: title })
    }
    return output
}

function ActionManager() {

    this.getDocProperty = function (property) {
        property = s2t(property)
        var ref = new ActionReference()
        ref.putProperty(s2t("property"), property)
        ref.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"))
        return getDescValue(executeActionGet(ref), property)
    }

    this.getLayerProperty = function (property, index) {
        property = s2t(property)
        var ref = new ActionReference()
        ref.putProperty(s2t("property"), property)
        ref.putIndex(s2t("layer"), index)
        return getDescValue(executeActionGet(ref), property)
    }

    this.selectLayerById = function (id, addToSelection) {
        var desc = new ActionDescriptor()
        var ref = new ActionReference()
        ref.putIdentifier(s2t("layer"), id)
        desc.putReference(s2t("null"), ref)
        if (addToSelection) desc.putEnumerated(s2t("selectionModifier"), s2t("addToSelectionContinuous"), s2t("addToSelection"))
        executeAction(s2t("select"), desc, DialogModes.NO);
    }

    function getDescValue(desc, property) {

        switch (desc.getType(property)) {
            case DescValueType.OBJECTTYPE:
                return (desc.getObjectValue(property));
                break;
            case DescValueType.LISTTYPE:
                return desc.getList(property);
                break;
            case DescValueType.REFERENCETYPE:
                return desc.getReference(property);
                break;
            case DescValueType.BOOLEANTYPE:
                return desc.getBoolean(property);
                break;
            case DescValueType.STRINGTYPE:
                return desc.getString(property);
                break;
            case DescValueType.INTEGERTYPE:
                return desc.getInteger(property);
                break;
            case DescValueType.LARGEINTEGERTYPE:
                return desc.getLargeInteger(property);
                break;
            case DescValueType.DOUBLETYPE:
                return desc.getDouble(property);
                break;
            case DescValueType.ALIASTYPE:
                return desc.getPath(property);
                break;
            case DescValueType.CLASSTYPE:
                return desc.getClass(property);
                break;
            case DescValueType.UNITDOUBLE:
                return (desc.getUnitDoubleValue(property));
                break;
            case DescValueType.ENUMERATEDTYPE:
                return (t2s(desc.getEnumerationValue(property)));
                break;
            case DescValueType.RAWTYPE:
                var tempStr = desc.getData(property);
                var rawData = new Array();
                for (var tempi = 0; tempi < tempStr.length; tempi++) {
                    rawData[tempi] = tempStr.charCodeAt(tempi);
                }
                return rawData;
                break;
            default:
                break;
        };
    }

    function s2t(s) { return stringIDToTypeID(s) }
    function t2s(t) { return typeIDToStringID(t) }
}

 

As a rule, I get all the necessary attributes in this loop (getting the name and ID of the layer in the example below) and put them in an object, the array of which the function returns.
For further processing, i can also use AM code and access to the layer via his ID, or use the DOM through AM.selectLayerById (), for example: 

 

for (var i=0; i<layerSetArray.length; i++){
   AM.selectLayerById (layerSetArray[i].id)
   alert (app.activeDocument.activeLayer.name)
}

 

(I never use .getByName () since a document can contain several layers with the same name)

Maybe it will help you.

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
Advocate ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

@jazz-y  @willcampbell7 

 

sorry to return this late, many thanks for your input. This helps me understand to get cleaner and faster code.

 

Do any of you perhaps have an idea how i would get all layers in a layerset? My intended need is to get the first and last layer in a layerset but also the last and first in a document. That last one should not be that hard. Though i cant seem to figure out a way to get all layers in a layerset.

 

My initial idea is to traverse up in a layerset and if we bump into a layerset we can use hide others. Then i could do a select perhaps select all and get the first and last one.

 

use hide other so we can use select alluse hide other so we can use select alltraverse up until we meet a layersettraverse up until we meet a layerset

 

after tinkering a bit about it. Prehaps this is a solution, its the only method i can think of using traverse up properly. I would need to get all layers id or layers indexes, then i get the activeLayer index. Then, i think, i can use layer index to move up until up, each time i move up i check if the layer is a layerset, if so then hide all others. Then select all and get the first and last 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
Guide ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

I wrote a recursive function for similar tasks. It can be modified to handle only the group you need:

https://community.adobe.com/t5/photoshop/recursive-function-to-get-layers-with-nested-groups-in-acti...

 

Also in the latest versions of Photoshop added layer property 'parentLayerID', with which you can easily iterate over all the layers and select only the ones you need 

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
Advocate ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

I did notice layers have parent in the descriptions. Im not sure i saw parentId though. I simply run a code to see what is available. I super simple but i can find all kind of options with that

 

var items = []
for(i in docRef.activeLayer){
    items.push(i);
}
alert(items)

 

I need to check if lower versions also have parent, otherwise i wont use it. I need to be able to run the code also on lower version of PS.

 

Thanks for the links and feedback, ill check it out.

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 ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

Simple.

layerset.layers

See my earlier post Mar 2019 about how to traverse through layers/layersets. To simplify, first get the active document.

var doc = app.activeDocument;

Within 'doc' is an array of layers.

doc.layers

Each element of that array is a layer or layerset object.

You can test if a layerset by checking 'instanceof'.

if (doc.layers[0] instanceof LayerSet) {
 // doc.layers[0] is a layer set.
} else {
 // doc.layers[0] is a regular layer.
}

Understand, just as you can see in the layers palette, groups can be inside of groups (layer sets) inside of groups... on and on. These layer sets can be nested. My post over a year ago was about how to dig down into them.

If you already have a layer set selected (saved in a variable, for example), just go through that object's 'layers' property. That is an array of the layers or layer sets inside that particular layer set.

Does this make sense?

William Campbell

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
Advocate ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

@willcampbell7 

I did see the traverse method of nested layers. But that will do all layers righr?
My idea is to only do it within the current layerset. Thats why i thought of using move activeLayer up 1 at a time until we reach the layerSet. With the newer PS we have "parent" so we could perhaps target it at once. Though i guess i need more data of each layer to get this to work. I tried a piece of code i grabbed from scriptlistener to move activeLayer upwards in hierarchy, but that also needs to name. I think i need something to getLayerByIndex. 

 

I did found this in the _lastLogEntry script. Perhaps i can make use of 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
Enthusiast ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

I'm not sure what you're trying to do.

"Get layer by index" is easy. It's an array. So... object.layers[0] is index 0, object.layers[1] is index 1, etc.

Continuing to however many there are, which is object.layers.length. It's zero-indexed like all arrays so keep in mind the last element is length -1,

Do you have the object reference? See this link... very helpful...

https://www.indesignjs.de/extendscriptAPI/photoshop-latest/#about.html

Here is everything about 'layer' class...

https://www.indesignjs.de/extendscriptAPI/photoshop-latest/#Layer.html

If you're trying to get the parent, that is a property of the layer class. It's not an index, it's a reference to the actual object. So if what you're trying to do is find the parent layer set (or doc) of a layer, that would do it.

Maybe this reply will help, maybe not. You'll need to better explain your objective.

William Campbell

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 ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

I looked again at your earlier message. You say "Get first and last layer" of a layer set and of the doc, if I read that correctly.

First and last of a doc goes like this...

var doc = app.activeDocument;
var layerFirst = doc.layers[0];
var layerLast = doc.layers[doc.layers.length - 1];

This doesn't yet recognize if the first or last 'layer' is a layer set. Further tests are needed for that. When a layer set is discovered, the same logic applies. Let's say the first 'layer' is actually a layer set. Then...

// (assume var layerFirst set by code above)
var layerSetLayerFirst = layerFirst.layers[0];
var layerSetLayerLast = layerFirst.layers[layerFirst.layers.length - 1];
William Campbell

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
Advocate ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

Yes i was think of this in the main case when needed. The other case was to get first and last layer of a set. Im not sure when the parent property was added, so therefor i thought of moving up the layerstack until we reach a layerSet. Then we can the amount of artlayers in this set and get the first and last. 

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