Skip to main content
Known Participant
February 26, 2016
Answered

random action selection script

  • February 26, 2016
  • 7 replies
  • 5803 views

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 topic has been closed for replies.
Correct answer SuperMerlin

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;}

    }

};

teslaballAuthor
Known Participant
March 3, 2016

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

SuperMerlin
Inspiring
March 3, 2016

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;

};

teslaballAuthor
Known Participant
March 4, 2016

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!

teslaballAuthor
Known Participant
February 29, 2016

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!

SuperMerlin
Inspiring
February 29, 2016

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;

}

teslaballAuthor
Known Participant
February 29, 2016

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.

teslaballAuthor
Known Participant
February 28, 2016

SuperMerlin
Inspiring
February 29, 2016

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:-

JsDoc Reference - jamActions

teslaballAuthor
Known Participant
February 27, 2016

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!

c.pfaffenbichler
Community Expert
Community Expert
February 27, 2016

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.

Tom Winkelmann
Inspiring
February 27, 2016

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

urielt87568523
Participant
September 6, 2018

Hey Tom,

I use your script to load every few action i get an error : see image
please advice

Participant
October 31, 2020

Did you Get Solution for this??

 

teslaballAuthor
Known Participant
February 27, 2016

Please, if someone could answer my question.

SuperMerlin
SuperMerlinCorrect answer
Inspiring
February 27, 2016

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;}

    }

};