diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 8d0c7f070..29316a9de 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -836,6 +836,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu path_tmp += ".tmp"; m_processor.initialize(path_tmp); + m_processor.set_print(print); GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"), m_processor); if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 728d381f1..e34e4e5dd 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -3384,7 +3384,7 @@ void GCodeProcessor::process_T(const std::string_view command) if (m_extruder_id != id) { if (((m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) && id >= m_result.extruders_count) || ((m_producer != EProducer::PrusaSlicer && m_producer != EProducer::Slic3rPE && m_producer != EProducer::Slic3r) && id >= m_result.extruder_colors.size())) - BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode."; + BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode (" << command << ")."; else { unsigned char old_extruder_id = m_extruder_id; process_filaments(CustomGCode::ToolChange); @@ -3984,13 +3984,25 @@ void GCodeProcessor::post_process() #if ENABLE_GCODE_POSTPROCESS_BACKTRACE // add lines XXX to exported gcode - auto process_line_T = [this, &export_lines](const std::string& gcode_line, const size_t g1_lines_counter, const ExportLines::Backtrace& backtrace) { + auto process_line_T = [this, &export_lines](const std::string& gcode_line, const size_t g1_lines_counter, const ExportLines::Backtrace& backtrace) { const std::string cmd = GCodeReader::GCodeLine::extract_cmd(gcode_line); if (cmd.size() >= 2) { std::stringstream ss(cmd.substr(1)); int tool_number = -1; ss >> tool_number; if (tool_number != -1) + if (tool_number < 0 || (int)m_extruder_temps_config.size() <= tool_number) { + // found an invalid value, clamp it to a valid one + tool_number = std::clamp(0, m_extruder_temps_config.size() - 1, tool_number); + // emit warning + std::string warning = _u8L("GCode Post-Processor encountered an invalid toolchange, maybe from a custom gcode:"); + warning += "\n> "; + warning += gcode_line; + warning += _u8L("Generated M104 lines may be incorrect."); + BOOST_LOG_TRIVIAL(error) << warning; + if (m_print != nullptr) + m_print->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning); + } export_lines.insert_lines(backtrace, cmd, // line inserter [tool_number, this](unsigned int id, float time, float time_diff) { diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 856d5b31f..1f29488c3 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -16,6 +16,8 @@ namespace Slic3r { + class Print; + enum class EMoveType : unsigned char { Noop, @@ -588,6 +590,8 @@ namespace Slic3r { TimeProcessor m_time_processor; UsedFilaments m_used_filaments; + Print* m_print{ nullptr }; + GCodeProcessorResult m_result; static unsigned int s_result_id; @@ -601,6 +605,8 @@ namespace Slic3r { GCodeProcessor(); void apply_config(const PrintConfig& config); + void set_print(Print* print) { m_print = print; } + void enable_stealth_time_estimator(bool enabled); bool is_stealth_time_estimator_enabled() const { return m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 4496de5bf..d222fbfe2 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -660,6 +660,8 @@ private: // To allow GCode to set the Print's GCodeExport step status. friend class GCode; + // To allow GCodeProcessor to emit warnings. + friend class GCodeProcessor; // Allow PrintObject to access m_mutex and m_cancel_callback. friend class PrintObject; };