Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Script question

  • Posted by Mike Park on August 11, 2010 at 3:33 pm

    While I know this is really not an expression question per se, I thought this would be the best place to post.

    I am trying to cobble together a script to duplicate a selected layer and then automatically link all possible animatable parameters of not only the layer, but also any effects applied. Basically, I want to duplicate the layer and have all parameters linked via expressions to the original layer…kind of like a master and slave. That way, any changes in the master would drive the same changes in the slave. I have been reviewing many different scripts which do various pieces of this, but have not been able to put it all together. Is there already a script to do this out there, or is there a simpler way to accomplish this without manually linking all parameters?

    thanks in advance for the help

    Mike Park

    Dan Ebberts replied 15 years, 9 months ago 2 Members · 14 Replies
  • 14 Replies
  • Dan Ebberts

    August 11, 2010 at 4:20 pm

    I don’t know that I’ve seen a script that does exactly that. If there isn’t one out there it would be a bit of work to set up, but definitely do-able. I think the key would be a recursive property handling function that puts the property’s name on a stack and calls itself until it gets down to a property that’s not a named or indexed group, checks to see if the property can accept expressions, then uses the names on the stack to construct the appropriate expression. Something like that. Probably not something you’d want to tackle if you haven’t done much scripting.

    Dan

  • Mike Park

    August 11, 2010 at 5:31 pm

    thanks for responding, Dan.

    Chris Keller wrote a script which kind of accomplishes this. In his script, he duplicates an enitre composition and offsets it for use with rb sterioscopic glasses. However the code I am interested in does what you are saying. It recursively goes through all properties of the layers and links them to the main comp. I want to port this so that I can simply do it to one layer. I have some programming knowledge from a long time ago in college (Fortran and C+) but am only starting to wade through Javascript. I will post the particular section from his free script in the box. Is this way more complicated than I am thinking?

    Thanks,

    Mike

    // Recursively goes through all properties and links them to the main comp
    function converterProcessExpressions(parentProperty, propertyName)
    {
    if (parentProperty != null)
    {
    for (var i = 1; i <= parentProperty.numProperties; ++i)
    {
    var property = parentProperty.property(i);

    if (property.propertyType == PropertyType.PROPERTY && property.canSetExpression)
    {
    try
    {
    if (property.enabled)
    {
    property.expression = propertyName + "("" + property.matchName + "")";
    property.expressionEnabled = true;
    }
    } catch (e) {}
    }
    else if ((property.propertyType == PropertyType.INDEXED_GROUP) || (property.propertyType == PropertyType.NAMED_GROUP))
    converterProcessExpressions(property, propertyName + "("" + property.name + "")");
    }
    }
    }

    // -----------------------------------------------------------------------------------------------------------------------------

  • Dan Ebberts

    August 11, 2010 at 6:06 pm

    Yeah, that looks more efficient than what I was thinking. It looks like it builds the property name as it descends through the hierarchy. I think that’s most of what you need.

    Dan

  • Mike Park

    August 11, 2010 at 7:37 pm

    Dan,

    Did they change the ability to use activeItem in CS5? It is throwing me an error everytime I try to use it to create a variable in the script.

    var myComp = app.project.activeItem;

  • Dan Ebberts

    August 11, 2010 at 7:39 pm

    As far as I know, it hasn’t changed. The comp does need to be selected.

    Dan

  • Mike Park

    August 11, 2010 at 8:59 pm

    Alright Dan, I am driving myself crazy with this. I can duplicate the layers in the comp, but only want to duplicate selected layers. I cannot figure out the proper syntax for this. Any help would be appreciated.

    thanks,
    Mike

  • Dan Ebberts

    August 11, 2010 at 9:08 pm

    Like this:


    var mySelected = app.project.activeItem.selectedLayers;
    for (var i = 0 ; i < mySelected.length; i++){
    mySelected[i].duplicate();
    }

    Dan

  • Mike Park

    September 21, 2010 at 7:59 pm

    Alright Dan,

    I have poured over this code and looked at the reference material, and still cant get this to work right. Sorry I have to bug you about this, but I dont know where to go from here. The code below (using your help above) successfully duplicates all selected layers. However, when the loop runs through the expression link section, it doesnt do anything. what am I missing? I really appreciate all the help. This will be quite the handy expression for duplicating a bunch of layers where you want all the attributes to track the changes in the other layers, especially for things like Particular.

    {
    // create an undo group
    app.beginUndoGroup("Clone_and_link");

    var mySel = app.project.activeItem.selectedLayers;

    // duplicate layer
    for (var s = 0; s &lt; mySel.length; s++){
    mySel[s].duplicate();

    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    // add function to turn on all possible expressions and link to first layer;
    function converterProcessExpressions(parentProperty, propertyName)
    {
    if (parentProperty != null) //if parentProperty is something, then
    {
    for (var i = 1; i &lt;= parentProperty.numProperties; i++) // increment for every property
    {
    var property = parentProperty.property(i); // put value of new property as value of old property

    if (property.propertyType == PropertyType.PROPERTY && property.canSetExpression) // test to see if property can be picwipped
    {
    try
    {
    if (property.enabled) // if the property is enabled
    {
    property.expression = propertyName + "("" + property.matchName + "")"; // set up expression to exact match of other layer
    property.expressionEnabled = true; // enable expression
    }
    } catch (e) {} // catch everything else
    }
    else if ((property.propertyType == PropertyType.INDEXED_GROUP) || (property.propertyType == PropertyType.NAMED_GROUP))
    converterProcessExpressions(property, propertyName + "("" + property.name + "")");
    }
    }
    }

    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    }
    // close the undo group
    app.endUndoGroup();
    }

  • Dan Ebberts

    September 21, 2010 at 8:18 pm

    For one thing, it looks like the lines that create the expressions have too many double quotes. I’d debug something like this with the ExtendScript debugger using breakpoints. If you don’t know how to do that, it’s worth learning. Another thing you can do is comment out the try/catch statements to see if it is in fact the expressions that are failing.

    Dan

  • Mike Park

    October 12, 2010 at 7:52 pm

    Ok Dan,

    I am almost there. But now, the function is throwing me an “undefined” in the middle of my expression. I am not sure what the problem is. Otherwise, it appears to work. Any thoughts? Thanks again for the help.

    {
    // create an undo group
    app.beginUndoGroup("Slave")
    clearOutput();
    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    // add function to turn on all possible expressions and link to first layer;

    function LinkAll(parentProperty, propertyName)
    {
    if (parentProperty != null) //if parentProperty is something, then
    {
    for (var i = 1; i &lt;= parentProperty.numProperties; i++) // increment for every property
    {
    var property = parentProperty.property(i); // put value of new property as value of old property

    if (property.propertyType == PropertyType.PROPERTY && property.canSetExpression) // test to see if property can be picwipped
    {
    try
    {
    if (property.enabled) // if the property is enabled
    {
    property.expression = "thisComp.layer" + "("" + mySel[s].name + "")" + propertyName + "("" + property.matchName + "")"; // set up expression to exact match of other layer
    property.expressionEnabled = true; // enable expression
    }
    } catch (e) {} // catch everything else
    }
    else if ((property.propertyType == PropertyType.INDEXED_GROUP) || (property.propertyType == PropertyType.NAMED_GROUP))
    LinkAll(property, propertyName + "("" + property.name + "")");
    }
    }
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    // check to see that a layer is selected
    var mySel = app.project.activeItem.selectedLayers;
    if (mySel &lt; 1){
    alert("Please select one or more layers and try again.", "No Layers Selected");
    }
    else
    // Display number of layers duplicated in info panel
    write("Number of Layers duplicated = ");
    writeLn(mySel.length);

    // duplicate layer(s) by increments
    for (var s = 0; s &lt; mySel.length; s++){
    mySel[s].duplicate();
    LinkAll (mySel[s]);
    mySel[s].name = mySel[s].name + " Linked";
    mySel[s].locked = true;

    }
    // close the undo group
    app.endUndoGroup();
    }

Page 1 of 2

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy