事前に用意したキーフレームをマーカーごとに再生させる「マーカーでリズムを刻むエクスプレッションアイディア」をスクリプト化。
マーカーを活用して決まった動きをリズミカルにリピートできます。
[チュートリアル動画]
あったらヤなチュートリアルを作りました。スクリプトの動きと概要を掴めます。
[概要]
アンカーポイント、位置、スケール、回転、不透明度用にエクスプレッションでリンクしたエフェクト制御にセットしたキーフレームをマーカーのタイミングで再生させます。
[使い方]
- 再生できるようにしたいプロパティを全選択する
- スクリプトを実行する
- 追加されたエフェクトの方にキーフレームをセッティングする
- セットしたキーフレームを再生させたいタイミングでマーカーを打つ
- 曲に合わせてリズミカルに押せばいいと思う
- そう思う
[注意点]
対応するプロパティをレイヤーのトランスフォーム内に限定しています。エフェクトのプロパティ、シェイプのプロパティなどは処理を拒否します。アラート出します。(絶対出します。)
キーフレームのセッティング時にも動きをプレビューできるように、選択レイヤーのインポイントに先に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'+
'}';
この記事へのコメントはありません。