Merge branch 'main' into dev/cut-keep-paint

This commit is contained in:
Noisyfox
2026-05-11 17:22:21 +08:00
committed by GitHub
217 changed files with 24144 additions and 279 deletions

View File

@@ -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";
}

View File

@@ -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");

View File

@@ -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
};

View File

@@ -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);
}
}
}

View File

@@ -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",

View File

@@ -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));
}

View File

@@ -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,

View File

@@ -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();

View File

@@ -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) {

View File

@@ -110,6 +110,8 @@ protected:
void OnDismiss() override;
bool ShouldDismissOnTopWindowDeactivate() override;
private:
void paintEvent(wxPaintEvent& evt);
void paintNow();

View File

@@ -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

View File

@@ -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);