Pause history when adjusting sliders using BatchPlay?

Community Beginner ,
Dec 30, 2020

Copy link to clipboard

Copied

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

TOPICS
Actions and scripting, Feature request, SDK

Views

59

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Pause history when adjusting sliders using BatchPlay?

Community Beginner ,
Dec 30, 2020

Copy link to clipboard

Copied

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

TOPICS
Actions and scripting, Feature request, SDK

Views

60

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Dec 30, 2020 0
Most Valuable Participant ,
Dec 30, 2020

Copy link to clipboard

Copied

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

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 30, 2020 0
Community Beginner ,
Dec 30, 2020

Copy link to clipboard

Copied

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?

 

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 30, 2020 0
Most Valuable Participant ,
Dec 30, 2020

Copy link to clipboard

Copied

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

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 30, 2020 0
Community Beginner ,
Dec 30, 2020

Copy link to clipboard

Copied

That makes sense, but isn't that the only way of doing this?  Is there a better way of having sliders adjust properties of things such as opacity or whatever?  It sounds like you might be saying that scripting is the wrong way to approach this.  Is there a better way?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 30, 2020 0
Most Valuable Participant ,
Dec 30, 2020

Copy link to clipboard

Copied

My gut tells me only a compiled Plug-in would be able provide a real time image preview feedback for a user for its  in control of Photoshop's processing and not relieing on Photoshop events handlers.  Photoshop events handlers are triggered after the event and are not alwaye triggeed if the event was not not started from Photoshop UI. An event handlers may not be triggered by an event if the event is started from some Photoshop automation precess. 

 

I have not worked with Adobe Photoshop SDK so I do not know what can be done in Plug-ins. I have seen  many plug-ins that provide image previews.  I have see Plug-in the Provide  small parts of an image preview that can also be added the to Photoshop Image window as a preview using a check box in the Plug-in's UI.  Using the Check box noticeably slow down processing its not real time when the preview is also rendered in Photoshop image window. 

 

Any script of mine that uses even handles are reusing code other have written that I have modified for my script's use.  The Only real time feedback I see any of my scripts provide is an Audible beep when a user tries to enter a none numeric character in the Script Dialog's numeric entry fields. 

 

I have seen scripts that provide a Process bar feedback.    I have not seen any script that provide a Image Preview feedback.  Some may exists.  I  would think any Image preview a script provides would not be a real time preview rather it would be a real time update that would be back out if the user cancels out of the adjustment.  

JJMack

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 30, 2020 0
Community Beginner ,
Dec 31, 2020

Copy link to clipboard

Copied

Thank you again for replying but I think you might misunderstand what I'm developing.  I'm not creating a plugin, rather it's a panel.  But Adobe said in the documentation that they're not going to refer to them as "panels" anymore and instead are going to call everything a "plugin"...so I was trying to use the terminology they asked us to us.  You're right, if it was a compiled plugin that was being run, I wouldn't need to worry about history states at all.

 

I have a panel that I bought called "Infinite Unify" that does what I'm trying to do.  When you move a slider, it adjusts the image in real-time yet only adds one entry to the History panel.  So I'm sure there must be a way to do it.  Maybe I'll try to debug the panel and see if I can figure it out or, if nothing else, reach out to the developer to ask for a tip.

 

Thanks again for replying.  Happy New Year to you and yours!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 31, 2020 0