Copy link to clipboard
Copied
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
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
...
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(
...
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
Use in BrushRenameEventHandler.jsx
alert ("Brush with index " + actionDescriptor.getReference(charIDToTypeID('null')).getIndex() + " was renamed )");
Is it useful?
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
It's hard for me to translate so much text )
Do you want this?
alert ("Brush new name is: " + actionDescriptor.getString(charIDToTypeID('T ')) + " \n:)");
.
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
It seems to me that the environment is not rubbery. Maybe it will overflow. Probably it is better to use putCustomOptions (desc), where desc is the pure descriptor obtained by executeActionGet (). Then use getCustomOptions () and eraseCustomOptions ().
No? )
Copy link to clipboard
Copied
That's funny, before I asked you of help with getString() I searched for some solution on this forum and found a topic about that you say now Is there any way to assign a global value to a document (object)? I tested it a while, but never met it before. Well if you say so I give it a try... Ps. it won't be overflowed, I ussed at the end $.setenv('bP', '') to clear global var.
Copy link to clipboard
Copied
In two word (have no time) )
instead setenv() use
app.putCustomOptions("_BRUSHLIST_", executeActionGet(ref).getList(sTT('presetManager')).getObjectValue(0), true);
instead of code with getenv() should use
try { var desc = app.getCustomOptions("_BRUSHLIST_"); } catch(e) { /*do putCustomOptions first*/ }
var orig_name = desc.getList(sTT('name')).getString(idx);
ps. not tested