FORUMS: list search recent posts

Mutual recursion: this.function is undefined. error.

COW Forums : Adobe After Effects Expressions

<< PREVIOUS   •   FAQ   •   VIEW ALL   •   PRINT   •   NEXT >>
Miguel de Mendoza
Mutual recursion: this.function is undefined. error.
on Sep 3, 2015 at 8:59:21 am

Hello, I'm writing a 'static' class to walk arround Project ítems. I want it to be abstract as posible so I can walk arround layers and properties as needed. The code bellow works for me when no folders are included on the selected item, but when I include a folder, gives me an error: this.crawl is undefined. Someone can see why is this happening?

var proj = app.project;
var Spider = {

crawl : function(callback, object){
for(i = 1; i &lt;= object.numItems; i ++){
subObject = object.item(i);
callback(subObject);
}
},

getName : function(obj){
name = obj.name;
return name;
},

getNames : function(obj){
if(obj instanceof FolderItem){
this.crawl(this.getNames, obj)
}
else{
this.getName(obj);
}
}
}


items = proj.selection[0];

spider.getNames(items)


Return to posts index

Xavier Gomez
Re: Mutual recursion: this.function is undefined. error.
on Sep 3, 2015 at 9:39:16 am

To see what happens, run the script step by step (using the down arrow button instead of the "play" button).

if obj is a folder, this.getNames(folder) will do:

--> this.crawl(this.getNames, folder)
--> for all children of folder, execute handler(child), ie this.getNames(child).
but now, inside this.getNames(child), this is no longer your spider object but the global object.

If you replace everywhere "this" by "spider" it will work.

Xavier


Return to posts index

Miguel de Mendoza
Re: Mutual recursion: this.function is undefined. error.
on Sep 4, 2015 at 8:57:46 am

I see. Thanks for help again Xavier!. I changed 'this' for 'Spider' and don't give me the error, but now seems that the crawl function overwrites itself on the stack on each new call, and don't return to the 'upper level'. I come from C++ and I don't understand how a function can loose his scope inside an object, so I think I need to review scopes in JavaScript :/


Return to posts index


Xavier Gomez
Re: Mutual recursion: this.function is undefined. error.
on Sep 4, 2015 at 10:22:22 am

What would you like it to do exactly ?


Return to posts index

Miguel de Mendoza
Re: Mutual recursion: this.function is undefined. error.
on Sep 4, 2015 at 11:00:58 am

I try to explain:
All my projects start with the same configuration: lots of scenes, vectors and images that need to be precomposed, organized and linked to their own controllers on the top level comps. The footage is organized in their respective folders on my system, so I want to automatically import the project structure from footage folder and create the comps and controls I need, based on that structure and a code system in the footage names (ie: 1.1-Plane_One-Planes.eps, 2.3-Building_B-City_One.png,...), and put all comps in the correct folder on the project.

That said, one of the common tasks I have to do is to walk over several tree structures: folders, Project ítems, layers and properties, and my idea was to make a prototype of recurisive function to do the walk, and adapt it for each access type.

I hope it is understandable XD


Return to posts index

Xavier Gomez
Re: Mutual recursion: this.function is undefined. error.
on Sep 5, 2015 at 5:29:50 pm
Last Edited By Xavier Gomez on Sep 5, 2015 at 5:40:29 pm

It's possible to give a uniform treatment to layers and items since they belong to a collection, but there is no seach thing as a PropertyCollection, so that properties/propertyGroups would have to be handled differently.

For instance i do use something like your spider object, and it is organized like this:

var $coll = {

forEach : function forEach(coll, callback){
var n, N=coll.length;
for (n=1; n<=N; n++){
callback(coll[n], n, coll);
};
return;
},

find : function find(coll, filter){
var n, N=coll.length;

if (filter(coll[n], n, coll)) return coll[n];
},
return null;
},

indexOf : function indexOf(coll, x){
var n, N=coll.length;
for (n=1; n<=N; n++){
if (coll[n]==x) return n;
},
return 0;
},

// etc,, etc
};


So $coll.forEach would be the equivalent of your spider.crawl
I find it usefull too, so you can write things like :

var footageFolder = $coll.find(app.project.items, function(element, index, collection){return element.name === "Footage" && element.typeName === "Folder";}) || app.project.items.addFolder("Footage");

(this searches a folder called "Footage" and creates it if not found).

But as soon as recursions are involved i found it a lot clearer to write full code, since there are many ways to recurse through a folder architecture.

Here is a very basic starting block to import and then create.
It only import basic footage (image, video) and creates comps at a fixed size/duration (not based on content!).
It would require quite a lot of work to turn it ito what you actually want, but it can help to start with:


function recursiveImport(sysFolder, aeFolder){
// create a AE folder and parent it to aeFolder:
var folder = app.project.items.addFolder(sysFolder.name);
folder.parentFolder = aeFolder || app.project.rootFolder;

var files = sysFolder.getFiles();
var n, N=files.length;

for (n=0; n<=N; n++){
if (files[n] instanceof Folder){
recursiveImport(files[n], folder);
}
else{
try{app.project.importFile(new ImportOptions(files[n])).parentFolder = folder;}catch(e){};
};
};
return folder;
};

function recursiveCreate(aeFootageFolder, aeCompFolder, compSpec){

var N=aeFootageFolder.items.length, n, item;

var comp = aeCompFolder.items.addComp(aeFootageFolder.name, compSpec.width, compSpec.height, compSpec.pixelAspect, compSpec.duration, compSpec.frameRate);

for (n=N; n>0; n--){
item = aeFootageFolder.items[n];
if (item instanceof FolderItem){
comp.layers.add(recursiveCreate(item, aeCompFolder.items.addFolder(item.name), compSpec));
}
else{
comp.layers.add(item);
};
};
return comp;
};

(function(){

var sysFolder = Folder.selectDialog();
if (!sysFolder) return;

var allFootageFolder = $coll.find(app.project.items, function(element, index, collection){return element.name === "Footage" && element.typeName === "Folder";}) || app.project.items.addFolder("Footage");
var thisFootageFolder = recursiveImport(sysFolder, allFootageFolder);

var allCompFolder = $coll.find(app.project.items, function(element, index, collection){return element.name === "Comps" && element.typeName === "Folder";}) || app.project.items.addFolder("Comps");
var thisCompFolder = allCompFolder.items.addFolder(thisFootageFolder.name);
var compSpec = {
width : 1280,
height : 720,
pixelAspect : 1.0,
duration : 10,
frameRate : 25
};

recursiveCreate(thisFootageFolder, thisCompFolder, compSpec);

return;

})();


Xavier.

Edit: tried to correct the <= bugs, if failed again i give up.


Return to posts index


Miguel de Mendoza
Re: Mutual recursion: this.function is undefined. error.
on Sep 7, 2015 at 4:02:39 pm

Wow! That's awesome! I looks pretty good. I have an overflowed week so I will paly arround with it this weekend. Thanks for help Xavier!


Return to posts index

<< PREVIOUS   •   VIEW ALL   •   PRINT   •   NEXT >>
© 2017 CreativeCOW.net All Rights Reserved
[TOP]