I’d always thought that using the filter controls at the top of the layers panel was just a UI thing, that it hid layers in that panel, but had no other effect. I’ve just discovered that that is very wrong. If a layer is hidden with a layer filter then it cannot be selected by a plugin, which means an awful lot of operations that the plugin might want to perform on that layer won’t work.
I’ve just been scanning document and layer properties, both in the DOM and using Alchemist and I can’t see any changes in those when a filter is applied. In the UI filters can be set differently for each document, so it shouldn’t be an app property, but I had a quick look there anyway.
I’m also not seeing any events caught by Alchemist that suggest that I could determine whether a filter is applied or not. There is an event, but it’s a notifier and leaving an event handler watching permanently doesn’t feel lika good solution.
What I can do is to check whether my requests to make layers active are applied. If I call thisLayer.selected = true;, is thisLayer.selected actually true afterwards? At least then I can cancel processing cleanly with a message to the user to tell them to turn off layer filters and try again. I could even just process the layers that are not filtered out, although in my case I’m not sure that would be useful.
That seems very clunky. Anyone else hit this before and have a better solution?
Scratch that last bit, I don’t think I could just process the layers that are visible through the filter. If, for instance, the filter is set to show just pixel layers and the plugin converts them to smart objects they will now be filtered out and unselectable.
By far the best solution would be for the plugin to turn off the layer filter, but I can’t see any way to do that.
I think you are right. One of the features of filter is to prevent layers being selected. So if it is hidden by filter it cannot be selected but is still visible on canvas. If it was already selected it gets deselected.
And the action manager code legacy is that old actions needs layer being selected to make them work correctly. Those action references needs to be reworked @samgannaway
I am also not aware of how to turn on/off filters or how to detect them properly per document level.
Thanks @Jarda. I’ll liberally sprinkle checks that selecting layers actually selects them, and that there is a layer selected after conversion to a smart object etc. Then I can tell the user what they need to do and exit cleanly.
Conversion to smart object kills original layer ID makes a new layer and assigns new layer ID. Meaning instance of layer in DOM is useless unless you update ID. You need to get the new ID but last time I checked conversion to SO does not return newly created layer ID. So you have to get layer ID somehow. One way is to get all layerIDs in document before and after that and compare the changes. Easier approach is to use selected layer as a result of conversion to SO and assign ID based on selected layer… but if it cannot be selected because it is hidden by filter it will fail.
I think you meant app.activeDocument.activeLayers.length === 0 so [0] was typo.
Conversion to smart object could fail e.g. if you are in indexed color mode typical for GIF because it can have only one layer. In one layer color modes you have always exactly one layer active and layer filter is disabled. And batchPlay does not throw an error by default so you would need to rethrow. …but in such case majority of all actions would fail anyway. So it is just nitpicking.
Still new to Javascript, so I’m never sure when to use == and when === (other than for comparison with null).
By the time I hit any of these cases in the plugin I’m currently working on the doc will never be in indexed or multichannel mode. And I have batchPlay inside a wrapper that handles the errors.