Copy link to clipboard
Copied
Hello,
I need one keyboard shortcut that toggles visibility of one of layers.
I paint and need to toggle on and off one layer below (layer with a reference picture, not one i paint on). with a shortcut painting process will be not break as with case click at icon.
tried to make toggle layer visibility with actions unfortunately with no success.
it is possibility to toggle active layer visibility by add shortcut in keyboard shortcuts preferences but here it going not about active layer.
I have no experience with scripting.
thank you!
Copy link to clipboard
Copied
If I understand what you are asking the script below will toggle the layer visibility of the layer below the active/selected layer. It works with layerSets. If the selected layer is at the bottom of the stack/set, the script does nothing.
var curentLayer = app.activeDocument.activeLayer;
var curentParent = curentLayer.parent;
var currentIndex = getLayerIndex( curentParent, curentLayer );
if(currentIndex != (curentParent.artLayers.length-1)){
curentParent.artLayers[currentIndex+1].visible= !curentParent.artLayers[currentIndex+1].visible;
}
function getLayerIndex( parent, layer ){
for(var i=0;i<parent.artLayers.length;i++){
if(parent.artLayers==layer) return i;
}
};
Copy link to clipboard
Copied
Exactly what i need! works great! Thank you!!
it is possible to have some additional functionality like that: script check if layer named "Ref" exist and if yes toggles its visibility ?
many thanks!
Copy link to clipboard
Copied
Do you mean you only want to toggle the layer below the selected layer if the layer below's name is 'Ref'?
Or do you mean you want to toggle the layer named 'Ref' no matter where it is in a stack?
Copy link to clipboard
Copied
yes, i mean no matter where it is in stack.
Copy link to clipboard
Copied
For this to work as written there can only be one layer in the document named 'Ref' otherwise it will toggle the top most layer with that name.
var targetID = getLayerIDByName('Ref');
if(undefined != targetID){
if(getLayerVisibilityByID( targetID ) ){
hideByName('Ref');
}else{
showByName('Ref');
}
}
function getLayerIDByName(name) {
try{
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "LyrI" ));
ref.putName( charIDToTypeID( "Lyr " ), name );
return executeActionGet(ref).getInteger(charIDToTypeID( "LyrI" ));
}catch(e){}
};
function getLayerVisibilityByID( id ) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "Vsbl" ));
ref.putIdentifier( charIDToTypeID( "Lyr " ), id );
return executeActionGet(ref).getBoolean(charIDToTypeID( "Vsbl" ));
};
function hideByName(name) {
var desc = new ActionDescriptor();
var list = new ActionList();
var ref = new ActionReference();
ref.putName( charIDToTypeID('Lyr '), name );
list.putReference( ref );
desc.putList( charIDToTypeID('null'), list );
executeAction( charIDToTypeID('Hd '), desc, DialogModes.NO );
};
function showByName(name) {
var desc = new ActionDescriptor();
var list = new ActionList();
var ref = new ActionReference();
ref.putName( charIDToTypeID('Lyr '), name );
list.putReference( ref );
desc.putList( charIDToTypeID('null'), list );
executeAction( charIDToTypeID('Shw '), desc, DialogModes.NO );
};
Copy link to clipboard
Copied
Michael, you are my Santa!
Thank you very much!
Copy link to clipboard
Copied
Michaeal - these are both *great* painting scripts, but how could you remember the current visibility state for all layers, then create a toggle to make only the current layer visible? The visibility state isn't essential, but it would be nice...
Copy link to clipboard
Copied
To clairfy: the other layers' visibility state check and rememberance isn't essential, but it would be nice...
Copy link to clipboard
Copied
You mean like alt-clicking on the layer visibility icon in the layer's panel?
Copy link to clipboard
Copied
This script is works perfect and toggles only the first layer with specific name. Is there any possibility to toggle ALL the layers with this specific name?
Copy link to clipboard
Copied
When there are duplicate name I do not think a the script could use just get by name I think the script would need to loop through all layer locate the layers with the name and flip their visibility state. All may not have the same state and may not be visible when their sate is visible for they may be in a layer group that has it visibility state of off. But I'm just a hacker. What do I know not much, but know sometings.
Copy link to clipboard
Copied
Yes, this is a possible way but it's too slow on big documents. I've already wrote some code that works as expected but I need something more quick. It seems that it should be written with photoshop actionDescriptors like above.
var layerName = 'LayerName';
var docRef = activeDocument;
toggle(docRef);
function toggle(obj) {
for(var i=0;i<obj.layers.length;i++) {
if(obj.layers.typename =='LayerSet') {
toggle (obj.layers);
if(obj.layers.name == layerName) {
if(obj.layers.visible == false) {
obj.layers.visible = true;
}
else {
obj.layers.visible = false;
}
}
}
}
}
Copy link to clipboard
Copied
function layers(v) {
function sTT(v) {return stringIDToTypeID(v)}
(ref = new ActionReference()).putEnumerated(sTT('document'), sTT('ordinal'),
sTT('targetEnum')); len = executeActionGet(ref).getInteger(sTT('numberOfLayers'))
for(; i <= len;) {
(ref = new ActionReference()).putIndex(sTT('layer'), i++)
if ((dsc = executeActionGet(ref)).getString(sTT('name')) == v) {
(lst = new ActionList()).putReference(ref), dsc.putList(sTT('null'), lst)
vis = sTT(dsc.getBoolean(sTT('visible')) ? 'hide' : 'show')
executeAction(vis, dsc, DialogModes.NO)
}
}
}
layers('Layer 1')
Copy link to clipboard
Copied
Wow! Thanks! Almost perfect.
Kukurykus, one moment. Is there any possibility to toggle only LayerSets with specified name but not Layers?
Copy link to clipboard
Copied
Why not perfect. Doesn't it do that you wanted? For layerSets having the same name as layers change:
if ((dsc = executeActionGet(ref)).getString(sTT('name')) == v) {
to:
if ((dsc = executeActionGet(ref)).getString(sTT('name')) == v && typeIDToStringID
(dsc.getEnumerationValue(sTT(lS = 'layerSection'))) == lS + 'Start') {
Copy link to clipboard
Copied
Kukurykus, yes, it does what I wanted. I just need this clarification about layerSets/layers. Now it's perfect! Thanks a lot!
Btw, can you please point me to some photoshop actionScript references to learn? I was not able to find any good ones.
Copy link to clipboard
Copied
It's my first code with layer(Set)s using Action Manager. I simply played with code of Michael L Hale , then modified to write it my way and fit your goal. I have no knowledge about it. If I want something to get to know I use this forum and try to understand how something works to do what I need, like with Sets I found in other theard.
Copy link to clipboard
Copied
Kukurykus, the script does not work if there is no Background in the file. How can this be fixed?
Copy link to clipboard
Copied
You do not need background for your script, (do you?) however it is (un)present, so the easiest workaround is to change:
for(; i <= len;) {
to:
for(i = 1; i <= len;) {
Copy link to clipboard
Copied
Yes, right. Background always has ID=0;
You do not need background for your script, (do you?)
Sometimes I do, sometimes not.
Btw this code:
for(; i <= len;) {
Always throws an exception, so I've first changed it to:
for(i=0; i <= len;) {
And this caused an error if the Background is not present in the file.
Thanks again!
Copy link to clipboard
Copied
If I understand you tried to set i to 0 - that didn't work untill I came with correct solution? I didn't test it much but here's ok.
Copy link to clipboard
Copied
This thread has helped me. I only needed to toggle a named layer. This is the Javascript that works for me. Perhaps someone else will find it useful.
app.activeDocument.layers.getByName('LayerNameHere').visible ^= 1;
Copy link to clipboard
Copied
Good to know '^=' toggles visibility.