WIP Undo / Redo: ModelID / ModelBase renamed to ObjectID / ObjectBase

This commit is contained in:
bubnikv 2019-06-27 11:02:45 +02:00
parent d99e932ee8
commit 27ee68d2f9
15 changed files with 179 additions and 155 deletions

View File

@ -114,6 +114,8 @@ add_library(libslic3r STATIC
MultiPoint.cpp MultiPoint.cpp
MultiPoint.hpp MultiPoint.hpp
MutablePriorityQueue.hpp MutablePriorityQueue.hpp
ObjectID.cpp
ObjectID.hpp
PerimeterGenerator.cpp PerimeterGenerator.cpp
PerimeterGenerator.hpp PerimeterGenerator.hpp
PlaceholderParser.cpp PlaceholderParser.cpp

View File

@ -22,18 +22,16 @@ namespace Slic3r {
unsigned int Model::s_auto_extruder_id = 1; unsigned int Model::s_auto_extruder_id = 1;
size_t ModelBase::s_last_id = 0;
// Unique object / instance ID for the wipe tower. // Unique object / instance ID for the wipe tower.
ModelID wipe_tower_object_id() ObjectID wipe_tower_object_id()
{ {
static ModelBase mine; static ObjectBase mine;
return mine.id(); return mine.id();
} }
ModelID wipe_tower_instance_id() ObjectID wipe_tower_instance_id()
{ {
static ModelBase mine; static ObjectBase mine;
return mine.id(); return mine.id();
} }
@ -221,7 +219,7 @@ bool Model::delete_object(ModelObject* object)
return false; return false;
} }
bool Model::delete_object(ModelID id) bool Model::delete_object(ObjectID id)
{ {
if (id.id != 0) { if (id.id != 0) {
size_t idx = 0; size_t idx = 0;
@ -1865,8 +1863,8 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique. // Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
void check_model_ids_validity(const Model &model) void check_model_ids_validity(const Model &model)
{ {
std::set<ModelID> ids; std::set<ObjectID> ids;
auto check = [&ids](ModelID id) { auto check = [&ids](ObjectID id) {
assert(id.id > 0); assert(id.id > 0);
assert(ids.find(id) == ids.end()); assert(ids.find(id) == ids.end());
ids.insert(id); ids.insert(id);
@ -1912,14 +1910,13 @@ void check_model_ids_equal(const Model &model1, const Model &model2)
} }
#if 0 #if 0
CEREAL_REGISTER_TYPE(Slic3r::ModelBase)
CEREAL_REGISTER_TYPE(Slic3r::ModelObject) CEREAL_REGISTER_TYPE(Slic3r::ModelObject)
CEREAL_REGISTER_TYPE(Slic3r::ModelVolume) CEREAL_REGISTER_TYPE(Slic3r::ModelVolume)
CEREAL_REGISTER_TYPE(Slic3r::ModelInstance) CEREAL_REGISTER_TYPE(Slic3r::ModelInstance)
CEREAL_REGISTER_TYPE(Slic3r::Model) CEREAL_REGISTER_TYPE(Slic3r::Model)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelObject) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelObject)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelVolume) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelVolume)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::ModelInstance) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelInstance)
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ModelBase, Slic3r::Model) CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::Model)
#endif #endif

View File

@ -2,19 +2,20 @@
#define slic3r_Model_hpp_ #define slic3r_Model_hpp_
#include "libslic3r.h" #include "libslic3r.h"
#include "PrintConfig.hpp" #include "Geometry.hpp"
#include "Layer.hpp" #include "Layer.hpp"
#include "ObjectID.hpp"
#include "Point.hpp" #include "Point.hpp"
#include "TriangleMesh.hpp" #include "PrintConfig.hpp"
#include "Slicing.hpp" #include "Slicing.hpp"
#include "SLA/SLACommon.hpp"
#include "TriangleMesh.hpp"
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "Geometry.hpp"
#include <libslic3r/SLA/SLACommon.hpp>
namespace Slic3r { namespace Slic3r {
@ -35,82 +36,11 @@ typedef std::vector<ModelObject*> ModelObjectPtrs;
typedef std::vector<ModelVolume*> ModelVolumePtrs; typedef std::vector<ModelVolume*> ModelVolumePtrs;
typedef std::vector<ModelInstance*> ModelInstancePtrs; typedef std::vector<ModelInstance*> ModelInstancePtrs;
// Unique identifier of a Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial.
// Used to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject)
// 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 ModelID
{
public:
ModelID(size_t id) : id(id) {}
bool operator==(const ModelID &rhs) const { return this->id == rhs.id; }
bool operator!=(const ModelID &rhs) const { return this->id != rhs.id; }
bool operator< (const ModelID &rhs) const { return this->id < rhs.id; }
bool operator> (const ModelID &rhs) const { return this->id > rhs.id; }
bool operator<=(const ModelID &rhs) const { return this->id <= rhs.id; }
bool operator>=(const ModelID &rhs) const { return this->id >= rhs.id; }
bool valid() const { return id != 0; }
size_t id;
private:
ModelID() {}
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(id); }
};
// Unique object / instance ID for the wipe tower. // Unique object / instance ID for the wipe tower.
extern ModelID wipe_tower_object_id(); extern ObjectID wipe_tower_object_id();
extern ModelID wipe_tower_instance_id(); extern ObjectID wipe_tower_instance_id();
// Base for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial to provide a unique ID #define OBJECTBASE_DERIVED_COPY_MOVE_CLONE(TYPE) \
// to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject).
// Achtung! The s_last_id counter is not thread safe, so it is expected, that the ModelBase derived instances
// are only instantiated from the main thread.
class ModelBase
{
public:
ModelID id() const { return m_id; }
protected:
// Constructors to be only called by derived classes.
// Default constructor to assign a unique ID.
ModelBase() : 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.
ModelBase(int) : m_id(ModelID(0)) {}
// The class tree will have virtual tables and type information.
virtual ~ModelBase() {}
// 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 ModelBase &rhs) { m_id = rhs.id(); }
// Override this method if a ModelBase derived class owns other ModelBase derived instances.
void assign_new_unique_ids_recursive() { this->set_new_unique_id(); }
private:
ModelID m_id;
static inline ModelID generate_new_id() { return ModelID(++ s_last_id); }
static size_t s_last_id;
friend ModelID wipe_tower_object_id();
friend ModelID wipe_tower_instance_id();
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(m_id); }
ModelBase(const ModelID id) : m_id(id) {}
template<class Archive> static void load_and_construct(Archive & ar, cereal::construct<ModelBase> &construct) { ModelID id; ar(id); construct(id); }
};
#define MODELBASE_DERIVED_COPY_MOVE_CLONE(TYPE) \
/* Copy a model, copy the IDs. The Print::apply() will call the TYPE::copy() method */ \ /* Copy a model, copy the IDs. The Print::apply() will call the TYPE::copy() method */ \
/* to make a private copy for background processing. */ \ /* to make a private copy for background processing. */ \
static TYPE* new_copy(const TYPE &rhs) { return new TYPE(rhs); } \ static TYPE* new_copy(const TYPE &rhs) { return new TYPE(rhs); } \
@ -138,14 +68,14 @@ private:
return *this; \ return *this; \
} }
#define MODELBASE_DERIVED_PRIVATE_COPY_MOVE(TYPE) \ #define OBJECTBASE_DERIVED_PRIVATE_COPY_MOVE(TYPE) \
private: \ private: \
/* Private constructor with an unused int parameter will create a TYPE instance with an invalid ID. */ \ /* Private constructor with an unused int parameter will create a TYPE instance with an invalid ID. */ \
explicit TYPE(int) : ModelBase(-1) {}; \ explicit TYPE(int) : ObjectBase(-1) {}; \
void assign_new_unique_ids_recursive(); void assign_new_unique_ids_recursive();
// Material, which may be shared across multiple ModelObjects of a single Model. // Material, which may be shared across multiple ModelObjects of a single Model.
class ModelMaterial : public ModelBase class ModelMaterial : public ObjectBase
{ {
public: public:
// Attributes are defined by the AMF file format, but they don't seem to be used by Slic3r for any purpose. // Attributes are defined by the AMF file format, but they don't seem to be used by Slic3r for any purpose.
@ -175,14 +105,14 @@ private:
friend class cereal::access; friend class cereal::access;
ModelMaterial() : m_model(nullptr) {} ModelMaterial() : m_model(nullptr) {}
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ModelBase>(this)); ar(attributes, config); } template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ObjectBase>(this)); ar(attributes, config); }
}; };
// A printable object, possibly having multiple print volumes (each with its own set of parameters and materials), // A printable object, possibly having multiple print volumes (each with its own set of parameters and materials),
// and possibly having multiple modifier volumes, each modifier volume with its set of parameters and materials. // and possibly having multiple modifier volumes, each modifier volume with its set of parameters and materials.
// Each ModelObject may be instantiated mutliple times, each instance having different placement on the print bed, // Each ModelObject may be instantiated mutliple times, each instance having different placement on the print bed,
// different rotation and different uniform scaling. // different rotation and different uniform scaling.
class ModelObject : public ModelBase class ModelObject : public ObjectBase
{ {
friend class Model; friend class Model;
public: public:
@ -323,13 +253,13 @@ private:
/* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */
/* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */ /* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */
ModelObject(const ModelObject &rhs) : ModelBase(-1), m_model(rhs.m_model) { this->assign_copy(rhs); } ModelObject(const ModelObject &rhs) : ObjectBase(-1), m_model(rhs.m_model) { this->assign_copy(rhs); }
explicit ModelObject(ModelObject &&rhs) : ModelBase(-1) { this->assign_copy(std::move(rhs)); } explicit ModelObject(ModelObject &&rhs) : ObjectBase(-1) { this->assign_copy(std::move(rhs)); }
ModelObject& operator=(const ModelObject &rhs) { this->assign_copy(rhs); m_model = rhs.m_model; return *this; } ModelObject& operator=(const ModelObject &rhs) { this->assign_copy(rhs); m_model = rhs.m_model; return *this; }
ModelObject& operator=(ModelObject &&rhs) { this->assign_copy(std::move(rhs)); m_model = rhs.m_model; return *this; } ModelObject& operator=(ModelObject &&rhs) { this->assign_copy(std::move(rhs)); m_model = rhs.m_model; return *this; }
MODELBASE_DERIVED_COPY_MOVE_CLONE(ModelObject) OBJECTBASE_DERIVED_COPY_MOVE_CLONE(ModelObject)
MODELBASE_DERIVED_PRIVATE_COPY_MOVE(ModelObject) OBJECTBASE_DERIVED_PRIVATE_COPY_MOVE(ModelObject)
// Parent object, owning this ModelObject. Set to nullptr here, so the macros above will have it initialized. // Parent object, owning this ModelObject. Set to nullptr here, so the macros above will have it initialized.
Model *m_model = nullptr; Model *m_model = nullptr;
@ -345,7 +275,7 @@ private:
friend class cereal::access; friend class cereal::access;
ModelObject() : m_model(nullptr), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} ModelObject() : m_model(nullptr), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {}
template<class Archive> void serialize(Archive &ar) { template<class Archive> void serialize(Archive &ar) {
ar(cereal::base_class<ModelBase>(this)); ar(cereal::base_class<ObjectBase>(this));
ar(name, input_file, instances, volumes, config, layer_height_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation, ar(name, input_file, instances, volumes, config, layer_height_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid); m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
} }
@ -362,7 +292,7 @@ enum class ModelVolumeType : int {
// An object STL, or a modifier volume, over which a different set of parameters shall be applied. // An object STL, or a modifier volume, over which a different set of parameters shall be applied.
// ModelVolume instances are owned by a ModelObject. // ModelVolume instances are owned by a ModelObject.
class ModelVolume : public ModelBase class ModelVolume : public ObjectBase
{ {
public: public:
std::string name; std::string name;
@ -456,7 +386,7 @@ public:
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
using ModelBase::set_new_unique_id; using ObjectBase::set_new_unique_id;
protected: protected:
friend class Print; friend class Print;
@ -496,7 +426,7 @@ private:
// Copying an existing volume, therefore this volume will get a copy of the ID assigned. // Copying an existing volume, therefore this volume will get a copy of the ID assigned.
ModelVolume(ModelObject *object, const ModelVolume &other) : ModelVolume(ModelObject *object, const ModelVolume &other) :
ModelBase(other), // copy the ID ObjectBase(other), // copy the ID
name(other.name), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation) name(other.name), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
{ {
this->set_material_id(other.material_id()); this->set_material_id(other.material_id());
@ -515,14 +445,14 @@ private:
friend class cereal::access; friend class cereal::access;
ModelVolume() : object(nullptr) {} ModelVolume() : object(nullptr) {}
template<class Archive> void serialize(Archive &ar) { template<class Archive> void serialize(Archive &ar) {
ar(cereal::base_class<ModelBase>(this)); ar(cereal::base_class<ObjectBase>(this));
ar(name, config, m_mesh, m_type, m_material_id, m_convex_hull, m_transformation, m_is_splittable); ar(name, config, m_mesh, m_type, m_material_id, m_convex_hull, m_transformation, m_is_splittable);
} }
}; };
// A single instance of a ModelObject. // A single instance of a ModelObject.
// Knows the affine transformation of an object. // Knows the affine transformation of an object.
class ModelInstance : public ModelBase class ModelInstance : public ObjectBase
{ {
public: public:
enum EPrintVolumeState : unsigned char enum EPrintVolumeState : unsigned char
@ -610,7 +540,7 @@ private:
friend class cereal::access; friend class cereal::access;
ModelInstance() : object(nullptr) {} ModelInstance() : object(nullptr) {}
template<class Archive> void serialize(Archive &ar) { template<class Archive> void serialize(Archive &ar) {
ar(cereal::base_class<ModelBase>(this)); ar(cereal::base_class<ObjectBase>(this));
ar(m_transformation, print_volume_state); ar(m_transformation, print_volume_state);
} }
}; };
@ -620,7 +550,7 @@ private:
// and with multiple modifier meshes. // and with multiple modifier meshes.
// A model groups multiple objects, each object having possibly multiple instances, // A model groups multiple objects, each object having possibly multiple instances,
// all objects may share mutliple materials. // all objects may share mutliple materials.
class Model : public ModelBase class Model : public ObjectBase
{ {
static unsigned int s_auto_extruder_id; static unsigned int s_auto_extruder_id;
@ -637,12 +567,12 @@ public:
/* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */
/* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */ /* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */
Model(const Model &rhs) : ModelBase(-1) { this->assign_copy(rhs); } Model(const Model &rhs) : ObjectBase(-1) { this->assign_copy(rhs); }
explicit Model(Model &&rhs) : ModelBase(-1) { this->assign_copy(std::move(rhs)); } explicit Model(Model &&rhs) : ObjectBase(-1) { this->assign_copy(std::move(rhs)); }
Model& operator=(const Model &rhs) { this->assign_copy(rhs); return *this; } Model& operator=(const Model &rhs) { this->assign_copy(rhs); return *this; }
Model& operator=(Model &&rhs) { this->assign_copy(std::move(rhs)); return *this; } Model& operator=(Model &&rhs) { this->assign_copy(std::move(rhs)); return *this; }
MODELBASE_DERIVED_COPY_MOVE_CLONE(Model) OBJECTBASE_DERIVED_COPY_MOVE_CLONE(Model)
static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config = nullptr, bool add_default_instances = true); static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config = nullptr, bool add_default_instances = true);
static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances = true); static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances = true);
@ -653,7 +583,7 @@ public:
ModelObject* add_object(const char *name, const char *path, TriangleMesh &&mesh); ModelObject* add_object(const char *name, const char *path, TriangleMesh &&mesh);
ModelObject* add_object(const ModelObject &other); ModelObject* add_object(const ModelObject &other);
void delete_object(size_t idx); void delete_object(size_t idx);
bool delete_object(ModelID id); bool delete_object(ObjectID id);
bool delete_object(ModelObject* object); bool delete_object(ModelObject* object);
void clear_objects(); void clear_objects();
@ -700,16 +630,16 @@ public:
std::string propose_export_file_name_and_path(const std::string &new_extension) const; std::string propose_export_file_name_and_path(const std::string &new_extension) const;
private: private:
MODELBASE_DERIVED_PRIVATE_COPY_MOVE(Model) OBJECTBASE_DERIVED_PRIVATE_COPY_MOVE(Model)
friend class cereal::access; friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { template<class Archive> void serialize(Archive &ar) {
ar(cereal::base_class<ModelBase>(this), materials, objects); ar(cereal::base_class<ObjectBase>(this), materials, objects);
} }
}; };
#undef MODELBASE_DERIVED_COPY_MOVE_CLONE #undef OBJECTBASE_DERIVED_COPY_MOVE_CLONE
#undef MODELBASE_DERIVED_PRIVATE_COPY_MOVE #undef OBJECTBASE_DERIVED_PRIVATE_COPY_MOVE
// Test whether the two models contain the same number of ModelObjects with the same set of IDs // Test whether the two models contain the same number of ModelObjects with the same set of IDs
// ordered in the same order. In that case it is not necessary to kill the background processing. // ordered in the same order. In that case it is not necessary to kill the background processing.
@ -729,6 +659,6 @@ void check_model_ids_validity(const Model &model);
void check_model_ids_equal(const Model &model1, const Model &model2); void check_model_ids_equal(const Model &model1, const Model &model2);
#endif /* NDEBUG */ #endif /* NDEBUG */
} } // namespace Slic3r
#endif #endif /* slic3r_Model_hpp_ */

View File

@ -0,0 +1,9 @@
#include "ObjectID.hpp"
namespace Slic3r {
size_t ObjectBase::s_last_id = 0;
} // namespace Slic3r
// CEREAL_REGISTER_TYPE(Slic3r::ObjectBase)

View File

@ -0,0 +1,87 @@
#ifndef slic3r_ObjectID_hpp_
#define slic3r_ObjectID_hpp_
#include <cereal/types/polymorphic.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/archives/binary.hpp>
namespace Slic3r {
// 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) {}
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; }
size_t id;
private:
ObjectID() {}
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).
// 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:
ObjectID id() const { return m_id; }
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.
virtual ~ObjectBase() {}
// 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.
void assign_new_unique_ids_recursive() { this->set_new_unique_id(); }
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;
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); }
};
} // namespace Slic3r
#endif /* slic3r_ObjectID_hpp_ */

View File

@ -732,8 +732,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
Moved, Moved,
Deleted, Deleted,
}; };
ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {} ModelObjectStatus(ObjectID id, Status status = Unknown) : id(id), status(status) {}
ModelID id; ObjectID id;
Status status; Status status;
// Search by id. // Search by id.
bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; } bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; }
@ -839,9 +839,9 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
print_object(print_object), print_object(print_object),
trafo(print_object->trafo()), trafo(print_object->trafo()),
status(status) {} status(status) {}
PrintObjectStatus(ModelID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {} PrintObjectStatus(ObjectID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {}
// ID of the ModelObject & PrintObject // ID of the ModelObject & PrintObject
ModelID id; ObjectID id;
// Pointer to the old PrintObject // Pointer to the old PrintObject
PrintObject *print_object; PrintObject *print_object;
// Trafo generated with model_object->world_matrix(true) // Trafo generated with model_object->world_matrix(true)

View File

@ -246,7 +246,7 @@ public:
struct TaskParams { struct TaskParams {
TaskParams() : single_model_object(0), single_model_instance_only(false), to_object_step(-1), to_print_step(-1) {} 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. // If non-empty, limit the processing to this ModelObject.
ModelID single_model_object; ObjectID single_model_object;
// If set, only process single_model_object. Otherwise process everything, but single_model_object first. // If set, only process single_model_object. Otherwise process everything, but single_model_object first.
bool single_model_instance_only; bool single_model_instance_only;
// If non-negative, stop processing at the successive object step. // If non-negative, stop processing at the successive object step.

View File

@ -212,8 +212,8 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
Moved, Moved,
Deleted, Deleted,
}; };
ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {} ModelObjectStatus(ObjectID id, Status status = Unknown) : id(id), status(status) {}
ModelID id; ObjectID id;
Status status; Status status;
// Search by id. // Search by id.
bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; } bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; }
@ -316,9 +316,9 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
print_object(print_object), print_object(print_object),
trafo(print_object->trafo()), trafo(print_object->trafo()),
status(status) {} status(status) {}
PrintObjectStatus(ModelID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {} PrintObjectStatus(ObjectID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {}
// ID of the ModelObject & PrintObject // ID of the ModelObject & PrintObject
ModelID id; ObjectID id;
// Pointer to the old PrintObject // Pointer to the old PrintObject
SLAPrintObject *print_object; SLAPrintObject *print_object;
// Trafo generated with model_object->world_matrix(true) // Trafo generated with model_object->world_matrix(true)

View File

@ -54,10 +54,10 @@ public:
bool is_left_handed() const { return m_left_handed; } bool is_left_handed() const { return m_left_handed; }
struct Instance { struct Instance {
Instance(ModelID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {} Instance(ObjectID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {}
bool operator==(const Instance &rhs) const { return this->instance_id == rhs.instance_id && this->shift == rhs.shift && this->rotation == rhs.rotation; } bool operator==(const Instance &rhs) const { return this->instance_id == rhs.instance_id && this->shift == rhs.shift && this->rotation == rhs.rotation; }
// ID of the corresponding ModelInstance. // ID of the corresponding ModelInstance.
ModelID instance_id; ObjectID instance_id;
// Slic3r::Point objects in scaled G-code coordinates // Slic3r::Point objects in scaled G-code coordinates
Point shift; Point shift;
// Rotation along the Z axis, in radians. // Rotation along the Z axis, in radians.

View File

@ -1812,14 +1812,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
struct ModelVolumeState { struct ModelVolumeState {
ModelVolumeState(const GLVolume *volume) : ModelVolumeState(const GLVolume *volume) :
model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {} model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
ModelVolumeState(const ModelVolume *model_volume, const ModelID &instance_id, const GLVolume::CompositeID &composite_id) : ModelVolumeState(const ModelVolume *model_volume, const ObjectID &instance_id, const GLVolume::CompositeID &composite_id) :
model_volume(model_volume), geometry_id(std::make_pair(model_volume->id().id, instance_id.id)), composite_id(composite_id), volume_idx(-1) {} model_volume(model_volume), geometry_id(std::make_pair(model_volume->id().id, instance_id.id)), composite_id(composite_id), volume_idx(-1) {}
ModelVolumeState(const ModelID &volume_id, const ModelID &instance_id) : ModelVolumeState(const ObjectID &volume_id, const ObjectID &instance_id) :
model_volume(nullptr), geometry_id(std::make_pair(volume_id.id, instance_id.id)), volume_idx(-1) {} model_volume(nullptr), geometry_id(std::make_pair(volume_id.id, instance_id.id)), volume_idx(-1) {}
bool new_geometry() const { return this->volume_idx == size_t(-1); } bool new_geometry() const { return this->volume_idx == size_t(-1); }
const ModelVolume *model_volume; const ModelVolume *model_volume;
// ModelID of ModelVolume + ModelID of ModelInstance // ObjectID of ModelVolume + ObjectID of ModelInstance
// or timestamp of an SLAPrintObjectStep + ModelID of ModelInstance // or timestamp of an SLAPrintObjectStep + ObjectID of ModelInstance
std::pair<size_t, size_t> geometry_id; std::pair<size_t, size_t> geometry_id;
GLVolume::CompositeID composite_id; GLVolume::CompositeID composite_id;
// Volume index in the new GLVolume vector. // Volume index in the new GLVolume vector.

View File

@ -380,7 +380,7 @@ bool GLGizmoSlaSupports::is_point_clipped(const Vec3d& point) const
bool GLGizmoSlaSupports::is_mesh_update_necessary() const bool GLGizmoSlaSupports::is_mesh_update_necessary() const
{ {
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty()) return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
&& ((m_model_object->id() != m_current_mesh_model_id) || m_its == nullptr); && ((m_model_object->id() != m_current_mesh_object_id) || m_its == nullptr);
} }
void GLGizmoSlaSupports::update_mesh() void GLGizmoSlaSupports::update_mesh()
@ -390,7 +390,7 @@ void GLGizmoSlaSupports::update_mesh()
// This mesh does not account for the possible Z up SLA offset. // This mesh does not account for the possible Z up SLA offset.
m_mesh = &m_model_object->volumes.front()->mesh(); m_mesh = &m_model_object->volumes.front()->mesh();
m_its = &m_mesh->its; m_its = &m_mesh->its;
m_current_mesh_model_id = m_model_object->id(); m_current_mesh_object_id = m_model_object->id();
m_editing_mode = false; m_editing_mode = false;
m_AABB.deinit(); m_AABB.deinit();

View File

@ -26,7 +26,7 @@ class GLGizmoSlaSupports : public GLGizmoBase
{ {
private: private:
ModelObject* m_model_object = nullptr; ModelObject* m_model_object = nullptr;
ModelID m_current_mesh_model_id = 0; ObjectID m_current_mesh_object_id = 0;
int m_active_instance = -1; int m_active_instance = -1;
float m_active_instance_bb_radius; // to cache the bb float m_active_instance_bb_radius; // to cache the bb
mutable float m_z_shift = 0.f; mutable float m_z_shift = 0.f;

View File

@ -171,7 +171,7 @@ private:
Vec3d dragging_center; Vec3d dragging_center;
// Map from indices of ModelObject instances in Model::objects // Map from indices of ModelObject instances in Model::objects
// to a set of indices of ModelVolume instances in ModelObject::instances // to a set of indices of ModelVolume instances in ModelObject::instances
// Here the index means a position inside the respective std::vector, not ModelID. // Here the index means a position inside the respective std::vector, not ObjectID.
ObjectIdxsToInstanceIdxsMap content; ObjectIdxsToInstanceIdxsMap content;
}; };

View File

@ -9,19 +9,19 @@ use Test::More tests => 147;
foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintConfig) { foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintConfig) {
$config->set('layer_height', 0.3); $config->set('layer_height', 0.3);
ok abs($config->get('layer_height') - 0.3) < 1e-4, 'set/get float'; ok abs($config->get('layer_height') - 0.3) < 1e-4, 'set/get float';
is $config->serialize('layer_height'), '0.3', 'serialize float'; is $config->opt_serialize('layer_height'), '0.3', 'serialize float';
$config->set('perimeters', 2); $config->set('perimeters', 2);
is $config->get('perimeters'), 2, 'set/get int'; is $config->get('perimeters'), 2, 'set/get int';
is $config->serialize('perimeters'), '2', 'serialize int'; is $config->opt_serialize('perimeters'), '2', 'serialize int';
$config->set('extrusion_axis', 'A'); $config->set('extrusion_axis', 'A');
is $config->get('extrusion_axis'), 'A', 'set/get string'; is $config->get('extrusion_axis'), 'A', 'set/get string';
is $config->serialize('extrusion_axis'), 'A', 'serialize string'; is $config->opt_serialize('extrusion_axis'), 'A', 'serialize string';
$config->set('notes', "foo\nbar"); $config->set('notes', "foo\nbar");
is $config->get('notes'), "foo\nbar", 'set/get string with newline'; is $config->get('notes'), "foo\nbar", 'set/get string with newline';
is $config->serialize('notes'), 'foo\nbar', 'serialize string with newline'; is $config->opt_serialize('notes'), 'foo\nbar', 'serialize string with newline';
$config->set_deserialize('notes', 'bar\nbaz'); $config->set_deserialize('notes', 'bar\nbaz');
is $config->get('notes'), "bar\nbaz", 'deserialize string with newline'; is $config->get('notes'), "bar\nbaz", 'deserialize string with newline';
@ -59,7 +59,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
) )
{ {
$config->set('filament_notes', $test_data->{values}); $config->set('filament_notes', $test_data->{values});
is $config->serialize('filament_notes'), $test_data->{serialized}, 'serialize multi-string value ' . $test_data->{name}; is $config->opt_serialize('filament_notes'), $test_data->{serialized}, 'serialize multi-string value ' . $test_data->{name};
$config->set_deserialize('filament_notes', ''); $config->set_deserialize('filament_notes', '');
is_deeply $config->get('filament_notes'), [], 'deserialize multi-string value - empty ' . $test_data->{name}; is_deeply $config->get('filament_notes'), [], 'deserialize multi-string value - empty ' . $test_data->{name};
$config->set_deserialize('filament_notes', $test_data->{serialized}); $config->set_deserialize('filament_notes', $test_data->{serialized});
@ -68,12 +68,12 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
$config->set('first_layer_height', 0.3); $config->set('first_layer_height', 0.3);
ok abs($config->get('first_layer_height') - 0.3) < 1e-4, 'set/get absolute floatOrPercent'; ok abs($config->get('first_layer_height') - 0.3) < 1e-4, 'set/get absolute floatOrPercent';
is $config->serialize('first_layer_height'), '0.3', 'serialize absolute floatOrPercent'; is $config->opt_serialize('first_layer_height'), '0.3', 'serialize absolute floatOrPercent';
$config->set('first_layer_height', '50%'); $config->set('first_layer_height', '50%');
$config->get_abs_value('first_layer_height'); $config->get_abs_value('first_layer_height');
ok abs($config->get_abs_value('first_layer_height') - 0.15) < 1e-4, 'set/get relative floatOrPercent'; ok abs($config->get_abs_value('first_layer_height') - 0.15) < 1e-4, 'set/get relative floatOrPercent';
is $config->serialize('first_layer_height'), '50%', 'serialize relative floatOrPercent'; is $config->opt_serialize('first_layer_height'), '50%', 'serialize relative floatOrPercent';
# Uh-oh, we have no point option to test at the moment # Uh-oh, we have no point option to test at the moment
#ok $config->set('print_center', [50,80]), 'valid point coordinates'; #ok $config->set('print_center', [50,80]), 'valid point coordinates';
@ -86,11 +86,10 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
$config->set('use_relative_e_distances', 1); $config->set('use_relative_e_distances', 1);
is $config->get('use_relative_e_distances'), 1, 'set/get bool'; is $config->get('use_relative_e_distances'), 1, 'set/get bool';
is $config->serialize('use_relative_e_distances'), '1', 'serialize bool'; is $config->opt_serialize('use_relative_e_distances'), '1', 'serialize bool';
$config->set('gcode_flavor', 'teacup'); $config->set('gcode_flavor', 'teacup');
is $config->get('gcode_flavor'), 'teacup', 'set/get enum'; is $config->get('gcode_flavor'), 'teacup', 'set/get enum';
is $config->serialize('gcode_flavor'), 'teacup', 'serialize enum'; is $config->opt_serialize('gcode_flavor'), 'teacup', 'serialize enum';
$config->set_deserialize('gcode_flavor', 'mach3'); $config->set_deserialize('gcode_flavor', 'mach3');
is $config->get('gcode_flavor'), 'mach3', 'deserialize enum (gcode_flavor)'; is $config->get('gcode_flavor'), 'mach3', 'deserialize enum (gcode_flavor)';
$config->set_deserialize('gcode_flavor', 'machinekit'); $config->set_deserialize('gcode_flavor', 'machinekit');
@ -106,7 +105,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points'; is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
$config->set('extruder_offset', [Slic3r::Pointf->new(10,20),Slic3r::Pointf->new(30,45)]); $config->set('extruder_offset', [Slic3r::Pointf->new(10,20),Slic3r::Pointf->new(30,45)]);
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points'; is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
is $config->serialize('extruder_offset'), '10x20,30x45', 'serialize points'; is $config->opt_serialize('extruder_offset'), '10x20,30x45', 'serialize points';
$config->set_deserialize('extruder_offset', '20x10'); $config->set_deserialize('extruder_offset', '20x10');
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[20,10]], 'deserialize points'; is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[20,10]], 'deserialize points';
$config->set_deserialize('extruder_offset', '0x0'); $config->set_deserialize('extruder_offset', '0x0');
@ -120,7 +119,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
# truncate ->get() to first decimal digit # truncate ->get() to first decimal digit
$config->set('nozzle_diameter', [0.2,3]); $config->set('nozzle_diameter', [0.2,3]);
is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.2,3], 'set/get floats'; is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.2,3], 'set/get floats';
is $config->serialize('nozzle_diameter'), '0.2,3', 'serialize floats'; is $config->opt_serialize('nozzle_diameter'), '0.2,3', 'serialize floats';
$config->set_deserialize('nozzle_diameter', '0.1,0.4'); $config->set_deserialize('nozzle_diameter', '0.1,0.4');
is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.1,0.4], 'deserialize floats'; is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.1,0.4], 'deserialize floats';
$config->set_deserialize('nozzle_diameter', '3'); $config->set_deserialize('nozzle_diameter', '3');
@ -133,7 +132,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
$config->set('temperature', [180,210]); $config->set('temperature', [180,210]);
is_deeply $config->get('temperature'), [180,210], 'set/get ints'; is_deeply $config->get('temperature'), [180,210], 'set/get ints';
is $config->serialize('temperature'), '180,210', 'serialize ints'; is $config->opt_serialize('temperature'), '180,210', 'serialize ints';
$config->set_deserialize('temperature', '195,220'); $config->set_deserialize('temperature', '195,220');
is_deeply $config->get('temperature'), [195,220], 'deserialize ints'; is_deeply $config->get('temperature'), [195,220], 'deserialize ints';
{ {
@ -147,7 +146,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
is $config->get_at('wipe', 0), 1, 'get_at bools'; is $config->get_at('wipe', 0), 1, 'get_at bools';
is $config->get_at('wipe', 1), 0, 'get_at bools'; is $config->get_at('wipe', 1), 0, 'get_at bools';
is $config->get_at('wipe', 9), 1, 'get_at bools'; is $config->get_at('wipe', 9), 1, 'get_at bools';
is $config->serialize('wipe'), '1,0', 'serialize bools'; is $config->opt_serialize('wipe'), '1,0', 'serialize bools';
$config->set_deserialize('wipe', '0,1,1'); $config->set_deserialize('wipe', '0,1,1');
is_deeply $config->get('wipe'), [0,1,1], 'deserialize bools'; is_deeply $config->get('wipe'), [0,1,1], 'deserialize bools';
$config->set_deserialize('wipe', ''); $config->set_deserialize('wipe', '');
@ -162,7 +161,7 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintCo
$config->set('post_process', ['foo','bar']); $config->set('post_process', ['foo','bar']);
is_deeply $config->get('post_process'), ['foo','bar'], 'set/get strings'; is_deeply $config->get('post_process'), ['foo','bar'], 'set/get strings';
is $config->serialize('post_process'), 'foo;bar', 'serialize strings'; is $config->opt_serialize('post_process'), 'foo;bar', 'serialize strings';
$config->set_deserialize('post_process', 'bar;baz'); $config->set_deserialize('post_process', 'bar;baz');
is_deeply $config->get('post_process'), ['bar','baz'], 'deserialize strings'; is_deeply $config->get('post_process'), ['bar','baz'], 'deserialize strings';
{ {

View File

@ -33,7 +33,7 @@
%code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %}; %code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %};
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false) void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false)
%code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %}; %code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %};
std::string serialize(t_config_option_key opt_key); std::string opt_serialize(t_config_option_key opt_key);
double get_abs_value(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key);
%name{get_abs_value_over} %name{get_abs_value_over}
double get_abs_value(t_config_option_key opt_key, double ratio_over); double get_abs_value(t_config_option_key opt_key, double ratio_over);
@ -95,7 +95,7 @@
%code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %}; %code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %};
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false) void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false)
%code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %}; %code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %};
std::string serialize(t_config_option_key opt_key); std::string opt_serialize(t_config_option_key opt_key);
double get_abs_value(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key);
%name{get_abs_value_over} %name{get_abs_value_over}
double get_abs_value(t_config_option_key opt_key, double ratio_over); double get_abs_value(t_config_option_key opt_key, double ratio_over);