Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
91d574f8ad
@ -169,6 +169,9 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2
|
|||||||
|
|
||||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
||||||
{
|
{
|
||||||
|
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||||
|
throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||||
|
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
|
|
||||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
||||||
@ -182,8 +185,11 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||||||
end_pos = Eigen::Rotation2Df(alpha) * end_pos;
|
end_pos = Eigen::Rotation2Df(alpha) * end_pos;
|
||||||
end_pos += m_wipe_tower_pos;
|
end_pos += m_wipe_tower_pos;
|
||||||
}
|
}
|
||||||
std::string tcr_rotated_gcode = tcr.priming ? tcr.gcode : rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
|
|
||||||
|
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||||
|
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||||
|
|
||||||
|
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||||
|
|
||||||
// Disable linear advance for the wipe tower operations.
|
// Disable linear advance for the wipe tower operations.
|
||||||
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
||||||
@ -285,17 +291,21 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||||||
|
|
||||||
// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
|
// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
|
||||||
// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
|
// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
|
||||||
std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const
|
std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const
|
||||||
{
|
{
|
||||||
std::istringstream gcode_str(gcode_original);
|
Vec2f extruder_offset = m_extruder_offsets[tcr.initial_tool].cast<float>();
|
||||||
|
|
||||||
|
std::istringstream gcode_str(tcr.gcode);
|
||||||
std::string gcode_out;
|
std::string gcode_out;
|
||||||
std::string line;
|
std::string line;
|
||||||
Vec2f pos = start_pos;
|
Vec2f pos = tcr.start_pos;
|
||||||
Vec2f transformed_pos;
|
Vec2f transformed_pos = pos;
|
||||||
Vec2f old_pos(-1000.1f, -1000.1f);
|
Vec2f old_pos(-1000.1f, -1000.1f);
|
||||||
|
|
||||||
while (gcode_str) {
|
while (gcode_str) {
|
||||||
std::getline(gcode_str, line); // we read the gcode line by line
|
std::getline(gcode_str, line); // we read the gcode line by line
|
||||||
|
|
||||||
|
// All G1 commands should be translated and rotated
|
||||||
if (line.find("G1 ") == 0) {
|
if (line.find("G1 ") == 0) {
|
||||||
std::ostringstream line_out;
|
std::ostringstream line_out;
|
||||||
std::istringstream line_str(line);
|
std::istringstream line_str(line);
|
||||||
@ -317,17 +327,34 @@ std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gco
|
|||||||
|
|
||||||
if (transformed_pos != old_pos) {
|
if (transformed_pos != old_pos) {
|
||||||
line = line_out.str();
|
line = line_out.str();
|
||||||
char buf[2048] = "G1";
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed << std::setprecision(3) << "G1 ";
|
||||||
if (transformed_pos.x() != old_pos.x())
|
if (transformed_pos.x() != old_pos.x())
|
||||||
sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x());
|
oss << " X" << transformed_pos.x() - extruder_offset.x();
|
||||||
if (transformed_pos.y() != old_pos.y())
|
if (transformed_pos.y() != old_pos.y())
|
||||||
sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y());
|
oss << " Y" << transformed_pos.y() - extruder_offset.y();
|
||||||
|
|
||||||
line.replace(line.find("G1 "), 3, buf);
|
line.replace(line.find("G1 "), 3, oss.str());
|
||||||
old_pos = transformed_pos;
|
old_pos = transformed_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gcode_out += line + "\n";
|
gcode_out += line + "\n";
|
||||||
|
|
||||||
|
// If this was a toolchange command, we should change current extruder offset
|
||||||
|
if (line == "[toolchange_gcode]") {
|
||||||
|
extruder_offset = m_extruder_offsets[tcr.new_tool].cast<float>();
|
||||||
|
|
||||||
|
// If the extruder offset changed, add an extra move so everything is continuous
|
||||||
|
if (extruder_offset != m_extruder_offsets[tcr.initial_tool].cast<float>()) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed << std::setprecision(3)
|
||||||
|
<< "G1 X" << transformed_pos.x() - extruder_offset.x()
|
||||||
|
<< " Y" << transformed_pos.y() - extruder_offset.y()
|
||||||
|
<< "\n";
|
||||||
|
gcode_out += oss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return gcode_out;
|
return gcode_out;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
|
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
|
||||||
m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
|
m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
|
||||||
m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
|
m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
|
||||||
|
m_extruder_offsets(print_config.extruder_offset.values),
|
||||||
m_priming(priming),
|
m_priming(priming),
|
||||||
m_tool_changes(tool_changes),
|
m_tool_changes(tool_changes),
|
||||||
m_final_purge(final_purge),
|
m_final_purge(final_purge),
|
||||||
@ -107,14 +108,16 @@ private:
|
|||||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
||||||
|
|
||||||
// Postprocesses gcode: rotates and moves all G1 extrusions and returns result
|
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||||
std::string rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const;
|
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||||
|
|
||||||
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
||||||
const float m_left;
|
const float m_left;
|
||||||
const float m_right;
|
const float m_right;
|
||||||
const Vec2f m_wipe_tower_pos;
|
const Vec2f m_wipe_tower_pos;
|
||||||
const float m_wipe_tower_rotation;
|
const float m_wipe_tower_rotation;
|
||||||
|
const std::vector<Vec2d> m_extruder_offsets;
|
||||||
|
|
||||||
// Reference to cached values at the Printer class.
|
// Reference to cached values at the Printer class.
|
||||||
const std::vector<WipeTower::ToolChangeResult> &m_priming;
|
const std::vector<WipeTower::ToolChangeResult> &m_priming;
|
||||||
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
|
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
|
||||||
|
@ -553,7 +553,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
|||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
result.start_pos = writer.start_pos_rotated();
|
result.start_pos = writer.start_pos_rotated();
|
||||||
result.end_pos = writer.pos_rotated();
|
result.end_pos = writer.pos();
|
||||||
|
|
||||||
results.push_back(std::move(result));
|
results.push_back(std::move(result));
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
|||||||
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
|
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
|
||||||
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
||||||
toolchange_Load(writer, cleaning_box);
|
toolchange_Load(writer, cleaning_box);
|
||||||
writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
writer.travel(writer.x(), writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
||||||
toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
||||||
++ m_num_tool_changes;
|
++ m_num_tool_changes;
|
||||||
} else
|
} else
|
||||||
|
@ -139,13 +139,15 @@ public:
|
|||||||
|
|
||||||
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||||
|
|
||||||
std::stringstream stream{m_semm ? ramming_parameters : std::string()};
|
if (m_semm) {
|
||||||
float speed = 0.f;
|
std::stringstream stream{ramming_parameters};
|
||||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
float speed = 0.f;
|
||||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||||
while (stream >> speed)
|
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||||
m_filpar[idx].ramming_speed.push_back(speed);
|
while (stream >> speed)
|
||||||
|
m_filpar[idx].ramming_speed.push_back(speed);
|
||||||
|
}
|
||||||
|
|
||||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||||
}
|
}
|
||||||
@ -241,8 +243,8 @@ public:
|
|||||||
int cooling_moves = 0;
|
int cooling_moves = 0;
|
||||||
float cooling_initial_speed = 0.f;
|
float cooling_initial_speed = 0.f;
|
||||||
float cooling_final_speed = 0.f;
|
float cooling_final_speed = 0.f;
|
||||||
float ramming_line_width_multiplicator = 0.f;
|
float ramming_line_width_multiplicator = 1.f;
|
||||||
float ramming_step_multiplicator = 0.f;
|
float ramming_step_multiplicator = 1.f;
|
||||||
float max_e_speed = std::numeric_limits<float>::max();
|
float max_e_speed = std::numeric_limits<float>::max();
|
||||||
std::vector<float> ramming_speed;
|
std::vector<float> ramming_speed;
|
||||||
float nozzle_diameter;
|
float nozzle_diameter;
|
||||||
|
@ -1971,4 +1971,4 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelObject)
|
|||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelVolume)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelVolume)
|
||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelInstance)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelInstance)
|
||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::Model)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::Model)
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,8 @@ namespace cereal {
|
|||||||
class BinaryOutputArchive;
|
class BinaryOutputArchive;
|
||||||
template <class T> void load_optional(BinaryInputArchive &ar, std::shared_ptr<const T> &ptr);
|
template <class T> void load_optional(BinaryInputArchive &ar, std::shared_ptr<const T> &ptr);
|
||||||
template <class T> void save_optional(BinaryOutputArchive &ar, const std::shared_ptr<const T> &ptr);
|
template <class T> void save_optional(BinaryOutputArchive &ar, const std::shared_ptr<const T> &ptr);
|
||||||
|
template <class T> void load_by_value(BinaryInputArchive &ar, T &obj);
|
||||||
|
template <class T> void save_by_value(BinaryOutputArchive &ar, const T &obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -31,6 +33,7 @@ class ModelInstance;
|
|||||||
class ModelMaterial;
|
class ModelMaterial;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
|
class ModelWipeTower;
|
||||||
class Print;
|
class Print;
|
||||||
class SLAPrint;
|
class SLAPrint;
|
||||||
|
|
||||||
@ -66,6 +69,21 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
template<typename T>
|
||||||
|
class StaticSerializationWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StaticSerializationWrapper(T &wrap) : wrapped(wrap) {}
|
||||||
|
private:
|
||||||
|
friend class cereal::access;
|
||||||
|
friend class UndoRedo::StackImpl;
|
||||||
|
template<class Archive> void load(Archive &ar) { cereal::load_by_value(ar, wrapped); }
|
||||||
|
template<class Archive> void save(Archive &ar) const { cereal::save_by_value(ar, wrapped); }
|
||||||
|
T& wrapped;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::string t_model_material_id;
|
typedef std::string t_model_material_id;
|
||||||
typedef std::string t_model_material_attribute;
|
typedef std::string t_model_material_attribute;
|
||||||
typedef std::map<t_model_material_attribute, std::string> t_model_material_attributes;
|
typedef std::map<t_model_material_attribute, std::string> t_model_material_attributes;
|
||||||
@ -140,7 +158,8 @@ private:
|
|||||||
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
assert(this->id().invalid()); assert(this->config.id().invalid());
|
assert(this->id().invalid()); assert(this->config.id().invalid());
|
||||||
ar(attributes, config);
|
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||||
|
ar(attributes, config_wrapper);
|
||||||
// assert(this->id().valid()); assert(this->config.id().valid());
|
// assert(this->id().valid()); assert(this->config.id().valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +368,8 @@ private:
|
|||||||
}
|
}
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
ar(cereal::base_class<ObjectBase>(this));
|
ar(cereal::base_class<ObjectBase>(this));
|
||||||
ar(name, input_file, instances, volumes, config, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||||
|
ar(name, input_file, instances, volumes, config_wrapper, layer_config_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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -535,7 +555,8 @@ private:
|
|||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar) {
|
template<class Archive> void load(Archive &ar) {
|
||||||
bool has_convex_hull;
|
bool has_convex_hull;
|
||||||
ar(name, config, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||||
|
cereal::load_by_value(ar, config);
|
||||||
assert(m_mesh);
|
assert(m_mesh);
|
||||||
if (has_convex_hull) {
|
if (has_convex_hull) {
|
||||||
cereal::load_optional(ar, m_convex_hull);
|
cereal::load_optional(ar, m_convex_hull);
|
||||||
@ -547,7 +568,8 @@ private:
|
|||||||
}
|
}
|
||||||
template<class Archive> void save(Archive &ar) const {
|
template<class Archive> void save(Archive &ar) const {
|
||||||
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
||||||
ar(name, config, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||||
|
cereal::save_by_value(ar, config);
|
||||||
if (has_convex_hull)
|
if (has_convex_hull)
|
||||||
cereal::save_optional(ar, m_convex_hull);
|
cereal::save_optional(ar, m_convex_hull);
|
||||||
}
|
}
|
||||||
@ -650,6 +672,35 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModelWipeTower final : public ObjectBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec2d position;
|
||||||
|
double rotation;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class cereal::access;
|
||||||
|
friend class UndoRedo::StackImpl;
|
||||||
|
friend class Model;
|
||||||
|
|
||||||
|
// Constructors to be only called by derived classes.
|
||||||
|
// Default constructor to assign a unique ID.
|
||||||
|
explicit ModelWipeTower() {}
|
||||||
|
// Constructor with ignored int parameter to assign an invalid ID, to be replaced
|
||||||
|
// by an existing ID copied from elsewhere.
|
||||||
|
explicit ModelWipeTower(int) : ObjectBase(-1) {}
|
||||||
|
// Copy constructor copies the ID.
|
||||||
|
explicit ModelWipeTower(const ModelWipeTower &cfg) = default;
|
||||||
|
|
||||||
|
// Disabled methods.
|
||||||
|
ModelWipeTower(ModelWipeTower &&rhs) = delete;
|
||||||
|
ModelWipeTower& operator=(const ModelWipeTower &rhs) = delete;
|
||||||
|
ModelWipeTower& operator=(ModelWipeTower &&rhs) = delete;
|
||||||
|
|
||||||
|
// For serialization / deserialization of ModelWipeTower composed into another class into the Undo / Redo stack as a separate object.
|
||||||
|
template<typename Archive> void serialize(Archive &ar) { ar(position, rotation); }
|
||||||
|
};
|
||||||
|
|
||||||
// The print bed content.
|
// The print bed content.
|
||||||
// Description of a triangular model with multiple materials, multiple instances with various affine transformations
|
// Description of a triangular model with multiple materials, multiple instances with various affine transformations
|
||||||
// and with multiple modifier meshes.
|
// and with multiple modifier meshes.
|
||||||
@ -665,6 +716,8 @@ public:
|
|||||||
ModelMaterialMap materials;
|
ModelMaterialMap materials;
|
||||||
// Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
|
// Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
|
||||||
ModelObjectPtrs objects;
|
ModelObjectPtrs objects;
|
||||||
|
// Wipe tower object.
|
||||||
|
ModelWipeTower wipe_tower;
|
||||||
|
|
||||||
// Default constructor assigns a new ID to the model.
|
// Default constructor assigns a new ID to the model.
|
||||||
Model() { assert(this->id().valid()); }
|
Model() { assert(this->id().valid()); }
|
||||||
@ -742,7 +795,8 @@ private:
|
|||||||
friend class cereal::access;
|
friend class cereal::access;
|
||||||
friend class UndoRedo::StackImpl;
|
friend class UndoRedo::StackImpl;
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
ar(materials, objects);
|
Internal::StaticSerializationWrapper<ModelWipeTower> wipe_tower_wrapper(wipe_tower);
|
||||||
|
ar(materials, objects, wipe_tower_wrapper);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -778,6 +832,7 @@ void check_model_ids_equal(const Model &model1, const Model &model2);
|
|||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume, cereal::specialization::member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume, cereal::specialization::member_load_save> {};
|
||||||
|
template <class Archive> struct specialize<Archive, Slic3r::ModelConfig, cereal::specialization::member_serialize> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* slic3r_Model_hpp_ */
|
#endif /* slic3r_Model_hpp_ */
|
||||||
|
@ -3586,6 +3586,13 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name)
|
|||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
if (this->view3D->is_layers_editing_enabled())
|
if (this->view3D->is_layers_editing_enabled())
|
||||||
flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
||||||
|
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y"));
|
||||||
|
model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
}
|
||||||
this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags);
|
this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags);
|
||||||
this->undo_redo_stack.release_least_recently_used();
|
this->undo_redo_stack.release_least_recently_used();
|
||||||
// Save the last active preset name of a particular printer technology.
|
// Save the last active preset name of a particular printer technology.
|
||||||
@ -3632,6 +3639,13 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
|||||||
}
|
}
|
||||||
// Save the last active preset name of a particular printer technology.
|
// Save the last active preset name of a particular printer technology.
|
||||||
((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
|
((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
|
||||||
|
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y"));
|
||||||
|
model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
}
|
||||||
// Flags made of Snapshot::Flags enum values.
|
// Flags made of Snapshot::Flags enum values.
|
||||||
unsigned int new_flags = it_snapshot->flags;
|
unsigned int new_flags = it_snapshot->flags;
|
||||||
unsigned int top_snapshot_flags = 0;
|
unsigned int top_snapshot_flags = 0;
|
||||||
@ -3654,6 +3668,22 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
|||||||
// This also switches the printer technology based on the printer technology of the active printer profile.
|
// This also switches the printer technology based on the printer technology of the active printer profile.
|
||||||
wxGetApp().load_current_presets();
|
wxGetApp().load_current_presets();
|
||||||
}
|
}
|
||||||
|
//FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
Vec2d current_position(current_config.opt_float("wipe_tower_x"), current_config.opt_float("wipe_tower_y"));
|
||||||
|
double current_rotation = current_config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
if (current_position != model.wipe_tower.position || current_rotation != model.wipe_tower.rotation) {
|
||||||
|
DynamicPrintConfig new_config;
|
||||||
|
new_config.set_key_value("wipe_tower_x", new ConfigOptionFloat(model.wipe_tower.position.x()));
|
||||||
|
new_config.set_key_value("wipe_tower_y", new ConfigOptionFloat(model.wipe_tower.position.y()));
|
||||||
|
new_config.set_key_value("wipe_tower_rotation_angle", new ConfigOptionFloat(model.wipe_tower.rotation));
|
||||||
|
Tab *tab_print = wxGetApp().get_tab(Preset::TYPE_PRINT);
|
||||||
|
tab_print->load_config(new_config);
|
||||||
|
tab_print->update_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
this->update_after_undo_redo(temp_snapshot_was_taken);
|
this->update_after_undo_redo(temp_snapshot_was_taken);
|
||||||
// Enable layer editing after the Undo / Redo jump.
|
// Enable layer editing after the Undo / Redo jump.
|
||||||
if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
|
if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
|
||||||
|
@ -514,11 +514,11 @@ public:
|
|||||||
const Selection& selection_deserialized() const { return m_selection; }
|
const Selection& selection_deserialized() const { return m_selection; }
|
||||||
|
|
||||||
//protected:
|
//protected:
|
||||||
template<typename T, typename T_AS> ObjectID save_mutable_object(const T &object);
|
template<typename T> ObjectID save_mutable_object(const T &object);
|
||||||
template<typename T> ObjectID save_immutable_object(std::shared_ptr<const T> &object, bool optional);
|
template<typename T> ObjectID save_immutable_object(std::shared_ptr<const T> &object, bool optional);
|
||||||
template<typename T> T* load_mutable_object(const Slic3r::ObjectID id);
|
template<typename T> T* load_mutable_object(const Slic3r::ObjectID id);
|
||||||
template<typename T> std::shared_ptr<const T> load_immutable_object(const Slic3r::ObjectID id, bool optional);
|
template<typename T> std::shared_ptr<const T> load_immutable_object(const Slic3r::ObjectID id, bool optional);
|
||||||
template<typename T, typename T_AS> void load_mutable_object(const Slic3r::ObjectID id, T &target);
|
template<typename T> void load_mutable_object(const Slic3r::ObjectID id, T &target);
|
||||||
|
|
||||||
#ifdef SLIC3R_UNDOREDO_DEBUG
|
#ifdef SLIC3R_UNDOREDO_DEBUG
|
||||||
std::string format() const {
|
std::string format() const {
|
||||||
@ -601,7 +601,6 @@ class ModelObject;
|
|||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
class ModelInstance;
|
class ModelInstance;
|
||||||
class ModelMaterial;
|
class ModelMaterial;
|
||||||
class ModelConfig;
|
|
||||||
class DynamicPrintConfig;
|
class DynamicPrintConfig;
|
||||||
class TriangleMesh;
|
class TriangleMesh;
|
||||||
|
|
||||||
@ -616,14 +615,13 @@ namespace cereal
|
|||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelInstance*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelInstance*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelMaterial*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelMaterial*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelConfig, cereal::specialization::non_member_load_save> {};
|
|
||||||
template <class Archive> struct specialize<Archive, std::shared_ptr<Slic3r::TriangleMesh>, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, std::shared_ptr<Slic3r::TriangleMesh>, cereal::specialization::non_member_load_save> {};
|
||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
// store just the ObjectID to this stream.
|
// store just the ObjectID to this stream.
|
||||||
template <class T> void save(BinaryOutputArchive& ar, T* const& ptr)
|
template <class T> void save(BinaryOutputArchive& ar, T* const& ptr)
|
||||||
{
|
{
|
||||||
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T, T>(*ptr));
|
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T>(*ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
||||||
@ -655,19 +653,18 @@ namespace cereal
|
|||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
// store just the ObjectID to this stream.
|
// store just the ObjectID to this stream.
|
||||||
void save(BinaryOutputArchive& ar, const Slic3r::ModelConfig &cfg)
|
template<class T> void save_by_value(BinaryOutputArchive& ar, const T &cfg)
|
||||||
{
|
{
|
||||||
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<Slic3r::ModelConfig, Slic3r::DynamicPrintConfig>(cfg));
|
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T>(cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
||||||
// based on the ObjectID loaded from this stream.
|
// based on the ObjectID loaded from this stream.
|
||||||
void load(BinaryInputArchive& ar, Slic3r::ModelConfig &cfg)
|
template<class T> void load_by_value(BinaryInputArchive& ar, T &cfg)
|
||||||
{
|
{
|
||||||
Slic3r::UndoRedo::StackImpl& stack = cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar);
|
Slic3r::UndoRedo::StackImpl& stack = cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar);
|
||||||
size_t id;
|
size_t id;
|
||||||
ar(id);
|
ar(id);
|
||||||
stack.load_mutable_object<Slic3r::ModelConfig, Slic3r::DynamicPrintConfig>(Slic3r::ObjectID(id), cfg);
|
stack.load_mutable_object<T>(Slic3r::ObjectID(id), cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
@ -723,7 +720,7 @@ template<typename T> std::shared_ptr<const T>& ImmutableObjectHistory<T>::share
|
|||||||
return m_shared_object;
|
return m_shared_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename T_AS> ObjectID StackImpl::save_mutable_object(const T &object)
|
template<typename T> ObjectID StackImpl::save_mutable_object(const T &object)
|
||||||
{
|
{
|
||||||
// First find or allocate a history stack for the ObjectID of this object instance.
|
// First find or allocate a history stack for the ObjectID of this object instance.
|
||||||
auto it_object_history = m_objects.find(object.id());
|
auto it_object_history = m_objects.find(object.id());
|
||||||
@ -734,7 +731,7 @@ template<typename T, typename T_AS> ObjectID StackImpl::save_mutable_object(cons
|
|||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
{
|
{
|
||||||
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
||||||
archive(static_cast<const T_AS&>(object));
|
archive(object);
|
||||||
}
|
}
|
||||||
object_history->save(m_active_snapshot_time, m_current_time, oss.str());
|
object_history->save(m_active_snapshot_time, m_current_time, oss.str());
|
||||||
return object.id();
|
return object.id();
|
||||||
@ -758,7 +755,7 @@ template<typename T> ObjectID StackImpl::save_immutable_object(std::shared_ptr<c
|
|||||||
template<typename T> T* StackImpl::load_mutable_object(const Slic3r::ObjectID id)
|
template<typename T> T* StackImpl::load_mutable_object(const Slic3r::ObjectID id)
|
||||||
{
|
{
|
||||||
T *target = new T();
|
T *target = new T();
|
||||||
this->load_mutable_object<T, T>(id, *target);
|
this->load_mutable_object<T>(id, *target);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,7 +772,7 @@ template<typename T> std::shared_ptr<const T> StackImpl::load_immutable_object(c
|
|||||||
return object_history->shared_ptr(*this);
|
return object_history->shared_ptr(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Slic3r::ObjectID id, T &target)
|
template<typename T> void StackImpl::load_mutable_object(const Slic3r::ObjectID id, T &target)
|
||||||
{
|
{
|
||||||
// First find a history stack for the ObjectID of this object instance.
|
// First find a history stack for the ObjectID of this object instance.
|
||||||
auto it_object_history = m_objects.find(id);
|
auto it_object_history = m_objects.find(id);
|
||||||
@ -785,7 +782,7 @@ template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Sl
|
|||||||
std::istringstream iss(object_history->load(m_active_snapshot_time));
|
std::istringstream iss(object_history->load(m_active_snapshot_time));
|
||||||
Slic3r::UndoRedo::InputArchive archive(*this, iss);
|
Slic3r::UndoRedo::InputArchive archive(*this, iss);
|
||||||
target.m_id = id;
|
target.m_id = id;
|
||||||
archive(static_cast<T_AS&>(target));
|
archive(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
|
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
|
||||||
@ -800,14 +797,14 @@ void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Mo
|
|||||||
m_snapshots.erase(it, m_snapshots.end());
|
m_snapshots.erase(it, m_snapshots.end());
|
||||||
}
|
}
|
||||||
// Take new snapshots.
|
// Take new snapshots.
|
||||||
this->save_mutable_object<Slic3r::Model, Slic3r::Model>(model);
|
this->save_mutable_object<Slic3r::Model>(model);
|
||||||
m_selection.volumes_and_instances.clear();
|
m_selection.volumes_and_instances.clear();
|
||||||
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
|
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
|
||||||
m_selection.mode = selection.get_mode();
|
m_selection.mode = selection.get_mode();
|
||||||
for (unsigned int volume_idx : selection.get_volume_idxs())
|
for (unsigned int volume_idx : selection.get_volume_idxs())
|
||||||
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
|
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
|
||||||
this->save_mutable_object<Selection, Selection>(m_selection);
|
this->save_mutable_object<Selection>(m_selection);
|
||||||
this->save_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos);
|
this->save_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos);
|
||||||
// Save the snapshot info.
|
// Save the snapshot info.
|
||||||
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags);
|
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags);
|
||||||
m_active_snapshot_time = m_current_time;
|
m_active_snapshot_time = m_current_time;
|
||||||
@ -833,12 +830,12 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GU
|
|||||||
m_active_snapshot_time = timestamp;
|
m_active_snapshot_time = timestamp;
|
||||||
model.clear_objects();
|
model.clear_objects();
|
||||||
model.clear_materials();
|
model.clear_materials();
|
||||||
this->load_mutable_object<Slic3r::Model, Slic3r::Model>(ObjectID(it_snapshot->model_id), model);
|
this->load_mutable_object<Slic3r::Model>(ObjectID(it_snapshot->model_id), model);
|
||||||
model.update_links_bottom_up_recursive();
|
model.update_links_bottom_up_recursive();
|
||||||
m_selection.volumes_and_instances.clear();
|
m_selection.volumes_and_instances.clear();
|
||||||
this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection);
|
this->load_mutable_object<Selection>(m_selection.id(), m_selection);
|
||||||
gizmos.reset_all_states();
|
gizmos.reset_all_states();
|
||||||
this->load_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
|
this->load_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
|
||||||
// Sort the volumes so that we may use binary search.
|
// Sort the volumes so that we may use binary search.
|
||||||
std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
|
std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
|
||||||
this->m_active_snapshot_time = timestamp;
|
this->m_active_snapshot_time = timestamp;
|
||||||
|
Loading…
Reference in New Issue
Block a user