コンポジションのツリー構造を得る

コンポべての尺を伸ばす場合、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}];

}

}

}

};

}