Activity › Forums › Adobe After Effects Expressions › Script question
-
Script question
Posted by Mike Park on August 11, 2010 at 3:33 pmWhile 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 pmI 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 pmthanks 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 pmYeah, 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 pmDan,
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 pmAs far as I know, it hasn’t changed. The comp does need to be selected.
Dan
-
Mike Park
August 11, 2010 at 8:59 pmAlright 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 pmLike 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 pmAlright 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 < 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 <= parentProperty.numProperties; i++) // increment for every property
{
var property = parentProperty.property(i); // put value of new property as value of old propertyif (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 pmFor 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 pmOk 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 <= parentProperty.numProperties; i++) // increment for every property
{
var property = parentProperty.property(i); // put value of new property as value of old propertyif (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 < 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 < 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();
}
Reply to this Discussion! Login or Sign Up