Photoshopのスクリプトでレイヤーが選択されているかどうかを検出する

フォトショで「選択されているレイヤー」に対して処理を行いたかったのですが、先に「ドキュメントが開いているか」「レイヤーが選択されているか」をチェックしなきゃいけなくて、そこがなかなか骨が折れたのでメモしておきます。
選択されていない場合は一番上のレイヤーを取得しちゃう
参考にさせていただいたサイトにも書かれていますが、
var ly = activeDocument.activeLayer;
と書いただけだと、選択されていなくても一番上(最前面)のレイヤーが返ってきてしまうのですよね。そうではない…、そうではないんだ……ッ!! で、いろいろ試行錯誤したのですが、別の処理で「ドキュメント内のすべてのレイヤー・レイヤーセットの総数を数える」関数を利用する場面があったので、これを使ってなんとかならないかな、と思って作った結果です。
これがベストというわけじゃない気がするので、参考程度に御覧ください。
参考
ありがとうございました!
コード
メイン
try {
if ( documents.length == 0 ) { //開いているドキュメントがゼロなら
throw new Error( "ドキュメントが開いていません" );
}
var doc = activeDocument; //ドキュメントを取得
if ( !isSelected( doc ) ) { //選択レイヤーが存在しなければ
throw new Error( "レイヤーが選択されていません" );
}
//選択レイヤーがあるので処理をします!
} catch ( e ) { //例外
alert( e.message ); //例外メッセージ出力
}
まずこちらがメインコード。6行目でドキュメントを引数にして、選択レイヤーの存在有無をTrue/Falseで返す自作関数です。ドキュメントが開いていない、レイヤーが選択されていない場合12行目にジャンプしてメッセージ出力して処理をせずに終了、という流れです。
選択レイヤーの存在有無を返す関数
//選択レイヤーが存在するか確認する関数
function isSelected( doc ) {
//すべてのレイヤーとレイヤーセットの数を数える
allLsLen = -1; //初期化
allLyLen = 0;
getAllLyLen( doc ); //数える
var beforeLsLen = allLsLen;
var beforeLyLen = allLyLen;
//存在確認としての複製
var desc0 = new ActionDescriptor();
var ref0_1 = new ActionReference();
ref0_1.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc0.putReference( charIDToTypeID( "null" ), ref0_1 );
desc0.putString( charIDToTypeID( "Nm " ), "tmp" );
desc0.putInteger( charIDToTypeID( "Vrsn" ), 5 );
var list0_2 = new ActionList();
list0_2.putInteger( 179 );
desc0.putList( charIDToTypeID( "Idnt" ), list0_2 );
executeAction( charIDToTypeID( "Dplc" ), desc0, DialogModes.NO );
//再度すべてのレイヤーとレイヤーセットの数を数える
allLsLen = -1; //初期化
allLyLen = 0;
getAllLyLen( doc ); //数える
var afterLsLen = allLsLen;
var afterLyLen = allLyLen;
//判定
if ( beforeLsLen == afterLsLen && beforeLyLen == afterLyLen ){ //数が同じなら
return false; //存在しない
}else{
executeAction( charIDToTypeID('undo'), undefined, DialogModes.NO ); //複製をアンドゥ
return true; //存在する
}
}
//すべてのレイヤーとレイヤーセットの数を数える関数
function getAllLyLen(layObj){
var n = layObj.artLayers.length;
for ( var i = 0; i < n; i++ ) {
allLyLen++;
}
var ns = layObj.layerSets.length;
allLsLen++;
for ( var i = 0; i < ns; i++ ) {
getAllLyLen(layObj.layerSets[i]); //再帰処理
}
}
2つの関数に分かれていて、6行目と25行目で下の「すべてのレイヤーとレイヤーセットの数を数える関数」を呼び出しています。
大きな流れは、「現状を数える」→「複製」→「もう一度数える」→「判定」という形です。選択レイヤーがある場合は、複製後レイヤーが増えているはずなので、複製前後の数の違いで判定しています。





コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。