コンポジションのツリー構造を得る
コンポべての尺を伸ばす場合、Durationを変更して必要なレイヤーのoutPointに新しい値を渡す必要がある。
平面やタイムリマップされているものであれば自由にoutPointを渡せるのだが、コンポだとまず先にそのコンポに入っているコンポからDurationを変更してからoutPointを渡す必要がある
この例の場合、cameraコンポを2秒から4秒にしたい場合、先にcompositコンポを4秒に変えておかないといけない。
これを調べるスクリプトを書いてみる。
先頭から全レイヤーを調べるのも良さげだが、レイヤーの数によって動作が遅くなると思われることや、レイヤーの中では同じコンポを使用できるので、それらの判別もめんどくさそうである。
usedInという、どこのコンポで使われているかという値が初めからあるので、それを繰り返し使用して順番を決定することにする。
例ではこのようになるのだが、shakeコンポはoutput1の次でもあるが、filterコンポの次でもある。
filterコンポはoutput1の次のコンポであるので、shakeコンポはこのツリーにおいて3番目のコンポであるということになる。
shakeコンポを評価する前にfilterコンポとoutputコンポの順序が決定されていればよいのだが、コンポの名前によってその評価の順番が変わってしまう。
usedInが無いものは先頭だということがすぐにわかるので、まずはusedInの無いoutput1に順番をつける。
filterコンポのusedInはoutput1コンポだけなのでそのままoutput1コンポの順番に1足したものを自分の順番にしてよい。
shakeコンポのusedInはfilterコンポとoutput1コンポである。
filterコンポが先に評価されている場合、前述の通りoutput1コンポの次のコンポだということが決定されているので、usedIn2つとも順番が決定されている。
filterコンポより先に評価される場合、filterコンポの順番がわからないのでoutput1コンポの次のコンポかどうかはわからない。
よって、評価するコンポの順番を決定するにはusedIn先のコンポすべての順番が決定されている必要がある。
また、usedIn先が複数の場合、大きな順番のほうを得て、自分をその次の順番とするためデータをマージする必要もある。
複数のツリー構造に置いても同じ理論が言えるため、それらをすべてのコンポの順番が決定されるまで繰り返すことで、複数ルートとそのルートにおける自分自身の順番が決定されることになる。
拙作スクリプトにおいて、評価されたデータの値は直接[object CompItem]に付加することにした
複数ルートがある場合はtree配列に複数格納される
とりあえず動く版ソース
このままでは扱いづらいと思うので後に修正する
/*
GetNestingCompsDepth
コンポジションのツリー構造を調べて値を[object CompItem]に割り当てる
[object CompItem].tree 配列に「どのコンポを基にしているか」、「そのコンポからの順番」の値を割り当てる
[object CompItem].tree[0].root = [object CompItem]
[object CompItem].tree[0].depth = [object CompItem].tree[0].rootから何番目か
*/
Project.prototype.comps = function(){
var n = [];
for(var i=1;i<=app.project.numItems;i++){
if(app.project.item(i) instanceof CompItem){
n[n.length] = app.project.item(i);
}
}
return n;
}();
function allDepthChecker(comps){
var flag=1;
for(var i=0;i<comps.length;i++){
for(var j=0;j<comps[i].tree.length;j++){
flag = flag*comps[i].tree[j].depth + "\r";
}
}
return (flag!=0)?true:false;
}
function makeCompDepth(comp){
var data = [];
for(var i=0;i<comp.usedIn.length;i++){
for(var j=0;j<comp.usedIn[i].tree.length;j++){
data[data.length] = comp.usedIn[i].tree[j];
}
}
var key = "root";
var len=data.length,count={},dst=[];
for(var i=0;i<len;i++){
if(!count[data[i][key].id]){
dst[dst.length] = {root:data[i].root,depth:data[i].depth};
count[data[i][key].id]=data[i].depth;
}else{
if(count[data[i][key].id]<data[i].depth){
count[data[i][key].id] = data[i].depth;
for(var j=0;j<dst.length;j++){
if(data[i].root.id==dst[j].root.id){
dst[j].depth = data[i].depth;
}
}
}
}
}
var flag = 1;
for(var i=0;i<dst.length;i++){
flag = flag*dst[i].depth;
}
flag = (flag!=0)?true:false;
if(flag){
return dst;
}else{
return false;
}
}
function makeTreeComp(){
var comp =app.project.comps;
var root = [];
for(i=0;i<comp.length;i++){
comp[i].tree = [{root:"",depth:0}];
if(comp[i].usedIn==""){
comp[i].tree = [{root:comp[i],depth:1}];
root[root.length] = comp[i];
}
}
while(!allDepthChecker(comp)){
for(var i=0;i<comp.length;i++){
if(comp[i].tree[0].depth==0){
var data = makeCompDepth(comp[i]);
if(data){
comp[i].tree = [];
for(var j=0;j<data.length;j++){
comp[i].tree[comp[i].tree.length] = {root:data[j].root,depth:data[j].depth+1};
}
}else{
comp[i].tree = [{root:"",depth:0}];
}
}
}
};
}