Photoshop UXP BatchPlay For Beginners

I’m not sure if I am only own here or maybe there are others out there in the same position so I guess this could be classed as a request more than anything.

From what I understand, the API for the UXP Plugins is an ongoing project and as time moves forward more will be added.

In the meantime, from the Docs I have read, we are been encouraged to use the BatchPlay method for filling in the gaps to the API which are not currently available.

Also from my own research, the best tool we have to inspect Photoshop is the Alchemist Plugin which can be used to Generate Code from various tasks we do in Photoshop as well as Inspecting different parts of Photoshops activities and active documents etc.

BatchPlay Code Examples
What I would personally like to see and again, there maybe others out there in the same position who would like to see some code examples on how to use Alchemist along with BatchPlay in order to further understand this new UXP system.

Scenario
Here is a typical scenario which I would like to perform but has got me completely baffled due to the level I am at.

From the Active Document in Photoshop, using the Alchemist Plugin, generate the code and return the color space the active document is in which could either be RGB or Grayscale

Thanks
Ian

2 Likes

The whole BatchPlay approach is definitely much more self-explaining if you already had contact with Action Manager code in CEP panels, as it’s just like a better version of it with less required syntax.
So don’t get discouraged, the beginning of learning it is difficult but once the concept get’s more clearer you see a lot of recurring patterns. Essentially, you send directions to Photoshop (for example set or get some objects/property) that get assigned to a specific element like the active Document or the layer at index 23 etc. (that’s the _ref part or the BatchPlay object)

I agree that more code examples would be helpful for certain scenarios, I’m sure now that UXP is public there will be a lot more examples and open-source repos coming in the next weeks & months.

For your specific scenario, it’s helpful to just inspect the available properties in Alchemist. You can either browse through the property dropdown and see what properties are there or add the descriptor for the whole document (without a property selected) and browse through the tree-content in the main view on the right.

You can click the pin icon in this view to pin a single property. If you go to the generated code, it will respect the pin and adjust the code:

const batchPlay = require("photoshop").action.batchPlay;

const result = await batchPlay(
[
   {
      "_obj": "get",
      "_target": [
         {
            "_ref": "document",
            "_id": 271
         }
      ],
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});
const pinned = result[0].mode;

If you already select the property from the dropdown, only the mode property will be fetched:

const batchPlay = require("photoshop").action.batchPlay;

const result = await batchPlay(
[
   {
      "_obj": "get",
      "_target": [
         {
            "_property": "mode"
         },
         {
            "_ref": "document",
            "_id": 271
         }
      ],
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});

The results are the same, but the second approach has better performance since not all other document properties will be fetched, only the mode property.
If you log the result from the above code, you will see that it’s an array of objects (descriptors), where the first has the property mode:
modeobject
So you can’t use it as is, instead you get the mode via
result[0].mode

Also note, that the generated Code references the document by its ID. If you want to reuse the code, you should alter this part to reference the active document, otherwise your code will only work on this specific document. Also, for getters it’s fine to set the synchronousExecution to true, because you’ll want to wait for the result anyway:

function getDocumentMode() {
    const batchPlay = require("photoshop").action.batchPlay;
    return batchPlay(
      [
         {
            "_obj": "get",
            "_target": [
               {
                  "_property": "mode"
               },
               {
                  "_ref": "document",
                  "_enum": "ordinal",
                  "_value": "targetEnum"
               }
            ],
            "_options": {
               "dialogOptions": "dontDisplay"
            }
         }
      ],{
         "synchronousExecution": true,
         "modalBehavior": "fail"
      })[0].mode;
  }

Many properties in Photoshop don’t just come as the value, instead it’s incapsulated in an
{
_enum: …
_value: …
}

object.

So here’s an example of how to log the mode as a string:
console.log(getDocumentMode()._value)

3 Likes

Simon, this is excellent and I would like to say thanks for taking the time to explain this step by step and I am sure other people are going to find this useful.

I shall grab a coffee and study everything you have wrote here and then attempt to put it into practice.

Got this working now thanks Simon.
I now have a better understanding on how to use Alchemist and hopefully, after some more experimenting, I can move forward now.

1 Like

You’re welcome, great that you got it working. Sometimes it’s better when the copied code doesn’t work right away, this makes you analyse and understand it much better :nerd_face:

2 Likes