diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index aa857e8e4..02fefceec 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -442,6 +442,7 @@ std::vector GCode::collect_layers_to_print(const PrintObjec // Pair the object layers with the support layers by z. size_t idx_object_layer = 0; size_t idx_support_layer = 0; + const LayerToPrint* last_extrusion_layer = nullptr; while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { LayerToPrint layer_to_print; layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer ++] : nullptr; @@ -456,17 +457,25 @@ std::vector GCode::collect_layers_to_print(const PrintObjec } } - // Let's make sure that the last layer is not empty, so we don't build on top of it. - if (! layers_to_print.empty() - && ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) - || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) - && (! layers_to_print.back().object_layer || ! layers_to_print.back().object_layer->has_extrusions()) - && (! layers_to_print.back().support_layer || ! layers_to_print.back().support_layer->has_extrusions())) - throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" + - _(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) + - std::to_string(layers_to_print.back().print_z())); - layers_to_print.emplace_back(layer_to_print); + + // In case there are extrusions on this layer, check there is a layer to lay it on. + if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) + || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) { + double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) + ? object.config().support_material_contact_distance + : 0.; + double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) + + layer_to_print.layer()->height + + support_contact_z; + + if (layer_to_print.print_z() > maximal_print_z + EPSILON) + throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" + + _(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) + + std::to_string(layers_to_print.back().print_z())); + // Remember last layer with extrusions. + last_extrusion_layer = &layers_to_print.back(); + } } return layers_to_print; @@ -766,7 +775,7 @@ void GCode::_do_export(Print &print, FILE *file) mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [](double v) { return v < 0.000001; }), mm3_per_mm.end()); if (! mm3_per_mm.empty()) { // In order to honor max_print_speed we need to find a target volumetric - // speed that we can use throughout the print. So we define this target + // speed that we can use throughout the print. So we define this target // volumetric speed as the volumetric speed produced by printing the // smallest cross-section at the maximum speed: any larger cross-section // will need slower feedrates. @@ -833,7 +842,7 @@ void GCode::_do_export(Print &print, FILE *file) _writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag); } - // Prepare the helper object for replacing placeholders in custom G-code and output filename. + // Prepare the helper object for replacing placeholders in custom G-code and output filename. m_placeholder_parser = print.placeholder_parser(); m_placeholder_parser.update_timestamp(); print.update_object_placeholders(m_placeholder_parser.config_writable(), ".gcode"); @@ -2617,7 +2626,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm ); } - double F = speed * 60; // convert mm/sec to mm/min + double F = speed * 60; // convert mm/sec to mm/min // extrude arc or line if (m_enable_extrusion_role_markers) diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 2c8941632..c8fd01f41 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -1,9 +1,11 @@ #ifndef slic3r_GLTexture_hpp_ #define slic3r_GLTexture_hpp_ +#include #include #include #include +#include class wxImage; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8a785760c..dd107550e 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -986,6 +986,7 @@ wxString GUI_App::current_language_code_safe() const language_code = language_code.substr(0, idx_underscore); const std::map mapping { { "cs", "cs_CZ", }, + { "sk", "cs_CZ", }, { "de", "de_DE", }, { "es", "es_ES", }, { "fr", "fr_FR", }, diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 346d4494b..b03120e62 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -186,7 +186,18 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, [this](wxCommandEvent& e) { last_volume_is_deleted(e.GetInt()); }); - Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { this->EnsureVisible(this->GetCurrentItem()); e.Skip(); })); + Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { +#ifdef __WXGTK__ + // On GTK, the EnsureVisible call is postponed to Idle processing (see wxDataViewCtrl::m_ensureVisibleDefered). + // So the postponed EnsureVisible() call is planned for an item, which may not exist at the Idle processing time, if this wxEVT_SIZE + // event is succeeded by a delete of the currently active item. We are trying our luck by postponing the wxEVT_SIZE triggered EnsureVisible(), + // which seems to be working as of now. + this->CallAfter([this](){ this->EnsureVisible(this->GetCurrentItem()); }); +#else + this->EnsureVisible(this->GetCurrentItem()); +#endif + e.Skip(); + })); } ObjectList::~ObjectList() @@ -1013,6 +1024,11 @@ const std::vector& ObjectList::get_options_for_bundle(const wxStrin return empty; } +static bool improper_category(const std::string& category, const int extruders_cnt) +{ + return category.empty() || (extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" )); +} + void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) { auto options = get_options(is_part); @@ -1024,8 +1040,8 @@ void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const { auto const opt = config.def()->get(option); auto category = opt->category; - if (category.empty() || - (category == "Extruders" && extruders_cnt == 1)) continue; + if (improper_category(category, extruders_cnt)) + continue; const std::string& label = !opt->full_label.empty() ? opt->full_label : opt->label; std::pair option_label(option, label); @@ -1537,7 +1553,7 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) const int extruders_cnt = extruders_count(); for (auto& it : bundle) { - if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1) + if (improper_category(it.first, extruders_cnt)) continue; append_menu_item(menu, wxID_ANY, _(it.first), "", @@ -1550,7 +1566,7 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) m_freq_settings_fff : m_freq_settings_sla; for (auto& it : bundle_quick) { - if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1) + if (improper_category(it.first, extruders_cnt)) continue; append_menu_item(menu, wxID_ANY, wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)), "", @@ -2184,7 +2200,7 @@ SettingsBundle ObjectList::get_item_settings_bundle(const DynamicPrintConfig* co for (auto& opt_key : opt_keys) { auto category = config->def()->get(opt_key)->category; - if (category.empty() || (category == "Extruders" && extruders_cnt == 1)) + if (improper_category(category, extruders_cnt)) continue; std::vector< std::string > new_category; @@ -2456,13 +2472,13 @@ void ObjectList::del_layer_range(const t_layer_height_range& range) select_item(selectable_item); } -double get_min_layer_height(const int extruder_idx) +static double get_min_layer_height(const int extruder_idx) { const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; return config.opt_float("min_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); } -double get_max_layer_height(const int extruder_idx) +static double get_max_layer_height(const int extruder_idx) { const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; return config.opt_float("max_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); @@ -3601,4 +3617,4 @@ ModelObject* ObjectList::object(const int obj_idx) const } } //namespace GUI -} //namespace Slic3r \ No newline at end of file +} //namespace Slic3r