diff --git a/src/avrdude/avrdude-slic3r.cpp b/src/avrdude/avrdude-slic3r.cpp index 7eff436e2e..b561cd8433 100644 --- a/src/avrdude/avrdude-slic3r.cpp +++ b/src/avrdude/avrdude-slic3r.cpp @@ -204,18 +204,6 @@ AvrDude::Ptr AvrDude::run() message_fn("\n", 1); } - if (self->p->complete_fn) { - self->p->complete_fn(); - } - } catch (...) { - self->p->exit_code = EXIT_EXCEPTION; - - static const char *msg = "An unkown exception was thrown in the background thread.\n"; - - if (self->p->message_fn) { - self->p->message_fn(msg, sizeof(msg)); - } - if (self->p->complete_fn) { self->p->complete_fn(); } diff --git a/src/build-utils/CMakeLists.txt b/src/build-utils/CMakeLists.txt index 3b3961b562..d47e5b97ff 100644 --- a/src/build-utils/CMakeLists.txt +++ b/src/build-utils/CMakeLists.txt @@ -1,39 +1,45 @@ -add_executable(encoding-check encoding-check.cpp) +option(SLIC3R_ENC_CHECK "Verify encoding of source files" 1) -# A global no-op target which depends on all encodings checks, -# and on which in turn all checked targets depend. -# This is done to make encoding checks the first thing to be -# performed before actually compiling any sources of the checked targets -# to make the check fail as early as possible. -add_custom_target(global-encoding-check - ALL - DEPENDS encoding-check -) +if (SLIC3R_ENC_CHECK) + add_executable(encoding-check encoding-check.cpp) + + # A global no-op target which depends on all encodings checks, + # and on which in turn all checked targets depend. + # This is done to make encoding checks the first thing to be + # performed before actually compiling any sources of the checked targets + # to make the check fail as early as possible. + add_custom_target(global-encoding-check + ALL + DEPENDS encoding-check + ) +endif() # Function that adds source file encoding check to a target # using the above encoding-check binary function(encoding_check TARGET) - # Obtain target source files - get_target_property(T_SOURCES ${TARGET} SOURCES) + if (SLIC3R_ENC_CHECK) + # Obtain target source files + get_target_property(T_SOURCES ${TARGET} SOURCES) - # Define top-level encoding check target for this ${TARGET} - add_custom_target(encoding-check-${TARGET} - DEPENDS encoding-check ${T_SOURCES} - COMMENT "Checking source files encodings for target ${TARGET}" - ) - - # Add checking of each source file as a subcommand of encoding-check-${TARGET} - foreach(file ${T_SOURCES}) - add_custom_command(TARGET encoding-check-${TARGET} - COMMAND $ ${TARGET} ${file} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + # Define top-level encoding check target for this ${TARGET} + add_custom_target(encoding-check-${TARGET} + DEPENDS encoding-check ${T_SOURCES} + COMMENT "Checking source files encodings for target ${TARGET}" ) - endforeach() - # This adds dependency on encoding-check-${TARGET} to ${TARET} - # via the global-encoding-check - add_dependencies(global-encoding-check encoding-check-${TARGET}) - add_dependencies(${TARGET} global-encoding-check) + # Add checking of each source file as a subcommand of encoding-check-${TARGET} + foreach(file ${T_SOURCES}) + add_custom_command(TARGET encoding-check-${TARGET} + COMMAND $ ${TARGET} ${file} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + endforeach() + + # This adds dependency on encoding-check-${TARGET} to ${TARET} + # via the global-encoding-check + add_dependencies(global-encoding-check encoding-check-${TARGET}) + add_dependencies(${TARGET} global-encoding-check) + endif() endfunction() diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index a62a189ce0..b32943b7db 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -29,6 +29,7 @@ enum ExtrusionRole { erCustom, // Extrusion role for a collection with multiple extrusion roles. erMixed, + erCount, }; inline bool is_perimeter(ExtrusionRole role) diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 6ef17f4f41..51fca58f64 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -298,7 +298,11 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co used for unlift. */ if (!this->will_move_z(point(2))) { double nominal_z = m_pos(2) - m_lifted; - m_lifted = m_lifted - (point(2) - nominal_z); + m_lifted -= (point(2) - nominal_z); + // In case that retract_lift == layer_height we could end up with almost zero in_m_lifted + // and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154 + if (std::abs(m_lifted) < EPSILON) + m_lifted = 0.; return this->travel_to_xy(to_2d(point)); } @@ -324,7 +328,9 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment) reducing the lift amount that will be used for unlift. */ if (!this->will_move_z(z)) { double nominal_z = m_pos(2) - m_lifted; - m_lifted = m_lifted - (z - nominal_z); + m_lifted -= (z - nominal_z); + if (std::abs(m_lifted) < EPSILON) + m_lifted = 0.; return ""; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8f56c1b83d..4779624050 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -368,7 +368,7 @@ void PrintConfigDef::init_fff_params() def = this->add("end_gcode", coString); def->label = L("End G-code"); def->tooltip = L("This end procedure is inserted at the end of the output file. " - "Note that you can use placeholder variables for all Slic3r settings."); + "Note that you can use placeholder variables for all PrusaSlicer settings."); def->multiline = true; def->full_width = true; def->height = 12; @@ -379,7 +379,7 @@ void PrintConfigDef::init_fff_params() def->label = L("End G-code"); def->tooltip = L("This end procedure is inserted at the end of the output file, before the printer end gcode (and " "before any toolchange from this filament in case of multimaterial printers). " - "Note that you can use placeholder variables for all Slic3r settings. " + "Note that you can use placeholder variables for all PrusaSlicer settings. " "If you have multiple extruders, the gcode is processed in extruder order."); def->multiline = true; def->full_width = true; @@ -913,7 +913,7 @@ void PrintConfigDef::init_fff_params() def->label = L("G-code flavor"); def->tooltip = L("Some G/M-code commands, including temperature control and others, are not universal. " "Set this option to your printer's firmware to get a compatible output. " - "The \"No extrusion\" flavor prevents Slic3r from exporting any extrusion value at all."); + "The \"No extrusion\" flavor prevents PrusaSlicer from exporting any extrusion value at all."); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("reprap"); def->enum_values.push_back("repetier"); @@ -1785,10 +1785,10 @@ void PrintConfigDef::init_fff_params() def->label = L("Start G-code"); def->tooltip = L("This start procedure is inserted at the beginning, after bed has reached " "the target temperature and extruder just started heating, and before extruder " - "has finished heating. If Slic3r detects M104 or M190 in your custom codes, " + "has finished heating. If PrusaSlicer detects M104 or M190 in your custom codes, " "such commands will not be prepended automatically so you're free to customize " "the order of heating commands and other custom actions. Note that you can use " - "placeholder variables for all Slic3r settings, so you can put " + "placeholder variables for all PrusaSlicer settings, so you can put " "a \"M109 S[first_layer_temperature]\" command wherever you want."); def->multiline = true; def->full_width = true; @@ -1800,11 +1800,11 @@ void PrintConfigDef::init_fff_params() def->label = L("Start G-code"); def->tooltip = L("This start procedure is inserted at the beginning, after any printer start gcode (and " "after any toolchange to this filament in case of multi-material printers). " - "This is used to override settings for a specific filament. If Slic3r detects " + "This is used to override settings for a specific filament. If PrusaSlicer detects " "M104, M109, M140 or M190 in your custom codes, such commands will " "not be prepended automatically so you're free to customize the order " "of heating commands and other custom actions. Note that you can use placeholder variables " - "for all Slic3r settings, so you can put a \"M109 S[first_layer_temperature]\" command " + "for all PrusaSlicer settings, so you can put a \"M109 S[first_layer_temperature]\" command " "wherever you want. If you have multiple extruders, the gcode is processed " "in extruder order."); def->multiline = true; @@ -2749,8 +2749,7 @@ void PrintConfigDef::init_sla_params() def = this->add("pad_object_connector_stride", coFloat); def->label = L("Pad object connector stride"); def->category = L("Pad"); - def->tooltip = L("Distance between two connector sticks between " - "the object pad and the generated pad."); + def->tooltip = L("Distance between two connector sticks which connect the object and the generated pad."); def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; @@ -2759,8 +2758,7 @@ void PrintConfigDef::init_sla_params() def = this->add("pad_object_connector_width", coFloat); def->label = L("Pad object connector width"); def->category = L("Pad"); - def->tooltip = L("The width of the connectors sticks which connect the " - "object pad and the generated pad."); + def->tooltip = L("Width of the connector sticks which connect the object and the generated pad."); def->sidetext = L("mm"); def->min = 0; def->mode = comExpert; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 236460dd2c..ecf3fa5482 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -46,10 +46,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (config->opt_float("layer_height") < EPSILON) { const wxString msg_text = _(L("Zero layer height is not valid.\n\nThe layer height will be reset to 0.01.")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK); + wxMessageDialog dialog(nullptr, msg_text, _(L("Layer height")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; is_msg_dlg_already_exist = true; - dialog->ShowModal(); + dialog.ShowModal(); new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.01)); apply(config, &new_conf); is_msg_dlg_already_exist = false; @@ -58,10 +58,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (fabs(config->option("first_layer_height")->value - 0) < EPSILON) { const wxString msg_text = _(L("Zero first layer height is not valid.\n\nThe first layer height will be reset to 0.01.")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK); + wxMessageDialog dialog(nullptr, msg_text, _(L("First layer height")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; is_msg_dlg_already_exist = true; - dialog->ShowModal(); + dialog.ShowModal(); new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.01, false)); apply(config, &new_conf); is_msg_dlg_already_exist = false; @@ -80,10 +80,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "- no ensure_vertical_shell_thickness")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable Spiral Vase?")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Spiral Vase")), - wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); + wxMessageDialog dialog(nullptr, msg_text, _(L("Spiral Vase")), + wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; - auto answer = dialog->ShowModal(); + auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0)); @@ -109,10 +109,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "(both support_material_extruder and support_material_interface_extruder need to be set to 0).")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable the Wipe Tower?")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Wipe Tower")), - wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); + wxMessageDialog dialog (nullptr, msg_text, _(L("Wipe Tower")), + wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; - auto answer = dialog->ShowModal(); + auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0)); new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0)); @@ -129,10 +129,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con "need to be synchronized with the object layers.")); if (is_global_config) msg_text += "\n\n" + _(L("Shall I synchronize support layers in order to enable the Wipe Tower?")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Wipe Tower")), - wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); + wxMessageDialog dialog(nullptr, msg_text, _(L("Wipe Tower")), + wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; - auto answer = dialog->ShowModal(); + auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true)); } @@ -141,6 +141,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con apply(config, &new_conf); } + static bool support_material_overhangs_queried = false; + if (config->opt_bool("support_material")) { // Ask only once. if (!support_material_overhangs_queried) { @@ -150,10 +152,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?")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Support Generator")), - wxICON_WARNING | (is_global_config ? wxYES | wxNO | wxCANCEL : wxOK)); + wxMessageDialog dialog(nullptr, msg_text, _(L("Support Generator")), + wxICON_WARNING | (is_global_config ? wxYES | wxNO | wxCANCEL : wxOK)); DynamicPrintConfig new_conf = *config; - auto answer = dialog->ShowModal(); + auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { // Enable "detect bridging perimeters". new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); @@ -198,10 +200,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density."))) % str_fill_pattern).str()); if (is_global_config) msg_text += "\n\n" + _(L("Shall I switch to rectilinear fill pattern?")); - auto dialog = new wxMessageDialog(nullptr, msg_text, _(L("Infill")), + wxMessageDialog dialog(nullptr, msg_text, _(L("Infill")), wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK) ); DynamicPrintConfig new_conf = *config; - auto answer = dialog->ShowModal(); + auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { new_conf.set_key_value("fill_pattern", new ConfigOptionEnum(ipRectilinear)); fill_density = 100; @@ -300,13 +302,9 @@ void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, con if (head_penetration > head_width) { wxString msg_text = _(L("Head penetration should not be greater than the head width.")); - auto dialog = new wxMessageDialog(nullptr, - msg_text, - _(L("Invalid Head penetration")), - wxICON_WARNING | wxOK); - + wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid Head penetration")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; - if (dialog->ShowModal() == wxID_OK) { + if (dialog.ShowModal() == wxID_OK) { new_conf.set_key_value("support_head_penetration", new ConfigOptionFloat(head_width)); apply(config, &new_conf); } @@ -317,13 +315,10 @@ void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, con if (pinhead_d > pillar_d) { wxString msg_text = _(L("Pinhead diameter should be smaller than the pillar diameter.")); - auto dialog = new wxMessageDialog(nullptr, - msg_text, - _(L("Invalid pinhead diameter")), - wxICON_WARNING | wxOK); + wxMessageDialog dialog(nullptr, msg_text, _(L("Invalid pinhead diameter")), wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; - if (dialog->ShowModal() == wxID_OK) { + if (dialog.ShowModal() == wxID_OK) { new_conf.set_key_value("support_head_front_diameter", new ConfigOptionFloat(pillar_d / 2.0)); apply(config, &new_conf); } diff --git a/src/slic3r/GUI/ConfigManipulation.hpp b/src/slic3r/GUI/ConfigManipulation.hpp index 1dbadc2bd9..7344f758be 100644 --- a/src/slic3r/GUI/ConfigManipulation.hpp +++ b/src/slic3r/GUI/ConfigManipulation.hpp @@ -18,7 +18,6 @@ namespace GUI { class ConfigManipulation { bool is_msg_dlg_already_exist{ false }; - bool support_material_overhangs_queried{ false }; // function to loading of changed configuration std::function load_config = nullptr; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4fa68ecf20..d9b948c2f0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -8,6 +8,7 @@ #include "libslic3r/PrintConfig.hpp" #include "libslic3r/GCode/PreviewData.hpp" #include "libslic3r/Geometry.hpp" +#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Technologies.hpp" #include "libslic3r/Tesselate.hpp" @@ -71,9 +72,11 @@ static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f }; //static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; // Number of floats -static const float MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB +static const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB // Reserve size in number of floats. -static const float VERTEX_BUFFER_RESERVE_SIZE = 131072 * 2; // 1.05MB +static const size_t VERTEX_BUFFER_RESERVE_SIZE = 131072 * 2; // 1.05MB +// Reserve size in number of floats, maximum sum of all preallocated buffers. +static const size_t VERTEX_BUFFER_RESERVE_SIZE_SUM_MAX = 1024 * 1024 * 128 / 4; // 128MB namespace Slic3r { namespace GUI { @@ -2083,7 +2086,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re m_dirty = true; } -static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& vol_old, bool gl_initialized) +static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& vol_old, bool gl_initialized, size_t prealloc_size = VERTEX_BUFFER_RESERVE_SIZE) { // Assign the large pre-allocated buffers to the new GLVolume. vol_new.indexed_vertex_array = std::move(vol_old.indexed_vertex_array); @@ -2093,7 +2096,7 @@ static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& vol_new.indexed_vertex_array.clear(); // Just make sure that clear did not clear the reserved memory. // Reserving number of vertices (3x position + 3x color) - vol_new.indexed_vertex_array.reserve(VERTEX_BUFFER_RESERVE_SIZE / 6); + vol_new.indexed_vertex_array.reserve(prealloc_size / 6); // Finalize the old geometry, possibly move data to the graphics card. vol_old.finalize_geometry(gl_initialized); } @@ -3468,14 +3471,13 @@ static bool string_getter(const bool is_undo, int idx, const char** out_text) void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x) { - const wxString& stack_name = _(is_undo ? L("Undo") : L("Redo")); ImGuiWrapper* imgui = wxGetApp().imgui(); const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width(); imgui->set_next_window_pos(x, m_undoredo_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); imgui->set_next_window_bg_alpha(0.5f); - imgui->begin(wxString::Format(_(L("%s Stack")), stack_name), - ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + std::string title = is_undo ? L("Undo History") : L("Redo History"); + imgui->begin(_(title), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); int hovered = m_imgui_undo_redo_hovered_pos; int selected = -1; @@ -3492,7 +3494,7 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x) if (selected >= 0) is_undo ? wxGetApp().plater()->undo_to(selected) : wxGetApp().plater()->redo_to(selected); - imgui->text(wxString::Format(_(L("%s %d Action")), stack_name, hovered + 1)); + imgui->text(wxString::Format(_(hovered ? (is_undo ? L("Undo %d Actions") : L("Redo %d Actions")) : (is_undo ? L("Undo %d Action") : L("Redo %d Action"))), hovered + 1)); imgui->end(); } @@ -3645,7 +3647,7 @@ bool GLCanvas3D::_init_main_toolbar() item.name = "layersediting"; item.icon_filename = "layers_white.svg"; - item.tooltip = _utf8(L("Layers editing")); + item.tooltip = _utf8(L("Height ranges")); item.sprite_id = 10; item.left.toggable = true; item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); }; @@ -3696,7 +3698,7 @@ bool GLCanvas3D::_init_undoredo_toolbar() item.name = "undo"; item.icon_filename = "undo_toolbar.svg"; - item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]"; + item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]\n" + _utf8(L("Click right mouse button to open History")); item.sprite_id = 0; item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); }; item.right.toggable = true; @@ -3710,8 +3712,11 @@ bool GLCanvas3D::_init_undoredo_toolbar() m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); std::string new_additional_tooltip = ""; - if (can_undo) - wxGetApp().plater()->undo_redo_topmost_string_getter(true, new_additional_tooltip); + if (can_undo) { + std::string action; + wxGetApp().plater()->undo_redo_topmost_string_getter(true, action); + new_additional_tooltip = (boost::format(_utf8(L("Next Undo action: %1%"))) % action).str(); + } if (new_additional_tooltip != curr_additional_tooltip) { @@ -3726,7 +3731,7 @@ bool GLCanvas3D::_init_undoredo_toolbar() item.name = "redo"; item.icon_filename = "redo_toolbar.svg"; - item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]"; + item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]\n" + _utf8(L("Click right mouse button to open History")); item.sprite_id = 1; item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_REDO)); }; item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; }; @@ -3739,8 +3744,11 @@ bool GLCanvas3D::_init_undoredo_toolbar() m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); std::string new_additional_tooltip = ""; - if (can_redo) - wxGetApp().plater()->undo_redo_topmost_string_getter(false, new_additional_tooltip); + if (can_redo) { + std::string action; + wxGetApp().plater()->undo_redo_topmost_string_getter(false, action); + new_additional_tooltip = (boost::format(_utf8(L("Next Redo action: %1%"))) % action).str(); + } if (new_additional_tooltip != curr_additional_tooltip) { @@ -4959,6 +4967,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat switch (type) { case GCodePreviewData::Extrusion::FeatureType: + // The role here is used for coloring. return (float)path.role(); case GCodePreviewData::Extrusion::Height: return path.height; @@ -5020,32 +5029,6 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat } }; - // Helper structure for filters - struct Filter - { - float value; - ExtrusionRole role; - GLVolume* volume; - - Filter(float value, ExtrusionRole role, GLVolume *volume = nullptr) - : value(value) - , role(role) - , volume(volume) - { - } - - bool operator == (const Filter& other) const - { - if (value != other.value) - return false; - - if (role != other.role) - return false; - - return true; - } - }; - size_t initial_volumes_count = m_volumes.volumes.size(); size_t initial_volume_index_count = m_gcode_preview_volume_index.first_volumes.size(); @@ -5054,30 +5037,42 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info(); // detects filters - typedef std::vector FiltersList; - FiltersList filters; + size_t vertex_buffer_prealloc_size = 0; + std::vector>> roles_filters; { - size_t num_paths = 0; - for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers) - num_paths += layer.paths.size(); - std::vector> values; - values.reserve(num_paths); + std::vector num_paths_per_role(size_t(erCount), 0); + for (const GCodePreviewData::Extrusion::Layer &layer : preview_data.extrusion.layers) + for (const ExtrusionPath &path : layer.paths) + ++ num_paths_per_role[size_t(path.role())]; + std::vector> roles_values; + roles_values.assign(size_t(erCount), std::vector()); + for (size_t i = 0; i < roles_values.size(); ++ i) + roles_values[i].reserve(num_paths_per_role[i]); for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers) for (const ExtrusionPath& path : layer.paths) - values.emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path), (unsigned int)path.role()); - sort_remove_duplicates(values); - filters.reserve(values.size()); - for (const std::pair &value : values) { - m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, value.second /* role */, (unsigned int)m_volumes.volumes.size()); - filters.emplace_back(value.first, (ExtrusionRole)value.second, - m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value.first).rgba, VERTEX_BUFFER_RESERVE_SIZE)); + roles_values[size_t(path.role())].emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path)); + roles_filters.reserve(size_t(erCount)); + size_t num_buffers = 0; + for (std::vector &values : roles_values) { + sort_remove_duplicates(values); + num_buffers += values.size(); + } + if (num_buffers == 0) + // nothing to render, return + return; + vertex_buffer_prealloc_size = (uint64_t(num_buffers) * uint64_t(VERTEX_BUFFER_RESERVE_SIZE) < VERTEX_BUFFER_RESERVE_SIZE_SUM_MAX) ? + VERTEX_BUFFER_RESERVE_SIZE : next_highest_power_of_2(VERTEX_BUFFER_RESERVE_SIZE_SUM_MAX / num_buffers) / 2; + for (std::vector &values : roles_values) { + size_t role = &values - &roles_values.front(); + roles_filters.emplace_back(); + if (! values.empty()) { + m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, role, (unsigned int)m_volumes.volumes.size()); + for (const float value : values) + roles_filters.back().emplace_back(value, m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value).rgba, vertex_buffer_prealloc_size)); + } } } - // nothing to render, return - if (filters.empty()) - return; - BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - populate volumes" << m_volumes.log_memory_info() << log_memory_info(); // populates volumes @@ -5085,12 +5080,12 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat { for (const ExtrusionPath& path : layer.paths) { - Filter key(Helper::path_filter(preview_data.extrusion.view_type, path), path.role()); - FiltersList::iterator filter = std::lower_bound(filters.begin(), filters.end(), key, - [](const Filter& l, const Filter& r) { return (l.value < r.value) || (l.value == r.value && l.role < r.role); }); - assert(filter != filters.end() && key.value == filter->value && key.role == filter->role); + std::vector> &filters = roles_filters[size_t(path.role())]; + auto key = std::make_pair(Helper::path_filter(preview_data.extrusion.view_type, path), nullptr); + auto it_filter = std::lower_bound(filters.begin(), filters.end(), key); + assert(it_filter != filters.end() && key.first == it_filter->first); - GLVolume& vol = *filter->volume; + GLVolume& vol = *it_filter->second; vol.print_zs.push_back(layer.z); vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size()); vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size()); @@ -5098,17 +5093,23 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat _3DScene::extrusionentity_to_verts(path, layer.z, vol); } // Ensure that no volume grows over the limits. If the volume is too large, allocate a new one. - for (Filter &filter : filters) - if (filter.volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) { - GLVolume& vol = *filter.volume; - filter.volume = m_volumes.new_toolpath_volume(vol.color); - reserve_new_volume_finalize_old_volume(*filter.volume, vol, m_initialized); - } + for (std::vector> &filters : roles_filters) { + unsigned int role = (unsigned int)(&filters - &roles_filters.front()); + for (std::pair &filter : filters) + if (filter.second->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) { + if (m_gcode_preview_volume_index.first_volumes.back().id != role) + m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, role, (unsigned int)m_volumes.volumes.size()); + GLVolume& vol = *filter.second; + filter.second = m_volumes.new_toolpath_volume(vol.color); + reserve_new_volume_finalize_old_volume(*filter.second, vol, m_initialized, vertex_buffer_prealloc_size); + } + } } // Finalize volumes and sends geometry to gpu - for (Filter &filter : filters) - filter.volume->indexed_vertex_array.finalize_geometry(m_initialized); + for (std::vector> &filters : roles_filters) + for (std::pair &filter : filters) + filter.second->indexed_vertex_array.finalize_geometry(m_initialized); BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - end" << m_volumes.log_memory_info() << log_memory_info(); } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 9fe0bab963..2b63447832 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -139,9 +139,6 @@ static void generic_exception_handle() wxLogError("Internal error: %s", ex.what()); BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what(); throw; - } catch (...) { - wxLogError("Unknown internal error"); - BOOST_LOG_TRIVIAL(error) << "Uncaught exception: Unknown error"; } } @@ -169,7 +166,7 @@ bool GUI_App::OnInit() { try { return on_init_inner(); - } catch (...) { + } catch (const std::exception&) { generic_exception_handle(); return false; } diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index b30d3ecd31..a11033e27f 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -20,13 +20,12 @@ namespace GUI ObjectLayers::ObjectLayers(wxWindow* parent) : OG_Settings(parent, true) { - m_grid_sizer = new wxFlexGridSizer(3, 5, 5); // "Min Z", "Max Z", "Layer height" & buttons sizer + m_grid_sizer = new wxFlexGridSizer(3, 5, wxGetApp().em_unit()); // "Min Z", "Max Z", "Layer height" & buttons sizer m_grid_sizer->SetFlexibleDirection(wxHORIZONTAL); // Legend for object layers - for (const std::string col : { "Min Z", "Max Z", "Layer height" }) { - auto temp = new wxStaticText(m_parent, wxID_ANY, _(L(col)), wxDefaultPosition, /*size*/wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + for (const std::string col : { L("Start at height"), L("Stop at height"), L("Layer height") }) { + auto temp = new wxStaticText(m_parent, wxID_ANY, _(col), wxDefaultPosition, /*size*/wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); temp->SetBackgroundStyle(wxBG_STYLE_PAINT); temp->SetFont(wxGetApp().bold_font()); @@ -132,6 +131,12 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(editor); + + auto temp = new wxStaticText(m_parent, wxID_ANY, _(L("mm"))); + temp->SetBackgroundStyle(wxBG_STYLE_PAINT); + temp->SetFont(wxGetApp().normal_font()); + sizer->Add(temp, 0, wxLEFT|wxRIGHT, wxGetApp().em_unit()); + m_grid_sizer->Add(sizer); return sizer; @@ -145,7 +150,7 @@ void ObjectLayers::create_layers_list() auto sizer = create_layer(range); auto del_btn = new ScalableButton(m_parent, wxID_ANY, m_bmp_delete); - del_btn->SetToolTip(_(L("Remove layer"))); + del_btn->SetToolTip(_(L("Remove layer range"))); sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(m_parent)); @@ -154,7 +159,7 @@ void ObjectLayers::create_layers_list() }); auto add_btn = new ScalableButton(m_parent, wxID_ANY, m_bmp_add); - add_btn->SetToolTip(_(L("Add layer"))); + add_btn->SetToolTip(_(L("Add layer range"))); sizer->Add(add_btn, 0, wxRIGHT, em_unit(m_parent)); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 94f3252ae7..1f0adf3637 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1249,7 +1249,7 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) assert(m_config); auto opt_keys = m_config->keys(); - const wxString snapshot_text = item_type & itLayer ? _(L("Add Settings Bundle for Layers")) : + const wxString snapshot_text = item_type & itLayer ? _(L("Add Settings Bundle for Height range")) : item_type & itVolume ? _(L("Add Settings Bundle for Sub-object")) : _(L("Add Settings Bundle for Object")); take_snapshot(snapshot_text); @@ -1347,7 +1347,7 @@ wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_layers_editing(wxMenu* menu) { - return append_menu_item(menu, wxID_ANY, _(L("Edit Layers")), "", + return append_menu_item(menu, wxID_ANY, _(L("Height range Modifier")), "", [this](wxCommandEvent&) { layers_editing(); }, "edit_layers_all", menu); } @@ -1895,7 +1895,7 @@ void ObjectList::del_layer_from_object(const int obj_idx, const t_layer_height_r if (del_range == object(obj_idx)->layer_config_ranges.end()) return; - take_snapshot(_(L("Delete Layers Range"))); + take_snapshot(_(L("Delete Height Range"))); object(obj_idx)->layer_config_ranges.erase(del_range); @@ -2203,7 +2203,7 @@ void ObjectList::part_selection_changed() m_config = &(*m_objects)[obj_idx]->config; } else if (type & (itLayerRoot|itLayer)) { - og_name = type & itLayerRoot ? _(L("Layers Editing")) : _(L("Layer Editing")); + og_name = type & itLayerRoot ? _(L("Height ranges")) : _(L("Settings for height range")); update_and_show_layers = true; if (type & itLayer) @@ -2581,7 +2581,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre if (current_range == last_range) { - take_snapshot(_(L("Add New Layers Range"))); + take_snapshot(_(L("Add Height Range"))); const t_layer_height_range& new_range = { last_range.second, last_range.second + 2.0f }; ranges[new_range] = get_default_layer_config(obj_idx); @@ -2610,7 +2610,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre t_layer_height_range new_range = { midl_layer, next_range.second }; - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add New Layers Range"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add Height Range"))); // create new 2 layers instead of deleted one @@ -2628,7 +2628,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre } else { - take_snapshot(_(L("Add New Layers Range"))); + take_snapshot(_(L("Add Height Range"))); const t_layer_height_range new_range = { current_range.second, next_range.first }; ranges[new_range] = get_default_layer_config(obj_idx); @@ -2687,7 +2687,7 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return false; - take_snapshot(_(L("Edit Layers Range"))); + take_snapshot(_(L("Edit Height Range"))); const ItemType sel_type = m_objects_model->GetItemType(GetSelection()); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 29013389e5..51717a420d 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -562,7 +562,7 @@ void ObjectManipulation::update_if_dirty() if (selection.requires_uniform_scale()) { m_lock_bnt->SetLock(true); - m_lock_bnt->SetToolTip(_(L("You cann't use non-uniform scaling mode for multiple objects/parts selection"))); + m_lock_bnt->SetToolTip(_(L("You cannot use non-uniform scaling mode for multiple objects/parts selection"))); m_lock_bnt->disable(); } else { diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 64218d08f6..de6289f7d2 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -252,7 +252,6 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view m_checkbox_retractions = new wxCheckBox(this, wxID_ANY, _(L("Retractions"))); m_checkbox_unretractions = new wxCheckBox(this, wxID_ANY, _(L("Unretractions"))); m_checkbox_shells = new wxCheckBox(this, wxID_ANY, _(L("Shells"))); - m_checkbox_legend = new wxCheckBox(this, wxID_ANY, _(L("Legend"))); m_checkbox_legend->SetValue(true); diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 2d5454ce99..e3ef335e68 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -151,7 +151,7 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("F", L("Press to scale selection to fit print volume\nin Gizmo scale"))); plater_shortcuts.push_back(Shortcut(alt, L("Press to activate deselection rectangle\nor to scale or rotate selected objects\naround their own center"))); plater_shortcuts.push_back(Shortcut(ctrl, L("Press to activate one direction scaling in Gizmo scale"))); - plater_shortcuts.push_back(Shortcut("K", L("Change camera type"))); + plater_shortcuts.push_back(Shortcut("K", L("Change camera type (perspective, orthographic)"))); plater_shortcuts.push_back(Shortcut("B", L("Zoom to Bed"))); plater_shortcuts.push_back(Shortcut("Z", L("Zoom to all objects in scene, if none selected"))); plater_shortcuts.push_back(Shortcut("Z", L("Zoom to selected object"))); @@ -159,7 +159,8 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("O", L("Zoom out"))); plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo / Clear selection"))); #if ENABLE_RENDER_PICKING_PASS - plater_shortcuts.push_back(Shortcut("T", L("Toggle picking pass texture rendering on/off"))); + // Don't localize debugging texts. + plater_shortcuts.push_back(Shortcut("T", "Toggle picking pass texture rendering on/off")); #endif // ENABLE_RENDER_PICKING_PASS m_full_shortcuts.push_back(std::make_pair(_(L("Plater Shortcuts")), std::make_pair(plater_shortcuts, szRight))); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d33b858890..460b5b0de9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2240,7 +2240,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (object->volumes.size() > 1) { Slic3r::GUI::show_info(nullptr, - _(L("You can't to load SLA project if there is at least one multi-part object on the bed")) + "\n\n" + + _(L("You can't load SLA project if there is at least one multi-part object on the bed")) + "\n\n" + _(L("Please check your object list before preset changing.")), _(L("Attention!"))); return obj_idxs; @@ -3946,6 +3946,9 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator AppConfig *app_config = wxGetApp().app_config; app_config->set("presets", "printer", (new_printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name); wxGetApp().preset_bundle->load_presets(*app_config); + // load_current_presets() calls Tab::load_current_preset() -> TabPrint::update() -> Object_list::update_and_show_object_settings_item(), + // but the Object list still keeps pointer to the old Model. Avoid a crash by removing selection first. + this->sidebar->obj_list()->unselect_objects(); // Load the currently selected preset into the GUI, update the preset selection box. // This also switches the printer technology based on the printer technology of the active printer profile. wxGetApp().load_current_presets(); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index d6e99b0142..af1298bfb9 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -445,6 +445,7 @@ DynamicPrintConfig PresetBundle::full_config() const DynamicPrintConfig PresetBundle::full_config_secure() const { DynamicPrintConfig config = this->full_config(); + config.erase("print_host"); config.erase("printhost_apikey"); config.erase("printhost_cafile"); return config; diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 2ea9040075..a1a113066f 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -113,7 +113,9 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector &updates) : if (! update.comment.empty()) { flex->Add(new wxStaticText(this, wxID_ANY, _(L("Comment:"))), 0, wxALIGN_RIGHT); - flex->Add(new wxStaticText(this, wxID_ANY, from_u8(update.comment))); + auto *update_comment = new wxStaticText(this, wxID_ANY, from_u8(update.comment)); + update_comment->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); + flex->Add(update_comment); } versions->Add(flex); diff --git a/src/slic3r/Utils/Serial.cpp b/src/slic3r/Utils/Serial.cpp index 5944646926..737e76c0b5 100644 --- a/src/slic3r/Utils/Serial.cpp +++ b/src/slic3r/Utils/Serial.cpp @@ -98,7 +98,7 @@ optional sysfs_tty_prop_hex(const std::string &tty_dev, const std if (!prop) { return boost::none; } try { return std::stoul(*prop, 0, 16); } - catch (...) { return boost::none; } + catch (const std::exception&) { return boost::none; } } #endif