Photoshop UXP Plugins
The Basics
This section covers the basics of UXP in Photoshop. For the basics of UXP itself, see Getting Started with UXP. For the full API for Photoshop, see the Photoshop API pages.
While generic UXP APIs work across applications that support UXP (such as Adobe XD as well as Photoshop), the APIs in this section are specific to Photoshop. As such, they affect Photoshop documents rather than changing your plugin's UI, accessing the file system, and other non-Photoshop operations.
UXP exposes APIs for Photoshop at the same level in your plugin as your UI code. Unlike CEP plugins, UXP plugins do not have to serialize strings and send them back and forth between the UI code and the ExtendScript engine. This removes a substantial barrier to rapid development and debugging.
As of this writing, UXP in Photoshop is a work in progress, with some Photoshop functionality not yet exposed in the API. The workaround if you need some Photoshop function that is not in the API is to use a feature called batchPlay.
To start writing your plugin, first review the UXP Toolchain. Then download the UXP Developer Tool. You can use that tool to create a plugin folder containing basic scaffolding for HTML, JavaScript, and other required files. Edit these files, replacing the sample code with your code.
More detailed information about these APIs can be found in the Photoshop API reference.
Synchronous vs Asynchronous Methods
An important difference between ExtendScript (and CEP) and UXP in Photoshop is that all ExtendScript calls to Photoshop were synchronous. This means they blocked the Photoshop UI while they were executing. In UXP, a method call can be synchronous or asynchronous, i.e., non-blocking.
Asynchronous operations are typically used for methods that can take a long time (e.g., creating a document). Simpler operations, such as getting properties of an object, are typically synchronous.
Photoshop Objects
Every interaction with Photoshop is done via one of the objects below. Methods on the object allow you to get and set properties and access child objects.
Most objects are accessed through the app
object, which exposes the Photoshop DOM. The objects currently implemented are:
Photoshop Application
This is the top-level object, the root of the Photoshop DOM. From here, you can access open documents, tools, and UI elements as well as run commands or menu items. To get access to this object, use:
Copied to your clipboardconst app = require('photoshop').app;
Through the app
object you've just created, you can access Photoshop's objects and methods. For example, the currently-active document is obtained like this:
Copied to your clipboard1const app = require('photoshop').app;2const doc = app.activeDocument;
And you can get an array of all open documents like this:
Copied to your clipboard1const app = require('photoshop').app;2const allDocuments = app.documents;
Creating a document is also straightforward:
Copied to your clipboard1const app = require('photoshop').app;2let myDoc = await app.createDocument(); // creates a document with default settings34// You can also add some document properties while you're creating a document:5let myDoc = await app.createDocument({width: 1200, height: 800,6 resolution: 300, mode: 'CMYKColorMode',7 name: 'hello world', fill: 'transparent'});
Note that, since createDocument
is an expensive operation, you need to use await
(or .then
) to wait for its completion.
Finally, the app
object also exposes a method for opening a document. UXP does not allow arbitrary access to the local filesystem; for any file outside of your plugin's home folder, data folder, or temp folder, you must ask the user for access by presenting a (built into UXP) dialog.
Copied to your clipboard1const app = require('photoshop').app;2let entry = await require('uxp').storage.localFileSystem.getFileForOpening();3const document = await app.open(entry);
See the reference for more methods and properties of the app
object. But here's one final very useful method: to show a simple alert, use this code:
Copied to your clipboard1const app = require('photoshop').app;2await app.showAlert('There's no business like show business');
Document
A single, open, Photoshop document. From this object, you can access the document's layers, its dimensions, resolution, etc. You can crop it, add/delete/duplicate layers, resize, rotate, and save it.
For example, to get the dimensions of the active document:
Copied to your clipboard1const app = require('photoshop').app;2const myDoc = app.activeDocument;3const docHeight = myDoc.height;4const docWidth = myDoc.width;5const docResolution = myDoc.resolution;6await app.showAlert(`Doc size is ${docWidth} x ${docHeight}. Resolution is ${docResolution}`);
To get an array of all layers in a document, use code like this:
Copied to your clipboard1const app = require('photoshop').app;2const myDoc = app.activeDocument;3const docLayers = myDoc.layers; // returns an array of layer objects
A layer in that list includes a number of properties, including layer name, parent, whether it's locked or not, etc.
And to create a layer, do this:
Copied to your clipboard1const app = require('photoshop').app;2const myDoc = app.activeDocument;3const myLayer = await myDoc.createLayer({name:'hello layer'});
Other methods available in the document
object include merging and grouping layers, flattening, saving, closing, resizing, and rotating.
Layer
With this class, you can delete and duplicate layers, move them around, link them, rotate them, scale/skew them, and get their parent (but not their children).
There is only one Layer class as of this writing. Ultimately, there will be subclasses for the different layer types.
For a full discussion of the layer
class, see the API Reference. Here's an example of how to scale a layer named "foo":
Copied to your clipboard1 const app = require('photoshop').app;2 const myDoc = app.activeDocument;3 const docLayers = myDoc.layers;4 // there's no "getLayerByName" method, so we loop until we find the layer:5 for (let i=0; i< docLayers.length; i++) {6 if (docLayers[i].name == 'foo') {7 await docLayers[i].scale(50, 50);8 }9 }
Actions and ActionSets
Many Photoshop users make heavy use of the Actions
panel. Actions are basically macros that you can record and play back to script commands and tools that you use frequently. Actions are grouped into Action Sets
, similarly to the way layers can be grouped into Layer Sets.
The Actions object allows you to delete, duplicate, rename, and play actions. There is no current way to create an action using UXP.
Similarly to Actions, the ActionSet object allows you to delete, duplicate, rename, and play Action Sets. There is no current way to create an Action Set.
Note that Actions and Action Sets exist app-wide; they're not tied to a specific Document.
Here's an example that finds a particular Action in the default Action Set, then plays it if it exists:
Copied to your clipboard1 const app = require('photoshop').app;2 const allActionSets = app.actionTree;3 const firstActionSet = allActionSets[0];4 let actions = new Map(); // a JS Map allows easy "find by name" operations5 firstActionSet.actions.forEach((action) => { actions.set(action.name, action)});6 const myAction = actions.get("Wood Frame - 50 pixel");7 if (myAction) { // user may have deleted this action8 await myAction.play();9 }
Again, for more information about these operations, see the API Reference.
batchPlay
Not all objects and actions are exposed in the current Photoshop UXP API. For those that aren't, the workaround is to use batchPlay. With batchPlay, you construct a JSON structure telling Photoshop which actions to perform. Unlike the ExtendScript method ExecuteAction, batchPlay allows you to chain multiple actions together and execute them in sequence.