I'm new to After Effects but I thought I'd post a script I just completed to get your feedback and in case anyone's interested. I'm not a good coder but I managed this in a couple of days with a lot of reading, in this forum, especially. I needed to solve a problem, my animation contained two shapes as compositions "A" and "B" animated above each other, but "A" needed a mask that followed the outline of shape "B" (which happened to be a scaling rectangle). Its something I could do simply in Flash.
Anyhow by referencing other people's scripts here I managed it. As I understand it you can't animate a Mask's co-ordinates as I needed with expressions, it has to be done with a script. When I run this script it generates a mask as a series of keyframes for every frame in which the referenced shape "B" has changed along the time line.
Its a bit clumsy, I wasn't quite sure when to declare variables with var and I'm sure my "for loop" could be simplified


Code: Select all
// Find the source and destination composition index numbers by name search;
var index_01 = 0;
var index_02 = 0;
function projectItem(name_01, name_02) {
var items = app.project.items;
for (i=1; i<=items.length; i++) {
if (items[i].name == name_01) {
index_01 = (i);
break;
}
}
for (i=1; i<=items.length; i++) {
if (items[i].name == name_02) {
index_02 = (i);
break;
}
}
}
projectItem("Panel fill", "Bonus pawn accuracy");
// Find reference and destination layer start and end times
var layerStart = app.project.item(index_02).layer(2).inPoint;
var layerEnd = app.project.item(index_02).layer(2).outPoint;
var sourceLayerStart = app.project.item(index_02).layer(3).inPoint;
// Offset, fixed value according to the graphic and comp used
var offset_x = 272;
var offset_y = 272;
// Use the index variable above
// Access the array values with .value (scale has 3 values)
// Get the scale of the source graphic at time zero
var scaleWidth = app.project.item(index_01).layer(1).scale.valueAtTime(0, false)[0];
var scaleHeight = app.project.item(index_01).layer(1).scale.valueAtTime(0, false)[1];
// Use the scale and offset to work out the co-ordinates of the source graphic
// Panel is 94px at 100% so multiple factor is 94 / 2
var vertex_01 = [(-scaleWidth + offset_x)*0.47, (-scaleHeight + offset_y)*0.47];
var vertex_02 = [(-scaleWidth + offset_x)*0.47, (scaleHeight + offset_y)*0.47];
var vertex_03 = [(scaleWidth + offset_x)*0.47, (scaleHeight + offset_y)*0.47];
var vertex_04 = [(scaleWidth + offset_x)*0.47, (-scaleHeight + offset_y)*0.47];
// Create the mask parameters
newMask = app.project.item(index_02).layer(2).Masks.addProperty("ADBE Mask Atom");
newMask.maskMode = MaskMode.ADD;
myProperty = newMask.property("ADBE Mask Shape");
myShape = myProperty.value;
myShape.vertices = [vertex_01, vertex_02, vertex_03, vertex_04];
myShape.closed = true;
// Mask from the destination layers inPoint to outPoint.
// Frames per second is 30
var FPS = 30;
for (i=(layerStart-sourceLayerStart)*FPS; i<=(layerEnd-sourceLayerStart)*FPS; i++) {
scaleWidth = app.project.item(index_01).layer(1).scale.valueAtTime(i/FPS, false)[0];
previousWidth = app.project.item(index_01).layer(1).scale.valueAtTime((i/FPS)-1/FPS, false)[0];
nextWidth = app.project.item(index_01).layer(1).scale.valueAtTime((i/FPS)+1/FPS, false)[0];
scaleHeight = app.project.item(index_01).layer(1).scale.valueAtTime(i/FPS, false)[1];
previousHeight = app.project.item(index_01).layer(1).scale.valueAtTime((i/FPS)-1/FPS, false)[1];
nextHeight = app.project.item(index_01).layer(1).scale.valueAtTime((i/FPS)+1/FPS, false)[1];
vertex_01 = [(-scaleWidth + offset_x)*0.47, (-scaleHeight + offset_y)*0.47];
vertex_02 = [(-scaleWidth + offset_x)*0.47, (scaleHeight + offset_y)*0.47];
vertex_03 = [(scaleWidth + offset_x)*0.47, (scaleHeight + offset_y)*0.47];
vertex_04 = [(scaleWidth + offset_x)*0.47, (-scaleHeight + offset_y)*0.47];
myShape.vertices = [vertex_01, vertex_02, vertex_03, vertex_04];
// Draw a shape mask only if the source scale changes
// Account for the sourceLayer not starting at zero on the timeline
if (scaleWidth != previousWidth || scaleWidth != nextWidth || scaleHeight != previousHeight || scaleHeight != nextHeight) {
myProperty.setValueAtTime((i+(sourceLayerStart*FPS))/FPS, myShape);
}
}
//alert("test");