From 7e1b2d99d324db63919fb7ad874a16c5ef86ccd0 Mon Sep 17 00:00:00 2001 From: minicx <39405619+loss-and-quick@users.noreply.github.com> Date: Sat, 21 Feb 2026 16:10:08 +0300 Subject: [PATCH] Add Pressure Advance visualization support (#11673) * Add Pressure Advance visualization support Signed-off-by: minicx * Port Pressure Advance visualization to libvgcode architecture Adapt PA visualization (originally in commit e3a77259) to work with the new libvgcode library introduced by upstream PR #10735. Changes across the libvgcode stack: - PathVertex: add pressure_advance field - Types.hpp: add PressureAdvance to EViewType enum - ViewerImpl: add ColorRange, color mapping, range updates for PA - LibVGCodeWrapper: pass pressure_advance from MoveVertex to PathVertex GCodeViewer UI integration: - Add "Pressure Advance" to view type dropdown - Add PA color range in legend (3 decimal places) - Add PA value display in sequential view marker tooltip - Add PA row in position properties table The GCodeProcessor PA parsing (M900, M572, SET_PRESSURE_ADVANCE) is preserved from the original implementation. * Tag Pressure Advance visualization changes with ORCA comments Signed-off-by: minicx --------- Signed-off-by: minicx Co-authored-by: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Co-authored-by: Claude --- src/libslic3r/GCode/GCodeProcessor.cpp | 43 +++++++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 10 +++++ src/libvgcode/include/PathVertex.hpp | 5 +++ src/libvgcode/include/Types.hpp | 2 + src/libvgcode/include/Viewer.hpp | 4 ++ src/libvgcode/src/ViewerImpl.cpp | 16 +++++++ src/libvgcode/src/ViewerImpl.hpp | 2 + src/slic3r/GUI/GCodeViewer.cpp | 21 +++++++++ src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp | 12 ++++-- 9 files changed, 111 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 8bf39eb715..be57bc563f 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1967,6 +1967,10 @@ void GCodeProcessor::register_commands() {"M702", [this](const GCodeReader::GCodeLine& line) { process_M702(line); }}, // Unload the current filament into the MK3 MMU2 unit at the end of print. {"M1020", [this](const GCodeReader::GCodeLine& line) { process_M1020(line); }}, // Select Tool +// ORCA: Add Pressure Advance visualization support + {"M900", [this](const GCodeReader::GCodeLine& line) { process_M900(line); }}, // Marlin: Set pressure advance + {"M572", [this](const GCodeReader::GCodeLine& line) { process_M572(line); }}, // RepRapFirmware/Duet: Set pressure advance + {"T", [this](const GCodeReader::GCodeLine& line) { process_T(line); }}, // Select Tool {"SYNC", [this](const GCodeReader::GCodeLine& line) { process_SYNC(line); }}, // SYNC TIME @@ -3028,6 +3032,12 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool process_SET_VELOCITY_LIMIT(line); return; } +// ORCA: Add Pressure Advance visualization support + if (boost::iequals(cmd, "SET_PRESSURE_ADVANCE")) + { + process_SET_PRESSURE_ADVANCE(line); + return; + } } if (cmd.length() > 1) { @@ -5150,6 +5160,37 @@ void GCodeProcessor::process_M106(const GCodeReader::GCodeLine& line) } } +// ORCA: Add Pressure Advance visualization support +void GCodeProcessor::process_M900(const GCodeReader::GCodeLine &line) +{ + float pa_value = m_pressure_advance; + line.has_value('K', pa_value); + m_pressure_advance = std::max(0.0f, pa_value); + // BOOST_LOG_TRIVIAL(debug) << "M900 command: PA set to " << m_pressure_advance; +} + +void GCodeProcessor::process_M572(const GCodeReader::GCodeLine &line) +{ + float pa_value = m_pressure_advance; + line.has_value('S', pa_value); + m_pressure_advance = std::max(0.0f, pa_value); + // BOOST_LOG_TRIVIAL(debug) << "M572 command: PA set to " << m_pressure_advance; +} + +void GCodeProcessor::process_SET_PRESSURE_ADVANCE(const GCodeReader::GCodeLine& line) +{ + std::regex regex(R"(SET_PRESSURE_ADVANCE\s+(?:.*\s+)?ADVANCE\s*=\s*([\d.]+))"); + std::smatch matches; + + if (std::regex_search(line.raw(), matches, regex) && matches.size() > 1) { + float pa_value = 0; + try { + pa_value = std::stof(matches[1].str()); + } catch (...) {} + m_pressure_advance = std::max(0.0f, pa_value); + } +} + void GCodeProcessor::process_M107(const GCodeReader::GCodeLine& line) { m_fan_speed = 0.0f; @@ -5689,6 +5730,8 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type, m_travel_dist, m_fan_speed, m_extruder_temps[filament_id], +// ORCA: Add Pressure Advance visualization support + m_pressure_advance, { 0.0f, 0.0f }, // time static_cast(m_layer_id), //layer_duration: set later std::max(1, m_layer_id) - 1, diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 06a448eac2..eb86aa57ab 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -184,6 +184,8 @@ class Print; float travel_dist{ 0.0f }; // mm float fan_speed{ 0.0f }; // percentage float temperature{ 0.0f }; // Celsius degrees +// ORCA: Add Pressure Advance visualization support + float pressure_advance{ 0.0f }; std::array(PrintEstimatedStatistics::ETimeMode::Count)> time{ 0.0f, 0.0f }; // s float layer_duration{ 0.0f }; // s unsigned int layer_id{ 0 }; @@ -777,6 +779,8 @@ class Print; float m_travel_dist; // mm float m_fan_speed; // percentage float m_z_offset; // mm +// ORCA: Add Pressure Advance visualization support + float m_pressure_advance; ExtrusionRole m_extrusion_role; std::vector m_filament_maps; std::vector m_last_filament_id; @@ -981,6 +985,12 @@ class Print; // Disable fan void process_M107(const GCodeReader::GCodeLine& line); +// ORCA: Add Pressure Advance visualization support + // Set pressure advance + void process_M900(const GCodeReader::GCodeLine& line); + void process_M572(const GCodeReader::GCodeLine &line); + void process_SET_PRESSURE_ADVANCE(const GCodeReader::GCodeLine& line); + // Set tool (Sailfish) void process_M108(const GCodeReader::GCodeLine& line); diff --git a/src/libvgcode/include/PathVertex.hpp b/src/libvgcode/include/PathVertex.hpp index d5101d9318..54d0a800f4 100644 --- a/src/libvgcode/include/PathVertex.hpp +++ b/src/libvgcode/include/PathVertex.hpp @@ -86,6 +86,11 @@ struct PathVertex // Layer duration in seconds // float layer_duration{ 0.0f }; + // + // ORCA: Add Pressure Advance visualization support + // Pressure advance value + // + float pressure_advance{ 0.0f }; // // Return true if the segment is an extrusion move diff --git a/src/libvgcode/include/Types.hpp b/src/libvgcode/include/Types.hpp index f637d9c290..7503ebc18b 100644 --- a/src/libvgcode/include/Types.hpp +++ b/src/libvgcode/include/Types.hpp @@ -92,6 +92,8 @@ enum class EViewType : uint8_t LayerTimeLogarithmic, FanSpeed, Temperature, +// ORCA: Add Pressure Advance visualization support + PressureAdvance, Tool, COUNT }; diff --git a/src/libvgcode/include/Viewer.hpp b/src/libvgcode/include/Viewer.hpp index 45636b465d..817b6ef5c2 100644 --- a/src/libvgcode/include/Viewer.hpp +++ b/src/libvgcode/include/Viewer.hpp @@ -169,6 +169,8 @@ public: // EViewType::ActualSpeed // EViewType::FanSpeed // EViewType::Temperature + // ORCA: Add Pressure Advance visualization support + // EViewType::PressureAdvance // EViewType::VolumetricFlowRate // EViewType::ActualVolumetricFlowRate // EViewType::LayerTimeLinear @@ -185,6 +187,8 @@ public: // EViewType::ActualSpeed // EViewType::FanSpeed // EViewType::Temperature + // ORCA: Add Pressure Advance visualization support + // EViewType::PressureAdvance // EViewType::VolumetricFlowRate // EViewType::ActualVolumetricFlowRate // EViewType::LayerTimeLinear diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index 51a3079be1..8576d697ad 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -1493,6 +1493,11 @@ Color ViewerImpl::get_vertex_color(const PathVertex& v) const { return v.is_travel() ? get_option_color(move_type_to_option(v.type)) : m_temperature_range.get_color_at(v.temperature); } +// ORCA: Add Pressure Advance visualization support + case EViewType::PressureAdvance: + { + return v.is_travel() ? get_option_color(move_type_to_option(v.type)) : m_pressure_advance_range.get_color_at(v.pressure_advance); + } case EViewType::VolumetricFlowRate: { return v.is_travel() ? get_option_color(move_type_to_option(v.type)) : m_volumetric_rate_range.get_color_at(v.volumetric_rate()); @@ -1582,6 +1587,8 @@ const ColorRange& ViewerImpl::get_color_range(EViewType type) const case EViewType::ActualSpeed: { return m_actual_speed_range; } case EViewType::FanSpeed: { return m_fan_speed_range; } case EViewType::Temperature: { return m_temperature_range; } +// ORCA: Add Pressure Advance visualization support + case EViewType::PressureAdvance: { return m_pressure_advance_range; } case EViewType::VolumetricFlowRate: { return m_volumetric_rate_range; } case EViewType::ActualVolumetricFlowRate: { return m_actual_volumetric_rate_range; } case EViewType::LayerTimeLinear: { return m_layer_time_range[0]; } @@ -1600,6 +1607,8 @@ void ViewerImpl::set_color_range_palette(EViewType type, const Palette& palette) case EViewType::ActualSpeed: { m_actual_speed_range.set_palette(palette); break; } case EViewType::FanSpeed: { m_fan_speed_range.set_palette(palette); break; } case EViewType::Temperature: { m_temperature_range.set_palette(palette); break; } +// ORCA: Add Pressure Advance visualization support + case EViewType::PressureAdvance: { m_pressure_advance_range.set_palette(palette); break; } case EViewType::VolumetricFlowRate: { m_volumetric_rate_range.set_palette(palette); break; } case EViewType::ActualVolumetricFlowRate: { m_actual_volumetric_rate_range.set_palette(palette); break; } case EViewType::LayerTimeLinear: { m_layer_time_range[0].set_palette(palette); break; } @@ -1637,6 +1646,8 @@ size_t ViewerImpl::get_used_cpu_memory() const ret += m_actual_speed_range.size_in_bytes_cpu(); ret += m_fan_speed_range.size_in_bytes_cpu(); ret += m_temperature_range.size_in_bytes_cpu(); + // ORCA: Add Pressure Advance visualization support + ret += m_pressure_advance_range.size_in_bytes_cpu(); ret += m_volumetric_rate_range.size_in_bytes_cpu(); ret += m_actual_volumetric_rate_range.size_in_bytes_cpu(); for (size_t i = 0; i < COLOR_RANGE_TYPES_COUNT; ++i) { @@ -1787,6 +1798,8 @@ void ViewerImpl::update_color_ranges() m_actual_speed_range.reset(); m_fan_speed_range.reset(); m_temperature_range.reset(); + // ORCA: Add Pressure Advance visualization support + m_pressure_advance_range.reset(); m_volumetric_rate_range.reset(); m_actual_volumetric_rate_range.reset(); m_layer_time_range[0].reset(); // ColorRange::EType::Linear @@ -1803,6 +1816,9 @@ void ViewerImpl::update_color_ranges() } m_fan_speed_range.update(round_to_bin(v.fan_speed)); m_temperature_range.update(round_to_bin(v.temperature)); + // ORCA: Add Pressure Advance visualization support + if (v.pressure_advance >= 0.0f) + m_pressure_advance_range.update(v.pressure_advance); } if ((v.is_travel() && m_settings.options_visibility[size_t(EOptionType::Travels)]) || (v.is_wipe() && m_settings.options_visibility[size_t(EOptionType::Wipes)]) || diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index e506274615..428815d277 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -289,6 +289,8 @@ private: ColorRange m_actual_speed_range; ColorRange m_fan_speed_range; ColorRange m_temperature_range; + // ORCA: Add Pressure Advance visualization support + ColorRange m_pressure_advance_range; ColorRange m_volumetric_rate_range; ColorRange m_actual_volumetric_rate_range; std::array m_layer_time_range{ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1d5d6b7883..a371a838da 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -91,6 +91,9 @@ static std::string get_view_type_string(libvgcode::EViewType view_type) return _u8L("Layer Time"); else if (view_type == libvgcode::EViewType::LayerTimeLogarithmic) return _u8L("Layer Time (log)"); +// ORCA: Add Pressure Advance visualization support + else if (view_type == libvgcode::EViewType::PressureAdvance) + return _u8L("Pressure Advance"); return ""; } @@ -397,6 +400,11 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode sprintf(buff, ("%.0f " + _u8L("°C")).c_str(), vertex.temperature); ImGuiWrapper::text(std::string(buff)); }); +// ORCA: Add Pressure Advance visualization support + append_table_row(_u8L("Pressure Advance"), [&vertex, &buff]() { + sprintf(buff, "%.4f", vertex.pressure_advance); + ImGuiWrapper::text(std::string(buff)); + }); append_table_row(_u8L("Time"), [viewer, &vertex, &buff, vertex_id]() { const float estimated_time = viewer->get_estimated_time_at(vertex_id); sprintf(buff, "%s (%.3fs)", get_time_dhms(estimated_time).c_str(), vertex.times[static_cast(viewer->get_time_mode())]); @@ -607,6 +615,11 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode sprintf(buf, "%s %s%.1f", buf, _u8L("Actual Speed: ").c_str(), vertex.actual_feedrate); break; } +// ORCA: Add Pressure Advance visualization support + case libvgcode::EViewType::PressureAdvance: { + sprintf(buf, "%s %s%.4f", buf, _u8L("PA: ").c_str(), vertex.pressure_advance); + break; + } default: break; @@ -1024,6 +1037,8 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode) view_type_items.push_back(libvgcode::EViewType::LayerTimeLogarithmic); view_type_items.push_back(libvgcode::EViewType::FanSpeed); view_type_items.push_back(libvgcode::EViewType::Temperature); +// ORCA: Add Pressure Advance visualization support + view_type_items.push_back(libvgcode::EViewType::PressureAdvance); //if (mode == ConfigOptionMode::comDevelop) { // view_type_items.push_back(EViewType::Tool); //} @@ -2250,6 +2265,8 @@ void GCodeViewer::render_toolpaths() add_range_property_row("speed range", m_viewer.get_color_range(libvgcode::EViewType::Speed).get_range()); add_range_property_row("fan speed range", m_viewer.get_color_range(libvgcode::EViewType::FanSpeed).get_range()); add_range_property_row("temperature range", m_viewer.get_color_range(libvgcode::EViewType::Temperature).get_range()); +// ORCA: Add Pressure Advance visualization support + add_range_property_row("pressure advance range", m_viewer.get_color_range(libvgcode::EViewType::PressureAdvance).get_range()); add_range_property_row("volumetric rate range", m_viewer.get_color_range(libvgcode::EViewType::VolumetricFlowRate).get_range()); add_range_property_row("layer time linear range", m_viewer.get_color_range(libvgcode::EViewType::LayerTimeLinear).get_range()); add_range_property_row("layer time logarithmic range", m_viewer.get_color_range(libvgcode::EViewType::LayerTimeLogarithmic).get_range()); @@ -3498,6 +3515,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } case libvgcode::EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } case libvgcode::EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } +// ORCA: Add Pressure Advance visualization support + case libvgcode::EViewType::PressureAdvance:{ imgui.title(_u8L("Pressure Advance")); break; } case libvgcode::EViewType::VolumetricFlowRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } case libvgcode::EViewType::ActualVolumetricFlowRate: @@ -3674,6 +3693,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } case libvgcode::EViewType::FanSpeed: { append_range(m_viewer.get_color_range(libvgcode::EViewType::FanSpeed), 0); break; } case libvgcode::EViewType::Temperature: { append_range(m_viewer.get_color_range(libvgcode::EViewType::Temperature), 0); break; } +// ORCA: Add Pressure Advance visualization support + case libvgcode::EViewType::PressureAdvance: { append_range(m_viewer.get_color_range(libvgcode::EViewType::PressureAdvance), 3); break; } case libvgcode::EViewType::LayerTimeLinear: { append_range(m_viewer.get_color_range(libvgcode::EViewType::LayerTimeLinear), true); break; } case libvgcode::EViewType::LayerTimeLogarithmic: { append_range(m_viewer.get_color_range(libvgcode::EViewType::LayerTimeLogarithmic), true); break; } case libvgcode::EViewType::VolumetricFlowRate: { append_range(m_viewer.get_color_range(libvgcode::EViewType::VolumetricFlowRate), 2); break; } diff --git a/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp b/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp index a966a391f3..4f33c18b80 100644 --- a/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp +++ b/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp @@ -224,12 +224,14 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve const libvgcode::PathVertex vertex = { convert(prev.position), curr.height, curr.width, curr.feedrate, prev.actual_feedrate, curr.mm3_per_mm, curr.fan_speed, curr.temperature, 0.0f, convert(curr.extrusion_role), curr_type, static_cast(curr.gcode_id), static_cast(curr.layer_id), - static_cast(curr.extruder_id), static_cast(curr.cp_color_id), { 0.0f, 0.0f } }; + static_cast(curr.extruder_id), static_cast(curr.cp_color_id), { 0.0f, 0.0f }, + /* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance }; #else const libvgcode::PathVertex vertex = { convert(prev.position), curr.height, curr.width, curr.feedrate, prev.actual_feedrate, curr.mm3_per_mm, curr.fan_speed, curr.temperature, convert(curr.extrusion_role), curr_type, static_cast(curr.gcode_id), static_cast(curr.layer_id), - static_cast(curr.extruder_id), static_cast(curr.cp_color_id), { 0.0f, 0.0f } }; + static_cast(curr.extruder_id), static_cast(curr.cp_color_id), { 0.0f, 0.0f }, + /* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance }; #endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS ret.vertices.emplace_back(vertex); } @@ -240,12 +242,14 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve curr.mm3_per_mm, curr.fan_speed, curr.temperature, result.filament_densities[curr.extruder_id] * curr.mm3_per_mm * (curr.position - prev.position).norm(), convert(curr.extrusion_role), curr_type, static_cast(curr.gcode_id), static_cast(curr.layer_id), - static_cast(curr.extruder_id), static_cast(curr.cp_color_id), curr.time }; + static_cast(curr.extruder_id), static_cast(curr.cp_color_id), curr.time, + /* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance }; #else const libvgcode::PathVertex vertex = { convert(curr.position), curr.height, curr.width, curr.feedrate, curr.actual_feedrate, curr.mm3_per_mm, curr.fan_speed, curr.temperature, convert(curr.extrusion_role), curr_type, static_cast(curr.gcode_id), static_cast(curr.layer_id), - static_cast(curr.extruder_id), static_cast(curr.cp_color_id), curr.time }; + static_cast(curr.extruder_id), static_cast(curr.cp_color_id), curr.time, + /* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance }; #endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS ret.vertices.emplace_back(vertex); }