Skip to main content
Known Participant
February 4, 2024
Answered

How can i select all smart object in selected group (using Script)

  • February 4, 2024
  • 3 replies
  • 3239 views

Hello
I am currently facing a situation where I have multiple groups containing multiple smart objects, adjustment layers, type layers, and more. I am in need of a script that can select all smart objects within the group for which I'm currently selected. I have searched for a solution and come across some options, but none help my problem. I only have basic knowledge of JavaScript and also try to use Chat-GPT but it also doesn't work.
If anyone knows please give me a solution. thank you very much

This topic has been closed for replies.
Correct answer Davide_Barranca12040269
quote

Thank you very much! It works so well now. Can I ask you one more question? Where can I learn to code like this? Could you please recommend any websites or courses for beginners to learn JavaScript?


By @GiangHg999

If you are relatively new to Photoshop Scripting you may want to avoid ESTK Scripting, as it is unclear how long it will be supported, and focus on UXP Scripting right away.

@DBarranca has published a book on the issue; I haven’t purchased it yet, but I suspect it may make for easier reading than the documentation Adobe itself offers. 

https://www.ps-scripting.com/professional-ps-uxp.html 


Thanks for the mention, @c.pfaffenbichler 

The UXP code (write it in a `.psjs` file and call it via File > Scripts > Browse...) would be:

const { app, constants } = require("photoshop");

const processLayer = (layer) => {
  if (layer.kind === constants.LayerKind.GROUP && layer.layers) {
    for (let l of layer.layers) {
      processLayer(l);
    }
  } else if (layer.kind === constants.LayerKind.SMARTOBJECT) {
    layer.selected = true;
  }
};

const startLayer = app.activeDocument?.activeLayers[0];
if (startLayer) {
  startLayer.selected = false;
  processLayer(startLayer);
}

Hope this helps!

 

 

3 replies

c.pfaffenbichler
Community Expert
Community Expert
February 5, 2024

This should work for SOs in a selected Group, but not for those in a Group in the Group. 

Edited the code to include SO in Group In Group …

 

 

// select smart objects in selected group;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var thisLayerId = getLayerIdAndBounds ();
var theSOs = collectSmartObjectsInFolder(thisLayerId[1]);
var theAdd = false;
for (var m = 0; m < theSOs.length; m++) {
    selectLayerByID(theSOs[m][1], theAdd);
    theAdd = true;
}
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjectsInFolder (thisParentID) {
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theParentID = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
if (layerDesc.hasKey(stringIDToTypeID('smartObject'))) {
if (theParentID == thisParentID) {theLayers.push([theName, theID, theParentID])}
else {
nextParentID = getLayerParentId(theParentID);
while (nextParentID != -1) {
    if (thisParentID == nextParentID) {theLayers.push([theName, theID, theParentID])};
    nextParentID = getLayerParentId(nextParentID);
};
};
};
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){ 
add = undefined ? add = false:add 
var ref = new ActionReference();
    ref.putIdentifier(charIDToTypeID("Lyr "), id);
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID("null"), ref );
       if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
      desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
   try{
    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message); 
}
};
////// get active layer’s id //////
function getLayerIdAndBounds () {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
var theWidth = theseBounds[2]-theseBounds[0];
var theHeight = theseBounds[3]-theseBounds[1];
return [theName, theID, theseBounds, theWidth, theHeight]
};
////// get active layer’s id //////
function getLayerParentId (theLayerId) {
var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID("Lyr "), theLayerId); 
var layerDesc = executeActionGet(ref);
var theParentID = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
return theParentID
};

 

 

 

Known Participant
February 5, 2024

I used your code and it worked really well. Just like you said, it seems like the code is unable to choose when I have multiple subgroups within a group, which i am currently facing. Still, providing me with this code as it has been a life saver for me. Thank you a lot though

Stephen Marsh
Community Expert
Community Expert
February 5, 2024

Thank you very much! It works so well now. Can I ask you one more question? Where can I learn to code like this? Could you please recommend any websites or courses for beginners to learn JavaScript?


@GiangHg999 - Please mark the updated code from @c.pfaffenbichler as the correct answer.

Stephen Marsh
Community Expert
Community Expert
February 5, 2024

@GiangHg999 

 

The question from @Chuck Uebele has a huge bearing on the code!

 

Selecting all the smart object layers is much harder for me than looping over them. Here is an example of a loop:

 

#target photoshop

// Check if the active layer is a layer group
if (app.activeDocument.activeLayer.typename == "LayerSet") {

    // Set the layers variable to the layers contained within the selected layer group
    var theLayers = app.activeDocument.activeLayer.layers;

    // Forward loop over the layers in the selected layer group
    for (var i = 0; i < theLayers.length; i++) {
        // Check if the top-level layer is a smart object
        if (theLayers[i].typename == "ArtLayer") {
            if (theLayers[i].kind == LayerKind.SMARTOBJECT) {
                alert("Do something with layer:" + "\n" + theLayers[i].name);
            }
        }
    }
} else {
    alert("Select a layer group and re-run the script...");
}

 

 

Known Participant
February 5, 2024

i dont really understand the question too much but i have an example here. In this image below, i want to chose layer 1, 2 ,3... all at once or each layer individually just find . I try to run your code but it seem just said "do something with layer 1 2 3"

Stephen Marsh
Community Expert
Community Expert
February 5, 2024

The "Do something with..." is just a placeholder to swap with your code to do something for the single selected smart object layer, before it moves on to the next smart object layer in the for loop. The for loop processes one layer at a time.

 

Depending on what you wish to do, it may be OK to work one smart object layer at a time in the for loop.

 

If you need all layers selected at the same time, before you add code to "do something" – then I hope someone else can help as I find this hard to do as it generally uses Action Manager code.

Chuck Uebele
Community Expert
Community Expert
February 4, 2024

Do you want them all selected at once, or are you going to run a loop to process each layer individually? 

Known Participant
February 5, 2024

I think both is just fine, i just want to select and use another script from kami to scale it down