My employer tasked me with the development of a Photoshop UXP plug-in, but after some reading I’m beginning to doubt the feasibility of the project. Please, correct me if I’m wrong.
These are some of the plug-in’s requested core features:
Export the contents of various layer folders to predefined directories as TGA files by simply pressing an “Export” button in the plug-in’s UI panel. (No SaveAs dialog pop-up!)
Before exporting, some layer folders are merged down to single black and white layers and then mapped to certain color channels of the document. (for example: folder1 becomes the R channel, folder2 becomes the G channel etc.)
The aforementioned target directories used during saving are defined by the user in text fields in the plug-in’s UI panel and stored permanently within the PSD file itself.
If any of these points are beyond UXP’s capabilities, are there alternative means for developing plug-in-like companion applications?
Thanks for the reply.
That was unexpected news. I specifically saw someone on this forum say that it was impossible(!) to avoid the SaveAs dialog when saving files programmatically. And there is no example code to be found that would suggest otherwise.
Were you forced to write a JS/C++ hybrid plug-in in order to get all this to work?
Path can be defined in plugin text area and you just grab that value before running function.
Wouldn’t closing Photoshop clear these text fields, though? And IF data can in fact be saved between sessions, is there even a way to do so on a per PSD basis? Not from my experience.
Before I leave and have one last go at this plug-in, perhaps a few general questions if I may:
How does one avoid constant trial and error with UXP? Development has been moving at a snail’s pace so far, because every other line of code throws an error initially, and every error has to be googled - oftentimes unsuccessfully. Is everyone having this same experience with UXP?
Coming from Python development, I was originally hoping to have this plug-in completed within a single day, because what it does is so trivial.
Is there perhaps a support Discord where people can go to ask about issues with specific lines of code as I don’t intend to make new forum threads on a daily basis?
@Pmax
Feasible does not mean easy, I have been studying UXP for a few months now and what you intend to do is not easy if you don’t know UXP, session tokens are needed, then you need strings of code that you will have to find or invent.
I’m not a Photoshop expert, so I’ll leave the PS-specific questions to others. Regarding this point, however, here are my thoughts (having been a UXP developer since UXP became available in 2018):
Trial and error is a part of developing plugins. This is only natural given that these applications (host apps, may that be Photoshop, XD, or InDesign) weren’t designed to support your plugin’s specific use-case. So developing plugins is basically a discipline of working around what the host app comes with (as its core features) to enable the plugin’s features.
Of course, with experience, you gain a bit more intuition of what might or might not be possible and how to go about it. That, however, requires dedicated specialization in the field. In other words: there is a reason why I and other plugin developers can make a living from their expertise in this relatively small market.
A part of that expertise is also how to efficiently (and cost-effectively, so to speak) navigate trial and error-based development within the UXP environment (in my case, this, e.g., involves custom-built developer tooling, and much more).
Another part of that expertise is ways to find knowledge on how to achieve something. For InDesign (where I’m currently working on a plugin for a client), that entails searching through ancient forums, PDFs, and much more. For Photoshop (as I said: not my specialization!), a part of it is to experiment with @Jarda’s Alchemist plugin, reading up on how batchPlay works, and much more. Another part of an experienced plugin developer’s tool belt is, in all honesty, knowing who in the community and at Adobe to (and how to) contact, utilizing events like office hours, and more. All of this, however, is quite unique to plugin development. For other development environments, chances are you’ll find an answer to a related question on Stack Overflow (or simply through your general experience of googling things from potentially years of software development).
That isn’t to say, of course, that you need to have all these things to begin with. This community is, in my experience, extremely welcoming and happily helps with questions (as long as you’re not asking them to develop it for you free-of-charge, which some have tried in the past). For Photoshop in particular, an incredible resource for getting started exists in the form of @DavideBarranca’s books.
But yes: it is a unique field to get into, with quite a steep learning curve if you try to do it economically (this, of course, isn’t as much of an issue when you’re just working on a side project). And it isn’t “just another field of software development” (or if it is, it’s more akin to embedded development in how specialized it is/additional knowledge is needed). To summarize, at the risk of sounding harsh (but trying to give you an honest answer): it is its own unique field, and there’s a reason developers can specialize in it. What you lack in experience (in the beginning), you will pay for in time (may that be learning how to research UXP knowledge, waiting for replies on forums, not having good strategies for trial and error in UXP, yet, etc.). It will always involve trial and error (that just comes with the field), but with experience, you’ll find less frustrating ways (and perhaps build your own tooling) to navigate that.
We ended up creating a pure JS/HTML plugin without the use of C++.
Exporting to .tga without a dialog is possible.
You can save the path to a .txt or .json file and store it locally somewhere on the disk. Then, when you initiate the plugin, you will read that file and put those values inside a text field.
Personally, I came from a Python Maya environment, and it took me around a month to learn JavaScript, UXP, and the Photoshop API.
You have to experiment a lot and take some time to learn the stuff. Don’t expect to be able to jump from Python straight to the Photoshop API.
Check this youtube channel:
and also this is great resource (my employer bought me the book, you should ask yours)
Here is a very basic demo I made a long time ago that does what you want except the file format and the channel separation. Replacing the save function with code for your file format would be trivial. Channel separation is going to take some work on your part.
@pklaschka
Thank you for that very informative post. An invaluable look into the world of full-time Adobe plug-in development that I wish me and my team could have had on day one.
There is absolutely no way that my employer is going to pay for even another 1-2 weeks of development, let alone learning materials – so this experiment is mosty likely going to come to an end real soon. At least now, thanks to you, the cancellation would be a well-informed decision that I can get behind.
You can save the path to a .txt or .json file and store it locally somewhere on the disk.
Our artists and project manager wouldn’t accept that I’m afraid. Also, this approach could potentially lead to inconveniences when files get renamed/deleted/moved, especially with versioning on top of that.
I’ll definitely check out that Youtube channel, though.
Glad it has helped - it was such a common question on the forum it was easier to build that than keep explaining it!
In regards to one of the other points raised - you didn’t seem keen on saving the export paths in a json file. You could store them in the file’s metadata instead. That presents its own set of challenges and considerations but it’s viable I guess.
I was just reading about XMP when you posted this, only I hadn’t found that particular thread yet.
I’m happy to say that I’m now able to read and write custom meta data from my PSD file. One tiny step closer to something usable.
the reason Adobe plug-in development is so torturously complicated is not because plug-in development is “trial-and-error-based” or “akin to embedded development”.* it’s because Adobe’s UXP development team has devised a set of platforms and APIs so incredibly unintuitive and ineffective, beneath a layer of “tooling” and “documentation” so fragmented and incomprehensible, that I’m sure ChatGPT could’ve done a better job in an evening than has been done over all these years.
*just try writing an extension for Chrome, or for VS Code, or hell, even a mod for a game, and you’ll see just how incredibly easier and more productive extensibility can be. and no, the fact that those two specific programs already run on web platforms is no excuse; the UXP run-time itself is already pretty functional and all of the horrible design decisions on top of it could’ve been prevented, or even reverted.
@Timothy_Bennett
As it turns out, one of those challenges of using XMP to store folders is the fact that they can’t be stored as Folder objects inside the json block.
What I initially got from fs.getFolder() ends up looking like this in the XMP data:
There appears to be no way to revert this string to a Folder object which, as it seems, is required when saving a file: folderobjectvariable.createFile().
Could this be a dead end after all, or is there a way to create Folder objects from scratch?
@catte
It may also have to do with Photoshop being over 30 years old as well as the sheer size of the entire Adobe suite. I mean, good luck refactoring that. Many things would need to be rebuilt from the ground up if you were going for something as accessible as a moddable video game.
That being said, I wouldn’t mind Adobe giving it a try.
Alright, after some trial and error I am finally able to save PSD files to string locations stored in the XMP data.
Here are two more issues I had to fix to make it work:
Outdated minVersion in the manifest: I used @Timothy_Bennett 's Github project as a basis, and it turns out it was written for an older version of Photoshop (22.0.0) that did not yet understand getEntryWithUrl().
The manifest did not yet include "requiredPermissions": { "localFileSystem": "fullAccess" } which is a requirement for getEntryWithUrl() to actually work.
This is a huge milestone for me.
Hopefully I can handle the remaining plug-in features a little more independently.
Thanks to everyone who helped me up to this point.