Skip to main content
DanielAllen
Inspiring
December 30, 2020
Question

Pause history when adjusting sliders using BatchPlay?

  • December 30, 2020
  • 1 reply
  • 1268 views

I know that there are other posts on the forum about pausing history states and the solution is to use SuspendHistory() to have multiple changes collapse into one history state, but that assumes that there's a single function that you can call to do it.  When giving the user real-time controls, this doesn't work...at least, not how I'm doing it.

 

I'm working on a panel that uses UXP and BatchPlay to allow the user to modify sliders on their document and each call to BatchPlay is creating an entry in the user's History panel.  If I use the Change event on the slider it only puts one history state, but I want the user to see real-time updates by using the Input event when they adjust the slider.  This also works okay, but each change in the slider is updating the history states, which is spamming the history panel with hundreds of unnecessary states.

 

The gist of what I'm doing is:

import { SetContrast } from "../components/AdjustSettings.jsx";

document.getElementById("slideContrast").addEventListener("input", evt => {
   this.onSlideContrastInput(evt.target.value);
});

async ChangeContrast(offset) { await SetContrast(offset); }
onSlideContrastInput = (offset) => {
   console.log("onSlideContrastInput " + offset);
   this.ChangeContrast(offset).then(() => {}).catch(err => {
      console.error(err);
   });
}

AdjustSettings.jsx looks like this:

export const SetContrast = (offset) => {
    var intLeft = offset;
    var intRight = 255 - offset;

    require('photoshop').action.batchPlay(
        [
            {
                "_obj": "set",
                "_target": [
                    {
                        "_ref": "adjustmentLayer",
                        "_name": "Contrast"
                    }
                ],
                "to": {
                    "_obj": "curves",
                    "adjustment": [
                        {
                            "_obj": "curvesAdjustment",
                            "channel": {
                                "_ref": "channel",
                                "_enum": "channel",
                                "_value": "composite"
                            },
                            "curve": [
                                {
                                    "_obj": "paint",
                                    "horizontal": intLeft,
                                    "vertical": 0
                                },
                                {
                                    "_obj": "paint",
                                    "horizontal": intRight,
                                    "vertical": 255
                                }
                            ]
                        }
                    ]
                },
                "_isCommand": false,
                "_options": {
                    "dialogOptions": "dontDisplay"
                }
            }
        ], {
        "synchronousExecution": true,
            "modalBehavior": "execute"
    });
}

 

Ideally, I'd like to turn off history logging until the Change event fires, which means that that user has stopped moving the slider.  Is there a way to do this?  Based on what I'm seeing on other threads here, it doesn't look like it--but with how much sliders are used in Photoshop (and in other apps) I can't believe this hasn't been addressed already.  Internally I know their own panels do this for their sliders and things like Nudge, etc.

 

I would even be happy with something like a history state starting when the user starts interacting with the panel and ending when the panel loses focus...if something like that is even possible.  I'm thinking that it might be possible to have a modal dialog appear as a single history state, but panels???

 

Any suggestions?  How do existing panels/plugins with real-time sliders handle this?  (...or do they?)

This topic has been closed for replies.

1 reply

JJMack
Community Expert
Community Expert
December 30, 2020

That Photoshop Scripting method "SuspendHistory() " does not collapse history states.  It creates a history state for the document current state with the name you specify then stops  the creation  of addition history states for photoshop document for steps the script does in the document. If the script open a document  steps the script does in that document will most likely be created for that document.  The reason you use this is history states are expensive and limited. Scripts that loop will exhaust your documents history states and wipe out prior history before the scripts usage. Users have no way to back out the script's changes  or able to back up in history to before the script was used. There is also a bug Photoshop Scripting SuspendHistory support  the bug is very specific it rarely bites a script. When it bites the script's code need to be chanced to program around the bug so it will not bite.

 

SuspendHistory() just creates a history state  then stops creating history states for a document for photoshop steps the script perform. All the scripts does can be backed out using the single  suspend history state created for SuspendHistory you named. 

 

I have not look at Adobe's  "UXP" plans  how it will interface with current Photoshop automation Scripts, Actions, and plug-ins. If it like other thing Adobe has developed there will be issues and not cover everything.

 

 

 

 

JJMack
DanielAllen
Inspiring
December 30, 2020

Thank you for the reply.  The BatchPlay stuff actually has a way to collapse all the actions being executed into a single History state already, and that part works really great.  It's easily done by adding something like this to your script:

        "historyStateInfo": {
            "name": "Set up panel layers",
            "target": {
                "_ref": "document",
                "_enum": "ordinal",
                "_value": "targetEnum"
            }
        }

I use that when I first set up the layers that my panel controls in the document.

 

The problem is when the user is adjusting sliders in my panel and each change is calling a BatchPlay command.  So if the user moves the control from 0 to 50, BatchPlay is being called 50 times (it actually seems like it may be firing more because some numbers are firing more than once) and each of the 50 calls is logged to the History panel.  I know this is unacceptable, which is why I'm trying to find a way around it.  There must be a way because sliders are used everywhere in Photoshop!

 

These slider changes are event driven from the control, so there really isn't a "script" that I can tell the SuspendHistory() function to call...or am I missing something?

 

 

JJMack
Community Expert
Community Expert
December 30, 2020

I have no idea how all fits together extensions, cep,actions, scripts, uxp, plug-ins etc.  Pieces that use scripting  like Actions can use scripts, extension cans use script. The part that use scripting are going to have importations and not perform well script are not compiled into optimized machine code for a  particular process. There a lot of overhead when it come to scripting. Script do not perform well and have limited abilities to display things  for users.  Providing a preview the with little lag may not be doable.

JJMack