由于我的键盘不是美国键盘,所以我必须执行一个将“选择前一层”映射到 F 键的操作。
但是“选择前向层”不会选择不可见的层。
有没有办法选择前层,尽管它是不可见的?
答案1
我使用递归重写了提供的代码。它更加简洁,并且可以处理无限嵌套组。
它还可以更好地(且可配置地)处理隐藏组及其内容,这是原始代码中的一个问题。
// Setting the activeLayer in photoshop automatically makes it visible, so to
// traverse through the layer stack without ruining it we need to check if a
// layer is hidden first, then restore its state after activation.
// Unfortunately any layer within a hidden group appears hidden regardless of
// its true state in the interface. As we cannot know its true state we must
// are forced to set any layer within a hidden group to either visible or
// hidden. Your preferred behavior can be chosen in activateLayer().
// Alternatively, we can simply skip over the contents of hidden layer groups.
// I recommend this behavior as navigating within a a hidden group has limited
// usefulness.
var skipHiddenGroups = true;
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
var activateNext = false;
function traverseLayers(layers, inHiddenGroup) {
if (inHiddenGroup && skipHiddenGroups)
return;
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
if (activateNext) {
activateLayer(layer, inHiddenGroup);
activateNext = false;
} else if (layer === currentLayer) {
activateNext = true;
}
if (layer.typename === "LayerSet") {
traverseLayers(layer.layers, (!layer.visible || inHiddenGroup));
}
}
}
function traverseLayersReverse(layers, inHiddenGroup) {
if (inHiddenGroup && skipHiddenGroups)
return;
for (var i = layers.length - 1; i >= 0; i--) {
var layer = layers[i];
if (layer.typename === "LayerSet") {
traverseLayersReverse(layer.layers, (!layer.visible || inHiddenGroup));
}
if (activateNext) {
activateLayer(layer, inHiddenGroup);
activateNext = false;
} else if (layer === currentLayer) {
activateNext = true;
}
}
}
function activateLayer(layer, inHiddenGroup) {
var isVisible = layer.visible
doc.activeLayer = layer
if (inHiddenGroup) {
// Ignore layers that are within a hidden group as we cannot know their true state.
} else if (!isVisible) {
doc.activeLayer.visible = false;
}
}
// Call traverseLayers or traverseLayersReverse depending on which direction you want to go.
traverseLayers(doc.layers, false);
答案2
假设您所说的前向层是指顶层,您可以使用一个简单的脚本来执行此操作。打开您的 ExtendScript Toolkit(它应该与 Photoshop 一起安装)并创建一个新的 Javascript 文档。然后输入:
var doc = app.activeDocument; //references current document
doc.activeLayer = doc.layers[0]; //selects the top layer
这将使顶层在被选中时可见。如果你想让它不可见,请在末尾添加以下行:
doc.activeLayer.visible = false;
为了方便起见,请将其保存在您的 Presets/Scripts 文件夹中(尽管它可以保存在任何地方)。
然后进入 Photoshop,创建一个新文件,开始录制新操作,然后转到文件 > 脚本 > 浏览,找到您的脚本。打开它即可运行它。运行后,停止录制并为该操作分配一个快捷键,瞧!
如果由于某种原因您找不到 ExtendScript Toolkit,只需将代码放入空白文本文档中,并将扩展名更改为 .jsx 。如果在录制操作后移动脚本文件,则必须重新录制它,因为它会记住路径。
答案3
我通过稍微修改我在 AHK 论坛上找到的脚本(该脚本强制将目标层切换为可见并存在其他小错误)来做到这一点,它对我来说有效:
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;
这是为了进入下一层(下一层);对于上一层(上一层),只需制作另一个脚本,将 TRY 部分中的 [a+1] 更改为 [a-1],将 CATCH 部分中的 [0] 更改为 [doc.layers.length-1]。好吧,下面是常用方法:将两个脚本都放在 Ps 脚本文件夹中,使用“插入菜单项”执行操作,并根据需要分配热键。您以后甚至可以使用您最喜欢的 AHK 快捷键等等……
答案4
对上面的脚本进行一些补充。
在 Ps 中测试这些脚本后,我发现如果当前工作流中有组,脚本将无法正常工作。它们不考虑组内的图层(在脚本语言中称为图层集);当脚本通过“图层”列出时,它只处理上层元素(组外的图层和组本身)。
因此我尝试对它们进行调整以满足更广泛的需求。
修改后的脚本如下;它们可以正确处理具有上层图层和组以及上层组中嵌套元素的工作流。如果活动层不是两次嵌套元素,它们也可以在更多层次下工作(否则“向下”脚本将切换到最上层,“向上”脚本将不执行任何操作)。但我真的很少处理一次以上的嵌套组,最糟糕的情况是,如果太有必要,可以使用老式的鼠标单击(或者使用传统的 Alt+[/] 快捷键,它们仍然适用于所有非隐藏层,无论如何嵌套)。
抱歉,我远不是一个程序员,所以功能齐全的代码超出了我的能力范围;此外,我想这些脚本也相当庞大。但它们确实有效。(例如,我将“向上”循环分配给 F3,将“向下”循环分配给 F4,将“切换可见性”脚本分配给 F2;对我来说,这种组合非常方便,节省了很多时间)。
“循环下降”脚本
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
//===========
var gropp = doc.layerSets.length;
var docl = doc.layers.length;
var sublayer = 0;
//alert(gropp)
for (i=0; i < gropp;)
{
sublayer = sublayer + doc.layerSets[i].layers.length;
i++;
}
//==============
var a = -1
var kk = -1
var aa = -1
//если активный слой - элемент высшего порядка:
for(i=0; i<docl;)
{
if(doc.layers[i]==currentLayer)
{
a=i;
i = docl;
}
else{ i++;}
}
//если активный слой - элемент группы:
if (a<0)
{
for (i=0; i<gropp;)
{
var subdocl = doc.layerSets[i].layers.length;
for (k=0; k<subdocl;)
{
if(doc.layerSets[i].layers[k]==currentLayer)
{
aa = i;
kk = k;
k = doc.layerSets[i].layers.length;
i = gropp-1;
}
else { k++; }
}
i++;
}
}
//ACTIVATING
//если активный слой - слой высшего порядка:
if (kk<0)
{
//если активный слой - группа (т.е. нижележ. слой - внутри её):
for (i=0; i<gropp;)
{
if (doc.layerSets[i] == currentLayer)
{
var nLayer = doc.layerSets[i].layers[0];
var check = nLayer.visible;
doc.activeLayer = nLayer;
var isGroup = true;
var isActived = true;
if (check == false)
doc.activeLayer.visible = false;
i = gropp;
}
else {i++;}
}
//если активный слой - простой слой (будет обрабатываться в try-catch):
if (isGroup != true)
{
for (i=0; i<docl;)
{
if (doc.layers[i]==currentLayer)
{
numm = i;
i=docl;
}
else {i++;}
}
}
}
else
//(если активный слой - подобъект (элемент группы), т.е. известны (неотриц.) aa и kk:
{
//если элемент группы - последний в ней (будет обрабатываться в try-catch):
if (kk == subdocl-1)
{
for (i=0; i<docl;)
{
if (doc.layers[i] == doc.layerSets[aa])
{
numm = i;
i = docl;
}
else {i++;}
}
}
//если не последний в группе, то проще:
else
{
var nLayer = doc.layerSets[aa].layers[kk+1];
var check = nLayer.visible;
doc.activeLayer = nLayer;
var isActived = true;
if (check == false)
doc.activeLayer.visible = false;
}
}
//try-catch секция для последних вариантов (самых нижних слоёв):
try
{
//alert ("isActived is " + isActived)
if (isActived != true)
{
var nLayer = doc.layers[numm+1];
var check = nLayer.visible;
doc.activeLayer = nLayer;
if (check == false)
doc.activeLayer.visible = false;
}
}
catch(e)
{
var nLayer = doc.layers[0];
var check = nLayer.visible;
doc.activeLayer = nLayer;
if (check == false)
doc.activeLayer.visible = false;
}
“循环”脚本
var doc = app.activeDocument;
var currentLayer = doc.activeLayer;
var gropp = doc.layerSets.length;
var docl = doc.layers.length;
var a = -1
var kk = -1
var aa = -1
//если активный слой - элемент высшего порядка:
for(i=0; i<docl;)
{
if(doc.layers[i]==currentLayer)
{
a=i;
i = docl;
}
else{ i++;}
}
//если активный слой - элемент группы:
if (a<0)
{
for (i=0; i<gropp;)
{
var subdocl = doc.layerSets[i].layers.length;
for (k=0; k<subdocl;)
{
if(doc.layerSets[i].layers[k]==currentLayer)
{
aa = i;
kk = k;
k = doc.layerSets[i].layers.length;
//модернизируем скрипт: вносим сразу в этот цикл обработку активизации.
//если элемент группы - первый в ней (активизируем саму группу - гипероним):
if (kk==0)
{
var pLayer = doc.layerSets[i];
var check = pLayer.visible;
doc.activeLayer = pLayer;
//var isGroup = true;
var isActived = true;
if (check == false)
doc.activeLayer.visible = false;
}
//если не первый, то просто слой вверх:
else
{
var pLayer = doc.layerSets[i].layers[kk-1];
var check = pLayer.visible;
doc.activeLayer = pLayer;
var isActived = true;
if (check == false)
doc.activeLayer.visible = false;
}
i = gropp-1;
}
else { k++; }
}
i++;
}
}
//если активный слой - высший элемент; нам известно (неотриц) a:
else
{
if (a==0)
a=docl;
for (i=0; i<gropp;)
{
//если предыдущий слой - последний элемент находящейся выше группы:
if (doc.layerSets[i] == doc.layers[a-1])
{
var subdocl = doc.layerSets[i].layers.length;
var pLayer = doc.layerSets[i].layers[subdocl-1];
var check = pLayer.visible;
doc.activeLayer = pLayer;
var isActived = true;
if (check == false)
doc.activeLayer.visible = false;
i = gropp;
}
else {i++;}
}
if (isActived != true)
{
var pLayer = doc.layers[a-1];
var check = pLayer.visible;
doc.activeLayer = pLayer;
if (check == false)
doc.activeLayer.visible = false;
}
}
“奖励”-“切换可见性”-脚本
var currentLayer = activeDocument.activeLayer;
currentLayer.visible = !currentLayer.visible
注意:将它们保存为 *.jsx 文件并放入 C:\Program Files\Adobe\%Your Adobe Version Folder%\Presets\Scripts