Copy link to clipboard
Copied
Hello,
I have made 10 actions with brush definitions. I need a script for random action execution(instead of executing them on the actions panel) if it is possible. Can someone show me how to do it or post a final example here?
I have very low knowledge for scripting, please be gentle with me.
Thank you for your kindness,
Nick
This version requires you change the variable to suit your LayerSet name.
...#target photoshop;
if(documents.length){
main();
}else{
alert("You need a document open to run this script!");
}
function main(){
//////////////////////////////////////////////////////////////////////
// Change "Default Actions" to the name of your LayerSet
var ASname = "Default Actions";
/////////////////////////////////////////////////////////////////////
if(!checkActionExists(ASname.toString()))
Copy link to clipboard
Copied
Please, if someone could answer my question.
Copy link to clipboard
Copied
This version requires you change the variable to suit your LayerSet name.
#target photoshop;
if(documents.length){
main();
}else{
alert("You need a document open to run this script!");
}
function main(){
//////////////////////////////////////////////////////////////////////
// Change "Default Actions" to the name of your LayerSet
var ASname = "Default Actions";
/////////////////////////////////////////////////////////////////////
if(!checkActionExists(ASname.toString())) {
alert("\"" +ASname+ "\"" + " does not exist!\nPlease check your spelling\nIt is case sensitive!")
return;
}
var ActionSets =getActionSets();
for(var a in ActionSets){
if(ActionSets.toString() == ASname.toString()){
var Actions = getActions(ActionSets.toString());
var RA = Actions[Math.floor(Math.random() * Actions.length)];
try{
app.doAction(RA.toString(), ASname.toString());
}catch(e){};
break;
}
}
};
function checkActionExists( setName, actionName ){
var res = false;
try{
var ref = new ActionReference();
if(actionName != undefined){
ref.putName( charIDToTypeID( 'Actn' ), actionName );
}
ref.putName( charIDToTypeID( "ASet" ), setName );
executeActionGet( ref );
res = true;
}catch(e){return false}
return res;
};
function getActionSets(){
var aSets=[];
var z = 1;
while(true){
var ref = new ActionReference();
ref.putIndex(charIDToTypeID('ASet'), z);
try{
var desc = executeActionGet(ref);
var actName = desc.getString(charIDToTypeID('Nm '));
aSets.push(actName);
z++;
}catch(e){return aSets;}
}
};
function getActions(aSet){
var names = [];
var z =1;
while(true){
var ref = new ActionReference();
ref.putIndex(charIDToTypeID('Actn'), z);
ref.putName(charIDToTypeID('ASet'), aSet);
try{
var adesc = executeActionGet(ref);
var actName = adesc.getString(charIDToTypeID('Nm '));
names.push(actName);
z++;
}catch(e){return names;}
}
};
Copy link to clipboard
Copied
cTID = function(s) { return app.charIDToTypeID(s); };
function getActions(aset) {
var i = 1;
var names = [];
if (!aset) {
throw Error.runtimeError(9001, "Action set must be specified");
}
while (true) {
var ref = new ActionReference();
ref.putIndex(cTID("ASet"), i);
var desc;
try {
desc = executeActionGet(ref);
} catch (e) {
names = undefined;
break; // all done
}
if (desc.hasKey(cTID("Nm "))) {
var aname = desc.getString(cTID("Nm "));
if (aname == aset) {
var count = desc.getInteger(cTID("NmbC"));
for (var j = 1; j <= count; j++) {
var ref = new ActionReference();
ref.putIndex(cTID('Actn'), j);
ref.putIndex(cTID('ASet'), i);
var adesc = executeActionGet(ref);
var actName = adesc.getString(cTID('Nm '));
names.push(actName);
}
break;
}
}
i++;
}
return names;
};
function randomElement(ary) {
return ary[Math.floor(Math.random(ary.length) * ary.length)];
};
function getRandomAction(aset) {
return randomElement(getActions(aset));
};
Copy link to clipboard
Copied
var actionSet = "myActionSet"; // name of your ActionSet
var actions = ["Action 01","Action 02","Action 03","Action 04","Action 05","Action 06","Action 07","Action 08"]; // names of your actions
var randomAction = actions[Math.floor(Math.random() * actions.length)];
app.doAction(actions[randomAction], actionSet );
Copy link to clipboard
Copied
Hey Tom,
I use your script to load every few action i get an error : see image
please advice
Copy link to clipboard
Copied
Did you Get Solution for this??
Copy link to clipboard
Copied
In case the number/names of the Actions changes in this thread
Re: Photoshop list actions with script
xbytor provided code to get a list of ActionsSets’ and the contains Actions’ names.
Copy link to clipboard
Copied
Wow! So many answers by great people here! I will study the complete code of SuperMerlin how it is made.
Thanks a bunch, especially to SuperMerlin!
Copy link to clipboard
Copied
Thank you xbytor2, you are great!!!
This is becoming much more interesting as today I have found a tool from xtools to convert an action to javascript and also using the CC extension builder for brackets to create a panel. I am good at HTML and CSS and have created the panel, I even found a way how to implement the converted actions (to javascript) in the default script file called hostscript.jsx (it can be any name for the extendscripts implementation). Can someone (SuperMerlin, xbytor2 or anyone else) help me with script randomizing the implemented functions (converted from the actions)?
Thank you.
Copy link to clipboard
Copied
Here is the basics of running a random script:
var scriptsFolder = Folder("your path to folder");
var Filelist = scriptsFolder.getFiles("*.jsx");
var RS = Actions[Math.floor(Math.random() * Filelist.length)];
$.evalfile(Filelist[RS]);
There is another method of running an Action that is NOT loaded in Photoshop, details can be found:-
Copy link to clipboard
Copied
Thank you SuperMerlin, obviously I did not ask the question the right way. I will try to explain it with more details. For example, I have included three functions (Cut, Copy and Paste) that want to be randomized on each pressing of the button in the panel that I will link it later. I think that this is much clearer of what I need to do.
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
//
//==================== Cut (selection) ==============
//
function Cut_selection() {
try {
if (documents.length == 0) {
alert('Please open a document.')
return;
}
// Cut
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('cut '), undefined, dialogMode);
};
step1(); // Cut
} catch(e) {
alert(e + ":" + e.line);
};
//
//==================== Copy (selection) ==============
//
function Copy_selection() {
try {
if (documents.length == 0) {
alert('Please open a document.')
return;
}
// Copy
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('copy'), undefined, dialogMode);
};
step1(); // Copy
} catch(e) {
alert(e + ":" + e.line);
};
//
//==================== Paste ==============
//
function Paste() {
try {
if (documents.length == 0) {
alert('Please open a document.')
return;
}
// Paste
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('past'), undefined, dialogMode);
};
step1(); // Paste
} catch(e) {
alert(e + ":" + e.line);
};
//
I found something on StackOverflow like this:
function randomact() {
var func = randomFrom(['Cut_selection', 'Copy_selection', 'Paste']);
window[func]();
}
or:
function randomact() {
var func = randomFrom([Cut_selection
,'Copy_selection
,Paste
]);
(func)();
}
`The only problem is I don't know how to make things in order for everything to function as it should.
Thank you!
Copy link to clipboard
Copied
Ah, that would be :-
var ran = Math.floor(Math.random() * 3);
switch(ran){
case 0: app.activeDocument.selection.copy(); break;
case 1: app.activeDocument.selection.cut(); break;
case 2: app.activeDocument.paste(); break;
default : return;
}
Copy link to clipboard
Copied
SuperMerlin, thank you, but I don' think this is what I need. As I understood, your code is strictly for random copy, cut and paste of a selection. I actually need the concept of random execution of the above mentioned functions (they could be brush or style selection functions or whatever). The first script that you wrote is doing exactly what I need. Now, I need function to randomize those functons execution and how to exactly implement it in my above mentioned code.
Thank you.
Copy link to clipboard
Copied
Once you have your functions writen tey can be called via the switch statement..
NumberOfFunctions = 7;//Number of functions in your switch statement.
var ran = Math.floor(Math.random() * NumberOfFunctions);
switch(ran){
case 0: app.activeDocument.selection.copy(); break;
case 1: app.activeDocument.selection.cut(); break;
case 2: app.activeDocument.paste(); break;
case 3: brushFunction(); break;
case 4: anotherFunction(); break;
case 5: yetAnotherFunction(); break;
case 6: etcetc(); break();
default : return;
}
Copy link to clipboard
Copied
You are great SuperMerlin. Thank you for your effort explaining all of my requests! Please excuse my lack of JavaScript knowledge. This is much clear now.
Copy link to clipboard
Copied
I have successfully implemented this method of randomizing, but is it possible to randomize the cases with no repeat until each of them are passed in random order on each button press, for example [1,3,2,4],[3,2,4,1] etc. and not [1,1,3,2,2,4,4,1,1,1,3,2]?
Thank you.
Copy link to clipboard
Copied
Not that I know of, as then it isn't random.
Maybe someone knows different?
Copy link to clipboard
Copied
This code is for shuffling numbers that I have found:
/**
* Shuffles array in place.
* @param {Array} a items The array containing the items.
* @return {Array} a The shuffled array
*/
function shuffle(a) {
var j, x, i;
for (i = a.length; i; i -= 1) {
j = Math.floor(Math.random() * i);
x = a[i - 1];
a[i - 1] = a[j];
a[j] = x;
}
}
then use:
var myArray = ['1','2','3','4','5','6','7','8','9'];
shuffle(myArray);
I have found these examples here:
https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript#6274381
But instead of numbers, I want to make functions being shuffled and executed one random function on each button press without repeating that same function on next button press.
I have implemented the codes, but it doesn't work. Where do I get wrong?
P.S. rnd_act_select() is called by a button press.
function rnd_act_select() {
try {
if (documents.length == 0) {
alert('Please open a document.')
return;
}
// random selection
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
var arr = [func_one,func_two,func_three,func_four];
var shuf = shuffle(arr);
switch(shuf) {
case 0: func_one(); break;
case 1: func_two(); break;
case 2: func_three(); break;
case 3: func_four(); break;
default : return;
}
// random selection end
} catch(e) {
alert(e + ":" + e.line);
}
};
Thank you
Copy link to clipboard
Copied
It would be something like this.
#target photoshop;
main();
function main(){
//add as many numbers as required.
var numArray = [0,1,2,3];
var Prefs ={};
try{
var desc1 = app.getCustomOptions('randomShuffle');
Prefs = eval(desc1.getString(0));
}catch(e){
Prefs.numbers = shuffle(numArray);
Prefs.count=0;
var desc1 = new ActionDescriptor();
desc1.putString(0, Prefs.toSource());
app.putCustomOptions( 'randomShuffle', desc1, true );
}
if(Prefs.count == numArray.length){
// $.writeln("end of array count = " + Prefs.count);
Prefs.count=0;
Prefs.numbers=shuffle(numArray);
var desc1 = new ActionDescriptor();
desc1.putString(0, Prefs.toSource());
app.putCustomOptions( 'randomShuffle', desc1, true );
var ran = Prefs.numbers[Prefs.count];
Prefs.count++;
var desc1 = new ActionDescriptor();
desc1.putString(0, Prefs.toSource());
app.putCustomOptions( 'randomShuffle', desc1, true );
}else{
var ran = Prefs.numbers[Prefs.count];
Prefs.count++;
var desc1 = new ActionDescriptor();
desc1.putString(0, Prefs.toSource());
app.putCustomOptions( 'randomShuffle', desc1, true );
}
//$.writeln(ran);
switch(ran) {
case 0: func_one(); break;
case 1: func_two(); break;
case 2: func_three(); break;
case 3: func_four(); break;
default : return;
}
//the following line when run will erase the CustomOptions
//app.eraseCustomOptions( 'randomShuffle');
};
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
Copy link to clipboard
Copied
Yes, this is it. It works a bit strange, rarely repeats same function, but I think it is because of some sluggishness in the script. I think it needs optimization.
Great SuperMerlin! Thank you very much!
Copy link to clipboard
Copied
Something strange has happened, the panel button worked smoothly and now it suddenly stopped responding at all. I changed to previous script with the simple switch randomizing and it works well. I have backup of the script and nothing changed, resigned the zxp and everything is in order except it does not work. Is this in connection with JavaScript or with Photoshop bug?
Copy link to clipboard
Copied
What you could try is run this code from ExtendScript Toolkit to remove the saved details.
#target photoshop;
app.eraseCustomOptions( 'randomShuffle');
Then try your panel again?
Copy link to clipboard
Copied
It works now, but I am little bit confused why app.eraseCustomOptions( 'randomShuffle'); was commented out instead put active. I guess it can bring some consequences to other extensions(or documents) if using always when the extension loads?
Copy link to clipboard
Copied
That line must not be uncommented, if it is the script will not work.
The array is saved in Photoshops preferences also a count is stored, if you run that line all that information is wiped out.
At the moment you can shut Photoshop down an when restarted it will continue where it left off.
If you want it fresh each time Photoshop is loaded change app.putCustomOptions( 'randomShuffle', desc1, true );
to app.putCustomOptions( 'randomShuffle', desc1, false );