Copy link to clipboard
Copied
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 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;
}
};
//////////////////
...
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
...
Copy link to clipboard
Copied
Do you want them all selected at once, or are you going to run a loop to process each layer individually?
Copy link to clipboard
Copied
I think both is just fine, i just want to select and use another script from kami to scale it down
Copy link to clipboard
Copied
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...");
}
Copy link to clipboard
Copied
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
Oh that was it do, thank you any way hope someone can help me :<
Copy link to clipboard
Copied
Oh that was it do, thank you any way hope someone can help me :<
By @GiangHg999
Your previous screenshot didn't show the selected layers highlighted.
It would help if you explicitly stated what you wanted to do once all the smart object layers in the target layer group were selected.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Ah, nested groups which also contain smart objects...
Once they are all selected, what next???
Copy link to clipboard
Copied
Yeah, next i want them to scale down individually but keep there axis using a script from "kami" but now i have to chose them one by one, sadly haha
Copy link to clipboard
Copied
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
};
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
I edited the code in the previous post.
Copy link to clipboard
Copied
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?
Copy link to clipboard
Copied
@GiangHg999 - Please mark the updated code from @c.pfaffenbichler as the correct answer.
Copy link to clipboard
Copied
Okay i will do it now, thank you
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
@c.pfaffenbichler Thank you for the recommendation, I will take a look right now