Skip to main content
Silly-V
Legend
August 11, 2018
Answered

Select/refer to brushes by name within brush sets by name

  • August 11, 2018
  • 2 replies
  • 1469 views

New question from me:

Is it possible to do the following items when it comes to Ps scripting?

  1. List all brush sets and their brushes in an array
  2. Obtain last-selected brush and its parent set.
  3. Obtain last-selected brush set if no brush is selected within.
  4. Select a brush by name within a parent set (so as to be able to traverse brushes of same name in different sets.
  5. It's possible to nest brush sets.. is it possible to do all of the above considering the tree-view structure?
This topic has been closed for replies.
Correct answer r-bin

Look what I dug up in CC2018 )

show_brushes_object();

show_brushes_tree();

if (!select_brush("Mesh - Medium", "Legacy Brushes", "Faux Finish Brushes"))

    alert("Wrong Brush!");

else

    alert("Brush Selected!")

// next function works correctly only if the highlighting of the brush is visible

// alert_curr_brush();

////////////////////////////////////////////////////////////////////////////////////////////////////

function get_brushes_tree(donot_split)

    {

    try

        {

        var tree = "";

   

        var r = new ActionReference();

        r.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "brushes" ) );

        r.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

        eval("var b = " + executeActionGet(r).getString(stringIDToTypeID("brushes")) + ".brushes");

        process_brushes(b, "");

   

        if (donot_split != true) tree = tree.split("\n");

   

        return tree;

   

        function process_brushes(b, set)

            {

            for (var i = 0; i < b.length; i++)

                {

                if (b.children)

                    {

                    tree += set + b.name + "\\" + "\n";

   

                    if (b.children.length)

                        process_brushes(b.children, set + b.name + "\\");

                    }

                else

                    {

                    tree += set + b.name + "\n";

                    }

                }

            }

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function get_brush_idx(name)

    {

    var tree = get_brushes_tree();

    var s = "";

    for (var i = 1; i < arguments.length; i++) s += arguments + "\\";

    s += name;

    for (var i = 0; i < tree.length; i++) if (tree == s) return i+1;

    return 0;

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function select_brush_idx(idx)

    {

    try

        {

        if (idx)

            {

            var d = new ActionDescriptor();

            var r = new ActionReference();

            r.putIndex(stringIDToTypeID("brush"), idx);

            d.putReference(stringIDToTypeID("null"), r);

            executeAction(stringIDToTypeID("select"), d, DialogModes.NO);

            return true;

            }

        return false;

        }

    catch (e) { return false; }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function select_brush(name)

    {

    var tree = get_brushes_tree();

    var s = "";

    for (var i = 1; i < arguments.length; i++) s += arguments + "\\";

    s += name;

    var idx = 0;

    for (var i = 0; i < tree.length; i++) if (tree == s) { idx = i+1; break; }

    return select_brush_idx(idx);

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function show_brushes_object()

    {

    try {

        var d = new Window("dialog", "Brushes Object");

        d.t = d.add("edittext", undefined, "", {multiline: true, readonly: true, scrolling:true, fontsize: '30pt' });

        d.t.preferredSize = [1000, 750];

        var r = new ActionReference();

        r.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "brushes" ) );

        r.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

        d.t.text = executeActionGet(r).getString(stringIDToTypeID("brushes"));

        d.add("button", undefined, "OK");

        d.show();

        d = null;

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function show_brushes_tree()

    {

    try {

        var d = new Window("dialog", "Brushes Tree");

        d.t = d.add("edittext", undefined, "", {multiline: true, readonly: true, scrolling:true, fontsize: '30pt' });

        d.t.preferredSize = [1000, 750];

        d.t.text = get_brushes_tree(true);

        d.add("button", undefined, "OK");

        d.show();

        d = null;

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function alert_curr_brush()

    {

    try {

        var tmp = Math.random().toString().substr(2) + Math.random().toString().substr(2);

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putClass(stringIDToTypeID("brush"));

        d.putReference(stringIDToTypeID("null"), r);

        d.putString(stringIDToTypeID("name"), tmp);

        var r1 = new ActionReference();

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

        r1.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("using"), r1);

        executeAction(stringIDToTypeID("make"), d, DialogModes.NO);

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putName(stringIDToTypeID("brush"), tmp);

        d.putReference(stringIDToTypeID("null"), r);

        var idx = executeAction(stringIDToTypeID("delete"), d, DialogModes.NO).getReference(stringIDToTypeID("null")).getIndex() - 1;

        select_brush_idx(idx);

        var tree = get_brushes_tree();

        alert("Current Brush:\n\n" + tree[idx-1]);

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function alert_curr_brush_v2()

    {

    try {

        var tmp = new File(Folder.temp.fsName + "\\" + "TMP");

        if (tmp.exists) tmp.remove();

        var d = new ActionDescriptor();

        d.putPath(stringIDToTypeID("null"), tmp);

        var r = new ActionReference();

        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("brush"));

        r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("to"), r);

        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);

        var tree1 = get_brushes_tree();

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putEnumerated(stringIDToTypeID("brush"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("null"), r);

        ret = executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);

        var tree2 = get_brushes_tree();

        for (var i = 0; i < tree2.length; i++)

            {

            if (tree2 != tree1) break;

            }

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("brush"));

        r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("null"), r);

        d.putPath(stringIDToTypeID("to"), tmp);

        d.putBoolean(stringIDToTypeID("append"), false);

        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);

        tmp.remove();

        select_brush_idx(i+2);

        var tree = get_brushes_tree();

        alert("Current Brush:\n\n" + tree[i+2]);

        }

    catch (e) { throw(e); }

    }

2 replies

r-binCorrect answer
Legend
August 12, 2018

Look what I dug up in CC2018 )

show_brushes_object();

show_brushes_tree();

if (!select_brush("Mesh - Medium", "Legacy Brushes", "Faux Finish Brushes"))

    alert("Wrong Brush!");

else

    alert("Brush Selected!")

// next function works correctly only if the highlighting of the brush is visible

// alert_curr_brush();

////////////////////////////////////////////////////////////////////////////////////////////////////

function get_brushes_tree(donot_split)

    {

    try

        {

        var tree = "";

   

        var r = new ActionReference();

        r.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "brushes" ) );

        r.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

        eval("var b = " + executeActionGet(r).getString(stringIDToTypeID("brushes")) + ".brushes");

        process_brushes(b, "");

   

        if (donot_split != true) tree = tree.split("\n");

   

        return tree;

   

        function process_brushes(b, set)

            {

            for (var i = 0; i < b.length; i++)

                {

                if (b.children)

                    {

                    tree += set + b.name + "\\" + "\n";

   

                    if (b.children.length)

                        process_brushes(b.children, set + b.name + "\\");

                    }

                else

                    {

                    tree += set + b.name + "\n";

                    }

                }

            }

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function get_brush_idx(name)

    {

    var tree = get_brushes_tree();

    var s = "";

    for (var i = 1; i < arguments.length; i++) s += arguments + "\\";

    s += name;

    for (var i = 0; i < tree.length; i++) if (tree == s) return i+1;

    return 0;

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function select_brush_idx(idx)

    {

    try

        {

        if (idx)

            {

            var d = new ActionDescriptor();

            var r = new ActionReference();

            r.putIndex(stringIDToTypeID("brush"), idx);

            d.putReference(stringIDToTypeID("null"), r);

            executeAction(stringIDToTypeID("select"), d, DialogModes.NO);

            return true;

            }

        return false;

        }

    catch (e) { return false; }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function select_brush(name)

    {

    var tree = get_brushes_tree();

    var s = "";

    for (var i = 1; i < arguments.length; i++) s += arguments + "\\";

    s += name;

    var idx = 0;

    for (var i = 0; i < tree.length; i++) if (tree == s) { idx = i+1; break; }

    return select_brush_idx(idx);

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function show_brushes_object()

    {

    try {

        var d = new Window("dialog", "Brushes Object");

        d.t = d.add("edittext", undefined, "", {multiline: true, readonly: true, scrolling:true, fontsize: '30pt' });

        d.t.preferredSize = [1000, 750];

        var r = new ActionReference();

        r.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "brushes" ) );

        r.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

        d.t.text = executeActionGet(r).getString(stringIDToTypeID("brushes"));

        d.add("button", undefined, "OK");

        d.show();

        d = null;

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function show_brushes_tree()

    {

    try {

        var d = new Window("dialog", "Brushes Tree");

        d.t = d.add("edittext", undefined, "", {multiline: true, readonly: true, scrolling:true, fontsize: '30pt' });

        d.t.preferredSize = [1000, 750];

        d.t.text = get_brushes_tree(true);

        d.add("button", undefined, "OK");

        d.show();

        d = null;

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function alert_curr_brush()

    {

    try {

        var tmp = Math.random().toString().substr(2) + Math.random().toString().substr(2);

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putClass(stringIDToTypeID("brush"));

        d.putReference(stringIDToTypeID("null"), r);

        d.putString(stringIDToTypeID("name"), tmp);

        var r1 = new ActionReference();

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

        r1.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("using"), r1);

        executeAction(stringIDToTypeID("make"), d, DialogModes.NO);

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putName(stringIDToTypeID("brush"), tmp);

        d.putReference(stringIDToTypeID("null"), r);

        var idx = executeAction(stringIDToTypeID("delete"), d, DialogModes.NO).getReference(stringIDToTypeID("null")).getIndex() - 1;

        select_brush_idx(idx);

        var tree = get_brushes_tree();

        alert("Current Brush:\n\n" + tree[idx-1]);

        }

    catch (e) { alert(e); throw(e); }

    }

////////////////////////////////////////////////////////////////////////////////////////////////////

function alert_curr_brush_v2()

    {

    try {

        var tmp = new File(Folder.temp.fsName + "\\" + "TMP");

        if (tmp.exists) tmp.remove();

        var d = new ActionDescriptor();

        d.putPath(stringIDToTypeID("null"), tmp);

        var r = new ActionReference();

        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("brush"));

        r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("to"), r);

        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);

        var tree1 = get_brushes_tree();

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putEnumerated(stringIDToTypeID("brush"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("null"), r);

        ret = executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);

        var tree2 = get_brushes_tree();

        for (var i = 0; i < tree2.length; i++)

            {

            if (tree2 != tree1) break;

            }

        var d = new ActionDescriptor();

        var r = new ActionReference();

        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("brush"));

        r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));

        d.putReference(stringIDToTypeID("null"), r);

        d.putPath(stringIDToTypeID("to"), tmp);

        d.putBoolean(stringIDToTypeID("append"), false);

        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);

        tmp.remove();

        select_brush_idx(i+2);

        var tree = get_brushes_tree();

        alert("Current Brush:\n\n" + tree[i+2]);

        }

    catch (e) { throw(e); }

    }

Silly-V
Silly-VAuthor
Legend
August 12, 2018

A very helpful and informative answer, thank you!

Kukurykus
Legend
August 11, 2018

I doubt you can use Action Manager to list Sets of Brushes. Probably you can do it only by reading binaries of .abr files.

Silly-V
Silly-VAuthor
Legend
August 11, 2018

Hmm, at least in Illustrator there's a Brushes and a Brush objects which can be used to create & apply brushes - but more fundamentally to see the brushes in the brush panel and have a list of them. However this is all mostly due to how Illustrator only deals with document-specific palette items, as in, when the document switches, the brushes are all different now. In Ps, it appears to be app-centered and I guess not so easily accessed.

I wonder how the Ps pros deal with the brush panel contents for when there's a need to use different brushes - in those hypothetical situations where someone may have identically-named brushes in separate sets.

I did a test with a "select brush by name" function from these forums (Re: Is it possible to cycle through brushes (tpls) using a script? ).

What it does is select the 1st brush named some name, that happens to be toward the top in the brush panel.

"Toward the top" in this case means regardless of nesting order: a brush in a single-nested-group set which is located below a same-named brush in a multiple-nested set which is below the single-nested set will not get selected, rather the group above it with multiple nested groups and the named brush in it will get selected.

That's what I found out so far!

Kukurykus
Legend
August 11, 2018

I tried some time ago and found there is limited access to sets. You can do some basic operation on them like deleting when one is selected (not selected by script) - but that is all. You can do more with sole brushes until you refer them to their sets.