Alchemist Plugin Question

I have started to use the Alchemist Plugin by @Jarda mainly in the Listener Mode to try and get to grips with how this UXP stuff works but I have a question which is slightly bugging me.

Using Alchemist I have recorded 2 actions

1: Extend the document canvas
2: Duplicate the layer

In the Index.js I have made a function and added the generated code from the Extend Canvas Reordered Action.

function ExtendCanvas () {

const batchPlay = require(“photoshop”).action.batchPlay;

const result = batchPlay(
[
{
“_obj”: “canvasSize”,
“relative”: true,
“width”: {
“_unit”: “pixelsUnit”,
“_value”: 300
},
“height”: {
“_unit”: “pixelsUnit”,
“_value”: 300
},
“horizontal”: {
“_enum”: “horizontalLocation”,
“_value”: “center”
},
“vertical”: {
“_enum”: “verticalLocation”,
“_value”: “center”
},
“_isCommand”: true,
“_options”: {
“dialogOptions”: “dontDisplay”
}
}
],{
“synchronousExecution”: true,
“modalBehavior”: “fail”
});
}

The Generated code from the Duplicate Layer looks like this…

const batchPlay = require(“photoshop”).action.batchPlay;

const result = batchPlay(
[
{
“_obj”: “copyToLayer”,
“_isCommand”: true,
“_options”: {
“dialogOptions”: “dontDisplay”
}
}
],{
“synchronousExecution”: true,
“modalBehavior”: “fail”
});

Question:
How can I add the Duplicate Layer code to the Extend Canvas code so it runs them from the single ExtendCanvas () function.

Thanks

Ian

1 Like

Something like this will work. You probably don’t need to use await for each batchPlay because it is redundant I think with the “synchronousExecution”. However, this is how I’ve been doing it in my testing just to be double sure of synchronous execution.

You can declare the batchPlay var globally so you don’t need it in every function. Also, I don’t think you also don’t need to assign a const result variable to each batchPlay either. That would probably only be needed if you wanted a returned value from it.

I’m still new to using batchPlay myself but this is how I’ve been doing it which works.


 //declare global so you don't need it for every function
var batchPlay = require("photoshop").action.batchPlay;

async function extendCanvas(){
    
await batchPlay(
[
{
"_obj": "canvasSize",
"relative": true,
"width": {
"_unit": "pixelsUnit",
"_value": 300
},
"height": {
"_unit": "pixelsUnit",
"_value": 300
},
"horizontal": {
"_enum": "horizontalLocation",
"_value": "center"
},
"vertical": {
"_enum": "verticalLocation",
"_value": "center"
},
"_isCommand": true,
"_options": {
"dialogOptions": "dontDisplay"
}
}
],{
"synchronousExecution": true,
"modalBehavior": "fail"
});
    
await batchPlay(
[
{
"_obj": "copyToLayer",
"_isCommand": true,
"_options": {
"dialogOptions": "dontDisplay"
}
}
],{
"synchronousExecution": true,
"modalBehavior": "fail"
});
    
    
}
1 Like

Thank you @ddbell this has been driving me crazy all afternoon. The Alchemist listener is really good and is going to be a god send when it comes to learning UXP to m.

Many thanks for your input.

Ian

Batchplay can execute an array of ActionDescriptors, so you can call require("photoshop").action.batchPlay([Descriptor1, Descriptor2], {})
If you put each Descriptor in its own function, it becomes a lot more readable and reusable:

function extendCanvas(width, height) {
  return {
    "_obj": "canvasSize",
    "relative": true,
    "width": {
      "_unit": "pixelsUnit",
      "_value": width
    },
    "height": {
      "_unit": "pixelsUnit",
      "_value": height
    },
    "horizontal": {
      "_enum": "horizontalLocation",
      "_value": "center"
    },
    "vertical": {
      "_enum": "verticalLocation",
      "_value": "center"
    },
    "_isCommand": true,
    "_options": {
      "dialogOptions": "dontDisplay"
    }
  }
}

function duplicateLayer() {
  return {
    "_obj": "copyToLayer",
    "_isCommand": true,
    "_options": {
      "dialogOptions": "dontDisplay"
    }
  }
}

require("photoshop").action.batchPlay([extendCanvas(300,300), duplicateLayer()], {})

The empty object at the end is for the batchPlay Options, where you can put
{
“synchronousExecution”: true,
“modalBehavior”: “fail”
}
etc

edit: Oops, my reply came a little too late

1 Like

Also, just because it is synchronous within the function itself doesn’t mean that scripting outside the function will wait for that function to finish. So you need to use “await extendCavnas();” from within another async function if you want each of your combined functions to run synchronously with each other.

So something like this is you need to create and run multiple functions back to back. I learned quickly about things getting out of sequence with batchPlay :slight_smile:

async yourSequencing(){

await yourFunction1();
await extendCanvas();
await yourFunction2();

}

After recording an action in Listener mode of Alchemist, do you know if there is a way to hide all the history state changes as it gets confusing trying to filter out what you need.

Screenshot 2020-10-28 at 17.30.08

Thanks for the heads up on running multiple descriptors at once. I just started messing with it a couple of days ago. That will be helpful in some cases for sure. I was wondering why it was called "batch"Play. I’m just transitioning over from ExtendScript myself and trying to make sense of all the new ways…

1 Like

Sure. You can switch main dropdown into “Listener” mode and add any event name in the exclusion list. Like this:
image

Once you set the filter you can remove all hidden items like this:
image

1 Like

And if you want to run multiple actions in single batchplay you can just select multiple items and those will be shown merged in generated code like this:

2 Likes

@Jarda Perfect. This is exactly what I was looking for. Thanks for taking the time to respond.
Ian