Copy link to clipboard
Copied
Finally i found out how to set tool options, so here is a script that switches tools Sample Mode.
And finally we can assign a shortcut to that.
For some tools it toggles "Sample All Layers" on/off,
for others it switches Sample Mode between Current / Current & Below / All Layers / etc.
In the start of the script there is a variable called 'includeAllOptions' that controls whether to cycle all options (set to true) or only Current / Current & Below (set to false).
The script will appear in the top of the File / Scripts menu.
It was kinda hard to figure some stuff out, so i decided not to encrypt it's contents, so that anyone could investigate it.
Happy switching ☺ And if you have any comments, questions or suggestions, i'll be happy to hear them.
The script:
/*
<javascriptresource>
<name>Switch Sample Mode</name>
<enableinfo>true</enableinfo>
<category>Hirlin Scripts</category>
</javascriptresource>
// Oleksii Hirlin 2021
*/
var includeAllOptions = true; // should be either true or false
// if set to false will switch between 'Current' and 'Current &below' or just switch on / off
// if seet to true will switch between all avaliable variants as well as on / off
// getting currentToolOptions property
function checkCTOoption(charString, isIdTypeString){
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
ref.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
if (charString=="eyeDropperSampleSheet"){
return executeActionGet(ref).getObjectValue(stringIDToTypeID("currentToolOptions")).getInteger(stringIDToTypeID(charString));
}
if (isIdTypeString==true){
return executeActionGet(ref).getObjectValue(stringIDToTypeID("currentToolOptions")).getBoolean(stringIDToTypeID(charString));
} else {
return executeActionGet(ref).getObjectValue(stringIDToTypeID("currentToolOptions")).getBoolean(charIDToTypeID(charString));
}
}
// get current tool options object
function getCTO(){
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
ref.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
return executeActionGet(ref).getObjectValue(stringIDToTypeID("currentToolOptions"));
}
// setting currentToolOptions with options array
function setCTO( options, isIdTypeString ){
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass( stringIDToTypeID( app.currentTool ) );
desc.putReference( stringIDToTypeID( "target" ), ref );
// getting current tool options so that they do not get reset
var ctoObj = getCTO();
// check if we are setting the eyedropper tool
if ( app.currentTool=="eyedropperTool" ){
ctoObj.putInteger( stringIDToTypeID( options[0][0] ), options[0][1] );
} else {
// iteration through options array and putting booleans into cto descriptor
for (var i=0; i < options.length; i++){
if (isIdTypeString==true){
ctoObj.putBoolean( stringIDToTypeID( options[i][0] ), options[i][1] );
} else {
ctoObj.putBoolean( charIDToTypeID( options[i][0] ), options[i][1] );
}
}
}
desc.putObject( stringIDToTypeID( "to" ), stringIDToTypeID( "currentToolOptions" ), ctoObj );
executeAction( stringIDToTypeID( "set" ), desc, DialogModes.NO );
}
// switching currentToolOptions if it's one of the tools, ignoring otherwise
function switchCTO (){
if ( app.currentTool=="magicStampTool" || app.currentTool=="cloneStampTool" ){
if ( checkCTOoption("StmA")==true && checkCTOoption("StmB")==false && checkCTOoption("StmS")==false ){
// if 'Current' set to 'Current and below'
setCTO( [ ["StmA",true], ["StmB",true], ["StmS",true] ] );
}
else if ( checkCTOoption("StmA")==true && checkCTOoption("StmB")==true && checkCTOoption("StmS")==true && includeAllOptions==true ){
// if 'current & below' set to 'all layers'
setCTO( [ ["StmA",true], ["StmB",false], ["StmS",true] ] );
}
else {
// otherwise set it to 'Current'
setCTO( [ ["StmA",true], ["StmB",false], ["StmS",false] ] );
}
}
else if ( app.currentTool=="magicLassoTool" || app.currentTool=="wetBrushTool" || app.currentTool=="recomposeSelection" ){
if ( checkCTOoption("sampleAllLayers", true)==false ){
setCTO( [ ["sampleAllLayers", true] ], true );
} else {
setCTO( [ ["sampleAllLayers", false] ], true );
}
}
else if ( app.currentTool=="quickSelectTool" ){
if ( checkCTOoption("quickSelectSampleAllLayers", true)==false ){
setCTO( [ ["quickSelectSampleAllLayers", true] ], true );
} else {
setCTO( [ ["quickSelectSampleAllLayers", false] ], true );
}
}
else if ( app.currentTool=="magicWandTool" ){
if ( checkCTOoption("windowsSystem", true)==false ){
setCTO( [ ["windowsSystem", true] ], true );
} else {
setCTO( [ ["windowsSystem", false] ], true );
}
}
else if ( app.currentTool=="spotHealingBrushTool" ){
if (checkCTOoption("StmS")==true){
setCTO( [ ["StmS",false] ] );
} else {
setCTO( [ ["StmS",true] ] );
}
}
else if ( app.currentTool=="patchSelection" && checkCTOoption("contentAware", true)==true ){
if ( checkCTOoption("sampleAllLayers", true)==false ){
setCTO( [ ["sampleAllLayers", true] ], true );
} else {
setCTO( [ ["sampleAllLayers", false] ], true );
}
}
else if ( app.currentTool=="eyedropperTool" ){
/*
current layer = 1
cur & below = 3
all layers = 0
all layers no adj = 6
cur & below no adj = 8
*/
if ( checkCTOoption("eyeDropperSampleSheet")==1 ) {
setCTO( [ ["eyeDropperSampleSheet", 3] ] );
} else if ( checkCTOoption("eyeDropperSampleSheet")==3 ) {
if ( includeAllOptions==true ){
setCTO( [ ["eyeDropperSampleSheet", 0] ] );
} else {
setCTO( [ ["eyeDropperSampleSheet", 1] ] );
}
} else if ( checkCTOoption("eyeDropperSampleSheet")==0 ) {
if ( includeAllOptions==true ){
setCTO( [ ["eyeDropperSampleSheet", 6] ] );
} else {
setCTO( [ ["eyeDropperSampleSheet", 1] ] );
}
} else if ( checkCTOoption("eyeDropperSampleSheet")==6 ) {
if ( includeAllOptions==true ){
setCTO( [ ["eyeDropperSampleSheet", 8] ] );
} else {
setCTO( [ ["eyeDropperSampleSheet", 1] ] );
}
} else if ( checkCTOoption("eyeDropperSampleSheet")==8 ) {
setCTO( [ ["eyeDropperSampleSheet", 1] ] );
} else {
setCTO( [ ["eyeDropperSampleSheet", 1] ] );
}
}
else if ( app.currentTool=="bucketTool" || app.currentTool=="magicEraserTool"){
if (checkCTOoption("BckS")==true){
setCTO( [ ["BckS",false] ] );
} else {
setCTO( [ ["BckS",true] ] );
}
}
else if ( app.currentTool=="blurTool" || app.currentTool=="sharpenTool" ){
if (checkCTOoption("BlrS")==true){
setCTO( [ ["BlrS",false] ] );
} else {
setCTO( [ ["BlrS",true] ] );
}
}
else if ( app.currentTool=="smudgeTool" ){
if ( checkCTOoption("smudgeStick", true)==false ){
setCTO( [ ["smudgeStick", true] ], true );
} else {
setCTO( [ ["smudgeStick", false] ], true );
}
}
else {
// if other tools, do nothing
}
}
switchCTO();
Well, i guess, unless i get my hands on older PS version, this script is for 2021 only.
Cause that error is probably due to an inappropriate reference in the getter for that PS version.
But if anyone has the knowledge and will, they will fix it for older versions.
By @Oleqsa
Did you write this code yourself? Where did you get this way of getting currentToolOptions?
You can read here
ActionDescriptor getter: can't use Property for nested Descriptors?
Yes. In two places you need to replace
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
with
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("tool"));
Copy link to clipboard
Copied
May you link us to the site where script was found at?
Copy link to clipboard
Copied
I made the script, but i had to find some puzzles like having to reference the tool when setting the options. I would not figure that out myself for probably a decade.
But that particular thing i found on PS-SCRIPTS.COM in some discussion, probably including you 🙂
Found it - it says it was originally Tom Ruark script. The thread Set Brush Options problem
I kinda had all the pieces for some time, but didn't know how to set the tool options.
Also Yaroslav Bereza's "Alchemist" plugin helped a lot to see the differences in settings and names for the variables.
I've build my own script that logs any descriptor i reference into a txt file, but looking at it all as a tree is much more pleasing.
Here is the investigator logging script if you're interested.
I comment and uncomment parts that i need to log, and i don't feel it is complete, cause there are more stuff i can get to log, but it's a start.
/*
<javascriptresource>
<name>Get Descriptor</name>
<enableinfo>true</enableinfo>
<category>Hirlin Scripts</category>
</javascriptresource>
// Oleksii Hirlin 2021
*/
function getCTO(){
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
ref.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
return executeActionGet(ref).getObjectValue(stringIDToTypeID("currentToolOptions"));
}
function getApp(){
var ref = new ActionReference();
ref.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
return executeActionGet(ref);
}
function getLyr(){
var ref = new ActionReference();
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
return executeActionGet(ref);
}
var logg = new File("c:\\Program Files\\Adobe\\Adobe Photoshop 2021\\Presets\\Scripts\\loggCTO.txt");
// var logg = new File("c:\\Program Files\\Adobe\\Adobe Photoshop 2021\\Presets\\Scripts\\loggApp.txt");
// var logg = new File("c:\\Program Files\\Adobe\\Adobe Photoshop 2021\\Presets\\Scripts\\loggLyr.txt");
logg.open("w");
var desc = getCTO();
// var desc = getApp();
// var desc = getLyr();
logg.write(desc.typename+"\t"+desc.count+"\n");
for (var i=0; i<desc.count; i++) {
logg.write("• "+ i +"\t");
//id number
var keyIdNumber = desc.getKey(i).toString();
while ( keyIdNumber.length<10 ) {keyIdNumber+=" ";};
logg.write( keyIdNumber +"\t" );
// type
var typeOfKey = desc.getType( desc.getKey(i) ).toString().replace("DescValueType.", "").replace("TYPE","");
var typeOfKey12 = typeOfKey;
while ( typeOfKey12.length<12 ) {typeOfKey12+=" ";};
logg.write( typeOfKey12 +"\t" );
// char
if (typeIDToCharID ( desc.getKey(i) )){
logg.write("\""+ typeIDToCharID ( desc.getKey(i) )+"\"\t");
} else {
logg.write("\"\"\t\t");
}
// string
logg.write("\""+ typeIDToStringID ( desc.getKey(i) ) +"\"\t");
// data
if ( typeOfKey == "BOOLEAN" ) { logg.write( desc.getBoolean( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "CLASS" ) { logg.write( desc.getClass( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "DOUBLE" ) { logg.write( desc.getDouble( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "INTEGER" ) { logg.write( desc.getInteger( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "LIST" ) { logg.write( desc.getList( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "REFERENCE" ) { logg.write( desc.getReference( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "STRING" ) { logg.write( desc.getString( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "LARGEINTEGER" ) { logg.write( typeIDToCharID( desc.getLargeInteger( desc.getKey(i) ) )+"\t"+ typeIDToStringID( desc.getLargeInteger( desc.getKey(i) ) )+"\t"); }
if ( typeOfKey == "ENUMERATED" ) { logg.write( typeIDToCharID( desc.getEnumerationType( desc.getKey(i) ) )+"\t"+ typeIDToStringID( desc.getEnumerationType( desc.getKey(i) ) )+"\t"); }
if ( typeOfKey == "ENUMERATED" ) { logg.write( typeIDToCharID( desc.getEnumerationValue( desc.getKey(i) ) )+"\t"+ typeIDToStringID( desc.getEnumerationValue( desc.getKey(i) ) )+"\t"); }
if ( typeOfKey == "OBJECT" ) { logg.write( typeIDToCharID( desc.getObjectType( desc.getKey(i) ) )+"\t"+ typeIDToStringID( desc.getObjectType( desc.getKey(i) ) )+"\t"); }
if ( typeOfKey == "OBJECT" ) { logg.write( desc.getObjectValue( desc.getKey(i) )+"\t"); }
if ( typeOfKey == "UNITDOUBLE" ) { logg.write( typeIDToCharID( desc.getUnitDoubleType( desc.getKey(i) ) )+"\t"+ typeIDToStringID( desc.getUnitDoubleType( desc.getKey(i) ) )+"\t"); }
if ( typeOfKey == "UNITDOUBLE" ) { logg.write( desc.getUnitDoubleValue( desc.getKey(i) )+"\t"); }
// new line
logg.write("\n");
}
logg.close();
//
Copy link to clipboard
Copied
Cool Script!
Some user had practically just been asking for it over on
Shortcut für Reperatur-Pinsel (Aktuelle Ebene / Akt. u. darunter / Alle Ebenen)
Copy link to clipboard
Copied
thanks forsharingthere link to here.
it was in german, so i didn't find it.
i had the same problem / wish as that guy, and that's i decided to make the script.
Soon i'll post a similar one that toggles "Use pressure for size" feature, that is also by default can't have a shortcut.
Copy link to clipboard
Copied
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
ref.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
/*...*/ executeActionGet(ref) /*...*/
This code from your script causes an error in Photoshop CS6-CC2020. Also you are not using try-catch, which can lead to problems in modern Photoshop (higher than CS6)
Copy link to clipboard
Copied
What error does it cause?
I would not postit if it caused an error for me, and people who tested it never said about any error.
The code is streight forward, so i didn't use try/catch.
Please elaborate on the error and why lack of try/catch would cause a problem here.
Also i have no other versions of PS 2021 to test the code on, cause i can't legally install them from Adobe, so no way to test it other then pirate, which i don't want to do.
If Adobe would make it possible for PS subscribers / developers to test scripts on older versions, for example in some online thingy, i would totally do that.
Copy link to clipboard
Copied
Error: General Photoshop error occurred. This functionality may not be available in this version of Photoshop. - The command "Get" is not currently available.
Copy link to clipboard
Copied
Well, i guess, unless i get my hands on older PS version, this script is for 2021 only.
Cause that error is probably due to an inappropriate reference in the getter for that PS version.
But if anyone has the knowledge and will, they will fix it for older versions.
Copy link to clipboard
Copied
Well, i guess, unless i get my hands on older PS version, this script is for 2021 only.
Cause that error is probably due to an inappropriate reference in the getter for that PS version.
But if anyone has the knowledge and will, they will fix it for older versions.
By @Oleqsa
Did you write this code yourself? Where did you get this way of getting currentToolOptions?
You can read here
ActionDescriptor getter: can't use Property for nested Descriptors?
Copy link to clipboard
Copied
yeah, i found it with "tool" instead of "currentToolOptions", but since i didn't see any difference for me between referencing one or the other, i used "currentToolOptions".
So in order to not get an error in older versions i should put "tool" there and that will fix it?
Copy link to clipboard
Copied
Yes. In two places you need to replace
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));
with
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("tool"));
Copy link to clipboard
Copied
thank you