Copy link to clipboard
Copied
As far as I can see these two lines of AM code sets idUsrM to true
var idUsrM = charIDToTypeID( "UsrM" );
desc43.putBoolean( idUsrM, true );
My question is how to I get the value of a variable in AM?
In a better context this code will enable a layer mask.
var idsetd = charIDToTypeID( "setd" );
var desc42 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref12 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref12.putEnumerated( idLyr, idOrdn, idTrgt );
desc42.putReference( idnull, ref12 );
var idT = charIDToTypeID( "T " );
var desc43 = new ActionDescriptor();
var idUsrM = charIDToTypeID( "UsrM" );
desc43.putBoolean( idUsrM, true ); // set to true here
var idLyr = charIDToTypeID( "Lyr " );
desc42.putObject( idT, idLyr, desc43 );
executeAction( idsetd, desc42, DialogModes.NO );
I want to set a variable to the opposite. ie switching it off when on and visa versa.
var layerMaskState = !layerMaskCurrentState;
Hopefully, that's reasonabaly clear. If not just say so.
1 Correct answer
Let me help a little with the ActionManager code 🙂
In fact, in Photoshop, in order to explore the properties of ActionManager objects, it is not necessary to loop through all of their keys. There is a handy convertJSONdescriptor function. As the name suggests, it takes an ActionDescriptor and converts it to a JSON string representation. Previously, its description could be found in the ccx-start.jsx file in the Required\CEP\extensions directory:
// Automatically convert to Action JSON, the
...
Explore related tutorials & articles
Copy link to clipboard
Copied
Of course, I can give you the code, but I advise you to read this topic and first try to do it yourself: Action Manager Scripting
Copy link to clipboard
Copied
I have read that post. - It stops just when it was getting good 😉
Also some of us need to learn with examples.
Copy link to clipboard
Copied
One way of toggling the layer mask without Action Manager code is to write a state to a text file:
Not elegant, but it works. And you don't even need to know what state it was in!
// Switch off any dialog boxes
displayDialogs = DialogModes.ERROR; // OFF
var f = "C:\\temp\\layer_mask_state.txt"; // layer mask file
var layerMaskState = read_it(f);
// toggle it!
if (layerMaskState != undefined)
{
layerMaskState = !layerMaskState;
}
else
{
layerMaskState = true;
}
layer_mask(layerMaskState);
// write_it
write_it(layerMaskState, f);
// Switch off any dialog boxes
displayDialogs = DialogModes.ALL; // OFF
function layer_mask(bool)
{
var idsetd = charIDToTypeID( "setd" );
var desc22 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref5 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref5.putEnumerated( idLyr, idOrdn, idTrgt );
desc22.putReference( idnull, ref5 );
var idT = charIDToTypeID( "T " );
var desc23 = new ActionDescriptor();
var idUsrM = charIDToTypeID( "UsrM" );
desc23.putBoolean( idUsrM, bool ); // set here
var idLyr = charIDToTypeID( "Lyr " );
desc22.putObject( idT, idLyr, desc23 );
executeAction( idsetd, desc22, DialogModes.NO );
}
function write_it(astring, afilename)
{
var exportFile = new File(afilename);
exportFile.open("w"); // write destroys
exportFile.writeln(astring);
exportFile.close();
}
function read_it(afilepath)
{
var theFile = new File(afilepath);
// read in file
var words = []; // text array
var textFile = new File(theFile);
textFile.open('r');
while(!textFile.eof)
{
var line = textFile.readln();
if (line != null && line.length >0)
{
words.push(line); // array
}
}
textFile.close();
if (words[0] == "true") return true;
if (words[0] == "false") return false;
return undefined;
}
Copy link to clipboard
Copied
Let me help a little with the ActionManager code 🙂
In fact, in Photoshop, in order to explore the properties of ActionManager objects, it is not necessary to loop through all of their keys. There is a handy convertJSONdescriptor function. As the name suggests, it takes an ActionDescriptor and converts it to a JSON string representation. Previously, its description could be found in the ccx-start.jsx file in the Required\CEP\extensions directory:
// Automatically convert to Action JSON, the JSON representation of
// an ActionDescriptor. It is easiest to do this here while we know
// that we still have an object (not a list, string, etc).
if (appDesc && appDesc.hasKey(propertyKey)) {
var convertDesc = new ActionDescriptor();
convertDesc.putObject(sTID('object'), sTID('object'), appDesc);
var jsonDesc = executeAction(sTID('convertJSONdescriptor'), convertDesc, DialogModes.NO);
return jsonDesc.getString(sTID('json'));
}
The most important thing to see here is to create a new ActionDescriptor, put the object to be converted into it (be sure to indicate that this is an "object" in the first argument of the .putObject() function, the class of the object (second argument) does not play a role - it can be any), execute the function, store the result in a variable and extract the "json" string key from it.
Ok, let's try.
To begin with, let's prepare a document with which we will work: create a new file, a new layer, create a mask on it and turn it off.
Our function, as usual, begins with an ActionReference (a description of the path to the object we want to get). Since we are talking about a layer mask, then, most likely, the property we need will be contained in its properties, so we will write the path to the active layer:
s2t = stringIDToTypeID;
var r = new ActionReference();
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
As we know, executeActionGet(r) as a result should return the ActionDescriptor() object by the specified path.
Next, we build on the example from ccx-start.jsx and add a function to convert ActionDescriptor to json (for convenience, we output information to the console):
s2t = stringIDToTypeID;
var r = new ActionReference();
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var d = new ActionDescriptor();
d.putObject(s2t('object'), s2t('layerInfo'), executeActionGet(r));
$.writeln(executeAction(s2t('convertJSONdescriptor'), d).getString(s2t('json')));
Result:
It works, but the json output goes on one line without formatting. We copy it and go to any online json beautifier, format our code and start looking for everything related to masks:
"hasFilterMask": false,
"hasUserMask": true,
"hasVectorMask": false,
"userMaskDensity": 255,
"userMaskEnabled": false,
"userMaskFeather": 0,
"userMaskLinked": true,
"vectorMaskDensity": 255,
"vectorMaskEmpty": true,
"vectorMaskFeather": 0,
Obviously, we need the "userMaskEnabled" property. Let's do a simple test: turn on the layer mask, get the ActionDescriptor's content again, and make sure "userMaskEnabled" has changed to "true". Good. And what happens if the layer has no mask at all - delete the layer mask and get the ActionDescriptor again. We see that the "userMaskEnabled" property has disappeared from the layer altogether, that is, if we try to get it for a layer without a mask, we will get an error. On the one hand, there is a try...catch, on the other hand, we can notice that when the mask was removed, another "hasUserMask" property changed its value from "true" to "false", but we will do it a little differently: we use the .hasKey() ActionDescriptor method to check if the property exists.
So, we know which property we need to get, so we can specify our code. Instead of getting the full layer object, let's specify that we only need one property:
s2t = stringIDToTypeID;
var r = new ActionReference();
r.putProperty(s2t('property'), s2t('userMaskEnabled'));
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
Make sure that the object that executeActionGet returns contains this key (which means the layer has a mask):
var d = executeActionGet(r);
if (d.hasKey(s2t('userMaskEnabled'))) { }
and now finsh our code:
s2t = stringIDToTypeID;
var r = new ActionReference();
r.putProperty(s2t('property'), s2t('userMaskEnabled'));
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var d = executeActionGet(r);
if (d.hasKey(s2t('userMaskEnabled'))) { $.writeln('User mask enabled: ' + d.getBoolean(s2t('userMaskEnabled'))) }
else { $.writeln('Layer has no mask') }
Copy link to clipboard
Copied
Following your wonderful explanation, Sadly just
var s2t = stringIDToTypeID;
var r = new ActionReference();
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var d = new ActionDescriptor();
var j = executeAction(s2t('convertJSONdescriptor'), d).getString(s2t('json'))
alert(j);
results in the existential error:
Error 8500: The requested property does not exist.
- Yes I realise teh code is not identical -I'm doing an alert, not writing a line.
Copy link to clipboard
Copied
You've created a new ActionDescriptor, but you haven't placed an object containing the result of executeActionGet() into it. Look at my example a little more closely.
Copy link to clipboard
Copied
I sees wheres I gone wrong! 😉
All good now. Thank you.

