Maya C++ API: create a progress window
How to add a progress bar in Maya's UI. - 05/2022 - #Maya
Leaving some C++ code snippet to display a progress window (MProgressWindow) or progress Bar (MComputation) within Maya's interface. Note that using MProgessWindow or MComputation inside a node's compute() method is unsafe/undefined. I may add that as stated in the documentation you should not modify anything within a compute() method except for the node's output attributes.
Progress window snippet:
#pragma once #include <string> #include <time.h> /** * @brief Maya progress window wrapper. * * Display a progress window in Maya * Usage: @code int total = nb_iter; Progress_window window("Process in progress", total); // will only display progress if operation is running greater than // a certain delay window.set_delay(0.5); // (optional default = 1 sec) for(int iter = 0; iter < total; iter++) { if(window.is_canceled()) break; //do stuff ... window.add(1); } window.stop(); // Optional (performed when the object is destructed) @endcode @warning Like a lot of things in Maya nodes it's not safe to use a progress window (or any UI related functions) inside a MPxNode::compute() MPxDeformer::deform() etc. * */ class Progress_window { private: /// How much we wait before displaying the window /// (time represented in clocks ticks) (see time.h clock()) time_t _delay; /// starting time (in clock ticks) (see time.h clock()) time_t _start; bool _is_init; bool _interruptable; std::string _win_title; int _progress; int _max_range; public: Progress_window(); Progress_window(const std::string& win_title, int max_range, bool interuptable = true); ~Progress_window(); void start(const std::string& win_title, int max_range); void set_delay(float seconds) { _delay = time_t((float)CLOCKS_PER_SEC*seconds); _delay = _delay <= 0 ? 0 : _delay; } void add_progess(int increment = 1); void stop(); /// @brief force window to show regardless of the delay /// set with "set_delay()" void show(); /// @return if the canceled button was hit by the user. const bool is_canceled()const; };
#include "progress_window.hpp" #include <maya_error.hpp> // my custom macros to check errors #include <maya/MProgressWindow.h> #include <maya/MString.h> Progress_window::Progress_window() : _delay(CLOCKS_PER_SEC*1) { } // ----------------------------------------------------------------------------- Progress_window::Progress_window(const std::string& win_title, int max_range, bool interuptable) : _delay(CLOCKS_PER_SEC*1) , _interruptable( interuptable ) { start(win_title,max_range); } // ----------------------------------------------------------------------------- Progress_window::~Progress_window(void) { stop(); } // ----------------------------------------------------------------------------- void Progress_window::start(const std::string& win_title, int max_range) { _max_range = max_range; _win_title = win_title; _start = clock(); _progress = 0; _is_init = false; } // ----------------------------------------------------------------------------- void Progress_window::stop() { if (_is_init) { // Maya doc: // Destroys the progress window and removes it from the screen. // This method also unreserves the progress window, // making it available for future reservation. mayaCheck( MProgressWindow::endProgress() ); _is_init = false; } } // ----------------------------------------------------------------------------- void Progress_window::add_progess(int increment) { if( clock() > (_start + Progress_window::_delay) ) { show(); } if (_is_init){ mayaCheck( MProgressWindow::advanceProgress(increment) ); } else{ _progress += increment; } } // ----------------------------------------------------------------------------- void Progress_window::show() { if(!_is_init ) { // Maya doc: MProgressWindow::reserve() // Reserves a progress window for use through this class. // This method must be called before setting progress window parameters or starting progress. // Returns: true if the progress window was successfully reserved if (MProgressWindow::reserve()) { _is_init = true; mayaCheck( MProgressWindow::setProgressRange(0, _max_range) ); mayaCheck( MProgressWindow::setTitle( _win_title.c_str() ) ); mayaCheck( MProgressWindow::setProgressStatus(_win_title.c_str()) ); mayaCheck( MProgressWindow::setInterruptable(_interruptable) ); mayaCheck( MProgressWindow::setProgress(_progress) ); // Maya doc: Displays the progress window on the screen. mayaCheck( MProgressWindow::startProgress() ); } } } // ----------------------------------------------------------------------------- const bool Progress_window::is_canceled() const { return _is_init && MProgressWindow::isCancelled(); }
Progress bar snippet:
#pragma once #include <string> #include <time.h> #include <maya/MComputation.h> /** * @brief Maya MComputation wrapper. * * Display a progress bar in the lower left corner of Maya UI * You can also cancel computation with "ESC" key * Usage: @code int total = nb_iter; Progress_bar a_bar("Process in progress", total); // will only display progress if operation is running greater than // a certain delay a_bar.set_delay(0.5); // (optional default = 1 sec) for(int iter = 0; iter < total; iter++) { // Triggered on escape key: if(a_bar.is_canceled()) break; //do stuff ... a_bar.add(1); } a_bar.stop(); // Optional (performed when the object is destructed) @endcode @warning Like a lot of things in Maya nodes it's not safe to use a progress bar (or any UI related functions) inside a MPxNode::compute() MPxDeformer::deform() etc. * */ class Progress_bar { private: mutable MComputation _computation; /* MComputation is not const correct..*/ /// How much we wait before displaying the window /// (time represented in clocks ticks) (see time.h clock()) time_t _delay; /// starting time (in clock ticks) (see time.h clock()) time_t _start; bool _is_init; bool _interruptable; std::string _win_title; int _progress; int _max_range; public: Progress_bar(); Progress_bar(const std::string& win_title, int max_range, bool interuptable = true); ~Progress_bar(); void start(const std::string& win_title, int max_range); void set_delay(float seconds) { _delay = time_t((float)CLOCKS_PER_SEC*seconds); _delay = _delay <= 0 ? 0 : _delay; } void add_progess(int increment = 1); void stop(); /// @brief force window to show regardless of the delay /// set with "set_delay()" void show(); /// @return if the canceled button was hit by the user. const bool is_canceled()const; };
#include "progress_bar.hpp" #include <maya_error.hpp> // custom macros to hande errors #include <maya/MString.h> Progress_bar::Progress_bar() : _delay(CLOCKS_PER_SEC*1) { } // ----------------------------------------------------------------------------- Progress_bar::Progress_bar(const std::string& win_title, int max_range, bool interuptable) : _delay(CLOCKS_PER_SEC*1) , _interruptable( interuptable ) { start(win_title,max_range); } // ----------------------------------------------------------------------------- Progress_bar::~Progress_bar(void) { stop(); } // ----------------------------------------------------------------------------- void Progress_bar::start(const std::string& win_title, int max_range) { _max_range = max_range; _win_title = win_title; _start = clock(); _progress = 0; _is_init = false; } // ----------------------------------------------------------------------------- void Progress_bar::stop() { if (_is_init) { _computation.endComputation(); _is_init = false; } } // ----------------------------------------------------------------------------- void Progress_bar::add_progess(int increment) { _progress += increment; if( clock() > (_start + Progress_bar::_delay) ) { show(); } if (_is_init){ _computation.setProgress(_progress); } } // ----------------------------------------------------------------------------- void Progress_bar::show() { if(!_is_init ) { _is_init = true; _computation.beginComputation(true/*show progress bar*/, _interruptable, true /*wait cursor*/); if( !_interruptable ) _computation.setProgressStatus( _win_title.c_str() ); _computation.setProgressRange(0, _max_range) ; _computation.setProgress(_progress); } } // ----------------------------------------------------------------------------- const bool Progress_bar::is_canceled() const { return _is_init && _computation.isInterruptRequested(); }
No comments