Copy link to clipboard
Copied
Hi!
This script simulates Option/Alt+] , hides active group and select the next one
( https://screenpal.com/watch/c0l6qDVmGJf )
I need help for scripting - simulating the opposite, select next group up and make it visible, can anyone help ?
(only groups should be selected)
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
// =============Toggle visbility ==============
var idHd = charIDToTypeID( "Hd " );
var desc170 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var list54 = new ActionList();
var ref127 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref127.putEnumerated( idLyr, idOrdn, idTrgt );
list54.putReference( ref127 );
desc170.putList( idnull, list54 );
executeAction( idHd, desc170, DialogModes.NO );
// ========== Simulate shortcut Option/Alt+[ select next goup==================
var idslct = charIDToTypeID( "slct" );
var desc117 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref83 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idBckw = charIDToTypeID( "Bckw" );
ref83.putEnumerated( idLyr, idOrdn, idBckw );
desc117.putReference( idnull, ref83 );
var idMkVs = charIDToTypeID( "MkVs" );
desc117.putBoolean( idMkVs, false );
var idLyrI = charIDToTypeID( "LyrI" );
var list33 = new ActionList();
list33.putInteger( 10 );
desc117.putList( idLyrI, list33 );
executeAction( idslct, desc117, DialogModes.NO );
The following isn’t pretty, but it does do what you want (it's based on the action method above):
activeDocument.suspendHistory("Select Layer...", "selectLayerMakeVisible('forwardEnum')"); // 'forwardEnum' or 'backwardEnum'
function selectLayerMakeVisible(forwardORbackward) {
toggleShow();
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var list = new ActionList();
var reference = new ActionReference();
reference.putEnumerat
...
A little crooked but it seems to work )
var layer = activeDocument.activeLayer;
// remember the visibility of layers
var d = new ActionDescriptor();
var r = new ActionReference();
r.putClass(stringIDToTypeID("compsClass"));
d.putReference(stringIDToTypeID("null"), r);
var d1 = new ActionDescriptor();
d1.putBoolean(stringIDToTypeID("useVisibility"), true);
d1.putBoolean(stringIDToTypeID("usePosition"), false);
d1.putBoolean(stringIDToTypeID("useAppearance"), false);
d.putObject(stringIDToTypeID
...
Copy link to clipboard
Copied
Does this have to be for the next invisible group? Or could it just be for the next invisible layer or group?
I don't have a copy of the code (I wish I did), however, I think that it may have been either @c.pfaffenbichler or perhaps @Chuck Uebele who posted a script to select the forward or backward visible/invisible layer. The great thing about that script was that it behaved just like the keyboard shortcut in that once it hit the top or bottom of the layers panel, it would then cycle through and keep going through the stack again (not sticking at the top or bottom).
EDIT: Your original script only works for visible layers, do you also wish for it to work with invisible layers as well?
Copy link to clipboard
Copied
Hi,
you are right, it have to work with the next up invisible group
I want to select groups, not layers
Bellow it is a screen recording of my workflow
(The "buttons" I click are shortcuts to specific scripts, form an extension)
Copy link to clipboard
Copied
@Manan Joshi wrote a script to select the next group within a selected group, but this isn't exactly what you are looking for and it is too advanced for me to edit.
Copy link to clipboard
Copied
One option to select the next invisible layer/group here from @Joonass
https://gist.github.com/joonaspaakko/048c9b58ccbb6e6f44c894bf4ce30b68
You must add the code to set the active layer visibility to true.
Copy link to clipboard
Copied
I had planned to expand on the layer selection script that @Stephen Marsh linked to, but I never finished it or put online... They're a little redundant unless you really care about selecting hidden layers. I just added it to my existing layer selection repo... Maybe there's something helpful there. There is a config that finds the next group (the two test scripts that start with "Select next layer group..."), but I'm not certain they operate with the same logic as that native shortcut. @siomosp, if you want the same exact functionality as in your scripting listener code, but you also want to make the group visible at the same time, there's an example here on line 263 that should make the layer visible if set to true. That should work in the scripting listener code you posted too.
Copy link to clipboard
Copied
The "Cycle-up" script at this 10 years old post works fine, but it is slow... and expands subgroups
https://superuser.com/questions/255506/select-forward-layer-keyboard-shortcut-include-invisible-laye...
screen recording
(The "buttons" I click are shortcuts to specific scripts, using an extension)
Copy link to clipboard
Copied
Something like this. If you want to address the 2 potential hangups I've listed at the top, you're going to have to do that by yourself.
Copy link to clipboard
Copied
It's also possible to select the next invisible layer/group with an action, it just takes a little more work than one might expect:
Again, you would need to add a "show current layer" step to make the selected layer or group visible.
Copy link to clipboard
Copied
@Stephen Marsh , The action is not selecting forward invisible layer, dont know why 😞
Copy link to clipboard
Copied
The following isn’t pretty, but it does do what you want (it's based on the action method above):
activeDocument.suspendHistory("Select Layer...", "selectLayerMakeVisible('forwardEnum')"); // 'forwardEnum' or 'backwardEnum'
function selectLayerMakeVisible(forwardORbackward) {
toggleShow();
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var list = new ActionList();
var reference = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t(forwardORbackward));
descriptor.putReference(s2t("null"), reference);
descriptor.putBoolean(s2t("makeVisible"), false);
list.putInteger(3);
descriptor.putList(s2t("layerID"), list);
executeAction(s2t("select"), descriptor, DialogModes.NO);
toggleShow();
activeDocument.activeLayer.visible = true;
//activeDocument.activeLayer.visible ^= 1; // toggle visibility
function toggleShow() {
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var list = new ActionList();
var reference = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
list.putReference(reference);
descriptor.putList(s2t("null"), list);
descriptor.putBoolean(s2t("toggleOptionsPalette"), true);
executeAction(s2t("show"), descriptor, DialogModes.NO);
}
}
Note: It makes the layer visible (there is commented placeholder code to toggle the visibility from off/on or on/off).
Copy link to clipboard
Copied
Yet another option for selecting the next visible/invisible layer. You would need to add an activeDocument.activeLayer.visible = true; line to make the selected layer or group visible or use code to toggle the visibility from off/on or on/off.
/*
https://superuser.com/questions/255506/select-forward-layer-keyboard-shortcut-include-invisible-layers
Select previous/backward layer
*/
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
for(i=0; i < doc.layers.length; )
{
if(doc.layers[i]==currentLayer)
{
a=i;
//alert(a);
i = doc.layers.length;
}
else{ i++; }
}
try
{
var nextLayer = doc.layers[a+1];
var check = nextLayer.visible;
}
catch(e)
{
var nextLayer = doc.layers[0];
var check = nextLayer.visible;
}
doc.activeLayer = nextLayer;
if (check == false)
doc.activeLayer.visible = false;
or
/*
https://superuser.com/questions/255506/select-forward-layer-keyboard-shortcut-include-invisible-layers
Select next/forward layer
*/
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
for(i=0; i < doc.layers.length; )
{
if(doc.layers[i]==currentLayer)
{
a=i;
//alert(a);
i = doc.layers.length;
}
else{ i++; }
}
try
{
var nextLayer = doc.layers[a-1];
var check = nextLayer.visible;
}
catch(e)
{
var nextLayer = doc.layers[doc.layers.length-1];
var check = nextLayer.visible;
}
doc.activeLayer = nextLayer;
if (check == false)
doc.activeLayer.visible = false;
Copy link to clipboard
Copied
Could you please post screenshots with the pertinent Panels (Toolbar, Layers, Options Bar, …) visible to illustrate the process?
Copy link to clipboard
Copied
A little crooked but it seems to work )
var layer = activeDocument.activeLayer;
// remember the visibility of layers
var d = new ActionDescriptor();
var r = new ActionReference();
r.putClass(stringIDToTypeID("compsClass"));
d.putReference(stringIDToTypeID("null"), r);
var d1 = new ActionDescriptor();
d1.putBoolean(stringIDToTypeID("useVisibility"), true);
d1.putBoolean(stringIDToTypeID("usePosition"), false);
d1.putBoolean(stringIDToTypeID("useAppearance"), false);
d.putObject(stringIDToTypeID("using"), stringIDToTypeID("compsClass"), d1);
executeAction(stringIDToTypeID("make"), d, DialogModes.NO);
// select all layers and turn on visibility for all
var d = new ActionDescriptor();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("null"), r);
executeAction(stringIDToTypeID("selectAllLayers"), d, DialogModes.NO);
var d = new ActionDescriptor();
var list = new ActionList();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
list.putReference(r);
d.putList(stringIDToTypeID("null"), list);
executeAction(stringIDToTypeID("show"), d, DialogModes.NO);
// restoring the current active layer
var d = new ActionDescriptor();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("null"), r);
executeAction(stringIDToTypeID("selectNoLayers"), d, DialogModes.NO);
activeDocument.activeLayer = layer;
// execute the command Alt+]
var d = new ActionDescriptor();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("forwardEnum"));
d.putReference(stringIDToTypeID("null"), r);
executeAction(stringIDToTypeID("select"), d, DialogModes.NO);
// restoring the visibility of layers
var d = new ActionDescriptor();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("compsClass"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("null"), r);
executeAction(stringIDToTypeID("applyComp"), d, DialogModes.NO);
executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);
// make the current layer visible anyway
activeDocument.activeLayer.visible = true;
Copy link to clipboard
Copied
The following code is getting there, perhaps somebody with better scripting knowledge than I possess can make something of it? It only selects layer sets, regardless of visibility. Ideally it would cycle either up or down (2 scripts) from the current active layer or layer group to the next layer group. I'm only looking at top-level layers at the moment, the extra complexity of going through nested groups is even more challenging.
/*
based on:
https://www.autohotkey.com/board/topic/94621-photoshop-cycle-through-layers-script/
*/
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
for (i = 0; i < doc.layerSets.length;) {
if (doc.layerSets[i] == currentLayer) {
a = i;
i = doc.layerSets.length;
} else {
i++;
}
}
try {
var nextLayer = doc.layerSets[a + 1];
var check = nextLayer.visible;
} catch (e) {
var nextLayer = doc.layerSets[0];
var check = nextLayer.visible;
}
doc.activeLayer = nextLayer;
if (check == false)
doc.activeLayer.visible = false;
Copy link to clipboard
Copied
If you are interested, this uses pretty much the same idea, but adds a few key things to it.
Copy link to clipboard
Copied
Thanks @Joonass – the original request has now been clarified, only groups should be selected, not any other layerKind.
Looking at the screen recording, this is for top-level groups inside groups, however for flexibility it would be better to just cycle through all top level layer groups.
Copy link to clipboard
Copied
I'm just dropping bread crumbs because I don't want to do all his work for him. I mean, all you really need to add to that is wrap the layer selection in a recursive function that asks after a selection: "is this layer a group? No → trigger the function again. Yes → stop.".
As a real world example of that, this script (or rather the included script inside it) does exactly that, though the way it operates might make it too complex to use as an example (function is defined here and when it decides the target hasn't been reathed, it recursively calls the function inside itself here) since it doesn't select layer on the same level, rather linearly the next layer.
Edit: Now that you said it... Looping through layerSets, rather than layers, should be more efficient.
Copy link to clipboard
Copied
Thank you all for the effort, I marked the correct answer 🙂