Saving JS settings in Actions Tutorial

Documentation, Reference material and Tutorials for Photoshop Scripting

Moderators: Tom, Kukurykus

xbytor

Saving JS settings in Actions Tutorial

Post by xbytor »

Photoshop has a large number of interesting features that are underdocumented or not documented at all. For instance, the docs for Application.playbackParameters say:
The playback options, which indicate the speed at which Adobe PhotoshopCS3 plays actions.

I have no clue if this is actually true. I suspect not. If you want to change the speed of action playback (and the other related settings) you would do something like this (from xtools/xlib/stdlib.js):

Code: Select allStdlib.setActionPlaybackOption = function(opt, arg) {
  function _ftn() {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putProperty(cTID("Prpr"), cTID("PbkO"));
    ref.putEnumerated(cTID("capp"), cTID("Ordn"), cTID("Trgt"));
    desc.putReference(cTID("null"), ref );
    var pdesc = new ActionDescriptor();
    pdesc.putEnumerated(sTID("performance"), sTID("performance"), sTID(opt));
    if (opt == "pause" && arg != undefined) {
      pdesc.putInteger(sTID("pause"), parseInt(arg));
    }
    desc.putObject(cTID("T   "), cTID("PbkO"), pdesc );
    executeAction(cTID("setd"), desc, DialogModes.NO);
  }
  _ftn();
};
Stdlib.setPlaybackAccelerated = function() {
  Stdlib.setActionPlaybackOption("accelerated");
};
Stdlib.setPlaybackStepByStep = function() {
  Stdlib.setActionPlaybackOption("stepByStep");
};
Stdlib.setPlaybackPaused = function(delaySec) {
  Stdlib.setActionPlaybackOption("pause", delaySec);
};



Unfortunately, there is no way to read the playback options, so this capability is not quite as useful as it could be.

Application.playbackParameters can actually be used by scripts to store and read settings when they are recorded as steps in an Action. It's sibling
Application.playbackDisplayDialogs can be used to determine whether or not the step should be interactive (as indicated by that little dialog thingy
in the Action palette by the Action steps).

Code: Select all// utility stuff
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };

function main() {

  // check to see if we already have settings available
  if (app.playbackParameters.count > 0) {
    // if we do, get them and display them
    var ini = getSettings(app.playbackParameters);
    alert("Current settings in Action:\n" +
          ini.name + "\n" + ini.level + "\n" + ini.timestamp);

  } else {
    alert("No settings are stored for this Action step");
  }

  // if the interactive toggle is set _or_ we don't have any settings
  // available (probably because we are recording the action), this is
  // where we would put up a UI to gather the needed settings.
  // if we are re-recording an action step, those values would be used
  // as the defaults for the UI
  if (app.playbackDisplayDialogs == DialogModes.ALL ||
      app.playbackParameters.count == 0) {
    alert("A UI to gather settings would be display here");
  }

  // the main processing of the script would take place at this point since
  // we've gathered all of the settings that we need

  // since we don't use a UI in this script, use these settings.
  var ini = {};
  ini.name = "xbytor";
  ini.level = 20;

  // Note that the timestamp changes each time the script is run
  ini.timestamp = Date();

  storeSettings(ini);
};

// we 'get' the settings by pulling them out of the ActionDescriptor
function getSettings(desc) {
  var ini = {};

  // pull out our settings
  if (desc.hasKey(cTID('Name'))) {
    ini.name = desc.getString(cTID('Name'));
  }
  if (desc.hasKey(cTID('Levl'))) {
    ini.level = desc.getInteger(cTID('Levl'));
  }
  if (desc.hasKey(cTID('Date'))) {
    ini.timestamp = desc.getString(cTID('Date'));
  }

  return ini;
};

// we 'set' the settings by putting them into a new ActionDescriptor
function storeSettings(ini) {
  // create a descriptor
  var desc = new ActionDescriptor();

  // stick in our settings
  desc.putString(cTID('Name'), ini.name);
  desc.putInteger(cTID('Levl'), ini.level);
  desc.putString(cTID('Date'), ini.timestamp);

  // store them (if possible/needed)
  app.playbackParameters = desc;
};

main();

Important points:

1) If you run this script via File->Script->Browse (or from ESTK or by double clicking) you will always see the messages:
"No settings are stored for this Action step"
and
"A UI to gather settings would be display here"

2) The first time you record this script as an action, you will see the same two messages.

3) When you play the action contain the script, you will see the
"Current settings in Action:"
message. If you have the 'Toggle dialog' thing turned on, you will also see
"A UI to gather settings would be display here"
The new settings will _not_ be stored in the action.

4) If you re-record the action step (double-click on the right end of that action step) you will see
"Current settings in Action:"
and
"A UI to gather settings would be display here"
And the new settings will be stored in the action.

Watching the timestamp carefully should help you get a better handle on how 3) and 4) differ.

For a real-life example, see ContactSheetX.jsx in CSX on sourceforge.

-X