picture home | art | events | music | rack extensions | downloads | pixel blog | qt_tools

omino pixel blog

pixels, motion, and scripting
entries for category "extendscript"
david van brink // Tue 2009.08.4 17:40 // {after effects extendscript}

AE: Scripting Notes

Just a quick note about a bug and an optimization when scripting After Effects CS4 (and probably earlier versions, too).

addProperty() bug

When adding several effects, each addition invalidates the object variable references to earlier ones. Here’s a code fragment which shows the problem and the solution.

var comp = app.project.activeItem;
var layer = comp.layers.addNull();
layer.name = "null_layer";

var slider1 = layer.Effects.addProperty("Slider Control");
slider1.name = "s1";

var slider2 = layer.Effects.addProperty("Slider Control");
slider2.name = "s2";

// At this point, slider2 is valid, but slider1 is mysteriously not!
// Any action or reference to slider1 will cause an "invalid object" error
// What can we do?
// Fortunately, they have names by which we can recover them

slider1 = layer.Effects.property("s1");
slider2 = layer.Effects.property("s2");

// Now they're both good to go.

setValueAtTime() Gets very slow!

If you do a whole lot of setValueAtTime() calls to set keyframes, the script will run very slowly. Fortunately, you can just call setValuesAtTimes(), the plural form, to set many at once, which is much more efficient! Makes the minutes seem like seconds, Captain.

// this will be very slow, if myData has more than a few dozen items
for(var i = 0; i < myData.length; i++)

// but if we build up our arrays first...
var timesArray = new Array();
var valuesArray = new Array();
for(var i = 0; i < myData.length; i++)
// and set them all at once

// it will go lickity-split!

(Thanks creative cow thread!)

oh, i dont know. what do you think?

david van brink // Sat 2008.12.27 10:05 // {after effects extendscript}

AE: A Snowflake


download snowflakeSteps.aep

Featuring: Bevel Alpha, omino kaleidoscope, and animated paths.

Sounds like the USA has had a heck of a Christmas weather run! Folks taking their vacations on airport waiting benches, and so forth. In particular, Seattle, home to After Effects. Where I am, it’s 7:33 pm, and I’ve just returned, sweating, from a nice bowl of Mun Eefoo Mee. Total google hits for that dish: 0, but the chef told me it’s his specialty, and it was delicious. Cost, with a cup of iced sweetened barley, 5 Ringitts Malaysian. Current temperature: 80F. Current exchange rate: 3.8 Ringitts to the US Dollar.

It’s my kind of place. “Christmas” is a national holiday, but nobody celebrates beyond a few santas at the mall. On the 25th, the shoe stores and the hardware stores were all open. As were thankfully the restaurants; I’m expated here alone for a few months, no home cooking for this coder.

So, in a fit of boundless atheism, I spent the 25th cobbling together an After Effects project to grow snowflakes!

Step 0: Research

I found this great site, http://snowcrystals.com/ maintained by Kenneth G. Libbrecht, a Caltech physics professor. Fabulous stuff, including movies of lab-grown snow crystals!

After reading his site, and other sources, and general pondering, I jumped in with the scripting. It’s only a 2 day project, so it’s not really going to accurately mimic the physics of snow… but we’ll settle for “suggestive” and “cool-looking”.

(And, here is a short article about snowflake symmetry.)

Step 1: Growth


click for

This movie shows one branch of a snowflake being “grown”. It’s a layer mask path, animated by ridiculous please-don’t-read-the-code script I wrote… but, truth to tell, you could animate almost anything in there, and, by the end, it’s going to look pretty snow-ish. You can download my script if you like. It’s kinda tweaky; the main trick is that the lengths parameter consists of letters, where a is a very short spike, and z is full length.

Step 2: Hexagonal Symmetry

We all know how to make a paper snowflake, with three or four folds and some scissors. We’ll do the same thing with my plugin, omino kaleidoscope, downloadable here.

(You can also use CC Kaleida, which is included with AE these days, to make an 8-fold snowflake. But use mine for authentic regulation 6-way symmetry.)

The omino kaleidoscope works by using an AE layer’s Mask Path to represent the shape of the mirrors. Any path will work (though curves are treated as straight segments). For snowflake symmetry, we need a wedge which is one twelfth of the pie. Again, I wrote a script, wedgePath to do this. But you could draw the mask manually, if you’re careful. (Be sure to set its mode to “none”, we don’t want it to clip the image.)

And set up omino kaleidoscope as shown in the screenshot above.

Step 3: Moreness


click for

So far so good. Next, let’s add a few more layers of animated paths. We’ll superimpose them to get different gray-levels. Some of them are time-shifted, to evolve at different rates. Different transfer-modes can liven this up a little. Again: you can animate almost anything, and the kaleidoscope will make it snowflake-like.

Step 4: Imperfect


To make it look just a shade less mechanical, we can have the snowflake grow a little bit irregularly. Now, it is supposed to be a crystal, so we’ll go gently with this. Real snowflakes often show subtle imperfections like this, presumably due to environmental variations during formation.

The above frame is from Step 3, with Time Displaclement applied. Here’s the layer used as the Time Displacement Map. It ranges from black to 50% grey, ensuring that only negative time displacements will be used.


click for

Note. Time Displacement is a render-time hog, since AE needs to render many frames past and present for each final frame. It’s helpful to disable this effect while tinkering, turn it back on for the render.

Step 5: Crystallize

This is the last step, really. We’ll use a few applications of Channel Mapper to convert luma to alpha. And then, this is the exciting part, we use Bevel Alpha with several colored lights to get the colorful crystalline look.

The “light angle” for the bevel effect has been animated with an expression

effect("Bevel Alpha")("Light Angle") + time * 90

just to keep it lively.

Also, Channel Mapper has been used to pull a dark grey in for the snowflake’s color. The different brightnesses earlier were mapped to alpha, for the beveling; the final result looks better with colors darker than white.

And I’m not above adding a bit of Find Edges and Glow, no sir. The secret sauce is ketchup. Whatever it takes!

Here’s the final result:


click for

As ever, here’s the After Effects project. It doesn’t require any assets (the finalMovie comp references the photo and music loops, but pay it no mind).
download snowflakeSteps.aep

And so far, it has not been a cold day in Penang, Malaysia.

oh, i dont know. what do you think?

david van brink // Thu 2008.12.25 00:11 // {after effects extendscript}

AE: Mask Vertices from ExtendScript

We’ll take it as axiomatic that scripting After Effects is pretty keen. But sometimes you can get lost in the nest of properties, property groups, values, attributes, and the subtle differences in nomenclature for properties and attributes used by After Effects and the JavaScript.

It is definitely possible to access and manipulate each vertex on a layer mask. Below is a script which displays some mask points, and then modifies a vertex. It will show this alert:


And this is the script which displays the dialog, and then modifies the 4th vertex of the mask. It demonstrates the recipe to navigate the Masks, Mask, Mask Path, and so on.

One thing first. Many sites and blogs show only very, very short scripts. I take a slightly different approach. I think code should tell a story. I try to build things up as simply as possible. Despite its apparent length, I think you’ll find the script easy to follow. Just go 1 line at a time.

// Utility to find a comp by name.
function findComp(name)
	for(var i = 1; i <= app.project.numItems; i++)
		var item = app.project.item(i);
		if(item != null && item.name == name)
			return item;
	return null;

// Show the vertices of the first mask of comp1/layer1.
function main()
	var comp = findComp("comp1");
	var layer = comp.layer("layer1");
	var masks = layer.Masks;

	var firstMask = masks.property(1);

	if(firstMask == null)
	var maskPathProperty = firstMask.property("Mask Path");
	var maskPath = maskPathProperty.value; // or valueAtTime(t) if  you like

	var sm = "Vertices\n";
	var vertices = maskPath.vertices; // array of [x,y] pairs
	for(var i = 0; i < vertices.length; i++)
		var p = vertices[i];
		var x = p[0];
		var y = p[1];
		sm += "v[" + i + "] = " + x + "," + y + "\n";

	alert(sm); // Show the vertices.

    // Now, we change a point.
	var p = vertices[3];
	p[1] = 300;
	// Must be "put back" bit by bit.
	maskPath.vertices = vertices;



A few notes:

  • To change the vertex, we need to assign it back to the Mask Path and then into the Mask property; changing it "in place" won't alter the actual mask.
  • Chris-g notices that you must assign the vertices before assigning closed to true or false; assigning the vertices "automagically" sets closed to true. Thanks Chris!

Hope that's useful.

oh, i dont know. what do you think?

david van brink // Mon 2008.12.15 06:59 // {extendscript illustrator}

Two Illustrator Scripts

Here’s a pair of Illustrator scripts I’ve had up for a while, but this is the first time I’ve posted examples. Also, Javier Enciso of www.formaestudio.com in Uruguay spotted a bug in the triangle script, which is now fixed.

Both available at http://omino.com/sw/ominoAdobeScriptsSuite/.

Circular Gauge (circularGauge.jsx)


This script draws numbers and tick-marks to resemble a circular gauge. It lands up in its own layer, and the text and ticks are in their own group, ready for tweaking. I use it to make pretty machines in Second Life. A bit of emboss and off you go.

Triangle By Sides (triangleBySides.jsx)


I can’t remember what I needed this for, but it was exactly what I needed at the time. Self explanatory!

oh, i dont know. what do you think?

(c) 2003-2013 omino.com / contact poly@omino.com