Copy link to clipboard
Copied
I came across this post of GDSE and now, it nearly being the end of 2023, can anyone confirm or deny if this (unsourced) statement "...Action manager won't be supported in newer versions of Photoshop." is true or not??
Is this a random rumour? Or is it anything that Action Manager coding fans should be concerned about? Clarity with an explantion is due.
The truth is out there with a side order of cookies...
Copy link to clipboard
Copied
Rightly, or wrongly let us assume that UXP is the future...
An immediate (interim/bridging) solution would be a (Hail Mary) UXP script that can read a classic .jsx and run it as normal - kind of a wrapper for the original.
That's got to be possible, surely?
Copy link to clipboard
Copied
sorry for the question but now how do you program, do you use actions do you use javascript or what
Copy link to clipboard
Copied
A combination of Extendscript, Action Manager, and Actions usually.
This is the script I use to implement the above image, starting with no text overlay and ending with a finished, saved PSD and JPEG. Weight saved to dc:description and vendor part number (second line) saved to Photoshop:transmissionReference. The actions align the text layer, save a PSD, and Save for Web. Please feel free to laugh at how bad this code is LOL
#target photoshop
testText();
function testText(){
if(documents.length > 0){
var originalDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.ERROR;
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var docRef = app.activeDocument;
var fileNameNoExtension = docRef.name;
//text formatting
var size1 = 96;
var size2 = 60;
var size3 = 54;
var size4 = 42;
var font1 = 'Calibri';
var font2 = 'Calibri';
var style1 = 'Bold';
var style2 = 'Regular';
var texth = 220;
var textw = 660;
try{
var vendorItem = '';
var itemWeight = '';
var newText = '';
var LayerRef = null;
var TextRef = null;
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
var xmp = new XMPMeta(docRef.xmpMetadata.rawData);
for(var x = 0; x < documents.length; x++){
activeDocument = documents[x];
docRef = documents[x];
fileNameNoExtension = docRef.name;
vendorItem = '';
itemWeight = '';
newText = '';
LayerRef = null;
TextRef = null;
xmp = new XMPMeta(docRef.xmpMetadata.rawData);
if(xmp.doesPropertyExist(XMPConst.NS_DC, 'description')){
itemWeight = xmp.getLocalizedText(XMPConst.NS_DC, 'description', null, 'x-default');
docRef.info.headline = itemWeight.toString();
}
if(xmp.doesPropertyExist(XMPConst.NS_PHOTOSHOP, 'TransmissionReference')){
vendorItem = xmp.getProperty(XMPConst.NS_PHOTOSHOP, 'TransmissionReference').toString();
}
if(itemWeight == null){
preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;
return;
}
vendorItem = vendorItem.toUpperCase();
preferences.rulerUnits = Units.PIXELS;
for(var i = 0; i < docRef.artLayers.length; i++){
if(docRef.artLayers[i].kind == LayerKind.TEXT){
docRef.artLayers[i].remove();
}
}
fileNameNoExtension = docRef.name;
fileNameNoExtension = fileNameNoExtension.split('-');
if(fileNameNoExtension.length > 1){
fileNameNoExtension.length--;
}
fileNameNoExtension = fileNameNoExtension.join('-');
fileNameNoExtension = fileNameNoExtension.split('.');
if(fileNameNoExtension.length > 1){
fileNameNoExtension.length--;
}
fileNameNoExtension = fileNameNoExtension.join('.');
if(vendorItem == ''){
newText = fileNameNoExtension;
}
else{
newText = fileNameNoExtension + '\r(' + vendorItem + ')';
}
if((docRef.name.search('-front') != -1) || (docRef.name.search('-back') != -1)){
if(fileNameNoExtension.length > 6){
app.doAction('2000','EGP');
}
else{
app.doAction('1800','EGP');
}
}
LayerRef = docRef.artLayers.add();
LayerRef.kind = LayerKind.TEXT;
TextRef = LayerRef.textItem;
TextRef.kind = TextType.PARAGRAPHTEXT;
TextRef.contents = newText + '\rShipping Weight: ' + itemWeight;
TextRef.position = new Array(425, 425);
preferences.rulerUnits = Units.POINTS;
TextRef.size = size1;
TextRef.useAutoLeading = false;
TextRef.leading = size4;
TextRef.font = font1;
TextRef.style = style1;
TextRef.justification = Justification.CENTER;
TextRef.autoKerning = AutoKernType.METRICS;
layerUpdate();
function setFormatting(start, end, fontName, fontStyle, fontSize){ //format text per input
var idsetd = app.charIDToTypeID('setd');
var action = new ActionDescriptor();
var idnull = app.charIDToTypeID('null');
var reference = new ActionReference();
var idTxLr = app.charIDToTypeID('TxLr');
var idOrdn = app.charIDToTypeID('Ordn');
var idTrgt = app.charIDToTypeID('Trgt');
reference.putEnumerated(idTxLr, idOrdn, idTrgt);
action.putReference(idnull, reference);
var idT = app.charIDToTypeID('T ');
var textAction = new ActionDescriptor();
var idTxtt = app.charIDToTypeID('Txtt');
var actionList = new ActionList();
var textRange = new ActionDescriptor();
var idFrom = app.charIDToTypeID('From');
textRange.putInteger(idFrom, start);
textRange.putInteger(idT, end);
var idTxtS = app.charIDToTypeID('TxtS');
var formatting = new ActionDescriptor();
var idFntN = app.charIDToTypeID('FntN');
formatting.putString(idFntN, fontName);
var idFntS = app.charIDToTypeID('FntS');
formatting.putString(idFntS, fontStyle);
var idSz = app.charIDToTypeID('Sz ');
var idPnt = app.charIDToTypeID('#Pnt');
formatting.putUnitDouble(idSz, idPnt, fontSize);
textRange.putObject(idTxtS, idTxtS, formatting);
actionList.putObject(idTxtt, textRange);
textAction.putList(idTxtt, actionList);
action.putObject(idT, idTxLr, textAction);
app.executeAction(idsetd, action, DialogModes.NO);
}
function layerUpdate(){
try{
preferences.rulerUnits = Units.POINTS;
TextRef.textComposer = TextComposer.ADOBESINGLELINE;
if(TextRef.size == size1){
TextRef.size = size4;
TextRef.font = font2;
TextRef.style = style2;
TextRef.useAutoLeading = false;
TextRef.leading = size4;
var l = TextRef.contents.split(/\r/);
setFormatting(0, l[0].length, font1, style1, size1);
var textFragmentLen = l[0].length + l[1].length + 1;
if(l.length > 2){
setFormatting(textFragmentLen, (textFragmentLen + l[2].length -8), font1, style1, size4);
}
else{
var sectextFragmentLen = l[1].split(':');
setFormatting((textFragmentLen - l[1].length), l[0].length + sectextFragmentLen[0].length + 2, font1, style1, size4);
}
preferences.rulerUnits = Units.PIXELS;
if(TextRef.kind == TextType.PARAGRAPHTEXT){
TextRef.height = texth;
TextRef.width = textw;
TextRef.useAutoLeading = false;
TextRef.leading = size4;
}
app.doAction('Align title', 'EGP');
app.doAction('Save', 'EGP');
app.doAction('SFW', 'EGP');
}
}
catch(e){
alert(e + ' ' + e.line);
return;
}
}
}
}
catch(e){
preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;
return;
}
preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;
}
else{
alert('You must have a document open to run this script.');
return;
}
}
Copy link to clipboard
Copied
@Lumigraphic I've seen the code and it shouldn't be difficult to get the result, the only problem that could arise is the use of tokens for importing images and saving them, this is due to the restrictions of some operating systems. An example of how to use an action in the action panel.
Example:
let command = [
{“_obj”: “play”, “_target”:[{“_ref”:“action”,“_name”:“Action 1”},{“_ref”:“actionSet”,“_name”:“My Action Set”}], “_options”: {“dialogOptions”: “dontDisplay”}}
];
let result = await require(“photoshop”).action.batchPlay(command, {});
in uxp there is also a powerful tool that is similar to scrptenlistener, does various things, for example converts actions into uxp code.
the application is called Alchemist and is distributed free of charge.
Copy link to clipboard
Copied
Thank you. I'm just frustrated, if you look at the forums that is probably as much of an issue as actual technical problems. Adobe seems to have lost their way and they are making things harder, not easier, for their customers.
Copy link to clipboard
Copied
Unfortunately it is not possible You need to learn some uxp code but if you create actions to convert, everything is simpler.
Copy link to clipboard
Copied
You may want to look around here:
https://forums.creativeclouddeveloper.com/search?q=jsx
(this is to reply to the question about running JSX in the context of UXP)
Davide
Copy link to clipboard
Copied
Davide you know very well that investing time to use jsx again is wasting time, So it's better to invest the time to study uxp.
Copy link to clipboard
Copied
Thanks for the tip, Davide. Looks like I need to start saving up for your book.
Well... not today, but at some point, this old carcass will have to learn UXP. Not today
But when that eventful day happens, I'll break free from the tradition of "Hello world!" and have something different like "Hello Adobe".
Only much, much, much ruder.
Copy link to clipboard
Copied
May I ask :
1. I follow the code you provided, but I get an exception while attempting to assign "result" to "PIUASZString" , which gives me the error on the line (REQUIRE_NON_NULL (sASZString);) saying like "sASZString" is NULL
err = sScriptingSuite->ExecuteScript(engineRef, un, kJSExecutionModeNoDebug/*kJSExecutionModeNoDebug*/, &result);
PIUASZString aszResult(result);
2. Where are the source files of this part??
returnMsg = icu::wstringToString(resultString);
if (err == kJSScriptExecutionError) {
showError(ag::ps::failedExecution);
}
Copy link to clipboard
Copied
Hey
There might be a proper API Photoshop one for it, but I didn't find it, so I have this >
inline std::string wstringToString(const std::wstring &wstr) {
std::string str;
str.reserve(wstr.length());
for (const auto &wchar: wstr) {
if (wchar <= 0x7f) {
str.push_back(static_cast<char>(wchar));
} else if (wchar <= 0x7ff) {
str.push_back(static_cast<char>((wchar >> 6) | 0xc0));
str.push_back(static_cast<char>((wchar & 0x3f) | 0x80));
} else if (wchar <= 0xffff) {
if (wchar >= 0xD800 && wchar <= 0xDFFF) {
// Surrogate pair values are invalid in UTF-32
//throw std::invalid_argument("Invalid wide character in input");
continue;
}
str.push_back(static_cast<char>((wchar >> 12) | 0xe0));
str.push_back(static_cast<char>(((wchar >> 6) & 0x3f) | 0x80));
str.push_back(static_cast<char>((wchar & 0x3f) | 0x80));
} else if (wchar <= 0x10ffff) {
str.push_back(static_cast<char>((wchar >> 18) | 0xf0));
str.push_back(static_cast<char>(((wchar >> 12) & 0x3f) | 0x80));
str.push_back(static_cast<char>(((wchar >> 6) & 0x3f) | 0x80));
str.push_back(static_cast<char>((wchar & 0x3f) | 0x80));
} else {
// Code points above 0x10ffff are invalid in Unicode
}
}
return str;
}