2018-11-08 13:23:17 +00:00
# ifndef slic3r_PrintBase_hpp_
# define slic3r_PrintBase_hpp_
# include "libslic3r.h"
# include <set>
# include <vector>
# include <string>
# include <functional>
// tbb/mutex.h includes Windows, which in turn defines min/max macros. Convince Windows.h to not define these min/max macros.
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include "tbb/mutex.h"
# include "Model.hpp"
2018-12-03 12:14:28 +00:00
# include "PlaceholderParser.hpp"
2018-11-08 13:23:17 +00:00
# include "PrintConfig.hpp"
namespace Slic3r {
class CanceledException : public std : : exception {
public :
const char * what ( ) const throw ( ) { return " Background processing has been canceled " ; }
} ;
2018-11-16 17:28:50 +00:00
class PrintStateBase {
2018-11-08 13:23:17 +00:00
public :
enum State {
INVALID ,
STARTED ,
DONE ,
} ;
2018-11-16 17:28:50 +00:00
2018-11-20 12:22:26 +00:00
typedef size_t TimeStamp ;
2018-11-16 17:28:50 +00:00
// A new unique timestamp is being assigned to the step every time the step changes its state.
struct StateWithTimeStamp
{
StateWithTimeStamp ( ) : state ( INVALID ) , timestamp ( 0 ) { }
2018-11-20 12:22:26 +00:00
State state ;
TimeStamp timestamp ;
2018-11-16 17:28:50 +00:00
} ;
protected :
//FIXME last timestamp is shared between Print & SLAPrint,
// and if multiple Print or SLAPrint instances are executed in parallel, modification of g_last_timestamp
// is not synchronized!
static size_t g_last_timestamp ;
} ;
// To be instantiated over PrintStep or PrintObjectStep enums.
template < class StepType , size_t COUNT >
class PrintState : public PrintStateBase
{
public :
PrintState ( ) { }
StateWithTimeStamp state_with_timestamp ( StepType step , tbb : : mutex & mtx ) const {
tbb : : mutex : : scoped_lock lock ( mtx ) ;
StateWithTimeStamp state = m_state [ step ] ;
return state ;
}
2019-02-21 07:44:07 +00:00
bool is_started ( StepType step , tbb : : mutex & mtx ) const {
return this - > state_with_timestamp ( step , mtx ) . state = = STARTED ;
}
2018-11-16 17:28:50 +00:00
bool is_done ( StepType step , tbb : : mutex & mtx ) const {
return this - > state_with_timestamp ( step , mtx ) . state = = DONE ;
}
StateWithTimeStamp state_with_timestamp_unguarded ( StepType step ) const {
return m_state [ step ] ;
}
2019-02-21 07:44:07 +00:00
bool is_started_unguarded ( StepType step ) const {
return this - > state_with_timestamp_unguarded ( step ) . state = = STARTED ;
}
2018-11-16 17:28:50 +00:00
bool is_done_unguarded ( StepType step ) const {
return this - > state_with_timestamp_unguarded ( step ) . state = = DONE ;
}
2018-11-08 13:23:17 +00:00
// Set the step as started. Block on mutex while the Print / PrintObject / PrintRegion objects are being
// modified by the UI thread.
2019-05-22 14:43:14 +00:00
// This is necessary to block until the Print::apply() updates its state, which may
2018-11-08 13:23:17 +00:00
// influence the processing step being entered.
2018-11-16 17:28:50 +00:00
template < typename ThrowIfCanceled >
bool set_started ( StepType step , tbb : : mutex & mtx , ThrowIfCanceled throw_if_canceled ) {
tbb : : mutex : : scoped_lock lock ( mtx ) ;
// If canceled, throw before changing the step state.
throw_if_canceled ( ) ;
if ( m_state [ step ] . state = = DONE )
return false ;
m_state [ step ] . state = STARTED ;
m_state [ step ] . timestamp = + + g_last_timestamp ;
return true ;
2018-11-08 13:23:17 +00:00
}
// Set the step as done. Block on mutex while the Print / PrintObject / PrintRegion objects are being
// modified by the UI thread.
2018-11-16 17:28:50 +00:00
template < typename ThrowIfCanceled >
2018-11-20 12:22:26 +00:00
TimeStamp set_done ( StepType step , tbb : : mutex & mtx , ThrowIfCanceled throw_if_canceled ) {
2018-11-16 17:28:50 +00:00
tbb : : mutex : : scoped_lock lock ( mtx ) ;
// If canceled, throw before changing the step state.
throw_if_canceled ( ) ;
assert ( m_state [ step ] . state ! = DONE ) ;
m_state [ step ] . state = DONE ;
m_state [ step ] . timestamp = + + g_last_timestamp ;
2018-11-20 12:22:26 +00:00
return m_state [ step ] . timestamp ;
2018-11-08 13:23:17 +00:00
}
// Make the step invalid.
2018-11-16 17:28:50 +00:00
// PrintBase::m_state_mutex should be locked at this point, guarding access to m_state.
2018-11-08 13:23:17 +00:00
// In case the step has already been entered or finished, cancel the background
// processing by calling the cancel callback.
template < typename CancelationCallback >
2018-11-16 17:28:50 +00:00
bool invalidate ( StepType step , CancelationCallback cancel ) {
bool invalidated = m_state [ step ] . state ! = INVALID ;
2018-11-08 13:23:17 +00:00
if ( invalidated ) {
#if 0
if ( mtx . state ! = mtx . HELD ) {
printf ( " Not held! \n " ) ;
}
# endif
2018-11-16 17:28:50 +00:00
m_state [ step ] . state = INVALID ;
m_state [ step ] . timestamp = + + g_last_timestamp ;
2018-11-08 13:23:17 +00:00
// Raise the mutex, so that the following cancel() callback could cancel
// the background processing.
2018-11-16 17:28:50 +00:00
// Internally the cancel() callback shall unlock the PrintBase::m_status_mutex to let
// the working thread to proceed.
2018-11-08 13:23:17 +00:00
cancel ( ) ;
}
return invalidated ;
}
template < typename CancelationCallback , typename StepTypeIterator >
2018-11-16 17:28:50 +00:00
bool invalidate_multiple ( StepTypeIterator step_begin , StepTypeIterator step_end , CancelationCallback cancel ) {
2018-11-08 13:23:17 +00:00
bool invalidated = false ;
2018-11-16 17:28:50 +00:00
for ( StepTypeIterator it = step_begin ; it ! = step_end ; + + it ) {
StateWithTimeStamp & state = m_state [ * it ] ;
if ( state . state ! = INVALID ) {
invalidated = true ;
state . state = INVALID ;
state . timestamp = + + g_last_timestamp ;
}
}
2018-11-08 13:23:17 +00:00
if ( invalidated ) {
#if 0
if ( mtx . state ! = mtx . HELD ) {
printf ( " Not held! \n " ) ;
}
# endif
// Raise the mutex, so that the following cancel() callback could cancel
// the background processing.
2018-11-16 17:28:50 +00:00
// Internally the cancel() callback shall unlock the PrintBase::m_status_mutex to let
// the working thread to proceed.
2018-11-08 13:23:17 +00:00
cancel ( ) ;
}
return invalidated ;
}
// Make all steps invalid.
2018-11-16 17:28:50 +00:00
// PrintBase::m_state_mutex should be locked at this point, guarding access to m_state.
2018-11-08 13:23:17 +00:00
// In case any step has already been entered or finished, cancel the background
// processing by calling the cancel callback.
template < typename CancelationCallback >
2018-11-16 17:28:50 +00:00
bool invalidate_all ( CancelationCallback cancel ) {
2018-11-08 13:23:17 +00:00
bool invalidated = false ;
2018-11-16 17:28:50 +00:00
for ( size_t i = 0 ; i < COUNT ; + + i ) {
StateWithTimeStamp & state = m_state [ i ] ;
if ( state . state ! = INVALID ) {
2018-11-08 13:23:17 +00:00
invalidated = true ;
2018-11-16 17:28:50 +00:00
state . state = INVALID ;
state . timestamp = + + g_last_timestamp ;
2018-11-08 13:23:17 +00:00
}
}
2018-11-16 17:28:50 +00:00
if ( invalidated )
cancel ( ) ;
2018-11-08 13:23:17 +00:00
return invalidated ;
}
private :
2018-11-16 17:28:50 +00:00
StateWithTimeStamp m_state [ COUNT ] ;
2018-11-08 13:23:17 +00:00
} ;
class PrintBase ;
class PrintObjectBase
{
2018-11-16 17:28:50 +00:00
public :
const ModelObject * model_object ( ) const { return m_model_object ; }
ModelObject * model_object ( ) { return m_model_object ; }
2018-11-08 13:23:17 +00:00
protected :
2018-11-16 17:28:50 +00:00
PrintObjectBase ( ModelObject * model_object ) : m_model_object ( model_object ) { }
2018-11-08 13:23:17 +00:00
virtual ~ PrintObjectBase ( ) { }
// Declared here to allow access from PrintBase through friendship.
2018-11-16 17:28:50 +00:00
static tbb : : mutex & state_mutex ( PrintBase * print ) ;
2018-11-08 13:23:17 +00:00
static std : : function < void ( ) > cancel_callback ( PrintBase * print ) ;
2018-11-16 17:28:50 +00:00
ModelObject * m_model_object ;
2018-11-08 13:23:17 +00:00
} ;
/**
* @ brief Printing involves slicing and export of device dependent instructions .
*
* Every technology has a potentially different set of requirements for
* slicing , support structures and output print instructions . The pipeline
* however remains roughly the same :
* slice - > convert to instructions - > send to printer
*
* The PrintBase class will abstract this flow for different technologies .
*
*/
class PrintBase
{
public :
2019-07-25 12:39:19 +00:00
PrintBase ( ) : m_placeholder_parser ( & m_full_print_config ) { this - > restart ( ) ; }
2018-11-08 13:23:17 +00:00
inline virtual ~ PrintBase ( ) { }
virtual PrinterTechnology technology ( ) const noexcept = 0 ;
// Reset the print status including the copy of the Model / ModelObject hierarchy.
virtual void clear ( ) = 0 ;
2018-11-08 19:18:40 +00:00
// The Print is empty either after clear() or after apply() over an empty model,
// or after apply() over a model, where no object is printable (all outside the print volume).
virtual bool empty ( ) const = 0 ;
// Validate the print, return empty string if valid, return error if process() cannot (or should not) be started.
virtual std : : string validate ( ) const { return std : : string ( ) ; }
2018-11-08 13:23:17 +00:00
enum ApplyStatus {
// No change after the Print::apply() call.
APPLY_STATUS_UNCHANGED ,
// Some of the Print / PrintObject / PrintObjectInstance data was changed,
// but no result was invalidated (only data influencing not yet calculated results were changed).
APPLY_STATUS_CHANGED ,
// Some data was changed, which in turn invalidated already calculated steps.
APPLY_STATUS_INVALIDATED ,
} ;
2019-07-25 12:39:19 +00:00
virtual ApplyStatus apply ( const Model & model , DynamicPrintConfig config ) = 0 ;
2018-11-16 17:28:50 +00:00
const Model & model ( ) const { return m_model ; }
2018-11-08 13:23:17 +00:00
2019-02-21 07:44:07 +00:00
struct TaskParams {
TaskParams ( ) : single_model_object ( 0 ) , single_model_instance_only ( false ) , to_object_step ( - 1 ) , to_print_step ( - 1 ) { }
// If non-empty, limit the processing to this ModelObject.
2019-06-27 09:02:45 +00:00
ObjectID single_model_object ;
2019-02-21 07:44:07 +00:00
// If set, only process single_model_object. Otherwise process everything, but single_model_object first.
bool single_model_instance_only ;
// If non-negative, stop processing at the successive object step.
int to_object_step ;
// If non-negative, stop processing at the successive print step.
int to_print_step ;
} ;
2019-02-21 10:40:56 +00:00
// After calling the apply() function, call set_task() to limit the task to be processed by process().
virtual void set_task ( const TaskParams & params ) { }
// Perform the calculation. This is the only method that is to be called at a worker thread.
2018-11-08 13:23:17 +00:00
virtual void process ( ) = 0 ;
2019-02-21 10:40:56 +00:00
// Clean up after process() finished, either with success, error or if canceled.
// The adjustments on the Print / PrintObject data due to set_task() are to be reverted here.
virtual void finalize ( ) { }
2018-11-08 13:23:17 +00:00
2018-11-20 15:27:30 +00:00
struct SlicingStatus {
SlicingStatus ( int percent , const std : : string & text , unsigned int flags = 0 ) : percent ( percent ) , text ( text ) , flags ( flags ) { }
2018-11-20 12:22:26 +00:00
int percent ;
std : : string text ;
// Bitmap of flags.
enum FlagBits {
2019-09-25 10:06:38 +00:00
DEFAULT = 0 ,
2019-02-06 13:18:04 +00:00
RELOAD_SCENE = 1 < < 1 ,
RELOAD_SLA_SUPPORT_POINTS = 1 < < 2 ,
2019-03-14 14:11:27 +00:00
RELOAD_SLA_PREVIEW = 1 < < 3 ,
2018-11-20 12:22:26 +00:00
} ;
// Bitmap of FlagBits
unsigned int flags ;
} ;
2018-11-20 15:27:30 +00:00
typedef std : : function < void ( const SlicingStatus & ) > status_callback_type ;
2018-11-08 13:23:17 +00:00
// Default status console print out in the form of percent => message.
void set_status_default ( ) { m_status_callback = nullptr ; }
// No status output or callback whatsoever, useful mostly for automatic tests.
2018-11-20 15:27:30 +00:00
void set_status_silent ( ) { m_status_callback = [ ] ( const SlicingStatus & ) { } ; }
2018-11-08 13:23:17 +00:00
// Register a custom status callback.
void set_status_callback ( status_callback_type cb ) { m_status_callback = cb ; }
// Calls a registered callback to update the status, or print out the default message.
2018-11-21 11:10:10 +00:00
void set_status ( int percent , const std : : string & message , unsigned int flags = SlicingStatus : : DEFAULT ) {
2018-11-20 15:27:30 +00:00
if ( m_status_callback ) m_status_callback ( SlicingStatus ( percent , message , flags ) ) ;
2018-11-08 13:23:17 +00:00
else printf ( " %d => %s \n " , percent , message . c_str ( ) ) ;
}
typedef std : : function < void ( ) > cancel_callback_type ;
// Various methods will call this callback to stop the background processing (the Print::process() call)
// in case a successive change of the Print / PrintObject / PrintRegion instances changed
// the state of the finished or running calculations.
2018-12-03 12:14:28 +00:00
void set_cancel_callback ( cancel_callback_type cancel_callback ) { m_cancel_callback = cancel_callback ; }
2018-11-08 13:23:17 +00:00
// Has the calculation been canceled?
enum CancelStatus {
// No cancelation, background processing should run.
NOT_CANCELED = 0 ,
// Canceled by user from the user interface (user pressed the "Cancel" button or user closed the application).
CANCELED_BY_USER = 1 ,
// Canceled internally from Print::apply() through the Print/PrintObject::invalidate_step() or ::invalidate_all_steps().
CANCELED_INTERNAL = 2
} ;
2018-12-03 12:14:28 +00:00
CancelStatus cancel_status ( ) const { return m_cancel_status ; }
2018-11-08 13:23:17 +00:00
// Has the calculation been canceled?
2018-12-03 12:14:28 +00:00
bool canceled ( ) const { return m_cancel_status ! = NOT_CANCELED ; }
2018-11-08 13:23:17 +00:00
// Cancel the running computation. Stop execution of all the background threads.
2018-12-03 12:14:28 +00:00
void cancel ( ) { m_cancel_status = CANCELED_BY_USER ; }
void cancel_internal ( ) { m_cancel_status = CANCELED_INTERNAL ; }
2018-11-08 13:23:17 +00:00
// Cancel the running computation. Stop execution of all the background threads.
2018-12-03 12:14:28 +00:00
void restart ( ) { m_cancel_status = NOT_CANCELED ; }
2018-12-11 16:49:31 +00:00
// Returns true if the last step was finished with success.
virtual bool finished ( ) const = 0 ;
2018-12-03 12:14:28 +00:00
const PlaceholderParser & placeholder_parser ( ) const { return m_placeholder_parser ; }
2019-07-25 12:39:19 +00:00
const DynamicPrintConfig & full_print_config ( ) const { return m_full_print_config ; }
2018-12-03 12:14:28 +00:00
2019-05-17 14:27:00 +00:00
virtual std : : string output_filename ( const std : : string & filename_base = std : : string ( ) ) const = 0 ;
// If the filename_base is set, it is used as the input for the template processing. In that case the path is expected to be the directory (may be empty).
// If filename_set is empty, than the path may be a file or directory. If it is a file, then the macro will not be processed.
std : : string output_filepath ( const std : : string & path , const std : : string & filename_base = std : : string ( ) ) const ;
2018-11-08 13:23:17 +00:00
protected :
friend class PrintObjectBase ;
2018-11-16 17:28:50 +00:00
friend class BackgroundSlicingProcess ;
2018-11-08 13:23:17 +00:00
2018-11-16 17:28:50 +00:00
tbb : : mutex & state_mutex ( ) const { return m_state_mutex ; }
2018-11-08 13:23:17 +00:00
std : : function < void ( ) > cancel_callback ( ) { return m_cancel_callback ; }
2019-02-21 11:39:38 +00:00
void call_cancel_callback ( ) { m_cancel_callback ( ) ; }
2018-11-08 13:23:17 +00:00
// If the background processing stop was requested, throw CanceledException.
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
void throw_if_canceled ( ) const { if ( m_cancel_status ) throw CanceledException ( ) ; }
2018-12-03 12:14:28 +00:00
// To be called by this->output_filename() with the format string pulled from the configuration layer.
2019-05-17 14:27:00 +00:00
std : : string output_filename ( const std : : string & format , const std : : string & default_ext , const std : : string & filename_base , const DynamicConfig * config_override = nullptr ) const ;
2018-12-03 12:14:28 +00:00
// Update "scale", "input_filename", "input_filename_base" placeholders from the current printable ModelObjects.
2019-05-17 14:27:00 +00:00
void update_object_placeholders ( DynamicConfig & config , const std : : string & default_ext ) const ;
2018-12-03 12:14:28 +00:00
2018-11-16 17:28:50 +00:00
Model m_model ;
2019-07-25 12:39:19 +00:00
DynamicPrintConfig m_full_print_config ;
2019-07-25 15:08:31 +00:00
PlaceholderParser m_placeholder_parser ;
2018-11-16 17:28:50 +00:00
2018-11-08 13:23:17 +00:00
private :
tbb : : atomic < CancelStatus > m_cancel_status ;
// Callback to be evoked regularly to update state of the UI thread.
status_callback_type m_status_callback ;
// Callback to be evoked to stop the background processing before a state is updated.
cancel_callback_type m_cancel_callback = [ ] ( ) { } ;
// Mutex used for synchronization of the worker thread with the UI thread:
// The mutex will be used to guard the worker thread against entering a stage
// while the data influencing the stage is modified.
2018-11-16 17:28:50 +00:00
mutable tbb : : mutex m_state_mutex ;
2018-11-08 13:23:17 +00:00
} ;
template < typename PrintStepEnum , const size_t COUNT >
class PrintBaseWithState : public PrintBase
{
public :
2018-11-16 17:28:50 +00:00
bool is_step_done ( PrintStepEnum step ) const { return m_state . is_done ( step , this - > state_mutex ( ) ) ; }
PrintStateBase : : StateWithTimeStamp step_state_with_timestamp ( PrintStepEnum step ) const { return m_state . state_with_timestamp ( step , this - > state_mutex ( ) ) ; }
2018-11-08 13:23:17 +00:00
protected :
2018-11-16 17:28:50 +00:00
bool set_started ( PrintStepEnum step ) { return m_state . set_started ( step , this - > state_mutex ( ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ; }
2018-11-20 12:22:26 +00:00
PrintStateBase : : TimeStamp set_done ( PrintStepEnum step ) { return m_state . set_done ( step , this - > state_mutex ( ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ; }
2018-11-08 13:23:17 +00:00
bool invalidate_step ( PrintStepEnum step )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate ( step , this - > cancel_callback ( ) ) ; }
2018-11-08 13:23:17 +00:00
template < typename StepTypeIterator >
bool invalidate_steps ( StepTypeIterator step_begin , StepTypeIterator step_end )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate_multiple ( step_begin , step_end , this - > cancel_callback ( ) ) ; }
2018-11-08 13:23:17 +00:00
bool invalidate_steps ( std : : initializer_list < PrintStepEnum > il )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate_multiple ( il . begin ( ) , il . end ( ) , this - > cancel_callback ( ) ) ; }
2018-11-08 13:23:17 +00:00
bool invalidate_all_steps ( )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate_all ( this - > cancel_callback ( ) ) ; }
2018-11-08 13:23:17 +00:00
2019-02-21 07:44:07 +00:00
bool is_step_started_unguarded ( PrintStepEnum step ) const { return m_state . is_started_unguarded ( step ) ; }
bool is_step_done_unguarded ( PrintStepEnum step ) const { return m_state . is_done_unguarded ( step ) ; }
2018-11-08 13:23:17 +00:00
private :
PrintState < PrintStepEnum , COUNT > m_state ;
} ;
template < typename PrintType , typename PrintObjectStepEnum , const size_t COUNT >
class PrintObjectBaseWithState : public PrintObjectBase
{
public :
2018-11-09 11:02:42 +00:00
PrintType * print ( ) { return m_print ; }
const PrintType * print ( ) const { return m_print ; }
2018-11-08 13:23:17 +00:00
2018-11-16 17:28:50 +00:00
typedef PrintState < PrintObjectStepEnum , COUNT > PrintObjectState ;
bool is_step_done ( PrintObjectStepEnum step ) const { return m_state . is_done ( step , PrintObjectBase : : state_mutex ( m_print ) ) ; }
PrintStateBase : : StateWithTimeStamp step_state_with_timestamp ( PrintObjectStepEnum step ) const { return m_state . state_with_timestamp ( step , PrintObjectBase : : state_mutex ( m_print ) ) ; }
2018-11-08 13:23:17 +00:00
protected :
2018-11-16 17:28:50 +00:00
PrintObjectBaseWithState ( PrintType * print , ModelObject * model_object ) : PrintObjectBase ( model_object ) , m_print ( print ) { }
2018-11-08 13:23:17 +00:00
2018-11-16 17:28:50 +00:00
bool set_started ( PrintObjectStepEnum step )
2018-11-20 14:18:46 +00:00
{ return m_state . set_started ( step , PrintObjectBase : : state_mutex ( m_print ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ; }
2018-11-20 12:22:26 +00:00
PrintStateBase : : TimeStamp set_done ( PrintObjectStepEnum step )
2018-11-20 14:18:46 +00:00
{ return m_state . set_done ( step , PrintObjectBase : : state_mutex ( m_print ) , [ this ] ( ) { this - > throw_if_canceled ( ) ; } ) ; }
2018-11-08 13:23:17 +00:00
bool invalidate_step ( PrintObjectStepEnum step )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate ( step , PrintObjectBase : : cancel_callback ( m_print ) ) ; }
2018-11-08 13:23:17 +00:00
template < typename StepTypeIterator >
bool invalidate_steps ( StepTypeIterator step_begin , StepTypeIterator step_end )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate_multiple ( step_begin , step_end , PrintObjectBase : : cancel_callback ( m_print ) ) ; }
2018-11-08 13:23:17 +00:00
bool invalidate_steps ( std : : initializer_list < PrintObjectStepEnum > il )
2018-11-16 17:28:50 +00:00
{ return m_state . invalidate_multiple ( il . begin ( ) , il . end ( ) , PrintObjectBase : : cancel_callback ( m_print ) ) ; }
bool invalidate_all_steps ( )
{ return m_state . invalidate_all ( PrintObjectBase : : cancel_callback ( m_print ) ) ; }
2018-11-08 13:23:17 +00:00
2019-02-21 07:44:07 +00:00
bool is_step_started_unguarded ( PrintObjectStepEnum step ) const { return m_state . is_started_unguarded ( step ) ; }
bool is_step_done_unguarded ( PrintObjectStepEnum step ) const { return m_state . is_done_unguarded ( step ) ; }
2018-11-08 13:23:17 +00:00
protected :
2018-11-20 14:18:46 +00:00
// If the background processing stop was requested, throw CanceledException.
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
void throw_if_canceled ( ) { if ( m_print - > canceled ( ) ) throw CanceledException ( ) ; }
2018-11-08 13:57:42 +00:00
friend PrintType ;
2018-11-08 13:23:17 +00:00
PrintType * m_print ;
private :
PrintState < PrintObjectStepEnum , COUNT > m_state ;
} ;
} // namespace Slic3r
# endif /* slic3r_PrintBase_hpp_ */