How to get, set and unset layer color?

The title says it all I think :slight_smile: It’s about that eye icon in layers list.
I think set and unset should be done with batchPlay, right? But is there any way to get the color?

So I found this topic about document bits and managed to get a color of one active layer with:

batchPlay(
    [{
      "_obj": "get",
      "_target": [{
          "_property": "color"
        },
        {
          "_ref": "layer",
          "_enum": "ordinal",
          "_value": "targetEnum"
        }
      ],
      "_options": {
        "dialogOptions": "dontDisplay"
      }
    }], {
      "synchronousExecution": false,
      "modalBehavior": "fail"
    })

But the result is a bit strange. There are seven colors I can assign to layers and five of them return usual color names (red, blue, orange, etc.), but two of them are different. Yellow is yellowColor and green is grain :confused: I’m a bit lost here. Is there some real documentation with full reference about all this batchPlay and descriptors stuff?

Another problem I have - how to get a color of a particular layer I have as an object in UXP script? I guess same question goes for setting the color and unsetting

Those color names are correct. They originate from mistakes that were done many years ago, for example the grain/green thing exists due to the accidental double assignment of the char-code "Grn ".
There is no documentation on every single internal property of Photoshop that you can target via BatchPlay, however I started to create Typescript types for some stuff, where you can also see the ColorNames.

You can’t really directly mix BatchPlay and DOM code, but you can get the id from a layer object and then use it to set the target of the Descriptor that you put into the batchPlay function.

I’m not really familiar with TS and read the readme, but didn’t get how I can get it working on VSC :confused:
And I see there you still have green, is that correct? Shouldn’t it be grain?

How do I do that?


I’m also trying this:

  batchPlay(
    [{
      "_target": [
       {
        "_ref": "layer",
        "_enum": "ordinal",
        "_value": "targetEnum"
       }
      ],
      "to": {
       "_obj": "layer",
       "color": {
        "_enum": "color",
        "_value": "blue"
       }
      },
      "_isCommand": true
     }], {
      "synchronousExecution": true,
      "modalBehavior": "wait"
    }
  );

But can’t figure out why I get this error and what it means:

VM997 <…>\index.js:202 Uncaught Error: Invalid command Property ‘descriptor’ is missing

There’s so little info on descriptors :frowning: Google also isn’t helpful at all

You don’t have to use TS, it’s just some kind of assistance to be more type-safe and get less runtime errors. However, the types can give a clue about the internal structure of some of the objects inside Photoshop.

Yep, the actual value is grain. I probably just messed around with setting the color, in that case it doesn’t really matter, as both grain and green will be converted to "Grn " internally, so the result is the same. If you want to check whether a layer color is green however, you’d have to match it against grain of course.

The _ref thing defines the class of the object (layer) you want PS to send the descriptor to, this one stays the same. Instead of the target layer (_enum: "ordinal", _value: "targetEnum") you can add other keys to reference specific layers, for example _name or _id.

Not sure about your error, the descriptor looks fine at first glance. You can also try to google for CEP/ActionManager code, the structure is still the same but the syntax is different. I think there was a tool also to convert AM to UXP.

Anyways, Alchemist is always a good starting point to inspect various descriptors.

Tried this a couple of hours ago actually :slight_smile: But it’s a bit overwhelming :smiley: Didn’t see more value than a simple app.eventNotifier usage. Maybe I’ll have to play with it more.

So that’s what I’m interested in :slight_smile: Is there a place I can see what I can use? Just listening for events always gives structure of active elements and I have no idea what other options I have. And I guess it’s not only for _target, but other properties I might be missing. Like getters for example :slight_smile:

Is this the TS thingy?
image

If it is, then _name isn’t there also. Or I misunderstood something? And suggestions are the same no matter what the parent property is. Is this how it works?


Sorry for all the noob questions all over the UXP API category :smiley: Trying to write a couple simple plugins before I proceed to a much more complex one I was thinking about for almost a year now, which I think still might be not achievable for me, until more DOM (API endpoints) are available and we wouldn’t have to rely so much on batchPlay :slight_smile:

If you select specific properties in Alchemist and add the descriptor, the generated code will be a getter for that property actually.

Looks like it’s just the normal intellisense/autocomplete of vsc. Those are probably suggestions based on things you’ve wrote before. Typescript has to be installed (via npm or yarn) and then you get suggestions that fit the actual model of the object, given that you have the type definitions for that type of object. Here’s an example of how that looks.
It doesn’t help you with constructing your descriptor though - It just helps me when I’m working with descriptors returned from getter functions.

There isn’t really some UXP specific documentation on all that, but there are a lot of AM examples on the internet and as mentioned, batchPlay is kind of the same just with other syntax. You can look at Old docs and search for “ActionDescriptor” or “ActionReference” to get an idea of what you could do with those:
image
As you can see, there isn’t much more to it than referencing layers by index, name, id or enum value (target layer, next layer, previous layer, …). In batchPlay that’s done by adding _index, _name or _id to the target object for example.

1 Like

Thanks for all your help and resources :slight_smile:

It seems I’ve got my first simple JS plugin logic fully working, except for the above mentioned JS error about invalid descriptor missing and strange layers moving issue, which I still need to solve and - I believe - wait for Adobe to fix layer moving, because it just doesn’t behave like it should.

It seems batchPlay() isn’t considering passed target _id. I try:

batchPlay(
[
   {
      "_obj": "set",
      "_target": [
         {
            "_ref": "layer",
            "_id": 2
         }
      ],
      "to": {
         "_obj": "layer",
         "color": {
            "_enum": "color",
            "_value": "grain"
         }
      },
      "_isCommand": true
   }
],{
   "synchronousExecution": true,
   "modalBehavior": "execute"
});

But it still sets color to the active/selected layer and not to the layer ID 2.
Any tips @simonhenke?

Some things, such as transform only work on the active layer. It’s kinda bad design if you ask me, but that’s how it is unfortunately. Seems like setting the color is one of those things. If you inspect the descriptor that gets returned when the promise is resolved, you see that it always sets the target back to {_ref: "layer", _enum: "ordinal", _value: "targetEnum"}

You can however simply select the layer beforehand:

export function __selectByID(id: number) {
  return {
    _obj: 'select',
    _target: { _ref: 'layer', _id: id },
  }
}
1 Like

I see. That’s what I actually was thinking, but thought I was missing something. I’ll have to do this with multiple layers selected. Also would have to restore selection that was before changing colors of the layers I need. Well… I’d say not a very nice solution, but it seems it’s the only one.

Thanks a lot for all the tips.