This will take a mask that you have drawn on a solid and add some effects to it to highlight a particular object. See below for details:
/************************************************************
To use:
Create a new solid of any color
Select the pen tool and draw a mask with as many points as necessary
Run the script
The script will:
Set the solid layer to white color
Add keyframes for the mask opacity to flash in and then fade out
Add a stroke for the mask
Add an Echo effect
Add keyframes for the mask shape
You must then go to the first mask shape keyframe and scale the mask shape up by double clickingon a point and draging the mouse out while holding CTRL and SHIFT
You can then:
Change the color of the stroke
Change the timing of the keyframes
Change the color of the solid if necessary
Anything else that strikes your fancy
***************************************************************/
var initialLayer = null;
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a composition before running this script");
}
else
{
var selectedLayers = activeItem.selectedLayers;
if (selectedLayers.length > 0 )
{
DoWork(selectedLayers[0]);
}
else
{
alert("You must select a layer with a closed mask.");
}
}
function DoWork(initialLayer)
{
app.beginUndoGroup("Generate Mask Echo Effect");
if(initialLayer.property("mask").numProperties > 0)
{
var initialMask = initialLayer.mask(1);
initialLayer.source.mainSource.color = [1,1,1];
var point1, point2, point3, point4;
var vertsArray = initialMask.maskShape.value.vertices;
var maskShape = initialMask("Mask Shape");
var initialShapeKey = maskShape.addKey(initialLayer.inPoint);
var secondShapeKey = maskShape.addKey(initialLayer.inPoint+6/12);
var maskOpacity = initialMask("Mask Opacity");
var initialOpacKey = maskOpacity.addKey(initialLayer.inPoint+5/12);
var secondOpacKey = maskOpacity.addKey(initialLayer.inPoint+6/12);
var thirdOpacKey = maskOpacity.addKey(initialLayer.inPoint+11/12);
maskOpacity.setValueAtKey(1, 0);
maskOpacity.setValueAtKey(2, 80);
maskOpacity.setValueAtKey(3, 0);
var opacityProp = initialLayer("Opacity");
var initialOpacKeyframe = opacityProp.addKey(initialLayer.inPoint+12/12);
var secondOpacKeyframe = opacityProp.addKey(initialLayer.inPoint+18/12);
opacityProp.setValueAtKey(1,100);
opacityProp.setValueAtKey(2,0);
initialLayer.outPoint = initialLayer.inPoint+24/12;
var stroke = initialLayer("Effects").addProperty("Stroke");
stroke.allMasks.setValue(1);
var echo = initialLayer("Effects").addProperty("Echo");
echo(1).setValue(-.04);
echo(2).setValue(4);
echo(3).setValue(1);
echo(4).setValue(.55);
return;
}
app.endUndoGroup();
}
*/
This will take a 3-point mask drawn on a layer, add some effects to it, and animate it so the result is a label that animates in. See below for details:
/************************************************************
To use:
Create a new solid of any color
Select the pen tool and draw three points on the solid:
The first 2 points should be horizontal
The 3rd point should be the ending point (what you want to point to)
Run the script
The script will:
Add a second mask which is the dot for the pointer
Add a yellow stroke and a drop shadow to the layer
Animate the masks starting at the first point and ending at the 3rd point
Add easing to the keyframes
Set the opacity on the layer to 100
Change the name of the layer and the solid to "Animated Pointer Layer"
You can then:
Change the color of the stroke
Change the timing of the keyframes
Anything else that strikes your fancy
***************************************************************/
var initialLayer = null;
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a composition before running this script");
}
else
{
var selectedLayers = activeItem.selectedLayers;
app.beginUndoGroup("Generate animated pointer");
if (selectedLayers.length > 0 )
{
DoWork(selectedLayers[0]);
}
else
{
alert("You must select a layer to add the mask to.");
}
app.endUndoGroup();
}
function DoWork(initialLayer)
{
if(initialLayer.property("mask").numProperties > 0)
{
var initialMask = initialLayer.mask(1);
var point1, point2, point3;
var vertsArray = initialMask.maskShape.value.vertices;
if(vertsArray.length == 3)
{
point1 = vertsArray[0];
point2 = vertsArray[1];
point3 = vertsArray[2];
var np1,np2,np3,np4;
var x = point3[0];
var y= point3[1];
var radius = 3;
np1 = new Array([x], [y+radius]);
np2 = new Array([x-radius], [y]);
np3 = new Array([x], [y-radius]);
np4 = new Array([x+radius], [y]);
newMask = initialLayer.Masks.addProperty("Mask");
myMaskShape = newMask.property("maskShape");
myShape = myMaskShape.value;
myShape.vertices = [np1,np2,np3,np4];
var startTime = initialLayer.inPoint;
myMaskShape.setValueAtTime(startTime+1, myShape);
var firstMask = initialLayer.mask(1);
initialMaskShape = firstMask.maskShape;
iShape = initialMaskShape.value;
iShape.vertices = [point1,point2,point3];
initialMaskShape.setValueAtTime(startTime+1,iShape);
var xDiff = point3[0]-point2[0];
var yDiff = point3[1]-point2[1];
var tp1 = new Array([np1[0]-xDiff],[np1[1]-yDiff]);
var tp2 = new Array([np2[0]-xDiff],[np2[1]-yDiff]);
var tp3 = new Array([np3[0]-xDiff],[np3[1]-yDiff]);
var tp4 = new Array([np4[0]-xDiff],[np4[1]-yDiff]);
var shapeTween = new Shape();
shapeTween.vertices = [tp1,tp2,tp3,tp4];
myMaskShape.setValueAtTime(startTime+.5, shapeTween);
iShape.vertices = [point1,point2,point2];
initialMaskShape.setValueAtTime(startTime+.5,iShape);
xDiff = point2[0]-point1[0];
yDiff = point2[1]-point1[1];
tp1 = new Array([tp1[0]-xDiff],[tp1[1]-yDiff]);
tp2 = new Array([tp2[0]-xDiff],[tp2[1]-yDiff]);
tp3 = new Array([tp3[0]-xDiff],[tp3[1]-yDiff]);
tp4 = new Array([tp4[0]-xDiff],[tp4[1]-yDiff]);
shapeTween = new Shape();
shapeTween.vertices = [tp1,tp2,tp3,tp4];
myMaskShape.setValueAtTime(startTime,shapeTween);
iShape.vertices = [point1,point1,point1];
initialMaskShape.setValueAtTime(startTime,iShape);
var ease = new KeyframeEase(0, 50);
initialMaskShape.setTemporalEaseAtKey(1, [ease], [ease]);
initialMaskShape.setTemporalEaseAtKey(2, [ease], [ease]);
initialMaskShape.setTemporalEaseAtKey(3, [ease], [ease]);
myMaskShape.setTemporalEaseAtKey(1, [ease], [ease]);
myMaskShape.setTemporalEaseAtKey(2, [ease], [ease]);
myMaskShape.setTemporalEaseAtKey(3, [ease], [ease]);
if(initialLayer("Effects").canAddProperty("Stroke"))
{
var stroke = initialLayer("Effects").addProperty("Stroke");
stroke.allMasks.setValue(1);
stroke.color.setValue([1,1,0]);
}
if(initialLayer("Effects").canAddProperty("Drop Shadow"))
{
var ds = initialLayer("Effects").addProperty("Drop Shadow");
ds.distance = 4;
ds.softness = 3;
}
initialLayer.property("Opacity").setValue(100);
initialLayer.source.mainSource.color = [1,1,0];
initialLayer.name = "Animated Pointer Layer";
initialLayer.source.name = "Animated Pointer Layer";
}
}
else
{
alert("No mask on selected layer.");
}
}
The following script is nothing fancy, but helps increase workflow by putting several common tasks together. This will animate a layer from a scale of 0,0 to its current size, with a nice bounce effect. See details below:
/************************************************************
To use:
Run script for any layer
The script will:
Set a 0,0 scale keyframe at the inpoint of the layer
Animate the scale to the current size with a little bounce at the end
Turn motion blur on for the layer
Turn motion blur on for the composition (if it isn't already on)
If the layer has a mask on it, it will re-center the layer's anchor point so that it scales-in evenly
You can then:
Change the timing of the keyframes
Change the amount of "bump" by tweaking the scale values
Move the anchor point as needed
Anything else you may need
***************************************************************/
function fadeLayer(myLayer)
{
//If there is a mask, reset the anchor point
if(myLayer.property("mask").numProperties > 0)
{
var initialMask = myLayer.mask(1);
var point1, point2, point3, point4;
var vertsArray = initialMask.maskShape.value.vertices;
if(vertsArray.length == 4)
{
point1 = vertsArray[0];
point2 = vertsArray[1];
point3 = vertsArray[2];
point4 = vertsArray[3];
var maskWidth = Math.abs(vertsArray[0][0] - vertsArray[1][0]);
var maskHeight = Math.abs(vertsArray[1][1] - vertsArray[2][1]);
ap1 = point2[0]+maskWidth/2;
ap2 = point2[1]+maskHeight/2;
pArray = new Array(ap1, ap2);
var diffPoint = pArray - myLayer.property("Anchor Point").value;
myLayer.property("Anchor Point").setValue(pArray);
myLayer.property("Position").setValue(myLayer.property("Position").value+diffPoint);
}
}
myProp = myLayer.property("Scale");
inPoint = myLayer.inPoint;
outPoint = inPoint + (8/12);
bouncePoint = inPoint + (6/12);
outKey = myProp.addKey(outPoint);
myProp.setValueAtKey(outKey, myProp.value);
bounceKey = myProp.addKey(bouncePoint);
myProp.setValueAtKey(bounceKey, myProp.value*1.05);
inKey = myProp.addKey(inPoint);
myProp.setValueAtKey(inKey, [0,0]);
var ease = new KeyframeEase(0, 33);
myProp.setInterpolationTypeAtKey(1,5013);
myProp.setInterpolationTypeAtKey(2,5013);
myProp.setInterpolationTypeAtKey(3,5013);
myLayer.motionBlur = true;
}
// make sure a comp is selected
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a layer before running this script");
}
else
{
// make sure at least one layer is selected
var selectedLayers = activeItem.selectedLayers;
if (selectedLayers.length == 0 )
{
alert("Select at least one layer before running this script.");
}
else
{
app.beginUndoGroup("Scale Layer 0 to current with bounce");
selectedLayers[0].containingComp.motionBlur = true;
for(i=0; i<selectedLayers.length; i++)
{
fadeLayer(selectedLayers[i]);
}
app.endUndoGroup();
}
}
This script takes a layer with a round mask on it, and adds a stroke (set to paint on transparent) and a drop shadow. It sets the pivot point to the center of the mask. It adds keyframes to animate the stroke so the circle animates in and then extends with a little stub on the right. The drop shadow's direction is set to an expression so you can rotate the stub to any direction and the shadow is still looking good. It's harder than I thought to describe it, so check out the attached video for a quick sample.
//Make mask into circling pointer thing
var initialLayer = null;
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a composition before running this script");
}
else
{
var selectedLayers = activeItem.selectedLayers;
if (selectedLayers.length > 0 )
{
DoWork(selectedLayers[0]);
}
else
{
alert("You must select a layer to add the mask to.");
}
}
function DoWork(initialLayer)
{
app.beginUndoGroup("Generate encirlcing mask");
if(initialLayer.property("mask").numProperties > 0)
{
var initialMask = initialLayer.mask(1);
var point1, point2, point3, point4;
var vertsArray = initialMask.maskShape.value.vertices;
if(vertsArray.length == 4)
{
point1 = vertsArray[0];
point2 = vertsArray[1];
point3 = vertsArray[2];
point4 = vertsArray[3];
pArray = new Array(point1[0], point2[1]);
var circumference = (22/7)*(point1[1]-point3[1]);
var stubLength = 30;
var circleEndPercent = (stubLength/circumference*100)+100;
initialLayer.property("Anchor Point").setValue(pArray);
initialLayer.property("Position").setValue(pArray);
initialLayer.property("Rotation").setValue(90);
var newPoint1 = [point1[0], point1[1]-stubLength];
newMask = initialLayer.Masks.addProperty("Mask");
newMask.inverted = false;
myMaskShape = newMask.property("maskShape");
myShape = myMaskShape.value;
myShape.vertices = [point1,newPoint1];
myShape.closed = false;
myMaskShape.setValue(myShape);
if(initialLayer("Effects").canAddProperty("Stroke"))
{
var stroke = initialLayer("Effects").addProperty("Stroke");
stroke.allMasks.setValue(1);
var endProp = stroke.end;
var startTime = initialLayer.inPoint;
endProp.setValueAtTime(startTime,0);
endProp.setValueAtTime(startTime+.5, circleEndPercent);
endProp.setValueAtTime(startTime+1, 100);
endProp.setInterpolationTypeAtKey(1,5013);
endProp.setInterpolationTypeAtKey(2,5013);
endProp.setInterpolationTypeAtKey(3,5013);
var ease = new KeyframeEase(0, 33);
endProp.setTemporalEaseAtKey(1, [ease], [ease]);
endProp.setTemporalEaseAtKey(2, [ease], [ease]);
endProp.setTemporalEaseAtKey(3, [ease], [ease]);
stroke.paintStyle.setValue(2);
}
if(initialLayer("Effects").canAddProperty("Drop Shadow"))
{
var ds = initialLayer("Effects").addProperty("Drop Shadow");
ds.distance = 5;
ds.softness = 3;
ds.direction.expression = '(transform.rotation*-1)+135';
}
initialLayer.property("Opacity").setValue(100);
initialLayer.motionBlur = true;
}
}
else
{
alert("No mask on selected layer.");
}
app.endUndoGroup();
}
This script will take a text layer with multiple lines, and create a new range selector. It will create keyframes that incrementally select each line of text. We use this a lot for animating lists and things. You can than easily apply properties to the selector.
/*********************************************/
// make sure a comp is selected
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a layer before running this script");
}
else
{
// make sure at least one layer is selected
var selectedLayers = activeItem.selectedLayers;
if (selectedLayers.length != 1 )
{
alert("Select one layer before running this script.");
}
else
{
app.beginUndoGroup("Create Text Selector");
for(i=0; i<selectedLayers.length; i++)
{
//If Text layer
var theTextLayer = selectedLayers[i];
CreateTextSelector(theTextLayer);
}
app.endUndoGroup();
}
}
function CreateTextSelector(theTextLayer)
{
var lineCount = 1;
var layerText = String(theTextLayer.text.sourceText.value);
for(i=0; i<=layerText.length; i++)
{
if(layerText.charCodeAt(i) == 13)
lineCount++;
}
var theTextProperties = theTextLayer.property("ADBE Text Properties");
var theAnimators = theTextProperties.property("ADBE Text Animators");
// add a Text Animator property to control the highlight style
var highlightAnimator = theAnimators.addProperty("ADBE Text Animator");
var highlightSelectors = highlightAnimator.property("ADBE Text Selectors");
// add a Range Selector property to control the highlight timing
var highlightSelector = highlightSelectors.addProperty("ADBE Text Selector");
// define the range selector's Advanced (7) property group
var advancedSelector = highlightSelector.property("ADBE Text Range Advanced");
// define the Advanced property group's Unit (1) property and set to Index (percentage = 1, index = 2)
var unitsProperty = advancedSelector.property("ADBE Text Range Units");
unitsProperty.setValue(2);
// base sur ligne
var basedOnProperty = advancedSelector.property("ADBE Text Range Type2");
basedOnProperty.setValue(4);
// define the range selector's Start (4) and End (5) properties and set both to zero
var rangeStartProp = highlightSelector.property("ADBE Text Index Start");
var rangeEndProp = highlightSelector.property("ADBE Text Index End");
var animLength = .5;
var animSpacing = 2;
for(j=0; j<lineCount; j++)
{
var inPoint = theTextLayer.inPoint + (animSpacing * j);
var outPoint = theTextLayer.inPoint + animLength+(animSpacing * j);
startKey = rangeStartProp.addKey(inPoint);
rangeStartProp.setValueAtKey(startKey, (j<1)?(0)
j-1));
startKey2 = rangeStartProp.addKey(inPoint+animLength);
rangeStartProp.setValueAtKey(startKey2, j);
endKey = rangeEndProp.addKey(inPoint);
rangeEndProp.setValueAtKey(endKey, j);
endKey2 = rangeEndProp.addKey(inPoint+animLength);
rangeEndProp.setValueAtKey(endKey2, j+1);
}
}
function SetKey(myLayer)
{
opacProp = myLayer.property("Opacity");
inPoint = myLayer.time;
outPoint = inPoint + .5;
var startVal = 100;
if(opacProp.numKeys > 0)
startVal = opacProp.value;
inKey = opacProp.addKey(inPoint);
opacProp.setValueAtKey(inKey, startVal);
outKey = opacProp.addKey(outPoint);
opacProp.setValueAtKey(outKey, 0);
}
Simple script that add's a new null and sets any selected layers to use the new null as parent:
/***************************************/
var initialLayer = null;
var activeItem = app.project.activeItem;
if (activeItem == null || !(activeItem instanceof CompItem))
{
alert("You need to select a composition before running this script");
}
else
{
app.beginUndoGroup("Add Null");
var selectedLayers = activeItem.selectedLayers;
//Add null
myNull = activeItem.layers.addNull(activeItem.duration);
var startTime = 9999;
//Set selected layers parent to the new null
for(var i=0; i<selectedLayers.length; i++)
{
selectedLayers[i].parent = myNull;
if(selectedLayers[i].startTime < startTime)
startTime = selectedLayers[i].startTime;
}
if(startTime == 9999)
startTime = 0;
myNull.startTime = startTime;
app.endUndoGroup();
}