Skip to main content
tsliwkan
Participant
May 31, 2015
Answered

Brush Rename Event

  • May 31, 2015
  • 2 replies
  • 2014 views

Hi everyone,

One of the parts of my plugin has to do with responding to brush rename events. I can subscribe to the event and get a callback when the event happens, but I'm at a loss of how to figure out *which* brush was renamed. I am working with Photoshop CC 2014.

Using the script listener when I renamed a brush I get

var idRnm = charIDToTypeID( "Rnm " );

    var desc3 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref1 = new ActionReference();

        var idBrsh = charIDToTypeID( "Brsh" );

        ref1.putIndex( idBrsh, 2 );

    desc3.putReference( idnull, ref1 );

    var idT = charIDToTypeID( "T   " );

    desc3.putString( idT, """hhjk""" );

executeAction( idRnm, desc3, DialogModes.NO );

I can subscribe to the event by running the following code

var eventFile = new File(app.path + '/Presets/Scripts/Event Scripts Only/BrushRenameEventHandler.jsx');

app.notifiers.add('Rnm ',  eventFile, 'Brsh');

And I can handle the event with

try {

    var renameClassID = charIDToTypeID('Rnm ');

    var brushClassID = charIDToTypeID('Brsh');

    var actionDescriptor = arguments[0];

    var eventClass = arguments[1];

    if( eventClass == renameClassID ) {

        var list = actionDescriptor.getList( charIDToTypeID('null') );

        if( list.count == 1 ) {

            var ref = list.getReference(0);

            if( ref.getDesiredClass() == brushClassID ) {

                alert( 'Brush renamed' );

                // How do we know which brush was renamed?!

            }

        }

    }

} catch( e ) {

    alert(e);

}

However, I don't know how to grab which brush was renamed. Looking at the script listener code I should be able to get the index of the brush (2) that was renamed along with the new name (hhjk). Is it possible to get this information from the ActionReference and/or ActionDescriptor

This topic has been closed for replies.
Correct answer Kukurykus

It's hard for me to translate so much text )

Do you want this?

alert ("Brush new name is: " + actionDescriptor.getString(charIDToTypeID('T   ')) + " \n:)"); 

.


Thank you very much, that was so easy, but I couldn't find it though. I tired eveyrhitng only not that 'to' string. I knew it has to do something with it but gave up before used it 🙂


So here is version which doesn't use RegEx, as that was changed to pure ActionManager method and this way also ScriptListenerJS.log file part was removed from code as it's not necessary anymore to get proper values / strings:

if (typeof name != 'undefined') {
	function bP() {
		arr = [], (ref = new ActionReference()).putEnumerated
		(sTT('application'), sTT('ordinal'), sTT('targetEnum'))
		for(lst = (executeActionGet(ref).getList(sTT('presetManager')))
		.getObjectValue(0).getList(sTT('name')), j = 0; j < lst.count; j++) {
			arr.push('"' + lst.getString(j) + '"')}; $.setenv('bP', arr), arr = []
	}

	function sTT(v) {return stringIDToTypeID(v)}; if (!$.getenv('bP')) bP()

	if ((!eval(evl = "typeof arguments != 'undefined'") && notifiersEnabled)
	|| (eval(evl) && (args = arguments)[1] != 1382968608)) notifiersEnabled = false

	if (!notifiersEnabled) {
		for(notifiersEnabled = true, i = 0; i < notifiers.length; i++) {
			if (rnm = app.notifiers[i].event == 'Rnm ') break
		}
		if (typeof rnm == 'undefined') notifiers.add('Rnm ',  File($.fileName))
	}
	else if(((a0 = args[0]).getReference(sTT('null')).getDesiredClass()) == sTT('brush')) {
		idx = a0.getReference(sTT('null')).getIndex() - 1, nme = a0.getString(sTT('to'))
		alrt = 'Name before change: \r' + eval('[' + $.getenv('bP') + ']')[idx] +
		'\r\rName after change: \r' + nme, alert(alrt), $.setenv('bP', ''), bP()
	}
}

 

For those who want to use it, search for instructions few posts upper, where I pasted first version of this code.

2 replies

Legend
December 21, 2017

Use in BrushRenameEventHandler.jsx

alert ("Brush with index " + actionDescriptor.getReference(charIDToTypeID('null')).getIndex() + " was renamed )");

Is it useful?

Kukurykus
Legend
December 21, 2017

He asked for a name, not index on a list; and not a name of changed Brush Preset, but a name that existed before change.

Anyway, r-bin using it:

app.notifiers.add('Rnm ',  File(app.path + '/Presets/Scripts/Event Scripts Only/BrushRenameEventHandler.jsx'), 'Brsh')

I activate:

alert(arguments[0].getReference(charIDToTypeID('null')).getIndex())

So I know index from:

var idRnm = charIDToTypeID( "Rnm " )

    var desc = new ActionDescriptor()

    var idnull = charIDToTypeID( "null" )

        var ref = new ActionReference()

        var idBrsh = charIDToTypeID( "Brsh" )

        ref.putIndex( idBrsh, 2 )

    desc.putReference( idnull, ref )

    var idT = charIDToTypeID( "T   " )

    desc.putString( idT, """changedName""" )

executeAction( idRnm, desc, DialogModes.NO )

Can you answer for my silly question (as I'm a little ActionManager noob , it's why I'm using RegEx).

How to access "changedName" from above code.

For example there was ActionDescriptor ---> ActionReference ---> Index way to get the '2' value.

What should I write to get String, (where I see there is direct ActionDescriptor ---> String​ way) as this doesn't work:

alert(arguments[0].getString()) <--- probalby that must be changed to something else, correct version. THX in advance!

Legend
December 21, 2017

It's hard for me to translate so much text )

Do you want this?

alert ("Brush new name is: " + actionDescriptor.getString(charIDToTypeID('T   ')) + " \n:)"); 

.

Kukurykus
Legend
December 21, 2017

Name it as Brush Rename Presets Notifier.jsx and copy to your Ps StartupScripts folder, so probably at end of this path:

C:\Program Files (x86)\Common Files\Adobe\Startup Scripts CS6\Adobe Photoshop / (it's CS6 EXTENDED in my case)

 

function rw(v1, v2, v3) {v2.open(v1), v1 < 'w' ? v3 = v2.read() : v2.write(v3), v2.close(); return v3}
function sTT(v) {return stringIDToTypeID(v)}; fle = File('~/desktop/ScriptingListenerJS.log')

if (typeof name != 'undefined') {
	function bP() {
		arr = [], (ref = new ActionReference()).putEnumerated
		(sTT('application'), sTT('ordinal'), sTT('targetEnum'))
		for(lst = (executeActionGet(ref).getList(sTT('presetManager')))
		.getObjectValue(0).getList(sTT('name')), j = 0; j < lst.count; j++) {
			arr.push('"' + lst.getString(j) + '"')}; $.setenv('bP', arr), arr = []
	}

	if (!$.getenv('bP')) bP()

	if ((!eval(evl = "typeof arguments != 'undefined'") && notifiersEnabled)
	|| (eval(evl) && (args = arguments)[1] != 1382968608)) notifiersEnabled = false

	if (!notifiersEnabled) {
		for(notifiersEnabled = true, i = 0; i < notifiers.length; i++) {
			if (rnm = app.notifiers[i].event == 'Rnm ') break
		}
		if (typeof rnm == 'undefined') notifiers.add('Rnm ',  File($.fileName))
	}
	else if((args[0].getReference(sTT('null')).getDesiredClass()) == sTT('brush')) {
		vls = rw('r', fle).match(/(\d+) \);(?:.*\n){3}.*"{3}(.*)\b(.*\n){3}$/)
		alrt = 'Name before change: \r' + eval('[' + $.getenv('bP') + ']')[vls[1] - 1]
		 + '\r\rName after change: \r' + vls[2], alert(alrt), $.setenv('bP', ''), bP()
	}
}

 

 

With a start of new session of Ps it takes to to memory an array of loaded Brush Presets by setenv(). When user will rename some Brush Preset an notifier register its changed name and position from a list of available Brush Presets. Then it'll use this position on previous Brush Presets list to get original name of changed Brush Preset. Both of them will be alerted each time an user performs such operation. At the end it updates a list of Brush Presets for changes made so all process starts over...

 

There are limitation in user behaviour I didn't have time to solve however I know how. For example, someone may load new set of Brush Presets, while script wasn't wrote yet for taking to memory list of new Brush Presets. There may be situation that user will delete some Preset or append others to current ones. Again, script is not ready for these circumstances, however it's not hard to add few another notifiers to prevent all these incidents.

 

Ps. as this script uses ScriptListener.log created on desktop and you write your plugin for other users you may instruct them that to use it with all its components they should change Administrator Priviliges for Adobe folder, so your plugin may send ScriptListener.8li to "Required" Ps subfolder in order of activating recordings they be saved in SL file on their desktops.