矢印シェイプを生成しつつ、ベンドで曲げれるようにしました。
既存のアニメーションプリセット配布記事、2点をつまんで描ける矢印シェイプ(.ffx配布あり)「Shape-Arrow」の仕様を活かしつつスクリプト化しました。
[概要]
ベンド可の矢印シェイプを作成するスクリプト。
[使い方]
- スクリプトを実行
- エフェクトにあるCC Bend ItのStartとEndで矢印をセット
[オプション]
- CC Bend Itの[Bend]で曲がり具合を調節可能
- [矢印B]をONでおしりも矢印になる
- [矢の高さ]、[矢の太さ]、[全体太さ]調整可能
- [線の色]でシェイプの塗りの色を調整可能
- [境界線の太さ]でシェイプの線幅を調節可能
- [境界線の色]でシェイプの線の色を調節可能
[完成品]
//////////////////////////////////////////////////
// 矢印シェイプを生成するスクリプト
// Bend対応
//////////////////////////////////////////////////
var actCmp=app.project.activeItem;
function f_ShapeArrow_s_2dBend(){
var shapeLyr = actCmp.layers.addShape();// 空のシェイプレイヤーが作られる
shapeLyr.name="Shape-Arrow(s)@2DBend";
shapeLyr.label=2;
// セットするエフェクト準備
var efAry=["CC Bend It","矢印B","矢の高さ","矢の太さ","全体太さ","線の色","境界線の太さ","境界線の色"];
var efAry2=["CC Bend It","ADBE Checkbox Control","ADBE Slider Control","ADBE Slider Control","ADBE Slider Control","ADBE Color Control","ADBE Slider Control","ADBE Color Control"];
var addAry=[];
//エフェクトを次々適用
for(i=0;i<efAry.length;i++){
addAry[i]=shapeLyr.property("ADBE Effect Parade").addProperty(efAry2[i]);
if(i!=0){addAry[i].enabled=false;}
addAry[i].name=efAry[i];
}//for
//エフェクトに初期値セット
var pointA=shapeLyr.property("ADBE Effect Parade")(efAry[0])(2);
var pointB=shapeLyr.property("ADBE Effect Parade")(efAry[0])(3);
var center=shapeLyr.property("ADBE Transform Group").property("ADBE Position").value;
pointA.setValue([center[0]-100,center[1]]);
pointB.setValue([center[0]+100,center[1]]);
shapeLyr.property("ADBE Effect Parade")(efAry[1])(1).setValue(0);
shapeLyr.property("ADBE Effect Parade")(efAry[2])(1).setValue(40);
shapeLyr.property("ADBE Effect Parade")(efAry[3])(1).setValue(20);
shapeLyr.property("ADBE Effect Parade")(efAry[4])(1).setValue(10);
shapeLyr.property("ADBE Effect Parade")(efAry[5])(1).setValue([136,136,136,255]/255);//グレー
shapeLyr.property("ADBE Effect Parade")(efAry[6])(1).setValue(10);
shapeLyr.property("ADBE Effect Parade")(efAry[7])(1).setValue([0,0,0,255]/255);//黒
var shapeProperty = shapeLyr.property("ADBE Root Vectors Group"); // これにシェイプを追加していく
var shapeGroup1 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup1.name="ヨコ線";
/* 長方形パスを3つ準備+エクスプレッションもセットしていく */
var shapePath1 = shapeGroup1.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath1(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n'+
'var bf=[10,0];\r\n'+
'var arB;\r\n\r\n'+
'if(effect("'+efAry[1]+'")(1)==0){\r\n'+
' arHeight=(length(pA,pB)>arHeight)?arHeight:length(pA,pB);\r\n'+
' arB=arHeight;\r\n'+
'}else{\r\n'+
' arB=0;\r\n'+
' arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n'+
'}\r\n\r\n'+
'var p1=-(length(pA,pB)/2)+[arHeight,0];\r\n'+
'var p1a=p1-([0,allWidth]);\r\n'+
'var p1b=p1+([0,allWidth]);\r\n'+
'var p2=(length(pA,pB)/2)-[arHeight,0]+arB;\r\n'+
'var p2a=p2-([0,allWidth]);\r\n'+
'var p2b=p2+([0,allWidth]);\r\n\r\n'+
'createPath(points=[p1a,p2a-bf,p2b-bf,p1b,p1a],[],[],true);';
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var pA=effect("CC Bend It")("Start")-anchor;\r\n'+
'var pB=effect("CC Bend It")("End")-anchor;\r\n\r\n'+
'[(pA[0]+pB[0])/2,(pA[1]+pB[1])/2];';
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var pA=effect("CC Bend It")("Start")-anchor;\r\n'+
'var pB=effect("CC Bend It")("End")-anchor;\r\n'+
'var a=(pB-pA);\r\n'+
'var angle=Math.atan2(a[1],a[0]);\r\n\r\n'+
'radiansToDegrees(angle)';
var shapeGroup2 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup2.name="矢印A";
var shapePath2 = shapeGroup2.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath2(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n\r\n'+
'if(effect("矢印B")(1)==0){\r\n'+
' arHeight=(length(pA,pB)>arHeight)?arHeight:length(pA,pB);\r\n'+
'}else{\r\n'+
' arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n'+
'}\r\n\r\n'+
'var p1=[0,0];\r\n'+
'var p2a=[arHeight,allWidth+arWidth];\r\n'+
'var p3a=[arHeight,-allWidth-arWidth];\r\n\r\n'+
'createPath(points=[p1,p2a,p3a,p1],[],[],true);';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'effect("CC Bend It")("Start")-anchor;';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'content("ヨコ線").transform.rotation';
var shapeGroup3 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup3.name="矢印B";
var shapePath3 = shapeGroup3.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath3(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n\r\n'+
'var angle2a=degreesToRadians(0);\r\n'+
'arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n\r\n'+
'var p1=[0,0];\r\n'+
'var p2a=-[arHeight,allWidth+arWidth];\r\n'+
'var p3a=-[arHeight,-allWidth-arWidth];\r\n'+
'var bf=[10,0];\r\n\r\n'+
'if(effect("矢印B")(1)==0){\r\n'+
' p1=p2a;\r\n'+
' p3a=p2a;\r\n'+
'}else{\r\n'+
'}\r\n\r\n'+
'createPath(points=[p1-bf,p2a-bf,p3a-bf,p1-bf],[],[],true);';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'effect("CC Bend It")("End")-anchor;';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'content("ヨコ線").transform.rotation';
// 塗り
shapeProperty.addProperty("ADBE Vector Graphic - Fill").property("ADBE Vector Fill Color").expression=
'effect("'+efAry[5]+'")(1);';
// 線
var stroke=shapeProperty.addProperty("ADBE Vector Graphic - Stroke");
stroke.property("ADBE Vector Stroke Width").expression=
'effect("'+efAry[6]+'")(1);';
stroke.property("ADBE Vector Stroke Color").expression=
'effect("'+efAry[7]+'")(1);';
}
app.beginUndoGroup("ShapeArrow(s)@2DBend");
f_ShapeArrow_s_2dBend();
app.endUndoGroup();[解説]
まずはシェイプレイヤーを準備します。H型の定規シェイプを作成するスクリプト「Shape-RulerH_V2.jsx」の通り、スクリプトでシェイプを作る場合、指定が大変面倒です。
まずは9行目、addShape()します。空のシェイプレイヤーを準備し、パスや塗りなどプロパティはこの後にいちいち指定してぶち込んでいきます。リネームとラベルを黄色に設定します。
var shapeLyr = actCmp.layers.addShape();// 空のシェイプレイヤーが作られる
shapeLyr.name="Shape-Arrow(s)@2DBend";
shapeLyr.label=2;13行目からはエフェクト追加の処理をまとめました。任意のエフェクト名と、対応する型のエクスプレッション制御をマッチネームで配列に入れます。
そのままfor文で回しながら連続で追加→リネームさせます。
基本的にはエフェクトOFFでも問題のないエクスプレッション制御は、エフェクトのオフ化でメモリを省エネ化します。CC Bend Itはエフェクトの効果として必要なのでif(i!=0)でオフ化をスキップします。
// セットするエフェクト準備
var efAry=["CC Bend It","矢印B","矢の高さ","矢の太さ","全体太さ","線の色","境界線の太さ","境界線の色"];
var efAry2=["CC Bend It","ADBE Checkbox Control","ADBE Slider Control","ADBE Slider Control","ADBE Slider Control","ADBE Color Control","ADBE Slider Control","ADBE Color Control"];
var addAry=[];
//エフェクトを次々適用
for(i=0;i<efAry.length;i++){
addAry[i]=shapeLyr.property("ADBE Effect Parade").addProperty(efAry2[i]);
if(i!=0){addAry[i].enabled=false;}
addAry[i].name=efAry[i];
}//for25行目から、追加したエフェクトの初期値をセットしていきます。
//エフェクトに初期値セット
var pointA=shapeLyr.property("ADBE Effect Parade")(efAry[0])(2);
var pointB=shapeLyr.property("ADBE Effect Parade")(efAry[0])(3);
var center=shapeLyr.property("ADBE Transform Group").property("ADBE Position").value;
pointA.setValue([center[0]-100,center[1]]);
pointB.setValue([center[0]+100,center[1]]);
shapeLyr.property("ADBE Effect Parade")(efAry[1])(1).setValue(0);
shapeLyr.property("ADBE Effect Parade")(efAry[2])(1).setValue(40);
shapeLyr.property("ADBE Effect Parade")(efAry[3])(1).setValue(20);
shapeLyr.property("ADBE Effect Parade")(efAry[4])(1).setValue(10);
shapeLyr.property("ADBE Effect Parade")(efAry[5])(1).setValue([136,136,136,255]/255);//グレー
shapeLyr.property("ADBE Effect Parade")(efAry[6])(1).setValue(10);
shapeLyr.property("ADBE Effect Parade")(efAry[7])(1).setValue([0,0,0,255]/255);//黒39行目でシェイプレイヤー内のルートとなるグループを作りながら取得しておいて、変数で使い回せるようにします。
40行目はルートのグループの下にヨコ線用のシェイプグループをaddします。リネームもします。
var shapeProperty = shapeLyr.property("ADBE Root Vectors Group"); // これにシェイプを追加していく
var shapeGroup1 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup1.name="ヨコ線";43行目、ルートのグループの下に作ったヨコ線用のシェイプグループに「パス」を追加します。このようにAfter Effectsのシェイプレイヤーはプログラム上の構造が入れ子入れ子で非常にややこしいです。しっかりと階層を理解して指定しないとガンガンにエラーを吐いてきますので歯を食いしばりましょう。
スタート位置とエンド位置を結ぶ長方形を、エクスプレッションで描きます。
arHeightが「矢の高さ」で、マイナスの数値にならないように優しさの処理でちょっと長くなっています。if文の省略形である三項演算子を使いました。
arWidthが「矢の太さ」、allWidthが「全体太さ」です。
bfはバッファのことで、CC Bend Itにより描画範囲が少し削られるので、End位置より10px短くシェイプを描くためです。
arBはおしり用の矢印「矢印B」をONにした際に、ヨコ線は矢印の身長分短くしないと突き抜けるので回避用です。また、56行目if文の中で、arHeight(矢の高さ)が無制限に大きくならないよう、制限をかけます。
最後にcreatePathでパスの頂点を4箇所指定し、4つ目の引数で「閉じたパスにするか」をtrueにし描画させます。
/* 長方形パスを3つ準備+エクスプレッションもセットしていく */
var shapePath1 = shapeGroup1.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath1(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n'+
'var bf=[10,0];\r\n'+
'var arB;\r\n\r\n'+
'if(effect("'+efAry[1]+'")(1)==0){\r\n'+
' arHeight=(length(pA,pB)>arHeight)?arHeight:length(pA,pB);\r\n'+
' arB=arHeight;\r\n'+
'}else{\r\n'+
' arB=0;\r\n'+
' arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n'+
'}\r\n\r\n'+
'var p1=-(length(pA,pB)/2)+[arHeight,0];\r\n'+
'var p1a=p1-([0,allWidth]);\r\n'+
'var p1b=p1+([0,allWidth]);\r\n'+
'var p2=(length(pA,pB)/2)-[arHeight,0]+arB;\r\n'+
'var p2a=p2-([0,allWidth]);\r\n'+
'var p2b=p2+([0,allWidth]);\r\n\r\n'+
'createPath(points=[p1a,p2a-bf,p2b-bf,p1b,p1a],[],[],true);';続いてこのヨコ線のグループのトランスフォームで位置と回転にエクスプレッションを追加します。
位置はコンポジションの中央に固定し、回転でStart位置とEnd位置にヨコ線が重なるよう回転させます。createPathの計算を楽にするためにStart座標とEnd座標は左右に伸びる距離としてしか使っていない仕様上、これがないと角度の追従が行われません。
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var pA=effect("CC Bend It")("Start")-anchor;\r\n'+
'var pB=effect("CC Bend It")("End")-anchor;\r\n\r\n'+
'[(pA[0]+pB[0])/2,(pA[1]+pB[1])/2];';
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var pA=effect("CC Bend It")("Start")-anchor;\r\n'+
'var pB=effect("CC Bend It")("End")-anchor;\r\n'+
'var a=(pB-pA);\r\n'+
'var angle=Math.atan2(a[1],a[0]);\r\n\r\n'+
'radiansToDegrees(angle)';89行目からはStart位置に作る三角形「矢印A」です。
これもシェイプグループを追加し、さらにパスを追加します。ヨコ線と同じくエクスプレッションで描画です。
矢印Bがある場合は、101行目~105行目でヨコ線のど真ん中までしか大きくならないように制限をかけています。
var shapeGroup2 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup2.name="矢印A";
var shapePath2 = shapeGroup2.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath2(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n\r\n'+
'if(effect("矢印B")(1)==0){\r\n'+
' arHeight=(length(pA,pB)>arHeight)?arHeight:length(pA,pB);\r\n'+
'}else{\r\n'+
' arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n'+
'}\r\n\r\n'+
'var p1=[0,0];\r\n'+
'var p2a=[arHeight,allWidth+arWidth];\r\n'+
'var p3a=[arHeight,-allWidth-arWidth];\r\n\r\n'+
'createPath(points=[p1,p2a,p3a,p1],[],[],true);';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'effect("CC Bend It")("Start")-anchor;';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'content("ヨコ線").transform.rotation';119行目からはEnd位置に作る三角形「矢印B」です。
矢印Aとほぼ同じですが、ヨコ線に仕掛けた”End位置を10px短くするバッファ”を忘れずに一致させます。
var shapeGroup3 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup3.name="矢印B";
var shapePath3 = shapeGroup3.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Group");
//パス
shapePath3(2).expression=
'var pA=effect("CC Bend It")("Start");\r\n'+
'var pB=effect("CC Bend It")("End");\r\n'+
'var anchor=[thisComp.width/2,thisComp.height/2];\r\n'+
'var arHeight=(effect("'+efAry[2]+'")(1)>0)?effect("'+efAry[2]+'")(1):0;\r\n'+
'var arWidth=(effect("'+efAry[3]+'")(1)>0)?effect("'+efAry[3]+'")(1):0;\r\n'+
'var allWidth=(effect("'+efAry[4]+'")(1)>0)?effect("'+efAry[4]+'")(1):0;\r\n\r\n'+
'var angle2a=degreesToRadians(0);\r\n'+
'arHeight=(length(pA,pB)/2>arHeight)?arHeight:length(pA,pB)/2;\r\n\r\n'+
'var p1=[0,0];\r\n'+
'var p2a=-[arHeight,allWidth+arWidth];\r\n'+
'var p3a=-[arHeight,-allWidth-arWidth];\r\n'+
'var bf=[10,0];\r\n\r\n'+
'if(effect("矢印B")(1)==0){\r\n'+
' p1=p2a;\r\n'+
' p3a=p2a;\r\n'+
'}else{\r\n'+
'}\r\n\r\n'+
'createPath(points=[p1-bf,p2a-bf,p3a-bf,p1-bf],[],[],true);';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'effect("CC Bend It")("End")-anchor;';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'content("ヨコ線").transform.rotation';153行目、あとは3つのパスにまとめて塗りと線を指定できるよう、これらと同じ階層に追加し、エフェクトに追加したエクスプレッション制御から色なり線幅を引っ張ってくるエクスプレッションを追加します。
お疲れ様でございます。







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