【AEスクリプト】エフェクトのドロップダウンメニューからレイヤーをすばやく選ぶ 『DropTune』

レイヤー数が多いと、ドロップダウンメニューから目当てのレイヤーを選ぶのも一苦労です。そんなときにお使いください。

以下のボタンからダウンロードできます。

あるいは以下のコードをテキストにコピーして、拡張子を.jsxにすれば完成です。
右上のマークをクリックすれば全文をコピーできます。

(function (aGbl) {
    function mCreateUI(aObj) {
        var mPorW = (aObj instanceof Panel) ? aObj : new Window("palette", "DropTune", undefined);
        mPorW.preferredSize = [200, 200];
        mPorW.margins = [10, 10, 10, 10];
        mPorW.spacing = 4;
        
        mPorW.mCbDrpDwn = mPorW.add("checkbox { preferredSize : [180,20] ,alignment :  [ 'left','top' ] ,text : 'Lock'}");
        mPorW.mGpDrpDwn = mPorW.add("group { orientation : 'column', alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 4}");
        mPorW.mBtDrpDwn = mPorW.mGpDrpDwn.add("button { preferredSize : [180,20] ,  alignment :  [ 'left','top' ] ,text : 'Get DropDownMenu'}");    
        mPorW.mEtPropN = mPorW.mGpDrpDwn.add("edittext { preferredSize : [180,20] ,alignment :  [ 'left','top' ] ,text : ''}");
        mPorW.mEtPrmN = mPorW.mGpDrpDwn.add("edittext { preferredSize : [180,20] ,alignment :  [ 'left','top' ] ,text : ''}");
        
        mPorW.mGpBrnk = mPorW.add("group { orientation : 'stack', preferredSize : [20,20] , alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 0}");
        mPorW.mGpBrnk.add("statictext { preferredSize : [20,20] ,alignment :  ['left','center' ] ,text : ''}");
        mPorW.mGpBrnk.add("panel {  preferredSize : [180,1],alignment :  [ 'fill','center' ] , margins : [0, 0, 0, 0], spacing : 0}");
        
        mPorW.mGpEftLyr = mPorW.add("group {  orientation : 'column',alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 4}");
        mPorW.mGpEftLyrBtCb = mPorW.mGpEftLyr.add("group {alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 4}");    
        mPorW.mBtEftLyr = mPorW.mGpEftLyrBtCb.add("button { preferredSize : [60,20] ,  alignment :  [ 'left','top' ] ,text : 'Get Effect'}");
        mPorW.mCbEftLyr = mPorW.mGpEftLyrBtCb.add("checkbox { preferredSize : [20,20] ,alignment :  [ 'left','top' ] ,text : ''}");
        mPorW.mStEftLyr = mPorW.mGpEftLyr.add("statictext { preferredSize : [180,20] ,alignment :  [ 'left','top' ] ,text : ''}");
        
        mPorW.mGpTgt = mPorW.add("group {  orientation : 'column',alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 4}");
        mPorW.mGpTgtEtSt = mPorW.mGpTgt.add("group { alignment :  [ 'left','top' ] , margins : [0, 0, 0, 0], spacing : 4}");
        mPorW.mBtTgt = mPorW.mGpTgtEtSt.add("button { preferredSize : [60,20] ,  alignment :  [ 'left','top' ] ,text : 'Get Index'}");
        mPorW.mEtTgt = mPorW.mGpTgtEtSt.add("edittext { preferredSize : [120,20] ,alignment :  [ 'left','top' ] ,text : ''}");
        mPorW.mStTgt = mPorW.mGpTgt.add("statictext { preferredSize : [180,20] ,alignment :  [ 'left','top' ] ,text : ''}");

        mPorW.mBtAply = mPorW.add("button { preferredSize : [-1,40] ,  alignment :  [ 'fill','top' ] ,text : 'Apply'}");

        mPorW.mEtPropN.text = "ADBE Set Matte3";
        mPorW.mEtPrmN.text = "レイヤーからマットを取り込む";
        mPorW.mCbDrpDwn.value = true;
        mPorW.mGpDrpDwn.enabled = false;
        mPorW.mCbEftLyr.value = true;
        
        //レイヤー情報用の変数。
        mPorW.mLyrName = "";
        mPorW.mLyrIdx = null;
        mPorW.mPrpName = "";
        mPorW.mPrpIdx = null;
        
        return mPorW;

    }

    //mPnlという名でメインウインドウを作成。
    var mPnl = mCreateUI(aGbl);
    if (mPnl instanceof Window) {
        mPnl.center();
        mPnl.show();
    } else if (mPnl instanceof Panel) {
        //UIパネルの場合は以下をしないと自動レイアウトされない。
        mPnl.layout.layout(true);
    }
    //----------------------------------------------------------------------------------------------------------------------   
    //セッティングパート。
    var mSecName = "DropTune";
    //設定があれば読み込む。
    if (app.settings.haveSetting(mSecName, "mEtPropN")) {
        mPnl.mEtPropN.text = mConvertCodesTxtToTxt(app.settings.getSetting(mSecName, "mEtPropN"));
    }
    if (app.settings.haveSetting(mSecName, "mEtPrmN")) {
        mPnl.mEtPrmN.text = mConvertCodesTxtToTxt(app.settings.getSetting(mSecName, "mEtPrmN"));
    }
    if (app.settings.haveSetting(mSecName, "mCbDrpDwn")) {
        mPnl.mCbDrpDwn.value = (app.settings.getSetting(mSecName, "mCbDrpDwn") === "true");
        mPnl.mGpDrpDwn.enabled = !(mPnl.mCbDrpDwn.value);
    }
    if (app.settings.haveSetting(mSecName, "mCbEftLyr")) {
        mPnl.mCbEftLyr.value = (app.settings.getSetting(mSecName, "mCbEftLyr") === "true");
        mPnl.mBtEftLyr.enabled = mPnl.mCbEftLyr.value;
        mPnl.mStEftLyr.enabled = mPnl.mCbEftLyr.value;
    }
    //----------------------------------------------
    //チェックボックスとEnabledの連動。
    mPnl.mCbDrpDwn.onClick = function () {
        mPnl.mGpDrpDwn.enabled = !(mPnl.mCbDrpDwn.value);
        app.settings.saveSetting(mSecName, "mCbDrpDwn", mPnl.mCbDrpDwn.value);
    }
    mPnl.mCbEftLyr.onClick = function () {
        mPnl.mBtEftLyr.enabled = mPnl.mCbEftLyr.value;
        mPnl.mStEftLyr.enabled = mPnl.mCbEftLyr.value;
        app.settings.saveSetting(mSecName, "mCbEftLyr", mPnl.mCbEftLyr.value);
    }
    //PropとParamのエディットテキストに入力したときにその文字を保存する。
    mPnl.mEtPropN.onChanging = mPnl.mEtPropN.onChange = function () {
        app.settings.saveSetting(mSecName, "mEtPropN", mConvertTxtToCodesTxt(mPnl.mEtPropN.text));
    }
    mPnl.mEtPrmN.onChanging = mPnl.mEtPrmN.onChange = function () {
        app.settings.saveSetting(mSecName, "mEtPrmN", mConvertTxtToCodesTxt(mPnl.mEtPrmN.text));
    }
    //----------------------------------------------------------------------------------------------------------------------  
    //メインパート。
    //テキスト入力するとレイヤー名を検索する。
    mPnl.mEtTgt.onChanging = mPnl.mEtTgt.onChange = function () {
        app.beginUndoGroup("Get Layer Name");

        var mStr = mPnl.mEtTgt.text;
        var mIdx = parseInt(mStr);
        if (isNaN(mIdx)) {
            mPnl.mStTgt.text = "";
            return;
        }

        var mAi = app.project.activeItem;
        if (0 >= mIdx || mIdx > mAi.numLayers) {
            mPnl.mStTgt.text = "";
            return;
        }

        var mLyr = mAi.layer(mIdx);
        mPnl.mStTgt.text = mLyr.name;

        app.endUndoGroup();
    }
    //--------------------------------------------------------------
    //ターゲットレイヤーを得る。
    mPnl.mBtTgt.onClick = function () {
        app.beginUndoGroup("Get Target Layer Index");

        var mAi = app.project.activeItem;
        var mSl = mAi.selectedLayers[0];

        mPnl.mEtTgt.text = mSl.index;
        mPnl.mStTgt.text = mSl.name;
        app.endUndoGroup();
    }
    //--------------------------------------------------------------
    //エフェクトレイヤーを得る。
    mPnl.mBtEftLyr.onClick = function () {
        app.beginUndoGroup("Get Effect Prop");

        var mAi = app.project.activeItem;
        var mSl = mAi.selectedLayers[0];
        var mSp = mSl.selectedProperties[0];

        mPnl.mStEftLyr.text = "No." + mSl.index + ":" + mSl.name + " / "+ "No." + mSp.propertyIndex + ":" + mSp.name;
        //ウインドウの要素変数にも値を入れておく。
        mPnl.mLyrName = mSl.name;
        mPnl.mLyrIdx = mSl.index;
        mPnl.mPrpName = mSp.name;
        mPnl.mPrpIdx = mSp.propertyIndex;

        app.endUndoGroup();
    }
    //--------------------------------------------------------------
    //ドロップダウンメニュー情報を得る。
    mPnl.mBtDrpDwn.onClick = function () {
        app.beginUndoGroup("Get DropDownMenu Info");

        var mAi = app.project.activeItem;
        var mSl = mAi.selectedLayers[0];

        var mSps = mSl.selectedProperties;
        if (mSps.length !== 2) {
            alert("Select effect\'s parameter from timeline.")
            return;
        }
        var mSp1 = mSps[0];
        var mSp2 = mSps[1];
        var mSpPre = mSp2.propertyGroup(1);
        if (mSpPre.name !== mSp1.name) { return; }

        mPnl.mEtPropN.text = mSp1.matchName;
        mPnl.mEtPrmN.text = mSp2.name;

        app.settings.saveSetting(mSecName, "mEtPropN", mConvertTxtToCodesTxt(mPnl.mEtPropN.text));
        app.settings.saveSetting(mSecName, "mEtPrmN", mConvertTxtToCodesTxt(mPnl.mEtPrmN.text));

        app.endUndoGroup();
    }
    //--------------------------------------------------------------
    //得た値を適用する。
    mPnl.mBtAply.onClick = function () {
        app.beginUndoGroup("Apply");
        var mAi = app.project.activeItem;
        
        //ボタンで得たエフェクトを使う場合。
        if(mPnl.mCbEftLyr.value){
            var mSlIN= mPnl.mLyrName;
            var mSlIdx = mPnl.mLyrIdx;
            var mSpN= mPnl.mPrpName;
            var mSpIdx = mPnl.mPrpIdx;

            /*
            var mStr = mPnl.mStEftLyr.text;
            var mStrAry = mStr.split(" / ");
            var mSlData = mStrAry[0].split(":");
            var mSpData = mStrAry[1].split(":");
            var mSlIdx = parseInt( mSlData[0].replace ("No.", ""));
            var mSlIN= mSlData[1];
            var mSpIdx = parseInt(mSpData[0].replace ("No.", ""));
            var mSpN= mSpData[1];
            */

            mAi.layer(mSlIdx).effect.property(mSpIdx).property(mPnl.mEtPrmN.text).setValue(parseInt(mPnl.mEtTgt.text));
        //選択レイヤーを使う場合。複数レイヤーに対応。
        }else{
            var mSls = mAi.selectedLayers;
            if( mSls.length === 0 ){
                return;
            }else if( mSls.length === 1 ){
                var mSl = mSls[0];
                var mSps = mSl.selectedProperties;
                //エフェクトを選択している場合はそれに適用する。そうでなければマッチネームで一番上のものに適用する。
                if (mSps.length !== 0) { var mSp = mSps[0];}
                else{ var mSp = mSl.effect.property(mPnl.mEtPropN.text);}

                mSp.property(mPnl.mEtPrmN.text).setValue(parseInt(mPnl.mEtTgt.text));
            //複数レイヤーの場合は一番上のものに適用する。
            }else{
                for(var i = 0; i < mSls.length; i++ ){
                    var mSl = mSls[i];
                    alert();
                    if( !(mSl.effect.hasOwnProperty (mPnl.mEtPropN.text)) ){ continue;}
                    var mSp = mSl.effect.property(mPnl.mEtPropN.text);
                    mSp.property(mPnl.mEtPrmN.text).setValue(parseInt(mPnl.mEtTgt.text));
                }
            }  
        }
        app.activeViewer.setActive();
        app.endUndoGroup();
    }
    //----------------------------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------------------------
    //使用関数。
    //文字をコード(数字)の文字列にする関数。
    function mConvertTxtToCodesTxt(aTxt) {
        var mNameCodes = [];
        //文字を一つずつUnicode(数字)で取得して、配列に入れる。
        for (var i = 0; i < aTxt.length; i++) {
            var mCode = aTxt.charCodeAt(i);
            mNameCodes.push(mCode);
        }
        //コードの配列をコンマ区切りの文字列にする。
        //aTxtに””を入力すると、lengthゼロなので直接ここへ来て、空の配列mNameCodesを処理する。
        //join()は[]を””にするので、戻り値がコード文字列or””となるが、読み込み関数で処理する。
        var mNameCodesStr = mNameCodes.join(",");
        return mNameCodesStr;
    }
    //----------------------------------------------
    //コード(数字)の文字列を元の文字にする関数。
    function mConvertCodesTxtToTxt(aCodesTxt) {
        //空""にはコード番号はない。それに対し、
        //(本来コード番号数値を入れるはずの)fromCharCode()に空””(文字列)を入れると
        //なぜかコード番号0番目の空を取得してしまう。厳密には変換できていないので、その対策が以下。
        if (aCodesTxt === "") { return "" }

        //まずは文字列を配列にする。
        var mNameCodesAry = aCodesTxt.split(",");
        var mNameLetterAry = [];
        //Unicode(数字)を文字にして1つずつ取得、配列に入れていく。
        for (var i = 0; i < mNameCodesAry.length; i++) {
            var mLetter = String.fromCharCode(mNameCodesAry[i]);
            mNameLetterAry.push(mLetter);
        }
        //1文字ずつ入った配列を1つの文字列にまとめる。
        var mNameRst = mNameLetterAry.join("");
        return mNameRst;
    }
    //---------------------------------------------------------------------------------------------------------------------- 
}(this));

使い方

準備

初回のみ、最初に『Lock』を外してドロップダウンメニューエフェクトの種類を決めます。
レイヤーに適用された好きなエフェクトのドロップダウンメニュープロパティを選び、『Get DropDownMenu』を押します。その下の欄に情報が入力されればOKです。

*エフェクトプロパティはエフェクトパネルから選択できないので、タイムラインで選択してください。
(エフェクトパネル内のプロパティをダブルクリックすれば、タイムラインに表示されます)

*Get DropDownMenuの再ロックは(処理に影響しないため)してもしなくてもかまいません。

*準備で入力された情報はAEの設定に保存されます。ゆえに次回以降、「別エフェクトでやりたい」となるまではこの準備は不要となります。

*欄のエフェクト名はマッチネーム(スクリプト内での正式名称のようなもの)が入力されます。


2通りのやり方

エフェクトを選んでからレイヤーを選ぶ方法と、レイヤーを選んでからエフェクトを選ぶ方法があります。

エフェクトを選んでからレイヤーを選ぶ方法

STEP
エフェクトを選ぶ。

『Get Effect』の右にあるチェックをONにし、”準備”で決めた種類のエフェクトを選んで『Get Effect』を押します。

STEP
レイヤー番号を得る。

ドロップダウンメニューへ適用したいレイヤーを選び、『Get Index』を押します。
直接番号を入力することもできます。

*番号を手入力するとレイヤー名が自動検索されます。

STEP
適用する。

一番下の『Apply』を押せば完了です!

レイヤーを選んでからエフェクトを選ぶ方法

STEP
レイヤー番号を得る。

『Get Effect』の右にあるチェックをOFFにし、
ドロップダウンメニューへ適用したいレイヤーを選び、『Get Index』を押します。
直接番号を入力することもできます。

*番号を手入力するとレイヤー名が自動検索されます。

STEP
エフェクト(あるいはレイヤー)を選んで適用する。

”準備”で決めた種類のエフェクト自体、あるいはそれを持つレイヤーを選んで『Apply』を押せば完了です!

*該当エフェクトを持っているレイヤーを選択すれば、エフェクトを選択しなくてもかまいません。同種のエフェクトが複数ある場合、1番上にあるものに適用されます。2つ目以降のエフェクトに適用したい場合は、それを選択して『Apply』を押せばOKです。


*追記
「レイヤーを選んでからエフェクトを選ぶ方法」に限り、『複数レイヤーそれぞれが持つ同エフェクトに適用』に対応しています。レイヤーを1つ選んで番号を得てから、複数レイヤーを選んで『Apply』を押せばOKです。同種エフェクトが1枚に複数ある場合、1番上にあるものに適用されます。2つ目以降のエフェクトには適用できません。

解説

最初に作ったバージョンは「エフェクトを選んでからレイヤーを選ぶ方法」だったんですが、どうも順番が直観的ではないなあと思い、逆順操作も可能にしました。

後者の「レイヤーを選んでからエフェクトを選ぶ方法」は直観的なんですが、レイヤー選択をビューワーではなくタイムラインでやらざるを得ない場面ではちょっとめんどうかなと思います。『エフェクトレイヤー』と『ドロップダウンメニューへ適用したいレイヤー』を行ったり来たりせねばです。

適材適所でお使いいただければ幸いです!

よかったらシェアしてね!
  • URLをコピーしました!