From 5d2537af35e754950329f2e12c3c940435c8e4f0 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Apr 2019 11:01:59 +0200 Subject: [PATCH 01/15] WIP: Transformations of an instance in world coordinate system from the side panel. --- src/slic3r/GUI/Field.cpp | 14 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 263 ++++++++-------------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 15 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 5 +- src/slic3r/GUI/KBShortcutsDialog.cpp | 4 +- src/slic3r/GUI/OptionsGroup.cpp | 23 +- src/slic3r/GUI/OptionsGroup.hpp | 2 +- src/slic3r/GUI/Selection.cpp | 13 +- src/slic3r/GUI/Selection.hpp | 2 +- 9 files changed, 134 insertions(+), 207 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 6da0800d9..d8ed9f27a 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -15,19 +15,7 @@ namespace Slic3r { namespace GUI { wxString double_to_string(double const value, const int max_precision /*= 4*/) { - if (value - int(value) == 0) - return wxString::Format(_T("%i"), int(value)); - - int precision = max_precision; - for (size_t p = 1; p < max_precision; p++) - { - double cur_val = pow(10, p)*value; - if (cur_val - int(cur_val) == 0) { - precision = p; - break; - } - } - return wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None); + return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes); } void Field::PostInitialize() diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index f9284a19b..663ff8ad9 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -57,16 +57,14 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : def.type = coString; def.width = field_width/*50*/; - std::vector axes{ "x", "y", "z" }; - for (const auto axis : axes) { - const auto label = boost::algorithm::to_upper_copy(axis); + for (const std::string axis : { "x", "y", "z" }) { + const std::string label = boost::algorithm::to_upper_copy(axis); def.default_value = new ConfigOptionString{ " " + label }; Option option = Option(def, axis + "_axis_legend"); line.append_option(option); } m_og->append_line(line); - auto add_og_to_object_settings = [this, field_width](const std::string& option_name, const std::string& sidetext) { Line line = { _(option_name), "" }; @@ -98,11 +96,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : const std::string lower_name = boost::algorithm::to_lower_copy(option_name); - std::vector axes{ "x", "y", "z" }; - for (auto axis : axes) { - if (axis == "z") + for (const char *axis : { "_x", "_y", "_z" }) { + if (axis[1] == 'z') def.sidetext = sidetext; - Option option = Option(def, lower_name + "_" + axis); + Option option = Option(def, lower_name + axis); option.opt.full_width = true; line.append_option(option); } @@ -162,7 +159,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_scale_label_string = L("Scale factors"); ObjectList* obj_list = wxGetApp().obj_list(); - if (selection.is_single_full_instance()) + if (selection.is_single_full_instance() && ! m_world_coordinates) { // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); @@ -174,21 +171,26 @@ void ObjectManipulation::update_settings_value(const Selection& selection) if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) { bool changed_box = false; + //FIXME matching an object idx may not be enough if (!m_cache.instance.matches_object(obj_idx)) { m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size()); changed_box = true; } + //FIXME matching an instance idx may not be enough. Check for ModelObject id an all ModelVolume ids. if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale)) - m_new_size = (volume->get_instance_transformation().get_matrix(true, true) * m_cache.instance.box_size).cwiseAbs(); + m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(m_cache.instance.box_size); } - else + else { // this should never happen + assert(false); m_new_size = Vec3d::Zero(); + } m_new_enabled = true; } - else if (selection.is_single_full_object() && obj_list->is_selected(itObject)) + else if ((selection.is_single_full_instance() && m_world_coordinates) || + (selection.is_single_full_object() && obj_list->is_selected(itObject))) { m_cache.instance.reset(); @@ -210,7 +212,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = volume->get_volume_offset(); m_new_rotation = volume->get_volume_rotation(); m_new_scale = volume->get_volume_scaling_factor(); - m_new_size = (volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size()).cwiseAbs(); + m_new_size = volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box.size()); m_new_enabled = true; } else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) @@ -222,8 +224,11 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_size = selection.get_bounding_box().size(); m_new_enabled = true; } - else - reset_settings_value(); + else { + // No selection, reset the cache. + assert(selection.is_empty()); + reset_settings_value(); + } m_dirty = true; } @@ -233,73 +238,35 @@ void ObjectManipulation::update_if_dirty() if (!m_dirty) return; - if (m_cache.move_label_string != _(m_new_move_label_string)+ ":") - { - m_cache.move_label_string = _(m_new_move_label_string)+ ":"; - m_move_Label->SetLabel(m_cache.move_label_string); + auto update_label = [](std::string &label_cache, const std::string &new_label, wxStaticText *widget) { + std::string new_label_localized = _(new_label) + ":"; + if (label_cache != new_label_localized) { + label_cache = new_label_localized; + widget->SetLabel(new_label_localized); + } + }; + update_label(m_cache.move_label_string, m_new_move_label_string, m_move_Label); + update_label(m_cache.rotate_label_string, m_new_rotate_label_string, m_rotate_Label); + update_label(m_cache.scale_label_string, m_new_scale_label_string, m_scale_Label); + + Vec3d scale = m_new_scale * 100.0; + Vec3d deg_rotation = (180.0 / M_PI) * m_new_rotation; + + char axis[2] = "x"; + for (int i = 0; i < 3; ++ i, ++ axis[0]) { + if (m_cache.position(i) != m_new_position(i)) + m_og->set_value(std::string("position_") + axis, double_to_string(m_new_position(i), 2)); + if (m_cache.scale(i) != scale(i)) + m_og->set_value(std::string("scale_") + axis, double_to_string(scale(i), 2)); + if (m_cache.size(i) != m_new_size(i)) + m_og->set_value(std::string("size_") + axis, double_to_string(m_new_size(i), 2)); + if (m_cache.rotation(i) != m_new_rotation(i) || m_new_rotation(i) == 0.0) + m_og->set_value(std::string("rotation_") + axis, double_to_string(deg_rotation(i), 2)); } - if (m_cache.rotate_label_string != _(m_new_rotate_label_string)+ ":") - { - m_cache.rotate_label_string = _(m_new_rotate_label_string)+ ":"; - m_rotate_Label->SetLabel(m_cache.rotate_label_string); - } - - if (m_cache.scale_label_string != _(m_new_scale_label_string)+ ":") - { - m_cache.scale_label_string = _(m_new_scale_label_string)+ ":"; - m_scale_Label->SetLabel(m_cache.scale_label_string); - } - - if (m_cache.position(0) != m_new_position(0)) - m_og->set_value("position_x", double_to_string(m_new_position(0), 2)); - - if (m_cache.position(1) != m_new_position(1)) - m_og->set_value("position_y", double_to_string(m_new_position(1), 2)); - - if (m_cache.position(2) != m_new_position(2)) - m_og->set_value("position_z", double_to_string(m_new_position(2), 2)); - m_cache.position = m_new_position; - - auto scale = m_new_scale * 100.0; - if (m_cache.scale(0) != scale(0)) - m_og->set_value("scale_x", double_to_string(scale(0), 2)); - - if (m_cache.scale(1) != scale(1)) - m_og->set_value("scale_y", double_to_string(scale(1), 2)); - - if (m_cache.scale(2) != scale(2)) - m_og->set_value("scale_z", double_to_string(scale(2), 2)); - m_cache.scale = scale; - - if (m_cache.size(0) != m_new_size(0)) - m_og->set_value("size_x", double_to_string(m_new_size(0), 2)); - - if (m_cache.size(1) != m_new_size(1)) - m_og->set_value("size_y", double_to_string(m_new_size(1), 2)); - - if (m_cache.size(2) != m_new_size(2)) - m_og->set_value("size_z", double_to_string(m_new_size(2), 2)); - m_cache.size = m_new_size; - - Vec3d deg_rotation; - for (size_t i = 0; i < 3; ++i) - { - deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i)); - } - - if ((m_cache.rotation(0) != m_new_rotation(0)) || (m_new_rotation(0) == 0.0)) - m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2)); - - if ((m_cache.rotation(1) != m_new_rotation(1)) || (m_new_rotation(1) == 0.0)) - m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2)); - - if ((m_cache.rotation(2) != m_new_rotation(2)) || (m_new_rotation(2) == 0.0)) - m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2)); - m_cache.rotation = deg_rotation; if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) { @@ -361,23 +328,21 @@ void ObjectManipulation::change_position_value(const Vec3d& position) void ObjectManipulation::change_rotation_value(const Vec3d& rotation) { GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); - const Selection& selection = canvas->get_selection(); + Selection& selection = canvas->get_selection(); TransformationType transformation_type(TransformationType::World_Relative_Joint); if (selection.is_single_full_instance() || selection.requires_local_axes()) transformation_type.set_independent(); - if (selection.is_single_full_instance()) { + if (selection.is_single_full_instance() && ! m_world_coordinates) { //FIXME Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed. // transformation_type.set_absolute(); transformation_type.set_local(); } - Vec3d rad_rotation; - for (size_t i = 0; i < 3; ++i) - rad_rotation(i) = Geometry::deg2rad((transformation_type.absolute()) ? rotation(i) : rotation(i) - m_cache.rotation(i)); - - canvas->get_selection().start_dragging(); - canvas->get_selection().rotate(rad_rotation, transformation_type); + selection.start_dragging(); + selection.rotate( + (M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation), + transformation_type); canvas->do_rotate(); m_cache.rotation = rotation; @@ -385,32 +350,7 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation) void ObjectManipulation::change_scale_value(const Vec3d& scale) { - Vec3d scaling_factor = scale; - const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); - if (m_uniform_scale || selection.requires_uniform_scale()) - { - Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs(); - double max_diff = abs_scale_diff(X); - Axis max_diff_axis = X; - if (max_diff < abs_scale_diff(Y)) - { - max_diff = abs_scale_diff(Y); - max_diff_axis = Y; - } - if (max_diff < abs_scale_diff(Z)) - { - max_diff = abs_scale_diff(Z); - max_diff_axis = Z; - } - scaling_factor = scale(max_diff_axis) * Vec3d::Ones(); - } - - scaling_factor *= 0.01; - - auto canvas = wxGetApp().plater()->canvas3D(); - canvas->get_selection().start_dragging(); - canvas->get_selection().scale(scaling_factor, false); - canvas->do_scale(); + this->do_scale(scale); if (!m_cache.scale.isApprox(scale)) m_cache.instance.instance_idx = -1; @@ -428,41 +368,35 @@ void ObjectManipulation::change_size_value(const Vec3d& size) const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); ref_size = volume->bounding_box.size(); } - else if (selection.is_single_full_instance()) + else if (selection.is_single_full_instance() && ! m_world_coordinates) ref_size = m_cache.instance.box_size; - Vec3d scale = 100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2)); - Vec3d scaling_factor = scale; - - if (m_uniform_scale || selection.requires_uniform_scale()) - { - Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs(); - double max_diff = abs_scale_diff(X); - Axis max_diff_axis = X; - if (max_diff < abs_scale_diff(Y)) - { - max_diff = abs_scale_diff(Y); - max_diff_axis = Y; - } - if (max_diff < abs_scale_diff(Z)) - { - max_diff = abs_scale_diff(Z); - max_diff_axis = Z; - } - scaling_factor = scale(max_diff_axis) * Vec3d::Ones(); - } - - scaling_factor *= 0.01; - - auto canvas = wxGetApp().plater()->canvas3D(); - canvas->get_selection().start_dragging(); - canvas->get_selection().scale(scaling_factor, false); - canvas->do_scale(); + this->do_scale(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); m_cache.size = size; } -void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boost::any& value) +void ObjectManipulation::do_scale(const Vec3d &scale) const +{ + Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); + Vec3d scaling_factor = scale; + + if (m_uniform_scale || selection.requires_uniform_scale()) + { + int max_diff_axis; + (scale - m_cache.scale).cwiseAbs().maxCoeff(&max_diff_axis); + scaling_factor = scale(max_diff_axis) * Vec3d::Ones(); + } + + TransformationType transformation_type(TransformationType::World_Relative_Joint); + if (selection.is_single_full_instance() && ! m_world_coordinates) + transformation_type.set_local(); + selection.start_dragging(); + selection.scale(scaling_factor * 0.01, transformation_type); + wxGetApp().plater()->canvas3D()->do_scale(); +} + +void ObjectManipulation::on_change(t_config_option_key opt_key, const boost::any& value) { // needed to hide the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); @@ -473,23 +407,19 @@ void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boo if (!m_cache.is_valid()) return; - std::vector axes{ "_x", "_y", "_z" }; - - std::string param; - std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); - - size_t i = 0; + // Value of all three axes of the position / rotation / scale / size is extracted. Vec3d new_value; - for (auto axis : axes) - new_value(i++) = boost::any_cast(m_og->get_value(param + axis)); + opt_key.back() = 'x'; + for (int i = 0; i < 3; ++ i, ++ opt_key.back()) + new_value(i) = boost::any_cast(m_og->get_value(opt_key)); - if (param == "position") + if (boost::starts_with(opt_key, "position_")) change_position_value(new_value); - else if (param == "rotation") + else if (boost::starts_with(opt_key, "rotation_")) change_rotation_value(new_value); - else if (param == "scale") + else if (boost::starts_with(opt_key, "scale_")) change_scale_value(new_value); - else if (param == "size") + else if (boost::starts_with(opt_key, "size_")) change_size_value(new_value); } @@ -504,22 +434,21 @@ void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) if (!m_cache.is_valid()) return; - std::string param; - std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); + const Vec3d *vec = nullptr; + if (boost::starts_with(opt_key, "position_")) + vec = &m_cache.position; + else if (boost::starts_with(opt_key, "rotation_")) + vec = &m_cache.rotation; + else if (boost::starts_with(opt_key, "scale_")) + vec = &m_cache.scale; + else if (boost::starts_with(opt_key, "size_")) + vec = &m_cache.size; + else + assert(false); - double value = 0.0; - auto opt_key_to_axis = [&opt_key]() { return opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; }; - if (param == "position") - value = m_cache.position(opt_key_to_axis()); - else if (param == "rotation") - value = m_cache.rotation(opt_key_to_axis()); - else if (param == "scale") - value = m_cache.scale(opt_key_to_axis()); - else if (param == "size") - value = m_cache.size(opt_key_to_axis()); - - m_og->set_value(opt_key, double_to_string(value)); + if (vec != nullptr) + m_og->set_value(opt_key, double_to_string((*vec)(opt_key.back() - 'x'))); } } //namespace GUI -} //namespace Slic3r \ No newline at end of file +} //namespace Slic3r diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index a5a180a56..ecd306c0a 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -76,6 +76,8 @@ class ObjectManipulation : public OG_Settings Vec3d m_new_size; bool m_new_enabled; bool m_uniform_scale {true}; + // Does the object manipulation panel work in World or Local coordinates? + bool m_world_coordinates = true; PrusaLockButton* m_lock_bnt{ nullptr }; #ifndef __APPLE__ @@ -98,6 +100,8 @@ public: void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;} bool get_uniform_scaling() const { return m_uniform_scale; } + // Does the object manipulation panel work in World or Local coordinates? + bool get_world_coordinates() const { return m_world_coordinates; } void reset_cache() { m_cache.reset(); } #ifndef __APPLE__ @@ -116,12 +120,13 @@ private: void update_rotation_value(const Vec3d& rotation); // change values - void change_position_value(const Vec3d& position); - void change_rotation_value(const Vec3d& rotation); - void change_scale_value(const Vec3d& scale); - void change_size_value(const Vec3d& size); + void change_position_value(const Vec3d& position); + void change_rotation_value(const Vec3d& rotation); + void change_scale_value(const Vec3d& scale); + void change_size_value(const Vec3d& size); + void do_scale(const Vec3d &scale) const; - void on_change(const t_config_option_key& opt_key, const boost::any& value); + void on_change(t_config_option_key opt_key, const boost::any& value); void on_fill_empty_value(const std::string& opt_key); }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 5e37e42ad..f55391865 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -629,7 +629,10 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) case Scale: { // Apply new temporary scale factors - selection.scale(get_scale(), evt.AltDown()); + TransformationType transformation_type(TransformationType::World_Relative_Joint); + if (evt.AltDown()) + transformation_type.set_independent(); + selection.scale(get_scale(), transformation_type); wxGetApp().obj_manipul()->update_settings_value(selection); break; } diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 65abba319..3c2f4182b 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -104,8 +104,8 @@ void KBShortcutsDialog::fill_shortcuts() main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)"))); main_shortcuts.push_back(Shortcut(ctrl+alt+"L" ,L("Load Config from .ini/amf/3mf/gcode and merge"))); main_shortcuts.push_back(Shortcut(ctrl+"R" ,L("(Re)slice"))); - main_shortcuts.push_back(Shortcut(ctrl+"U" ,L("Quick slice"))); - main_shortcuts.push_back(Shortcut(ctrl+"Shift+U" ,L("Repeat last quick slice"))); +// main_shortcuts.push_back(Shortcut(ctrl+"U" ,L("Quick slice"))); +// main_shortcuts.push_back(Shortcut(ctrl+"Shift+U" ,L("Repeat last quick slice"))); main_shortcuts.push_back(Shortcut(ctrl+"1" ,L("Select Plater Tab"))); main_shortcuts.push_back(Shortcut(ctrl+alt+"U" ,L("Quick slice and Save as"))); main_shortcuts.push_back(Shortcut(ctrl+"2" ,L("Select Print Settings Tab"))); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index df2f7b582..4abbbd45a 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -417,22 +417,21 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config, void ConfigOptionsGroup::on_kill_focus(const std::string& opt_key) { - if (m_fill_empty_value) { + if (m_fill_empty_value) m_fill_empty_value(opt_key); - return; - } - reload_config(); + else + reload_config(); } -void ConfigOptionsGroup::reload_config() { - for (t_opt_map::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) { - auto opt_id = it->first; - std::string opt_key = m_opt_map.at(opt_id).first; - int opt_index = m_opt_map.at(opt_id).second; - auto option = m_options.at(opt_id).opt; - set_value(opt_id, config_value(opt_key, opt_index, option.gui_flags.compare("serialized") == 0 )); +void ConfigOptionsGroup::reload_config() +{ + for (auto &kvp : m_opt_map) { + const std::string &opt_id = kvp.first; + const std::string &opt_key = kvp.second.first; + int opt_index = kvp.second.second; + const ConfigOptionDef &option = m_options.at(opt_id).opt; + this->set_value(opt_key, config_value(opt_key, opt_index, option.gui_flags == "serialized")); } - } void ConfigOptionsGroup::Hide() diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index e4ada3692..4eec68a37 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -255,7 +255,7 @@ public: void back_to_initial_value(const std::string& opt_key) override; void back_to_sys_value(const std::string& opt_key) override; void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key); - void on_kill_focus(const std::string& opt_key) override;// { reload_config(); } + void on_kill_focus(const std::string& opt_key) override; void reload_config(); // return value shows visibility : false => all options are hidden void Hide(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e014851ab..7a203fe74 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -631,14 +631,17 @@ void Selection::flattening_rotate(const Vec3d& normal) m_bounding_box_dirty = true; } -void Selection::scale(const Vec3d& scale, bool local) +void Selection::scale(const Vec3d& scale, TransformationType transformation_type) { if (!m_valid) return; + // Only relative scaling values are allowed in the world coordinate system. + assert(! transformation_type.world() || transformation_type.relative()); + for (unsigned int i : m_list) { - if (is_single_full_instance()) + if (is_single_full_instance() && ! transformation_type.world()) (*m_volumes)[i]->set_instance_scaling_factor(scale); else if (is_single_volume() || is_single_modifier()) (*m_volumes)[i]->set_volume_scaling_factor(scale); @@ -650,7 +653,7 @@ void Selection::scale(const Vec3d& scale, bool local) Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); - if (!local) + if (transformation_type.joint()) (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); (*m_volumes)[i]->set_instance_scaling_factor(new_scale); @@ -660,7 +663,7 @@ void Selection::scale(const Vec3d& scale, bool local) Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); - if (!local) + if (transformation_type.joint()) { Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center); (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); @@ -959,7 +962,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const const Vec3d& center = get_bounding_box().center(); - if (is_single_full_instance()) + if (is_single_full_instance() && ! wxGetApp().obj_manipul()->get_world_coordinates()) { glsafe(::glTranslated(center(0), center(1), center(2))); if (!boost::starts_with(sidebar_field, "position")) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 87c919680..2a54e9a18 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -269,7 +269,7 @@ public: void translate(const Vec3d& displacement, bool local = false); void rotate(const Vec3d& rotation, TransformationType transformation_type); void flattening_rotate(const Vec3d& normal); - void scale(const Vec3d& scale, bool local); + void scale(const Vec3d& scale, TransformationType transformation_type); void mirror(Axis axis); void translate(unsigned int object_idx, const Vec3d& displacement); From 2cc7b00a7d1d8e5f5f534a93da792d3297b9002c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Apr 2019 19:03:05 +0200 Subject: [PATCH 02/15] WIP: World / local transformations of an object instance from the side panel. --- src/slic3r/GUI/3DScene.hpp | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 13 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 183 ++++++++++++++++------ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 22 ++- src/slic3r/GUI/OptionsGroup.cpp | 30 ++-- src/slic3r/GUI/Plater.cpp | 25 +-- src/slic3r/GUI/Plater.hpp | 6 +- 7 files changed, 196 insertions(+), 85 deletions(-) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 88547359e..faf5a745d 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -275,6 +275,8 @@ public: int volume_id; // Instance ID, which is equal to the index of the respective ModelInstance in ModelObject.instances array. int instance_id; + bool operator==(const CompositeID &rhs) const { return object_id == rhs.object_id && volume_id == rhs.volume_id && instance_id == rhs.instance_id; } + bool operator!=(const CompositeID &rhs) const { return ! (*this == rhs); } }; CompositeID composite_id; // Fingerprint of the source geometry. For ModelVolumes, it is the ModelVolume::ID and ModelInstanceID, diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8aa3205a7..6690e33e3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1870,8 +1870,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (m_reload_delayed) return; + bool update_object_list = false; + if (m_regenerate_volumes) { + if (m_volumes.volumes != glvolumes_new) + update_object_list = true; m_volumes.volumes = std::move(glvolumes_new); for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) { const ModelObject &model_object = *m_model->objects[obj_idx]; @@ -1886,12 +1890,16 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // New volume. m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_use_VBOs && m_initialized); m_volumes.volumes.back()->geometry_id = key.geometry_id; + update_object_list = true; } else { // Recycling an old GLVolume. GLVolume &existing_volume = *m_volumes.volumes[it->volume_idx]; assert(existing_volume.geometry_id == key.geometry_id); // Update the Object/Volume/Instance indices into the current Model. - existing_volume.composite_id = it->composite_id; + if (existing_volume.composite_id != it->composite_id) { + existing_volume.composite_id = it->composite_id; + update_object_list = true; + } } } } @@ -1999,7 +2007,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re m_gizmos.update_data(*this); // Update the toolbar - post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); + if (update_object_list) + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); // checks for geometry outside the print volume to render it accordingly if (!m_volumes.empty()) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 663ff8ad9..3c569b591 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -16,6 +16,50 @@ namespace Slic3r namespace GUI { +static wxBitmapComboBox* create_word_local_combo(wxWindow *parent) +{ + wxSize size(15 * wxGetApp().em_unit(), -1); + + wxBitmapComboBox *temp = nullptr; +#ifdef __WXOSX__ + /* wxBitmapComboBox with wxCB_READONLY style return NULL for GetTextCtrl(), + * so ToolTip doesn't shown. + * Next workaround helps to solve this problem + */ + temp = new wxBitmapComboBox(); + temp->SetTextCtrlStyle(wxTE_READONLY); + temp->Create(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); +#else + temp = new wxBitmapComboBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY); +#endif //__WXOSX__ + + temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + temp->SetBackgroundStyle(wxBG_STYLE_PAINT); + + temp->Append(_(L("World"))); + temp->Append(_(L("Local"))); + temp->SetSelection(0); + temp->SetValue(temp->GetString(0)); + +#ifndef __WXGTK__ + /* Workaround for a correct rendering of the control without Bitmap (under MSW and OSX): + * + * 1. We should create small Bitmap to fill Bitmaps RefData, + * ! in this case wxBitmap.IsOK() return true. + * 2. But then set width to 0 value for no using of bitmap left and right spacing + * 3. Set this empty bitmap to the at list one item and BitmapCombobox will be recreated correct + * + * Note: Set bitmap height to the Font size because of OSX rendering. + */ + wxBitmap empty_bmp(1, temp->GetFont().GetPixelSize().y + 2); + empty_bmp.SetWidth(0); + temp->SetItemBitmap(0, empty_bmp); +#endif + + temp->SetToolTip(_(L("Select coordinate space, in which the transformation will be performed."))); + return temp; +} + ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) #ifndef __APPLE__ @@ -63,6 +107,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : Option option = Option(def, axis + "_axis_legend"); line.append_option(option); } + line.near_label_widget = [this](wxWindow* parent) { + wxBitmapComboBox *combo = create_word_local_combo(parent); + combo->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent &evt) { this->set_world_coordinates(evt.GetSelection() != 1); }), combo->GetId()); + m_word_local_combo = combo; + return combo; + }; m_og->append_line(line); auto add_og_to_object_settings = [this, field_width](const std::string& option_name, const std::string& sidetext) @@ -145,9 +195,8 @@ bool ObjectManipulation::IsShown() void ObjectManipulation::UpdateAndShow(const bool show) { - if (show) { + if (show) update_settings_value(wxGetApp().plater()->canvas3D()->get_selection()); - } OG_Settings::UpdateAndShow(show); } @@ -164,8 +213,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_instance_offset(); - m_new_rotation = volume->get_instance_rotation(); - m_new_scale = volume->get_instance_scaling_factor(); + m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); + m_new_scale = volume->get_instance_scaling_factor() * 100.; int obj_idx = volume->object_idx(); int instance_idx = volume->instance_idx(); if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) @@ -178,7 +227,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) changed_box = true; } //FIXME matching an instance idx may not be enough. Check for ModelObject id an all ModelVolume ids. - if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale)) + if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(m_new_scale)) m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(m_cache.instance.box_size); } else { @@ -197,7 +246,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) const BoundingBoxf3& box = selection.get_bounding_box(); m_new_position = box.center(); m_new_rotation = Vec3d::Zero(); - m_new_scale = Vec3d(1.0, 1.0, 1.0); + m_new_scale = Vec3d(100., 100., 100.); m_new_size = box.size(); m_new_rotate_label_string = L("Rotate"); m_new_scale_label_string = L("Scale"); @@ -210,8 +259,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_volume_offset(); - m_new_rotation = volume->get_volume_rotation(); - m_new_scale = volume->get_volume_scaling_factor(); + m_new_rotation = volume->get_volume_rotation() * (180. / M_PI); + m_new_scale = volume->get_volume_scaling_factor() * 100.; m_new_size = volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box.size()); m_new_enabled = true; } @@ -226,7 +275,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) } else { // No selection, reset the cache. - assert(selection.is_empty()); +// assert(selection.is_empty()); reset_settings_value(); } @@ -249,26 +298,24 @@ void ObjectManipulation::update_if_dirty() update_label(m_cache.rotate_label_string, m_new_rotate_label_string, m_rotate_Label); update_label(m_cache.scale_label_string, m_new_scale_label_string, m_scale_Label); - Vec3d scale = m_new_scale * 100.0; - Vec3d deg_rotation = (180.0 / M_PI) * m_new_rotation; - char axis[2] = "x"; for (int i = 0; i < 3; ++ i, ++ axis[0]) { - if (m_cache.position(i) != m_new_position(i)) - m_og->set_value(std::string("position_") + axis, double_to_string(m_new_position(i), 2)); - if (m_cache.scale(i) != scale(i)) - m_og->set_value(std::string("scale_") + axis, double_to_string(scale(i), 2)); - if (m_cache.size(i) != m_new_size(i)) - m_og->set_value(std::string("size_") + axis, double_to_string(m_new_size(i), 2)); - if (m_cache.rotation(i) != m_new_rotation(i) || m_new_rotation(i) == 0.0) - m_og->set_value(std::string("rotation_") + axis, double_to_string(deg_rotation(i), 2)); + auto update = [this, i, &axis](Vec3d &cached, Vec3d &cached_rounded, const char *key, const Vec3d &new_value) { + wxString new_text = double_to_string(new_value(i), 2); + double new_rounded; + new_text.ToDouble(&new_rounded); + if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) { + cached_rounded(i) = new_rounded; + m_og->set_value(std::string(key) + axis, new_text); + } + cached(i) = new_value(i); + }; + update(m_cache.position, m_cache.position_rounded, "position_", m_new_position); + update(m_cache.scale, m_cache.scale_rounded, "scale_", m_new_scale); + update(m_cache.size, m_cache.size_rounded, "size_", m_new_size); + update(m_cache.rotation, m_cache.rotation_rounded, "rotation_", m_new_rotation); } - m_cache.position = m_new_position; - m_cache.scale = scale; - m_cache.size = m_new_size; - m_cache.rotation = deg_rotation; - if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) { m_lock_bnt->SetLock(true); m_lock_bnt->Disable(); @@ -278,6 +325,12 @@ void ObjectManipulation::update_if_dirty() m_lock_bnt->Enable(); } + { + int new_selection = m_world_coordinates ? 0 : 1; + if (m_word_local_combo->GetSelection() != new_selection) + m_word_local_combo->SetSelection(new_selection); + } + if (m_new_enabled) m_og->enable(); else @@ -314,8 +367,14 @@ void ObjectManipulation::reset_settings_value() m_dirty = true; } -void ObjectManipulation::change_position_value(const Vec3d& position) +void ObjectManipulation::change_position_value(int axis, double value) { + if (std::abs(m_cache.position_rounded(axis) - value) < EPSILON) + return; + + Vec3d position = m_cache.position; + position(axis) = value; + auto canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); selection.start_dragging(); @@ -323,10 +382,18 @@ void ObjectManipulation::change_position_value(const Vec3d& position) canvas->do_move(); m_cache.position = position; + m_cache.position_rounded(axis) = DBL_MAX; + this->UpdateAndShow(true); } -void ObjectManipulation::change_rotation_value(const Vec3d& rotation) +void ObjectManipulation::change_rotation_value(int axis, double value) { + if (std::abs(m_cache.rotation_rounded(axis) - value) < EPSILON) + return; + + Vec3d rotation = m_cache.rotation; + rotation(axis) = value; + GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); @@ -346,20 +413,36 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation) canvas->do_rotate(); m_cache.rotation = rotation; + m_cache.rotation_rounded(axis) = DBL_MAX; + this->UpdateAndShow(true); } -void ObjectManipulation::change_scale_value(const Vec3d& scale) +void ObjectManipulation::change_scale_value(int axis, double value) { + if (std::abs(m_cache.scale_rounded(axis) - value) < EPSILON) + return; + + Vec3d scale = m_cache.scale; + scale(axis) = value; + this->do_scale(scale); if (!m_cache.scale.isApprox(scale)) m_cache.instance.instance_idx = -1; m_cache.scale = scale; + m_cache.scale_rounded(axis) = DBL_MAX; + this->UpdateAndShow(true); } -void ObjectManipulation::change_size_value(const Vec3d& size) +void ObjectManipulation::change_size_value(int axis, double value) { + if (std::abs(m_cache.size_rounded(axis) - value) < EPSILON) + return; + + Vec3d size = m_cache.size; + size(axis) = value; + const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d ref_size = m_cache.size; @@ -371,9 +454,11 @@ void ObjectManipulation::change_size_value(const Vec3d& size) else if (selection.is_single_full_instance() && ! m_world_coordinates) ref_size = m_cache.instance.box_size; - this->do_scale(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); + this->do_scale(100. * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); m_cache.size = size; + m_cache.size_rounded(axis) = DBL_MAX; + this->UpdateAndShow(true); } void ObjectManipulation::do_scale(const Vec3d &scale) const @@ -407,20 +492,17 @@ void ObjectManipulation::on_change(t_config_option_key opt_key, const boost::any if (!m_cache.is_valid()) return; - // Value of all three axes of the position / rotation / scale / size is extracted. - Vec3d new_value; - opt_key.back() = 'x'; - for (int i = 0; i < 3; ++ i, ++ opt_key.back()) - new_value(i) = boost::any_cast(m_og->get_value(opt_key)); + int axis = opt_key.back() - 'x'; + double new_value = boost::any_cast(m_og->get_value(opt_key)); if (boost::starts_with(opt_key, "position_")) - change_position_value(new_value); + change_position_value(axis, new_value); else if (boost::starts_with(opt_key, "rotation_")) - change_rotation_value(new_value); + change_rotation_value(axis, new_value); else if (boost::starts_with(opt_key, "scale_")) - change_scale_value(new_value); + change_scale_value(axis, new_value); else if (boost::starts_with(opt_key, "size_")) - change_size_value(new_value); + change_size_value(axis, new_value); } void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) @@ -435,19 +517,28 @@ void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) return; const Vec3d *vec = nullptr; - if (boost::starts_with(opt_key, "position_")) + Vec3d *rounded = nullptr; + if (boost::starts_with(opt_key, "position_")) { vec = &m_cache.position; - else if (boost::starts_with(opt_key, "rotation_")) + rounded = &m_cache.position_rounded; + } else if (boost::starts_with(opt_key, "rotation_")) { vec = &m_cache.rotation; - else if (boost::starts_with(opt_key, "scale_")) + rounded = &m_cache.rotation_rounded; + } else if (boost::starts_with(opt_key, "scale_")) { vec = &m_cache.scale; - else if (boost::starts_with(opt_key, "size_")) + rounded = &m_cache.scale_rounded; + } else if (boost::starts_with(opt_key, "size_")) { vec = &m_cache.size; - else + rounded = &m_cache.size_rounded; + } else assert(false); - if (vec != nullptr) - m_og->set_value(opt_key, double_to_string((*vec)(opt_key.back() - 'x'))); + if (vec != nullptr) { + int axis = opt_key.back() - 'x'; + wxString new_text = double_to_string((*vec)(axis)); + m_og->set_value(opt_key, new_text); + new_text.ToDouble(&(*rounded)(axis)); + } } } //namespace GUI diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index ecd306c0a..09b1b4fe6 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -19,9 +19,13 @@ class ObjectManipulation : public OG_Settings struct Cache { Vec3d position; + Vec3d position_rounded; Vec3d rotation; + Vec3d rotation_rounded; Vec3d scale; + Vec3d scale_rounded; Vec3d size; + Vec3d size_rounded; std::string move_label_string; std::string rotate_label_string; @@ -46,10 +50,10 @@ class ObjectManipulation : public OG_Settings Cache() { reset(); } void reset() { - position = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - rotation = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - scale = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - size = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + position = position_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + rotation = rotation_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + scale = scale_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + size = size_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); move_label_string = ""; rotate_label_string = ""; scale_label_string = ""; @@ -79,6 +83,7 @@ class ObjectManipulation : public OG_Settings // Does the object manipulation panel work in World or Local coordinates? bool m_world_coordinates = true; PrusaLockButton* m_lock_bnt{ nullptr }; + wxBitmapComboBox* m_word_local_combo = nullptr; #ifndef __APPLE__ // Currently focused option name (empty if none) @@ -101,6 +106,7 @@ public: void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;} bool get_uniform_scaling() const { return m_uniform_scale; } // Does the object manipulation panel work in World or Local coordinates? + void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); } bool get_world_coordinates() const { return m_world_coordinates; } void reset_cache() { m_cache.reset(); } @@ -120,10 +126,10 @@ private: void update_rotation_value(const Vec3d& rotation); // change values - void change_position_value(const Vec3d& position); - void change_rotation_value(const Vec3d& rotation); - void change_scale_value(const Vec3d& scale); - void change_size_value(const Vec3d& size); + void change_position_value(int axis, double value); + void change_rotation_value(int axis, double value); + void change_scale_value(int axis, double value); + void change_size_value(int axis, double value); void do_scale(const Vec3d &scale) const; void on_change(t_config_option_key opt_key, const boost::any& value); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 4abbbd45a..a4686d4d2 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -172,19 +172,21 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // Build a label if we have it wxStaticText* label=nullptr; if (label_width != 0) { - long label_style = staticbox ? 0 : wxALIGN_RIGHT; -#ifdef __WXGTK__ - // workaround for correct text align of the StaticBox on Linux - // flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given. - // Text is properly aligned only when Ellipsize is checked. - label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; -#endif /* __WXGTK__ */ - label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), - wxDefaultPosition, wxSize(label_width, -1), label_style); - label->SetBackgroundStyle(wxBG_STYLE_PAINT); - label->SetFont(label_font); - label->Wrap(label_width); // avoid a Linux/GTK bug - if (!line.near_label_widget) + if (! line.near_label_widget || ! line.label.IsEmpty()) { + long label_style = staticbox ? 0 : wxALIGN_RIGHT; + #ifdef __WXGTK__ + // workaround for correct text align of the StaticBox on Linux + // flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given. + // Text is properly aligned only when Ellipsize is checked. + label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; + #endif /* __WXGTK__ */ + label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), + wxDefaultPosition, wxSize(label_width, -1), label_style); + label->SetBackgroundStyle(wxBG_STYLE_PAINT); + label->SetFont(label_font); + label->Wrap(label_width); // avoid a Linux/GTK bug + } + if (! line.near_label_widget) grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5); else if (line.near_label_widget && line.label.IsEmpty()) grid_sizer->Add(line.near_label_widget(this->ctrl_parent()), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); @@ -196,7 +198,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n sizer->Add(line.near_label_widget(this->ctrl_parent()), 0, wxRIGHT, 7); sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); } - if (line.label_tooltip.compare("") != 0) + if (label != nullptr && line.label_tooltip != "") label->SetToolTip(line.label_tooltip); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8eb68fc39..b41b27af8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1056,9 +1056,9 @@ void Sidebar::enable_buttons(bool enable) p->btn_send_gcode->Enable(enable); } -void Sidebar::show_reslice(bool show) const { p->btn_reslice->Show(show); } -void Sidebar::show_export(bool show) const { p->btn_export_gcode->Show(show); } -void Sidebar::show_send(bool show) const { p->btn_send_gcode->Show(show); } +bool Sidebar::show_reslice(bool show) const { return p->btn_reslice->Show(show); } +bool Sidebar::show_export(bool show) const { return p->btn_export_gcode->Show(show); } +bool Sidebar::show_send(bool show) const { return p->btn_send_gcode->Show(show); } bool Sidebar::is_multifilament() { @@ -3129,17 +3129,18 @@ void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const // when a background processing is ON, export_btn and/or send_btn are showing if (wxGetApp().app_config->get("background_processing") == "1") { - sidebar->show_reslice(false); - sidebar->show_export(true); - sidebar->show_send(send_gcode_shown); - } + if (sidebar->show_reslice(false) | + sidebar->show_export(true) | + sidebar->show_send(send_gcode_shown)) + sidebar->Layout(); + } else { - sidebar->show_reslice(is_ready_to_slice); - sidebar->show_export(!is_ready_to_slice); - sidebar->show_send(send_gcode_shown && !is_ready_to_slice); - } - sidebar->Layout(); + if (sidebar->show_reslice(is_ready_to_slice) | + sidebar->show_export(!is_ready_to_slice) | + sidebar->show_send(send_gcode_shown && !is_ready_to_slice)) + sidebar->Layout(); + } } void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& label) const diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5319e3b43..f9c5a4d7f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -96,9 +96,9 @@ public: void show_sliced_info_sizer(const bool show); void enable_buttons(bool enable); void set_btn_label(const ActionButtonType btn_type, const wxString& label) const; - void show_reslice(bool show) const; - void show_export(bool show) const; - void show_send(bool show) const; + bool show_reslice(bool show) const; + bool show_export(bool show) const; + bool show_send(bool show) const; bool is_multifilament(); void update_mode(); From f78c3a0f1b02d462c7e7d3d5069d08f1f3aee6b2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 25 Apr 2019 09:24:33 +0200 Subject: [PATCH 03/15] WIP, non-uniform scaling in the world coordinate system: Disable non-uniform scaling when switching to the World coordinate system and the rotation is not multiples of ninety degrees. Ask user whether to bake in the transformations into the meshes if enabling the non-uniform scaling in that case. --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 50 +++++++++++++++++++++++ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 3c569b591..df28d8e07 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -201,6 +201,18 @@ void ObjectManipulation::UpdateAndShow(const bool show) OG_Settings::UpdateAndShow(show); } +static bool is_rotation_ninety_degrees(const Vec3d &rotation) +{ + // Is the angle close to a multiple of 90 degrees? + auto ninety_degrees = [](double a) { + a = fmod(std::abs(a), 0.5 * PI); + if (a > 0.25 * PI) + a = 0.5 * PI - a; + return a < 0.001; + }; + return ninety_degrees(rotation.x()) && ninety_degrees(rotation.y()) && ninety_degrees(rotation.z()); +} + void ObjectManipulation::update_settings_value(const Selection& selection) { m_new_move_label_string = L("Position"); @@ -251,6 +263,18 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_rotate_label_string = L("Rotate"); m_new_scale_label_string = L("Scale"); m_new_enabled = true; + + if (selection.is_single_full_instance() && m_world_coordinates && ! m_uniform_scale) { + // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. + // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + // Is the angle close to a multiple of 90 degrees? + if (! is_rotation_ninety_degrees(volume->get_instance_rotation())) { + // Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling. + m_uniform_scale = true; + m_lock_bnt->SetLock(true); + } + } } else if (selection.is_single_modifier() || selection.is_single_volume()) { @@ -541,5 +565,31 @@ void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) } } +void ObjectManipulation::set_uniform_scaling(const bool new_value) +{ + const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection(); + if (selection.is_single_full_instance() && m_world_coordinates && !new_value) { + // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. + // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + // Is the angle close to a multiple of 90 degrees? + if (! is_rotation_ninety_degrees(volume->get_instance_rotation())) { + // Cannot apply scaling in the world coordinate system. + wxMessageDialog dlg(GUI::wxGetApp().mainframe, + _(L("Non-uniform scaling of tilted objects is not supported in the World coordinate system.\n" + "Do you want to rotate the mesh?")), + SLIC3R_APP_NAME, + wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); + if (dlg.ShowModal() != wxID_YES) { + // Enforce uniform scaling. + m_lock_bnt->SetLock(true); + return; + } + // Bake the rotation into the meshes of the object. + } + } + m_uniform_scale = new_value; +} + } //namespace GUI } //namespace Slic3r diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 09b1b4fe6..5db9622ce 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -103,7 +103,7 @@ public: // Called from the App to update the UI if dirty. void update_if_dirty(); - void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;} + void set_uniform_scaling(const bool uniform_scale); bool get_uniform_scaling() const { return m_uniform_scale; } // Does the object manipulation panel work in World or Local coordinates? void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); } From 6526a8fcafaf2453e5b69ef65409a1bf728b63de Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 26 Apr 2019 17:28:31 +0200 Subject: [PATCH 04/15] WIP: Transformation of instances in world coordinate space: Ulocking the "anisotropic" scaling checkbox will bake the transformation into meshes to allow for scaling in world axes. Optimized and templated the stl_transform functions, now also available for 3x3 matrices. The Canvas3D::reload_scene() now maintains selection even if all volumes of an instance changed their IDs. --- src/admesh/stl.h | 61 ++++++++++++++++- src/admesh/util.cpp | 59 ----------------- src/libslic3r/Geometry.hpp | 15 +++++ src/libslic3r/Model.cpp | 81 +++++++++++++++++++++++ src/libslic3r/Model.hpp | 14 ++++ src/libslic3r/Point.hpp | 5 ++ src/libslic3r/TriangleMesh.cpp | 11 +++ src/libslic3r/TriangleMesh.hpp | 1 + src/slic3r/GUI/3DScene.cpp | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 11 ++- src/slic3r/GUI/GUI_ObjectList.cpp | 9 +-- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 37 +++++------ src/slic3r/GUI/Selection.cpp | 45 ++++++------- src/slic3r/GUI/Selection.hpp | 4 +- 14 files changed, 237 insertions(+), 118 deletions(-) diff --git a/src/admesh/stl.h b/src/admesh/stl.h index d682b2434..63b15986a 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -180,8 +180,65 @@ extern void stl_rotate_z(stl_file *stl, float angle); extern void stl_mirror_xy(stl_file *stl); extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); -extern void stl_transform(stl_file *stl, float *trafo3x4); -extern void stl_transform(stl_file *stl, const Eigen::Transform& t); + +template +extern void stl_transform(stl_file *stl, T *trafo3x4) +{ + if (stl->error) + return; + + for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { + stl_facet &face = stl->facet_start[i_face]; + for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) { + stl_vertex &v_dst = face.vertex[i_vertex]; + stl_vertex v_src = v_dst; + v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3]); + v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]); + v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); + } + stl_vertex &v_dst = face.normal; + stl_vertex v_src = v_dst; + v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2)); + v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2)); + v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2)); + } + + stl_get_size(stl); +} + +template +inline void stl_transform(stl_file *stl, const Eigen::Transform& t) +{ + if (stl->error) + return; + + const Eigen::Matrix r = t.matrix().block<3, 3>(0, 0); + for (size_t i = 0; i < stl->stats.number_of_facets; ++i) { + stl_facet &f = stl->facet_start[i]; + for (size_t j = 0; j < 3; ++j) + f.vertex[j] = (t * f.vertex[j].cast()).cast().eval(); + f.normal = (r * f.normal.cast()).cast().eval(); + } + + stl_get_size(stl); +} + +template +inline void stl_transform(stl_file *stl, const Eigen::Matrix& m) +{ + if (stl->error) + return; + + for (size_t i = 0; i < stl->stats.number_of_facets; ++i) { + stl_facet &f = stl->facet_start[i]; + for (size_t j = 0; j < 3; ++j) + f.vertex[j] = (m * f.vertex[j].cast()).cast().eval(); + f.normal = (m * f.normal.cast()).cast().eval(); + } + + stl_get_size(stl); +} + extern void stl_open_merge(stl_file *stl, char *file); extern void stl_invalidate_shared_vertices(stl_file *stl); extern void stl_generate_shared_vertices(stl_file *stl); diff --git a/src/admesh/util.cpp b/src/admesh/util.cpp index 7cb69bccd..305a58e22 100644 --- a/src/admesh/util.cpp +++ b/src/admesh/util.cpp @@ -137,65 +137,6 @@ static void calculate_normals(stl_file *stl) } } -void stl_transform(stl_file *stl, float *trafo3x4) { - int i_face, i_vertex; - if (stl->error) - return; - for (i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { - stl_vertex *vertices = stl->facet_start[i_face].vertex; - for (i_vertex = 0; i_vertex < 3; ++ i_vertex) { - stl_vertex &v_dst = vertices[i_vertex]; - stl_vertex v_src = v_dst; - v_dst(0) = trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3]; - v_dst(1) = trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]; - v_dst(2) = trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]; - } - } - stl_get_size(stl); - calculate_normals(stl); -} - -void stl_transform(stl_file *stl, const Eigen::Transform& t) -{ - if (stl->error) - return; - - unsigned int vertices_count = 3 * (unsigned int)stl->stats.number_of_facets; - if (vertices_count == 0) - return; - - Eigen::MatrixXf src_vertices(3, vertices_count); - stl_facet* facet_ptr = stl->facet_start; - unsigned int v_id = 0; - while (facet_ptr < stl->facet_start + stl->stats.number_of_facets) - { - for (int i = 0; i < 3; ++i) - { - ::memcpy((void*)src_vertices.col(v_id).data(), (const void*)&facet_ptr->vertex[i], 3 * sizeof(float)); - ++v_id; - } - facet_ptr += 1; - } - - Eigen::MatrixXf dst_vertices(3, vertices_count); - dst_vertices = t.cast() * src_vertices.colwise().homogeneous(); - - facet_ptr = stl->facet_start; - v_id = 0; - while (facet_ptr < stl->facet_start + stl->stats.number_of_facets) - { - for (int i = 0; i < 3; ++i) - { - ::memcpy((void*)&facet_ptr->vertex[i], (const void*)dst_vertices.col(v_id).data(), 3 * sizeof(float)); - ++v_id; - } - facet_ptr += 1; - } - - stl_get_size(stl); - calculate_normals(stl); -} - void stl_rotate_x(stl_file *stl, float angle) { int i; diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 25b849d8c..7b5abd2e5 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -269,6 +269,21 @@ extern Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec // This should only be called if it is known, that the two rotations only differ in rotation around the Z axis. extern double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to); +// Is the angle close to a multiple of 90 degrees? +inline bool is_rotation_ninety_degrees(double a) +{ + a = fmod(std::abs(a), 0.5 * M_PI); + if (a > 0.25 * PI) + a = 0.5 * PI - a; + return a < 0.001; +} + +// Is the angle close to a multiple of 90 degrees? +inline bool is_rotation_ninety_degrees(const Vec3d &rotation) +{ + return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z()); +} + } } #endif diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 37e1f4a1b..3800571f0 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -24,6 +24,19 @@ unsigned int Model::s_auto_extruder_id = 1; size_t ModelBase::s_last_id = 0; +// Unique object / instance ID for the wipe tower. +ModelID wipe_tower_object_id() +{ + static ModelBase mine; + return mine.id(); +} + +ModelID wipe_tower_instance_id() +{ + static ModelBase mine; + return mine.id(); +} + Model& Model::assign_copy(const Model &rhs) { this->copy_id(rhs); @@ -1320,6 +1333,58 @@ void ModelObject::repair() v->mesh.repair(); } +// Support for non-uniform scaling of instances. If an instance is rotated by angles, which are not multiples of ninety degrees, +// then the scaling in world coordinate system is not representable by the Geometry::Transformation structure. +// This situation is solved by baking in the instance transformation into the mesh vertices. +// Rotation and mirroring is being baked in. In case the instance scaling was non-uniform, it is baked in as well. +void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx) +{ + assert(instance_idx < this->instances.size()); + + const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation(); + if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation())) + // nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation. + return; + + bool left_handed = reference_trafo.is_left_handed(); + bool has_mirrorring = ! reference_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.)); + bool uniform_scaling = std::abs(reference_trafo.get_scaling_factor().x() - reference_trafo.get_scaling_factor().y()) < EPSILON && + std::abs(reference_trafo.get_scaling_factor().x() - reference_trafo.get_scaling_factor().z()) < EPSILON; + double new_scaling_factor = uniform_scaling ? reference_trafo.get_scaling_factor().x() : 1.; + + // Adjust the instances. + for (size_t i = 0; i < this->instances.size(); ++ i) { + ModelInstance &model_instance = *this->instances[i]; + model_instance.set_rotation(Vec3d(0., 0., Geometry::rotation_diff_z(reference_trafo.get_rotation(), model_instance.get_rotation()))); + model_instance.set_scaling_factor(Vec3d(new_scaling_factor, new_scaling_factor, new_scaling_factor)); + model_instance.set_mirror(Vec3d(1., 1., 1.)); + } + + // Adjust the meshes. + // Transformation to be applied to the meshes. + Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo.get_matrix(true, false, uniform_scaling, ! has_mirrorring).matrix().block<3, 3>(0, 0); + Transform3d volume_offset_correction = this->instances[instance_idx]->get_transformation().get_matrix().inverse() * reference_trafo.get_matrix(); + for (ModelVolume *model_volume : this->volumes) { + const Geometry::Transformation volume_trafo = model_volume->get_transformation(); + bool volume_left_handed = volume_trafo.is_left_handed(); + bool volume_has_mirrorring = ! volume_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.)); + bool volume_uniform_scaling = std::abs(volume_trafo.get_scaling_factor().x() - volume_trafo.get_scaling_factor().y()) < EPSILON && + std::abs(volume_trafo.get_scaling_factor().x() - volume_trafo.get_scaling_factor().z()) < EPSILON; + double volume_new_scaling_factor = volume_uniform_scaling ? volume_trafo.get_scaling_factor().x() : 1.; + // Transform the mesh. + Matrix3d volume_trafo_3x3 = volume_trafo.get_matrix(true, false, volume_uniform_scaling, !volume_has_mirrorring).matrix().block<3, 3>(0, 0); + model_volume->transform_mesh(mesh_trafo_3x3 * volume_trafo_3x3, left_handed != volume_left_handed); + // Reset the rotation, scaling and mirroring. + model_volume->set_rotation(Vec3d(0., 0., 0.)); + model_volume->set_scaling_factor(Vec3d(volume_new_scaling_factor, volume_new_scaling_factor, volume_new_scaling_factor)); + model_volume->set_mirror(Vec3d(1., 1., 1.)); + // Move the reference point of the volume to compensate for the change of the instance trafo. + model_volume->set_offset(volume_offset_correction * volume_trafo.get_offset()); + } + + this->invalidate_bounding_box(); +} + double ModelObject::get_min_z() const { if (instances.empty()) @@ -1656,6 +1721,22 @@ void ModelVolume::scale_geometry(const Vec3d& versor) m_convex_hull.scale(versor); } +void ModelVolume::transform_mesh(const Transform3d &mesh_trafo, bool fix_left_handed) +{ + this->mesh.transform(mesh_trafo, fix_left_handed); + this->m_convex_hull.transform(mesh_trafo, fix_left_handed); + // Let the rest of the application know that the geometry changed, so the meshes have to be reloaded. + this->set_new_unique_id(); +} + +void ModelVolume::transform_mesh(const Matrix3d &matrix, bool fix_left_handed) +{ + this->mesh.transform(matrix, fix_left_handed); + this->m_convex_hull.transform(matrix, fix_left_handed); + // Let the rest of the application know that the geometry changed, so the meshes have to be reloaded. + this->set_new_unique_id(); +} + void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { mesh->transform(get_matrix(dont_translate)); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 80187d259..c48979e97 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -54,6 +54,10 @@ struct ModelID size_t id; }; +// Unique object / instance ID for the wipe tower. +extern ModelID wipe_tower_object_id(); +extern ModelID wipe_tower_instance_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 ModelBase derived instances @@ -85,6 +89,9 @@ private: 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(); }; #define MODELBASE_DERIVED_COPY_MOVE_CLONE(TYPE) \ @@ -265,6 +272,11 @@ public: ModelObjectPtrs cut(size_t instance, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false); // Note: z is in world coordinates void split(ModelObjectPtrs* new_objects); void repair(); + // Support for non-uniform scaling of instances. If an instance is rotated by angles, which are not multiples of ninety degrees, + // then the scaling in world coordinate system is not representable by the Geometry::Transformation structure. + // This situation is solved by baking in the instance transformation into the mesh vertices. + // Rotation and mirroring is being baked in. In case the instance scaling was non-uniform, it is baked in as well. + void bake_xy_rotation_into_meshes(size_t instance_idx); double get_min_z() const; double get_instance_min_z(size_t instance_idx) const; @@ -414,6 +426,8 @@ protected: explicit ModelVolume(const ModelVolume &rhs) = default; void set_model_object(ModelObject *model_object) { object = model_object; } + void transform_mesh(const Transform3d& t, bool fix_left_handed); + void transform_mesh(const Matrix3d& m, bool fix_left_handed); private: // Parent object owning this ModelVolume. diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index 6b35600cb..b02ead299 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -40,6 +40,11 @@ typedef std::vector Points3; typedef std::vector Pointfs; typedef std::vector Pointf3s; +typedef Eigen::Matrix Matrix2f; +typedef Eigen::Matrix Matrix2d; +typedef Eigen::Matrix Matrix3f; +typedef Eigen::Matrix Matrix3d; + typedef Eigen::Transform Transform2f; typedef Eigen::Transform Transform2d; typedef Eigen::Transform Transform3f; diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index f449ac2b4..04194a0f6 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -330,6 +330,17 @@ void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed) } } +void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed) +{ + stl_transform(&stl, m); + stl_invalidate_shared_vertices(&stl); + if (fix_left_handed && m.determinant() < 0.) { + // Left handed transformation is being applied. It is a good idea to flip the faces and their normals. + this->repair(); + stl_reverse_all_facets(&stl); + } +} + void TriangleMesh::align_to_origin() { this->translate( diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 60ddcca08..c284f6482 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -52,6 +52,7 @@ public: void mirror_y() { this->mirror(Y); } void mirror_z() { this->mirror(Z); } void transform(const Transform3d& t, bool fix_left_handed = false); + void transform(const Matrix3d& t, bool fix_left_handed = false); void align_to_origin(); void rotate(double angle, Point* center); TriangleMeshPtrs split() const; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 9038e388c..bbedc0802 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -716,6 +716,8 @@ int GLVolumeCollection::load_wipe_tower_preview( v.bounding_box = v.indexed_vertex_array.bounding_box(); v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0); + v.geometry_id.first = 0; + v.geometry_id.second = wipe_tower_instance_id().id; v.is_wipe_tower = true; v.shader_outside_printer_detection_enabled = ! size_unknown; return int(this->volumes.size() - 1); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6690e33e3..f8859807f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1770,6 +1770,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // State of the sla_steps for all SLAPrintObjects. std::vector sla_support_state; + std::vector instance_ids_selected; std::vector map_glvolume_old_to_new(m_volumes.volumes.size(), size_t(-1)); std::vector glvolumes_new; glvolumes_new.reserve(m_volumes.volumes.size()); @@ -1834,6 +1835,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (it != model_volume_state.end() && it->geometry_id == key.geometry_id) mvs = &(*it); } + // Emplace instance ID of the volume. Both the aux volumes and model volumes share the same instance ID. + // The wipe tower has its own wipe_tower_instance_id(). + if (m_selection.contains_volume(volume_id)) + instance_ids_selected.emplace_back(volume->geometry_id.second); if (mvs == nullptr || force_full_scene_refresh) { // This GLVolume will be released. if (volume->is_wipe_tower) { @@ -1865,6 +1870,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } } } + sort_remove_duplicates(instance_ids_selected); } if (m_reload_delayed) @@ -2001,7 +2007,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re update_volumes_colors_by_extruder(); // Update selection indices based on the old/new GLVolumeCollection. - m_selection.volumes_changed(map_glvolume_old_to_new); + if (m_selection.get_mode() == Selection::Instance) + m_selection.instances_changed(instance_ids_selected); + else + m_selection.volumes_changed(map_glvolume_old_to_new); } m_gizmos.update_data(*this); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f8ad8b7bb..f65c83abb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1357,19 +1357,12 @@ Geometry::Transformation volume_to_bed_transformation(const Geometry::Transforma { Geometry::Transformation out; - // Is the angle close to a multiple of 90 degrees? - auto ninety_degrees = [](double a) { - a = fmod(std::abs(a), 0.5 * PI); - if (a > 0.25 * PI) - a = 0.5 * PI - a; - return a < 0.001; - }; if (instance_transformation.is_scaling_uniform()) { // No need to run the non-linear least squares fitting for uniform scaling. // Just set the inverse. out.set_from_transform(instance_transformation.get_matrix(true).inverse()); } - else if (ninety_degrees(instance_transformation.get_rotation().x()) && ninety_degrees(instance_transformation.get_rotation().y()) && ninety_degrees(instance_transformation.get_rotation().z())) + else if (Geometry::is_rotation_ninety_degrees(instance_transformation.get_rotation())) { // Anisotropic scaling, rotation by multiples of ninety degrees. Eigen::Matrix3d instance_rotation_trafo = diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index df28d8e07..761f29e98 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -177,15 +177,19 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : void ObjectManipulation::Show(const bool show) { - if (show == IsShown()) - return; + if (show != IsShown()) { + m_og->Show(show); - m_og->Show(show); + if (show && wxGetApp().get_mode() != comSimple) { + m_og->get_grid_sizer()->Show(size_t(0), false); + m_og->get_grid_sizer()->Show(size_t(1), false); + } + } - if (show && wxGetApp().get_mode() != comSimple) { - m_og->get_grid_sizer()->Show(size_t(0), false); - m_og->get_grid_sizer()->Show(size_t(1), false); - } + if (show) { + bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance(); + m_word_local_combo->Show(show_world_local_combo); + } } bool ObjectManipulation::IsShown() @@ -201,18 +205,6 @@ void ObjectManipulation::UpdateAndShow(const bool show) OG_Settings::UpdateAndShow(show); } -static bool is_rotation_ninety_degrees(const Vec3d &rotation) -{ - // Is the angle close to a multiple of 90 degrees? - auto ninety_degrees = [](double a) { - a = fmod(std::abs(a), 0.5 * PI); - if (a > 0.25 * PI) - a = 0.5 * PI - a; - return a < 0.001; - }; - return ninety_degrees(rotation.x()) && ninety_degrees(rotation.y()) && ninety_degrees(rotation.z()); -} - void ObjectManipulation::update_settings_value(const Selection& selection) { m_new_move_label_string = L("Position"); @@ -269,7 +261,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); // Is the angle close to a multiple of 90 degrees? - if (! is_rotation_ninety_degrees(volume->get_instance_rotation())) { + if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { // Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling. m_uniform_scale = true; m_lock_bnt->SetLock(true); @@ -573,7 +565,7 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); // Is the angle close to a multiple of 90 degrees? - if (! is_rotation_ninety_degrees(volume->get_instance_rotation())) { + if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { // Cannot apply scaling in the world coordinate system. wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Non-uniform scaling of tilted objects is not supported in the World coordinate system.\n" @@ -586,6 +578,9 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) return; } // Bake the rotation into the meshes of the object. + (*wxGetApp().model_objects())[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id); + // Update the 3D scene, selections etc. + wxGetApp().plater()->update(); } } m_uniform_scale = new_value; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 7a203fe74..e4912918d 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -310,43 +310,36 @@ void Selection::clear() wxGetApp().obj_manipul()->reset_cache(); } +// Update the selection based on the new instance IDs. +void Selection::instances_changed(const std::vector &instance_ids_selected) +{ + assert(m_valid); + assert(m_mode == Instance); + m_list.clear(); + for (unsigned int volume_idx = 0; volume_idx < (unsigned int)m_volumes->size(); ++ volume_idx) { + const GLVolume *volume = (*m_volumes)[volume_idx]; + auto it = std::lower_bound(instance_ids_selected.begin(), instance_ids_selected.end(), volume->geometry_id.second); + if (it != instance_ids_selected.end() && *it == volume->geometry_id.second) + this->do_add_volume(volume_idx); + } + update_type(); + m_bounding_box_dirty = true; +} + // Update the selection based on the map from old indices to new indices after m_volumes changed. // If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances. void Selection::volumes_changed(const std::vector &map_volume_old_to_new) { assert(m_valid); - - // 1) Update the selection set. + assert(m_mode == Volume); IndicesList list_new; - std::vector> model_instances; - for (unsigned int idx : m_list) { + for (unsigned int idx : m_list) if (map_volume_old_to_new[idx] != size_t(-1)) { unsigned int new_idx = (unsigned int)map_volume_old_to_new[idx]; + assert((*m_volumes)[new_idx]->selected); list_new.insert(new_idx); - if (m_mode == Instance) { - // Save the object_idx / instance_idx pair of selected old volumes, - // so we may add the newly added volumes of the same object_idx / instance_idx pair - // to the selection. - const GLVolume *volume = (*m_volumes)[new_idx]; - model_instances.emplace_back(volume->object_idx(), volume->instance_idx()); - } } - } m_list = std::move(list_new); - - if (!model_instances.empty()) { - // Instance selection mode. Add the newly added volumes of the same object_idx / instance_idx pair - // to the selection. - assert(m_mode == Instance); - sort_remove_duplicates(model_instances); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { - const GLVolume* volume = (*m_volumes)[i]; - for (const std::pair &model_instance : model_instances) - if (volume->object_idx() == model_instance.first && volume->instance_idx() == model_instance.second) - do_add_volume(i); - } - } - update_type(); m_bounding_box_dirty = true; } diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 2a54e9a18..9f9c1c325 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -224,6 +224,8 @@ public: void add_all(); + // Update the selection based on the new instance IDs. + void instances_changed(const std::vector &instance_ids_selected); // Update the selection based on the map from old indices to new indices after m_volumes changed. // If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances. void volumes_changed(const std::vector &map_volume_old_to_new); @@ -245,7 +247,7 @@ public: bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const; - bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); } + bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); } bool requires_uniform_scale() const; // Returns the the object id if the selection is from a single object, otherwise is -1 From e5c97364a4440ad362c2557f05ad6d89fcedc261 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 16:01:52 +0200 Subject: [PATCH 05/15] Fix of anisotropic scaling from the 3D scene. --- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index f55391865..90d6e6c6d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -629,7 +629,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) case Scale: { // Apply new temporary scale factors - TransformationType transformation_type(TransformationType::World_Relative_Joint); + TransformationType transformation_type(TransformationType::Local_Relative_Joint); if (evt.AltDown()) transformation_type.set_independent(); selection.scale(get_scale(), transformation_type); From 6921a04077ae72cb420db8b91dcf5b7dd366433f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 16:02:39 +0200 Subject: [PATCH 06/15] Trying to bind the common accelerators on the object list. --- src/slic3r/GUI/GUI_ObjectList.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index dbe8145f3..4625f572f 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -120,7 +120,7 @@ ObjectList::ObjectList(wxWindow* parent) : #endif //__WXMSW__ }); - Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX +// Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX #ifdef __WXMSW__ GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { @@ -142,9 +142,27 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, [this](wxCommandEvent& e) { last_volume_is_deleted(e.GetInt()); }); #ifdef __WXOSX__ - Bind(wxEVT_KEY_DOWN, &ObjectList::OnChar, this); +// Bind(wxEVT_KEY_DOWN, &ObjectList::OnChar, this); #endif //__WXOSX__ + { + // Accelerators + wxAcceleratorEntry entries[6]; + entries[0].Set(wxACCEL_CTRL, (int) 'C', wxID_COPY); + entries[1].Set(wxACCEL_CTRL, (int) 'X', wxID_CUT); + entries[2].Set(wxACCEL_CTRL, (int) 'V', wxID_PASTE); + entries[3].Set(wxACCEL_CTRL, (int) 'A', wxID_SELECTALL); + entries[4].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE); + entries[5].Set(wxACCEL_NORMAL, WXK_BACK, wxID_DELETE); + wxAcceleratorTable accel(6, entries); + SetAcceleratorTable(accel); + + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); }, wxID_COPY); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); }, wxID_PASTE); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->select_item_all_children(); }, wxID_SELECTALL); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->remove(); }, wxID_DELETE); + } + Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { this->EnsureVisible(this->GetCurrentItem()); e.Skip(); })); } From 8c8f8fd940cdaf2dd12df52949d7ad67c17b5658 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 16:11:39 +0200 Subject: [PATCH 07/15] Fixed compilation on osx --- src/admesh/stl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 63b15986a..07e8b6c3d 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -181,6 +181,8 @@ extern void stl_mirror_xy(stl_file *stl); extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); +extern void stl_get_size(stl_file *stl); + template extern void stl_transform(stl_file *stl, T *trafo3x4) { @@ -271,7 +273,6 @@ extern void stl_read(stl_file *stl, int first_facet, bool first); extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first); extern void stl_reallocate(stl_file *stl); extern void stl_add_facet(stl_file *stl, stl_facet *new_facet); -extern void stl_get_size(stl_file *stl); extern void stl_clear_error(stl_file *stl); extern int stl_get_error(stl_file *stl); From 558bd5d95a448679b8e44c6c2af56962d48d1cc3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 16:42:50 +0200 Subject: [PATCH 08/15] Fixed usage of template method, worked only on non-standard MS compiler. --- src/admesh/stl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 07e8b6c3d..1fe7ab05a 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -214,7 +214,7 @@ inline void stl_transform(stl_file *stl, const Eigen::Transformerror) return; - const Eigen::Matrix r = t.matrix().block<3, 3>(0, 0); + const Eigen::Matrix r = t.matrix().template block<3, 3>(0, 0); for (size_t i = 0; i < stl->stats.number_of_facets; ++i) { stl_facet &f = stl->facet_start[i]; for (size_t j = 0; j < 3; ++j) From bfb9288df6480ec5b0303b86fefbafd847c3a54b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 16:59:31 +0200 Subject: [PATCH 09/15] Yet another template gymnastics --- src/admesh/stl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 1fe7ab05a..f867e197b 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -218,8 +218,8 @@ inline void stl_transform(stl_file *stl, const Eigen::Transformstats.number_of_facets; ++i) { stl_facet &f = stl->facet_start[i]; for (size_t j = 0; j < 3; ++j) - f.vertex[j] = (t * f.vertex[j].cast()).cast().eval(); - f.normal = (r * f.normal.cast()).cast().eval(); + f.vertex[j] = (t * f.vertex[j].template cast()).template cast().eval(); + f.normal = (r * f.normal.template cast()).template cast().eval(); } stl_get_size(stl); @@ -234,8 +234,8 @@ inline void stl_transform(stl_file *stl, const Eigen::Matrixstats.number_of_facets; ++i) { stl_facet &f = stl->facet_start[i]; for (size_t j = 0; j < 3; ++j) - f.vertex[j] = (m * f.vertex[j].cast()).cast().eval(); - f.normal = (m * f.normal.cast()).cast().eval(); + f.vertex[j] = (m * f.vertex[j].template cast()).template cast().eval(); + f.normal = (m * f.normal.template cast()).template cast().eval(); } stl_get_size(stl); From a591bb0f15bc0e1c45517bf0fe791c1ff8927df7 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 17:24:05 +0200 Subject: [PATCH 10/15] Missing forward declaration --- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index b92654742..a66576498 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -6,6 +6,7 @@ #include "GUI_ObjectSettings.hpp" #include "GLCanvas3D.hpp" +class wxBitmapComboBox; class wxStaticText; class LockButton; From 5084d544a246063d315ae9ba000596726b2a7a67 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 29 Apr 2019 18:10:08 +0200 Subject: [PATCH 11/15] Fixed a bug, where std::string and wxString were mixed up. --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 7 +++++-- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index d15779308..010291156 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -301,8 +301,8 @@ void ObjectManipulation::update_if_dirty() if (!m_dirty) return; - auto update_label = [](std::string &label_cache, const std::string &new_label, wxStaticText *widget) { - std::string new_label_localized = _(new_label) + ":"; + auto update_label = [](wxString &label_cache, const std::string &new_label, wxStaticText *widget) { + wxString new_label_localized = _(new_label) + ":"; if (label_cache != new_label_localized) { label_cache = new_label_localized; widget->SetLabel(new_label_localized); @@ -420,6 +420,8 @@ void ObjectManipulation::change_rotation_value(int axis, double value) transformation_type.set_local(); } + //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the rotation vector. + selection.start_dragging(); selection.rotate( (M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation), @@ -490,6 +492,7 @@ void ObjectManipulation::do_scale(const Vec3d &scale) const TransformationType transformation_type(TransformationType::World_Relative_Joint); if (selection.is_single_full_instance() && ! m_world_coordinates) transformation_type.set_local(); + //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the scaling vector. selection.start_dragging(); selection.scale(scaling_factor * 0.01, transformation_type); wxGetApp().plater()->canvas3D()->do_scale(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index a66576498..e93ce1ffb 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -28,9 +28,9 @@ class ObjectManipulation : public OG_Settings Vec3d size; Vec3d size_rounded; - std::string move_label_string; - std::string rotate_label_string; - std::string scale_label_string; + wxString move_label_string; + wxString rotate_label_string; + wxString scale_label_string; struct Instance { @@ -55,9 +55,9 @@ class ObjectManipulation : public OG_Settings rotation = rotation_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); scale = scale_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); size = size_rounded = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - move_label_string = ""; - rotate_label_string = ""; - scale_label_string = ""; + move_label_string = wxString(); + rotate_label_string = wxString(); + scale_label_string = wxString(); instance.reset(); } bool is_valid() const { return position != Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); } From f2bb070ab94b01bd2a0c6b63bd37a8ff800ad4b4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 1 May 2019 11:33:41 +0200 Subject: [PATCH 12/15] Implemented scaling of instances through the object manipulation box for rotated, but still axis aligned coordinate systems. --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 010291156..174879adc 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -420,8 +420,6 @@ void ObjectManipulation::change_rotation_value(int axis, double value) transformation_type.set_local(); } - //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the rotation vector. - selection.start_dragging(); selection.rotate( (M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation), @@ -482,17 +480,27 @@ void ObjectManipulation::do_scale(const Vec3d &scale) const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d scaling_factor = scale; - if (m_uniform_scale || selection.requires_uniform_scale()) - { + TransformationType transformation_type(TransformationType::World_Relative_Joint); + if (selection.is_single_full_instance()) { + if (m_world_coordinates) { + // Only a 90 degree rotation is allowed, therefore an axis aligned scaling will + // be still axis aligned after the instance rotation is applied. + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + scaling_factor = (volume->get_instance_transformation().get_matrix(true, false, true, true) * scale).cwiseAbs(); + // Absolute scaling shall not change. + assert(std::abs(scale.maxCoeff() - scaling_factor.maxCoeff()) < EPSILON); + assert(std::abs(scale.minCoeff() - scaling_factor.minCoeff()) < EPSILON); + assert(std::abs(scale.squaredNorm() - scaling_factor.squaredNorm()) < EPSILON); + } else + transformation_type.set_local(); + } + + if (m_uniform_scale || selection.requires_uniform_scale()) { int max_diff_axis; (scale - m_cache.scale).cwiseAbs().maxCoeff(&max_diff_axis); scaling_factor = scale(max_diff_axis) * Vec3d::Ones(); } - TransformationType transformation_type(TransformationType::World_Relative_Joint); - if (selection.is_single_full_instance() && ! m_world_coordinates) - transformation_type.set_local(); - //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the scaling vector. selection.start_dragging(); selection.scale(scaling_factor * 0.01, transformation_type); wxGetApp().plater()->canvas3D()->do_scale(); From 0ab96ed6b5786eda18b7cceb4f7c695cd61065ee Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 3 May 2019 12:36:26 +0200 Subject: [PATCH 13/15] Changed the "non-uniform scaling is not possible" message. --- src/slic3r/GUI/3DScene.cpp | 19 ++-- src/slic3r/GUI/3DScene.hpp | 3 + src/slic3r/GUI/GLCanvas3D.cpp | 12 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 133 +++++++++------------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 23 +--- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 12 +- src/slic3r/GUI/Selection.cpp | 92 ++++++++++----- src/slic3r/GUI/Selection.hpp | 9 ++ 8 files changed, 150 insertions(+), 153 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index bbedc0802..c5ede9792 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -362,19 +362,18 @@ const BoundingBoxf3& GLVolume::transformed_bounding_box() const const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const { - if (m_transformed_convex_hull_bounding_box_dirty) - { - if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0)) - m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix()); - else - m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix()); - - m_transformed_convex_hull_bounding_box_dirty = false; - } - + if (m_transformed_convex_hull_bounding_box_dirty) + m_transformed_convex_hull_bounding_box = this->transformed_convex_hull_bounding_box(world_matrix()); return m_transformed_convex_hull_bounding_box; } +BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &trafo) const +{ + return (m_convex_hull != nullptr && m_convex_hull->stl.stats.number_of_facets > 0) ? + m_convex_hull->transformed_bounding_box(trafo) : + bounding_box.transformed(trafo); +} + void GLVolume::set_range(double min_z, double max_z) { this->qverts_range.first = 0; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index faf5a745d..191b6a016 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -397,6 +397,9 @@ public: bool is_left_handed() const; const BoundingBoxf3& transformed_bounding_box() const; + // non-caching variant + BoundingBoxf3 transformed_convex_hull_bounding_box(const Transform3d &trafo) const; + // caching variant const BoundingBoxf3& transformed_convex_hull_bounding_box() const; bool empty() const { return this->indexed_vertex_array.empty(); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 79d6b7d2e..09ef2b2ac 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1748,7 +1748,7 @@ void GLCanvas3D::mirror_selection(Axis axis) { m_selection.mirror(axis); do_mirror(); - wxGetApp().obj_manipul()->update_settings_value(m_selection); + wxGetApp().obj_manipul()->set_dirty(); } // Reload the 3D scene of @@ -2091,7 +2091,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // to force a reset of its cache auto manip = wxGetApp().obj_manipul(); if (manip != nullptr) - manip->update_settings_value(m_selection); + manip->set_dirty(); } // and force this canvas to be redrawn. @@ -2726,7 +2726,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_regenerate_volumes = false; m_selection.translate(cur_pos - m_mouse.drag.start_position_3D); - wxGetApp().obj_manipul()->update_settings_value(m_selection); + wxGetApp().obj_manipul()->set_dirty(); m_dirty = true; } @@ -2781,7 +2781,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { m_regenerate_volumes = false; do_move(); - wxGetApp().obj_manipul()->update_settings_value(m_selection); + wxGetApp().obj_manipul()->set_dirty(); // Let the platter know that the dragging finished, so a delayed refresh // of the scene with the background processing data should be performed. post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); @@ -2793,7 +2793,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { m_selection.clear(); m_selection.set_mode(Selection::Instance); - wxGetApp().obj_manipul()->update_settings_value(m_selection); + wxGetApp().obj_manipul()->set_dirty(); m_gizmos.reset_all_states(); m_gizmos.update_data(*this); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); @@ -2817,7 +2817,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_gizmos.refresh_on_off_state(m_selection); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); m_gizmos.update_data(*this); - wxGetApp().obj_manipul()->update_settings_value(m_selection); + wxGetApp().obj_manipul()->set_dirty(); // forces a frame render to update the view before the context menu is shown render(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 174879adc..1da17f676 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -197,8 +197,10 @@ bool ObjectManipulation::IsShown() void ObjectManipulation::UpdateAndShow(const bool show) { - if (show) - update_settings_value(wxGetApp().plater()->canvas3D()->get_selection()); + if (show) { + this->set_dirty(); + this->update_if_dirty(); + } OG_Settings::UpdateAndShow(show); } @@ -210,41 +212,35 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_scale_label_string = L("Scale factors"); ObjectList* obj_list = wxGetApp().obj_list(); - if (selection.is_single_full_instance() && ! m_world_coordinates) + if (selection.is_single_full_instance()) { // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_instance_offset(); - m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); - m_new_scale = volume->get_instance_scaling_factor() * 100.; - int obj_idx = volume->object_idx(); - int instance_idx = volume->instance_idx(); - if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) - { - bool changed_box = false; - //FIXME matching an object idx may not be enough - if (!m_cache.instance.matches_object(obj_idx)) - { - m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size()); - changed_box = true; - } - //FIXME matching an instance idx may not be enough. Check for ModelObject id an all ModelVolume ids. - if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(m_new_scale)) - m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(m_cache.instance.box_size); - } - else { - // this should never happen - assert(false); - m_new_size = Vec3d::Zero(); - } + + // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. + if (m_world_coordinates && ! m_uniform_scale && + ! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { + // Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling. + m_uniform_scale = true; + m_lock_bnt->SetLock(true); + } + + if (m_world_coordinates) { + m_new_rotate_label_string = L("Rotate"); + m_new_rotation = Vec3d::Zero(); + m_new_size = selection.get_bounding_box().size(); + m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.; + } else { + m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); + m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct((*wxGetApp().model_objects())[volume->object_idx()]->raw_mesh_bounding_box().size()); + m_new_scale = volume->get_instance_scaling_factor() * 100.; + } m_new_enabled = true; } - else if ((selection.is_single_full_instance() && m_world_coordinates) || - (selection.is_single_full_object() && obj_list->is_selected(itObject))) + else if (selection.is_single_full_object() && obj_list->is_selected(itObject)) { - m_cache.instance.reset(); - const BoundingBoxf3& box = selection.get_bounding_box(); m_new_position = box.center(); m_new_rotation = Vec3d::Zero(); @@ -253,23 +249,9 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_rotate_label_string = L("Rotate"); m_new_scale_label_string = L("Scale"); m_new_enabled = true; - - if (selection.is_single_full_instance() && m_world_coordinates && ! m_uniform_scale) { - // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. - // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - // Is the angle close to a multiple of 90 degrees? - if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { - // Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling. - m_uniform_scale = true; - m_lock_bnt->SetLock(true); - } - } } else if (selection.is_single_modifier() || selection.is_single_volume()) { - m_cache.instance.reset(); - // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_volume_offset(); @@ -292,15 +274,16 @@ void ObjectManipulation::update_settings_value(const Selection& selection) // assert(selection.is_empty()); reset_settings_value(); } - - m_dirty = true; } void ObjectManipulation::update_if_dirty() { - if (!m_dirty) + if (! m_dirty) return; + const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection(); + this->update_settings_value(selection); + auto update_label = [](wxString &label_cache, const std::string &new_label, wxStaticText *widget) { wxString new_label_localized = _(new_label) + ":"; if (label_cache != new_label_localized) { @@ -330,7 +313,7 @@ void ObjectManipulation::update_if_dirty() update(m_cache.rotation, m_cache.rotation_rounded, "rotation_", m_new_rotation); } - if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) { + if (selection.requires_uniform_scale()) { m_lock_bnt->SetLock(true); m_lock_bnt->Disable(); } @@ -377,8 +360,9 @@ void ObjectManipulation::reset_settings_value() m_new_scale = Vec3d::Ones(); m_new_size = Vec3d::Zero(); m_new_enabled = false; - m_cache.instance.reset(); - m_dirty = true; + // no need to set the dirty flag here as this method is called from update_settings_value(), + // which is called from update_if_dirty(), which resets the dirty flag anyways. +// m_dirty = true; } void ObjectManipulation::change_position_value(int axis, double value) @@ -437,12 +421,9 @@ void ObjectManipulation::change_scale_value(int axis, double value) return; Vec3d scale = m_cache.scale; - scale(axis) = value; + scale(axis) = value; - this->do_scale(scale); - - if (!m_cache.scale.isApprox(scale)) - m_cache.instance.instance_idx = -1; + this->do_scale(axis, scale); m_cache.scale = scale; m_cache.scale_rounded(axis) = DBL_MAX; @@ -460,46 +441,34 @@ void ObjectManipulation::change_size_value(int axis, double value) const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d ref_size = m_cache.size; - if (selection.is_single_volume() || selection.is_single_modifier()) - { - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - ref_size = volume->bounding_box.size(); - } - else if (selection.is_single_full_instance() && ! m_world_coordinates) - ref_size = m_cache.instance.box_size; + if (selection.is_single_volume() || selection.is_single_modifier()) + ref_size = selection.get_volume(*selection.get_volume_idxs().begin())->bounding_box.size(); + else if (selection.is_single_full_instance()) + ref_size = m_world_coordinates ? + selection.get_unscaled_instance_bounding_box().size() : + (*wxGetApp().model_objects())[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size(); - this->do_scale(100. * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); + this->do_scale(axis, 100. * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); m_cache.size = size; m_cache.size_rounded(axis) = DBL_MAX; this->UpdateAndShow(true); } -void ObjectManipulation::do_scale(const Vec3d &scale) const +void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const { Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d scaling_factor = scale; TransformationType transformation_type(TransformationType::World_Relative_Joint); if (selection.is_single_full_instance()) { - if (m_world_coordinates) { - // Only a 90 degree rotation is allowed, therefore an axis aligned scaling will - // be still axis aligned after the instance rotation is applied. - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - scaling_factor = (volume->get_instance_transformation().get_matrix(true, false, true, true) * scale).cwiseAbs(); - // Absolute scaling shall not change. - assert(std::abs(scale.maxCoeff() - scaling_factor.maxCoeff()) < EPSILON); - assert(std::abs(scale.minCoeff() - scaling_factor.minCoeff()) < EPSILON); - assert(std::abs(scale.squaredNorm() - scaling_factor.squaredNorm()) < EPSILON); - } else + transformation_type.set_absolute(); + if (! m_world_coordinates) transformation_type.set_local(); } - if (m_uniform_scale || selection.requires_uniform_scale()) { - int max_diff_axis; - (scale - m_cache.scale).cwiseAbs().maxCoeff(&max_diff_axis); - scaling_factor = scale(max_diff_axis) * Vec3d::Ones(); - } + if (m_uniform_scale || selection.requires_uniform_scale()) + scaling_factor = scale(axis) * Vec3d::Ones(); selection.start_dragging(); selection.scale(scaling_factor * 0.01, transformation_type); @@ -577,8 +546,10 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { // Cannot apply scaling in the world coordinate system. wxMessageDialog dlg(GUI::wxGetApp().mainframe, - _(L("Non-uniform scaling of tilted objects is not supported in the World coordinate system.\n" - "Do you want to rotate the mesh?")), + _(L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n" + "Non-uniform scaling of tilted objects is only possible in the World coordinate system,\n" + "once the rotation is embedded into the object coordinates.\n" + "Do you want to proceed?")), SLIC3R_APP_NAME, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); if (dlg.ShowModal() != wxID_YES) { @@ -590,6 +561,8 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) (*wxGetApp().model_objects())[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id); // Update the 3D scene, selections etc. wxGetApp().plater()->update(); + // Recalculate cached values at this panel, refresh the screen. + this->UpdateAndShow(true); } } m_uniform_scale = new_value; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index e93ce1ffb..833070e03 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -32,22 +32,6 @@ class ObjectManipulation : public OG_Settings wxString rotate_label_string; wxString scale_label_string; - struct Instance - { - int object_idx; - int instance_idx; - Vec3d box_size; - - Instance() { reset(); } - void reset() { this->object_idx = -1; this->instance_idx = -1; this->box_size = Vec3d::Zero(); } - void set(int object_idx, int instance_idx, const Vec3d& box_size) { this->object_idx = object_idx; this->instance_idx = instance_idx; this->box_size = box_size; } - bool matches(int object_idx, int instance_idx) const { return (this->object_idx == object_idx) && (this->instance_idx == instance_idx); } - bool matches_object(int object_idx) const { return (this->object_idx == object_idx); } - bool matches_instance(int instance_idx) const { return (this->instance_idx == instance_idx); } - }; - - Instance instance; - Cache() { reset(); } void reset() { @@ -58,7 +42,6 @@ class ObjectManipulation : public OG_Settings move_label_string = wxString(); rotate_label_string = wxString(); scale_label_string = wxString(); - instance.reset(); } bool is_valid() const { return position != Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); } }; @@ -99,8 +82,7 @@ public: bool IsShown() override; void UpdateAndShow(const bool show) override; - void update_settings_value(const Selection& selection); - + void set_dirty() { m_dirty = true; } // Called from the App to update the UI if dirty. void update_if_dirty(); @@ -120,6 +102,7 @@ public: private: void reset_settings_value(); + void update_settings_value(const Selection& selection); // update size values after scale unit changing or "gizmos" void update_size_value(const Vec3d& size); @@ -131,7 +114,7 @@ private: void change_rotation_value(int axis, double value); void change_scale_value(int axis, double value); void change_size_value(int axis, double value); - void do_scale(const Vec3d &scale) const; + void do_scale(int axis, const Vec3d &scale) const; void on_change(t_config_option_key opt_key, const boost::any& value); void on_fill_empty_value(const std::string& opt_key); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 90d6e6c6d..8e01806f1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -590,7 +590,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) // Rotate the object so the normal points downward: selection.flattening_rotate(get_flattening_normal()); canvas.do_flatten(); - wxGetApp().obj_manipul()->update_settings_value(selection); + wxGetApp().obj_manipul()->set_dirty(); } canvas.set_as_dirty(); @@ -623,17 +623,17 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) { // Apply new temporary offset selection.translate(get_displacement()); - wxGetApp().obj_manipul()->update_settings_value(selection); + wxGetApp().obj_manipul()->set_dirty(); break; } case Scale: { // Apply new temporary scale factors - TransformationType transformation_type(TransformationType::Local_Relative_Joint); + TransformationType transformation_type(TransformationType::Local_Absolute_Joint); if (evt.AltDown()) transformation_type.set_independent(); selection.scale(get_scale(), transformation_type); - wxGetApp().obj_manipul()->update_settings_value(selection); + wxGetApp().obj_manipul()->set_dirty(); break; } case Rotate: @@ -643,7 +643,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) if (evt.AltDown()) transformation_type.set_independent(); selection.rotate(get_rotation(), transformation_type); - wxGetApp().obj_manipul()->update_settings_value(selection); + wxGetApp().obj_manipul()->set_dirty(); break; } default: @@ -680,7 +680,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas) stop_dragging(); update_data(canvas); - wxGetApp().obj_manipul()->update_settings_value(selection); + wxGetApp().obj_manipul()->set_dirty(); // Let the platter know that the dragging finished, so a delayed refresh // of the scene with the background processing data should be performed. canvas.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e4912918d..28cab3eba 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -54,10 +54,10 @@ Selection::Selection() , m_mode(Instance) , m_type(Empty) , m_valid(false) - , m_bounding_box_dirty(true) , m_curved_arrow(16) , m_scale_factor(1.0f) { + this->set_bounding_boxes_dirty(); #if ENABLE_RENDER_SELECTION_CENTER m_quadric = ::gluNewQuadric(); if (m_quadric != nullptr) @@ -148,7 +148,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::remove(unsigned int volume_idx) @@ -173,7 +173,7 @@ void Selection::remove(unsigned int volume_idx) } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::add_object(unsigned int object_idx, bool as_single_selection) @@ -190,7 +190,7 @@ void Selection::add_object(unsigned int object_idx, bool as_single_selection) do_add_object(object_idx); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::remove_object(unsigned int object_idx) @@ -201,7 +201,7 @@ void Selection::remove_object(unsigned int object_idx) do_remove_object(object_idx); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection) @@ -218,7 +218,7 @@ void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, do_add_instance(object_idx, instance_idx); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::remove_instance(unsigned int object_idx, unsigned int instance_idx) @@ -229,7 +229,7 @@ void Selection::remove_instance(unsigned int object_idx, unsigned int instance_i do_remove_instance(object_idx, instance_idx); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection) @@ -254,7 +254,7 @@ void Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, int } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx) @@ -270,7 +270,7 @@ void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx) } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::add_all() @@ -288,7 +288,7 @@ void Selection::add_all() } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::clear() @@ -304,7 +304,7 @@ void Selection::clear() m_list.clear(); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); // resets the cache in the sidebar wxGetApp().obj_manipul()->reset_cache(); @@ -323,7 +323,7 @@ void Selection::instances_changed(const std::vector &instance_ids_select this->do_add_volume(volume_idx); } update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } // Update the selection based on the map from old indices to new indices after m_volumes changed. @@ -341,7 +341,7 @@ void Selection::volumes_changed(const std::vector &map_volume_old_to_new } m_list = std::move(list_new); update_type(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } bool Selection::is_single_full_instance() const @@ -426,6 +426,14 @@ const BoundingBoxf3& Selection::get_bounding_box() const return m_bounding_box; } +const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const +{ + if (m_unscaled_instance_bounding_box_dirty) + calc_unscaled_instance_bounding_box(); + + return m_unscaled_instance_bounding_box; +} + void Selection::start_dragging() { if (!m_valid) @@ -473,7 +481,7 @@ void Selection::translate(const Vec3d& displacement, bool local) synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } // Rotate an object around one of the axes. Only one rotation component is expected to be changing. @@ -580,7 +588,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::flattening_rotate(const Vec3d& normal) @@ -621,7 +629,7 @@ void Selection::flattening_rotate(const Vec3d& normal) synchronize_unselected_instances(SYNC_ROTATION_FULL); #endif // !DISABLE_INSTANCES_SYNCH - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::scale(const Vec3d& scale, TransformationType transformation_type) @@ -629,15 +637,21 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type if (!m_valid) return; - // Only relative scaling values are allowed in the world coordinate system. - assert(! transformation_type.world() || transformation_type.relative()); - for (unsigned int i : m_list) { - if (is_single_full_instance() && ! transformation_type.world()) - (*m_volumes)[i]->set_instance_scaling_factor(scale); + GLVolume &volume = *(*m_volumes)[i]; + if (is_single_full_instance()) { + assert(transformation_type.absolute()); + if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) { + // Non-uniform scaling. Transform the scaling factors into the local coordinate system. + // This is only possible, if the instance rotation is mulitples of ninety degrees. + assert(Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation())); + volume.set_instance_scaling_factor((volume.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs()); + } else + volume.set_instance_scaling_factor(scale); + } else if (is_single_volume() || is_single_modifier()) - (*m_volumes)[i]->set_volume_scaling_factor(scale); + volume.set_volume_scaling_factor(scale); else { Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale); @@ -647,9 +661,9 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); if (transformation_type.joint()) - (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); + volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); - (*m_volumes)[i]->set_instance_scaling_factor(new_scale); + volume.set_instance_scaling_factor(new_scale); } else if (m_mode == Volume) { @@ -659,9 +673,9 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type if (transformation_type.joint()) { Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center); - (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); + volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); } - (*m_volumes)[i]->set_volume_scaling_factor(new_scale); + volume.set_volume_scaling_factor(new_scale); } } } @@ -675,7 +689,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type ensure_on_bed(); - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::mirror(Axis axis) @@ -700,7 +714,7 @@ void Selection::mirror(Axis axis) synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::translate(unsigned int object_idx, const Vec3d& displacement) @@ -745,7 +759,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement) } } - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement) @@ -790,7 +804,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co } } - m_bounding_box_dirty = true; + this->set_bounding_boxes_dirty(); } void Selection::erase() @@ -1396,7 +1410,23 @@ void Selection::calc_bounding_box() const m_bounding_box.merge((*m_volumes)[i]->transformed_convex_hull_bounding_box()); } } - m_bounding_box_dirty = false; + m_bounding_box_dirty = false; +} + +void Selection::calc_unscaled_instance_bounding_box() const +{ + m_unscaled_instance_bounding_box = BoundingBoxf3(); + if (m_valid) + { + for (unsigned int i : m_list) + { + const GLVolume &volume = *(*m_volumes)[i]; + Transform3d trafo = volume.get_instance_transformation().get_matrix(false, false, true, false) * volume.get_volume_transformation().get_matrix(); + trafo.translation()(2) += volume.get_sla_shift_z(); + m_unscaled_instance_bounding_box.merge(volume.transformed_convex_hull_bounding_box(trafo)); + } + } + m_unscaled_instance_bounding_box_dirty = false; } void Selection::render_selected_volumes() const diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 9f9c1c325..d808bee07 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -183,6 +183,10 @@ private: Clipboard m_clipboard; mutable BoundingBoxf3 m_bounding_box; mutable bool m_bounding_box_dirty; + // Bounding box of a selection, with no instance scaling applied. This bounding box + // is useful for absolute scaling of tilted objects in world coordinate space. + mutable BoundingBoxf3 m_unscaled_instance_bounding_box; + mutable bool m_unscaled_instance_bounding_box_dirty; #if ENABLE_RENDER_SELECTION_CENTER GLUquadricObj* m_quadric; @@ -265,6 +269,9 @@ public: unsigned int volumes_count() const { return (unsigned int)m_list.size(); } const BoundingBoxf3& get_bounding_box() const; + // Bounding box of a selection, with no instance scaling applied. This bounding box + // is useful for absolute scaling of tilted objects in world coordinate space. + const BoundingBoxf3& get_unscaled_instance_bounding_box() const; void start_dragging(); @@ -303,6 +310,8 @@ private: void do_remove_instance(unsigned int object_idx, unsigned int instance_idx); void do_remove_object(unsigned int object_idx); void calc_bounding_box() const; + void calc_unscaled_instance_bounding_box() const; + void set_bounding_boxes_dirty() { m_bounding_box_dirty = true; m_unscaled_instance_bounding_box_dirty = true; } void render_selected_volumes() const; void render_synchronized_volumes() const; void render_bounding_box(const BoundingBoxf3& box, float* color) const; From a61e8335365d711be4f1cbe08e02832426cef294 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 3 May 2019 18:01:39 +0200 Subject: [PATCH 14/15] Implemented the "Support for support enforcers only" quick selection. Reduced some memory leaks due to the ConfigDef::default_value pointer. --- src/libslic3r/Config.cpp | 8 +- src/libslic3r/Config.hpp | 10 +- src/libslic3r/PrintConfig.cpp | 590 +++++++++++----------- src/libslic3r/PrintConfig.hpp | 4 +- src/libslic3r/clonable_ptr.hpp | 168 ++++++ src/slic3r/GUI/BedShapeDialog.cpp | 6 +- src/slic3r/GUI/ConfigWizard.cpp | 10 +- src/slic3r/GUI/Field.cpp | 26 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 6 +- src/slic3r/GUI/LambdaObjectDialog.cpp | 8 +- src/slic3r/GUI/Plater.cpp | 41 +- src/slic3r/GUI/Preferences.cpp | 18 +- src/slic3r/GUI/Tab.cpp | 48 +- xs/xsp/Config.xsp | 4 +- 14 files changed, 559 insertions(+), 388 deletions(-) create mode 100644 src/libslic3r/clonable_ptr.hpp diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index a7db29b8e..7273fda01 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -280,7 +280,7 @@ std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, s // right: option description std::string descr = def.tooltip; - if (show_defaults && def.default_value != nullptr && def.type != coBool + if (show_defaults && def.default_value && def.type != coBool && (def.type != coString || !def.default_value->serialize().empty())) { descr += " ("; if (!def.sidetext.empty()) { @@ -627,7 +627,7 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre // Let the parent decide what to do if the opt_key is not defined by this->def(). return nullptr; ConfigOption *opt = nullptr; - if (optdef->default_value != nullptr) { + if (optdef->default_value) { opt = (optdef->default_value->type() == coEnum) ? // Special case: For a DynamicConfig, convert a templated enum to a generic enum. new ConfigOptionEnumGeneric(optdef->enum_keys_map, optdef->default_value->getInt()) : @@ -783,8 +783,8 @@ void StaticConfig::set_defaults() for (const std::string &key : this->keys()) { const ConfigOptionDef *def = defs->get(key); ConfigOption *opt = this->option(key); - if (def != nullptr && opt != nullptr && def->default_value != nullptr) - opt->set(def->default_value); + if (def != nullptr && opt != nullptr && def->default_value) + opt->set(def->default_value.get()); } } } diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 1e5972701..625335de6 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -12,6 +12,7 @@ #include #include #include "libslic3r.h" +#include "clonable_ptr.hpp" #include "Point.hpp" #include @@ -1010,7 +1011,8 @@ public: // What type? bool, int, string etc. ConfigOptionType type = coNone; // Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor. - const ConfigOption *default_value = nullptr; + Slic3r::clonable_ptr default_value = nullptr; + void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr(ptr); } // Usually empty. // Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection, @@ -1099,12 +1101,6 @@ typedef std::map t_optiondef_map; class ConfigDef { public: - ~ConfigDef() { - for (std::pair &def : this->options) - delete def.second.default_value; - this->options.clear(); - } - t_optiondef_map options; bool has(const t_config_option_key &opt_key) const { return this->options.count(opt_key) > 0; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3e1fc5c3d..f9936530e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -44,12 +44,12 @@ void PrintConfigDef::init_common_params() def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("FFF"); def->enum_values.push_back("SLA"); - def->default_value = new ConfigOptionEnum(ptFFF); + def->set_default_value(new ConfigOptionEnum(ptFFF)); def = this->add("bed_shape", coPoints); def->label = L("Bed shape"); def->mode = comAdvanced; - def->default_value = new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }; + def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }); def = this->add("layer_height", coFloat); def->label = L("Layer height"); @@ -58,14 +58,14 @@ void PrintConfigDef::init_common_params() "Thinner layers give better accuracy but take more time to print."); def->sidetext = L("mm"); def->min = 0; - def->default_value = new ConfigOptionFloat(0.3); + def->set_default_value(new ConfigOptionFloat(0.3)); def = this->add("max_print_height", coFloat); def->label = L("Max print height"); def->tooltip = L("Set this to the maximum height that can be reached by your extruder while printing."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(200.0); + def->set_default_value(new ConfigOptionFloat(200.0)); def = this->add("slice_closing_radius", coFloat); def->label = L("Slice gap closing radius"); @@ -75,28 +75,28 @@ void PrintConfigDef::init_common_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0.049); + def->set_default_value(new ConfigOptionFloat(0.049)); def = this->add("print_host", coString); def->label = L("Hostname, IP or URL"); def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the hostname, IP address or URL of the printer host instance."); def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("printhost_apikey", coString); def->label = L("API Key / Password"); def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the API Key or the password required for authentication."); def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("printhost_cafile", coString); def->label = "HTTPS CA File"; def->tooltip = "Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. " "If left blank, the default OS CA certificate repository is used."; def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); } void PrintConfigDef::init_fff_params() @@ -113,7 +113,7 @@ void PrintConfigDef::init_fff_params() "This is mostly useful with Bowden extruders which suffer from oozing. " "This feature slows down both the print and the G-code generation."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("bed_temperature", coInts); def->label = L("Other layers"); @@ -122,7 +122,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Bed temperature"); def->min = 0; def->max = 300; - def->default_value = new ConfigOptionInts { 0 }; + def->set_default_value(new ConfigOptionInts { 0 }); def = this->add("before_layer_gcode", coString); def->label = L("Before layer change G-code"); @@ -133,7 +133,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 5; def->mode = comExpert; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("between_objects_gcode", coString); def->label = L("Between objects G-code"); @@ -142,7 +142,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 12; def->mode = comExpert; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("bottom_solid_layers", coInt); def->label = L("Bottom"); @@ -150,7 +150,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Number of solid layers to generate on bottom surfaces."); def->full_label = L("Bottom solid layers"); def->min = 0; - def->default_value = new ConfigOptionInt(3); + def->set_default_value(new ConfigOptionInt(3)); def = this->add("bridge_acceleration", coFloat); def->label = L("Bridge"); @@ -159,7 +159,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("bridge_angle", coFloat); def->label = L("Bridging angle"); @@ -170,7 +170,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("°"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0.); + def->set_default_value(new ConfigOptionFloat(0.)); def = this->add("bridge_fan_speed", coInts); def->label = L("Bridges fan speed"); @@ -179,7 +179,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 100 }; + def->set_default_value(new ConfigOptionInts { 100 }); def = this->add("bridge_flow_ratio", coFloat); def->label = L("Bridge flow ratio"); @@ -191,7 +191,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 2; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(1); + def->set_default_value(new ConfigOptionFloat(1)); def = this->add("bridge_speed", coFloat); def->label = L("Bridges"); @@ -201,7 +201,7 @@ void PrintConfigDef::init_fff_params() def->aliases = { "bridge_feed_rate" }; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(60); + def->set_default_value(new ConfigOptionFloat(60)); def = this->add("brim_width", coFloat); def->label = L("Brim width"); @@ -209,7 +209,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comSimple; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("clip_multipart_objects", coBool); def->label = L("Clip multi-part objects"); @@ -217,17 +217,17 @@ void PrintConfigDef::init_fff_params() "to clip the overlapping object parts one by the other " "(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc)."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("colorprint_heights", coFloats); def->label = L("Colorprint height"); def->tooltip = L("Heights at which a filament change is to occur. "); - def->default_value = new ConfigOptionFloats { }; + def->set_default_value(new ConfigOptionFloats { }); def = this->add("compatible_printers", coStrings); def->label = L("Compatible printers"); def->mode = comAdvanced; - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("compatible_printers_condition", coString); @@ -236,13 +236,13 @@ void PrintConfigDef::init_fff_params() "If this expression evaluates to true, this profile is considered compatible " "with the active printer profile."); def->mode = comExpert; - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("compatible_prints", coStrings); def->label = L("Compatible print profiles"); def->mode = comAdvanced; - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("compatible_prints_condition", coString); @@ -251,16 +251,16 @@ void PrintConfigDef::init_fff_params() "If this expression evaluates to true, this profile is considered compatible " "with the active print profile."); def->mode = comExpert; - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; // The following value is to be stored into the project file (AMF, 3MF, Config ...) // and it contains a sum of "compatible_printers_condition" values over the print and filament profiles. def = this->add("compatible_printers_condition_cummulative", coStrings); - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("compatible_prints_condition_cummulative", coStrings); - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("complete_objects", coBool); @@ -270,13 +270,13 @@ void PrintConfigDef::init_fff_params() "This feature is useful to avoid the risk of ruined prints. " "Slic3r should warn and prevent you from extruder collisions, but beware."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("cooling", coBools); def->label = L("Enable auto cooling"); def->tooltip = L("This flag enables the automatic cooling logic that adjusts print speed " "and fan speed according to layer printing time."); - def->default_value = new ConfigOptionBools { true }; + def->set_default_value(new ConfigOptionBools { true }); def = this->add("cooling_tube_retraction", coFloat); def->label = L("Cooling tube position"); @@ -284,7 +284,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(91.5f); + def->set_default_value(new ConfigOptionFloat(91.5f)); def = this->add("cooling_tube_length", coFloat); def->label = L("Cooling tube length"); @@ -292,7 +292,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(5.f); + def->set_default_value(new ConfigOptionFloat(5.f)); def = this->add("default_acceleration", coFloat); def->label = L("Default"); @@ -302,20 +302,20 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("default_filament_profile", coStrings); def->label = L("Default filament profile"); def->tooltip = L("Default filament profile associated with the current printer profile. " "On selection of the current printer profile, this filament profile will be activated."); - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("default_print_profile", coString); def->label = L("Default print profile"); def->tooltip = L("Default print profile associated with the current printer profile. " "On selection of the current printer profile, this print profile will be activated."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("disable_fan_first_layers", coInts); @@ -326,7 +326,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 1000; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 3 }; + def->set_default_value(new ConfigOptionInts { 3 }); def = this->add("dont_support_bridges", coBool); def->label = L("Don't support bridges"); @@ -334,7 +334,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option for preventing support material from being generated " "under bridged areas."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("duplicate_distance", coFloat); def->label = L("Distance between copies"); @@ -342,7 +342,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->aliases = { "multiply_distance" }; def->min = 0; - def->default_value = new ConfigOptionFloat(6); + def->set_default_value(new ConfigOptionFloat(6)); def = this->add("elefant_foot_compensation", coFloat); def->label = L("Elephant foot compensation"); @@ -352,7 +352,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("end_gcode", coString); def->label = L("End G-code"); @@ -362,7 +362,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 12; def->mode = comExpert; - def->default_value = new ConfigOptionString("M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n"); + def->set_default_value(new ConfigOptionString("M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n")); def = this->add("end_filament_gcode", coStrings); def->label = L("End G-code"); @@ -373,7 +373,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 120; def->mode = comExpert; - def->default_value = new ConfigOptionStrings { "; Filament-specific end gcode \n;END gcode for filament\n" }; + def->set_default_value(new ConfigOptionStrings { "; Filament-specific end gcode \n;END gcode for filament\n" }); def = this->add("ensure_vertical_shell_thickness", coBool); def->label = L("Ensure vertical shell thickness"); @@ -381,7 +381,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Add solid infill near sloping surfaces to guarantee the vertical shell thickness " "(top+bottom solid layers)."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); auto def_top_fill_pattern = def = this->add("top_fill_pattern", coEnum); def->label = L("Top fill pattern"); @@ -401,14 +401,14 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Octagram Spiral")); // solid_fill_pattern is an obsolete equivalent to top_fill_pattern/bottom_fill_pattern. def->aliases = { "solid_fill_pattern", "external_fill_pattern" }; - def->default_value = new ConfigOptionEnum(ipRectilinear); + def->set_default_value(new ConfigOptionEnum(ipRectilinear)); def = this->add("bottom_fill_pattern", coEnum); *def = *def_top_fill_pattern; def->label = L("Bottom fill pattern"); def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells."); def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern"; - def->default_value = new ConfigOptionEnum(ipRectilinear); + def->set_default_value(new ConfigOptionEnum(ipRectilinear)); def = this->add("external_perimeter_extrusion_width", coFloatOrPercent); def->label = L("External perimeters"); @@ -418,7 +418,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 200%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("external_perimeter_speed", coFloatOrPercent); def->label = L("External perimeters"); @@ -430,7 +430,7 @@ void PrintConfigDef::init_fff_params() def->ratio_over = "perimeter_speed"; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(50, true); + def->set_default_value(new ConfigOptionFloatOrPercent(50, true)); def = this->add("external_perimeters_first", coBool); def->label = L("External perimeters first"); @@ -438,7 +438,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Print contour perimeters from the outermost one to the innermost one " "instead of the default inverse order."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("extra_perimeters", coBool); def->label = L("Extra perimeters if needed"); @@ -447,7 +447,7 @@ void PrintConfigDef::init_fff_params() "Slic3r keeps adding perimeters, until more than 70% of the loop immediately above " "is supported."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("extruder", coInt); def->gui_type = "i_enum_open"; @@ -472,7 +472,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(20); + def->set_default_value(new ConfigOptionFloat(20)); def = this->add("extruder_clearance_radius", coFloat); def->label = L("Radius"); @@ -483,14 +483,14 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(20); + def->set_default_value(new ConfigOptionFloat(20)); def = this->add("extruder_colour", coStrings); def->label = L("Extruder Color"); def->tooltip = L("This is only used in the Slic3r interface as a visual help."); def->gui_type = "color"; // Empty string means no color assigned yet. - def->default_value = new ConfigOptionStrings { "" }; + def->set_default_value(new ConfigOptionStrings { "" }); def = this->add("extruder_offset", coPoints); def->label = L("Extruder offset"); @@ -500,13 +500,13 @@ void PrintConfigDef::init_fff_params() "from the XY coordinate)."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionPoints { Vec2d(0,0) }; + def->set_default_value(new ConfigOptionPoints { Vec2d(0,0) }); def = this->add("extrusion_axis", coString); def->label = L("Extrusion axis"); def->tooltip = L("Use this option to set the axis letter associated to your printer's extruder " "(usually E but some printers use A)."); - def->default_value = new ConfigOptionString("E"); + def->set_default_value(new ConfigOptionString("E")); def = this->add("extrusion_multiplier", coFloats); def->label = L("Extrusion multiplier"); @@ -515,7 +515,7 @@ void PrintConfigDef::init_fff_params() "Usual values are between 0.9 and 1.1. If you think you need to change this more, " "check filament diameter and your firmware E steps."); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 1. }; + def->set_default_value(new ConfigOptionFloats { 1. }); def = this->add("extrusion_width", coFloatOrPercent); def->label = L("Default extrusion width"); @@ -526,13 +526,13 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example: 230%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for auto)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("fan_always_on", coBools); def->label = L("Keep fan always on"); def->tooltip = L("If this is enabled, fan will never be disabled and will be kept running at least " "at its minimum speed. Useful for PLA, harmful for ABS."); - def->default_value = new ConfigOptionBools { false }; + def->set_default_value(new ConfigOptionBools { false }); def = this->add("fan_below_layer_time", coInts); def->label = L("Enable fan if layer print time is below"); @@ -543,13 +543,13 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 1000; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 60 }; + def->set_default_value(new ConfigOptionInts { 60 }); def = this->add("filament_colour", coStrings); def->label = L("Color"); def->tooltip = L("This is only used in the Slic3r interface as a visual help."); def->gui_type = "color"; - def->default_value = new ConfigOptionStrings { "#29B2B2" }; + def->set_default_value(new ConfigOptionStrings { "#29B2B2" }); def = this->add("filament_notes", coStrings); def->label = L("Filament notes"); @@ -558,7 +558,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 13; def->mode = comAdvanced; - def->default_value = new ConfigOptionStrings { "" }; + def->set_default_value(new ConfigOptionStrings { "" }); def = this->add("filament_max_volumetric_speed", coFloats); def->label = L("Max volumetric speed"); @@ -568,7 +568,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("filament_loading_speed", coFloats); def->label = L("Loading speed"); @@ -576,7 +576,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 28. }; + def->set_default_value(new ConfigOptionFloats { 28. }); def = this->add("filament_loading_speed_start", coFloats); def->label = L("Loading speed at the start"); @@ -584,7 +584,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 3. }; + def->set_default_value(new ConfigOptionFloats { 3. }); def = this->add("filament_unloading_speed", coFloats); def->label = L("Unloading speed"); @@ -593,7 +593,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 90. }; + def->set_default_value(new ConfigOptionFloats { 90. }); def = this->add("filament_unloading_speed_start", coFloats); def->label = L("Unloading speed at the start"); @@ -601,7 +601,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 100. }; + def->set_default_value(new ConfigOptionFloats { 100. }); def = this->add("filament_toolchange_delay", coFloats); def->label = L("Delay after unloading"); @@ -611,7 +611,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("filament_cooling_moves", coInts); def->label = L("Number of cooling moves"); @@ -620,7 +620,7 @@ void PrintConfigDef::init_fff_params() def->max = 0; def->max = 20; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 4 }; + def->set_default_value(new ConfigOptionInts { 4 }); def = this->add("filament_cooling_initial_speed", coFloats); def->label = L("Speed of the first cooling move"); @@ -628,7 +628,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 2.2f }; + def->set_default_value(new ConfigOptionFloats { 2.2f }); def = this->add("filament_minimal_purge_on_wipe_tower", coFloats); def->label = L("Minimal purge on wipe tower"); @@ -639,7 +639,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 15.f }; + def->set_default_value(new ConfigOptionFloats { 15.f }); def = this->add("filament_cooling_final_speed", coFloats); def->label = L("Speed of the last cooling move"); @@ -647,7 +647,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 3.4f }; + def->set_default_value(new ConfigOptionFloats { 3.4f }); def = this->add("filament_load_time", coFloats); def->label = L("Filament load time"); @@ -655,14 +655,14 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 0.0f }; + def->set_default_value(new ConfigOptionFloats { 0.0f }); def = this->add("filament_ramming_parameters", coStrings); def->label = L("Ramming parameters"); def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters "); def->mode = comExpert; - def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|" - " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }; + def->set_default_value(new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|" + " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }); def = this->add("filament_unload_time", coFloats); def->label = L("Filament unload time"); @@ -670,7 +670,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 0.0f }; + def->set_default_value(new ConfigOptionFloats { 0.0f }); def = this->add("filament_diameter", coFloats); def->label = L("Diameter"); @@ -678,7 +678,7 @@ void PrintConfigDef::init_fff_params() "and do multiple measurements along the filament, then compute the average."); def->sidetext = L("mm"); def->min = 0; - def->default_value = new ConfigOptionFloats { 3. }; + def->set_default_value(new ConfigOptionFloats { 3. }); def = this->add("filament_density", coFloats); def->label = L("Density"); @@ -687,7 +687,7 @@ void PrintConfigDef::init_fff_params() "of the length to volume. Better is to calculate the volume directly through displacement."); def->sidetext = L("g/cm³"); def->min = 0; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("filament_type", coStrings); def->label = L("Filament type"); @@ -704,23 +704,23 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("NGEN"); def->enum_values.push_back("PVA"); def->mode = comAdvanced; - def->default_value = new ConfigOptionStrings { "PLA" }; + def->set_default_value(new ConfigOptionStrings { "PLA" }); def = this->add("filament_soluble", coBools); def->label = L("Soluble material"); def->tooltip = L("Soluble material is most likely used for a soluble support."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBools { false }; + def->set_default_value(new ConfigOptionBools { false }); def = this->add("filament_cost", coFloats); def->label = L("Cost"); def->tooltip = L("Enter your filament cost per kg here. This is only for statistical information."); def->sidetext = L("money/kg"); def->min = 0; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("filament_settings_id", coStrings); - def->default_value = new ConfigOptionStrings { "" }; + def->set_default_value(new ConfigOptionStrings { "" }); def->cli = ConfigOptionDef::nocli; def = this->add("fill_angle", coFloat); @@ -733,7 +733,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 360; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(45); + def->set_default_value(new ConfigOptionFloat(45)); def = this->add("fill_density", coPercent); def->gui_type = "f_enum_open"; @@ -772,7 +772,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back("80%"); def->enum_labels.push_back("90%"); def->enum_labels.push_back("100%"); - def->default_value = new ConfigOptionPercent(20); + def->set_default_value(new ConfigOptionPercent(20)); def = this->add("fill_pattern", coEnum); def->label = L("Fill pattern"); @@ -805,7 +805,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Hilbert Curve")); def->enum_labels.push_back(L("Archimedean Chords")); def->enum_labels.push_back(L("Octagram Spiral")); - def->default_value = new ConfigOptionEnum(ipStars); + def->set_default_value(new ConfigOptionEnum(ipStars)); def = this->add("first_layer_acceleration", coFloat); def->label = L("First layer"); @@ -814,7 +814,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("first_layer_bed_temperature", coInts); def->label = L("First layer"); @@ -822,7 +822,7 @@ void PrintConfigDef::init_fff_params() "bed temperature control commands in the output."); def->max = 0; def->max = 300; - def->default_value = new ConfigOptionInts { 0 }; + def->set_default_value(new ConfigOptionInts { 0 }); def = this->add("first_layer_extrusion_width", coFloatOrPercent); def->label = L("First layer"); @@ -834,7 +834,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->ratio_over = "first_layer_height"; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(200, true); + def->set_default_value(new ConfigOptionFloatOrPercent(200, true)); def = this->add("first_layer_height", coFloatOrPercent); def->label = L("First layer height"); @@ -845,7 +845,7 @@ void PrintConfigDef::init_fff_params() "over the default layer height."); def->sidetext = L("mm or %"); def->ratio_over = "layer_height"; - def->default_value = new ConfigOptionFloatOrPercent(0.35, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0.35, false)); def = this->add("first_layer_speed", coFloatOrPercent); def->label = L("First layer speed"); @@ -855,7 +855,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s or %"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(30, false); + def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); def = this->add("first_layer_temperature", coInts); def->label = L("First layer"); @@ -863,7 +863,7 @@ void PrintConfigDef::init_fff_params() "during print, set this to zero to disable temperature control commands in the output file."); def->min = 0; def->max = max_temp; - def->default_value = new ConfigOptionInts { 200 }; + def->set_default_value(new ConfigOptionInts { 200 }); def = this->add("gap_fill_speed", coFloat); def->label = L("Gap fill"); @@ -873,7 +873,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(20); + def->set_default_value(new ConfigOptionFloat(20)); def = this->add("gcode_comments", coBool); def->label = L("Verbose G-code"); @@ -881,7 +881,7 @@ void PrintConfigDef::init_fff_params() "If you print from SD card, the additional weight of the file could make your firmware " "slow down."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(0); + def->set_default_value(new ConfigOptionBool(0)); def = this->add("gcode_flavor", coEnum); def->label = L("G-code flavor"); @@ -910,7 +910,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back("Smoothie"); def->enum_labels.push_back(L("No extrusion")); def->mode = comExpert; - def->default_value = new ConfigOptionEnum(gcfRepRap); + def->set_default_value(new ConfigOptionEnum(gcfRepRap)); def = this->add("gcode_label_objects", coBool); def->label = "Label objects"; @@ -918,7 +918,7 @@ void PrintConfigDef::init_fff_params() " which is useful for the Octoprint CancelObject plugin. This settings is NOT compatible with " "Single Extruder Multi Material setup and Wipe into Object / Wipe into Infill."; def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(0); + def->set_default_value(new ConfigOptionBool(0)); def = this->add("high_current_on_filament_swap", coBool); def->label = L("High extruder current on filament swap"); @@ -926,7 +926,7 @@ void PrintConfigDef::init_fff_params() " sequence to allow for rapid ramming feed rates and to overcome resistance when loading" " a filament with an ugly shaped tip."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(0); + def->set_default_value(new ConfigOptionBool(0)); def = this->add("infill_acceleration", coFloat); def->label = L("Infill"); @@ -935,7 +935,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("infill_every_layers", coInt); def->label = L("Combine infill every"); @@ -946,7 +946,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Combine infill every n layers"); def->min = 1; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("infill_extruder", coInt); def->label = L("Infill extruder"); @@ -954,7 +954,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing infill."); def->min = 1; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("infill_extrusion_width", coFloatOrPercent); def->label = L("Infill"); @@ -965,13 +965,13 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("infill_first", coBool); def->label = L("Infill before perimeters"); def->tooltip = L("This option will switch the print order of perimeters and infill, making the latter first."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("infill_only_where_needed", coBool); def->label = L("Only infill where needed"); @@ -980,7 +980,7 @@ void PrintConfigDef::init_fff_params() "(it will act as internal support material). If enabled, slows down the G-code generation " "due to the multiple checks involved."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("infill_overlap", coFloatOrPercent); def->label = L("Infill/perimeters overlap"); @@ -991,7 +991,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or %"); def->ratio_over = "perimeter_extrusion_width"; def->mode = comExpert; - def->default_value = new ConfigOptionFloatOrPercent(25, true); + def->set_default_value(new ConfigOptionFloatOrPercent(25, true)); def = this->add("infill_speed", coFloat); def->label = L("Infill"); @@ -1001,20 +1001,20 @@ void PrintConfigDef::init_fff_params() def->aliases = { "print_feed_rate", "infill_feed_rate" }; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(80); + def->set_default_value(new ConfigOptionFloat(80)); def = this->add("inherits", coString); def->label = L("Inherits profile"); def->tooltip = L("Name of the profile, from which this profile inherits."); def->full_width = true; def->height = 5; - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; // The following value is to be stored into the project file (AMF, 3MF, Config ...) // and it contains a sum of "inherits" values over the print and filament profiles. def = this->add("inherits_cummulative", coStrings); - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; def = this->add("interface_shells", coBool); @@ -1024,7 +1024,7 @@ void PrintConfigDef::init_fff_params() "support material."); def->category = L("Layers and Perimeters"); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("layer_gcode", coString); def->label = L("After layer change G-code"); @@ -1036,7 +1036,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 5; def->mode = comExpert; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("remaining_times", coBool); def->label = L("Supports remaining times"); @@ -1045,13 +1045,13 @@ void PrintConfigDef::init_fff_params() " As of now only the Prusa i3 MK3 firmware recognizes M73." " Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("silent_mode", coBool); def->label = L("Supports silent mode"); def->tooltip = L("Set silent mode for the G-code flavor"); def->mode = comExpert; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); const int machine_limits_opt_width = 7; { @@ -1079,7 +1079,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats(axis.max_feedrate); + def->set_default_value(new ConfigOptionFloats(axis.max_feedrate)); // Add the machine acceleration limits for XYZE axes (M201) def = this->add("machine_max_acceleration_" + axis.name, coFloats); def->full_label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str(); @@ -1089,7 +1089,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats(axis.max_acceleration); + def->set_default_value(new ConfigOptionFloats(axis.max_acceleration)); // Add the machine jerk limits for XYZE axes (M205) def = this->add("machine_max_jerk_" + axis.name, coFloats); def->full_label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str(); @@ -1099,7 +1099,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats(axis.max_jerk); + def->set_default_value(new ConfigOptionFloats(axis.max_jerk)); } } @@ -1112,7 +1112,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats{ 0., 0. }; + def->set_default_value(new ConfigOptionFloats{ 0., 0. }); // M205 T... [mm/sec] def = this->add("machine_min_travel_rate", coFloats); @@ -1123,7 +1123,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats{ 0., 0. }; + def->set_default_value(new ConfigOptionFloats{ 0., 0. }); // M204 S... [mm/sec^2] def = this->add("machine_max_acceleration_extruding", coFloats); @@ -1134,7 +1134,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats{ 1500., 1250. }; + def->set_default_value(new ConfigOptionFloats{ 1500., 1250. }); // M204 T... [mm/sec^2] def = this->add("machine_max_acceleration_retracting", coFloats); @@ -1145,7 +1145,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->width = machine_limits_opt_width; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats{ 1500., 1250. }; + def->set_default_value(new ConfigOptionFloats{ 1500., 1250. }); def = this->add("max_fan_speed", coInts); def->label = L("Max"); @@ -1154,7 +1154,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 100 }; + def->set_default_value(new ConfigOptionInts { 100 }); def = this->add("max_layer_height", coFloats); def->label = L("Max"); @@ -1165,7 +1165,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("max_print_speed", coFloat); def->label = L("Max print speed"); @@ -1175,7 +1175,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 1; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(80); + def->set_default_value(new ConfigOptionFloat(80)); def = this->add("max_volumetric_speed", coFloat); def->label = L("Max volumetric speed"); @@ -1184,7 +1184,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); #ifdef HAS_PRESSURE_EQUALIZER def = this->add("max_volumetric_extrusion_rate_slope_positive", coFloat); @@ -1196,7 +1196,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("max_volumetric_extrusion_rate_slope_negative", coFloat); def->label = L("Max volumetric slope negative"); @@ -1207,7 +1207,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); #endif /* HAS_PRESSURE_EQUALIZER */ def = this->add("min_fan_speed", coInts); @@ -1217,7 +1217,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 35 }; + def->set_default_value(new ConfigOptionInts { 35 }); def = this->add("min_layer_height", coFloats); def->label = L("Min"); @@ -1226,7 +1226,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0.07 }; + def->set_default_value(new ConfigOptionFloats { 0.07 }); def = this->add("min_print_speed", coFloats); def->label = L("Min print speed"); @@ -1234,7 +1234,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 10. }; + def->set_default_value(new ConfigOptionFloats { 10. }); def = this->add("min_skirt_length", coFloat); def->label = L("Minimal filament extrusion length"); @@ -1244,7 +1244,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("notes", coString); def->label = L("Configuration notes"); @@ -1254,13 +1254,13 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 13; def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("nozzle_diameter", coFloats); def->label = L("Nozzle diameter"); def->tooltip = L("This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)"); def->sidetext = L("mm"); - def->default_value = new ConfigOptionFloats { 0.5 }; + def->set_default_value(new ConfigOptionFloats { 0.5 }); def = this->add("host_type", coEnum); def->label = L("Host Type"); @@ -1272,14 +1272,14 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back("OctoPrint"); def->enum_labels.push_back("Duet"); def->mode = comAdvanced; - def->default_value = new ConfigOptionEnum(htOctoPrint); + def->set_default_value(new ConfigOptionEnum(htOctoPrint)); def = this->add("only_retract_when_crossing_perimeters", coBool); def->label = L("Only retract when crossing perimeters"); def->tooltip = L("Disables retraction when the travel path does not exceed the upper layer's perimeters " "(and thus any ooze will be probably invisible)."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("ooze_prevention", coBool); def->label = L("Enable"); @@ -1287,7 +1287,7 @@ void PrintConfigDef::init_fff_params() "It will enable a tall skirt automatically and move extruders outside such " "skirt when changing temperatures."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("output_filename_format", coString); def->label = L("Output filename format"); @@ -1297,7 +1297,7 @@ void PrintConfigDef::init_fff_params() "[input_filename_base]."); def->full_width = true; def->mode = comExpert; - def->default_value = new ConfigOptionString("[input_filename_base]"); + def->set_default_value(new ConfigOptionString("[input_filename_base]")); def = this->add("overhangs", coBool); def->label = L("Detect bridging perimeters"); @@ -1305,7 +1305,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option to adjust flow for overhangs (bridge flow will be used), " "to apply bridge speed to them and enable fan."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("parking_pos_retraction", coFloat); def->label = L("Filament parking position"); @@ -1314,7 +1314,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(92.f); + def->set_default_value(new ConfigOptionFloat(92.f)); def = this->add("extra_loading_move", coFloat); def->label = L("Extra loading distance"); @@ -1323,7 +1323,7 @@ void PrintConfigDef::init_fff_params() " if negative, the loading move is shorter than unloading. "); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(-2.f); + def->set_default_value(new ConfigOptionFloat(-2.f)); def = this->add("perimeter_acceleration", coFloat); def->label = L("Perimeters"); @@ -1332,7 +1332,7 @@ void PrintConfigDef::init_fff_params() "Set zero to disable acceleration control for perimeters."); def->sidetext = L("mm/s²"); def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("perimeter_extruder", coInt); def->label = L("Perimeter extruder"); @@ -1341,7 +1341,7 @@ void PrintConfigDef::init_fff_params() def->aliases = { "perimeters_extruder" }; def->min = 1; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("perimeter_extrusion_width", coFloatOrPercent); def->label = L("Perimeters"); @@ -1353,7 +1353,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->aliases = { "perimeters_extrusion_width" }; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("perimeter_speed", coFloat); def->label = L("Perimeters"); @@ -1363,7 +1363,7 @@ void PrintConfigDef::init_fff_params() def->aliases = { "perimeter_feed_rate" }; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(60); + def->set_default_value(new ConfigOptionFloat(60)); def = this->add("perimeters", coInt); def->label = L("Perimeters"); @@ -1376,7 +1376,7 @@ void PrintConfigDef::init_fff_params() def->aliases = { "perimeter_offsets" }; def->min = 0; def->max = 10000; - def->default_value = new ConfigOptionInt(3); + def->set_default_value(new ConfigOptionInt(3)); def = this->add("post_process", coStrings); def->label = L("Post-processing scripts"); @@ -1389,12 +1389,12 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 6; def->mode = comExpert; - def->default_value = new ConfigOptionStrings(); + def->set_default_value(new ConfigOptionStrings()); def = this->add("printer_model", coString); def->label = L("Printer type"); def->tooltip = L("Type of the printer."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("printer_notes", coString); @@ -1404,26 +1404,26 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 13; def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("printer_vendor", coString); def->label = L("Printer vendor"); def->tooltip = L("Name of the printer vendor."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("printer_variant", coString); def->label = L("Printer variant"); def->tooltip = L("Name of the printer variant. For example, the printer variants may be differentiated by a nozzle diameter."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("print_settings_id", coString); - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; def = this->add("printer_settings_id", coString); - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; def = this->add("raft_layers", coInt); @@ -1434,7 +1434,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(0); + def->set_default_value(new ConfigOptionInt(0)); def = this->add("resolution", coFloat); def->label = L("Resolution"); @@ -1445,14 +1445,14 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("retract_before_travel", coFloats); def->label = L("Minimum travel after retraction"); def->tooltip = L("Retraction is not triggered when travel moves are shorter than this length."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 2. }; + def->set_default_value(new ConfigOptionFloats { 2. }); def = this->add("retract_before_wipe", coPercents); def->label = L("Retract amount before wipe"); @@ -1460,13 +1460,13 @@ void PrintConfigDef::init_fff_params() "before doing the wipe movement."); def->sidetext = L("%"); def->mode = comAdvanced; - def->default_value = new ConfigOptionPercents { 0. }; + def->set_default_value(new ConfigOptionPercents { 0. }); def = this->add("retract_layer_change", coBools); def->label = L("Retract on layer change"); def->tooltip = L("This flag enforces a retraction whenever a Z move is done."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBools { false }; + def->set_default_value(new ConfigOptionBools { false }); def = this->add("retract_length", coFloats); def->label = L("Length"); @@ -1474,7 +1474,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("When retraction is triggered, filament is pulled back by the specified amount " "(the length is measured on raw filament, before it enters the extruder)."); def->sidetext = L("mm (zero to disable)"); - def->default_value = new ConfigOptionFloats { 2. }; + def->set_default_value(new ConfigOptionFloats { 2. }); def = this->add("retract_length_toolchange", coFloats); def->label = L("Length"); @@ -1484,7 +1484,7 @@ void PrintConfigDef::init_fff_params() "the extruder)."); def->sidetext = L("mm (zero to disable)"); def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 10. }; + def->set_default_value(new ConfigOptionFloats { 10. }); def = this->add("retract_lift", coFloats); def->label = L("Lift Z"); @@ -1492,7 +1492,7 @@ void PrintConfigDef::init_fff_params() "is triggered. When using multiple extruders, only the setting for the first extruder " "will be considered."); def->sidetext = L("mm"); - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("retract_lift_above", coFloats); def->label = L("Above Z"); @@ -1501,7 +1501,7 @@ void PrintConfigDef::init_fff_params() "absolute Z. You can tune this setting for skipping lift on the first layers."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("retract_lift_below", coFloats); def->label = L("Below Z"); @@ -1511,7 +1511,7 @@ void PrintConfigDef::init_fff_params() "to the first layers."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("retract_restart_extra", coFloats); def->label = L("Extra length on restart"); @@ -1519,7 +1519,7 @@ void PrintConfigDef::init_fff_params() "this additional amount of filament. This setting is rarely needed."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("retract_restart_extra_toolchange", coFloats); def->label = L("Extra length on restart"); @@ -1527,7 +1527,7 @@ void PrintConfigDef::init_fff_params() "this additional amount of filament."); def->sidetext = L("mm"); def->mode = comExpert; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("retract_speed", coFloats); def->label = L("Retraction Speed"); @@ -1535,7 +1535,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The speed for retractions (it only applies to the extruder motor)."); def->sidetext = L("mm/s"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 40. }; + def->set_default_value(new ConfigOptionFloats { 40. }); def = this->add("deretract_speed", coFloats); def->label = L("Deretraction Speed"); @@ -1544,7 +1544,7 @@ void PrintConfigDef::init_fff_params() "(it only applies to the extruder motor). If left to zero, the retraction speed is used."); def->sidetext = L("mm/s"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloats { 0. }; + def->set_default_value(new ConfigOptionFloats { 0. }); def = this->add("seam_position", coEnum); def->label = L("Seam position"); @@ -1560,7 +1560,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Aligned")); def->enum_labels.push_back(L("Rear")); def->mode = comSimple; - def->default_value = new ConfigOptionEnum(spAligned); + def->set_default_value(new ConfigOptionEnum(spAligned)); #if 0 def = this->add("seam_preferred_direction", coFloat); @@ -1571,7 +1571,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Seam preferred direction"); def->min = 0; def->max = 360; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("seam_preferred_direction_jitter", coFloat); // def->gui_type = "slider"; @@ -1581,7 +1581,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Preferred direction of the seam - jitter"); def->min = 0; def->max = 360; - def->default_value = new ConfigOptionFloat(30); + def->set_default_value(new ConfigOptionFloat(30)); #endif def = this->add("serial_port", coString); @@ -1590,7 +1590,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Serial port"); def->tooltip = L("USB/serial port for printer connection."); def->width = 20; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("serial_speed", coInt); def->gui_type = "i_enum_open"; @@ -1602,7 +1602,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("115200"); def->enum_values.push_back("250000"); def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(250000); + def->set_default_value(new ConfigOptionInt(250000)); def = this->add("skirt_distance", coFloat); def->label = L("Distance from object"); @@ -1610,7 +1610,7 @@ void PrintConfigDef::init_fff_params() "to the object(s) and get a brim for better adhesion."); def->sidetext = L("mm"); def->min = 0; - def->default_value = new ConfigOptionFloat(6); + def->set_default_value(new ConfigOptionFloat(6)); def = this->add("skirt_height", coInt); def->label = L("Skirt height"); @@ -1618,7 +1618,7 @@ void PrintConfigDef::init_fff_params() "as a shield against drafts."); def->sidetext = L("layers"); def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("skirts", coInt); def->label = L("Loops (minimum)"); @@ -1628,7 +1628,7 @@ void PrintConfigDef::init_fff_params() "to disable skirt completely."); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("slowdown_below_layer_time", coInts); def->label = L("Slow down if layer print time is below"); @@ -1639,7 +1639,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 1000; def->mode = comExpert; - def->default_value = new ConfigOptionInts { 5 }; + def->set_default_value(new ConfigOptionInts { 5 }); def = this->add("small_perimeter_speed", coFloatOrPercent); def->label = L("Small perimeters"); @@ -1651,7 +1651,7 @@ void PrintConfigDef::init_fff_params() def->ratio_over = "perimeter_speed"; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(15, false); + def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); def = this->add("solid_infill_below_area", coFloat); def->label = L("Solid infill threshold area"); @@ -1660,7 +1660,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm²"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(70); + def->set_default_value(new ConfigOptionFloat(70)); def = this->add("solid_infill_extruder", coInt); def->label = L("Solid infill extruder"); @@ -1668,7 +1668,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing solid infill."); def->min = 1; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("solid_infill_every_layers", coInt); def->label = L("Solid infill every"); @@ -1680,7 +1680,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionInt(0); + def->set_default_value(new ConfigOptionInt(0)); def = this->add("solid_infill_extrusion_width", coFloatOrPercent); def->label = L("Solid infill"); @@ -1690,7 +1690,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("solid_infill_speed", coFloatOrPercent); def->label = L("Solid infill"); @@ -1703,7 +1703,7 @@ void PrintConfigDef::init_fff_params() def->aliases = { "solid_infill_feed_rate" }; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(20, false); + def->set_default_value(new ConfigOptionFloatOrPercent(20, false)); def = this->add("solid_layers", coInt); def->label = L("Solid layers"); @@ -1719,7 +1719,7 @@ void PrintConfigDef::init_fff_params() "no infill, no top solid layers and no support material. You can still set " "any number of bottom solid layers as well as skirt/brim loops. " "It won't work when printing more than an object."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("standby_temperature_delta", coInt); def->label = L("Temperature variation"); @@ -1729,7 +1729,7 @@ void PrintConfigDef::init_fff_params() def->min = -max_temp; def->max = max_temp; def->mode = comExpert; - def->default_value = new ConfigOptionInt(-5); + def->set_default_value(new ConfigOptionInt(-5)); def = this->add("start_gcode", coString); def->label = L("Start G-code"); @@ -1744,7 +1744,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 12; def->mode = comExpert; - def->default_value = new ConfigOptionString("G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n"); + def->set_default_value(new ConfigOptionString("G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n")); def = this->add("start_filament_gcode", coStrings); def->label = L("Start G-code"); @@ -1760,25 +1760,25 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 12; def->mode = comExpert; - def->default_value = new ConfigOptionStrings { "; Filament gcode\n" }; + def->set_default_value(new ConfigOptionStrings { "; Filament gcode\n" }); def = this->add("single_extruder_multi_material", coBool); def->label = L("Single Extruder Multi Material"); def->tooltip = L("The printer multiplexes filaments into a single hot end."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("single_extruder_multi_material_priming", coBool); def->label = L("Prime all printing extruders"); def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("support_material", coBool); def->label = L("Generate support material"); def->category = L("Support material"); def->tooltip = L("Enable support material generation."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("support_material_auto", coBool); def->label = L("Auto generated supports"); @@ -1786,7 +1786,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("If checked, supports will be generated automatically based on the overhang threshold value."\ " If unchecked, supports will be generated inside the \"Support Enforcer\" volumes only."); def->mode = comSimple; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("support_material_xy_spacing", coFloatOrPercent); def->label = L("XY separation between an object and its support"); @@ -1798,7 +1798,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->mode = comAdvanced; // Default is half the external perimeter width. - def->default_value = new ConfigOptionFloatOrPercent(50, true); + def->set_default_value(new ConfigOptionFloatOrPercent(50, true)); def = this->add("support_material_angle", coFloat); def->label = L("Pattern angle"); @@ -1808,14 +1808,14 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 359; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("support_material_buildplate_only", coBool); def->label = L("Support on build plate only"); def->category = L("Support material"); def->tooltip = L("Only create support if it lies on a build plate. Don't create support on a print."); def->mode = comSimple; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("support_material_contact_distance", coFloat); def->gui_type = "f_enum_open"; @@ -1831,7 +1831,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str()); def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str()); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0.2); + def->set_default_value(new ConfigOptionFloat(0.2)); def = this->add("support_material_enforce_layers", coInt); def->label = L("Enforce support for the first"); @@ -1844,7 +1844,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Enforce support for the first n layers"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionInt(0); + def->set_default_value(new ConfigOptionInt(0)); def = this->add("support_material_extruder", coInt); def->label = L("Support material/raft/skirt extruder"); @@ -1853,7 +1853,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes)."); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("support_material_extrusion_width", coFloatOrPercent); def->label = L("Support material"); @@ -1863,14 +1863,14 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("support_material_interface_contact_loops", coBool); def->label = L("Interface loops"); def->category = L("Support material"); def->tooltip = L("Cover the top contact layer of the supports with loops. Disabled by default."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("support_material_interface_extruder", coInt); def->label = L("Support material/raft interface extruder"); @@ -1879,7 +1879,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes). This affects raft too."); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(1); + def->set_default_value(new ConfigOptionInt(1)); def = this->add("support_material_interface_layers", coInt); def->label = L("Interface layers"); @@ -1888,7 +1888,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(3); + def->set_default_value(new ConfigOptionInt(3)); def = this->add("support_material_interface_spacing", coFloat); def->label = L("Interface pattern spacing"); @@ -1897,7 +1897,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("support_material_interface_speed", coFloatOrPercent); def->label = L("Support material interface"); @@ -1908,7 +1908,7 @@ void PrintConfigDef::init_fff_params() def->ratio_over = "support_material_speed"; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(100, true); + def->set_default_value(new ConfigOptionFloatOrPercent(100, true)); def = this->add("support_material_pattern", coEnum); def->label = L("Pattern"); @@ -1922,7 +1922,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Rectilinear grid")); def->enum_labels.push_back(L("Honeycomb")); def->mode = comAdvanced; - def->default_value = new ConfigOptionEnum(smpRectilinear); + def->set_default_value(new ConfigOptionEnum(smpRectilinear)); def = this->add("support_material_spacing", coFloat); def->label = L("Pattern spacing"); @@ -1931,7 +1931,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(2.5); + def->set_default_value(new ConfigOptionFloat(2.5)); def = this->add("support_material_speed", coFloat); def->label = L("Support material"); @@ -1940,7 +1940,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(60); + def->set_default_value(new ConfigOptionFloat(60)); def = this->add("support_material_synchronize_layers", coBool); def->label = L("Synchronize with object layers"); @@ -1948,7 +1948,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Synchronize support layers with the object print layers. This is useful " "with multi-material printers, where the extruder switch is expensive."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("support_material_threshold", coInt); def->label = L("Overhang threshold"); @@ -1962,7 +1962,7 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 90; def->mode = comAdvanced; - def->default_value = new ConfigOptionInt(0); + def->set_default_value(new ConfigOptionInt(0)); def = this->add("support_material_with_sheath", coBool); def->label = L("With sheath around the support"); @@ -1970,7 +1970,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Add a sheath (a single perimeter line) around the base support. This makes " "the support more reliable, but also more difficult to remove."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("temperature", coInts); def->label = L("Other layers"); @@ -1979,7 +1979,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Temperature"); def->min = 0; def->max = max_temp; - def->default_value = new ConfigOptionInts { 200 }; + def->set_default_value(new ConfigOptionInts { 200 }); def = this->add("thin_walls", coBool); def->label = L("Detect thin walls"); @@ -1987,7 +1987,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("threads", coInt); def->label = L("Threads"); @@ -1997,7 +1997,7 @@ void PrintConfigDef::init_fff_params() def->min = 1; { int threads = (unsigned int)boost::thread::hardware_concurrency(); - def->default_value = new ConfigOptionInt(threads > 0 ? threads : 2); + def->set_default_value(new ConfigOptionInt(threads > 0 ? threads : 2)); def->cli == ConfigOptionDef::nocli; } @@ -2010,7 +2010,7 @@ void PrintConfigDef::init_fff_params() def->full_width = true; def->height = 5; def->mode = comExpert; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("top_infill_extrusion_width", coFloatOrPercent); def->label = L("Top solid infill"); @@ -2021,7 +2021,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(0, false); + def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def = this->add("top_solid_infill_speed", coFloatOrPercent); def->label = L("Top solid infill"); @@ -2035,7 +2035,7 @@ void PrintConfigDef::init_fff_params() def->ratio_over = "solid_infill_speed"; def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloatOrPercent(15, false); + def->set_default_value(new ConfigOptionFloatOrPercent(15, false)); def = this->add("top_solid_layers", coInt); def->label = L("Top"); @@ -2043,7 +2043,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Number of solid layers to generate on top surfaces."); def->full_label = L("Top solid layers"); def->min = 0; - def->default_value = new ConfigOptionInt(3); + def->set_default_value(new ConfigOptionInt(3)); def = this->add("travel_speed", coFloat); def->label = L("Travel"); @@ -2052,21 +2052,21 @@ void PrintConfigDef::init_fff_params() def->aliases = { "travel_feed_rate" }; def->min = 1; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(130); + def->set_default_value(new ConfigOptionFloat(130)); def = this->add("use_firmware_retraction", coBool); def->label = L("Use firmware retraction"); def->tooltip = L("This experimental setting uses G10 and G11 commands to have the firmware " "handle the retraction. This is only supported in recent Marlin."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("use_relative_e_distances", coBool); def->label = L("Use relative E distances"); def->tooltip = L("If your firmware requires relative E values, check this, " "otherwise leave it unchecked. Most firmwares use absolute values."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("use_volumetric_e", coBool); def->label = L("Use volumetric E"); @@ -2077,73 +2077,73 @@ void PrintConfigDef::init_fff_params() "diameter associated to the filament selected in Slic3r. This is only supported " "in recent Marlin."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("variable_layer_height", coBool); def->label = L("Enable variable layer height feature"); def->tooltip = L("Some printers or printer setups may have difficulties printing " "with a variable layer height. Enabled by default."); def->mode = comExpert; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("wipe", coBools); def->label = L("Wipe while retracting"); def->tooltip = L("This flag will move the nozzle while retracting to minimize the possible blob " "on leaky extruders."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBools { false }; + def->set_default_value(new ConfigOptionBools { false }); def = this->add("wipe_tower", coBool); def->label = L("Enable"); def->tooltip = L("Multi material printers may need to prime or purge extruders on tool changes. " "Extrude the excess material into the wipe tower."); def->mode = comAdvanced; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("wiping_volumes_extruders", coFloats); def->label = L("Purging volumes - load/unload volumes"); def->tooltip = L("This vector saves required volumes to change from/to each tool used on the " "wipe tower. These values are used to simplify creation of the full purging " "volumes below. "); - def->default_value = new ConfigOptionFloats { 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f }; + def->set_default_value(new ConfigOptionFloats { 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f, 70.f }); def = this->add("wiping_volumes_matrix", coFloats); def->label = L("Purging volumes - matrix"); def->tooltip = L("This matrix describes volumes (in cubic milimetres) required to purge the" " new filament on the wipe tower for any given pair of tools. "); - def->default_value = new ConfigOptionFloats { 0.f, 140.f, 140.f, 140.f, 140.f, - 140.f, 0.f, 140.f, 140.f, 140.f, - 140.f, 140.f, 0.f, 140.f, 140.f, - 140.f, 140.f, 140.f, 0.f, 140.f, - 140.f, 140.f, 140.f, 140.f, 0.f }; + def->set_default_value(new ConfigOptionFloats { 0.f, 140.f, 140.f, 140.f, 140.f, + 140.f, 0.f, 140.f, 140.f, 140.f, + 140.f, 140.f, 0.f, 140.f, 140.f, + 140.f, 140.f, 140.f, 0.f, 140.f, + 140.f, 140.f, 140.f, 140.f, 0.f }); def = this->add("wipe_tower_x", coFloat); def->label = L("Position X"); def->tooltip = L("X coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(180.); + def->set_default_value(new ConfigOptionFloat(180.)); def = this->add("wipe_tower_y", coFloat); def->label = L("Position Y"); def->tooltip = L("Y coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(140.); + def->set_default_value(new ConfigOptionFloat(140.)); def = this->add("wipe_tower_width", coFloat); def->label = L("Width"); def->tooltip = L("Width of a wipe tower"); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(60.); + def->set_default_value(new ConfigOptionFloat(60.)); def = this->add("wipe_tower_rotation_angle", coFloat); def->label = L("Wipe tower rotation angle"); def->tooltip = L("Wipe tower rotation angle with respect to x-axis "); def->sidetext = L("degrees"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0.); + def->set_default_value(new ConfigOptionFloat(0.)); def = this->add("wipe_into_infill", coBool); def->category = L("Extruders"); @@ -2151,7 +2151,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Purging after toolchange will done inside this object's infills. " "This lowers the amount of waste but may result in longer print time " " due to additional travel moves."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("wipe_into_objects", coBool); def->category = L("Extruders"); @@ -2159,14 +2159,14 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Object will be used to purge the nozzle after a toolchange to save material " "that would otherwise end up in the wipe tower and decrease print time. " "Colours of the objects will be mixed as a result."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("wipe_tower_bridging", coFloat); def->label = L("Maximal bridging distance"); def->tooltip = L("Maximal distance between supports on sparse infill sections. "); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(10.); + def->set_default_value(new ConfigOptionFloat(10.)); def = this->add("xy_size_compensation", coFloat); def->label = L("XY Size Compensation"); @@ -2176,7 +2176,7 @@ void PrintConfigDef::init_fff_params() "for fine-tuning hole sizes."); def->sidetext = L("mm"); def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("z_offset", coFloat); def->label = L("Z offset"); @@ -2186,7 +2186,7 @@ void PrintConfigDef::init_fff_params() "from the print bed, set this to -0.3 (or fix your endstop)."); def->sidetext = L("mm"); def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); } void PrintConfigDef::init_sla_params() @@ -2200,26 +2200,26 @@ void PrintConfigDef::init_sla_params() def->label = L("Display width"); def->tooltip = L("Width of the display"); def->min = 1; - def->default_value = new ConfigOptionFloat(120.); + def->set_default_value(new ConfigOptionFloat(120.)); def = this->add("display_height", coFloat); def->label = L("Display height"); def->tooltip = L("Height of the display"); def->min = 1; - def->default_value = new ConfigOptionFloat(68.); + def->set_default_value(new ConfigOptionFloat(68.)); def = this->add("display_pixels_x", coInt); def->full_label = L("Number of pixels in"); def->label = ("X"); def->tooltip = L("Number of pixels in X"); def->min = 100; - def->default_value = new ConfigOptionInt(2560); + def->set_default_value(new ConfigOptionInt(2560)); def = this->add("display_pixels_y", coInt); def->label = ("Y"); def->tooltip = L("Number of pixels in Y"); def->min = 100; - def->default_value = new ConfigOptionInt(1440); + def->set_default_value(new ConfigOptionInt(1440)); def = this->add("display_orientation", coEnum); def->label = L("Display orientation"); @@ -2232,7 +2232,7 @@ void PrintConfigDef::init_sla_params() def->enum_labels.push_back(L("Landscape")); def->enum_labels.push_back(L("Portrait")); def->mode = comExpert; - def->default_value = new ConfigOptionEnum(sladoPortrait); + def->set_default_value(new ConfigOptionEnum(sladoPortrait)); def = this->add("fast_tilt_time", coFloat); def->label = L("Fast"); @@ -2241,7 +2241,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(5.); + def->set_default_value(new ConfigOptionFloat(5.)); def = this->add("slow_tilt_time", coFloat); def->label = L("Slow"); @@ -2250,7 +2250,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("s"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(8.); + def->set_default_value(new ConfigOptionFloat(8.)); def = this->add("area_fill", coFloat); def->label = L("Area fill"); @@ -2258,7 +2258,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("%"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(50.); + def->set_default_value(new ConfigOptionFloat(50.)); def = this->add("relative_correction", coFloats); def->label = L("Printer scaling correction"); @@ -2266,7 +2266,7 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("Printer scaling correction"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats( { 1., 1. } ); + def->set_default_value(new ConfigOptionFloats( { 1., 1. } )); def = this->add("absolute_correction", coFloat); def->label = L("Printer absolute correction"); @@ -2274,7 +2274,7 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("Will inflate or deflate the sliced 2D polygons according " "to the sign of the correction."); def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0.0); + def->set_default_value(new ConfigOptionFloat(0.0)); def = this->add("gamma_correction", coFloat); def->label = L("Printer gamma correction"); @@ -2285,7 +2285,7 @@ void PrintConfigDef::init_sla_params() "antialiasing without losing holes in polygons."); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(1.0); + def->set_default_value(new ConfigOptionFloat(1.0)); // SLA Material settings. @@ -2294,7 +2294,7 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("Initial layer height"); def->sidetext = L("mm"); def->min = 0; - def->default_value = new ConfigOptionFloat(0.3); + def->set_default_value(new ConfigOptionFloat(0.3)); def = this->add("faded_layers", coInt); def->label = L("Faded layers"); @@ -2302,28 +2302,28 @@ void PrintConfigDef::init_sla_params() def->min = 3; def->max = 20; def->mode = comExpert; - def->default_value = new ConfigOptionInt(10); + def->set_default_value(new ConfigOptionInt(10)); def = this->add("exposure_time", coFloat); def->label = L("Exposure time"); def->tooltip = L("Exposure time"); def->sidetext = L("s"); def->min = 0; - def->default_value = new ConfigOptionFloat(10); + def->set_default_value(new ConfigOptionFloat(10)); def = this->add("initial_exposure_time", coFloat); def->label = L("Initial exposure time"); def->tooltip = L("Initial exposure time"); def->sidetext = L("s"); def->min = 0; - def->default_value = new ConfigOptionFloat(15); + def->set_default_value(new ConfigOptionFloat(15)); def = this->add("material_correction", coFloats); def->full_label = L("Correction for expansion"); def->tooltip = L("Correction for expansion"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloats( { 1. , 1. } ); + def->set_default_value(new ConfigOptionFloats( { 1. , 1. } )); def = this->add("material_notes", coString); def->label = L("SLA print material notes"); @@ -2332,28 +2332,28 @@ void PrintConfigDef::init_sla_params() def->full_width = true; def->height = 13; def->mode = comAdvanced; - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def = this->add("default_sla_material_profile", coString); def->label = L("Default SLA material profile"); def->tooltip = L("Default print profile associated with the current printer profile. " "On selection of the current printer profile, this print profile will be activated."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("sla_material_settings_id", coString); - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; def = this->add("default_sla_print_profile", coString); def->label = L("Default SLA material profile"); def->tooltip = L("Default print profile associated with the current printer profile. " "On selection of the current printer profile, this print profile will be activated."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); def->cli = ConfigOptionDef::nocli; def = this->add("sla_print_settings_id", coString); - def->default_value = new ConfigOptionString(""); + def->set_default_value(new ConfigOptionString("")); def->cli = ConfigOptionDef::nocli; def = this->add("supports_enable", coBool); @@ -2361,7 +2361,7 @@ void PrintConfigDef::init_sla_params() def->category = L("Supports"); def->tooltip = L("Generate supports for the models"); def->mode = comSimple; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("support_head_front_diameter", coFloat); def->label = L("Support head front diameter"); @@ -2370,7 +2370,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(0.4); + def->set_default_value(new ConfigOptionFloat(0.4)); def = this->add("support_head_penetration", coFloat); def->label = L("Support head penetration"); @@ -2379,7 +2379,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->mode = comAdvanced; def->min = 0; - def->default_value = new ConfigOptionFloat(0.2); + def->set_default_value(new ConfigOptionFloat(0.2)); def = this->add("support_head_width", coFloat); def->label = L("Support head width"); @@ -2389,7 +2389,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 20; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(1.0); + def->set_default_value(new ConfigOptionFloat(1.0)); def = this->add("support_pillar_diameter", coFloat); def->label = L("Support pillar diameter"); @@ -2399,7 +2399,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 15; def->mode = comSimple; - def->default_value = new ConfigOptionFloat(1.0); + def->set_default_value(new ConfigOptionFloat(1.0)); def = this->add("support_pillar_connection_mode", coEnum); def->label = L("Support pillar connection mode"); @@ -2415,14 +2415,14 @@ void PrintConfigDef::init_sla_params() def->enum_labels.push_back(L("Cross")); def->enum_labels.push_back(L("Dynamic")); def->mode = comAdvanced; - def->default_value = new ConfigOptionEnum(slapcmDynamic); + def->set_default_value(new ConfigOptionEnum(slapcmDynamic)); def = this->add("support_buildplate_only", coBool); def->label = L("Support on build plate only"); def->category = L("Supports"); def->tooltip = L("Only create support if it lies on a build plate. Don't create support on a print."); def->mode = comSimple; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("support_pillar_widening_factor", coFloat); def->label = L("Pillar widening factor"); @@ -2433,7 +2433,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 1; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0.0); + def->set_default_value(new ConfigOptionFloat(0.0)); def = this->add("support_base_diameter", coFloat); def->label = L("Support base diameter"); @@ -2443,7 +2443,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 30; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(4.0); + def->set_default_value(new ConfigOptionFloat(4.0)); def = this->add("support_base_height", coFloat); def->label = L("Support base height"); @@ -2452,7 +2452,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(1.0); + def->set_default_value(new ConfigOptionFloat(1.0)); def = this->add("support_critical_angle", coFloat); def->label = L("Critical angle"); @@ -2462,7 +2462,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 90; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(45); + def->set_default_value(new ConfigOptionFloat(45)); def = this->add("support_max_bridge_length", coFloat); def->label = L("Max bridge length"); @@ -2471,7 +2471,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(15.0); + def->set_default_value(new ConfigOptionFloat(15.0)); def = this->add("support_max_pillar_link_distance", coFloat); def->label = L("Max pillar linking distance"); @@ -2481,7 +2481,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; // 0 means no linking def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(10.0); + def->set_default_value(new ConfigOptionFloat(10.0)); def = this->add("support_object_elevation", coFloat); def->label = L("Object elevation"); @@ -2491,7 +2491,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 150; // This is the max height of print on SL1 def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(5.0); + def->set_default_value(new ConfigOptionFloat(5.0)); def = this->add("support_points_density_relative", coInt); def->label = L("Support points density"); @@ -2499,7 +2499,7 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("This is a relative measure of support points density."); def->sidetext = L("%"); def->min = 0; - def->default_value = new ConfigOptionInt(100); + def->set_default_value(new ConfigOptionInt(100)); def = this->add("support_points_minimal_distance", coFloat); def->label = L("Minimal distance of the support points"); @@ -2507,14 +2507,14 @@ void PrintConfigDef::init_sla_params() def->tooltip = L("No support points will be placed closer than this threshold."); def->sidetext = L("mm"); def->min = 0; - def->default_value = new ConfigOptionFloat(1.f); + def->set_default_value(new ConfigOptionFloat(1.f)); def = this->add("pad_enable", coBool); def->label = L("Use pad"); def->category = L("Pad"); def->tooltip = L("Add a pad underneath the supported model"); def->mode = comSimple; - def->default_value = new ConfigOptionBool(true); + def->set_default_value(new ConfigOptionBool(true)); def = this->add("pad_wall_thickness", coFloat); def->label = L("Pad wall thickness"); @@ -2524,7 +2524,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 30; def->mode = comSimple; - def->default_value = new ConfigOptionFloat(2.0); + def->set_default_value(new ConfigOptionFloat(2.0)); def = this->add("pad_wall_height", coFloat); def->label = L("Pad wall height"); @@ -2538,7 +2538,7 @@ void PrintConfigDef::init_sla_params() def->min = 0; def->max = 30; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(0.); + def->set_default_value(new ConfigOptionFloat(0.)); def = this->add("pad_max_merge_distance", coFloat); def->label = L("Max merge distance"); @@ -2550,7 +2550,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; - def->default_value = new ConfigOptionFloat(50.0); + def->set_default_value(new ConfigOptionFloat(50.0)); // This is disabled on the UI. I hope it will never be enabled. def = this->add("pad_edge_radius", coFloat); @@ -2560,7 +2560,7 @@ void PrintConfigDef::init_sla_params() def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(1.0); + def->set_default_value(new ConfigOptionFloat(1.0)); def = this->add("pad_wall_slope", coFloat); def->label = L("Pad wall slope"); @@ -2571,7 +2571,7 @@ void PrintConfigDef::init_sla_params() def->min = 45; def->max = 90; def->mode = comAdvanced; - def->default_value = new ConfigOptionFloat(45.0); + def->set_default_value(new ConfigOptionFloat(45.0)); } void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value) @@ -2928,73 +2928,73 @@ CLIActionsConfigDef::CLIActionsConfigDef() def = this->add("export_obj", coBool); def->label = L("Export OBJ"); def->tooltip = L("Export the model(s) as OBJ."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); /* def = this->add("export_svg", coBool); def->label = L("Export SVG"); def->tooltip = L("Slice the model and export solid slices as SVG."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); */ def = this->add("export_sla", coBool); def->label = L("Export SLA"); def->tooltip = L("Slice the model and export SLA printing layers as PNG."); def->cli = "export-sla|sla"; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("export_3mf", coBool); def->label = L("Export 3MF"); def->tooltip = L("Export the model(s) as 3MF."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("export_amf", coBool); def->label = L("Export AMF"); def->tooltip = L("Export the model(s) as AMF."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("export_stl", coBool); def->label = L("Export STL"); def->tooltip = L("Export the model(s) as STL."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("export_gcode", coBool); def->label = L("Export G-code"); def->tooltip = L("Slice the model and export toolpaths as G-code."); def->cli = "export-gcode|gcode|g"; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("slice", coBool); def->label = L("Slice"); def->tooltip = L("Slice the model as FFF or SLA based on the printer_technology configuration value."); def->cli = "slice|s"; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("help", coBool); def->label = L("Help"); def->tooltip = L("Show this help."); def->cli = "help|h"; - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("help_fff", coBool); def->label = L("Help (FFF options)"); def->tooltip = L("Show the full list of print/G-code configuration options."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("help_sla", coBool); def->label = L("Help (SLA options)"); def->tooltip = L("Show the full list of SLA print configuration options."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("info", coBool); def->label = L("Output Model Info"); def->tooltip = L("Write information about the model to the console."); - def->default_value = new ConfigOptionBool(false); + def->set_default_value(new ConfigOptionBool(false)); def = this->add("save", coString); def->label = L("Save config file"); def->tooltip = L("Save configuration to the specified file."); - def->default_value = new ConfigOptionString(); + def->set_default_value(new ConfigOptionString()); } CLITransformConfigDef::CLITransformConfigDef() @@ -3005,34 +3005,34 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("align_xy", coPoint); def->label = L("Align XY"); def->tooltip = L("Align the model to the given point."); - def->default_value = new ConfigOptionPoint(Vec2d(100,100)); + def->set_default_value(new ConfigOptionPoint(Vec2d(100,100))); def = this->add("cut", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given Z."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); /* def = this->add("cut_grid", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model in the XY plane into tiles of the specified max size."); - def->default_value = new ConfigOptionPoint(); + def->set_default_value(new ConfigOptionPoint()); def = this->add("cut_x", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given X."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("cut_y", coFloat); def->label = L("Cut"); def->tooltip = L("Cut model at the given Y."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); */ def = this->add("center", coPoint); def->label = L("Center"); def->tooltip = L("Center the print around the given center."); - def->default_value = new ConfigOptionPoint(Vec2d(100,100)); + def->set_default_value(new ConfigOptionPoint(Vec2d(100,100))); def = this->add("dont_arrange", coBool); def->label = L("Don't arrange"); @@ -3059,22 +3059,22 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("rotate", coFloat); def->label = L("Rotate"); def->tooltip = L("Rotation angle around the Z axis in degrees."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("rotate_x", coFloat); def->label = L("Rotate around X"); def->tooltip = L("Rotation angle around the X axis in degrees."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("rotate_y", coFloat); def->label = L("Rotate around Y"); def->tooltip = L("Rotation angle around the Y axis in degrees."); - def->default_value = new ConfigOptionFloat(0); + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("scale", coFloatOrPercent); def->label = L("Scale"); def->tooltip = L("Scaling factor or percentage."); - def->default_value = new ConfigOptionFloatOrPercent(1, false); + def->set_default_value(new ConfigOptionFloatOrPercent(1, false)); def = this->add("split", coBool); def->label = L("Split"); @@ -3083,7 +3083,7 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("scale_to_fit", coPoint3); def->label = L("Scale to Fit"); def->tooltip = L("Scale to fit the given volume."); - def->default_value = new ConfigOptionPoint3(Vec3d(0,0,0)); + def->set_default_value(new ConfigOptionPoint3(Vec3d(0,0,0))); } CLIMiscConfigDef::CLIMiscConfigDef() diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index db3e63fe7..d4ad1db8c 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -307,8 +307,8 @@ protected: m_keys.emplace_back(kvp.first); const ConfigOptionDef *def = defs->get(kvp.first); assert(def != nullptr); - if (def->default_value != nullptr) - opt->set(def->default_value); + if (def->default_value) + opt->set(def->default_value.get()); } } diff --git a/src/libslic3r/clonable_ptr.hpp b/src/libslic3r/clonable_ptr.hpp new file mode 100644 index 000000000..a3b7ee244 --- /dev/null +++ b/src/libslic3r/clonable_ptr.hpp @@ -0,0 +1,168 @@ +// clonable_ptr: a smart pointer with a usage similar to unique_ptr, with the exception, that +// the copy constructor / copy assignment operator work by calling the ->clone() method. + +// derived from https://github.com/SRombauts/shared_ptr/blob/master/include/unique_ptr.hpp +/** + * @file clonable_ptr.hpp + * @brief clonable_ptr is a fake implementation to use in place of a C++11 std::clonable_ptr when compiling on an older compiler. + * + * @see http://www.cplusplus.com/reference/memory/clonable_ptr/ + * + * Copyright (c) 2014-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ + +#include "assert.h" + +namespace Slic3r { + +// Detect whether the compiler supports C++11 noexcept exception specifications. +#if defined(_MSC_VER) && _MSC_VER < 1900 && ! defined(noexcept) + #define noexcept throw() +#endif + +template +class clonable_ptr +{ +public: + /// The type of the managed object, aliased as member type + typedef T element_type; + + /// @brief Default constructor + clonable_ptr() noexcept : + px(nullptr) + { + } + /// @brief Constructor with the provided pointer to manage + explicit clonable_ptr(T* p) noexcept : + px(p) + { + } + /// @brief Copy constructor, clones by calling the rhs.clone() method + clonable_ptr(const clonable_ptr& rhs) : + px(rhs ? rhs.px->clone() : nullptr) + { + } + /// @brief Move constructor, never throws + clonable_ptr(clonable_ptr&& rhs) noexcept : + px(rhs.px) + { + rhs.px = nullptr; + } + /// @brief Assignment operator + clonable_ptr& operator=(const clonable_ptr& rhs) + { + delete px; + px = rhs ? rhs.px->clone() : nullptr; + return *this; + } + /// @brief Move operator, never throws + clonable_ptr& operator=(clonable_ptr&& rhs) + { + delete px; + px = rhs.px; + rhs.px = nullptr; + return *this; + } + /// @brief the destructor releases its ownership and destroy the object + inline ~clonable_ptr() noexcept + { + destroy(); + } + /// @brief this reset releases its ownership and destroy the object + inline void reset() noexcept + { + destroy(); + } + /// @brief this reset release its ownership and re-acquire another one + void reset(T* p) noexcept + { + assert((nullptr == p) || (px != p)); // auto-reset not allowed + destroy(); + px = p; + } + + /// @brief Swap method for the copy-and-swap idiom (copy constructor and swap method) + void swap(clonable_ptr& rhs) noexcept + { + T *tmp = px; + px = rhs.px; + rhs.px = tmp; + } + + /// @brief release the ownership of the px pointer without destroying the object! + inline void release() noexcept + { + px = nullptr; + } + + // reference counter operations : + inline operator bool() const noexcept + { + return (nullptr != px); // TODO nullptrptr + } + + // underlying pointer operations : + inline T& operator*() const noexcept + { + assert(nullptr != px); + return *px; + } + inline T* operator->() const noexcept + { + assert(nullptr != px); + return px; + } + inline T* get() const noexcept + { + // no assert, can return nullptr + return px; + } + +private: + /// @brief release the ownership of the px pointer and destroy the object + inline void destroy() noexcept + { + delete px; + px = nullptr; + } + + /// @brief hack: const-cast release the ownership of the px pointer without destroying the object! + inline void release() const noexcept + { + px = nullptr; + } + +private: + T* px; //!< Native pointer +}; + +// comparison operators +template inline bool operator==(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() == r.get()); +} +template inline bool operator!=(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() != r.get()); +} +template inline bool operator<=(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() <= r.get()); +} +template inline bool operator<(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() < r.get()); +} +template inline bool operator>=(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() >= r.get()); +} +template inline bool operator>(const clonable_ptr& l, const clonable_ptr& r) noexcept +{ + return (l.get() > r.get()); +} + +} // namespace Slic3r diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 00ebf117c..fbbca7c70 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -68,14 +68,14 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) auto optgroup = init_shape_options_page(_(L("Rectangular"))); ConfigOptionDef def; def.type = coPoints; - def.default_value = new ConfigOptionPoints{ Vec2d(200, 200) }; + def.set_default_value(new ConfigOptionPoints{ Vec2d(200, 200) }); def.label = L("Size"); def.tooltip = L("Size in X and Y of the rectangular plate."); Option option(def, "rect_size"); optgroup->append_single_option_line(option); def.type = coPoints; - def.default_value = new ConfigOptionPoints{ Vec2d(0, 0) }; + def.set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) }); def.label = L("Origin"); def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle."); option = Option(def, "rect_origin"); @@ -83,7 +83,7 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) optgroup = init_shape_options_page(_(L("Circular"))); def.type = coFloat; - def.default_value = new ConfigOptionFloat(200); + def.set_default_value(new ConfigOptionFloat(200)); def.sidetext = L("mm"); def.label = L("Diameter"); def.tooltip = L("Diameter of the print bed. It is assumed that origin (0,0) is located in the center."); diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 93c780909..bd45104c4 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -499,7 +499,7 @@ PageFirmware::PageFirmware(ConfigWizard *parent) gcode_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); const auto &enum_values = gcode_opt.enum_values; auto needle = enum_values.cend(); - if (gcode_opt.default_value != nullptr) { + if (gcode_opt.default_value) { needle = std::find(enum_values.cbegin(), enum_values.cend(), gcode_opt.default_value->serialize()); } if (needle != enum_values.cend()) { @@ -545,13 +545,13 @@ PageDiameters::PageDiameters(ConfigWizard *parent) spin_nozzle->SetDigits(2); spin_nozzle->SetIncrement(0.1); const auto &def_nozzle = *print_config_def.get("nozzle_diameter"); - auto *default_nozzle = dynamic_cast(def_nozzle.default_value); + auto *default_nozzle = dynamic_cast(def_nozzle.default_value.get()); spin_nozzle->SetValue(default_nozzle != nullptr && default_nozzle->size() > 0 ? default_nozzle->get_at(0) : 0.5); spin_filam->SetDigits(2); spin_filam->SetIncrement(0.25); const auto &def_filam = *print_config_def.get("filament_diameter"); - auto *default_filam = dynamic_cast(def_filam.default_value); + auto *default_filam = dynamic_cast(def_filam.default_value.get()); spin_filam->SetValue(default_filam != nullptr && default_filam->size() > 0 ? default_filam->get_at(0) : 3.0); append_text(_(L("Enter the diameter of your printer's hot end nozzle."))); @@ -596,13 +596,13 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent) spin_extr->SetIncrement(5.0); const auto &def_extr = *print_config_def.get("temperature"); spin_extr->SetRange(def_extr.min, def_extr.max); - auto *default_extr = dynamic_cast(def_extr.default_value); + auto *default_extr = dynamic_cast(def_extr.default_value.get()); spin_extr->SetValue(default_extr != nullptr && default_extr->size() > 0 ? default_extr->get_at(0) : 200); spin_bed->SetIncrement(5.0); const auto &def_bed = *print_config_def.get("bed_temperature"); spin_bed->SetRange(def_bed.min, def_bed.max); - auto *default_bed = dynamic_cast(def_bed.default_value); + auto *default_bed = dynamic_cast(def_bed.default_value.get()); spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0); append_text(_(L("Enter the temperature needed for extruding your filament."))); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index cb414fa79..02f58667c 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -203,7 +203,7 @@ void TextCtrl::BUILD() { case coFloatOrPercent: { text_value = double_to_string(m_opt.default_value->getFloat()); - if (static_cast(m_opt.default_value)->percent) + if (static_cast(m_opt.default_value.get())->percent) text_value += "%"; break; } @@ -218,19 +218,19 @@ void TextCtrl::BUILD() { case coFloat: { double val = m_opt.type == coFloats ? - static_cast(m_opt.default_value)->get_at(m_opt_idx) : + static_cast(m_opt.default_value.get())->get_at(m_opt_idx) : m_opt.type == coFloat ? m_opt.default_value->getFloat() : - static_cast(m_opt.default_value)->get_at(m_opt_idx); + static_cast(m_opt.default_value.get())->get_at(m_opt_idx); text_value = double_to_string(val); break; } case coString: - text_value = static_cast(m_opt.default_value)->value; + text_value = static_cast(m_opt.default_value.get())->value; break; case coStrings: { - const ConfigOptionStrings *vec = static_cast(m_opt.default_value); + const ConfigOptionStrings *vec = static_cast(m_opt.default_value.get()); if (vec == nullptr || vec->empty()) break; //for the case of empty default value text_value = vec->get_at(m_opt_idx); break; @@ -373,7 +373,7 @@ void CheckBox::BUILD() { bool check_value = m_opt.type == coBool ? m_opt.default_value->getBool() : m_opt.type == coBools ? - static_cast(m_opt.default_value)->get_at(m_opt_idx) : + static_cast(m_opt.default_value.get())->get_at(m_opt_idx) : false; // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox @@ -427,7 +427,7 @@ void SpinCtrl::BUILD() { break; case coInts: { - const ConfigOptionInts *vec = static_cast(m_opt.default_value); + const ConfigOptionInts *vec = static_cast(m_opt.default_value.get()); if (vec == nullptr || vec->empty()) break; for (size_t id = 0; id < vec->size(); ++id) { @@ -629,7 +629,7 @@ void Choice::set_selection() break; } case coEnum:{ - int id_value = static_cast*>(m_opt.default_value)->value; //!! + int id_value = static_cast*>(m_opt.default_value.get())->value; //!! field->SetSelection(id_value); break; } @@ -649,7 +649,7 @@ void Choice::set_selection() break; } case coStrings:{ - text_value = static_cast(m_opt.default_value)->get_at(m_opt_idx); + text_value = static_cast(m_opt.default_value.get())->get_at(m_opt_idx); size_t idx = 0; for (auto el : m_opt.enum_values) @@ -886,7 +886,7 @@ void ColourPicker::BUILD() if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); // Validate the color - wxString clr_str(static_cast(m_opt.default_value)->get_at(m_opt_idx)); + wxString clr_str(static_cast(m_opt.default_value.get())->get_at(m_opt_idx)); wxColour clr(clr_str); if (! clr.IsOk()) { clr = wxTransparentColour; @@ -920,7 +920,7 @@ void PointCtrl::BUILD() const wxSize field_size(4 * m_em_unit, -1); - auto default_pt = static_cast(m_opt.default_value)->values.at(0); + auto default_pt = static_cast(m_opt.default_value.get())->values.at(0); double val = default_pt(0); wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); val = default_pt(1); @@ -1019,7 +1019,7 @@ void StaticText::BUILD() if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - const wxString legend(static_cast(m_opt.default_value)->value); + const wxString legend(static_cast(m_opt.default_value.get())->value); auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size, wxST_ELLIPSIZE_MIDDLE); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); temp->SetBackgroundStyle(wxBG_STYLE_PAINT); @@ -1054,7 +1054,7 @@ void SliderCtrl::BUILD() auto temp = new wxBoxSizer(wxHORIZONTAL); - auto def_val = static_cast(m_opt.default_value)->value; + auto def_val = static_cast(m_opt.default_value.get())->value; auto min = m_opt.min == INT_MIN ? 0 : m_opt.min; auto max = m_opt.max == INT_MAX ? 100 : m_opt.max; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 1da17f676..36b356c5d 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -90,7 +90,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : def.gui_type = "legend"; def.tooltip = L("Object name"); def.width = 21; - def.default_value = new ConfigOptionString{ " " }; + def.set_default_value(new ConfigOptionString{ " " }); m_og->append_single_option_line(Option(def, "object_name")); const int field_width = 5; @@ -103,7 +103,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : for (const std::string axis : { "x", "y", "z" }) { const std::string label = boost::algorithm::to_upper_copy(axis); - def.default_value = new ConfigOptionString{ " " + label }; + def.set_default_value(new ConfigOptionString{ " " + label }); Option option = Option(def, axis + "_axis_legend"); line.append_option(option); } @@ -120,7 +120,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : Line line = { _(option_name), "" }; ConfigOptionDef def; def.type = coFloat; - def.default_value = new ConfigOptionFloat(0.0); + def.set_default_value(new ConfigOptionFloat(0.0)); def.width = field_width/*50*/; // Add "uniform scaling" button in front of "Scale" option diff --git a/src/slic3r/GUI/LambdaObjectDialog.cpp b/src/slic3r/GUI/LambdaObjectDialog.cpp index 0146db5f6..4d1cb0658 100644 --- a/src/slic3r/GUI/LambdaObjectDialog.cpp +++ b/src/slic3r/GUI/LambdaObjectDialog.cpp @@ -49,7 +49,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, }; def.type = coFloat; - def.default_value = new ConfigOptionFloat{ 1.0 }; + def.set_default_value(new ConfigOptionFloat{ 1.0 }); def.label = L("Length"); Option option(def, "l"); optgroup->append_single_option_line(option); @@ -75,7 +75,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, }; def.type = coInt; - def.default_value = new ConfigOptionInt{ 1 }; + def.set_default_value(new ConfigOptionInt{ 1 }); def.label = L("Radius"); auto option = Option(def, "cyl_r"); optgroup->append_single_option_line(option); @@ -94,7 +94,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, }; def.type = coFloat; - def.default_value = new ConfigOptionFloat{ 1.0 }; + def.set_default_value(new ConfigOptionFloat{ 1.0 }); def.label = L("Rho"); auto option = Option(def, "sph_rho"); optgroup->append_single_option_line(option); @@ -112,7 +112,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, }; def.type = coFloat; - def.default_value = new ConfigOptionFloat{ 1.0 }; + def.set_default_value(new ConfigOptionFloat{ 1.0 }); def.label = L("Height"); auto option = Option(def, "slab_h"); optgroup->append_single_option_line(option); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b3757dc8b..292d47d91 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -394,16 +394,27 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : } new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); } - else { //(opt_key == "support") + else { + assert(opt_key == "support"); const wxString& selection = boost::any_cast(value); + PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); auto support_material = selection == _("None") ? false : true; new_conf.set_key_value("support_material", new ConfigOptionBool(support_material)); - if (selection == _("Everywhere")) + if (selection == _("Everywhere")) { new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); - else if (selection == _("Support on build plate only")) + if (printer_technology == ptFFF) + new_conf.set_key_value("support_material_auto", new ConfigOptionBool(true)); + } else if (selection == _("Support on build plate only")) { new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true)); + if (printer_technology == ptFFF) + new_conf.set_key_value("support_material_auto", new ConfigOptionBool(true)); + } else if (selection == _("For support enforcers only")) { + assert(printer_technology == ptFFF); + new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); + new_conf.set_key_value("support_material_auto", new ConfigOptionBool(false)); + } } tab_print->load_config(new_conf); } @@ -421,12 +432,9 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : support_def.tooltip = L("Select what kind of support do you need"); support_def.enum_labels.push_back(L("None")); support_def.enum_labels.push_back(L("Support on build plate only")); + support_def.enum_labels.push_back(L("For support enforcers only")); support_def.enum_labels.push_back(L("Everywhere")); - std::string selection = !config->opt_bool("support_material") ? - "None" : config->opt_bool("support_material_buildplate_only") ? - "Support on build plate only" : - "Everywhere"; - support_def.default_value = new ConfigOptionStrings{ selection }; + support_def.set_default_value(new ConfigOptionStrings{ "None" }); Option option = Option(support_def, "support"); option.opt.full_width = true; line.append_option(option); @@ -447,7 +455,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : def.type = coBool; def.tooltip = L("This flag enables the brim that will be printed around each object on the first layer."); def.gui_type = ""; - def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }; + def.set_default_value(new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }); option = Option(def, "brim"); option.opt.sidetext = " "; line.append_option(option); @@ -493,8 +501,9 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : tab->set_value(opt_key, value); tab->update(); } - else //(opt_key == "support") + else { + assert(opt_key == "support"); DynamicPrintConfig new_conf = *config_sla; const wxString& selection = boost::any_cast(value); @@ -514,17 +523,15 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : line = Line{ "", "" }; - selection = !config_sla->opt_bool("supports_enable") ? - "None" : config_sla->opt_bool("support_buildplate_only") ? - "Support on build plate only" : - "Everywhere"; - support_def.default_value = new ConfigOptionStrings{ selection }; - option = Option(support_def, "support"); + ConfigOptionDef support_def_sla = support_def; + support_def_sla.set_default_value(new ConfigOptionStrings{ "None" }); + assert(support_def_sla.enum_labels[2] == L("For support enforcers only")); + support_def_sla.enum_labels.erase(support_def_sla.enum_labels.begin() + 2); + option = Option(support_def_sla, "support"); option.opt.full_width = true; line.append_option(option); m_og_sla->append_line(line); - line = Line{ "", "" }; option = m_og_sla->get_option("pad_enable"); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index b6a340d08..2bf9b6332 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -37,7 +37,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("If this is enabled, Slic3r will prompt the last output directory " "instead of the one containing the input files."); - def.default_value = new ConfigOptionBool{ app_config->has("remember_output_path") ? app_config->get("remember_output_path") == "1" : true }; + def.set_default_value(new ConfigOptionBool{ app_config->has("remember_output_path") ? app_config->get("remember_output_path") == "1" : true }); Option option(def, "remember_output_path"); m_optgroup->append_single_option_line(option); @@ -45,7 +45,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("If this is enabled, Slic3r will auto-center objects " "around the print bed center."); - def.default_value = new ConfigOptionBool{ app_config->get("autocenter") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("autocenter") == "1" }); option = Option (def,"autocenter"); m_optgroup->append_single_option_line(option); @@ -53,7 +53,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("If this is enabled, Slic3r will pre-process objects as soon " "as they\'re loaded in order to save time when exporting G-code."); - def.default_value = new ConfigOptionBool{ app_config->get("background_processing") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("background_processing") == "1" }); option = Option (def,"background_processing"); m_optgroup->append_single_option_line(option); @@ -61,7 +61,7 @@ void PreferencesDialog::build() def.label = L("Check for application updates"); def.type = coBool; def.tooltip = L("If enabled, Slic3r checks for new versions of " SLIC3R_APP_NAME " online. When a new version becomes available a notification is displayed at the next application startup (never during program usage). This is only a notification mechanisms, no automatic installation is done."); - def.default_value = new ConfigOptionBool(app_config->get("version_check") == "1"); + def.set_default_value(new ConfigOptionBool(app_config->get("version_check") == "1")); option = Option (def, "version_check"); m_optgroup->append_single_option_line(option); @@ -69,7 +69,7 @@ void PreferencesDialog::build() def.label = L("Update built-in Presets automatically"); def.type = coBool; def.tooltip = L("If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup."); - def.default_value = new ConfigOptionBool(app_config->get("preset_update") == "1"); + def.set_default_value(new ConfigOptionBool(app_config->get("preset_update") == "1")); option = Option (def, "preset_update"); m_optgroup->append_single_option_line(option); @@ -77,7 +77,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("Suppress \" - default - \" presets in the Print / Filament / Printer " "selections once there are any other valid presets available."); - def.default_value = new ConfigOptionBool{ app_config->get("no_defaults") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("no_defaults") == "1" }); option = Option (def,"no_defaults"); m_optgroup->append_single_option_line(option); @@ -85,7 +85,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("When checked, the print and filament presets are shown in the preset editor " "even if they are marked as incompatible with the active printer"); - def.default_value = new ConfigOptionBool{ app_config->get("show_incompatible_presets") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("show_incompatible_presets") == "1" }); option = Option (def,"show_incompatible_presets"); m_optgroup->append_single_option_line(option); @@ -95,7 +95,7 @@ void PreferencesDialog::build() def.tooltip = L("If you have rendering issues caused by a buggy OpenGL 2.0 driver, " "you may try to check this checkbox. This will disable the layer height " "editing and anti aliasing, so it is likely better to upgrade your graphics driver."); - def.default_value = new ConfigOptionBool{ app_config->get("use_legacy_opengl") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("use_legacy_opengl") == "1" }); option = Option (def,"use_legacy_opengl"); m_optgroup->append_single_option_line(option); @@ -104,7 +104,7 @@ void PreferencesDialog::build() def.type = coBool; def.tooltip = L("If enabled, the 3D scene will be rendered in Retina resolution. " "If you are experiencing 3D performance problems, disabling this option may help."); - def.default_value = new ConfigOptionBool{ app_config->get("use_retina_opengl") == "1" }; + def.set_default_value(new ConfigOptionBool{ app_config->get("use_retina_opengl") == "1" }); option = Option (def, "use_retina_opengl"); m_optgroup->append_single_option_line(option); #endif diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fb8147ad2..129643d18 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -815,6 +815,19 @@ void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bo update(); } +static wxString support_combo_value_for_config(const DynamicPrintConfig &config, bool is_fff) +{ + const std::string support = is_fff ? "support_material" : "supports_enable"; + const std::string buildplate_only = is_fff ? "support_material_buildplate_only" : "support_buildplate_only"; + return + ! config.opt_bool(support) ? + _("None") : + (is_fff && !config.opt_bool("support_material_auto")) ? + _("For support enforcers only") : + (config.opt_bool(buildplate_only) ? _("Support on build plate only") : + _("Everywhere")); +} + void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { if (wxGetApp().plater() == nullptr) { @@ -822,23 +835,17 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) } const bool is_fff = supports_printer_technology(ptFFF); - ConfigOptionsGroup* og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); + ConfigOptionsGroup* og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); if (opt_key == "fill_density" || opt_key == "pad_enable") { boost::any val = og_freq_chng_params->get_config_value(*m_config, opt_key); og_freq_chng_params->set_value(opt_key, val); } - if ( is_fff && (opt_key == "support_material" || opt_key == "support_material_buildplate_only") || - !is_fff && (opt_key == "supports_enable" || opt_key == "support_buildplate_only")) - { - const std::string support = is_fff ? "support_material" : "supports_enable"; - const std::string buildplate_only = is_fff ? "support_material_buildplate_only" : "support_buildplate_only"; - wxString new_selection = !m_config->opt_bool(support) ? _("None") : - m_config->opt_bool(buildplate_only) ? _("Support on build plate only") : - _("Everywhere"); - og_freq_chng_params->set_value("support", new_selection); - } + if (is_fff ? + (opt_key == "support_material" || opt_key == "support_material_auto" || opt_key == "support_material_buildplate_only") : + (opt_key == "supports_enable" || opt_key == "support_buildplate_only")) + og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); if (opt_key == "brim_width") { @@ -964,18 +971,11 @@ void Tab::update_preset_description_line() void Tab::update_frequently_changed_parameters() { - auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(supports_printer_technology(ptFFF)); + const bool is_fff = supports_printer_technology(ptFFF); + auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); if (!og_freq_chng_params) return; - const bool is_fff = supports_printer_technology(ptFFF); - - const std::string support = is_fff ? "support_material" : "supports_enable"; - const std::string buildplate_only = is_fff ? "support_material_buildplate_only" : "support_buildplate_only"; - - wxString new_selection = !m_config->opt_bool(support) ? _("None") : - m_config->opt_bool(buildplate_only) ? _("Support on build plate only") : - _("Everywhere"); - og_freq_chng_params->set_value("support", new_selection); + og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); const std::string updated_value_key = is_fff ? "fill_density" : "pad_enable"; @@ -1840,7 +1840,7 @@ void TabPrinter::build_fff() optgroup = page->new_optgroup(_(L("Capabilities"))); ConfigOptionDef def; def.type = coInt, - def.default_value = new ConfigOptionInt(1); + def.set_default_value(new ConfigOptionInt(1)); def.label = L("Extruders"); def.tooltip = L("Number of extruders of the printer."); def.min = 1; @@ -2148,13 +2148,13 @@ PageShp TabPrinter::build_kinematics_page() def.gui_type = "legend"; def.mode = comAdvanced; def.tooltip = L("Values in this column are for Full Power mode"); - def.default_value = new ConfigOptionString{ L("Full Power") }; + def.set_default_value(new ConfigOptionString{ L("Full Power") }); auto option = Option(def, "full_power_legend"); line.append_option(option); def.tooltip = L("Values in this column are for Silent mode"); - def.default_value = new ConfigOptionString{ L("Silent") }; + def.set_default_value(new ConfigOptionString{ L("Silent") }); option = Option(def, "silent_legend"); line.append_option(option); diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index f9482bd3b..4d48a2c6f 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -223,8 +223,8 @@ print_config_def() (void)hv_stores( hv, "labels", newRV_noinc((SV*)av) ); } - if (optdef->default_value != NULL) - (void)hv_stores( hv, "default", ConfigOption_to_SV(*optdef->default_value, *optdef) ); + if (optdef->default_value) + (void)hv_stores( hv, "default", ConfigOption_to_SV(*optdef->default_value.get(), *optdef) ); (void)hv_store( options_hv, opt_key.c_str(), opt_key.length(), newRV_noinc((SV*)hv), 0 ); } From 09d80b1b2ad2a591b32822ec2cb3cc6fe99f70a3 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 3 May 2019 18:30:58 +0200 Subject: [PATCH 15/15] Added ConfigDef::get_default_value<>() template, refactored calling code to use it. --- src/libslic3r/Config.hpp | 4 +++- src/slic3r/GUI/ConfigWizard.cpp | 10 ++++------ src/slic3r/GUI/Field.cpp | 28 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 625335de6..ee4bc4e46 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1011,8 +1011,10 @@ public: // What type? bool, int, string etc. ConfigOptionType type = coNone; // Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor. - Slic3r::clonable_ptr default_value = nullptr; + Slic3r::clonable_ptr default_value; void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr(ptr); } + template + const T* get_default_value() const { return static_cast(this->default_value.get()); } // Usually empty. // Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection, diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index bd45104c4..4fbaa4563 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -544,14 +544,12 @@ PageDiameters::PageDiameters(ConfigWizard *parent) { spin_nozzle->SetDigits(2); spin_nozzle->SetIncrement(0.1); - const auto &def_nozzle = *print_config_def.get("nozzle_diameter"); - auto *default_nozzle = dynamic_cast(def_nozzle.default_value.get()); + auto *default_nozzle = print_config_def.get("nozzle_diameter")->get_default_value(); spin_nozzle->SetValue(default_nozzle != nullptr && default_nozzle->size() > 0 ? default_nozzle->get_at(0) : 0.5); spin_filam->SetDigits(2); spin_filam->SetIncrement(0.25); - const auto &def_filam = *print_config_def.get("filament_diameter"); - auto *default_filam = dynamic_cast(def_filam.default_value.get()); + auto *default_filam = print_config_def.get("filament_diameter")->get_default_value(); spin_filam->SetValue(default_filam != nullptr && default_filam->size() > 0 ? default_filam->get_at(0) : 3.0); append_text(_(L("Enter the diameter of your printer's hot end nozzle."))); @@ -596,13 +594,13 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent) spin_extr->SetIncrement(5.0); const auto &def_extr = *print_config_def.get("temperature"); spin_extr->SetRange(def_extr.min, def_extr.max); - auto *default_extr = dynamic_cast(def_extr.default_value.get()); + auto *default_extr = def_extr.get_default_value(); spin_extr->SetValue(default_extr != nullptr && default_extr->size() > 0 ? default_extr->get_at(0) : 200); spin_bed->SetIncrement(5.0); const auto &def_bed = *print_config_def.get("bed_temperature"); spin_bed->SetRange(def_bed.min, def_bed.max); - auto *default_bed = dynamic_cast(def_bed.default_value.get()); + auto *default_bed = def_bed.get_default_value(); spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0); append_text(_(L("Enter the temperature needed for extruding your filament."))); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 02f58667c..5e06efa29 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -203,7 +203,7 @@ void TextCtrl::BUILD() { case coFloatOrPercent: { text_value = double_to_string(m_opt.default_value->getFloat()); - if (static_cast(m_opt.default_value.get())->percent) + if (m_opt.get_default_value()->percent) text_value += "%"; break; } @@ -218,19 +218,19 @@ void TextCtrl::BUILD() { case coFloat: { double val = m_opt.type == coFloats ? - static_cast(m_opt.default_value.get())->get_at(m_opt_idx) : + m_opt.get_default_value()->get_at(m_opt_idx) : m_opt.type == coFloat ? m_opt.default_value->getFloat() : - static_cast(m_opt.default_value.get())->get_at(m_opt_idx); + m_opt.get_default_value()->get_at(m_opt_idx); text_value = double_to_string(val); break; } case coString: - text_value = static_cast(m_opt.default_value.get())->value; + text_value = m_opt.get_default_value()->value; break; case coStrings: { - const ConfigOptionStrings *vec = static_cast(m_opt.default_value.get()); + const ConfigOptionStrings *vec = m_opt.get_default_value(); if (vec == nullptr || vec->empty()) break; //for the case of empty default value text_value = vec->get_at(m_opt_idx); break; @@ -373,8 +373,8 @@ void CheckBox::BUILD() { bool check_value = m_opt.type == coBool ? m_opt.default_value->getBool() : m_opt.type == coBools ? - static_cast(m_opt.default_value.get())->get_at(m_opt_idx) : - false; + m_opt.get_default_value()->get_at(m_opt_idx) : + false; // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); @@ -427,7 +427,7 @@ void SpinCtrl::BUILD() { break; case coInts: { - const ConfigOptionInts *vec = static_cast(m_opt.default_value.get()); + const ConfigOptionInts *vec = m_opt.get_default_value(); if (vec == nullptr || vec->empty()) break; for (size_t id = 0; id < vec->size(); ++id) { @@ -629,7 +629,7 @@ void Choice::set_selection() break; } case coEnum:{ - int id_value = static_cast*>(m_opt.default_value.get())->value; //!! + int id_value = m_opt.get_default_value>()->value; //!! field->SetSelection(id_value); break; } @@ -649,7 +649,7 @@ void Choice::set_selection() break; } case coStrings:{ - text_value = static_cast(m_opt.default_value.get())->get_at(m_opt_idx); + text_value = m_opt.get_default_value()->get_at(m_opt_idx); size_t idx = 0; for (auto el : m_opt.enum_values) @@ -886,7 +886,7 @@ void ColourPicker::BUILD() if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); // Validate the color - wxString clr_str(static_cast(m_opt.default_value.get())->get_at(m_opt_idx)); + wxString clr_str(m_opt.get_default_value()->get_at(m_opt_idx)); wxColour clr(clr_str); if (! clr.IsOk()) { clr = wxTransparentColour; @@ -920,7 +920,7 @@ void PointCtrl::BUILD() const wxSize field_size(4 * m_em_unit, -1); - auto default_pt = static_cast(m_opt.default_value.get())->values.at(0); + auto default_pt = m_opt.get_default_value()->values.at(0); double val = default_pt(0); wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); val = default_pt(1); @@ -1019,7 +1019,7 @@ void StaticText::BUILD() if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - const wxString legend(static_cast(m_opt.default_value.get())->value); + const wxString legend(m_opt.get_default_value()->value); auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size, wxST_ELLIPSIZE_MIDDLE); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); temp->SetBackgroundStyle(wxBG_STYLE_PAINT); @@ -1054,7 +1054,7 @@ void SliderCtrl::BUILD() auto temp = new wxBoxSizer(wxHORIZONTAL); - auto def_val = static_cast(m_opt.default_value.get())->value; + auto def_val = m_opt.get_default_value()->value; auto min = m_opt.min == INT_MIN ? 0 : m_opt.min; auto max = m_opt.max == INT_MAX ? 100 : m_opt.max;