Photoshop Jsxで複数選択したレイヤーに共通処理を行う


PhotoshopのExtendScriptApiだと選択しているレイヤーの取得にapp.activeDocument.activeLayerを使いますが、これだと複数のレイヤーを取得している時に、代表レイヤーしかobjectの取得ができず、選択している全てのレイヤーに何か共通処理を施すことができません。

この問題に関して、チャレンジしている方が何人もおり、下の記事を参考にさせてもらっておりました。

色々と試行錯誤していく中で、自分なりにこれがいいかなーという手法を見つけたので紹介します。

選択しているレイヤー全てに共通処理を行うスクリプト

executeSelectLayersAction.jsx
function executeSelectLayersAction(exec_action)
{
  // 元のactiveLayer位置を覚えておく
  var active_layer = app.activeDocument.activeLayer;
  var is_visible = active_layer.visible;

  var doc_ref = new ActionReference()
  doc_ref.putEnumerated(charIDToTypeID("Dcmn"),charIDToTypeID("Ordn"),charIDToTypeID("Trgt"));
  var target_layers = executeActionGet(doc_ref).getList(stringIDToTypeID('targetLayersIndexes'));

  // 選択しているレイヤーのIDを取得しておく
  for(var i=0;i<target_layers.count;i++)
  {
    var index = target_layers.getReference(i).getIndex() + 1;

    // レイヤーを選択状態にする
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putIndex(charIDToTypeID( "Lyr " ), index);
    desc.putReference(charIDToTypeID( "null" ), ref );
    desc.putBoolean(charIDToTypeID( "MkVs" ), false );
    executeAction(charIDToTypeID( "slct" ), desc, DialogModes.NO );

    var select_layer = app.activeDocument.activeLayer;
    exec_action(select_layer);
  }

  app.activeDocument.activeLayer = active_layer;
  app.activeDocument.activeLayer.visible = is_visible;
}

使い方は以下の通り

#target photoshop;

var select_layer_names = [];
executeSelectLayersAction(function(layer){
  // 選択したレイヤーに対して行いたい処理をここに書く。
  select_layer_names.push(layer.name);
});

alert(select_layer_names.join(", "));

選択状態

実行結果

動作の説明

上のスクリプトは次のロジックで動作しています

  • 選択されているレイヤーのIndexのリストを取得
  • このレイヤーのIndex情報をforで回し、一つずつ選択状態にさせる(ActionDescriptorを使って選択状態にする)
  • app.activeDocument.activeLayerを取得し、登録されているactionを実行する

動作も軽くていい感じです!
ただし、Command押しで複数選択した場合は問題ないですが、Shif押しでグループレイヤーを選択した時、グループレイヤー内の全てのレイヤーが選択状態になるため、意図していない動作になる場合があります。