Copy link to clipboard
Copied
Sorry for the bad English in the title. What I mean is, for example I have 3 layers
top - Edit 2
mid - Edit
bot - Main layer with a name that makes sense
When I combine them together, the name of the combined layer becomes "Edit 2". Is it possible to make it the bottom one with a setting? Maybe with an action?
(just to be clear, it is not always 3 layers and the names are not "Edit, Edit2" etc.)
To you can automate that process with a Photoshop Script, Action can not use logic to see the Layer names that are being merged and rename the merged layer name to what you want based on the former layer names. Script can use the required logic to do what you wan to automate.
The previous script ran in approx. 6.7 seconds to run on a random set of 3 layers stacked.
The new code below took approx. 4 seconds for the same 3 layers.
It's still a less than ideal hack though... A better coder than me should be able to make this much faster. Can somebody upgrade my code?
EDIT: It appears that the best/common way is to temporarily group the selected layers, then do something with the group (rather than with a new doc as my second script uses).
/*
Select all requi
...
I think making it run in 2 steps is a bad idea because purpose of the script is making it work with single click, and seamless if possible.
And, it is indeed possible. With some external help as well, I managed to write this. It works without opening SO (which I didn't like), but it can be a bit slower with bigger files (very little tho). I personally prefer this.
/*
Create a new smart object with the bottom layer's name
Gökhan Şimşek - 7.5.21
v1.1
*/
#target photoshop
var myDoc = app.active
...
I modified the get selected layers code I posted to create the smart object layer, As the cods stands the Smart object layer name will be the bottom not the top name. However, there is code that is commented out. That code would make the layer name the list of merged layers.
app.activeDocument.suspendHistory('makeSmartObject','main()');
function main() {
try {
var selectedLayers = get_selected_layers_id();
var Names = (get_layer_by_id(selectedLayers[0]).name);
/*
var Names = ""
...
sTT = stringIDToTypeID;
(ref = new ActionReference()).putEnumerated
(sTT('layer'), sTT('ordinal'), sTT('targetEnum'));
(dsc = new ActionDescriptor()).putReference(sTT('null'), ref)
executeAction(sTT('linkSelectedLayers'), dsc)
with((actveDcmnt = activeDocument).activeLayer)
nme = linkedLayers.pop().name, merge()
actveDcmnt.activeLayer.name = nme
or:
(aD = activeDocument).suspendHistory('', ''), aHS = aD.activeHistoryState
sTT = stringIDToTypeID, dsc = new ActionDescriptor(), arr = ['back
...
I did not see the simplest way - to get the name of the 1st target layer and assign it after convert to SO.
function main() {
var s2t = stringIDToTypeID;
(tr = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
tr.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
(lr = new ActionReference).putProperty(s2t('property'), n = s2t('name'));
lr.putIdentifier(s2t('layer'), executeActionGet(tr).getList(p).getReference(0).getIdentifier(s2t('layerID')));
...
Copy link to clipboard
Copied
In the Layers panel, you can drag the layers to change the order, and you can relabel the layers.
Copy link to clipboard
Copied
So far I was renaming layers after combining them, but it takes a lot of time, so I thought maybe there is a way to change that setting.
Copy link to clipboard
Copied
Cmd + Option + Shift + E (Mac) merges the layers to one layer (keeping the individual layers).
Copy link to clipboard
Copied
Looks like I couldn't explain well : )
Normally, when combining 2 layers, combined layer's name becomes the top one.
Layer Top
Layer Bot
After combining this 2, the new layer's name becomes "Layer Top". I want it to become "Layer Bot". Is it possible?
Copy link to clipboard
Copied
To you can automate that process with a Photoshop Script, Action can not use logic to see the Layer names that are being merged and rename the merged layer name to what you want based on the former layer names. Script can use the required logic to do what you wan to automate.
Copy link to clipboard
Copied
How are you currently combing the two or more layers?
Have you looked at targeting the top layer and then using "merge down" – CMD/CTRL E as many times as required?
No need for a script, however, you could record an action to automate this command for 2, 3 or more "sets" of layers which will all retain the bottom name.
Copy link to clipboard
Copied
I am making them Smart File, would it still work?
Copy link to clipboard
Copied
No, that critical piece of info was not in your OP, I'm guessing that you need to retain the individual layers so you will then need a script.
Copy link to clipboard
Copied
I don't have time for "pretty" code with error checking and other nice things, however this script is functional. Simply select all required sequential/contiguous layers and then run the script:
/*
Select all required sequential/contiguous layers before executing this script
Selected Layers to SO Named After Bottom Layer.jsx
v1.1 - Stephen Marsh, 6th May 2021
*/
#target photoshop
// Convert the selected layers to an embedded Smart Object
executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
//app.runMenuItem(stringIDToTypeID('newPlacedLayer'));
// Open the SO (simple method for Photoshop compatible data)
executeAction(stringIDToTypeID("placedLayerEditContents"), undefined, DialogModes.NO);
//app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
// Select the back layer
app.activeDocument.activeLayer = app.activeDocument.layers[app.activeDocument.layers.length - 1];
// Capture the active layer name
var lyrName = app.activeDocument.activeLayer.name;
// Close SO doc without saving
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
// Rename the base document SO layer
app.activeDocument.activeLayer.name = lyrName;
Left: Original Layers Right: Final named SO layer from selected layers
Copy link to clipboard
Copied
Hey, sorry for not being clear first, and thank you for the script. It works without a problem.
I am just a bit curious, I write some AE scripts (at least I try to : ), and I am a bit surprised that you opened a smart object to copy name. Is it not possible to get the name without open it? So the script can run a bit more seamless. (I guess that was what you mean with the "pretty" code, right : )
Copy link to clipboard
Copied
Yes it's possible but I didn't have time for good code, just working code!
Copy link to clipboard
Copied
And it works indeed. Thank you!
Copy link to clipboard
Copied
Thank you, I still consider myself a beginner/hacker at scripting, so working through selected layers to target a layer in a certain position in the stack's selection is not easy for me. You may have missed the original code that I posted, this version has been simplified somewhat by removing a chunk of AM code for standard DOM code.
If I can figure out how to target a specific layer among selected layers, then yes, I agree it would be more logical and efficient to get the name from the selected layers than to get it from the SO. Small steps...
Copy link to clipboard
Copied
The previous script ran in approx. 6.7 seconds to run on a random set of 3 layers stacked.
The new code below took approx. 4 seconds for the same 3 layers.
It's still a less than ideal hack though... A better coder than me should be able to make this much faster. Can somebody upgrade my code?
EDIT: It appears that the best/common way is to temporarily group the selected layers, then do something with the group (rather than with a new doc as my second script uses).
/*
Select all required contiguous layers before executing this script
Selected Layers to SO Named After Bottom Layer.jsx
v1.2 - Stephen Marsh, 6th May 2021
*/
#target photoshop
// Dupe selected layers to temp doc, yes it's hack!
tempDoc("", 5);
// Select the back layer
app.activeDocument.activeLayer = app.activeDocument.layers[app.activeDocument.layers.length - 1];
// Capture the active layer name
var lyrName = app.activeDocument.activeLayer.name;
// Close temp doc without saving
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
// Convert the selected layers to an embedded Smart Object
executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
//app.runMenuItem(stringIDToTypeID('newPlacedLayer'));
// Rename the base document SO layer
app.activeDocument.activeLayer.name = lyrName;
function tempDoc(name2, version) {
var c2t = function (s) {
return app.charIDToTypeID(s);
}
var s2t = function (s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putClass(s2t("document"));
descriptor.putReference(c2t("null"), reference);
descriptor.putString(s2t("name"), "", "TempLayerCountDoc", name2);
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(s2t("using"), reference2);
descriptor.putInteger(s2t("version"), version);
executeAction(s2t("make"), descriptor, DialogModes.NO);
}
Copy link to clipboard
Copied
It is surprising that something like that is not possible
var Name = ...activeLayer(s)[..lenght-1]. I mean, they should've thought that there can be more than one active layer at once, right?
Anyway, how about another approach? We will basically create a for loop that checks every layer (from top to bottom) whether if it is an active layer or not. If it is, var Name will be that layer's name. Last layer will overwrite the older ones, so it should work. (my only concern is it can be slow, but I don't think it will. I think it will be faster actually)
I was going to try it myself, but I couldn't find a good documentation that I can understand easily.
edit. This almost works, only problem is "instanceof active" part. I created it with my AE knowledge so most likely it doesn't work on here.
edit 2. Well, looks like it is not the only problem. For doesn't work when the layers inside a folder. It counts the whole folder as a one layer. Anyway, I don't know how to do it programming-wise, but I think you understand what I am trying to do.
#target photoshop
var layers = app.activeDocument.layers;
var active = app.activeDocument.activeLayer;
for(i=0;i<layers.length;i++){
if(layers[i] instanceof active){
var lyrName = layers[i].name;
}
}
// Convert the selected layers to an embedded Smart Object
executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
//app.runMenuItem(stringIDToTypeID('newPlacedLayer'));
// Rename the base document SO layer
app.activeDocument.activeLayer.name = lyrName;
Copy link to clipboard
Copied
In Photoshop you can target more that one layer and a script, a plug-in can process these targeted layers. However, Photoshop does not have parallel Processing Support where you cans process layer in parallel using multiple processor support. Most of layer processing is sequential result of steps are use in the next step and the layer stack changes layers are deleted, added and changed. If you target two layers and merge them you effectively delete those two layers and create a new merged layer which will be Photoshop Current active layer. You can have a list open document and lists of layers and lists of targeted layers and each opened document can have an active layer. However, Photoshop is not a Parallel processor there is only a current Active document and that Document may have an current active layer.
So it will be easy to write as script to do what you want. A simple merge two layer script. Lets look at how Merge Down works. It basically that is what you want to do but you want to name the merged layer differently. In the Following Screen capture You will see the merge down blended layer ID 3 Green into layer ID 2 Red using layer ID 3 normal blending mode. Then deleted layer ID 3 Green leaving Layer ID 2 Red in the Layer stack. So you could Target the two layers and run a Photoshop merge layers script that would look at the two targeted Layers manes the merge the layers and rename the active layer using the two original layer manes. Or you could just target layer green like you did before using Ctrl+E merge down. Then you run your MergeDown Photoshop script that looks at the Active Layer's name before it does the Merge Down. Then after the merge down the script add a prefix to the active layer's current name The Original Active Layer name and so the layer names are merged as well.
Copy link to clipboard
Copied
Is it not possible to check a layer's activeness?
Copy link to clipboard
Copied
There is or there is not an active document active layer. So it is very easy to test if a layer is the active layer or make set a layer to be the active layer or get the active layer. There is only one active layer possible in a document app.activeDocument.activeLayer
try {alert("This document " + app.activeDocument.name + " active layer names is " + app.activeDocument.activeLayer.name);}
catch(e) {alert("There is no Active Layer");}
Also Layer names name may not be unique Photoshop process document using unique layer IDs
alert(get_selected_layers_id().toSource())
var selectedLayers = get_selected_layers_id();
var Names = "";
for ( var i = 0; i < selectedLayers.length; i++ ) {
thisLayer = get_layer_by_id(selectedLayers[i]);
var Names = Names + thisLayer.name + "\n";
}
alert(Names);
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
Thank you for your explanations!
Copy link to clipboard
Copied
Yet another approach, this time select the bottom layer, then run the script. Enter into the prompt the number of additional layers to select above the bottom active layer.
This version runs in ~1 second, much better than my previous 7 and 4 second scripts.
There is no error checking to ensure that nothing bad happens if you enter a number longer than the length of available layers.
/*
Is it possible to make the name of combined layers the bottom one's?
https://community.adobe.com/t5/photoshop/is-it-possible-to-make-the-name-of-combined-layers-the-bottom-one-s/td-p/12016052
Target the bottom layer, then run the script to select all required sequential layers
Selected Layers to SO Named After Bottom Layer.jsx
v1.3 - Stephen Marsh, 7th May 2021
*/
#target photoshop
function main() {
// Capture the active layer name
var lyrName = app.activeDocument.activeLayer.name;
// Enforce integer input
var origInput;
while (isNaN(origInput = prompt("Enter number of additional layers to select:", "1")));
var inputToInteger = parseInt(origInput);
// Loop forward layer selection N times
for (i = 0; i < inputToInteger; i++) {
selectForwardLayer(false);
function selectForwardLayer(makeVisible) {
var c2t = function (s) {
return app.charIDToTypeID(s);
}
var s2t = function (s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var list = new ActionList();
var reference = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("forwardEnum"));
descriptor.putReference(c2t("null"), reference);
descriptor.putEnumerated(s2t("selectionModifier"), s2t("selectionModifierType"), s2t("addToSelection"));
descriptor.putBoolean(s2t("makeVisible"), makeVisible);
list.putInteger(2);
list.putInteger(3);
descriptor.putList(s2t("layerID"), list);
executeAction(s2t("select"), descriptor, DialogModes.NO);
}
}
// Convert the selected layers to an embedded Smart Object
executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
//app.runMenuItem(stringIDToTypeID('newPlacedLayer'));
// Rename the SO layer
app.activeDocument.activeLayer.name = lyrName;
}
app.activeDocument.suspendHistory("Run script", "main()");
Copy link to clipboard
Copied
I think making it run in 2 steps is a bad idea because purpose of the script is making it work with single click, and seamless if possible.
And, it is indeed possible. With some external help as well, I managed to write this. It works without opening SO (which I didn't like), but it can be a bit slower with bigger files (very little tho). I personally prefer this.
/*
Create a new smart object with the bottom layer's name
Gökhan Şimşek - 7.5.21
v1.1
*/
#target photoshop
var myDoc = app.activeDocument.activeLayer.parent;
var myId = app.activeDocument.activeLayer.id;
var mainArray;
var beforeArray;
var afterArray;
var indexNum;
var diff;
var newName;
// Array function that creates array from the all layers 1.1
function createArray(doc){
var myLength= doc.layers.length;
for(i=0; i<myLength; i++){
mainArray.push(doc.layers[i].name);
if(doc.layers[i].id == myId){
indexNum = i;
}
}
return mainArray;
}
function main(){
//First Array
mainArray= [];
beforeArray = createArray(myDoc);
// Convert the selected layers to an embedded Smart Object
executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
//New Array
mainArray= [];
afterArray = createArray(myDoc);
//Length Difference
diff = beforeArray.length - afterArray.length;
// Set the new name - 1.1
newName= beforeArray[indexNum+diff];
// Rename the Smart Object
app.activeDocument.activeLayer.name = newName;
}
//To undo with single move
app.activeDocument.suspendHistory ("Smart Obj Script", "main()");
I made it undo friendly as well. I personally satisfied : D Thank you for all your help, it helped a lot to create this version : )
Copy link to clipboard
Copied
Here is the mergeDown.jsx I wrote you could script that would also merge the layer names as well as the layers contents. Just target the top layer an press the shortcut you set for the script you could change Ctrl+E to be the Scripts shortcut. You can coment out the alert in the script if you want to.
app.activeDocument.suspendHistory('mergeDown','main()');
function main() {
try {
topLayer = app.activeDocument.activeLayer.name;
mergeDown();
app.activeDocument.activeLayer.name = topLayer + " - " + app.activeDocument.activeLayer.name;
}
catch(e) {alert("Nothing Merged");}
}
function mergeDown() {
var descriptor = new ActionDescriptor();
executeAction( stringIDToTypeID( "mergeLayersNew" ), descriptor, DialogModes.NO );
}
Here I used the shortcut twice. You can also backout the script with an undo,
Copy link to clipboard
Copied
Thank you but I didn't want to merge, I wanted to use smart object. I already created something anyway, so you don't need to create something else : )
Copy link to clipboard
Copied
You could do the same thing with convert to smart object. You could rename the smart object layer to the collection of layer names.