New Photoshop Exporter- ExportThis!

After a long and (mostly) successful run of controlling Photoshop with Python, I decided to take a stab at writing a fully integrated Photoshop Extension, this time using the native Javascript based API.

The end result is a cleaner, smaller and all round better Photoshop tool that does a number of kinda cool things.

Export This!
Some of the User-facing features
Because its written to take advantage of the native API there is a significant difference in app size- Texture Monkey being almost 40mb when including all the additional GUI and Python library files it required, vs a 29kb .ZXP installer for ExportThis. The ZXP is easily distributed, and uses Adobe Extension Manager CC to install/update/remove itself. 

Within the tool, the document template system was added to allow artists to easily make documents that would be compatible with the exporter (as a lot of it is group name/hierachy based) but I expanded on it to allow artists to make and save their own particular document setups too. 

I chose JSON files for the templates, user configuration and project definitions due to it's ease of use- and the fact that it can easily be read by anybody. This turned out to be a little bit of a challenge, as Javascript is generally blocked from accessing any local files, as well as the Asynchronous nature of Javascript itself meaning that sometimes your functions end up being called before you have any data to read.

In addition to the trouble with reading files, another odd little challenge popped up due to Javascript supporting JSON parsers out of the box and Javascript Extended completely lacking any. I got around this using the eval feature in order to read the JSON strings back into useful objects.

The tool uses the Adobe extension framework, which is made up of several components, each of which operate on different levels and have their own little quirks. 

The GUI is created in a very similar way to a web page, using HTML and CSS to define it's layout, content and internal behaviors. I was able to embed things like interactive help drop-downs using JQuery, as well as easily modifiable selection lists and other standard web-fare. 

Behind the GUI is a Javascript file that bridges the GUI to the actual Photoshop JSX extension. This is where it starts to get a little clunky, for three particular reasons:
  • This part of the tool has the same security restrictions imposed on it as any other web related Javascript code, for example, restrictions to the local file system. 
  • All calls to the actual Photoshop extension are passed as strings to evaluate (including arguments) meaning passing data back and forth between the extension and the GUI can be pretty cumbersome.
  • Javascript operates in an async manner. Due to this, the Javascript layer was kept very lightweight to minimize introducing any lame async related bugs. Although initially this lead to a little bit of head-scratching on my part, it resulted in a much easier to maintain tool, with all the heavy lifting confined to the Photoshop JSX engine. 
As I decided pretty early on that I wanted to use JSON files to store both user settings (such as the last project used, and their local project root) I had to figure out a way to be able to both read and write data from the tool, which I ended up doing on the Photoshop JSX side, which is the third component!

The Photoshop JSX (JavascriptExtended) file is where all the work actually happens- This is the part of the tool that can access the local drive, as well as drive Photoshop. I wrote it to contain a mix of environment definition and actual exporting functions. Any data sourced from the local drive that might be required by the GUI is read by the JSX and then passed back as a string to be parsed into a JSON object in memory. In a similar fashion, any GUI modified data is passed back as a string to be written back to the file system by the JSX. Lots of juggling!

The JSX also contains a component that can interact with the local system through the command line in order to check out elements from Perforce, using .bat files. 

(the hidden) GUIRilla, or a sprite exporter. 

Although the main focus of the exporter is Texture exporting for 3d models, an additional feature is the ability to author and export multiple 2D sprites from a single document. The exporter allows a "UI_SPRITE" flag document name prefix to be defined in the Project Settings, which will change the exporter to treat the document as a sprite atlas and export each group as a individual trimmed element, with transparency. It's pretty cool, but I'll go into this in a little more depth in another post, as its a whole other workflow. 

Overall, it was a fun exercise and the Artists using it have responded very well to it as a replacement for TextureMonkey. 

If you made it this far, hooray! Drop me a line if you are working with the Adobe Extension framework at all. Next up will be some tips for rapid iteration while working on extensions, and some of the terrible mistakes I made along the way...