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

Getting the children of a selected group

Explorer ,
Dec 30, 2016 Dec 30, 2016

Copy link to clipboard

Copied

I'm still trying to get the hang of Action Manager code, but I keep hitting a wall. I'm trying to figure out how I can get all of the children of the selected group, but I can't find a way to do this.

- How can I retrieve all elements below a group (LayerSet) through AM code?

- Is it possible to retrieve the parent of a specific layer?

- Is it possible to collapse/expand groups with AM code?

How do you guys attack these kinds of challenges? I have googled and searched github for these questions, but I haven't found anything of help. I feel like there's just a few of you that knows AM code, how did you plow your way into learning AM coding? I mean, the basic operations that can be recorded by the listener is doable even for me, but approaching challenges like the one's I have now, I don't even know where to start?

TOPICS
Actions and scripting

Views

4.9K

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

Participant , Dec 30, 2016 Dec 30, 2016

Hey simene49649793​, these 2 functions should get you half way there.

getDocumentInfo() - Retrieves the document information. Super cool function that I found in one of these forums. This is similar to Generator's getDocumentInfo. It has some optional params to retrieve more specific data.

This AM function will return the document object as a string, because ExtendScript is very limited unfortunately. You will have to parse it using a JSON polyfill. I use this one: https://github.com/JavierAroche/descriptor-info/blob/master/example/helpers/JSON.jsx

...

Votes

Translate

Translate
Adobe
Community Expert ,
Dec 30, 2016 Dec 30, 2016

Copy link to clipboard

Copied

Hi simene49649793,

there is a script study years ago written by Michael L. Hale (RIP)

This should help you out:

// written by Michael L.Hale

// selektiert alle Ebenen in der aktiven Gruppe

// assumes the group you want to select the layer in is the activeLayer

var groupStartIdx = getActiveLayerIndex();

app.activeDocument.activeLayer = app.activeDocument.activeLayer.layers[app.activeDocument.activeLayer.layers.length-1];

var groupEndIdx = getActiveLayerIndex();

for(l=groupEndIdx;l<groupStartIdx;l++){

    addToLayerSelectionByIndex( l );

}

  

function addToLayerSelectionByIndex( idx ) {

    var desc = new ActionDescriptor();

        var ref = new ActionReference();

        ref.putIndex( charIDToTypeID('Lyr '), idx );

    desc.putReference( charIDToTypeID('null'), ref );

    desc.putEnumerated( stringIDToTypeID('selectionModifier'), stringIDToTypeID('selectionModifierType'), stringIDToTypeID('addToSelection') );

    desc.putBoolean( charIDToTypeID('MkVs'), false );

    executeAction( charIDToTypeID('slct'), desc, DialogModes.NO );

};

function getActiveLayerIndex() {

    var ref = new ActionReference();

    ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));

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

    var res = executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )) - Number( hasBackground() );

    return res;

};

function hasBackground(){

    var res = undefined;

    try{

        var ref = new ActionReference();

        ref.putProperty( 1349677170 , 1315774496);

        ref.putIndex( 1283027488, 0 );

        executeActionGet(ref).getString(1315774496 );;

        res = true;

    }catch(e){ res = false}

    return res;

};

Have fun

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
Participant ,
Dec 30, 2016 Dec 30, 2016

Copy link to clipboard

Copied

Hey simene49649793​, these 2 functions should get you half way there.

getDocumentInfo() - Retrieves the document information. Super cool function that I found in one of these forums. This is similar to Generator's getDocumentInfo. It has some optional params to retrieve more specific data.

This AM function will return the document object as a string, because ExtendScript is very limited unfortunately. You will have to parse it using a JSON polyfill. I use this one: https://github.com/JavierAroche/descriptor-info/blob/master/example/helpers/JSON.jsx

You can then grab the document.layers key which includes all the layers in the document.

function getDocumentInfo() {

  // Build Action Descriptor

  var ref = new ActionReference();

  var desc = new ActionDescriptor();

  var psJSON = stringIDToTypeID("json");

  ref.putProperty(charIDToTypeID('Prpr'), psJSON);

  ref.putEnumerated(stringIDToTypeID("document"), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));

  desc.putReference(charIDToTypeID('null'), ref);

// desc.putBoolean(stringIDToTypeID("expandSmartObjects"), true);

// desc.putBoolean(stringIDToTypeID("selectedLayers"), true);

// desc.putBoolean(stringIDToTypeID("getTextStyles"), true);

// desc.putBoolean(stringIDToTypeID("getFullTextStyles"), true);

// desc.putBoolean(stringIDToTypeID("getDefaultLayerFX"), true);

// desc.putBoolean(stringIDToTypeID("getPathData"), true);

  return executeAction(charIDToTypeID( "getd" ), desc, DialogModes.NO).getString(psJSON);

}

getSelectedLayerIDs() - Retrieves the selected layer IDs as an array.

function getSelectedLayerIDs() {

  var selectedLayerIDs = [];

  // Filter selected layers

  var docRef = new ActionReference();

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

  var docDesc = executeActionGet(docRef);

  // Get target layer ids

  if( docDesc.hasKey(stringIDToTypeID('targetLayersIDs'))) {

  targetLayersIDsDesc = docDesc.getList( stringIDToTypeID('targetLayersIDs'));

  for(var ii = 0; ii < targetLayersIDsDesc.count; ii++) {

  selectedLayerIDs.push(Number(targetLayersIDsDesc.getReference( ii ).getIdentifier()));

  }

  }

  return selectedLayerIDs;

}

Once you have the document layers as an object and the selected layer IDs, you can simply iterate through all the layers (recursive function) until you find the one you're looking for. If you're only targeting one group layer, it will be a lot easier.

- Is it possible to retrieve the parent of a specific layer?

This one is tricky, but if you're comfortable with recursive functions, you should be able to get the parent layer of the any layer in a document.

collapseAllGroups() - Collapses all document groups.

function collapseAllGroups() {

    try {

        var idcollapseAllGroupsEvent = stringIDToTypeID( "collapseAllGroupsEvent" );

        var desc13 = new ActionDescriptor();

        return executeAction( idcollapseAllGroupsEvent, desc13, DialogModes.NO );

    } catch(err) {}

}

How do you guys attack these kinds of challenges? I have googled and searched github for these questions, but I haven't found anything of help. I feel like there's just a few of you that knows AM code, how did you plow your way into learning AM coding? I mean, the basic operations that can be recorded by the listener is doable even for me, but approaching challenges like the one's I have now, I don't even know where to start?

It takes a lot of practice, patience, googling and spending lots of hours in forums

DBarranca​ is authoring a Photoshop Scripting book. That will be great for people trying to learn all of this.

http://www.davidebarranca.com/2016/10/new-course-photoshop-scripting/

Some resources that have helped me a lot:

I made this little module to better understand Action Descriptors.

https://github.com/JavierAroche/descriptor-info

Hope it helps!

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 ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

The code is here to get layerset layers...

https://www.ps-scripts.com/viewtopic.php?f=68&t=11268

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 ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

If want select all nested layers in one selected group then you can simply

1) create group - Ctrl + G

2) remove group - Ctrl + Shift + G

3) now you have all nested layers selected (recursively)

4) get selected layers indexes/ids

This should have good performance for complex nested layers.

Parent of specific layer

1) select your layer by index/id

2) app.activeDocument.activeLayer.parent.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
Community Expert ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

Hi Jarda Bereza,

did you try the performance of the code in the last three posts? Do you have problems with the performance of it?

Perhaps you can show a working code snippet for making a time comparison? I like to learn.

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 ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

pixxxel schubser  napsal(a):

Perhaps you can show a working code snippet for making a time comparison? I like to learn.

I did some time measurement.

Document has 1634 layers, 287 groups and 11136px × 6740px

1) 64 layers selected in 5 groups - 1402ms

2) 141 layers selected in 32 groups - 291ms

(ExtendScript Toolkit his buil-in time measurement features.)

Limitations:

- you can't group artboards

- you can create only 10 nested groups

If you select one layer by ID/index it should be +- 20ms per layer

DOM recursion is slow. With ActionManager you can read layers, they don't have tree structure but it is linear structure. So it is very fast, but you probably need select layers one by one. You can select layers range, but I am not sure how much reliably it is.

Code here: http://pastebin.com/dgUqSb1n

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
Contributor ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

I've aproach these problems into my toggle open close groups script, there is also a function that can get the children and one that can get the parent with AM. You will find them in this collection:

GitHub - cbuliarca/BCM_exetndShortcutsUI: Collection of Photoshop scripts accesed with an UI, main f...

just go to the BCM_ToolsUi/ extras/scripts and here the file with all the necessay functions  is mb_utils.jsxinc

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 ,
Dec 31, 2016 Dec 31, 2016

Copy link to clipboard

Copied

Great.

The TO simene49649793​ ask: "It is possible? How can I do this?"

And we start a very usefully discussion about: What is the first class way to do this?

I will also take a look next year on the several links. Thx for this.

I wish you all the best and a Happy New Year 2017

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 ,
Jan 01, 2017 Jan 01, 2017

Copy link to clipboard

Copied

pixxxel schubser: That was a clever way to do it! I've been able to retrieve all children of selected groups using this method, works great I would wish it was possible to retrieve them without making selections, but if I can figure out how to collapse groups afterwards it won't matter Also, using this method I think it should be easy to find the parent layer also by just decreasing the layer index until a hit a LayerSet, I'll try that later. Thank you

JavierAroche: That getDocumentInfo was awesome I couldn't get collapseAllGroups to work though, it doesn't seem to do anything Thank you for all of the resources

Thank you everyone, this is extremely interesting and helpful! I'm still looking for a way to collapse/expand LayerSets, so if anyone have any ideas on how to do this I'd be really interested to hear how it can be done Happy new year guys, and thanks again

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
Contributor ,
Jan 01, 2017 Jan 01, 2017

Copy link to clipboard

Copied

You can actually use AM to get the childrens of a layerset, without selecting each layer, that's the beauty of AM. I'm using it to get the chlid layers like this: I'm starting on the parent layerset and set a variable x to 1, then with a loop I go backwards by using the putIndex method for the layer class, with index set to i--, and everytime I get an LayerSectionStart, I'm incrementing the x var, and if I get an LayerSectionEnd I'm decrementing x, when I get x to be equal to 0, I stop the loop, and this way I know that all the layers gathered in an array while the loop run, are the child layers. I usually gather the id's of the layers, the idx and the names...this way I can use another function to select all the layers by Id.

As for the closing of a layer group I've solved it by selecting all the child layers, unparent them and group them into another set. And set the properties of the second set similar to the first group...Expanding the layer set it's easy you just have to select one child of that layer set. please take a look of the script I've mention to see how I've done it.

Thank you. And Happy New Year to you all.

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
Participant ,
Jan 02, 2017 Jan 02, 2017

Copy link to clipboard

Copied

LATEST

I couldn't get collapseAllGroups to work though, it doesn't seem to do anything

simene49649793 - That's weird, maybe the "collapseAllGroupsEvent" isn't available in your version of Photoshop? I just tested that same function and it seems to be working on Photoshop CC 2014.2.2 and CC 2015.0.0.

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