From 5d2537af35e754950329f2e12c3c940435c8e4f0 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Apr 2019 11:01:59 +0200 Subject: [PATCH] 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);