Animating a mask success

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
edwinbradford
Posts: 1
Joined: November 1st, 2008, 7:02 am

Hi all,

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 :oops: but it works :o . "Panel fill" is the referenced composition defining the mask area, "Bonus pawn accuracy" is the composition to be masked. I wrote the script so that as I add more comps to the project it won't break the composition referencing but I hard coded the layer index numbers. I find it strange that you can't just scale and transform a mask separate from its layer as you would any other shape, unless I've misunderstood. Anyway, hope its of interest. This site has been a real help.

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");
Post Reply