Script your first Adobe Generator plugin for Photoshop

Script your first Adobe Generator plugin for Photoshop


Tutorial GitHub repository.

Introduction

Today we have released an update to Photoshop CC that includes Adobe Generator. Read the announcement here.

Adobe Generator is a Node.js based server plugged into Photoshop via Kevlar API (ExtendScript). Generator is also open-sourced on GitHub.

This extends Photoshop scripting layers to three complementary options:

  • ExtendScript (write and run *.jsx scripts directly from File -> Scripts)
  • Photoshop Server (remote connection to Photoshop over TCP/IP, e.g. control Photoshop from iPhone/Android or other apps on the same machine)
  • Generator

Each one of them have a bit different use-case, however ExtendScript is still used in the end for invoking commands on Photoshop. Check out ExtendScript scripting guide.

Relationship between Photoshop scripting layers

Adobe_Photoshop_Generator_Scheme2

Primary use-case of Generator is to generate data or connect to resources from inside Photoshop, which is the OUTGOING direction.

On the other hand with Photoshop Server, you are connecting to Photoshop, which is the INCOMING direction and that requires a password set by a Photoshop user.

(Practically you could setup a socket-server (like a Node.js web-server) in Generator and allow INCOMING connections as well for a specific use-case to enable other apps or devices to connect to Photoshop, but that’s more of a secondary use-case.)

Your First Generator Plugin

Adobe Generator comes with Photoshop CC (version 14.1+), but for the development it’s better to get it from GitHub and launch it separately.

Step 0: Install Node.js

Go to Nodejs.org, download and install Node.js. Photoshop comes with Node.js version v0.10.15 (node –version will retrieve what version you use, if you install a new version of node, it will override the old one).

Step 1: Download The Generator-Core Project

Go to https://github.com/adobe-photoshop/generator-core and click Download ZIP or Clone in Desktop.

Open Terminal.app (on Mac) or Command Line (on Windows), navigate to generator-core-master folder that you have just downloaded and type npm install. If you don’t have NPM (Node Packaged Modules), you need to install Node.js (Step 0).

NPM Install Adobe Generator

Step 2: Setup Photoshop for Remote Connections

Open Photoshop, go to Photoshop -> Preferences -> Plug-ins and click Enable Remote Connections and set password to “password” string. (Note: Even-though deployed Adobe Generator lies right inside Photoshop, for development it’s preferred to use remotely sitting Generator.)

Photoshop Preferences

Step 3: Download The Getting started project

Download Generator Getting Started Plugin
Unpack and place it next to generator-master into plugins folder like this:
Screen Shot 2013-09-09 at 3.05.03 PM

View the complete main.js file.

To run Generator, type in Terminal from within the generator-master folder:

node app -f ../plugins
(which essentially means, run node with app.js file with -f parameter (plugins folder).

Step 4: Calling functions on Photoshop

The most important file here is main.js. Open it and locate the init function.
It shows three things, how to invoke ExtendScript in Photoshop via evaluateJSXString, retrieve an entire document structure in JSON and listen for changes in document.

function init(generator, config) {
    _generator = generator;
    _config = config;
 
    function initLater() {
        // Set data in Photoshop using ExtendScript via _generator.evaluateJSXString
        // Flip foreground color
        var flipColorsExtendScript = "var color = app.foregroundColor; color.rgb.red = 255 - color.rgb.red; color.rgb.green = 255 - color.rgb.green; color.rgb.blue = 255 - color.rgb.blue; app.foregroundColor = color;";
        sendJavascript(flipColorsExtendScript);
 
        // Get data from Photoshop via _generator.getDocumentInfo
        requestEntireDocument();
 
        // Register events on Photoshop
        _generator.onPhotoshopEvent("currentDocumentChanged", handleCurrentDocumentChanged);
        _generator.onPhotoshopEvent("imageChanged", handleImageChanged);
        _generator.onPhotoshopEvent("toolChanged", handleToolChanged);
    }
 
    process.nextTick(initLater);
}

Most of these features are actually implemented via evaluateJSXString on Photoshop at the end. The event registrations and the calls just invoke JSX and retrieve data via promises. Generator makes it easy for you and hides all that logic behind much a nicer API in Javascript.

Step 5: Requesting the document structure as a JSON

Let’s dig into requestEntireDocument.
This function retrieves the document by calling _generator.getDocumentInfo that uses sendDocumentInfoToNetworkClient to retrieve a document structure in JSON (read about the structure here).

function requestEntireDocument(documentId) {
    if (!documentId) {
        console.log("Determining the current document ID");
    }
 
    _generator.getDocumentInfo(documentId).then(
        function (document) {
            console.log("Received complete document:", stringify(document));
        },
        function (err) {
            console.error("[Tutorial] Error in getDocumentInfo:", err);
        }
    ).done();
}

Step 6: Photoshop Events

To register an event, call _generator.onPhotoshopEvent with an event name and handler.

We have registered three events in the init function: currentDocumentChanged (when we switch between the documents), imageChanged (when we change something in the image), toolChanged (when we pick a different tool).

Now we will just add handlers:
(uncomment and add stringify(document) if you want to see the new document structure)

function handleCurrentDocumentChanged(id) {
    console.log("handleCurrentDocumentChanged: "+id)
    setCurrentDocumentId(id);
}
 
function handleImageChanged(document) {
    console.log("Image " + document.id + " was changed:");//, stringify(document));
}
 
function handleToolChanged(document){
    console.log("Tool changed " + document.id + " was changed:");//, stringify(document));
}

Step 7: Photoshop Menu and Events

Now we need to add our own item in the File->Generate Menu in Photoshop.
Photoshop Menu Changed

You can see the pre-installed Generator plugins separated from ad-hoc development plugins. If you want to be pre-installed, you need to deploy your plugin into Applications/Adobe Photoshop CC/Plug-ins/Generator.

Now, in order to register your own menu item, call _generator.addMenuItem in the init function and register generatorMenuChanged event.

_generator.addMenuItem(MENU_ID, MENU_LABEL, true, false).then(
    function () {
        console.log("Menu created", MENU_ID);
    }, function () {
        console.error("Menu creation failed", MENU_ID);
    }
);
_generator.onPhotoshopEvent("generatorMenuChanged", handleGeneratorMenuClicked);

Where MENU_ID and MENU_LABEL are predefined strings:

MENU_ID = "tutorial",
MENU_LABEL = "$$$/JavaScripts/Generator/Tutorial/Menu=Tutorial",

Now when the user clicks on the menu item, we can determine the menu state using _generator.getMenuState:

function handleGeneratorMenuClicked(event) {
    // Ignore changes to other menus
    var menu = event.generatorMenuChanged;
    if (!menu || menu.name !== MENU_ID) {
        return;
    }
 
    var startingMenuState = _generator.getMenuState(menu.name);
    console.log("Menu event %s, starting state %s", stringify(event), stringify(startingMenuState));
}

Finally you can use _generator.toggleMenu to display the check sign.

function updateMenuState(enabled) {
    console.log("Setting menu state to", enabled);
    _generator.toggleMenu(MENU_ID, true, enabled);
}

Step 8: Retrieving a bitmap from Photoshop

The last step is to retrieve and process a bitmap that we get in the image changed event.

For this, please go to the next tutorial: Adobe Generator: Getting a layer bitmap

Video tutorial

Check out the getting started video tutorial about Adobe Generator by Lee Brimelow covering things covered in this article.


Written by: |   Uncategorized     |    September 9, 2013

Creative Cloud - Get all the Adobe creative desktop tools + services like 20 GBs file sharing.
  • Michael Chaize

    Fantastic !

  • Ahmed

    Hi,

    I am facing problems with step 3.

    On the windows command prompt, I am typing:

    F:SoftwaresGraphicsgenerator-core-mastergenerator-core-master>”C:Program Filesnodejsnode.exe” app -f

    It says this error and does not install:

    Log directory: C:Usersmirza.ahmedAppDataRoamingAdobeAdobe Photoshop CCGen
    eratorlogs
    [init] Package generator-core v1.0.1
    [init] No Git repository found
    [init] Node.js version: {“http_parser”:”1.0″,”node”:”0.10.18″,”v8″:”3.14.5.9″,”a
    res”:”1.9.0-DEV”,”uv”:”0.10.15″,”zlib”:”1.2.3″,”modules”:”11″,”openssl”:”1.0.1e”
    }
    [init] OS: Windows_NT 6.2.9200 (x64), platform: win32
    [init] unparsed command line: ["C:\Program Files\nodejs\node.exe","F:\Softwa
    res\Graphics\generator-core-master\generator-core-master\app","-f"]
    [init] parsed command line: {“_”:[],”$0″:”C:\Program Files\nodejs\node.exe F:
    \Softwares\Graphics\generator-core-master\generator-core-master\app”,”f”:tr
    ue,”pluginfolder”:true,”r”:”independent”,”launchreason”:”independent”,”m”:null,”
    menu”:null,”p”:49494,”port”:49494,”h”:”localhost”,”host”:”localhost”,”P”:”passwo
    rd”,”password”:”password”,”i”:null,”input”:null,”o”:null,”output”:null}
    connecting to localhost:49494
    Photoshop error Socket error: Error: connect ECONNREFUSED
    Photoshop error { [Error: connect ECONNREFUSED]
    code: ‘ECONNREFUSED’,
    errno: ‘ECONNREFUSED’,
    syscall: ‘connect’ }
    Photoshop connection closed
    Exiting
    Exiting with code 0: generator close event

    • tomkrcha

      have you done npm install?

      • Ahmed

        Yes, but npm file is not in generator-core-master folder so i installed node.js and from this i installed npm

    • Zoltán Szalay

      I had this same error, because I misread the password task in step 2. Write “password” as the password in photoshop prefs and you should good to go.

  • francis

    Can I use Photoshop 14.0 or CS6? thnx!

    • tomkrcha

      Hi Francis, this is a new feature added in Photoshop CC version 14.1. So no CS6 or below.

      • francis

        Thnx! I tried you tutorial in CC 14.1 and works with some errors like:

        Warning: unable to parse JavaScript message response ‘[SolidColor]‘ as JSON. Error: SyntaxError: Unexpected token S

        but detect document and tool changes

        I also tried image asset from github and doest work :S

        Thanks!

        • tomkrcha

          yeah, that warning is OK, it’s just a warning, but as you can see, the JSX has been applied and the color just changed. Generator is catching messages from Photoshop and if it doesn’t understand them it will show warning, but you can catch the message in your own event handler and process because you know what to expect from PS (as a message)

  • kyle.liu

    We can use it to do what?

  • Linton Ye

    Hi Tom, I’ve got a simple (but useful) plugin working in development mode, but how to deploy it? couldn’t find anything. Thanks!

    • tomkrcha

      you just copy and paste your plugin files into: (on Mac) Application/Adobe Photoshop CC/Plug-ins/Generator/nameofyourplugin.generate

      When you launch Photoshop, it will look into this folder and load your plugin. You can make an installer for your users, that just copies the files into this folder and you are good to go.

      • tomkrcha

        of course on Windows, it will be Program Files/Adobe Photoshop CC/Plugin-ins/Generator…

        • Linton Ye

          That was fast! Thanks Tom. However, it doesn’t seem to work though. The plugin is actually a fork of the “generator-assets” plugin. I added the support for the Android “dp” unit. https://github.com/jimulabs/generator-assets

          The directory “Generator” did not exist, so I created one and created a directory “generator-assets-android.generate” and copied files as your instructed. PS did’t seem to pick it up. See the attached screenshot.

          I changed plugin name to “generator-assets-android” in package.json.

          • kcoop

            Thanks, Linton Ye (and of course Tom, and all the other awesome folks at Adobe)! You gave me a big leg up on doing the iOS equivalent: adding image sets to the XCode Asset Catalog. I forked your code, and added an ‘is’ unit type to your ‘dp’.

            https://github.com/kcoop/generator-assets

          • tomkrcha

            Sweet! Great job!

        • Linton Ye

          Just got it working by including “node_modules”. Thanks Tom!

          • tomkrcha

            yes, npm install step is very important here :) good

      • Edgars Simsons

        Tom, but where should the latest version of core be place? I am having a modified version of the latest generator-assets and it depends on core version 2 to function correctly.

        • Edgar Simson

          Tom, could you help with this? Is there a solid way to use a different version of the core for my custom plugin when placed in “Plug-ins/Generator”?

  • Mark

    *headache*

  • Alan Greenblatt

    Very useful tutorial. 2 quick things:

    - You have 2 step #5′s :-)
    - You never actually call updateMenuState() to toggle the menu. You could add the following to the end of handleGeneratorMenuClicked():

    updateMenuState(!startingMenuState.checked);

    • tomkrcha

      Fixed #5.
      Ad updateMenuState – yep, it’s more for an illustration.

  • CSS3Ps
  • Davide Barranca

    To make it work (step #3) I’ve had to modify the generator-getting-started-master/package.json, the line that says: “generator-core-version”: “~1″ – modified to “~2″ otherwise I keep getting “[Error: The plugin generator-getting-started is incompatible with this version of generator-core. generator-core version: 2.0.0, plugin compatibility: ~1]“. BTW, what does the tilde mean, less or equal to 1.x? Thanks!

    • tomkrcha

      correct. Current version has been updated to ~2 … I believe it is 2.0.0+

  • Jakobud

    Why does Adobe’s built-in Generate Image Assets not require you to run an external node.js server? I understand this tutorial, but a lot of designers who want to generate web assets might be overwhelmed by some of the steps.

    Too bad you can’t just create a single file JS script that is easy to drop into Photoshop and easy to distribute to people instead of jumping through all these hoops just to make it work….

    • tomkrcha

      You can totally drop in a single JS file into plugins folder in PS and it will work. This tutorial is meant for developers building such scripts on top of Photoshop. You deployed script doesn’t require an external node.js server.

  • Sergey Kritskiy

    I’m having a trouble with step 3. I’ve enabled Generator and Remote connections, but I’m getting this error:

    Determining the current document ID
    Getting document info with these params: {“flags”:{“compInfo”:true,”imageInfo”:true,”layerInfo”:true,”expandSmartObjects”:false,”getTextStyles”:true,”selectedLayers”:false,”getCompSettings”:true}}
    Photoshop error Socket error: Error: write EPIPE
    Photoshop error Socket error: Error: write EPIPE
    Photoshop connection closed
    Exiting
    Exiting with code 0: generator close event

    What’s wrong?

    • tomkrcha

      That’s weird, ping @timriot on twitter, maybe he’d know.

  • andrei_amar

    Hi, I am not very familiar with Photoshop and I’m a little confused, but I would like to know if it is possible to do this:

    1. can I have a batch job that opens all images from an input folder, applies an action to each image, then saves the images into an output folder, all of this controlled by a script?
    2. can I have a node.js app that calls this script when, let’s say, the user clicks a button?

    I would like to integrate this into a webapp.

    Thanks.

    • tomkrcha

      Hey Andrei,

      1) first can be done using File -> Batch -> Automate…
      - however that’s with UI
      2) you can call ExtendScript from Node.js, Actions are essentially based on ExtendScript, but you need to dig in further on how to exactly what you want.

      It’s hard to imagine what you are trying to achieve.

      • andrei_amar

        Thanks for your reply. Basically I want to allow web users to upload photos which in turn I will process them in PS and it would be great if this could be automated.

        • tomkrcha

          so you want to run Photoshop on a server and provide its functionality to multiple users?

          • andrei_amar

            Yes, that’s basically it.

  • Erik

    If you find yourself wondering why ‘imageClosed’ isn’t dispatched when you close an image in Photoshop CC, try adding a listener for imageChanged as well. Due to what I presume to be a bug in CC a listener for imageChanged is required for imageClosed to work :/

    • Guest

      Sorry, make that documentClosed

  • Mike Delucchi

    This is excellent, thanks!

  • Ahmed

    I GOT SOLUTION 3:)
    gfx.ahmed (skype) me

  • http://www.friv2.org/Flappy_Bird.html flappy bird

    Would it be possible to use this with the Edge animate workflow

  • http://www.friv2.org/Flappy_Bird.html flappy bird

    it can’t convert text. please help me!

  • Ryan Wainwright

    High everyone.

    This is probably a “dumb” question, but looking back at step three of this tutorial… was wondering where I place the generator-master folder? Do I put it in my “Program Files/Adobe/PSCC/Plug-ins/Generator” dir?

ToTop