Merge branch 'main' into dev/cut-keep-paint
This commit is contained in:
@@ -267,6 +267,21 @@ std::string GCodeWriter::set_jerk_xy(double jerk)
|
||||
jerk = m_max_jerk_y;
|
||||
|
||||
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
|
||||
|
||||
} else if (FLAVOR_IS(gcfRepetier)) {
|
||||
// Repetier uses M207 for temporary Jerk and combines X/Y into a single 'X' parameter.
|
||||
double jerk_xy = jerk;
|
||||
|
||||
// Clamp against the X machine limit
|
||||
if (m_max_jerk_x > 0 && jerk_xy > m_max_jerk_x)
|
||||
jerk_xy = m_max_jerk_x;
|
||||
|
||||
// Clamp against the Y machine limit as well to be safe
|
||||
if (m_max_jerk_y > 0 && jerk_xy > m_max_jerk_y)
|
||||
jerk_xy = m_max_jerk_y;
|
||||
|
||||
// Output the lowest safe limit using ONLY the X parameter
|
||||
gcode << "M207 X" << jerk_xy;
|
||||
} else {
|
||||
double jerk_x = jerk;
|
||||
double jerk_y = jerk;
|
||||
@@ -278,7 +293,7 @@ std::string GCodeWriter::set_jerk_xy(double jerk)
|
||||
|
||||
gcode << "M205 X" << jerk_x << " Y" << jerk_y;
|
||||
}
|
||||
|
||||
//the is_bbl check should be in the else statement above so that it doesn't inadverently added Z & E to klipper
|
||||
if (m_is_bbl_printers)
|
||||
gcode << std::setprecision(2) << " Z" << m_max_jerk_z << " E" << m_max_jerk_e;
|
||||
|
||||
@@ -365,6 +380,10 @@ std::string GCodeWriter::set_pressure_advance(double pa) const
|
||||
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
|
||||
else if(FLAVOR_IS(gcfRepRapFirmware))
|
||||
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
|
||||
else if (FLAVOR_IS(gcfRepetier))
|
||||
// Repetier M233: X is quadratic (K), Y is linear (L).
|
||||
// Applying the value to both parameters simultaneously.
|
||||
gcode << "M233 X" << std::setprecision(4) << pa << " Y" << std::setprecision(4) << pa << " ; Override pressure advance value\n";
|
||||
else
|
||||
gcode << "M900 K" <<std::setprecision(4)<< pa << "; Override pressure advance value\n";
|
||||
}
|
||||
|
||||
@@ -141,14 +141,14 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(AuthorizationType)
|
||||
|
||||
static t_config_enum_values s_keys_map_GCodeFlavor {
|
||||
{ "marlin", gcfMarlinLegacy },
|
||||
{ "reprap", gcfRepRapSprinter },
|
||||
{ "klipper", gcfKlipper },
|
||||
{ "reprapfirmware", gcfRepRapFirmware },
|
||||
{ "repetier", gcfRepetier },
|
||||
{ "marlin2", gcfMarlinFirmware },
|
||||
{ "reprap", gcfRepRapSprinter },
|
||||
{ "teacup", gcfTeacup },
|
||||
{ "makerware", gcfMakerWare },
|
||||
{ "marlin2", gcfMarlinFirmware },
|
||||
{ "sailfish", gcfSailfish },
|
||||
{ "klipper", gcfKlipper },
|
||||
{ "smoothie", gcfSmoothie },
|
||||
{ "mach3", gcfMach3 },
|
||||
{ "machinekit", gcfMachinekit },
|
||||
@@ -3706,10 +3706,11 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_values.push_back("marlin");
|
||||
def->enum_values.push_back("klipper");
|
||||
def->enum_values.push_back("reprapfirmware");
|
||||
//def->enum_values.push_back("repetier");
|
||||
def->enum_values.push_back("repetier");
|
||||
def->enum_values.push_back("marlin2");
|
||||
//def->enum_values.push_back("reprap");
|
||||
//def->enum_values.push_back("teacup");
|
||||
//def->enum_values.push_back("makerware");
|
||||
def->enum_values.push_back("marlin2");
|
||||
//def->enum_values.push_back("sailfish");
|
||||
//def->enum_values.push_back("mach3");
|
||||
//def->enum_values.push_back("machinekit");
|
||||
@@ -3718,11 +3719,11 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_labels.push_back("Marlin(legacy)");
|
||||
def->enum_labels.push_back(L("Klipper"));
|
||||
def->enum_labels.push_back("RepRapFirmware");
|
||||
def->enum_labels.push_back("Repetier");
|
||||
def->enum_labels.push_back("Marlin 2");
|
||||
//def->enum_labels.push_back("RepRap/Sprinter");
|
||||
//def->enum_labels.push_back("Repetier");
|
||||
//def->enum_labels.push_back("Teacup");
|
||||
//def->enum_labels.push_back("MakerWare (MakerBot)");
|
||||
def->enum_labels.push_back("Marlin 2");
|
||||
//def->enum_labels.push_back("Sailfish (MakerBot)");
|
||||
//def->enum_labels.push_back("Mach3/LinuxCNC");
|
||||
//def->enum_labels.push_back("Machinekit");
|
||||
|
||||
@@ -31,8 +31,19 @@
|
||||
namespace Slic3r {
|
||||
|
||||
enum GCodeFlavor : unsigned char {
|
||||
gcfMarlinLegacy, gcfKlipper, gcfRepRapFirmware, gcfMarlinFirmware, gcfRepRapSprinter, gcfRepetier, gcfTeacup, gcfMakerWare, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion
|
||||
gcfMarlinLegacy,
|
||||
gcfKlipper,
|
||||
gcfRepRapFirmware,
|
||||
gcfRepetier,
|
||||
gcfMarlinFirmware,
|
||||
gcfRepRapSprinter,
|
||||
gcfTeacup,
|
||||
gcfMakerWare,
|
||||
gcfSailfish,
|
||||
gcfMach3,
|
||||
gcfMachinekit,
|
||||
gcfSmoothie,
|
||||
gcfNoExtrusion
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1253,9 +1253,19 @@ PageFirmware::PageFirmware(ConfigWizard *parent)
|
||||
void PageFirmware::apply_custom_config(DynamicPrintConfig &config)
|
||||
{
|
||||
auto sel = gcode_picker->GetSelection();
|
||||
if (sel >= 0 && (size_t)sel < gcode_opt.enum_labels.size()) {
|
||||
auto *opt = new ConfigOptionEnum<GCodeFlavor>(static_cast<GCodeFlavor>(sel));
|
||||
config.set_key_value("gcode_flavor", opt);
|
||||
|
||||
// Safety check: ensure selection index is within bounds
|
||||
if (sel >= 0 && (size_t) sel < gcode_opt.enum_values.size()) {
|
||||
std::string selected_flavor_str = gcode_opt.enum_values[sel];
|
||||
// Ensure the default value exists to prevent null pointer crashes
|
||||
if (gcode_opt.default_value) {
|
||||
//Clone the fully initialized option (preserves the dictionary map)
|
||||
ConfigOption* opt = gcode_opt.default_value->clone();
|
||||
// Deserialize the string safely
|
||||
opt->deserialize(selected_flavor_str);
|
||||
// Save it to the printer configuration
|
||||
config.set_key_value("gcode_flavor", opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ static const std::unordered_map<std::string, std::vector<std::string>> printer_m
|
||||
{{"Anker", {"Anker M5", "Anker M5 All-Metal Hot End", "Anker M5C"}},
|
||||
{"Anycubic", {"Anycubic i3 Mega S", "Anycubic Chiron", "Anycubic Vyper", "Anycubic Kobra", "Anycubic Kobra Max",
|
||||
"Anycubic Kobra Plus", "Anycubic 4Max Pro", "Anycubic 4Max Pro 2", "Anycubic Kobra 2", "Anycubic Kobra 2 Plus",
|
||||
"Anycubic Kobra 2 Max", "Anycubic Kobra 2 Pro", "Anycubic Kobra 2 Neo", "Anycubic Kobra 3", "Anycubic Kobra S1", "Anycubic Predator", }},
|
||||
"Anycubic Kobra 2 Max", "Anycubic Kobra 2 Pro", "Anycubic Kobra 2 Neo", "Anycubic Kobra 3", "Anycubic Kobra 3 Max", "Anycubic Kobra S1", "Anycubic Predator", }},
|
||||
{"Artillery", {"Artillery Sidewinder X1", "Artillery Genius", "Artillery Genius Pro", "Artillery Sidewinder X2", "Artillery Hornet",
|
||||
"Artillery Sidewinder X3 Pro", "Artillery Sidewinder X3 Plus", "Artillery Sidewinder X4 Pro", "Artillery Sidewinder X4 Plus"}},
|
||||
{"Bambulab", {"Bambu Lab X1 Carbon", "Bambu Lab X1", "Bambu Lab X1E", "Bambu Lab P1P", "Bambu Lab P1S",
|
||||
|
||||
@@ -326,7 +326,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
// ImGui::SameLine();
|
||||
libvgcode::PathVertex vertex = viewer->get_current_vertex();
|
||||
size_t vertex_id = viewer->get_current_vertex_id();
|
||||
if (vertex.type == libvgcode::EMoveType::Seam) {
|
||||
if (view_type != libvgcode::EViewType::FeatureType && vertex.type == libvgcode::EMoveType::Seam) { // exclude FeatureType for proper type readings
|
||||
vertex_id = static_cast<size_t>(viewer->get_view_visible_range()[1]) - 1;
|
||||
vertex = viewer->get_vertex_at(vertex_id);
|
||||
}
|
||||
@@ -574,17 +574,26 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
ImGui::Dummy({0,0});
|
||||
|
||||
const bool is_extrusion = vertex.is_extrusion();
|
||||
char buf[1024]; char valBuf[32]; char spdBuf[128];
|
||||
char buf[1024] = ""; char valBuf[32]; char spdBuf[128];
|
||||
sprintf(spdBuf, "%s%.0f ", _u8L("Speed: ").c_str(), vertex.feedrate);
|
||||
const float speed_width = ImGui::CalcTextSize((_u8L("Speed: ") + "9999 ").c_str()).x;
|
||||
ImGuiWrapper::text(std::string(spdBuf)); // render Speed as differrent item to keep next item in same place
|
||||
switch (view_type) {
|
||||
case libvgcode::EViewType::FeatureType: {
|
||||
if (is_extrusion && !vertex.is_option()) // ORCA show more types on FeatureType
|
||||
sprintf(buf, "%s", to_string(vertex.role).c_str());
|
||||
else if(vertex.is_travel() || vertex.is_option() || vertex.is_wipe())
|
||||
sprintf(buf, "%s", to_string(vertex.type).c_str());
|
||||
else
|
||||
sprintf(buf, "%s", NA_CSTR);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::Height: {
|
||||
if (is_extrusion)
|
||||
sprintf(valBuf, "%.2f", vertex.height);
|
||||
else
|
||||
sprintf(valBuf, "%s", NA_CSTR);
|
||||
sprintf(buf, "%s %s%s", buf, _u8L("Height: ").c_str(), valBuf);
|
||||
sprintf(buf, "%s%s", _u8L("Height: ").c_str(), valBuf);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::Width: {
|
||||
@@ -592,7 +601,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
sprintf(valBuf, "%.2f", vertex.width);
|
||||
else
|
||||
sprintf(valBuf, "%s", NA_CSTR);
|
||||
sprintf(buf, "%s %s%s", buf, _u8L("Width: ").c_str(), valBuf);
|
||||
sprintf(buf, "%s%s", _u8L("Width: ").c_str(), valBuf);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::VolumetricFlowRate: {
|
||||
@@ -600,38 +609,42 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
sprintf(valBuf, "%.2f", vertex.volumetric_rate());
|
||||
else
|
||||
sprintf(valBuf, "%s", NA_CSTR);
|
||||
sprintf(buf, "%s %s%s", buf, _u8L("Flow: ").c_str(), valBuf);
|
||||
sprintf(buf, "%s%s", _u8L("Flow: ").c_str(), valBuf);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::FanSpeed: {
|
||||
sprintf(buf, "%s %s%.0f", buf, _u8L("Fan: ").c_str(), vertex.fan_speed);
|
||||
sprintf(buf, "%s%.0f", _u8L("Fan: ").c_str(), vertex.fan_speed);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::Temperature: {
|
||||
sprintf(buf, "%s %s%.0f", buf, _u8L("Temperature: ").c_str(), vertex.temperature);
|
||||
sprintf(buf, "%s%.0f", _u8L("Temperature: ").c_str(), vertex.temperature);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::LayerTimeLinear:
|
||||
case libvgcode::EViewType::LayerTimeLogarithmic: {
|
||||
sprintf(buf, "%s %s%.1f", buf, _u8L("Layer Time: ").c_str(), vertex.layer_duration);
|
||||
sprintf(buf, "%s%.1f", _u8L("Layer Time: ").c_str(), vertex.layer_duration);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::Tool: {
|
||||
sprintf(buf, "%s %s%d", buf, _u8L("Tool: ").c_str(), vertex.extruder_id + 1);
|
||||
sprintf(buf, "%s%d", _u8L("Tool: ").c_str(), vertex.extruder_id + 1);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::ColorPrint: {
|
||||
sprintf(buf, "%s %s%d", buf, _u8L("Color: ").c_str(), vertex.color_id + 1);
|
||||
sprintf(buf, "%s%d", _u8L("Color: ").c_str(), vertex.color_id + 1);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::ActualVolumetricFlowRate: {
|
||||
// Don't display the actual flow, since it only gives data for the end of a segment
|
||||
// sprintf(buf, "%s %s%.2f", buf, _u8L("Actual Flow: ").c_str(), vertex.actual_volumetric_rate());
|
||||
sprintf(buf, "%s %s", buf, " ");
|
||||
//if (is_extrusion)
|
||||
// sprintf(valBuf, "%.2f", vertex.actual_volumetric_rate());
|
||||
//else
|
||||
// sprintf(valBuf, "%s", NA_CSTR);
|
||||
//sprintf(buf, "%s%s", _u8L("Actual Flow: ").c_str(), valBuf);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::ActualSpeed: {
|
||||
sprintf(buf, "%s %s%.1f", buf, _u8L("Actual Speed: ").c_str(), vertex.actual_feedrate);
|
||||
// Don't display the actual flow, since it only gives data for the end of a segment
|
||||
//sprintf(buf, "%s%.1f", _u8L("Actual Speed: ").c_str(), vertex.actual_feedrate);
|
||||
break;
|
||||
}
|
||||
case libvgcode::EViewType::Acceleration: {
|
||||
@@ -644,19 +657,16 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode
|
||||
}
|
||||
// ORCA: Add Pressure Advance visualization support
|
||||
case libvgcode::EViewType::PressureAdvance: {
|
||||
sprintf(buf, "%s %s%.4f", buf, _u8L("PA: ").c_str(), vertex.pressure_advance);
|
||||
sprintf(buf, "%s%.4f", _u8L("PA: ").c_str(), vertex.pressure_advance);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::SameLine(speed_width);
|
||||
if (view_type == libvgcode::EViewType::FeatureType) {
|
||||
ImGuiWrapper::text(vertex.is_extrusion() ? to_string(vertex.role).c_str() : NA_CSTR);
|
||||
}
|
||||
else {
|
||||
|
||||
if (buf[0] != '\0') { // dont render if buffer empty
|
||||
ImGui::SameLine(speed_width);
|
||||
ImGuiWrapper::text(std::string(buf));
|
||||
}
|
||||
|
||||
|
||||
@@ -4851,7 +4851,7 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
|
||||
{
|
||||
size_t n_before_extruders = 2; // Count of pages before Extruder pages
|
||||
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
||||
bool is_marlin_flavor = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfKlipper || flavor == gcfRepRapFirmware);
|
||||
bool is_marlin_flavor = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfKlipper || flavor == gcfRepRapFirmware || flavor == gcfRepetier);
|
||||
|
||||
/* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages
|
||||
* and be cause of application crash, when try to change Preset in moment,
|
||||
|
||||
@@ -526,6 +526,11 @@ void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
||||
if (InstallNetplugin)
|
||||
GUI::wxGetApp().CallAfter([] { GUI::wxGetApp().ShowDownNetPluginDlg(); });
|
||||
}
|
||||
else if (strCmd == "user_guide_create_printer") {
|
||||
this->EndModal(wxID_CANCEL);
|
||||
this->Close();
|
||||
GUI::wxGetApp().CallAfter([this] {GUI::wxGetApp().sidebar().create_printer_preset();});
|
||||
}
|
||||
else if (strCmd == "user_guide_cancel") {
|
||||
this->EndModal(wxID_CANCEL);
|
||||
this->Close();
|
||||
|
||||
@@ -563,6 +563,34 @@ void DropDown::messureSize()
|
||||
subDropDown->text_off = text_off;
|
||||
subDropDown->use_content_width = true;
|
||||
subDropDown->Create(GetParent());
|
||||
#ifdef __WXGTK__
|
||||
// Orca: Keep the wx parent as the combobox so wxPopupTransientWindow installs
|
||||
// its capture handlers on the main dropdown, but make the native GTK
|
||||
// popup transient for the currently open popup to satisfy Wayland's
|
||||
// xdg-shell rule that a popup's parent must be the topmost mapped popup.
|
||||
gtk_window_set_transient_for(GTK_WINDOW(subDropDown->GetHandle()), GTK_WINDOW(GetHandle()));
|
||||
// Orca: On Wayland, while the sub holds an xdg_popup grab, motion events for
|
||||
// the cursor over main may not be delivered (Mutter drops motion
|
||||
// outside the grabbing surface). Poll on idle and synthesize a
|
||||
// mouseMove on main so its hover highlight tracks and it can dismiss
|
||||
// the sub when the cursor leaves the parent (group) item.
|
||||
DropDown* sub = subDropDown;
|
||||
sub->Bind(wxEVT_IDLE, [sub](wxIdleEvent& e) {
|
||||
e.Skip();
|
||||
if (!sub->IsShown() || !sub->mainDropDown->IsShown())
|
||||
return;
|
||||
wxPoint screen_pt = wxGetMousePosition();
|
||||
if (sub->GetScreenRect().Contains(screen_pt) || !sub->mainDropDown->GetScreenRect().Contains(screen_pt))
|
||||
return;
|
||||
wxPoint main_pt = sub->mainDropDown->ScreenToClient(screen_pt);
|
||||
wxMouseEvent ev(wxEVT_MOTION);
|
||||
ev.SetEventObject(sub->mainDropDown);
|
||||
ev.m_x = main_pt.x;
|
||||
ev.m_y = main_pt.y;
|
||||
sub->mainDropDown->mouseMove(ev);
|
||||
e.RequestMore();
|
||||
});
|
||||
#endif
|
||||
subDropDown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
||||
e.SetEventObject(this);
|
||||
e.SetId(GetId());
|
||||
@@ -759,6 +787,15 @@ void DropDown::Dismiss()
|
||||
PopupWindow::Dismiss();
|
||||
}
|
||||
|
||||
bool DropDown::ShouldDismissOnTopWindowDeactivate()
|
||||
{
|
||||
// On Wayland, mapping a chained xdg_popup with grab makes the parent
|
||||
// toplevel inactive, which would otherwise cascade-dismiss the whole
|
||||
// chain. Skip when our chain peer is shown.
|
||||
return !((mainDropDown && mainDropDown->IsShown()) ||
|
||||
(subDropDown && subDropDown->IsShown()));
|
||||
}
|
||||
|
||||
void DropDown::OnDismiss()
|
||||
{
|
||||
if (mainDropDown) {
|
||||
|
||||
@@ -110,6 +110,8 @@ protected:
|
||||
|
||||
void OnDismiss() override;
|
||||
|
||||
bool ShouldDismissOnTopWindowDeactivate() override;
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void paintNow();
|
||||
|
||||
@@ -86,7 +86,8 @@ void PopupWindow::OnMouseEvent2(wxMouseEvent &evt)
|
||||
void PopupWindow::topWindowActiavate(wxActivateEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
if (!event.GetActive() && IsShown()) DismissAndNotify();
|
||||
if (!event.GetActive() && IsShown() && ShouldDismissOnTopWindowDeactivate())
|
||||
DismissAndNotify();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@ public:
|
||||
#ifdef __WXMSW__
|
||||
void BindUnfocusEvent();
|
||||
#endif
|
||||
protected:
|
||||
// Orca: Hook so derived classes (e.g. DropDown chains) can skip auto-dismissal
|
||||
// when the toplevel deactivates as a side effect of their own popup grab
|
||||
// (notably on Wayland, where mapping a chained xdg_popup with grab makes
|
||||
// the parent toplevel briefly inactive).
|
||||
virtual bool ShouldDismissOnTopWindowDeactivate() { return true; }
|
||||
private:
|
||||
#ifdef __WXOSX__
|
||||
void OnMouseEvent2(wxMouseEvent &evt);
|
||||
|
||||
Reference in New Issue
Block a user