Skip to main content
Osama Sa
Inspiring
June 5, 2016
Question

Progress Bars On AE CC15

  • June 5, 2016
  • 3 replies
  • 2087 views

Hi there,

I'm creating a script that duplicates a folder and all of its items and goes through each comp and replaces its layers, fixes expressions etc... I'm quite a beginner and have been doing quite well till yesterday, creating the progress bar for my script is where I'm stuck. My script's UI is dock-able and it has a button that triggers the script and creates a palette window where the progress bar is shown on. Inside the for loops that takes most of the time that the script needs (the script takes 2-3 minutes for the project I'm testing the script on), I increase both of the maxvalue and the value of the progress bar. So far nothing wrong, but in AE CC15 (my OS is Windows 10) the palette window crashes (I mean by that it shows "(Not Responding)" on the palette window's title bar) after a few seconds thus the progress bar doesn't update itself anymore. When the script finishes the operation, the progress bar goes to its max value right away. I tested the script on AE CS5.5 and that doesn't happen.

Why does the palette window crash? Is this a bug in CC15?

I don't want to share all of my code here, I don't want my script's source code to be online, so here is something I can share:

{

  function TrueFoldersDuplicatorScript (thisObj) {

  function CreateProgressBar () { // This function creates the progress bar's palette window

  var w = new Window("palette", "Progress", undefined);

  var res = "group{orientation:'column', alignment:['fill','fill'],\

  Grp: Group{orientation:'row', alignment:['fill','fill'],\

  pb: Progressbar{text: 'Progressbar', alignment:['fill','fill']},\

  percenText: StaticText{text: '', alignment:['center','center']},\

  },\

  pbText: StaticText{text: '', alignment:['fill','fill']},\

  okb: Button{text: 'Ok'},\

  }";

  w.grp = w.add(res);

  w.grp.Grp.pb.maxvalue = 0;

  w.grp.Grp.pb.minimumSize = [250, 10];

  w.grp.Grp.pb.value = 0;

  w.grp.pbText.text = "Please wait...";

  w.grp.Grp.percenText.text = "00.00%";

  w.grp.okb.enabled = false;

  w.grp.okb.onClick = function () {this.window.close()}

  w.center();

  w.show();

  return {

  theText: function(STR){w.grp.pbText.text = STR; w.update()},

  thePercnText: function(str){w.grp.Grp.percenText.text = str; w.update()},

  w:w,

  SetMax: function(max){w.grp.Grp.pb.maxvalue += max; w.update()}, //Resets the max value

  Increment: function(){w.grp.Grp.pb.value += 1; w.update()}, //Increases the value

  Finished: function(){w.grp.okb.enabled = true;},

  pbValue: function(){return w.grp.Grp.pb.value},

  pbMaxValue: function(){return w.grp.Grp.pb.maxvalue},

  }

  }

  function ButtonOnClickDuplicateFunction (panel) {

  var SelectedItems = app.project.selection;

  if (SelectedItems.length === 1 && SelectedItems[0] instanceof FolderItem) {

  var PB = CreateProgressBar (); // Calling the function that creates the palette window

  var SelectedItems = app.project.selection;

  for (var c = 0; c < SelectedItems.length; c++) {

  if (SelectedItems instanceof FolderItem) {

  var newFolder = DuplicateFolder(SelectedItems, PB); //Duplicates the original folder and its content

  var copyFolderItems = allItemsInFolder(newFolder); //Every comp, solid, footage in the new folder

  var origFolderItems = allItemsInFolder(SelectedItems); ////Every comp, solid, footage in the original folder

  PB.SetMax(copyFolderItems.length); //Increases the max value

  PB.thePercnText((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%");

  for (var k = 0; k < copyFolderItems.length; k++) {

  if (copyFolderItems instanceof CompItem) {

  PB.SetMax(copyFolderItems.numLayers);

  PB.thePercnText((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%");

  for (var j = 1; j <= copyFolderItems.numLayers; j++) {

  //Replaces each comp's layers in the new folder using layer.replaceSource()

  PB.Increment(); //Increases the value

  PB.thePercnText(((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%"));

  }

  }

  PB.Increment();

  PB.thePercnText(((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%"));

  }

  PB.SetMax(copyFolderItems.length);

  PB.thePercnText((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%");

  for (var g = 0; g < copyFolderItems.length; g++) { //Fixes all the expressions in the new folder

  if (copyFolderItems instanceof CompItem) {

  for (var t = 1; t <= copyFolderItems.numLayers; t++) {

  fixExpressions(copyFolderItems.layer(t), copyFolderItems, origFolderItems);

  }

  }

  PB.Increment();

  PB.thePercnText(((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%"));

  }

  }

  }

  PB.Finished();

  PB.thePercnText((Math.round((PB.pbValue() / PB.pbMaxValue()) * 10000) / 100).toString() + "%");

  PB.theText("All Done!");

  }

  function DuplicateFolder(Folder, PrB) {

  var newFolder = app.project.items.addFolder(Folder.name);

  PrB.SetMax(Folder.numItems);

  for (var b = 1; b <= Folder.numItems; b++) {

  //Duplicates every item in a folder

  PrB.Increment();

  }

  return newFolder;

  }

  function allItemsInFolder(aFolder) {

  var Items = new Array();

  //returns an array with everything in a folder

  }

  function fixExpressions (aProp, copyFolderItems, origFolderItems) {

  //Fixes expressions

  }

  }

  function numCopiesTextChange() {

  numCopiesTextValue = this.text;

  }

  function TrueFolderDuplicatorScript_buildUI(thisObj) { //The dock-able UI of the script

  var panel = (thisObj instanceof Panel) ? thisObj : new Window("palette", "Window Name", undefined, {resizeable:true});

  var res = "group{orientation:'column', alignment:['left','top'],\

  mainPanel: Panel {orientation:'column', alignment:['fill','fill'],\

  FirstGroup: Group{orientation:'row', alignment:['fill','bottom'],\

  numCopies: EditText{text: '1', alignment:['left','fill']},\

  numCopiesText: StaticText{text: 'Copies', alignment:['left','center']},\

  },\

  SecGroup: Group{orientation:'row', alignment:['fill','bottom'],\

  solidsCheckBox: Checkbox{text: 'Duplicate Solids', value: true, alignment:['left','fill']},\

  footageCheckBox: Checkbox{text: 'Duplicate Footage', value: false, alignment:['left','fill']},\

  },\

  replaceButton: Button{text: 'Duplicate!', alignment:['center','bottom']},\

  },\

  }";

  panel.grp = panel.add(res);

  panel.grp.mainPanel.FirstGroup.numCopies.minimumSize = [23,15];

  panel.layout.layout(true);

  panel.grp.minimumSize = panel.grp.size;

  panel.layout.resize();

  panel.onResizing = panel.onResize = function () {this.layout.resize();}

  solidsCheckBoxValue = true;

  footageCheckBoxValue = false;

  panel.grp.mainPanel.SecGroup.solidsCheckBox.onClick = function () {solidsCheckBoxValue = panel.grp.mainPanel.SecGroup.solidsCheckBox.value};

  panel.grp.mainPanel.SecGroup.footageCheckBox.onClick = function () {footageCheckBoxValue = panel.grp.mainPanel.SecGroup.footageCheckBox.value};

  panel.grp.mainPanel.FirstGroup.numCopies.onChange = panel.grp.mainPanel.FirstGroup.numCopies.onChanging = numCopiesTextChange;

  panel.grp.mainPanel.replaceButton.onClick = function () {

  app.beginUndoGroup("Duplicate Folder");

  ButtonOnClickDuplicateFunction(panel);

  app.endUndoGroup();

  }

  return panel;

  }

  var TrueFolderDuplicatorScriptPal = TrueFolderDuplicatorScript_buildUI(thisObj);

  if(TrueFolderDuplicatorScriptPal != null && TrueFolderDuplicatorScriptPal instanceof Window) {

  TrueFolderDuplicatorScriptPal.center();

  TrueFolderDuplicatorScriptPal.show();

  }

  }

  TrueFoldersDuplicatorScript(this);

}

Thanks!

Message was edited by: Osama Sa

This topic has been closed for replies.

3 replies

Osama Sa
Osama SaAuthor
Inspiring
June 16, 2016

So I've just stumbled upon a file called SnpCreateProgressBar.jsx that comes with Adobe ExtendScript CC. Ran this code and the same issue occurred. Can somebody test it on CC15/14 on Mac please?

Here is the code:

////////////////////////////////////////////////////////////////////////////

// ADOBE SYSTEMS INCORPORATED

// Copyright 2007 Adobe Systems Incorporated

// All Rights Reserved

//

// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the

// terms of the Adobe license agreement accompanying it.  If you have received this file from a

// source other than Adobe, then your use, modification, or distribution of it requires the prior

// written permission of Adobe.

/////////////////////////////////////////////////////////////////////////////

  /**

   @fileoverview Shows how to use a progress bar ScriptUI component.

   @class Shows how to use a progress bar ScriptUI component.

  

   <h4>Usage</h4>

   <ol>

   <li> Open this file and run it in the ExtendScript Toolkit.

    You can choose as the target any application that supports ScriptUI

   <li> Press Start in the displayed dialog and watch progress bar update

   <li> Press Reset to return the progress bar to its initial state

   </ol>

  

   <h4>Description</h4>

  

    <p>Creates a dialog containing a progress bar, a button that updates

    its value periodically, and another button that resets the progress to 0.<br />

  

   @constructor Constructor.

  */

function SnpCreateProgressBar ()

{

  this.windowRef = null;

}

/**

Create a window, add a progress-bar control, a text label, and buttons.

Define behavior for the buttons that increment or reset the progress value.

@return True if the snippet ran as expected, false  otherwise.

@type Boolean

*/

SnpCreateProgressBar.prototype.run = function() {

  var retval = true;

  // Create a palette-type window (a modeless or floating dialog),

  var win = new Window("palette", "SnpCreateProgressBar", [150, 150, 600, 300]);

  this.windowRef = win;

  // Add a panel to contain the components

  win.pnl = win.add("panel", [10, 10, 440, 100], "Click Start to move the Progress bar");

  // Add a progress bar with a label and initial value of 0, max value of 200.

  win.pnl.progBarLabel = win.pnl.add("statictext", [20, 20, 320, 35], "Progress");

  win.pnl.progBar = win.pnl.add("progressbar", [20, 35, 410, 60], 0, 1500);

  // Add buttons

  win.goButton = win.add("button", [25, 110, 125, 140], "Start");

  win.resetButton = win.add("button", [150, 110, 250, 140], "Reset");

  win.doneButton = win.add("button", [310, 110, 410, 140], "Done");

  // Define behavior for the "Done" button

  win.doneButton.onClick = function ()

  {

  win.close();

  };

  // Define behavior for the "Start" button

  win.goButton.onClick = function ()

  {

  while(win.pnl.progBar.value < win.pnl.progBar.maxvalue)

  {

  // this is what causes the progress bar increase its progress

  win.pnl.progBar.value++;

             win.update();

  $.sleep(10);

  }

  $.writeln("Progress Bar Complete");

  };

  // Define behavior for the "Reset" button

  win.resetButton.onClick = function()

  {

  // set the progress back to 0

  win.pnl.progBar.value = 0;

  $.writeln("Progress Bar Reset");

  }

  // Display the window

  win.show();

  return retval;

}

/**

"main program": construct an anonymous instance and run it

  as long as we are not unit-testing this snippet.

*/

if(typeof(SnpCreateProgressBar_unitTest) == "undefined") {

    new SnpCreateProgressBar().run();

}

Sorry if I'm not allowed to share the code.

Inspiring
April 5, 2018

I just wrote my own version of that Adobe sample (Osama's posted code comes bundled with the ESTK app if anyone else is looking for it) so here is mine.

I have been playing around with timeouts and stuff and CC2018 is super aggressive about timing out to Windows. It seems to want to lock up the UI if the app can't get control every second or so.

There really should be a call like "aftereffects.runMessageLoopOnce()" or something to keep it from that not responding state. Or we should be able to define a onTimer event handler or something of that sort so we can do long tasks inside a background thread.

I've discovered if I call update() a few times it usually keeps responding... as long as the time between updates never exceeds about five seconds. Well, also as long as you never actually click on any After Effects windows; you do that and it instantly "dies" until the script execution fails.

Here's my code if people want to play around with it. If you change numIterations to 4 it'll update too infrequently and you'll get a Not Responding.

#script "Demo: Progress Bar"

#strict on

(function() { try {

    var resource =

        "palette {" +

            "alignChildren: 'fill'," +

            "panel: Panel {" +

                "orientation: 'column'," +

                "alignment: ['fill', 'fill']," +

                "label: StaticText { text: 'Some text.', alignment: ['fill', 'center'], characters: 20, }," +

                "progress: Progressbar { value: 0, alignment: ['fill', 'center'], }," +

            "}," +

        "}";

    var win = new Window(resource);

    var panel = win.panel;

    var label = panel.label;

    var progress = panel.progress;

    win.layout.resize();

    win.show();

    var totalTime = 25.1; // in seconds

    var numIterations = 6;

    var sleepTime = (totalTime * 1000) / numIterations; // sleep in milliseconds

    win.text = numIterations + " iterations at " + (sleepTime/1000).toFixed(0) + "s each.";

    var then = Date.now();

    for (var i = 0; i < numIterations + 1; ++i) {

        if (i < numIterations)

            label.text = "Iteration " + (i + 1);

        else

            label.text = "Done!";

        progress.value = (100 * i) / numIterations;

        var now = Date.now();

        var elapsedTime = (now - then) / 1000;

        var numUpdates = elapsedTime + 2;

        //$.writeln(numUpdates + " updates.");

        for (var t = 0; t < numUpdates; ++t) {

            win.update();

        }

        then = now;

        $.sleep(sleepTime);

    }

    $.writeln("done.");

    $.sleep(250);

    win.close();

}

catch (error)

{

    var str = error.message + "\n\n"

            + "Exception: " + error.name     + "\n"

            + "File Name: " + File(error.fileName).fsName + "\n"

            + "Line: "      + error.line     + "\n";

    alert(str);

}

})();

Smallpath2013
Inspiring
June 13, 2016

Seems like there is something wrong with program response time of Windows. I'm not sure how the Windows treat a program as `not responsing`. In mac, there isn't `not responsing` error here

UQg
Legend
June 6, 2016

Hi Osama,

given that your script does nothing, it is not possible to test (the progress palette shows normally but things are done too fast and nothing hangs).

But this issue has been adressed several times on this forum (search progress bar + update): for long processes, the bar is not updated and AE is said to be "not responding". I have this too on Windows 7 + ae CC2014, and have never seen a solution for that.

Xavier

Osama Sa
Osama SaAuthor
Inspiring
June 6, 2016

Thanks Xavier.

Here is video of what is going on

That's really bad to have this issue on CC14 as well. Luckily it works on CS5.5.

Just a question, if the progress bar was on the dock-able UI, would I have this issue? if so, would AE crash entirely?

UQg
Legend
June 6, 2016

I dont know if it can make a difference, you can try.

You can also try to update the progress bar value less often, and put more update(), like: w.update(); $.sleep(50); w.update();

It might improve a bit, not sure...

But After Effects not responding during the execution of the script cannot be called a crash.

Xavier