2019-06-27 09:02:45 +00:00
# ifndef slic3r_ObjectID_hpp_
# define slic3r_ObjectID_hpp_
2019-07-04 20:09:14 +00:00
# include <cereal/access.hpp>
2019-06-27 09:02:45 +00:00
namespace Slic3r {
2019-07-02 14:42:23 +00:00
namespace UndoRedo {
class StackImpl ;
} ;
2019-06-27 09:02:45 +00:00
// Unique identifier of a mutable object accross the application.
// Used to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject)
// (for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial classes)
// and to serialize / deserialize an object onto the Undo / Redo stack.
// Valid IDs are strictly positive (non zero).
// It is declared as an object, as some compilers (notably msvcc) consider a typedef size_t equivalent to size_t
// for parameter overload.
class ObjectID
{
public :
ObjectID ( size_t id ) : id ( id ) { }
2019-07-04 12:35:04 +00:00
// Default constructor constructs an invalid ObjectID.
ObjectID ( ) : id ( 0 ) { }
2019-06-27 09:02:45 +00:00
bool operator = = ( const ObjectID & rhs ) const { return this - > id = = rhs . id ; }
bool operator ! = ( const ObjectID & rhs ) const { return this - > id ! = rhs . id ; }
bool operator < ( const ObjectID & rhs ) const { return this - > id < rhs . id ; }
bool operator > ( const ObjectID & rhs ) const { return this - > id > rhs . id ; }
bool operator < = ( const ObjectID & rhs ) const { return this - > id < = rhs . id ; }
bool operator > = ( const ObjectID & rhs ) const { return this - > id > = rhs . id ; }
bool valid ( ) const { return id ! = 0 ; }
2019-07-03 11:43:54 +00:00
bool invalid ( ) const { return id = = 0 ; }
2019-06-27 09:02:45 +00:00
size_t id ;
private :
friend class cereal : : access ;
template < class Archive > void serialize ( Archive & ar ) { ar ( id ) ; }
} ;
// Base for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial to provide a unique ID
// to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject).
2020-07-21 13:33:28 +00:00
// Also base for Print, PrintObject, SLAPrint, SLAPrintObject to provide a unique ID for matching Model / ModelObject
// with their corresponding Print / PrintObject objects by the notification center at the UI when processing back-end warnings.
2019-06-27 09:02:45 +00:00
// Achtung! The s_last_id counter is not thread safe, so it is expected, that the ObjectBase derived instances
// are only instantiated from the main thread.
class ObjectBase
{
public :
2020-09-24 13:34:13 +00:00
using Timestamp = uint64_t ;
2020-09-23 10:18:39 +00:00
ObjectID id ( ) const { return m_id ; }
// Return an optional timestamp of this object.
// If the timestamp returned is non-zero, then the serialization framework will
// only save this object on the Undo/Redo stack if the timestamp is different
// from the timestmap of the object at the top of the Undo / Redo stack.
2020-09-24 13:34:13 +00:00
virtual Timestamp timestamp ( ) const { return 0 ; }
2019-06-27 09:02:45 +00:00
protected :
// Constructors to be only called by derived classes.
// Default constructor to assign a unique ID.
ObjectBase ( ) : m_id ( generate_new_id ( ) ) { }
// Constructor with ignored int parameter to assign an invalid ID, to be replaced
// by an existing ID copied from elsewhere.
ObjectBase ( int ) : m_id ( ObjectID ( 0 ) ) { }
// The class tree will have virtual tables and type information.
2020-09-23 10:18:39 +00:00
virtual ~ ObjectBase ( ) = default ;
2019-06-27 09:02:45 +00:00
// Use with caution!
void set_new_unique_id ( ) { m_id = generate_new_id ( ) ; }
void set_invalid_id ( ) { m_id = 0 ; }
// Use with caution!
void copy_id ( const ObjectBase & rhs ) { m_id = rhs . id ( ) ; }
// Override this method if a ObjectBase derived class owns other ObjectBase derived instances.
2019-07-05 17:06:19 +00:00
virtual void assign_new_unique_ids_recursive ( ) { this - > set_new_unique_id ( ) ; }
2019-06-27 09:02:45 +00:00
private :
ObjectID m_id ;
static inline ObjectID generate_new_id ( ) { return ObjectID ( + + s_last_id ) ; }
static size_t s_last_id ;
friend ObjectID wipe_tower_object_id ( ) ;
friend ObjectID wipe_tower_instance_id ( ) ;
friend class cereal : : access ;
2019-07-04 20:52:33 +00:00
friend class Slic3r : : UndoRedo : : StackImpl ;
2019-06-27 09:02:45 +00:00
template < class Archive > void serialize ( Archive & ar ) { ar ( m_id ) ; }
ObjectBase ( const ObjectID id ) : m_id ( id ) { }
template < class Archive > static void load_and_construct ( Archive & ar , cereal : : construct < ObjectBase > & construct ) { ObjectID id ; ar ( id ) ; construct ( id ) ; }
} ;
2020-09-24 13:34:13 +00:00
class ObjectWithTimestamp : public ObjectBase
{
protected :
// Constructors to be only called by derived classes.
// Default constructor to assign a new timestamp unique to this object's history.
ObjectWithTimestamp ( ) = default ;
// Constructor with ignored int parameter to assign an invalid ID, to be replaced
// by an existing ID copied from elsewhere.
ObjectWithTimestamp ( int ) : ObjectBase ( - 1 ) { }
// The class tree will have virtual tables and type information.
virtual ~ ObjectWithTimestamp ( ) = default ;
// Resetting timestamp to 1 indicates the object is in its initial (cleared) state.
// To be called by the derived class's clear() method.
void reset_timestamp ( ) { m_timestamp = 1 ; }
2020-10-15 15:29:42 +00:00
// The timestamp uniquely identifies content of the derived class' data, therefore it makes sense to copy the timestamp if the content data was copied.
void copy_timestamp ( const ObjectWithTimestamp & rhs ) { m_timestamp = rhs . m_timestamp ; }
2020-09-24 13:34:13 +00:00
public :
// Return an optional timestamp of this object.
// If the timestamp returned is non-zero, then the serialization framework will
// only save this object on the Undo/Redo stack if the timestamp is different
// from the timestmap of the object at the top of the Undo / Redo stack.
Timestamp timestamp ( ) const throw ( ) override { return m_timestamp ; }
bool timestamp_matches ( const ObjectWithTimestamp & rhs ) const throw ( ) { return m_timestamp = = rhs . m_timestamp ; }
bool object_id_and_timestamp_match ( const ObjectWithTimestamp & rhs ) const throw ( ) { return this - > id ( ) = = rhs . id ( ) & & m_timestamp = = rhs . m_timestamp ; }
void touch ( ) { m_timestamp = + + s_last_timestamp ; }
private :
// The first timestamp is non-zero, as zero timestamp means the timestamp is not reliable.
Timestamp m_timestamp { 1 } ;
static Timestamp s_last_timestamp ;
friend class cereal : : access ;
friend class Slic3r : : UndoRedo : : StackImpl ;
template < class Archive > void serialize ( Archive & ar ) { ar ( m_timestamp ) ; }
} ;
2019-07-02 14:42:23 +00:00
// Unique object / instance ID for the wipe tower.
extern ObjectID wipe_tower_object_id ( ) ;
extern ObjectID wipe_tower_instance_id ( ) ;
2019-06-27 09:02:45 +00:00
} // namespace Slic3r
# endif /* slic3r_ObjectID_hpp_ */