diff options
author | Lukas Matena <lukasmatena@seznam.cz> | 2021-12-14 17:10:42 +0300 |
---|---|---|
committer | Lukas Matena <lukasmatena@seznam.cz> | 2021-12-14 17:10:42 +0300 |
commit | 7f9e519baf212cbae4b9a72d40a9071aa1ddf462 (patch) | |
tree | 6857fed15a817ad9d422549309fdb29c94f5e640 /src/slic3r/GUI | |
parent | 6204d107eef946f42fdac8dcc4e2d38e700aac49 (diff) | |
parent | e2ac37e7178e994680aaf9e894619c4cfb2e92a0 (diff) |
Merge branch 'master' into dev
Diffstat (limited to 'src/slic3r/GUI')
-rw-r--r-- | src/slic3r/GUI/BedShapeDialog.cpp | 4 | ||||
-rw-r--r-- | src/slic3r/GUI/BitmapComboBox.cpp | 4 | ||||
-rw-r--r-- | src/slic3r/GUI/ConfigManipulation.cpp | 7 | ||||
-rw-r--r-- | src/slic3r/GUI/GCodeViewer.cpp | 41 | ||||
-rw-r--r-- | src/slic3r/GUI/GUI.cpp | 4 | ||||
-rw-r--r-- | src/slic3r/GUI/GUI_App.cpp | 68 | ||||
-rw-r--r-- | src/slic3r/GUI/GUI_ObjectList.cpp | 13 | ||||
-rw-r--r-- | src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 2 | ||||
-rw-r--r-- | src/slic3r/GUI/MainFrame.cpp | 54 | ||||
-rw-r--r-- | src/slic3r/GUI/MsgDialog.cpp | 28 | ||||
-rw-r--r-- | src/slic3r/GUI/MsgDialog.hpp | 10 | ||||
-rw-r--r-- | src/slic3r/GUI/OptionsGroup.hpp | 2 | ||||
-rw-r--r-- | src/slic3r/GUI/Plater.cpp | 66 | ||||
-rw-r--r-- | src/slic3r/GUI/Preferences.cpp | 4 | ||||
-rw-r--r-- | src/slic3r/GUI/Selection.cpp | 3 | ||||
-rw-r--r-- | src/slic3r/GUI/Tab.cpp | 15 | ||||
-rw-r--r-- | src/slic3r/GUI/UnsavedChangesDialog.cpp | 16 | ||||
-rw-r--r-- | src/slic3r/GUI/UpdateDialogs.cpp | 2 |
18 files changed, 194 insertions, 149 deletions
diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 2d46a5228..246c8b63e 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -109,7 +109,7 @@ wxString BedShape::get_full_name_with_params() default: // rectangle, convex, concave... out += "\n" + _(get_option_label(Parameter::RectSize)) + ": [" + ConfigOptionPoint(to_2d(m_build_volume.bounding_volume().size())).serialize() + "]"; - out += "\n" + _(get_option_label(Parameter::RectOrigin)) + ": [" + ConfigOptionPoint(to_2d(m_build_volume.bounding_volume().min)).serialize() + "]"; + out += "\n" + _(get_option_label(Parameter::RectOrigin)) + ": [" + ConfigOptionPoint(- to_2d(m_build_volume.bounding_volume().min)).serialize() + "]"; break; } return out; @@ -124,7 +124,7 @@ void BedShape::apply_optgroup_values(ConfigOptionsGroupShp optgroup) default: // rectangle, convex, concave... optgroup->set_value("rect_size" , new ConfigOptionPoints{ to_2d(m_build_volume.bounding_volume().size()) }); - optgroup->set_value("rect_origin" , new ConfigOptionPoints{ to_2d(m_build_volume.bounding_volume().min) }); + optgroup->set_value("rect_origin" , new ConfigOptionPoints{ - to_2d(m_build_volume.bounding_volume().min) }); } } diff --git a/src/slic3r/GUI/BitmapComboBox.cpp b/src/slic3r/GUI/BitmapComboBox.cpp index 24bc8dcfd..3396c627b 100644 --- a/src/slic3r/GUI/BitmapComboBox.cpp +++ b/src/slic3r/GUI/BitmapComboBox.cpp @@ -254,8 +254,8 @@ void BitmapComboBox::DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED( dc.SetTextForeground(flags & ODCB_PAINTING_DISABLED ? wxColour(108,108,108) : wxGetApp().get_label_clr_default()); wxColour selCol = flags & ODCB_PAINTING_DISABLED ? -#ifdef _MSW_DAEK_MODE - wxRGBToColour(NppDarkMode::InvertLightnessSofter(NppDarkMode::GetBackgroundColor())) : +#ifdef _MSW_DARK_MODE + wxRGBToColour(NppDarkMode::GetSofterBackgroundColor()) : #else wxGetApp().get_highlight_default_clr() : #endif diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index fe108b1a6..8defc4554 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -155,7 +155,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con apply(config, &new_conf); } - if (config->opt_bool("support_material")) { + // Check "support_material" and "overhangs" relations only on global settings level + if (is_global_config && config->opt_bool("support_material")) { // Ask only once. if (!m_support_material_overhangs_queried) { m_support_material_overhangs_queried = true; @@ -164,10 +165,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "- Detect bridging perimeters")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings for supports?")); - MessageDialog dialog(m_msg_dlg_parent, msg_text, _L("Support Generator"), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); + MessageDialog dialog(m_msg_dlg_parent, msg_text, _L("Support Generator"), wxICON_WARNING | wxYES | wxNO); DynamicPrintConfig new_conf = *config; auto answer = dialog.ShowModal(); - if (!is_global_config || answer == wxID_YES) { + if (answer == wxID_YES) { // Enable "detect bridging perimeters". new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 574ba6ec5..6b9ba5da9 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -581,14 +581,14 @@ void GCodeViewer::init() case EMoveType::Retract: case EMoveType::Unretract: case EMoveType::Seam: { - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; - buffer.shader = "gouraud_light_instanced"; - buffer.model.model.init_from(diamond(16)); - buffer.model.color = option_color(type); - buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; - } - else { +// if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { +// buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; +// buffer.shader = "gouraud_light_instanced"; +// buffer.model.model.init_from(diamond(16)); +// buffer.model.color = option_color(type); +// buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; +// } +// else { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.shader = "gouraud_light"; @@ -596,7 +596,7 @@ void GCodeViewer::init() buffer.model.data = diamond(16); buffer.model.color = option_color(type); buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; - } +// } break; } case EMoveType::Wipe: @@ -608,7 +608,7 @@ void GCodeViewer::init() } case EMoveType::Travel: { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; - buffer.vertices.format = VBuffer::EFormat::PositionNormal1; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.shader = "toolpaths_lines"; break; } @@ -1140,15 +1140,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) // format data into the buffers to be rendered as lines auto add_vertices_as_line = [](const GCodeProcessorResult::MoveVertex& prev, const GCodeProcessorResult::MoveVertex& curr, VertexBuffer& vertices) { // x component of the normal to the current segment (the normal is parallel to the XY plane) - const float normal_x = (curr.position - prev.position).normalized().y(); + const Vec3f dir = (curr.position - prev.position).normalized(); + Vec3f normal(dir.y(), -dir.x(), 0.0); + normal.normalize(); - auto add_vertex = [&vertices, normal_x](const GCodeProcessorResult::MoveVertex& vertex) { + auto add_vertex = [&vertices, &normal](const GCodeProcessorResult::MoveVertex& vertex) { // add position vertices.push_back(vertex.position.x()); vertices.push_back(vertex.position.y()); vertices.push_back(vertex.position.z()); - // add normal x component - vertices.push_back(normal_x); + // add normal + vertices.push_back(normal.x()); + vertices.push_back(normal.y()); + vertices.push_back(normal.z()); }; // add previous vertex @@ -2654,6 +2658,9 @@ void GCodeViewer::render_toolpaths() for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { const RenderPath& path = *it; + // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. + assert(! path.sizes.empty()); + assert(! path.offsets.empty()); glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS @@ -2675,6 +2682,9 @@ void GCodeViewer::render_toolpaths() ](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) { for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { const RenderPath& path = *it; + // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. + assert(! path.sizes.empty()); + assert(! path.offsets.empty()); glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS @@ -2690,6 +2700,9 @@ void GCodeViewer::render_toolpaths() ](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) { for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { const RenderPath& path = *it; + // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. + assert(! path.sizes.empty()); + assert(! path.offsets.empty()); glsafe(::glUniform4fv(uniform_color, 1, static_cast<const GLfloat*>(path.color.data()))); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 8fe951292..fb7fa00f1 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -352,7 +352,7 @@ void show_substitutions_info(const PresetsConfigSubstitutions& presets_config_su add_config_substitutions(substitution.substitutions, changes); } - InfoDialog msg(nullptr, _L("Configuration bundle was loaded, however some configuration values were not recognized."), substitution_message(changes)); + InfoDialog msg(nullptr, _L("Configuration bundle was loaded, however some configuration values were not recognized."), substitution_message(changes), true); msg.ShowModal(); } @@ -363,7 +363,7 @@ void show_substitutions_info(const ConfigSubstitutions& config_substitutions, co InfoDialog msg(nullptr, format_wxstr(_L("Configuration file \"%1%\" was loaded, however some configuration values were not recognized."), from_u8(filename)), - substitution_message(changes)); + substitution_message(changes), true); msg.ShowModal(); } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 0c40000e5..e4078c9c1 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -948,24 +948,31 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup) return false; BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path; // ask about using older data folder - RichMessageDialog msg(nullptr, backup ? - wxString::Format(_L( - "Current configuration folder: %s" - "\n\n%s found another configuration for version %s." - "\nIt is found at %s." - "\n\nDo you wish to copy and use the configuration file for version %s (overwriting any file with the same name)? A backup of your current configuration will be created." - "\nIf you select no, you will continue with the configuration file for version %s (may not be fully compatible).") - , current_version.to_string(), SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string(), current_version.to_string()) - : wxString::Format(_L( - "%s found another configuration for version %s." - "\nIt is found at %s." - "\nThere is no configuration file in current configuration folder." - "\n\nDo you wish to copy and use the configuration file for version %s?" - "\nIf you select no, you will start with clean installation with configuration wizard.") - , SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path, last_semver.to_string()) - , _L("PrusaSlicer") - , wxYES_NO - , wxString::Format(_L("Load configuration from version %s?"), last_semver.to_string())); + + InfoDialog msg(nullptr + , format_wxstr(_L("You are opening %1% version %2%."), SLIC3R_APP_NAME, SLIC3R_VERSION) + , backup ? + format_wxstr(_L( + "The active configuration was created by <b>%1% %2%</b>," + "\nwhile a newer configuration was found in <b>%3%</b>" + "\ncreated by <b>%1% %4%</b>." + "\n\nShall the newer configuration be imported?" + "\nIf so, your active configuration will be backed up before importing the new configuration." + ) + , SLIC3R_APP_NAME, current_version.to_string(), m_older_data_dir_path, last_semver.to_string()) + : format_wxstr(_L( + "An existing configuration was found in <b>%3%</b>" + "\ncreated by <b>%1% %2%</b>." + "\n\nShall this configuration be imported?" + ) + , SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path) + , true, wxYES_NO); + + if (backup) { + msg.SetButtonLabel(wxID_YES, _L("Import")); + msg.SetButtonLabel(wxID_NO, _L("Don't import")); + } + if (msg.ShowModal() == wxID_YES) { std::string snapshot_id; if (backup) { @@ -1033,6 +1040,9 @@ bool GUI_App::OnInit() bool GUI_App::on_init_inner() { + // Set initialization of image handlers before any UI actions - See GH issue #7469 + wxInitAllImageHandlers(); + #if defined(_WIN32) && ! defined(_WIN64) // Win32 32bit build. if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") { @@ -1096,6 +1106,14 @@ bool GUI_App::on_init_inner() } } + // Set language and color mode before check_older_app_config() call + + // If load_language() fails, the application closes. + load_language(wxString(), true); +#ifdef _MSW_DARK_MODE + NppDarkMode::InitDarkMode(app_config->get("dark_color_mode") == "1", app_config->get("sys_menu_enabled") == "1"); +#endif + if (m_last_config_version) { if (*m_last_config_version < *Semver::parse(SLIC3R_VERSION)) check_older_app_config(*m_last_config_version, true); @@ -1106,14 +1124,6 @@ bool GUI_App::on_init_inner() app_config->set("version", SLIC3R_VERSION); app_config->save(); - // If load_language() fails, the application closes. - load_language(wxString(), true); - - wxInitAllImageHandlers(); - -#ifdef _MSW_DARK_MODE - NppDarkMode::InitDarkMode(app_config->get("dark_color_mode") == "1", app_config->get("sys_menu_enabled") == "1"); -#endif SplashScreen* scrn = nullptr; if (app_config->get("show_splash_screen") == "1") { // make a bitmap with dark grey banner on the left side @@ -1137,8 +1147,6 @@ bool GUI_App::on_init_inner() scrn->SetText(_L("Loading configuration")+ dots); } - - preset_bundle = new PresetBundle(); // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory @@ -2160,9 +2168,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->Append(config_id_base + ConfigMenuLanguage, _L("&Language")); if (is_editor()) { local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _L("Flash printer &firmware"), _L("Upload a firmware image into an Arduino based printer")); + local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _L("Flash Printer &Firmware"), _L("Upload a firmware image into an Arduino based printer")); // TODO: for when we're able to flash dictionaries - // local_menu->Append(config_id_base + FirmwareMenuDict, _L("Flash language file"), _L("Upload a language dictionary file into a Prusa printer")); + // local_menu->Append(config_id_base + FirmwareMenuDict, _L("Flash Language File"), _L("Upload a language dictionary file into a Prusa printer")); } local_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent &event) { diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f4d27b0b2..160999db3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -349,7 +349,8 @@ void ObjectList::get_selection_indexes(std::vector<int>& obj_idxs, std::vector<i { wxDataViewItemArray sels; GetSelections(sels); - assert(!sels.IsEmpty()); + if (sels.IsEmpty()) + return; if ( m_objects_model->GetItemType(sels[0]) & itVolume || (sels.Count()==1 && m_objects_model->GetItemType(m_objects_model->GetParent(sels[0])) & itVolume) ) { @@ -424,7 +425,7 @@ MeshErrorsInfo ObjectList::get_mesh_errors_info(const int obj_idx, const int vol if (!stats.manifold()) { remaining_info = format_wxstr(_L_PLURAL("%1$d open edge", "%1$d open edges", stats.open_edges), stats.open_edges); - tooltip += _L("Remaning errors") + ":\n"; + tooltip += _L("Remaining errors") + ":\n"; tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d open edge", "%1$d open edges", stats.open_edges), stats.open_edges) + "\n"; } @@ -1556,7 +1557,7 @@ void ObjectList::load_modifier(ModelObject& model_object, std::vector<ModelVolum for (auto object : model.objects) { if (model_object.origin_translation != Vec3d::Zero()) { object->center_around_origin(); - Vec3d delta = model_object.origin_translation - object->origin_translation; + const Vec3d delta = model_object.origin_translation - object->origin_translation; for (auto volume : object->volumes) { volume->translate(delta); } @@ -1570,6 +1571,12 @@ void ObjectList::load_modifier(ModelObject& model_object, std::vector<ModelVolum new_volume->name = boost::filesystem::path(input_file).filename().string(); // set a default extruder value, since user can't add it manually new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + // update source data + new_volume->source.input_file = input_file; + new_volume->source.object_idx = obj_idx; + new_volume->source.volume_idx = int(model_object.volumes.size()) - 1; + if (model.objects.size() == 1 && model.objects.front()->volumes.size() == 1) + new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset; if (from_galery) { // Transform the new modifier to be aligned with the print bed. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 260e46563..fa59d7646 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -256,7 +256,7 @@ std::vector<std::vector<GLGizmoPainterBase::ProjectedMousePosition>> GLGizmoPain const Camera &camera = wxGetApp().plater()->get_camera(); std::vector<ProjectedMousePosition> mesh_hit_points; - mesh_hit_points.reserve(mouse_position.size()); + mesh_hit_points.reserve(mouse_positions.size()); // In mesh_hit_points only the last item could have mesh_id == -1, any other items mustn't. for (const Vec2d &mp : mouse_positions) { diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 8a9702c40..1e589e432 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1094,7 +1094,7 @@ static wxMenu* generate_help_menu() else append_menu_item(helpMenu, wxID_ANY, wxString::Format(_L("&About %s"), GCODEVIEWER_APP_NAME), _L("Show about dialog"), [](wxCommandEvent&) { Slic3r::GUI::about(); }); - append_menu_item(helpMenu, wxID_ANY, _L("Show Tip of the day"), _L("Opens Tip of the day notification in bottom right corner or shows another tip if already opened."), + append_menu_item(helpMenu, wxID_ANY, _L("Show Tip of the Day"), _L("Opens Tip of the day notification in bottom right corner or shows another tip if already opened."), [](wxCommandEvent&) { wxGetApp().plater()->get_notification_manager()->push_hint_notification(false); }); helpMenu->AppendSeparator(); append_menu_item(helpMenu, wxID_ANY, _L("Keyboard Shortcuts") + sep + "&?", _L("Show the list of the keyboard shortcuts"), @@ -1188,9 +1188,9 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { save_project(); }, "save", nullptr, [this](){return m_plater != nullptr && can_save(); }, this); #ifdef __APPLE__ - append_menu_item(fileMenu, wxID_ANY, _L("Save project &as") + dots + "\tCtrl+Shift+S", _L("Save current project file as"), + append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Shift+S", _L("Save current project file as"), #else - append_menu_item(fileMenu, wxID_ANY, _L("Save project &as") + dots + "\tCtrl+Alt+S", _L("Save current project file as"), + append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Alt+S", _L("Save current project file as"), #endif // __APPLE__ [this](wxCommandEvent&) { save_project_as(); }, "save", nullptr, [this](){return m_plater != nullptr && can_save_as(); }, this); @@ -1202,11 +1202,11 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr, [this](){return m_plater != nullptr; }, this); - append_menu_item(import_menu, wxID_ANY, _L("Import STL (imperial units)"), _L("Load an model saved with imperial units"), + append_menu_item(import_menu, wxID_ANY, _L("Import STL (Imperial Units)"), _L("Load an model saved with imperial units"), [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(true); }, "import_plater", nullptr, [this](){return m_plater != nullptr; }, this); - append_menu_item(import_menu, wxID_ANY, _L("Import SL1 / SL1S archive") + dots, _L("Load an SL1 / Sl1S archive"), + append_menu_item(import_menu, wxID_ANY, _L("Import SL1 / SL1S Archive") + dots, _L("Load an SL1 / Sl1S archive"), [this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr, [this](){return m_plater != nullptr && !m_plater->is_any_job_running(); }, this); @@ -1214,7 +1214,7 @@ void MainFrame::init_menubar_as_editor() append_menu_item(import_menu, wxID_ANY, _L("Import &Config") + dots + "\tCtrl+L", _L("Load exported configuration file"), [this](wxCommandEvent&) { load_config_file(); }, "import_config", nullptr, []() {return true; }, this); - append_menu_item(import_menu, wxID_ANY, _L("Import Config from &project") + dots +"\tCtrl+Alt+L", _L("Load configuration from project file"), + append_menu_item(import_menu, wxID_ANY, _L("Import Config from &Project") + dots +"\tCtrl+Alt+L", _L("Load configuration from project file"), [this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "import_config", nullptr, []() {return true; }, this); import_menu->AppendSeparator(); @@ -1232,22 +1232,22 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { if (m_plater) m_plater->send_gcode(); }, "export_gcode", nullptr, [this](){return can_send_gcode(); }, this); m_changeable_menu_items.push_back(item_send_gcode); - append_menu_item(export_menu, wxID_ANY, _L("Export G-code to SD card / Flash drive") + dots + "\tCtrl+U", _L("Export current plate as G-code to SD card / Flash drive"), + append_menu_item(export_menu, wxID_ANY, _L("Export G-code to SD Card / Flash Drive") + dots + "\tCtrl+U", _L("Export current plate as G-code to SD card / Flash drive"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(true); }, "export_to_sd", nullptr, [this]() {return can_export_gcode_sd(); }, this); export_menu->AppendSeparator(); - append_menu_item(export_menu, wxID_ANY, _L("Export plate as &STL") + dots, _L("Export current plate as STL"), + append_menu_item(export_menu, wxID_ANY, _L("Export Plate as &STL") + dots, _L("Export current plate as STL"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "export_plater", nullptr, [this](){return can_export_model(); }, this); - append_menu_item(export_menu, wxID_ANY, _L("Export plate as STL &including supports") + dots, _L("Export current plate as STL including supports"), + append_menu_item(export_menu, wxID_ANY, _L("Export Plate as STL &Including Supports") + dots, _L("Export current plate as STL including supports"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, "export_plater", nullptr, [this](){return can_export_supports(); }, this); // Deprecating AMF export. Let's wait for user feedback. -// append_menu_item(export_menu, wxID_ANY, _L("Export plate as &AMF") + dots, _L("Export current plate as AMF"), +// append_menu_item(export_menu, wxID_ANY, _L("Export Plate as &AMF") + dots, _L("Export current plate as AMF"), // [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "export_plater", nullptr, // [this](){return can_export_model(); }, this); export_menu->AppendSeparator(); - append_menu_item(export_menu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), + append_menu_item(export_menu, wxID_ANY, _L("Export &Toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr, [this]() {return can_export_toolpaths(); }, this); export_menu->AppendSeparator(); @@ -1262,7 +1262,7 @@ void MainFrame::init_menubar_as_editor() []() {return true; }, this); append_submenu(fileMenu, export_menu, wxID_ANY, _L("&Export"), ""); - append_menu_item(fileMenu, wxID_ANY, _L("Ejec&t SD card / Flash drive") + dots + "\tCtrl+T", _L("Eject SD card / Flash drive after the G-code was exported to it."), + append_menu_item(fileMenu, wxID_ANY, _L("Ejec&t SD Card / Flash Drive") + dots + "\tCtrl+T", _L("Eject SD card / Flash drive after the G-code was exported to it."), [this](wxCommandEvent&) { if (m_plater) m_plater->eject_drive(); }, "eject_sd", nullptr, [this]() {return can_eject(); }, this); @@ -1298,7 +1298,7 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { repair_stl(); }, "wrench", nullptr, []() { return true; }, this); fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_ANY, _L("&G-code preview") + dots, _L("Open G-code viewer"), + append_menu_item(fileMenu, wxID_ANY, _L("&G-code Preview") + dots, _L("Open G-code viewer"), [this](wxCommandEvent&) { start_new_gcodeviewer_open_file(this); }, "", nullptr); fileMenu->AppendSeparator(); append_menu_item(fileMenu, wxID_EXIT, _L("&Quit"), wxString::Format(_L("Quit %s"), SLIC3R_APP_NAME), @@ -1316,17 +1316,17 @@ void MainFrame::init_menubar_as_editor() #else wxString hotkey_delete = "Del"; #endif - append_menu_item(editMenu, wxID_ANY, _L("&Select all") + sep + GUI::shortkey_ctrl_prefix() + sep_space + "A", + append_menu_item(editMenu, wxID_ANY, _L("&Select All") + sep + GUI::shortkey_ctrl_prefix() + sep_space + "A", _L("Selects all objects"), [this](wxCommandEvent&) { m_plater->select_all(); }, "", nullptr, [this](){return can_select(); }, this); - append_menu_item(editMenu, wxID_ANY, _L("D&eselect all") + sep + "Esc", + append_menu_item(editMenu, wxID_ANY, _L("D&eselect All") + sep + "Esc", _L("Deselects all objects"), [this](wxCommandEvent&) { m_plater->deselect_all(); }, "", nullptr, [this](){return can_deselect(); }, this); editMenu->AppendSeparator(); - append_menu_item(editMenu, wxID_ANY, _L("&Delete selected") + sep + hotkey_delete, + append_menu_item(editMenu, wxID_ANY, _L("&Delete Selected") + sep + hotkey_delete, _L("Deletes the current selection"),[this](wxCommandEvent&) { m_plater->remove_selected(); }, "remove_menu", nullptr, [this](){return can_delete(); }, this); - append_menu_item(editMenu, wxID_ANY, _L("Delete &all") + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, + append_menu_item(editMenu, wxID_ANY, _L("Delete &All") + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _L("Deletes all objects"), [this](wxCommandEvent&) { m_plater->reset_with_confirm(); }, "delete_all_menu", nullptr, [this](){return can_delete_all(); }, this); @@ -1348,11 +1348,11 @@ void MainFrame::init_menubar_as_editor() editMenu->AppendSeparator(); #ifdef __APPLE__ - append_menu_item(editMenu, wxID_ANY, _L("Re&load from disk") + dots + "\tCtrl+Shift+R", + append_menu_item(editMenu, wxID_ANY, _L("Re&load from Disk") + dots + "\tCtrl+Shift+R", _L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_all_from_disk(); }, "", nullptr, [this]() {return !m_plater->model().objects.empty(); }, this); #else - append_menu_item(editMenu, wxID_ANY, _L("Re&load from disk") + sep + "F5", + append_menu_item(editMenu, wxID_ANY, _L("Re&load from Disk") + sep + "F5", _L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_all_from_disk(); }, "", nullptr, [this]() {return !m_plater->model().objects.empty(); }, this); #endif // __APPLE__ @@ -1410,11 +1410,11 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue", nullptr, []() {return true; }, this); windowMenu->AppendSeparator(); - append_menu_item(windowMenu, wxID_ANY, _L("Open new instance") + "\tCtrl+Shift+I", _L("Open a new PrusaSlicer instance"), + append_menu_item(windowMenu, wxID_ANY, _L("Open New Instance") + "\tCtrl+Shift+I", _L("Open a new PrusaSlicer instance"), [](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, [this]() {return m_plater != nullptr && wxGetApp().app_config->get("single_instance") != "1"; }, this); windowMenu->AppendSeparator(); - append_menu_item(windowMenu, wxID_ANY, _L("Compare presets")/* + "\tCtrl+F"*/, _L("Compare presets"), + append_menu_item(windowMenu, wxID_ANY, _L("Compare Presets")/* + "\tCtrl+F"*/, _L("Compare presets"), [this](wxCommandEvent&) { diff_dialog.show();}, "compare", nullptr, []() {return true; }, this); } @@ -1424,15 +1424,15 @@ void MainFrame::init_menubar_as_editor() viewMenu = new wxMenu(); add_common_view_menu_items(viewMenu, this, std::bind(&MainFrame::can_change_view, this)); viewMenu->AppendSeparator(); - append_menu_check_item(viewMenu, wxID_ANY, _L("Show &labels") + sep + "E", _L("Show object/instance labels in 3D scene"), + append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + sep + "E", _L("Show object/instance labels in 3D scene"), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); - append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"), + append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse Sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"), [this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this, []() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this); #ifndef __APPLE__ // OSX adds its own menu item to toggle fullscreen. - append_menu_check_item(viewMenu, wxID_ANY, _L("&Full screen") + "\t" + "F11", _L("Full screen"), + append_menu_check_item(viewMenu, wxID_ANY, _L("&Fullscreen") + "\t" + "F11", _L("Fullscreen"), [this](wxCommandEvent&) { this->ShowFullScreen(!this->IsFullScreen(), // wxFULLSCREEN_ALL: wxFULLSCREEN_NOMENUBAR | wxFULLSCREEN_NOTOOLBAR | wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION); }, @@ -1519,16 +1519,16 @@ void MainFrame::init_menubar_as_gcodeviewer() [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->load_gcode(); }, "open", nullptr, [this]() {return m_plater != nullptr; }, this); #ifdef __APPLE__ - append_menu_item(fileMenu, wxID_ANY, _L("Re&load from disk") + dots + "\tCtrl+Shift+R", + append_menu_item(fileMenu, wxID_ANY, _L("Re&load from Disk") + dots + "\tCtrl+Shift+R", _L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_gcode_from_disk(); }, "", nullptr, [this]() { return !m_plater->get_last_loaded_gcode().empty(); }, this); #else - append_menu_item(fileMenu, wxID_ANY, _L("Re&load from disk") + sep + "F5", + append_menu_item(fileMenu, wxID_ANY, _L("Re&load from Disk") + sep + "F5", _L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_gcode_from_disk(); }, "", nullptr, [this]() { return !m_plater->get_last_loaded_gcode().empty(); }, this); #endif // __APPLE__ fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), + append_menu_item(fileMenu, wxID_ANY, _L("Export &Toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr, [this]() {return can_export_toolpaths(); }, this); append_menu_item(fileMenu, wxID_ANY, _L("Open &PrusaSlicer") + dots, _L("Open PrusaSlicer"), diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 9343bb741..4e2462d4b 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -63,6 +63,15 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he SetSizerAndFit(main_sizer); } +void MsgDialog::SetButtonLabel(wxWindowID btn_id, const wxString& label, bool set_focus/* = false*/) +{ + if (wxButton* btn = get_button(btn_id)) { + btn->SetLabel(label); + if (set_focus) + btn->SetFocus(); + } +} + wxButton* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, const wxString& label/* = wxString()*/) { wxButton* btn = new wxButton(this, btn_id, label); @@ -98,7 +107,7 @@ void MsgDialog::finalize() // Text shown as HTML, so that mouse selection and Ctrl-V to copy will work. -static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxString msg, bool monospaced_font = false) +static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxString msg, bool monospaced_font = false, bool is_marked_msg = false) { wxHtmlWindow* html = new wxHtmlWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); @@ -136,8 +145,7 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin int em = wxGetApp().em_unit(); // if message containes the table - bool is_marked = msg.Contains("<tr>"); - if (is_marked) { + if (msg.Contains("<tr>")) { int lines = msg.Freq('\n') + 1; int pos = 0; while (pos < (int)msg.Len() && pos != wxNOT_FOUND) { @@ -155,7 +163,7 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin } html->SetMinSize(page_size); - std::string msg_escaped = xml_escape(msg.ToUTF8().data(), is_marked); + std::string msg_escaped = xml_escape(msg.ToUTF8().data(), is_marked_msg); boost::replace_all(msg_escaped, "\r\n", "<br>"); boost::replace_all(msg_escaped, "\n", "<br>"); if (monospaced_font) @@ -215,10 +223,8 @@ MessageDialog::MessageDialog(wxWindow* parent, RichMessageDialog::RichMessageDialog(wxWindow* parent, const wxString& message, const wxString& caption/* = wxEmptyString*/, - long style/* = wxOK*/, - const wxString& headline/* = wxEmptyString*/ - ) - : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, headline, style) + long style/* = wxOK*/) + : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, style) { add_msg_content(this, content_sizer, message); @@ -245,11 +251,11 @@ int RichMessageDialog::ShowModal() // InfoDialog -InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString& msg) - : MsgDialog(parent, wxString::Format(_L("%s information"), SLIC3R_APP_NAME), title, wxOK | wxICON_INFORMATION) +InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString& msg, bool is_marked_msg/* = false*/, long style/* = wxOK | wxICON_INFORMATION*/) + : MsgDialog(parent, wxString::Format(_L("%s information"), SLIC3R_APP_NAME), title, style) , msg(msg) { - add_msg_content(this, content_sizer, msg); + add_msg_content(this, content_sizer, msg, false, is_marked_msg); finalize(); } diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index 50651312e..17d935495 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -30,7 +30,7 @@ struct MsgDialog : wxDialog MsgDialog &operator=(const MsgDialog &) = delete; virtual ~MsgDialog() = default; - // TODO: refactor with CreateStdDialogButtonSizer usage + void SetButtonLabel(wxWindowID btn_id, const wxString& label, bool set_focus = false); protected: enum { @@ -111,6 +111,7 @@ public: class MessageDialog : public MsgDialog { public: + // NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxMessageDialog MessageDialog( wxWindow *parent, const wxString& message, const wxString& caption = wxEmptyString, @@ -130,12 +131,11 @@ class RichMessageDialog : public MsgDialog bool m_checkBoxValue{ false }; public: + // NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxRichMessageDialog RichMessageDialog( wxWindow *parent, const wxString& message, const wxString& caption = wxEmptyString, - long style = wxOK, - const wxString& headline = wxEmptyString - ); + long style = wxOK); RichMessageDialog(RichMessageDialog&&) = delete; RichMessageDialog(const RichMessageDialog&) = delete; RichMessageDialog &operator=(RichMessageDialog&&) = delete; @@ -306,7 +306,7 @@ public: class InfoDialog : public MsgDialog { public: - InfoDialog(wxWindow *parent, const wxString &title, const wxString &msg); + InfoDialog(wxWindow *parent, const wxString &title, const wxString &msg, bool is_marked = false, long style = wxOK| wxICON_INFORMATION); InfoDialog(InfoDialog&&) = delete; InfoDialog(const InfoDialog&) = delete; InfoDialog&operator=(InfoDialog&&) = delete; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 6647740dd..67c3fbdbd 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -181,6 +181,8 @@ public: // we have to set same max contrtol width to all of them void set_max_win_width(int max_win_width); + bool is_activated() { return sizer != nullptr; } + protected: std::map<t_config_option_key, Option> m_options; wxWindow* m_parent {nullptr}; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 0485b0075..b3ec46425 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -223,6 +223,9 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : Add(sizer_manifold, 0, wxEXPAND | wxTOP, 4); sla_hidden_items = { label_volume, info_volume, /*label_materials, info_materials*/ }; + + // Fixes layout issues on plater, short BitmapComboBoxes with some Windows scaling, see GH issue #7414. + this->Show(false); } void ObjectInfo::show_sizer(bool show) @@ -3648,12 +3651,12 @@ void Plater::priv::reload_from_disk() if (has_source || has_name) { int new_volume_idx = -1; int new_object_idx = -1; - if (has_source) { - // take idxs from source - new_volume_idx = old_volume->source.volume_idx; - new_object_idx = old_volume->source.object_idx; - } - else { +// if (has_source) { +// // take idxs from source +// new_volume_idx = old_volume->source.volume_idx; +// new_object_idx = old_volume->source.object_idx; +// } +// else { // take idxs from the 1st matching volume for (size_t o = 0; o < new_model.objects.size(); ++o) { ModelObject* obj = new_model.objects[o]; @@ -3669,39 +3672,40 @@ void Plater::priv::reload_from_disk() if (found) break; } - } +// } - if (new_object_idx < 0 && (int)new_model.objects.size() <= new_object_idx) { + if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) { fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name)); continue; } ModelObject* new_model_object = new_model.objects[new_object_idx]; - if (new_volume_idx < 0 && (int)new_model.objects.size() <= new_volume_idx) { + if (new_volume_idx < 0 || int(new_model_object->volumes.size()) <= new_volume_idx) { fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name)); continue; } - if (new_volume_idx < (int)new_model_object->volumes.size()) { - old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]); - ModelVolume* new_volume = old_model_object->volumes.back(); - new_volume->set_new_unique_id(); - new_volume->config.apply(old_volume->config); - new_volume->set_type(old_volume->type()); - new_volume->set_material_id(old_volume->material_id()); - new_volume->set_transformation(old_volume->get_transformation()); - new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); - assert(! old_volume->source.is_converted_from_inches || ! old_volume->source.is_converted_from_meters); - if (old_volume->source.is_converted_from_inches) - new_volume->convert_from_imperial_units(); - else if (old_volume->source.is_converted_from_meters) - new_volume->convert_from_meters(); - std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back()); - old_model_object->delete_volume(old_model_object->volumes.size() - 1); - if (!sinking) - old_model_object->ensure_on_bed(); - old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); - - sla::reproject_points_and_holes(old_model_object); - } + + old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]); + ModelVolume* new_volume = old_model_object->volumes.back(); + new_volume->set_new_unique_id(); + new_volume->config.apply(old_volume->config); + new_volume->set_type(old_volume->type()); + new_volume->set_material_id(old_volume->material_id()); + new_volume->set_transformation(old_volume->get_transformation()); + new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); + new_volume->source.object_idx = old_volume->source.object_idx; + new_volume->source.volume_idx = old_volume->source.volume_idx; + assert(! old_volume->source.is_converted_from_inches || ! old_volume->source.is_converted_from_meters); + if (old_volume->source.is_converted_from_inches) + new_volume->convert_from_imperial_units(); + else if (old_volume->source.is_converted_from_meters) + new_volume->convert_from_meters(); + std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back()); + old_model_object->delete_volume(old_model_object->volumes.size() - 1); + if (!sinking) + old_model_object->ensure_on_bed(); + old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); + + sla::reproject_points_and_holes(old_model_object); } } } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 5bc7c981e..ff89d90ad 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -345,7 +345,7 @@ void PreferencesDialog::build(size_t selected_tab) def.label = L("Sequential slider applied only to top layer"); def.type = coBool; - def.tooltip = L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer." + def.tooltip = L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer. " "If disabled, changes made using the sequential slider, in preview, apply to the whole gcode."); def.set_default_value(new ConfigOptionBool{ app_config->get("seq_top_layer_only") == "1" }); option = Option(def, "seq_top_layer_only"); @@ -485,7 +485,7 @@ void PreferencesDialog::build(size_t selected_tab) { def.label = L("Use system menu for application"); def.type = coBool; - def.tooltip = L("If enabled, application will use the standart Windows system menu,\n" + def.tooltip = L("If enabled, application will use the standard Windows system menu,\n" "but on some combination of display scales it can looks ugly. If disabled, old UI will be used."); def.set_default_value(new ConfigOptionBool{ app_config->get("sys_menu_enabled") == "1" }); option = Option(def, "sys_menu_enabled"); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 12c26537c..406617d5a 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -954,7 +954,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type #if ENABLE_ENHANCED_PRINT_VOLUME_FIT void Selection::scale_to_fit_print_volume(const BuildVolume& volume) { - auto fit = [this](double s, const Vec3d& offset) { + auto fit = [this](double s, Vec3d offset) { if (s <= 0.0 || s == 1.0) return; @@ -972,6 +972,7 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume) // center selection on print bed start_dragging(); + offset.z() = -get_bounding_box().min.z(); translate(offset); wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 335dd6619..417ab60fa 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -289,7 +289,9 @@ void Tab::create_preset_tab() // There is used just additional sizer for m_mode_sizer with right alignment if (m_mode_sizer) { auto mode_sizer = new wxBoxSizer(wxVERTICAL); - mode_sizer->Add(m_mode_sizer, 1, wxALIGN_RIGHT); + // Don't set the 2nd parameter to 1, making the sizer rubbery scalable in Y axis may lead + // to wrong vertical size assigned to wxBitmapComboBoxes, see GH issue #7176. + mode_sizer->Add(m_mode_sizer, 0, wxALIGN_RIGHT); m_hsizer->Add(mode_sizer, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, wxOSX ? 15 : 10); } @@ -1767,11 +1769,14 @@ void TabPrint::update() // Note: This workaround works till "support_material" and "overhangs" is exclusive sets of mutually no-exclusive parameters. // But it should be corrected when we will have more such sets. // Disable check of the compatibility of the "support_material" and "overhangs" options for saved user profile - if (!m_config_manipulation.is_initialized_support_material_overhangs_queried()) { + // or for profile which was loaded from 3mf +// if (!m_config_manipulation.is_initialized_support_material_overhangs_queried()) + if (bool support_material_overhangs_queried = m_config->opt_bool("support_material") && !m_config->opt_bool("overhangs")) + { const Preset& selected_preset = m_preset_bundle->prints.get_selected_preset(); bool is_user_and_saved_preset = !selected_preset.is_system && !selected_preset.is_dirty; - bool support_material_overhangs_queried = m_config->opt_bool("support_material") && !m_config->opt_bool("overhangs"); - m_config_manipulation.initialize_support_material_overhangs_queried(is_user_and_saved_preset && support_material_overhangs_queried); + bool is_saved_in_3mf_preset = selected_preset.is_dirty && !wxGetApp().plater()->is_presets_dirty(); + m_config_manipulation.initialize_support_material_overhangs_queried((is_user_and_saved_preset || is_saved_in_3mf_preset) && support_material_overhangs_queried); } m_config_manipulation.update_print_fff_config(m_config, true); @@ -3931,6 +3936,8 @@ bool Tab::validate_custom_gcodes() bool valid = true; for (auto opt_group : m_active_page->m_optgroups) { assert(opt_group->opt_map().size() == 1); + if (!opt_group->is_activated()) + break; std::string key = opt_group->opt_map().begin()->first; valid &= validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(opt_group->get_value(key))); if (!valid) diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 037887ee6..38440b16a 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -891,18 +891,14 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_ { if (!evt.IsChecked()) return; - wxString preferences_item = m_app_config_key == "default_action_on_new_project" ? _L("Ask for unsaved changes when creating new project") : + wxString preferences_item = m_app_config_key == "default_action_on_new_project" ? _L("Ask for unsaved changes when creating new project") : m_app_config_key == "default_action_on_select_preset" ? _L("Ask for unsaved changes when selecting new preset") : - _L("Ask for unsaved changes when ??closing application??") ; + _L("Ask to save unsaved changes when closing the application or when loading a new project") ; wxString action = m_app_config_key == "default_action_on_new_project" ? _L("You will not be asked about the unsaved changes the next time you create new project") : m_app_config_key == "default_action_on_select_preset" ? _L("You will not be asked about the unsaved changes the next time you switch a preset") : _L("You will not be asked about the unsaved changes the next time you: \n" - "- close the application,\n" - "- load project,\n" - "- process Undo / Redo with a change of print technology,\n" - "- take/load snapshot,\n" - "- load config file/bundle,\n" - "- export config_bundle") ; + "- Closing PrusaSlicer while some presets are modified,\n" + "- Loading a new project while some presets are modified") ; wxString msg = _L("PrusaSlicer will remember your action.") + "\n\n" + action + "\n\n" + format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto be asked about unsaved changes again."), preferences_item); @@ -1494,7 +1490,7 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe) }); } - m_show_all_presets = new wxCheckBox(this, wxID_ANY, _L("Show all preset (including incompatible)")); + m_show_all_presets = new wxCheckBox(this, wxID_ANY, _L("Show all presets (including incompatible)")); m_show_all_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { bool show_all = m_show_all_presets->GetValue(); for (auto preset_combos : m_preset_combos) { @@ -1555,7 +1551,7 @@ void DiffPresetDialog::update_bundles_from_app() void DiffPresetDialog::show(Preset::Type type /* = Preset::TYPE_INVALID*/) { - this->SetTitle(type == Preset::TYPE_INVALID ? _L("Compare Presets") : format_wxstr(_L("Compare %1% Presets"), wxGetApp().get_tab(type)->name())); + this->SetTitle(_L("Compare Presets")); m_view_type = type; update_bundles_from_app(); diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index c76940fd0..367c290d9 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -49,7 +49,7 @@ MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_on if (dev_version) { const std::string url = (boost::format(URL_DEV) % ver_online.to_string()).str(); const wxString url_wx = from_u8(url); - auto *link = new wxHyperlinkCtrl(this, wxID_ANY, _(L("Changelog && Download")), url_wx); + auto *link = new wxHyperlinkCtrl(this, wxID_ANY, _(L("Changelog & Download")), url_wx); content_sizer->Add(link); } else { const auto lang_code = wxGetApp().current_language_code_safe().ToStdString(); |