Upgrading to API 2 reduces exposed layer properties

Hoping to get some clarification as to why this happens.

With apiVersion set to 1 you get a deprecated warning, but you also get a a full list of all layers when calling app.activeDocument.layers. Each layer object has an array of children objects. This structure makes it easy to build a full snapshot of the entire layer structure of a file without having to use BatchPlay.

With API2, only the top-level layers are listed and as far as I can see there is no access to children info.

This seems odd to me that upgrading the API results in less usability. Is there a reason for this?

Each group should have .layers property with its childs.

Ah you’re correct. Thanks. I need to use BatchPlay to get layers anyway since recursing these objects is too slow.

Yes it is… since there is no caching and it asks PS so many times…

Make sure to check multiGet first. https://twitter.com/J_Bereza/status/1555977684479627265

Also, you can always make a new Layer() instance based on IDs.

@Jarda or anyone:

I tried to use the Twitter thread code linked above to create a list of all layers in the document. Here’s the code I’m using:

const docRef = {
    _ref: "document",
    _id: this.id,
};

const allLayers = await batchPlay([{
    _obj: "multiGet", 
    _target: docRef,        
    extendedReference: [
        [
            "name", 
            "layerID",
        ], 
        {
            _obj: "layer", 
            index: this.backgroundLayer ? 0 : 1, 
            count: -1,
        },
    ],
},], {"modalBehavior": "execute",})
.then(result => {return result[0].list}, error => {console.log(error)})

console.log(allLayers)

I get an error that says: Error: NAPI API failure: Number expected

and the line referenced as causing the error is:

.then(result => {return result[0].list}, error => {console.log(error)})

I get all kinds of syntax errors when I try to include the line:

public get allLayers():{name: string, layerID: number}[]{

So that’s why I tried coming up with some alternate code, but I’m obviously not getting it right.

Any thoughts?

multiGet is documented here: https://developer.adobe.com/photoshop/uxp/2022/ps_reference/media/batchplay/#multi-get

1 Like

Thanks for that reminder @Jarda.

Working code below. If anyone has any suggestions for simplifying or improving, please post.

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

const hasBackgroundLayer = await batchPlay([
    { _obj: "get", _target: [ { _property: "hasBackgroundLayer" }, { _ref: "document", _enum: "ordinal", _value: "targetEnum" } ], _options: { dialogOptions: "dontDisplay" } }
],{}).then(result => {return result[0].hasBackgroundLayer}, error => {console.log(error)});

const layerProperties = await batchPlay([
    { _obj: "multiGet",
     _target: { _ref: [{_ref: "document", _enum: "ordinal"}]},
     extendedReference: [["name", "layerID"], {_obj: "layer", index: hasBackgroundLayer ? 0 : 1, count:-1}],
     options: {failOnMissingProperty:false, failOnMissingElement: false}
  }], {});

console.log(layerProperties[0].list)

I think it should be ok like this for active document.

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

const hasBackgroundLayer = await batchPlay([
	{
		_obj: "get",
		_target: [
			{_property: "hasBackgroundLayer"},
			{_ref: "document", _enum: "ordinal", _value: "targetEnum"}
		],
	}
], {});

const layerProperties = await batchPlay([
	{
		_obj: "multiGet",
		_target: {_ref: "document", _enum: "ordinal"},
		extendedReference: [["name", "layerID"], {_obj: "layer", index: hasBackgroundLayer ? 0 : 1, count: -1}]
	}], {});

console.log(layerProperties[0].list)

Anyway, I would personally prefer to edit the document prototype or extend the Document class. So you can use this. keyword as shown in my tweet. https://developer.adobe.com/photoshop/uxp/2022/ps_reference/media/prototype/