diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 97e78798f..74ea52c64 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -181,6 +181,9 @@ bool GUI_App::OnInit() if (app_config->dirty()) app_config->save(); + + if (this->plater() != nullptr) + this->obj_manipul()->update_if_dirty(); }); // On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 8cc2362e8..7955326f5 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -47,6 +47,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_og->m_fill_empty_value = [this](const std::string& opt_key) { + this->update_if_dirty(); + std::string param; std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); @@ -83,6 +85,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_og->m_set_focus = [this](const std::string& opt_key) { + this->update_if_dirty(); wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true); }; @@ -179,22 +182,19 @@ bool ObjectManipulation::IsShown() void ObjectManipulation::UpdateAndShow(const bool show) { - if (show) + if (show) { update_settings_value(wxGetApp().plater()->canvas3D()->get_selection()); + update_if_dirty(); + } OG_Settings::UpdateAndShow(show); } -int ObjectManipulation::ol_selection() -{ - return wxGetApp().obj_list()->get_selected_obj_idx(); -} - void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) { - wxString move_label = _(L("Position:")); - wxString rotate_label = _(L("Rotation:")); - wxString scale_label = _(L("Scale factors:")); + m_new_move_label_string = L("Position:"); + m_new_rotate_label_string = L("Rotation:"); + m_new_scale_label_string = L("Scale factors:"); #if ENABLE_MODELVOLUME_TRANSFORM if (selection.is_single_full_instance()) #else @@ -205,10 +205,10 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele { // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - update_position_value(volume->get_offset()); - update_rotation_value(volume->get_rotation()); - update_scale_value(volume->get_scaling_factor()); - m_og->enable(); + m_new_position = volume->get_offset(); + m_new_rotation = volume->get_rotation(); + m_new_scale = volume->get_scaling_factor(); + m_new_enabled = true; } else reset_settings_value(); @@ -219,143 +219,104 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); #if ENABLE_MODELVOLUME_TRANSFORM - update_position_value(volume->get_instance_offset()); - update_rotation_value(volume->get_instance_rotation()); - update_scale_value(volume->get_instance_scaling_factor()); - update_size_value(volume->get_instance_transformation().get_matrix(true, true) * volume->bounding_box.size()); + m_new_position = volume->get_instance_offset(); + m_new_rotation = volume->get_instance_rotation(); + m_new_scale = volume->get_instance_scaling_factor(); + m_new_size = volume->get_instance_transformation().get_matrix(true, true) * volume->bounding_box.size(); #else - update_position_value(volume->get_offset()); - update_rotation_value(volume->get_rotation()); - update_scale_value(volume->get_scaling_factor()); + m_new_position = volume->get_offset(); + m_new_rotation = volume->get_rotation(); + m_new_scale = volume->get_scaling_factor(); #endif // ENABLE_MODELVOLUME_TRANSFORM - m_og->enable(); + m_new_enabled = true; } else if (selection.is_single_full_object()) { const BoundingBoxf3& box = selection.get_bounding_box(); - update_position_value(box.center()); - reset_rotation_value(); - reset_scale_value(); - update_size_value(box.size()); - rotate_label = _(L("Rotate:")); - scale_label = _(L("Scale:")); - m_og->enable(); + m_new_position = box.center(); + m_new_rotation = Vec3d::Zero(); + m_new_scale = Vec3d(1.0, 1.0, 1.0); + m_new_size = box.size(); + m_new_rotate_label_string = L("Rotate:"); + m_new_scale_label_string = L("Scale:"); + m_new_enabled = true; } else if (selection.is_single_modifier() || selection.is_single_volume()) { // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); #if ENABLE_MODELVOLUME_TRANSFORM - update_position_value(volume->get_volume_offset()); - update_rotation_value(volume->get_volume_rotation()); - update_scale_value(volume->get_volume_scaling_factor()); - update_size_value(volume->bounding_box.size()); + 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->bounding_box.size(); #else - update_position_value(volume->get_offset()); - update_rotation_value(volume->get_rotation()); - update_scale_value(volume->get_scaling_factor()); + m_new_position = volume->get_offset(); + m_new_rotation = volume->get_rotation(); + m_new_scale = volume->get_scaling_factor(); #endif // ENABLE_MODELVOLUME_TRANSFORM - m_og->enable(); + m_new_enabled = true; } else if (wxGetApp().obj_list()->multiple_selection()) { reset_settings_value(); - move_label = _(L("Translate:")); - rotate_label = _(L("Rotate:")); - scale_label = _(L("Scale:")); - update_size_value(selection.get_bounding_box().size()); - m_og->enable(); + m_new_move_label_string = L("Translate:"); + m_new_rotate_label_string = L("Rotate:"); + m_new_scale_label_string = L("Scale:"); + m_new_size = selection.get_bounding_box().size(); + m_new_enabled = true; } else reset_settings_value(); - m_move_Label->SetLabel(move_label); - m_rotate_Label->SetLabel(rotate_label); - m_scale_Label->SetLabel(scale_label); + m_dirty = true; +} + +void ObjectManipulation::update_if_dirty() +{ + if (! m_dirty) + return; + + m_move_Label->SetLabel(_(m_new_move_label_string)); + m_rotate_Label->SetLabel(_(m_new_rotate_label_string)); + m_scale_Label->SetLabel(_(m_new_scale_label_string)); + + m_og->set_value("position_x", double_to_string(m_new_position(0), 2)); + m_og->set_value("position_y", double_to_string(m_new_position(1), 2)); + m_og->set_value("position_z", double_to_string(m_new_position(2), 2)); + cache_position = m_new_position; + + auto scale = m_new_scale * 100.0; + m_og->set_value("scale_x", double_to_string(scale(0), 2)); + m_og->set_value("scale_y", double_to_string(scale(1), 2)); + m_og->set_value("scale_z", double_to_string(scale(2), 2)); + cache_scale = scale; + + m_og->set_value("size_x", double_to_string(m_new_size(0), 2)); + m_og->set_value("size_y", double_to_string(m_new_size(1), 2)); + m_og->set_value("size_z", double_to_string(m_new_size(2), 2)); + cache_size = m_new_size; + + m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(0)), 0), 2)); + m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(1)), 0), 2)); + m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(2)), 0), 2)); + cache_rotation = m_new_rotation; + + if (m_new_enabled) + m_og->enable(); + else + m_og->disable(); + + m_dirty = false; } void ObjectManipulation::reset_settings_value() { - reset_position_value(); - reset_rotation_value(); - reset_scale_value(); - m_og->disable(); -} - -wxString def_0 {"0"}; -wxString def_100 {"100"}; - -void ObjectManipulation::reset_position_value() -{ - m_og->set_value("position_x", def_0); - m_og->set_value("position_y", def_0); - m_og->set_value("position_z", def_0); - - cache_position = Vec3d::Zero(); -} - -void ObjectManipulation::reset_rotation_value() -{ - m_og->set_value("rotation_x", def_0); - m_og->set_value("rotation_y", def_0); - m_og->set_value("rotation_z", def_0); - - cache_rotation = Vec3d::Zero(); -} - -void ObjectManipulation::reset_scale_value() -{ - m_og->set_value("scale_x", def_100); - m_og->set_value("scale_y", def_100); - m_og->set_value("scale_z", def_100); - - cache_scale = Vec3d(100.0, 100.0, 100.0); -} - -void ObjectManipulation::reset_size_value() -{ - m_og->set_value("size_x", def_0); - m_og->set_value("size_y", def_0); - m_og->set_value("size_z", def_0); - - cache_size = Vec3d::Zero(); -} - -void ObjectManipulation::update_position_value(const Vec3d& position) -{ - m_og->set_value("position_x", double_to_string(position(0), 2)); - m_og->set_value("position_y", double_to_string(position(1), 2)); - m_og->set_value("position_z", double_to_string(position(2), 2)); - - cache_position = position; -} - -void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor) -{ - auto scale = scaling_factor * 100.0; - m_og->set_value("scale_x", double_to_string(scale(0), 2)); - m_og->set_value("scale_y", double_to_string(scale(1), 2)); - m_og->set_value("scale_z", double_to_string(scale(2), 2)); - - cache_scale = scale; -} - -void ObjectManipulation::update_size_value(const Vec3d& size) -{ - m_og->set_value("size_x", double_to_string(size(0), 2)); - m_og->set_value("size_y", double_to_string(size(1), 2)); - m_og->set_value("size_z", double_to_string(size(2), 2)); - - cache_size = size; -} - -void ObjectManipulation::update_rotation_value(const Vec3d& rotation) -{ - m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(rotation(0)), 0), 2)); - m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(rotation(1)), 0), 2)); - m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(rotation(2)), 0), 2)); - - cache_rotation = rotation; + m_new_position = Vec3d::Zero(); + m_new_rotation = Vec3d::Zero(); + m_new_scale = Vec3d(1.0, 1.0, 1.0); + m_new_size = Vec3d::Zero(); + m_new_enabled = false; } void ObjectManipulation::change_position_value(const Vec3d& position) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 0ada37b96..cbac94058 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -23,6 +23,19 @@ class ObjectManipulation : public OG_Settings wxStaticText* m_scale_Label = nullptr; wxStaticText* m_rotate_Label = nullptr; + + // Needs to be updated from OnIdle? + bool m_dirty = false; + // Cached labels for the delayed update, not localized! + std::string m_new_move_label_string; + std::string m_new_rotate_label_string; + std::string m_new_scale_label_string; + Vec3d m_new_position; + Vec3d m_new_rotation; + Vec3d m_new_scale; + Vec3d m_new_size; + bool m_new_enabled; + public: ObjectManipulation(wxWindow* parent); ~ObjectManipulation() {} @@ -31,19 +44,14 @@ public: bool IsShown() override; void UpdateAndShow(const bool show) override; - int ol_selection(); + void update_settings_value(const GLCanvas3D::Selection& selection); - void update_settings_value(const GLCanvas3D::Selection& selection); + // Called from the App to update the UI if dirty. + void update_if_dirty(); + +private: void reset_settings_value(); - void reset_position_value(); - void reset_rotation_value(); - void reset_scale_value(); - void reset_size_value(); - // update position values displacements or "gizmos" - void update_position_value(const Vec3d& position); - // update scale values after scale unit changing or "gizmos" - void update_scale_value(const Vec3d& scaling_factor); // update size values after scale unit changing or "gizmos" void update_size_value(const Vec3d& size); // update rotation value after "gizmos"