mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-19 19:33:47 +00:00
enh: flow rate pattern calibration menu (#11956)
* feat: Add flow rate calibration pattern selector dialog * feat: Integrate PR #11881 and improve Flow Rate Calibration Wizard - Integrated PR #11881: Display layer duration in G-code viewer position window. - Enhanced Flow Rate Calibration: - Implemented a Wizard dialog (FlowRateCalibrationDialog) using DPIDialog for Dark Mode support. - Restricted pattern selection to 'Archimedean Chords' and 'Monotonic'. - Integrated logic to pass the selected pattern to the calibration generation. * fix(UI): Refactor FlowRateCalibrationDialog to calib_dlg for macOS build fix and UI consistency Moved FlowRateCalibrationDialog from MainFrame.cpp to calib_dlg.hpp/.cpp to resolve build errors on macOS. Updated UI to match Pressure Advance calibration dialog style (Dark Mode support, RadioGroups). Logic moved to dialog class. * Update Wiki link for flow rate calibration * ui: replace RadioGroup with BitmapComboBox for Flow Rate pattern selection * fix(ui): use custom ComboBox widget for Flow Rate Calibration Replaces wxBitmapComboBox with OrcaSlicer's custom ComboBox widget to fix rendering issues on Windows (empty selection) and compilation errors on Linux. * Refactor: Cleanup unused includes and members in FlowRate calibration dialog * Fix: Complete rename of Flow Rate to Flow ratio in calibration menus after merge * Fix: Update Flow Rate to Flow Ratio in Calibration Dialog and Wiki Link --------- Co-authored-by: yw4z <ywsyildiz@gmail.com> Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
@@ -25,7 +25,7 @@ wxString get_calibration_type_name(CalibMode cali_mode)
|
|||||||
case CalibMode::Calib_PA_Line:
|
case CalibMode::Calib_PA_Line:
|
||||||
return _L("Flow Dynamics");
|
return _L("Flow Dynamics");
|
||||||
case CalibMode::Calib_Flow_Rate:
|
case CalibMode::Calib_Flow_Rate:
|
||||||
return _L("Flow Rate");
|
return _L("Flow ratio");
|
||||||
case CalibMode::Calib_Vol_speed_Tower:
|
case CalibMode::Calib_Vol_speed_Tower:
|
||||||
return _L("Max Volumetric Speed");
|
return _L("Max Volumetric Speed");
|
||||||
case CalibMode::Calib_Temp_Tower:
|
case CalibMode::Calib_Temp_Tower:
|
||||||
|
|||||||
@@ -3278,23 +3278,15 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
}, "", nullptr,
|
}, "", nullptr,
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
[this]() {return m_plater->is_view3D_shown();; }, this);
|
||||||
|
|
||||||
// Flow rate (with submenu)
|
// Flow rate (Wizard Dialog)
|
||||||
auto flowrate_menu = new wxMenu();
|
append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Flow ratio"), _L("Flow Rate Calibration"),
|
||||||
append_menu_item(
|
[this](wxCommandEvent&) {
|
||||||
flowrate_menu, wxID_ANY, _L("Pass 1"), _L("Flow ratio test - Pass 1"),
|
if (!m_plater) return;
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 1); }, "", nullptr,
|
if (!m_flow_rate_calib_dlg)
|
||||||
|
m_flow_rate_calib_dlg = new FlowRateCalibrationDialog((wxWindow*)this, wxID_ANY, m_plater);
|
||||||
|
m_flow_rate_calib_dlg->ShowModal();
|
||||||
|
}, "", nullptr,
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
[this]() {return m_plater->is_view3D_shown();; }, this);
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("Pass 2"), _L("Flow ratio test - Pass 2"),
|
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 2); }, "", nullptr,
|
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
|
||||||
flowrate_menu->AppendSeparator();
|
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (Recommended)"), _L("Orca YOLO flowratio calibration, 0.01 step"),
|
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 1); }, "", nullptr,
|
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (perfectionist version)"), _L("Orca YOLO flowratio calibration, 0.005 step"),
|
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 2); }, "", nullptr,
|
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
|
||||||
m_topbar->GetCalibMenu()->AppendSubMenu(flowrate_menu, _L("Flow ratio"));
|
|
||||||
|
|
||||||
// Retraction
|
// Retraction
|
||||||
append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Retraction"), _L("Retraction"),
|
append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Retraction"), _L("Retraction"),
|
||||||
@@ -3390,21 +3382,14 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
[this]() {return m_plater->is_view3D_shown();; }, this);
|
||||||
|
|
||||||
// Flowrate (with submenu)
|
// Flowrate (with submenu)
|
||||||
auto flowrate_menu = new wxMenu();
|
// ORCA: Flow rate (Wizard Dialog)
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("Pass 1"), _L("Flow ratio test - Pass 1"),
|
append_menu_item(calib_menu, wxID_ANY, _L("Flow ratio"), _L("Flow Rate Calibration"),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 1); }, "", nullptr,
|
[this](wxCommandEvent&) {
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
if (!m_plater) return;
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("Pass 2"), _L("Flow ratio test - Pass 2"),
|
if (!m_flow_rate_calib_dlg)
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 2); }, "", nullptr,
|
m_flow_rate_calib_dlg = new FlowRateCalibrationDialog((wxWindow*)this, wxID_ANY, m_plater);
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
m_flow_rate_calib_dlg->ShowModal();
|
||||||
append_submenu(calib_menu,flowrate_menu,wxID_ANY,_L("Flow ratio"),_L("Flow ratio"),"",
|
}, "", nullptr,
|
||||||
[this]() {return m_plater->is_view3D_shown();; });
|
|
||||||
flowrate_menu->AppendSeparator();
|
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (Recommended)"), _L("Orca YOLO flowratio calibration, 0.01 step"),
|
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 1); }, "", nullptr,
|
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
|
||||||
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (perfectionist version)"), _L("Orca YOLO flowratio calibration, 0.005 step"),
|
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 2); }, "", nullptr,
|
|
||||||
[this]() {return m_plater->is_view3D_shown();; }, this);
|
[this]() {return m_plater->is_view3D_shown();; }, this);
|
||||||
|
|
||||||
// Retraction
|
// Retraction
|
||||||
@@ -4361,3 +4346,4 @@ void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
|
|||||||
|
|
||||||
} // GUI
|
} // GUI
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ public:
|
|||||||
void fit_tab_labels(); // ORCA
|
void fit_tab_labels(); // ORCA
|
||||||
|
|
||||||
PA_Calibration_Dlg* m_pa_calib_dlg{ nullptr };
|
PA_Calibration_Dlg* m_pa_calib_dlg{ nullptr };
|
||||||
|
FlowRateCalibrationDialog* m_flow_rate_calib_dlg{ nullptr };
|
||||||
Temp_Calibration_Dlg* m_temp_calib_dlg{ nullptr };
|
Temp_Calibration_Dlg* m_temp_calib_dlg{ nullptr };
|
||||||
MaxVolumetricSpeed_Test_Dlg* m_vol_test_dlg { nullptr };
|
MaxVolumetricSpeed_Test_Dlg* m_vol_test_dlg { nullptr };
|
||||||
VFA_Test_Dlg* m_vfa_test_dlg { nullptr };
|
VFA_Test_Dlg* m_vfa_test_dlg { nullptr };
|
||||||
|
|||||||
@@ -12769,7 +12769,8 @@ void Plater::_calib_pa_select_added_objects() {
|
|||||||
|
|
||||||
// Adjust settings for flowrate calibration
|
// Adjust settings for flowrate calibration
|
||||||
// For linear mode, pass 1 means normal version while pass 2 mean "for perfectionists" version
|
// For linear mode, pass 1 means normal version while pass 2 mean "for perfectionists" version
|
||||||
void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, int pass)
|
// ORCA: Add pattern parameter
|
||||||
|
void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, int pass, InfillPattern pattern)
|
||||||
{
|
{
|
||||||
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
auto printerConfig = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
auto printerConfig = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
@@ -12832,7 +12833,8 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
|||||||
_obj->config.set_key_value("sparse_infill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
_obj->config.set_key_value("sparse_infill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||||
_obj->config.set_key_value("top_surface_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
_obj->config.set_key_value("top_surface_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
||||||
_obj->config.set_key_value("internal_solid_infill_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
_obj->config.set_key_value("internal_solid_infill_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false));
|
||||||
_obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum<InfillPattern>(ipArchimedeanChords));
|
// ORCA: use the pattern parameter
|
||||||
|
_obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum<InfillPattern>(pattern));
|
||||||
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
_obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f));
|
||||||
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
_obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45));
|
||||||
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
_obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));
|
||||||
@@ -12883,7 +12885,8 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i
|
|||||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config();
|
wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::calib_flowrate(bool is_linear, int pass) {
|
// ORCA: Add pattern parameter
|
||||||
|
void Plater::calib_flowrate(bool is_linear, int pass, InfillPattern pattern) {
|
||||||
if (pass != 1 && pass != 2)
|
if (pass != 1 && pass != 2)
|
||||||
return;
|
return;
|
||||||
wxString calib_name;
|
wxString calib_name;
|
||||||
@@ -12915,7 +12918,8 @@ void Plater::calib_flowrate(bool is_linear, int pass) {
|
|||||||
(boost::filesystem::path(Slic3r::resources_dir()) / "calib" / "filament_flow" / "flowrate-test-pass2.3mf").string());
|
(boost::filesystem::path(Slic3r::resources_dir()) / "calib" / "filament_flow" / "flowrate-test-pass2.3mf").string());
|
||||||
}
|
}
|
||||||
|
|
||||||
adjust_settings_for_flowrate_calib(model().objects, is_linear, pass);
|
// ORCA: pass the pattern
|
||||||
|
adjust_settings_for_flowrate_calib(model().objects, is_linear, pass, pattern);
|
||||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config();
|
wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config();
|
||||||
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
|
printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false});
|
||||||
|
|||||||
@@ -331,7 +331,8 @@ public:
|
|||||||
|
|
||||||
// SoftFever
|
// SoftFever
|
||||||
void calib_pa(const Calib_Params& params);
|
void calib_pa(const Calib_Params& params);
|
||||||
void calib_flowrate(bool is_linear, int pass);
|
//ORCA: Add pattern parameter to calib_flowrate
|
||||||
|
void calib_flowrate(bool is_linear, int pass, InfillPattern pattern = ipArchimedeanChords);
|
||||||
void calib_temp(const Calib_Params& params);
|
void calib_temp(const Calib_Params& params);
|
||||||
void calib_max_vol_speed(const Calib_Params& params);
|
void calib_max_vol_speed(const Calib_Params& params);
|
||||||
void calib_retraction(const Calib_Params& params);
|
void calib_retraction(const Calib_Params& params);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
#include "libslic3r/Utils.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
@@ -1436,4 +1437,97 @@ void Cornering_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
|
|||||||
Fit();
|
Fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlowRateCalibrationDialog
|
||||||
|
//
|
||||||
|
FlowRateCalibrationDialog::FlowRateCalibrationDialog(wxWindow* parent, wxWindowID id, Plater* plater)
|
||||||
|
: DPIDialog(parent, id, _L("Flow Ratio Calibration"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
|
||||||
|
{
|
||||||
|
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
|
||||||
|
SetForegroundColour(wxColour("#363636"));
|
||||||
|
SetFont(Label::Body_14);
|
||||||
|
|
||||||
|
wxBoxSizer* v_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
SetSizer(v_sizer);
|
||||||
|
|
||||||
|
// Type selection
|
||||||
|
auto labeled_box_type = new LabeledStaticBox(this, _L("Calibration Test Type"));
|
||||||
|
auto type_box = new wxStaticBoxSizer(labeled_box_type, wxVERTICAL);
|
||||||
|
|
||||||
|
m_rbType = new RadioGroup(this, { _L("Pass 1 (Coarse)"), _L("Pass 2 (Fine)"), _L("YOLO (Recommended)"), _L("YOLO (Perfectionist)") }, wxVERTICAL, 1);
|
||||||
|
m_rbType->SetSelection(2); // Default to YOLO Recommended
|
||||||
|
type_box->Add(m_rbType, 0, wxALL | wxEXPAND, FromDIP(4));
|
||||||
|
v_sizer->Add(type_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
|
||||||
|
|
||||||
|
// Pattern selection
|
||||||
|
auto labeled_box_pattern = new LabeledStaticBox(this, _L("Top Surface Pattern"));
|
||||||
|
auto pattern_box = new wxStaticBoxSizer(labeled_box_pattern, wxVERTICAL);
|
||||||
|
|
||||||
|
// ORCA: Use ComboBox with icons instead of RadioGroup
|
||||||
|
m_rbPattern = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
|
||||||
|
|
||||||
|
boost::filesystem::path image_path(Slic3r::resources_dir());
|
||||||
|
image_path /= "images";
|
||||||
|
|
||||||
|
auto add_pattern_item = [&](const std::string& name, const wxString& label) {
|
||||||
|
auto icon_name = "param_" + name;
|
||||||
|
if (boost::filesystem::exists(image_path / (icon_name + ".svg"))) {
|
||||||
|
// Using 24px icon size to match other settings (Field.cpp uses 24)
|
||||||
|
ScalableBitmap bm(this, icon_name, 24);
|
||||||
|
m_rbPattern->Append(label, bm.bmp());
|
||||||
|
} else {
|
||||||
|
m_rbPattern->Append(label);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
add_pattern_item("archimedeanchords", _L("Archimedean Chords"));
|
||||||
|
add_pattern_item("monotonic", _L("Monotonic"));
|
||||||
|
m_rbPattern->SetSelection(0); // Default to Archimedean Chords
|
||||||
|
// ORCA: explicit set value to ensure display on Windows
|
||||||
|
m_rbPattern->SetValue(m_rbPattern->GetString(0));
|
||||||
|
|
||||||
|
pattern_box->Add(m_rbPattern, 0, wxALL | wxEXPAND, FromDIP(4));
|
||||||
|
v_sizer->Add(pattern_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
|
||||||
|
|
||||||
|
v_sizer->AddSpacer(FromDIP(5));
|
||||||
|
|
||||||
|
auto dlg_btns = new DialogButtons(this, {"OK"});
|
||||||
|
|
||||||
|
auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/calibration/flow-ratio-calib");
|
||||||
|
bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20));
|
||||||
|
bottom_sizer->AddStretchSpacer();
|
||||||
|
bottom_sizer->Add(dlg_btns, 0, wxEXPAND);
|
||||||
|
v_sizer->Add(bottom_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
|
dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &FlowRateCalibrationDialog::on_start, this);
|
||||||
|
|
||||||
|
wxGetApp().UpdateDlgDarkUI(this);
|
||||||
|
|
||||||
|
Layout();
|
||||||
|
Fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowRateCalibrationDialog::~FlowRateCalibrationDialog() {
|
||||||
|
// Disconnect Events
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowRateCalibrationDialog::on_start(wxCommandEvent& event) {
|
||||||
|
int type = m_rbType->GetSelection();
|
||||||
|
int patternIdx = m_rbPattern->GetSelection();
|
||||||
|
|
||||||
|
InfillPattern pattern = ipArchimedeanChords;
|
||||||
|
if (patternIdx == 1) pattern = ipMonotonic;
|
||||||
|
|
||||||
|
bool is_linear = (type >= 2);
|
||||||
|
int pass = (type % 2) + 1;
|
||||||
|
|
||||||
|
m_plater->calib_flowrate(is_linear, pass, pattern);
|
||||||
|
EndModal(wxID_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowRateCalibrationDialog::on_dpi_changed(const wxRect& suggested_rect) {
|
||||||
|
this->Refresh();
|
||||||
|
Fit();
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
|||||||
@@ -180,5 +180,21 @@ protected:
|
|||||||
TextInput* m_tiJDEnd;
|
TextInput* m_tiJDEnd;
|
||||||
Plater* m_plater;
|
Plater* m_plater;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FlowRateCalibrationDialog : public DPIDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FlowRateCalibrationDialog(wxWindow* parent, wxWindowID id, Plater* plater);
|
||||||
|
~FlowRateCalibrationDialog();
|
||||||
|
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void on_start(wxCommandEvent& event);
|
||||||
|
|
||||||
|
RadioGroup* m_rbType;
|
||||||
|
// ORCA: use standard OrcaSlicer ComboBox instead of BitmapComboBox
|
||||||
|
ComboBox* m_rbPattern;
|
||||||
|
Plater* m_plater;
|
||||||
|
};
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user