Get the Flash Player to see this player.

Hacking expressions

2769 views

You all know that I’m a expression junkie. You’ve seen my tutorial and my approach to animating things. I hate keyframes, I love expressions. Even though sometimes I find using expressions very frustrating. Theres no way to declare global variables, create your own functions, or extend the build-in functionality. But there actually is a nice way to deal with that that you might not be aware of.

This is going to be very interesting if you have any programming experience. Any programming language will do: C++, PHP, Ruby, Visual Basic, Java, or even ActionScript. AE Expressions are based on JavaScript, so they are not only object oriented. You can also use any JavaScritp syntax and build-in functions that are not listed anywhere in AE itself. Unfortunately some things will not work as expected, and sometimes you might even get an error message, when everything is ok. When that happens simply turn off the expression and turn it back on again, or select all, cut it out, press Enter, and then paste it again making sure that you don’t have any white spaces in the beginning or end of the expression. That helps sometimes.

For example:

var currentTime = new Date();

In Javascript this creates a new variable that holds the Date object, that if no attributes are used in the constructor points to the current local time represented in milliseconds. If you’d try that in expressions you’d get an error. AE will force you to pass some attributes to the constructor. But that doesn’t mean we’ll not gonna have any fun.

Create a new text layer, and in the text source property try this code:

this;

Aaaahhh…. Ok. We’re getting somewhere. But what is this (object Layer) thing? Lets find out. Next piece of code will enumerate all properties of the object Layer.

Replace the above code with this one:

myPropList = []; //declare new array
currentFrame = timeToFrames(time, 1 / thisComp.frameDuration, false);
targetObj = this;
for (var itm in targetObj) {
myPropList.push(itm);
}
myPropList[currentFrame];

Now use PageUp and PageDown to go through frames of your composition. On each frame you should see different properties of the layer. It’s interesting, but lets move to something more useful.

Lets say you’re doing a text based animation. For example a counter that should go from 0000 to 9999. Notice that it’s 0000 to 9999, not 0 to 9999. So to do that you’d have to write a bunch of code to add additional 0 at the beginning, right? But what if you could design a function to do that for you? Since you can have functions in Javascript, it’s worth to try it in expressions as well. So lets try it.

function formatNumber (val, basestr) {
return basestr.substr (0, (basestr.length - val.toString().length)) +  val.toString();
}

formatNumber(132, "0000");

This little piece of code takes two parameters. First one is the numeric value, and the second one is the output format for that value. So for example, if you have a number 132, and an output format 0000 as the result you’ll get 0132. Also, if your number is 132 and output format is ABCDEF the result will be ABC132. As you see this is a pretty useful function. The only downside is that each time you want to use it you have to write it from scratch. Not very optimal solution.

So how do you make your own functions reusable in expressions?

As said before - expressions are Javascript based pieces of code, and that means you can basically use any Javascript syntax. There fore why not try using #include statement? Let’s try it out. Copy the formatNumber function to your clipboard and save it as a file on your hard drive. Let’s assume that the path to the file is "c:\myUtils.java". Having that file setup everything left to do is to import it like that:

#include 'file:///c:\\myUtils.java'
formatNumber(132, "0000");

If you’re on Windows you might want to save your file in the Support Files directory that you can find inside of After Effects installation directory. The default path for that is C:\Program Files\Adobe\Adobe After Effects CS3\Support Files\. I’m guessing that on a Mac this should be similar, but you will probably have to option-click on your AE directory and choose “Show package content”. After that you can navigate to /Applications/Adobe After Effects CS3/Adobe After Effects CS3.ap/Contents/Resources/ and put the file there. Than you’ll be able to simply use #import 'file:///myUtils.java' instead of providing the whole path to your file.

You can also use this technique to drive variable values from an external file. For example:

myText = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam ultricies sapien et justo. Vestibulum et erat id ante imperdiet sollicitudin. Ut sed ligula ac mauris tempus egestas. Donec vel risus."

Please keep in mind that this is a hack and it’s not officially supported, although I think it will work with any expression-enabled AE version. Try to keep your code libraries as small as possible. Group your functions to separate files to help organize your code. Remember that each time you import a file all it’s content is being processed my AE expression engine and this may slow things down quite a bit.

I hope you found this article useful. Leave a comment and let me know what you think.
Thanks for reading.

16 Responses to “Hacking expressions”

  1. hahahahahahha ;)

    Really really intersting amazing awesome buddy;;;

    maltaannon = theBest()*1000;

    [maltaannon,maltaannon];

  2. Thant’s a nice expression, but I think it should rather be:
    maltaannon = theBest()*(time*1000);
    [maltaannon,maltaannon];

  3. ahh , sorry guys but i think it should rather be :

    maltaannon = the best()*exp(time*100);
    [maltaannon,maltaannon]

    thanks for this

    btw,don’t try my expression,it’ll take between 3 to 4 hours to render one frame

  4. again… theres a small error:
    maltaannon = theBest()*exp(time*100);
    [maltaannon,maltaannon]

  5. Who’s the expression junkie?!? :D
    Amazing, simply no words ;)

  6. haha guys i think it should be like this;

    maltaannnon = theBest();
    jezy = wiggle(5,500)/5;

    [maltaannon,jezy]

    hope this brand new expression will work();

    its Free guys just use it and feel free to ask be about it… ;)

    hahah

    Check this out and post comments;

    http://www.youtube.com/user/umairvfx

  7. hmm interesting, but i cannot understand anything here, dont have the programming knowledge. Mark

  8. hmmh..what a brilliant, i don’t even know what that’s mean.

  9. Thanks man… I never knew you could use #includes inside the expressions. This will be very useful!

  10. Your a genius dude! i didn’t even know AFX did even use javaScript =O but i feel like i should know that for a long time ago. Anyway, thanks for sharing your knowledge!

    #include ‘/the.world’

  11. i am having issues getting this to work on my Mac using CS3. I have tried putting the file in Resources folder as suggested and in a few other simple to link-to locations, but still have had no luck. Any ideas?

  12. Try changing the file path to this format: file:///yourfilepath.ext

  13. This might come in handy :)

  14. is it just me, or does this not work in AE CS4?

  15. Great tip. I’m using Win XP 64 bit with AE CS3. My findings vary from the notes in this post. I’ve been unable to target the same folder the AEP file is in with relative referencing. That’s my preference so my project can be more portable. Anyone have success with that?

    Here’s my findings. Hopefully this helps someone else use this great tip about the #include directive:

    I used the following format, without any file:/// prefix, and I was able to target the Support Files folder (the sample with file:/// targets the root of my C drive):
    #include “simpleNumber35.jsxinc”;

    Any filename/extension works, but I followed the jsxinc format I read about in the PDF guide referenced below.

    Example that targets the root of my C drive: #include “file:///simpleNumber50.jsxinc”;

    Example that targets a sub directory (note: no c:\\ needed. None of my trials worked when I included c:\\):
    #include “file:///Documents and Settings\\Administrator\\My Documents\\simpleNumber90.jsxinc”;

    Links to another thread that cites #include (again, my results are different than the results that are cited here):
    http://aenhancers.com/viewtopic.php?p=3420&sid=c63f9a5278cac83b47390f798063c92e#p3420

  16. That’s true. You can’t reference relative folder - at least I haven’t found any way of doing that. The file:/// is just good to use if you’re using the same project file and file structure on two systems like MacOS and Win, but it’s not required.

Please share your thoughts with the rest of the class...