スクリプト

マーカーでリズムを刻むスクリプト「keyframePlayer@Marker.jsx」

事前に用意したキーフレームをマーカーごとに再生させる「マーカーでリズムを刻むエクスプレッションアイディア」をスクリプト化。

マーカーを活用して決まった動きをリズミカルにリピートできます。

[チュートリアル動画]

あったらヤなチュートリアルを作りました。スクリプトの動きと概要を掴めます。

[概要]

アンカーポイント、位置、スケール、回転、不透明度用にエクスプレッションでリンクしたエフェクト制御にセットしたキーフレームをマーカーのタイミングで再生させます。

[使い方]

  1. 再生できるようにしたいプロパティを全選択する
  2. スクリプトを実行する
  3. 追加されたエフェクトの方にキーフレームをセッティングする
  4. セットしたキーフレームを再生させたいタイミングでマーカーを打つ
  5. 曲に合わせてリズミカルに押せばいいと思う
  6. そう思う

[注意点]

対応するプロパティをレイヤーのトランスフォーム内に限定しています。エフェクトのプロパティ、シェイプのプロパティなどは処理を拒否します。アラート出します。(絶対出します。)

キーフレームのセッティング時にも動きをプレビューできるように、選択レイヤーのインポイントに先に1つマーカー打っちゃいます。セットし終わったらズラすか消すかしてください。

[解説]

function f_keyframePlayerAtMarker(){
    var sel = app.project.activeItem.selectedLayers;
    var efName=["[E]markerNum","markerからズラす(f)"];
    var efValue=0;
    var parade="",addFx1="",addFx2="";
    var checkName="";

    if(sel.length!=0){
        for(i=0;i<sel.length;i++){
            if(sel[i].selectedProperties[0].parentProperty.matchName!="ADBE Transform Group"){
                alert("トランスフォームのプロパティを選んでから実行");
                return;
            }//プロパティ選んでるか
            sel[i].property("ADBE Marker").setValueAtTime(sel[i].inPoint,new MarkerValue(""));
            var efNameDup=[];
            for(j=0;j<sel[i].selectedProperties.length;j++){
                efNameDup.push("動きをセット_[E]"+sel[i].selectedProperties[j].name);
            }
            for(j=0;j<efName.length;j++){//エフェクトチェック->無いときだけ追加
                if(sel[i].property("ADBE Effect Parade")(efName[j])==null){
                    addFx1=sel[i].property("ADBE Effect Parade").addProperty("ADBE Slider Control");
                    addFx1.enabled=false;
                    addFx1.name=efName[j];
                }
            }
            for(j=0;j<sel[i].selectedProperties.length;j++){
                efValue=sel[i].selectedProperties[j].value;
                var exprsn=''+
                        'reM=-effect("'+efName[1]+'")(1);//マーカーの何フレーム前から動かすか\r'+
                        'if((effect("'+efNameDup[j]+'")(1).numKeys>0)&&(time>=0)&&(effect("'+efName[0]+'")(1)>0)&&(marker.numKeys>0)){\r'+
                        '   nowframe=timeToFrames((time+inPoint)+framesToTime(reM))-timeToFrames(marker.key(effect("'+efName[0]+'")(1)).time);\r'+
                        '   effect("'+efNameDup[j]+'")(1).valueAtTime(framesToTime(nowframe));\r'+
                        '}else{\r'+
                        '   value;\r'+
                        '}';
                if((sel[i].selectedProperties[j].matchName=="ADBE Rotate X")||(sel[i].selectedProperties[j].matchName=="ADBE Rotate Y")||(sel[i].selectedProperties[j].matchName=="ADBE Rotate Z")){
                    if(sel[i].property("ADBE Effect Parade")(efNameDup[j])==null){
                        parade=sel[i].property("ADBE Effect Parade");
                        addFx1=parade.addProperty("ADBE Angle Control");
                        addFx1.name=efNameDup[j];
                        parade(efNameDup[j]).enabled=false;
                        parade(efNameDup[j])(1).setValue(efValue);
                        parade(efNameDup[j])(1).addKey(sel[i].inPoint);
                    }
                    sel[i].selectedProperties[j].expression=exprsn;
                }else if(sel[i].selectedProperties[j].value.length==undefined){
                    if(sel[i].property("ADBE Effect Parade")(efNameDup[j])==null){
                        parade=sel[i].property("ADBE Effect Parade");
                        addFx1=parade.addProperty("ADBE Slider Control");
                        addFx1.name=efNameDup[j];
                        parade(efNameDup[j]).enabled=false;
                        parade(efNameDup[j])(1).setValue(efValue);
                        parade(efNameDup[j])(1).addKey(sel[i].inPoint);
                    }
                    sel[i].selectedProperties[j].expression=exprsn;
                }else if(sel[i].selectedProperties[j].value.length==3){
                    if(sel[i].property("ADBE Effect Parade")(efNameDup[j])==null){
                        checkName="┗縦横比を固定_[E]"+sel[i].selectedProperties[j].name;
                        parade=sel[i].property("ADBE Effect Parade");
                        addFx1=parade.addProperty("ADBE Point3D Control");
                        addFx1.name=efNameDup[j];
                        parade(efNameDup[j]).enabled=false;
                        parade(efNameDup[j]).name=efNameDup[j];
                        parade(efNameDup[j])(1).setValue(efValue);
                        parade(efNameDup[j])(1).addKey(sel[i].inPoint);

                        if(sel[i].selectedProperties[j].matchName=="ADBE Scale"){
                            addFx2=sel[i].property("ADBE Effect Parade").addProperty("ADBE Checkbox Control");
                            addFx2.name=checkName;
                            parade(checkName).enabled=false;
                            parade(efNameDup[j])(1).expression=''+
                                'if(effect("'+checkName+'")(1).value==1){\r'+
                                '   [value[0],value[0],value[0]]\r'+
                                '}else{\r'+
                                '   value;\r'+
                                '}';
                        }
                    }
                    sel[i].selectedProperties[j].expression=exprsn;
                }
            }//for selectedProperties.length

            sel[i].property("ADBE Effect Parade")(efName[0])(1).expression=''+//[E]markerNum
                        'var reM=-effect("markerからズラす(f)")(1);//マーカーの何フレーム前から動かすか\r'+
                        'var tugi=0;\r'+
                        'if(marker.numKeys>0){\r'+
                        '  var nKey=marker.nearestKey(time);\r'+
                        '  if(time+framesToTime(reM) >= nKey.time){\r'+
                        '    tugi=nKey.index;\r'+
                        '  }else{\r'+
                        '    tugi=nKey.index-1;\r'+
                        '  }\r'+
                        '}else{\r'+
                        '  value;\r'+
                        '}';

        }//for sel.length
    }else{
        alert("1つ以上プロパティを選んでから実行");
    }
}//function

app.beginUndoGroup("keyframePlayer@Marker");
    f_keyframePlayerAtMarker();
app.endUndoGroup();

まず、10行目でトランスフォームのプロパティが選択されているかどうかをチェック。これ以外なら処理しません。

if(sel[i].selectedProperties[0].parentProperty.matchName!="ADBE Transform Group"){

シェイプの線の太さや、エフェクトのプロパティなどで動きを再生できれば夢が広がるが、ややこしいアニメーションは逆にエフェクトコントロールパネルがカオスになるため、次回以降に「keyframePlayer@tRemap」なるものを目論んでいます。

そして16行目でエフェクトに追加する名前を溜めておきます。スケールを選択していれば「動きをセット_[E]スケール」など。

efNameDup.push("動きをセット_[E]"+sel[i].selectedProperties[j].name);

27行目以降で選択プロパティに見合うエクスプレッション制御を追加していきます。

  • 1次元ならスライダー制御
  • 2次元ならポイント制御
  • 3次元なら3Dポイント制御

それぞれのselectedProperties[j].value.lengthを調べれば次元がわかります。undefinedなら1次元、3なら3次元です。

ここで先に伝えてしまいますが、レイヤートランスフォームには2次元のプロパティがありません。アンカーポイント、位置、スケールは2Dレイヤー状態でも3Dレイヤー状態でも、3次元の値が帰ってきます。なのでポイント制御は使わず、2次元だった場合は無視できます。

さらに回転なら角度制御を使用したいところですが、回転は1次元なのでスライダー制御を追加する場合と被るため、調べ方を工夫する必要があります。

これはもうマッチネームで調べます。27行目の…

if((sel[i].selectedProperties[j].matchName=="ADBE Rotate X")||(sel[i].selectedProperties[j].matchName=="ADBE Rotate Y")||(sel[i].selectedProperties[j].matchName=="ADBE Rotate Z")){

にて、「X回転」「Y回転」「Z回転」の場合は角度制御を使用します。

2Dレイヤーの場合の「回転」は「Z回転(ADBE Rotate Z)」と帰ってきます。

先に回転を角度制御に割り当ててしまえば、その他のselectedProperties[j].value.lengthがundefinedであれば不透明度であると消去法でわかります。これにはスライダー制御です。

また、67行目でスケールを見つけて、いじる数値の縦横比を固定できるチェックボックスを追加しています。

if(sel[i].selectedProperties[j].matchName=="ADBE Scale"){

そして該当のレイヤープロパティに「マーカーでリズムを刻むエクスプレッションアイディア」通りエクスプレッションを仕込めばOKです。

sel[i].selectedProperties[j].expression=''+
    'reM=-effect("'+efName[1]+'")(1);//マーカーの何フレーム前から動かすか\r'+
    'if((effect("'+efNameDup[j]+'")(1).numKeys>0)&&(time>=0)&&(effect("'+efName[0]+'")(1)>0)&&(marker.numKeys>0)){\r'+
    '   nowframe=timeToFrames((time+inPoint)+framesToTime(reM))-timeToFrames(marker.key(effect("'+efName[0]+'")(1)).time);\r'+
    '   effect("'+efNameDup[j]+'")(1).valueAtTime(framesToTime(nowframe));\r'+
    '}else{\r'+
    '   value;\r'+
    '}';

最後に、追加したエフェクト[E]markerNumに今何個目のマーカーかを表示するエクスプレッションを仕込めば完成です。

sel[i].property("ADBE Effect Parade")(efName[0])(1).expression=''+//[E]markerNum
            'var reM=-effect("markerからズラす(f)")(1);//マーカーの何フレーム前から動かすか\r'+
            'var tugi=0;\r'+
            'if(marker.numKeys>0){\r'+
            '  var nKey=marker.nearestKey(time);\r'+
            '  if(time+framesToTime(reM) >= nKey.time){\r'+
            '    tugi=nKey.index;\r'+
            '  }else{\r'+
            '    tugi=nKey.index-1;\r'+
            '  }\r'+
            '}else{\r'+
            '  value;\r'+
            '}';

ダウンロード

ワンクリックでループするタイムリマップを仕込むスクリプト「tRemapLooper.jsx」前のページ

全選択レイヤーのデュレーションを一致させるスクリプト「durationMatcher.jsx」次のページ

ピックアップ記事

  1. なぜ?After Effectsのレイヤーをエクスプレッションで効率化
  2. なぜ?After Effectsの操作を「スクリプト」で効率化
  3. YouTubeで一時停止中のコントローラーを非表示にするブックマークレット
  4. フリーランスの開業届提出は開業freeeでとにかく簡単に
  5. amazonのスポンサー商品(広告)を非表示にするブックマークレット「amazO…

関連記事

  1. スクリプト

    tRemapSelectorSetterした2つのリマップ番号を入れ替えるスクリプト「numSlid…

    「タイムリマップでレイヤー管理するスクリプト(フリーズフレーム)「tR…

  2. スクリプト

    選択レイヤー名末尾の数値を#で始まるエフェクトに適用する補助スクリプト「numSliderSette…

    複数の整列させるレイヤーの管理を効率化するエクスプレッション連動スライ…

  3. スクリプト

    ワンクリックでループするタイムリマップを仕込むスクリプト「tRemapLooper.jsx」

    コンポジションをloopOut()した際のコマ飛び含め、ちょっとした手…

  4. スクリプト

    After Effectsのスクリプトの書き方

    After Effectsのスクリプトを作るのに必要なものを紹介します…

  5. スクリプト

    選択レイヤーサイズのマスクをシェイプで描くスクリプト「addShapeMask@rect.jsx」

    テキストに合わせたサイズの、さらにサイズ追従するエクスプレッションを仕…

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

CAPTCHA