Copy link to clipboard
Copied
So I spent the evening researching a way to expand/contract a layer group.. normally we have to click on the small triangle icon that appears before the layer name in the layers panel to expand the group, and click it again to fold it all up. So far, I've found information stating that it can't be done via scripting...
I thought up one way to do it, and that would be to search a layer by name (using a different script), and make sure that the layer name being searched for is inside of a contracted group.. and when that layer name is found and selected, it will unfold the layer group and show select the layer. It's quite a runaround though. Is there a more efficient way to do it with a script?
Copy link to clipboard
Copied
Using script code found here I put some together that give me the functions needed. I tested creating actions and assigned F keys during testing for fast access.
Open Target
// The main function
//@include "LayerSetSupport.jsx"
if (activeDocument.activeLayer.typename == 'LayerSet') {app.activeDocument.suspendHistory('openGroup','openGroup(activeDocument.activeLayer)');}
Close Target
// The main function
//@include "LayerSetSupport.jsx"
if (activeDocument.activeLayer.typename == 'LayerSet') {app.activeDocument.suspendHistory('closeGroup','closeGroup(activeDocument.activeLayer)');}
Open All Layer Groups
// The main function
//@include "LayerSetSupport.jsx"
openAllLayerSets( app.activeDocument );
Close All Layer Groups
// The main function
//@include "LayerSetSupport.jsx"
app.activeDocument.suspendHistory('closeAllGroup','closeAllLayerSets( app.activeDocument )');
LaySetSupport
//For code readability
function cTID(s){return charIDToTypeID(s)}
function sTID(s){return stringIDToTypeID(s)}
// =============================
function openAllLayerSets( parent ){
for(var setIndex=0;setIndex<parent.layerSets.length;setIndex++){
app.activeDocument.activeLayer = parent.layerSets[setIndex].layers[0];
openAllLayerSets( parent.layerSets[setIndex]);
}
};
function closeAllLayerSets(ref) {
var layers = ref.layers;
var len = layers.length;
for ( var i = 0; i < len; i ++) {
var layer = layers;
if (layer.typename == 'LayerSet') {closeGroup(layer); var layer = layers; closeAllLayerSets(layer);};
}
}
function openGroup(layerSet) {
var m_activeLayer = activeDocument.activeLayer;
var m_Layer_Dummy01 = layerSet.artLayers.add();
var m_Layer_Dummy02 = layerSet.artLayers.add();
layerSet.layers[1].name = layerSet.layers[1].name;
m_Layer_Dummy01.remove();
m_Layer_Dummy02.remove();
activeDocument.activeLayer = m_activeLayer;
}
function closeGroup(layerSet) {
var m_Name = layerSet.name;
var m_Opacity = layerSet.opacity;
var m_BlendMode = layerSet.blendMode;
var m_LinkedLayers = layerSet.linkedLayers;
var m_bHasMask = hasLayerMask();
if(m_bHasMask) loadSelectionOfMask();
if(layerSet.layers.length <= 1) {
addLayer();
var m_Tmp = activeDocument.activeLayer;
m_Tmp.name = "dummy - feel free to remove me";
activeDocument.activeLayer = layerSet;
ungroup();
addToSelection("dummy - feel free to remove me");
groupSelected(m_Name);
} else {
activeDocument.activeLayer = layerSet;
ungroup();
groupSelected(m_Name);
}
var m_Closed = activeDocument.activeLayer;
m_Closed.opacity = m_Opacity;
m_Closed.blendMode = m_BlendMode;
for(x in m_LinkedLayers) {
if(m_LinkedLayers
.typename == "LayerSet") activeDocument.activeLayer.link(m_LinkedLayers
); }
if(m_bHasMask) maskFromSelection();
return m_Closed;
}
function ungroup() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Lyr " ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( sTID( "ungroupLayersEvent" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function addLayer() {
var m_ActiveLayer = activeDocument.activeLayer;
var m_NewLayer = activeDocument.artLayers.add();
m_NewLayer.move(m_ActiveLayer, ElementPlacement.PLACEBEFORE);
return m_NewLayer;
}
function hasLayerMask() {
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( sTID( "layer" ), cTID( "Ordn" ), cTID( "Trgt" ));
var m_Dsc01= executeActionGet( m_Ref01 );
return m_Dsc01.hasKey(cTID('Usrs'));
}
function activateLayerMask() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Chnl" ), cTID( "Msk " ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( cTID( "slct" ), m_Dsc01, DialogModes.NO );
} catch(e) {
var m_TmpAlpha = new TemporaryAlpha();
maskFromSelection();
activateLayerMask();
m_TmpAlpha.consume();
}
}
function deleteMask(makeSelection) {
if(makeSelection) {
loadSelectionOfMask();
}
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( cTID( "Dlt " ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function selectLayerMask() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated(cTID("Chnl"), cTID("Chnl"), cTID("Msk "));
m_Dsc01.putReference(cTID("null"), m_Ref01);
m_Dsc01.putBoolean(cTID("MkVs"), false );
try {
executeAction(cTID("slct"), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function loadSelectionOfMask() {
selectLayerMask();
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putProperty( cTID( "Chnl" ), cTID( "fsel" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
var m_Ref02 = new ActionReference();
m_Ref02.putEnumerated( cTID( "Chnl" ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "T " ), m_Ref02 );
try {
executeAction( cTID( "setd" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function maskFromSelection() {
if(!hasLayerMask()) {
var m_Dsc01 = new ActionDescriptor();
m_Dsc01.putClass( cTID( "Nw " ), cTID( "Chnl" ) );
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Chnl" ), cTID( "Msk " ) );
m_Dsc01.putReference( cTID( "At " ), m_Ref01 );
m_Dsc01.putEnumerated( cTID( "Usng" ), cTID( "UsrM" ), cTID( "RvlS" ) );
try {
executeAction( cTID( "Mk " ), m_Dsc01, DialogModes.NO );
} catch(e) {
activeDocument.selection.selectAll();
maskFromSelection();
}
} else {
if(confirm("Delete existing mask?", true, "Warning")) {
activateLayerMask();
deleteMask();
}
}
}
function groupSelected(name) {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putClass( sTID( "layerSection" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
var m_Ref02 = new ActionReference();
m_Ref02.putEnumerated( cTID( "Lyr " ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "From" ), m_Ref02 );
var m_Dsc02 = new ActionDescriptor();
m_Dsc02.putString( cTID( "Nm " ), name);
m_Dsc01.putObject( cTID( "Usng" ), sTID( "layerSection" ), m_Dsc02 );
executeAction( cTID( "Mk " ), m_Dsc01, DialogModes.NO );
return activeDocument.activeLayer;
}
function addToSelection(layerName) {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putName( cTID( "Lyr " ), layerName );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
m_Dsc01.putEnumerated( sTID( "selectionModifier" ), sTID( "selectionModifierType" ), sTID( "addToSelection" ) );
m_Dsc01.putBoolean( cTID( "MkVs" ), false );
try {
executeAction( cTID( "slct" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function TemporaryAlpha() {
activeDocument.selection.store((this.alpha = activeDocument.channels.add()));
activeDocument.selection.deselect();
this.consume = function() {
activeDocument.selection.load(this.alpha);
this.alpha.remove();
}
}
// The main function
//openGroup(activeDocument.activeLayer);
//openAllLayerSets( app.activeDocument );
//closeGroup(activeDocument.activeLayer);
//closeAllLayerSets( app.activeDocument );
Message was edited by: JJMack
Copy link to clipboard
Copied
cbuliarca - works great now!! definitely a script that will stay in my collection and I'll be using it every day - the nice thing is that it has a 'search layer' function just like CS6.. (it's actually a little better than CS6 because it auto-completes your layer name for you when you start typing - very nice)
JJmack - these are perfect - the only thing with 'close target' and 'close all layer groups' is that when it closes the layer group(s), it also deletes the color coding of the layer (for example if the layer was set to blue, it resets it back to nothing when closing the group) - I always need to color code my layers or else I'd lose my mind (if I haven't already lol)
Copy link to clipboard
Copied
That is one reason I don't think there is a good way to close a layerSet. To be clear the code posted does not close the set. It mimics closing by making a new layerSet and moving layers.
It should be possible for the script to maintain the set's layer color by getting the current set's color so it can set the color of the new set.. But there are some settings like blend-if settings that can't be accessed by a script so it can't copy to the new set.
Copy link to clipboard
Copied
I agree the script uses a sledge hammer and flying chips may loose some things. Script is better then actions for actions can not open or close layer sets themselves. You can use a script an action to open layer sets, but Closeing a layer set is an other story. In an action when you create a group from selected layer the layer set is created closed. That is more or less what these script do. They save some information about a layer set ungroup the layer set then select all that was in the group and recreates the best it can the group. I see problem with layer set with layer mask for example hide all layer mask get changed to reveal all mask and vector mask are lost.... My testing was poor in fact the close all layerset routine messes up all layerset with layer mask Layers mask are changed and if you run open all layerset and close all layersets a couple of time all layer set layer mask will be lost.
I have address thelayerset layer mask problem some, Vector mask on layer sets are not supported and will be lost. Hide all layer mask still get invetted. However nornal raster layter mask on layer groups are retained.
LayerSetSupport.jsx
//For code readability
function cTID(s){return charIDToTypeID(s)}
function sTID(s){return stringIDToTypeID(s)}
// =============================
function openAllLayerSets( parent ){
var saveActivelayer = app.activeDocument.activeLayer;
for(var setIndex=0;setIndex<parent.layerSets.length;setIndex++){
app.activeDocument.activeLayer = parent.layerSets[setIndex].layers[0];
openAllLayerSets( parent.layerSets[setIndex]);
}
app.activeDocument.activeLayer = saveActivelayer;
};
function closeAllLayerSets(ref) {
var layers = ref.layers;
var len = layers.length;
for ( var i = 0; i < len; i ++) {
var layer = layers;
if (layer.typename == 'LayerSet') {app.activeDocument.activeLayer = layer; closeGroup(layer); var layer = layers; closeAllLayerSets(layer);};
}
}
function openGroup(layerSet) {
var m_activeLayer = activeDocument.activeLayer;
var m_Layer_Dummy01 = layerSet.artLayers.add();
var m_Layer_Dummy02 = layerSet.artLayers.add();
layerSet.layers[1].name = layerSet.layers[1].name;
m_Layer_Dummy01.remove();
m_Layer_Dummy02.remove();
activeDocument.activeLayer = m_activeLayer;
}
function closeGroup(layerSet) {
var m_Name = layerSet.name;
var m_Opacity = layerSet.opacity;
var m_BlendMode = layerSet.blendMode;
var m_LinkedLayers = layerSet.linkedLayers;
var m_bHasMask = hasLayerMask();
if(m_bHasMask) loadSelectionOfMask();
if(layerSet.layers.length <= 1) {
addLayer();
var m_Tmp = activeDocument.activeLayer;
m_Tmp.name = "dummy - feel free to remove me";
activeDocument.activeLayer = layerSet;
ungroup();
addToSelection("dummy - feel free to remove me");
groupSelected(m_Name);
} else {
activeDocument.activeLayer = layerSet;
ungroup();
groupSelected(m_Name);
}
var m_Closed = activeDocument.activeLayer;
m_Closed.opacity = m_Opacity;
m_Closed.blendMode = m_BlendMode;
for(x in m_LinkedLayers) {
if(m_LinkedLayers
.typename == "LayerSet") activeDocument.activeLayer.link(m_LinkedLayers
); }
if(m_bHasMask) maskFromSelection();
return m_Closed;
}
function ungroup() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Lyr " ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( sTID( "ungroupLayersEvent" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function addLayer() {
var m_ActiveLayer = activeDocument.activeLayer;
var m_NewLayer = activeDocument.artLayers.add();
m_NewLayer.move(m_ActiveLayer, ElementPlacement.PLACEBEFORE);
return m_NewLayer;
}
function hasLayerMask() {
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( sTID( "layer" ), cTID( "Ordn" ), cTID( "Trgt" ));
var m_Dsc01= executeActionGet( m_Ref01 );
return m_Dsc01.hasKey(cTID('Usrs'));
}
function activateLayerMask() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Chnl" ), cTID( "Msk " ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( cTID( "slct" ), m_Dsc01, DialogModes.NO );
} catch(e) {
var m_TmpAlpha = new TemporaryAlpha();
maskFromSelection();
activateLayerMask();
m_TmpAlpha.consume();
}
}
function deleteMask(makeSelection) {
if(makeSelection) {
loadSelectionOfMask();
}
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
try {
executeAction( cTID( "Dlt " ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function selectLayerMask() {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated(cTID("Chnl"), cTID("Chnl"), cTID("Msk "));
m_Dsc01.putReference(cTID("null"), m_Ref01);
m_Dsc01.putBoolean(cTID("MkVs"), false );
try {
executeAction(cTID("slct"), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function loadSelectionOfMask() {
selectLayerMask();
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putProperty( cTID( "Chnl" ), cTID( "fsel" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
var m_Ref02 = new ActionReference();
m_Ref02.putEnumerated( cTID( "Chnl" ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "T " ), m_Ref02 );
try {
executeAction( cTID( "setd" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function maskFromSelection() {
if(!hasLayerMask()) {
var m_Dsc01 = new ActionDescriptor();
m_Dsc01.putClass( cTID( "Nw " ), cTID( "Chnl" ) );
var m_Ref01 = new ActionReference();
m_Ref01.putEnumerated( cTID( "Chnl" ), cTID( "Chnl" ), cTID( "Msk " ) );
m_Dsc01.putReference( cTID( "At " ), m_Ref01 );
m_Dsc01.putEnumerated( cTID( "Usng" ), cTID( "UsrM" ), cTID( "RvlS" ) );
try {
executeAction( cTID( "Mk " ), m_Dsc01, DialogModes.NO );
} catch(e) {
activeDocument.selection.selectAll();
maskFromSelection();
}
} else {
if(confirm("Delete existing mask?", true, "Warning")) {
activateLayerMask();
deleteMask();
}
}
}
function groupSelected(name) {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putClass( sTID( "layerSection" ) );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
var m_Ref02 = new ActionReference();
m_Ref02.putEnumerated( cTID( "Lyr " ), cTID( "Ordn" ), cTID( "Trgt" ) );
m_Dsc01.putReference( cTID( "From" ), m_Ref02 );
var m_Dsc02 = new ActionDescriptor();
m_Dsc02.putString( cTID( "Nm " ), name);
m_Dsc01.putObject( cTID( "Usng" ), sTID( "layerSection" ), m_Dsc02 );
executeAction( cTID( "Mk " ), m_Dsc01, DialogModes.NO );
return activeDocument.activeLayer;
}
function addToSelection(layerName) {
var m_Dsc01 = new ActionDescriptor();
var m_Ref01 = new ActionReference();
m_Ref01.putName( cTID( "Lyr " ), layerName );
m_Dsc01.putReference( cTID( "null" ), m_Ref01 );
m_Dsc01.putEnumerated( sTID( "selectionModifier" ), sTID( "selectionModifierType" ), sTID( "addToSelection" ) );
m_Dsc01.putBoolean( cTID( "MkVs" ), false );
try {
executeAction( cTID( "slct" ), m_Dsc01, DialogModes.NO );
} catch(e) {}
}
function TemporaryAlpha() {
activeDocument.selection.store((this.alpha = activeDocument.channels.add()));
activeDocument.selection.deselect();
this.consume = function() {
activeDocument.selection.load(this.alpha);
this.alpha.remove();
}
}
// The main function
//openGroup(activeDocument.activeLayer);
//openAllLayerSets( app.activeDocument );
//closeGroup(activeDocument.activeLayer);
//closeAllLayerSets( app.activeDocument );
Message was edited by: JJMack
Copy link to clipboard
Copied
Yes that's right, the script on toggleOpen_CloseGroup is restrictive, I have this problem as well, for example the script can't see if a vector mask is enabled or linked, and as Michael said there are some functions that can't be accessed by script.
One other problem the script has is that if you have some colored layers inside your set and your set has another color when you will close the set with the script you will lose the color to your layers as well, they will change to the color of the set.
Copy link to clipboard
Copied
Yes you and I started with the script from posted on ps-scripts by TeddyBear. He call it ridiculous but it works and is fast. It has its faults and I don't use vector mask or color coding so its OK for me. You took it to up many notches to the height of ridiculousness. To code that much to stimulate what can be done better by pointing the mouse cursor and clicking the left mouse button. The good part is you learned a lot about scripting Photoshop in the process. I learned that its not possible to write a perfect script for it, So I really don use it. Sill I learned quite a bit about the workings of Photoshop in the process.
Copy link to clipboard
Copied
Yes you are so right, I've learned a lot on doing this script, before it I didn't knew how to use AM, it's great, to bad that there is no documentation for it. All I've learned I've learned from here and ps-scripts.com. Once again thank you all for taking the time to answer the questions and more important thank you for sharing your knowledge. You are right about the script as well, so much time spent on something that can be solved by moving and clicking the mouse.... but you know at first I thought that it can be a good idea just to press a key and open the group and TeddyBear gave a great ridiculous script on doing that, now as I seen that it can't be perfect I'm not so exited anymore, but anyway I'm grateful for the fact that it opened my eyes on AM.
Copy link to clipboard
Copied
I just stumbled on this topic, a related one here: