Thursday, May 14, 2009

Cross-scripting Adobe Illustrator and Adobe Flash

21st century, expensive products, same company makes them all, and sells them all in the same package.

You'd think they'd play happily together.

And Adobe documentation here and there hints that they do.

But finding out how is mighty difficult.

You fire up the ExtendScript Toolkit, and the documentation makes it sound like you can do almost anything from there.

Play around with Adobe Illustrator scripting in the ExtendScript Toolkit - sweet!

But now try to script Adobe Flash...

... oops, um, well, there doesn't really seem to be a way to do it.

Does Adobe document that you can't? Well, not that I've managed to find.

In fact, one other commentator stopped short of giving a definitive answer that Flash isn't supported by the ExtendScript Toolkit, and instead just said that it seems it isn't.

C'mon Adobe, give us clear, informative, unambiguous documentation!

In fact, if you put "#target flash" in a script in the ExtendScript Toolkit, and try to run it, it actually launches Flash, and then tells you that it failed to connect to the Flash scripting engine. What the???

An Adobe brochure about Flash CS3 claims that it is now compatible with ExtendScript, but frankly, I don't see how, and we're now up to CS4!!! ("Flash CS3 also adds ExtendScript and BridgeTalk support for cross-application scripting.")

So after many hours of wasted time, I've figured out how to make Illustrator and Flash sing to each other.

I'm not impressed by the obtuse steps required.

And I'm not impressed by the extremely non-definitive documentation on Adobe's part.

Here's how you do it :

1) Your Adobe Illustrator scripts will be written using the ExtendScript language, whereas your Adobe Flash scripts must be written using a language called JSFL. Both languages are javascript-based, and have many similarities, but they also have many differences. (e.g. native filesystem access in ExtendScript is done via the File class, whereas in JSFL it's done via the FLfile class. Hello, any reason for that, anybody?)

2) Adobe Bridge is not Adobe BridgeTalk. The names are very similar, but the use is very different, and unfortunately, the difference is not clearly articulated in Adobe docs.

Adobe Bridge is a moderately useless file cataloging and file browsing tool.

In contrast, Adobe BridgeTalk is a simple but powerful inter-process communication tool.

So, we're going to use Adobe BridgeTalk to communicate between Illustrator and Flash.

3) It is very hard to find Adobe BridgeTalk documentation. (e.g. Google-ing for "adobe bridgetalk reference" is close to useless.)

I suspect this is in part because BridgeTalk is SO simple that there's hardly anything to document, and thus, Adobe is content to let developers learn by example.

And learn by example is how I had to do it.

4) One of the best sources of examples of Adobe BridgeTalk scripting is actually in the Adobe Bridge SDK. Yes, that sounds confusing, but it's true.

Download said Adobe Bridge SDK. It's about 4MB of compressed files. Unzip, and inside are a few interesting PDFs, and a bunch of jsx files showing cool tricks using BridgeTalk (amongst other things).

(I suggest you read the short section "Communicating with Other Applications" in the "Bridge CS4 JavaScript Guide.pdf" that comes in the docs folder in the Adobe Bridge SDK.)

5) In brief, BridgeTalk sends javascript as a string, from one application to another (e.g. Illustrator to Flash), and sends the value of the last-executed-statement in said script back to the calling application. It's a bit obtuse, but it's very powerful.

6) Note that BridgeTalk is ASYNCHRONOUS. And there is no synchronous mode. So you have to be patient with writing the extra code to handle breaking a single synchronous procedure into smaller asynchronous steps.

7) There is an extremely-poorly-documented means of launching ANY application via BridgeTalk. e.g. you can run a Windows batch file, or trigger your source code versioning system, or invoke a custom tool you wrote in a non-Adobe language. You can pretty much run anything you like.

It's based around a function called "system".

As with most Adobe stuff, this "system" function is extremely poorly documented.

The only way I've found to use it is to call app.system('command-line.exe bla bla'); from within Bridge.

So - get this - if you want to fire up a useful external program (e.g. source code control) from within a script that is automating Illustrator or Flash, you need to use BridgeTalk to send a script to Bridge, and the script you send to Bridge needs to include the app.system(<command-line>) invocation. Talk about convoluted!

But at least it works.

Oh - and app.system(...) is SYNCHRONOUS, unlike BridgeTalk which is ASYNCHRONOUS. Just to make sure your neurons are really getting a workout...

8) If you've understood everything to this point, and want a cool trick to make it much easier to generate lengthy scripts that get shared between different Adobe products, you can use the toSource() function, as described by Justin of Ajar Productions in an article entitled "Easy (and Readable) ExtendScript to JSFL Workflow".

Remember : JSFL = scripting the Flash* development ("authoring") environment, whilst ExtendScript is used e.g. for Illustrator. Justin's article covers writing an ExtendScript for Adobe Illustrator, that also uses BridgeTalk to get Flash to do some things, yet all within a single script file, and without much messy code. Very nice work, Justin!

(* Technically, JSFL is used for a few other products, not just Flash, but for my present purposes, it is accurate enough to say JSFL = scripting the Flash development environment.)



Conclusion?

Adobe makes things horribly painful to learn.

Oh - and to use. e.g. obtuse error messages.

But despite the pain along the way, you can actually accomplish a huge amount. If you have spare hair and a high pain threshold, you might find (as I am finding) that ExtendScript, JSFL and BridgeTalk are extremely rewarding tools to be able to use.

1 comment:

Justin Putney said...

Great article! Thanks for the mention!