diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 737c4fcda5..fd1ddf0550 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -139,6 +139,11 @@ void AppConfig::set_defaults() if (get("seq_top_layer_only").empty()) set("seq_top_layer_only", "1"); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (get("seq_top_gcode_indices").empty()) + set("seq_top_gcode_indices", "1"); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (get("use_perspective_camera").empty()) set("use_perspective_camera", "1"); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 5ac9a34c4b..ab7046b50c 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -324,7 +324,11 @@ void GCodeProcessor::TimeProcessor::reset() machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Normal)].enabled = true; } +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER +void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves) +#else void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER { boost::nowide::ifstream in(filename); if (!in.good()) @@ -414,6 +418,9 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) g1_times_cache_it.emplace_back(machine.g1_times_cache.begin()); // add lines M73 to exported gcode auto process_line_G1 = [&]() { +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + unsigned int exported_lines_count = 0; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER if (export_remaining_time_enabled) { for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { const TimeMachine& machine = machines[i]; @@ -430,11 +437,17 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) export_line += format_line_M73(machine.line_m73_mask.c_str(), to_export.first, to_export.second); last_exported[i] = to_export; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + ++exported_lines_count; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER } } } } } +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + return exported_lines_count; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER }; // helper function to write to disk @@ -449,12 +462,21 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) export_line.clear(); }; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + unsigned int line_id = 0; + std::vector> offsets; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + while (std::getline(in, gcode_line)) { if (!in.good()) { fclose(out); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); } +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + ++line_id; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + gcode_line += "\n"; // replace placeholder lines auto [processed, result] = process_placeholders(gcode_line); @@ -468,8 +490,16 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) parser.parse_line(gcode_line, [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { if (line.cmd_is("G1")) { +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + unsigned int extra_lines_count = process_line_G1(); +#else process_line_G1(); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER ++g1_lines_counter; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (extra_lines_count > 0) + offsets.push_back({ line_id, extra_lines_count }); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER } }); } @@ -485,6 +515,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename) fclose(out); in.close(); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + // updates moves' gcode ids which have been modified by the insertion of the M73 lines + unsigned int curr_offset_id = 0; + unsigned int total_offset = 0; + for (MoveVertex& move : moves) { + while (curr_offset_id < static_cast(offsets.size()) && offsets[curr_offset_id].first <= move.gcode_id) { + total_offset += offsets[curr_offset_id].second; + ++curr_offset_id; + } + move.gcode_id += total_offset; + } +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (rename_file(out_path, filename)) throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + filename + '\n' + "Is " + out_path + " locked?" + '\n'); @@ -750,6 +793,9 @@ void GCodeProcessor::reset() m_cached_position.reset(); m_wiping = false; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_line_id = 0; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER m_feedrate = 0.0f; m_width = 0.0f; m_height = 0.0f; @@ -859,7 +905,11 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr // post-process to add M73 lines into the gcode if (apply_postprocess) +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_time_processor.post_process(filename, m_result.moves); +#else m_time_processor.post_process(filename); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER #if ENABLE_GCODE_VIEWER_DATA_CHECKING std::cout << "\n"; @@ -935,6 +985,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) { /* std::cout << line.raw() << std::endl; */ +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + ++m_line_id; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + // update start position m_start_position = m_end_position; @@ -2376,6 +2430,9 @@ void GCodeProcessor::process_T(const std::string_view command) void GCodeProcessor::store_move_vertex(EMoveType type) { MoveVertex vertex = { +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_line_id, +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER type, m_extrusion_role, m_extruder_id, diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 5068d0fd62..4b69b6c6ac 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -173,6 +173,27 @@ namespace Slic3r { float time() const; }; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + struct MoveVertex + { + unsigned int gcode_id{ 0 }; + EMoveType type{ EMoveType::Noop }; + ExtrusionRole extrusion_role{ erNone }; + unsigned char extruder_id{ 0 }; + unsigned char cp_color_id{ 0 }; + Vec3f position{ Vec3f::Zero() }; // mm + float delta_extruder{ 0.0f }; // mm + float feedrate{ 0.0f }; // mm/s + float width{ 0.0f }; // mm + float height{ 0.0f }; // mm + float mm3_per_mm{ 0.0f }; + float fan_speed{ 0.0f }; // percentage + float time{ 0.0f }; // s + + float volumetric_rate() const { return feedrate * mm3_per_mm; } + }; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + private: struct TimeMachine { @@ -253,10 +274,16 @@ namespace Slic3r { void reset(); // post process the file with the given filename to add remaining time lines M73 +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + // and updates moves' gcode ids accordingly + void post_process(const std::string& filename, std::vector& moves); +#else void post_process(const std::string& filename); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER }; public: +#if !ENABLE_GCODE_LINES_ID_IN_H_SLIDER struct MoveVertex { EMoveType type{ EMoveType::Noop }; @@ -274,6 +301,7 @@ namespace Slic3r { float volumetric_rate() const { return feedrate * mm3_per_mm; } }; +#endif // !ENABLE_GCODE_LINES_ID_IN_H_SLIDER struct Result { @@ -404,6 +432,9 @@ namespace Slic3r { CachedPosition m_cached_position; bool m_wiping; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + unsigned int m_line_id; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER float m_feedrate; // mm/s float m_width; // mm float m_height; // mm diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 5bdf9edb92..7588a82d39 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -117,6 +117,7 @@ #define ENABLE_RELOAD_FROM_DISK_FOR_3MF (1 && ENABLE_2_3_1_ALPHA1) #define ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS (1 && ENABLE_SPLITTED_VERTEX_BUFFER) #define ENABLE_WARNING_TEXTURE_REMOVAL (1 && ENABLE_2_3_1_ALPHA1) +#define ENABLE_GCODE_LINES_ID_IN_H_SLIDER (1 && ENABLE_2_3_1_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index fddb63e3e4..879a019dfa 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -646,8 +646,16 @@ wxString Control::get_label(int tick, LabelType label_type/* = ltHeightWithLayer if (value >= m_values.size()) return "ErrVal"; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (m_draw_mode == dmSequentialGCodeView) { + return (Slic3r::GUI::get_app_config()->get("seq_top_gcode_indices") == "1") ? + wxString::Format("%lu", static_cast(m_alternate_values[value])) : + wxString::Format("%lu", static_cast(m_values[value])); + } +#else if (m_draw_mode == dmSequentialGCodeView) return wxString::Format("%lu", static_cast(m_values[value])); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER else { if (label_type == ltEstimatedTime) { return (value < m_layers_times.size()) ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : ""; diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 0d90367c0a..ae12fb4c6e 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -215,6 +215,9 @@ public: void SetKoefForLabels(const double koef) { m_label_koef = koef; } void SetSliderValues(const std::vector& values); void ChangeOneLayerLock(); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + void SetSliderAlternateValues(const std::vector& values) { m_alternate_values = values; } +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER Info GetTicksValues() const; void SetTicksValues(const Info &custom_gcode_per_print_z); @@ -383,14 +386,17 @@ private: int m_cog_icon_dim; long m_style; long m_extra_style; - float m_label_koef = 1.0; + float m_label_koef{ 1.0 }; std::vector m_values; TickCodeInfo m_ticks; std::vector m_layers_times; - std::vector m_extruder_colors; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + std::vector m_alternate_values; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + // control's view variables wxCoord SLIDER_MARGIN; // margin around slider diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index fb60679312..efa290f3a7 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1516,6 +1516,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) m_max_bounding_box = m_paths_bounding_box; m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_sequential_view.gcode_ids.clear(); + for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) { + m_sequential_view.gcode_ids.push_back(move.gcode_id); + } +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + std::vector vertices(m_buffers.size()); std::vector indices(m_buffers.size()); std::vector options_zs; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 1d86cf55a2..f6dcce5cd1 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -599,6 +599,9 @@ public: Endpoints last_current; Vec3f current_position{ Vec3f::Zero() }; Marker marker; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + std::vector gcode_ids; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER }; enum class EViewType : unsigned char diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c672e0609a..3f36f0fed2 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1716,7 +1716,11 @@ void GUI_App::add_config_menu(wxMenuBar *menu) PreferencesDialog dlg(mainframe); dlg.ShowModal(); app_layout_changed = dlg.settings_layout_changed(); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed()) +#else if (dlg.seq_top_layer_only_changed()) +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER this->plater_->refresh_print(); #if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN #ifdef _WIN32 diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 3a1ec46f2e..5efbb4a73f 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -816,12 +816,25 @@ void Preview::update_moves_slider() return; std::vector values(view.endpoints.last - view.endpoints.first + 1); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + std::vector alternate_values(view.endpoints.last - view.endpoints.first + 1); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER unsigned int count = 0; for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i) { +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + values[count] = static_cast(i + 1); + if (view.gcode_ids[i] > 0) + alternate_values[count] = static_cast(view.gcode_ids[i]); + ++count; +#else values[count++] = static_cast(i + 1); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER } m_moves_slider->SetSliderValues(values); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_moves_slider->SetSliderAlternateValues(alternate_values); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first); m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first); } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index c4aa663aa1..cba941a396 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -39,7 +39,7 @@ static void activate_options_tab(std::shared_ptr optgroup) optgroup->activate(); optgroup->update_visibility(comSimple); wxBoxSizer* sizer = static_cast(static_cast(optgroup->parent())->GetSizer()); - sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 20); + sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); } void PreferencesDialog::build() @@ -275,12 +275,22 @@ void PreferencesDialog::build() 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"); m_optgroup_gui->append_single_option_line(option); +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + def.label = L("Sequential slider shows gcode line numbers"); + def.type = coBool; + def.tooltip = L("If enabled, the sequential slider, in preview, shows the gcode lines numbers." + "If disabled, the sequential slider, in preview, shows the move index."); + def.set_default_value(new ConfigOptionBool{ app_config->get("seq_top_gcode_indices") == "1" }); + option = Option(def, "seq_top_gcode_indices"); + m_optgroup_gui->append_single_option_line(option); +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + if (is_editor) { def.label = L("Show sidebar collapse/expand button"); def.type = coBool; @@ -366,6 +376,12 @@ void PreferencesDialog::accept() if (auto it = m_values.find("seq_top_layer_only"); it != m_values.end()) m_seq_top_layer_only_changed = app_config->get("seq_top_layer_only") != it->second; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_seq_top_gcode_indices_changed = false; + if (auto it = m_values.find("seq_top_gcode_indices"); it != m_values.end()) + m_seq_top_gcode_indices_changed = app_config->get("seq_top_gcode_indices") != it->second; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + m_settings_layout_changed = false; for (const std::string& key : { "old_settings_layout_mode", "new_settings_layout_mode", @@ -509,7 +525,7 @@ void PreferencesDialog::create_settings_mode_widget() auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_layout_mode_box, 1, wxALIGN_CENTER_VERTICAL); - m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND); + m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); } void PreferencesDialog::create_settings_text_color_widget() @@ -520,7 +536,7 @@ void PreferencesDialog::create_settings_text_color_widget() if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); wxSizer* sizer = new wxStaticBoxSizer(stb, wxVERTICAL); - wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, 10, 20); + wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, 5, 5); sizer->Add(grid_sizer, 0, wxEXPAND); auto sys_label = new wxStaticText(parent, wxID_ANY, _L("Value is the same as the system value")); @@ -531,8 +547,8 @@ void PreferencesDialog::create_settings_text_color_widget() sys_label->Refresh(); }); - grid_sizer->Add(m_sys_colour, -1, wxALIGN_CENTRE_VERTICAL); - grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + grid_sizer->Add(m_sys_colour, 0, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(sys_label, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND); auto mod_label = new wxStaticText(parent, wxID_ANY, _L("Value was changed and is not equal to the system value or the last saved preset")); mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified()); @@ -542,8 +558,8 @@ void PreferencesDialog::create_settings_text_color_widget() mod_label->Refresh(); }); - grid_sizer->Add(m_mod_colour, -1, wxALIGN_CENTRE_VERTICAL); - grid_sizer->Add(mod_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + grid_sizer->Add(m_mod_colour, 0, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(mod_label, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); } diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 0da0447365..68e75662ae 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -31,12 +31,19 @@ class PreferencesDialog : public DPIDialog bool isOSX {false}; bool m_settings_layout_changed {false}; bool m_seq_top_layer_only_changed{ false }; +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + bool m_seq_top_gcode_indices_changed{ false }; +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER + public: - PreferencesDialog(wxWindow* parent); - ~PreferencesDialog() {} + explicit PreferencesDialog(wxWindow* parent); + ~PreferencesDialog() = default; bool settings_layout_changed() const { return m_settings_layout_changed; } bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; } +#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER + bool seq_seq_top_gcode_indices_changed() const { return m_seq_top_gcode_indices_changed; } +#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER void build(); void accept();