Skip to main content
Oleqsa
Known Participant
September 23, 2021
Answered

Here is a script that switches (toggles) Sample Mode option for tools that support it

  • September 23, 2021
  • 4 replies
  • 2721 views

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();

 

Correct answer r-bin

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?


Yes. In two places you need to replace

 

ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));

 

with

 

ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("tool"));

4 replies

Flowgun
Inspiring
October 9, 2025

great script, but it also modifies StmA property which is not needed (e.g: it toggles "Aligned" for the clone Stamp Tool).

Legend
September 26, 2021
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)

Oleqsa
OleqsaAuthor
Known Participant
September 27, 2021

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.

r-binCorrect answer
Legend
September 27, 2021

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?


Yes. In two places you need to replace

 

ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("currentToolOptions"));

 

with

 

ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("tool"));

c.pfaffenbichler
Community Expert
Community Expert
September 26, 2021

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)

Oleqsa
OleqsaAuthor
Known Participant
September 26, 2021

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.

Kukurykus
Legend
September 23, 2021

May you link us to the site where script was found at?

Oleqsa
OleqsaAuthor
Known Participant
September 23, 2021

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();
//