Difference between revisions of "Dev:Adding a Render progress bar"

From Synfig Studio :: Documentation
Jump to: navigation, search
(Create + 1st part)
 
(2nd part)
Line 14: Line 14:
 
After all, this is a kind of information!
 
After all, this is a kind of information!
  
 +
=== How does really a render work? ===
 +
'''App''' ([https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/app.h .h][https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/app.cpp .cpp]) is the root of everything and used to store globals.<br />
 +
But we start in fact from '''CanvasView''' ([https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/canvasview.h .h][https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/canvasview.cpp .cpp]) which contains the call to display the '''RenderSettings''' Dialog ([https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/render.h .h][https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/render.cpp .cpp]).<br />
 +
Then we press on render button which leads to execute an '''AsyncRender''' ([https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/asyncrenderer.h .h][https://github.com/synfig/synfig/blob/master/synfig-studio/src/gui/asyncrenderer.cpp .cpp]) (or 2, sequentially, if we have a second pass for Alpha extraction).<br />
 +
'''AsyncRenderer''' can have 4 types of targets, ''AsyncTarget_Cairo'', AsyncTarget_Cairo_Tile, ''AsyncTarget_Scanline'', AsyncTarget_Tile.<br />
 +
Only ''AsyncTarget_Cairo'' and ''AsyncTarget_Scanline'' have a ''frame_ready()'' function that we will use to implement our call to update to the Render ProgressBar.<br />
 +
 +
Note that we can have 2 passes, this has to be considered when displaying the percents of accomplished render.<br />
  
 
== Implementation ==
 
== Implementation ==
 
=== synfig-studio/src/gui/docks/dock_info.h ===
 
=== synfig-studio/src/gui/docks/dock_info.h ===
 
* Declare the components and members<br />
 
* Declare the components and members<br />
In #include section
+
In #include section:
 
  #include <gtkmm/progressbar.h>
 
  #include <gtkmm/progressbar.h>
  
In private section
+
In private section:
 
  Gtk::ProgressBar render_progress;
 
  Gtk::ProgressBar render_progress;
 
   
 
   
Line 29: Line 37:
 
  int              n_passes_pending;
 
  int              n_passes_pending;
  
In public section
+
In public section:
 
  //! Current render progress - 0.0 to 1.0
 
  //! Current render progress - 0.0 to 1.0
 
  //  depends on n_passes_requested and current_pass
 
  //  depends on n_passes_requested and current_pass
Line 37: Line 45:
  
 
=== synfig-studio/src/gui/docks/dock_info.cpp ===
 
=== synfig-studio/src/gui/docks/dock_info.cpp ===
 +
* Here we will implement the UI and members
 +
In #include section:
 +
#include "app.h"
 +
#include <gtkmm/progressbar.h>
 +
''It will permit to access our App::dock_info_ as a static from anywhere in the application''
 +
 +
In Dock_Info(), at the end:
 +
//Render Progress Bar
 +
table->attach(*manage(new Gtk::Label(_("Render Progress: "))),0,1,5,6,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
 +
table->attach(render_progress,                                0,5,6,7,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
 +
 +
render_progress.set_show_text(true);
 +
render_progress.set_text(strprintf("%.1f%%", 0.0));
 +
render_progress.set_fraction(0.0);
 +
//Another spacer
 +
table->attach(*manage(new Gtk::Label),0,5,7,8);
 +
 +
''just before table->show_all();''
 +
 +
''and after add(*table);''
 +
 +
//Render progress
 +
set_n_passes_requested(1); //Default
 +
set_n_passes_pending  (1); //Default
 +
set_render_progress (0.0); //Default, 0.0%
 +
 +
Then at the end of the file, we add these 3 functions:
 +
 +
void studio::Dock_Info::set_n_passes_requested(int value)
 +
{
 +
    n_passes_requested = value;
 +
}
 +
 
 +
void studio::Dock_Info::set_n_passes_pending(int value)
 +
{
 +
    n_passes_pending = value;
 +
}
 +
 +
void studio::Dock_Info::set_render_progress(float value)
 +
{
 +
  float coeff        = (1.000 / (float)n_passes_requested);  //% of fraction for 1 pass if more than 1 pass
 +
  float already_done = coeff * (float)(n_passes_requested - n_passes_pending -1);
 +
  float r = ( coeff * value ) + already_done;
 +
 +
  render_progress.set_text( strprintf( "%.1f%%", r*100 ));
 +
  render_progress.set_fraction(r);
 +
}
 +
 +
The 2 first ones are obvious, the last one does the calculation for the display of the current percents of the WHOLE TASK.<br />
 +
If we have only 1 pass, value will be reflected directly.<br />
 +
In case of 2 (or more, who knows what will be implemented later!), each pass will still continue to send its progress as if it was the only one in the world; we will do the adjustments here.<br />
 +
100% of pass 1 while be displayed as 50%.<br />
 +
100% of pass 2 while be displayed as 100%.<br />
 +
If we had 3 passes, it would be 33.3%, 66.6% and 100.0%<br />

Revision as of 22:52, 3 January 2019

Now let's implement a Render Progress Bar!
It has been requested several time:
Indication needed that rendering is in progress. #383
Feature request: Give feedback when rendering is happening and complete #626
also in Default render parameter are bad #464

Things to take into account

  • Where to place the Progress Bar?
  • How does really a render work?
  • Where to do calls and implementation?

Where to place the Progress Bar?

I chose to implement it in the Dock_Info panel.
After all, this is a kind of information!

How does really a render work?

App (.h.cpp) is the root of everything and used to store globals.
But we start in fact from CanvasView (.h.cpp) which contains the call to display the RenderSettings Dialog (.h.cpp).
Then we press on render button which leads to execute an AsyncRender (.h.cpp) (or 2, sequentially, if we have a second pass for Alpha extraction).
AsyncRenderer can have 4 types of targets, AsyncTarget_Cairo, AsyncTarget_Cairo_Tile, AsyncTarget_Scanline, AsyncTarget_Tile.
Only AsyncTarget_Cairo and AsyncTarget_Scanline have a frame_ready() function that we will use to implement our call to update to the Render ProgressBar.

Note that we can have 2 passes, this has to be considered when displaying the percents of accomplished render.

Implementation

synfig-studio/src/gui/docks/dock_info.h

  • Declare the components and members

In #include section:

#include <gtkmm/progressbar.h>

In private section:

Gtk::ProgressBar render_progress;

//! Number of passes request - 1 or 2 (if alpha)
int              n_passes_requested;
//! Number of passes pending - 2,1,0
int              n_passes_pending;

In public section:

//! Current render progress - 0.0 to 1.0
//  depends on n_passes_requested and current_pass
void set_render_progress   (float value);
void set_n_passes_requested(int   value);
void set_n_passes_pending  (int   value);

synfig-studio/src/gui/docks/dock_info.cpp

  • Here we will implement the UI and members

In #include section:

#include "app.h"
#include <gtkmm/progressbar.h>

It will permit to access our App::dock_info_ as a static from anywhere in the application

In Dock_Info(), at the end:

//Render Progress Bar
table->attach(*manage(new Gtk::Label(_("Render Progress: "))),0,1,5,6,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
table->attach(render_progress,                                0,5,6,7,Gtk::EXPAND|Gtk::FILL,Gtk::SHRINK|Gtk::FILL);
render_progress.set_show_text(true);
render_progress.set_text(strprintf("%.1f%%", 0.0));
render_progress.set_fraction(0.0);
//Another spacer
table->attach(*manage(new Gtk::Label),0,5,7,8);

just before table->show_all();

and after add(*table);

//Render progress
set_n_passes_requested(1); //Default
set_n_passes_pending  (1); //Default
set_render_progress (0.0); //Default, 0.0%

Then at the end of the file, we add these 3 functions:

void studio::Dock_Info::set_n_passes_requested(int value)
{
    n_passes_requested = value;
}
 	
void studio::Dock_Info::set_n_passes_pending(int value)
{
    n_passes_pending = value;
}
void studio::Dock_Info::set_render_progress(float value)
{
 float coeff        = (1.000 / (float)n_passes_requested);  //% of fraction for 1 pass if more than 1 pass
 float already_done = coeff * (float)(n_passes_requested - n_passes_pending -1); 
 float r = ( coeff * value ) + already_done;

 render_progress.set_text( strprintf( "%.1f%%", r*100 ));
 render_progress.set_fraction(r);
}

The 2 first ones are obvious, the last one does the calculation for the display of the current percents of the WHOLE TASK.
If we have only 1 pass, value will be reflected directly.
In case of 2 (or more, who knows what will be implemented later!), each pass will still continue to send its progress as if it was the only one in the world; we will do the adjustments here.
100% of pass 1 while be displayed as 50%.
100% of pass 2 while be displayed as 100%.
If we had 3 passes, it would be 33.3%, 66.6% and 100.0%