Merge branch 'lm_kill_binary_switch' into master_271

This commit is contained in:
Lukas Matena 2023-12-11 15:40:51 +01:00
commit 270d4dd08f
15 changed files with 170 additions and 128 deletions

View File

@ -141,6 +141,9 @@ void AppConfig::set_defaults()
if (get("auto_toolbar_size").empty()) if (get("auto_toolbar_size").empty())
set("auto_toolbar_size", "100"); set("auto_toolbar_size", "100");
if (get("use_binary_gcode_when_supported").empty())
set("use_binary_gcode_when_supported", "1");
if (get("notify_release").empty()) if (get("notify_release").empty())
set("notify_release", "all"); // or "none" or "release" set("notify_release", "all"); // or "none" or "release"
@ -686,25 +689,7 @@ bool AppConfig::update_skein_dir(const std::string &dir)
return false; // do not save "shapes gallery" directory return false; // do not save "shapes gallery" directory
return this->set("recent", "skein_directory", dir); return this->set("recent", "skein_directory", dir);
} }
/*
std::string AppConfig::get_last_output_dir(const std::string &alt) const
{
const auto it = m_storage.find("");
if (it != m_storage.end()) {
const auto it2 = it->second.find("last_output_path");
const auto it3 = it->second.find("remember_output_path");
if (it2 != it->second.end() && it3 != it->second.end() && ! it2->second.empty() && it3->second == "1")
return it2->second;
}
return alt;
}
void AppConfig::update_last_output_dir(const std::string &dir)
{
this->set("", "last_output_path", dir);
}
*/
std::string AppConfig::get_last_output_dir(const std::string& alt, const bool removable) const std::string AppConfig::get_last_output_dir(const std::string& alt, const bool removable) const
{ {
std::string s1 = (removable ? "last_output_path_removable" : "last_output_path"); std::string s1 = (removable ? "last_output_path_removable" : "last_output_path");

View File

@ -868,7 +868,7 @@ static inline GCode::SmoothPathCache smooth_path_interpolate_global(const Print&
void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb)
{ {
const bool export_to_binary_gcode = print.full_print_config().option<ConfigOptionBool>("gcode_binary")->value; const bool export_to_binary_gcode = print.full_print_config().option<ConfigOptionBool>("binary_gcode")->value;
// if exporting gcode in binary format: // if exporting gcode in binary format:
// we generate here the data to be passed to the post-processor, who is responsible to export them to file // we generate here the data to be passed to the post-processor, who is responsible to export them to file
// 1) generate the thumbnails // 1) generate the thumbnails

View File

@ -572,8 +572,8 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
{ {
m_parser.apply_config(config); m_parser.apply_config(config);
m_binarizer.set_enabled(config.gcode_binary); m_binarizer.set_enabled(config.binary_gcode);
m_result.is_binary_file = config.gcode_binary; m_result.is_binary_file = config.binary_gcode;
m_producer = EProducer::PrusaSlicer; m_producer = EProducer::PrusaSlicer;
m_flavor = config.gcode_flavor; m_flavor = config.gcode_flavor;

View File

@ -462,7 +462,7 @@ static std::vector<std::string> s_Preset_print_options {
"support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter", "support_tree_branch_diameter_angle", "support_tree_branch_diameter_double_wall", "support_tree_angle", "support_tree_angle_slow", "support_tree_branch_diameter", "support_tree_branch_diameter_angle", "support_tree_branch_diameter_double_wall",
"support_tree_top_rate", "support_tree_branch_distance", "support_tree_tip_diameter", "support_tree_top_rate", "support_tree_branch_distance", "support_tree_tip_diameter",
"dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius", "dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius",
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "gcode_substitutions", "gcode_binary", "perimeter_extruder", "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "gcode_substitutions", "perimeter_extruder",
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
"ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width",
"perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width",
@ -503,7 +503,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {
static std::vector<std::string> s_Preset_printer_options { static std::vector<std::string> s_Preset_printer_options {
"printer_technology", "autoemit_temperature_commands", "printer_technology", "autoemit_temperature_commands",
"bed_shape", "bed_custom_texture", "bed_custom_model", "z_offset", "gcode_flavor", "use_relative_e_distances", "bed_shape", "bed_custom_texture", "bed_custom_model", "binary_gcode", "z_offset", "gcode_flavor", "use_relative_e_distances",
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
//FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset. //FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset.
"host_type", "print_host", "printhost_apikey", "printhost_cafile", "host_type", "print_host", "printhost_apikey", "printhost_cafile",

View File

@ -86,6 +86,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"bed_temperature", "bed_temperature",
"before_layer_gcode", "before_layer_gcode",
"between_objects_gcode", "between_objects_gcode",
"binary_gcode",
"bridge_acceleration", "bridge_acceleration",
"bridge_fan_speed", "bridge_fan_speed",
"enable_dynamic_fan_speeds", "enable_dynamic_fan_speeds",
@ -139,7 +140,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"perimeter_acceleration", "perimeter_acceleration",
"post_process", "post_process",
"gcode_substitutions", "gcode_substitutions",
"gcode_binary",
"printer_notes", "printer_notes",
"travel_ramping_lift", "travel_ramping_lift",
"travel_initial_part_length", "travel_initial_part_length",
@ -1598,7 +1598,15 @@ std::string Print::output_filename(const std::string &filename_base) const
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders(); DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
config.set_key_value("num_extruders", new ConfigOptionInt((int)m_config.nozzle_diameter.size())); config.set_key_value("num_extruders", new ConfigOptionInt((int)m_config.nozzle_diameter.size()));
config.set_key_value("default_output_extension", new ConfigOptionString(".gcode")); config.set_key_value("default_output_extension", new ConfigOptionString(".gcode"));
return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
// Handle output_filename_format. There is a hack related to binary G-codes: gcode / bgcode substitution.
std::string output_filename_format = m_config.output_filename_format.value;
if (m_config.binary_gcode && boost::iends_with(output_filename_format, ".gcode"))
output_filename_format.insert(output_filename_format.end()-5, 'b');
if (! m_config.binary_gcode && boost::iends_with(output_filename_format, ".bgcode"))
output_filename_format.erase(output_filename_format.end()-6);
return this->PrintBase::output_filename(output_filename_format, ".gcode", filename_base, &config);
} }
const std::string PrintStatistics::FilamentUsedG = "filament used [g]"; const std::string PrintStatistics::FilamentUsedG = "filament used [g]";

View File

@ -1510,12 +1510,6 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionStrings()); def->set_default_value(new ConfigOptionStrings());
def = this->add("gcode_binary", coBool);
def->label = L("Export as binary G-code");
def->tooltip = L("Export G-code in binary format.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(0));
def = this->add("high_current_on_filament_swap", coBool); def = this->add("high_current_on_filament_swap", coBool);
def->label = L("High extruder current on filament swap"); def->label = L("High extruder current on filament swap");
def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange" def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange"
@ -1791,6 +1785,12 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true)); def->set_default_value(new ConfigOptionBool(true));
def = this->add("binary_gcode", coBool);
def->label = L("Supports binary G-code");
def->tooltip = L("The firmware supports binary G-code format (bgcode). This can be overridden in Preferences.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("machine_limits_usage", coEnum); def = this->add("machine_limits_usage", coEnum);
def->label = L("How to apply limits"); def->label = L("How to apply limits");
def->full_label = L("Purpose of Machine Limits"); def->full_label = L("Purpose of Machine Limits");
@ -4320,6 +4320,7 @@ static std::set<std::string> PrintConfigDef_ignore = {
"ensure_vertical_shell_thickness", "ensure_vertical_shell_thickness",
// Disabled in 2.6.0-alpha6, this option is problematic // Disabled in 2.6.0-alpha6, this option is problematic
"infill_only_where_needed", "infill_only_where_needed",
"gcode_binary" // Introduced in 2.7.0-alpha1, removed in 2.7.1 (replaced by binary_gcode).
}; };
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value) void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)

View File

@ -703,6 +703,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, autoemit_temperature_commands)) ((ConfigOptionBool, autoemit_temperature_commands))
((ConfigOptionString, before_layer_gcode)) ((ConfigOptionString, before_layer_gcode))
((ConfigOptionString, between_objects_gcode)) ((ConfigOptionString, between_objects_gcode))
((ConfigOptionBool, binary_gcode))
((ConfigOptionFloats, deretract_speed)) ((ConfigOptionFloats, deretract_speed))
((ConfigOptionString, end_gcode)) ((ConfigOptionString, end_gcode))
((ConfigOptionStrings, end_filament_gcode)) ((ConfigOptionStrings, end_filament_gcode))
@ -739,7 +740,6 @@ PRINT_CONFIG_CLASS_DEFINE(
// i - case insensitive // i - case insensitive
// w - whole word // w - whole word
((ConfigOptionStrings, gcode_substitutions)) ((ConfigOptionStrings, gcode_substitutions))
((ConfigOptionBool, gcode_binary))
((ConfigOptionString, layer_gcode)) ((ConfigOptionString, layer_gcode))
((ConfigOptionFloat, max_print_speed)) ((ConfigOptionFloat, max_print_speed))
((ConfigOptionFloat, max_volumetric_speed)) ((ConfigOptionFloat, max_volumetric_speed))

View File

@ -205,9 +205,11 @@ wxString Field::get_tooltip_text(const wxString& default_string)
opt_id += "]"; opt_id += "]";
} }
bool newline_after_name = boost::iends_with(opt_id, "_gcode") && opt_id != "binary_gcode";
return from_u8(m_opt.tooltip) + "\n" + _L("default value") + "\t: " + return from_u8(m_opt.tooltip) + "\n" + _L("default value") + "\t: " +
(boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string + (newline_after_name ? "\n" : "") + default_string +
(boost::iends_with(opt_id, "_gcode") ? "" : "\n") + (newline_after_name ? "" : "\n") +
_L("parameter name") + "\t: " + opt_id; _L("parameter name") + "\t: " + opt_id;
} }

View File

@ -2019,7 +2019,7 @@ void GLCanvas3D::render()
} }
#if ENABLE_BINARIZED_GCODE_DEBUG_WINDOW #if ENABLE_BINARIZED_GCODE_DEBUG_WINDOW
if (wxGetApp().plater()->is_view3D_shown() && current_printer_technology() != ptSLA && fff_print()->config().gcode_binary) if (wxGetApp().plater()->is_view3D_shown() && current_printer_technology() != ptSLA && fff_print()->config().binary_gcode)
show_binary_gcode_debug_window(); show_binary_gcode_debug_window();
#endif // ENABLE_BINARIZED_GCODE_DEBUG_WINDOW #endif // ENABLE_BINARIZED_GCODE_DEBUG_WINDOW

View File

@ -251,6 +251,16 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg, const std::funct
create(m_content, 84); create(m_content, 84);
} }
HtmlCapableRichMessageDialog::HtmlCapableRichMessageDialog(wxWindow *parent,
const wxString &msg,
const wxString &caption,
long style,
const std::function<void(const std::string &)> &on_link_clicked)
: RichMessageDialogBase(parent, HtmlContent{msg, false, true, on_link_clicked}, caption, style)
{}
// WarningDialog // WarningDialog
WarningDialog::WarningDialog(wxWindow *parent, WarningDialog::WarningDialog(wxWindow *parent,
@ -276,28 +286,40 @@ MessageDialog::MessageDialog(wxWindow* parent,
add_msg_content(this, content_sizer, HtmlContent{ get_wraped_wxString(message) }); add_msg_content(this, content_sizer, HtmlContent{ get_wraped_wxString(message) });
finalize(); finalize();
} }
#endif
// RichMessageDialog // RichMessageDialogBase
RichMessageDialog::RichMessageDialog(wxWindow* parent, RichMessageDialogBase::RichMessageDialogBase(wxWindow* parent,
const wxString& message, const wxString& message,
const wxString& caption/* = wxEmptyString*/, const wxString& caption/* = wxEmptyString*/,
long style/* = wxOK*/) long style/* = wxOK*/)
: RichMessageDialogBase(parent, HtmlContent{get_wraped_wxString(message)}, caption, style)
{}
RichMessageDialogBase::RichMessageDialogBase(wxWindow* parent, const HtmlContent& content, const wxString& caption, long style)
: MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, style) : MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, style)
{ {
add_msg_content(this, content_sizer, HtmlContent{ get_wraped_wxString(message) }); m_content = content; // We need a copy for the on_link_clicked lambda.
add_msg_content(this, content_sizer, m_content);
#ifdef _WIN32 // See comment in the header where m_checkBox is defined.
m_checkBox = new ::CheckBox(this, m_checkBoxText); m_checkBox = new ::CheckBox(this, m_checkBoxText);
#else
m_checkBox = new wxCheckBox(this, wxID_ANY, m_checkBoxText);
#endif
wxGetApp().UpdateDarkUI(m_checkBox); wxGetApp().UpdateDarkUI(m_checkBox);
m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); }); m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); });
btn_sizer->Insert(0, m_checkBox, wxALIGN_CENTER_VERTICAL); btn_sizer->Insert(0, m_checkBox, wxALIGN_CENTER_VERTICAL);
finalize(); finalize();
} }
int RichMessageDialog::ShowModal()
int RichMessageDialogBase::ShowModal()
{ {
if (m_checkBoxText.IsEmpty()) if (m_checkBoxText.IsEmpty())
m_checkBox->Hide(); m_checkBox->Hide();
@ -309,7 +331,7 @@ int RichMessageDialog::ShowModal()
return wxDialog::ShowModal(); return wxDialog::ShowModal();
} }
#endif
// InfoDialog // InfoDialog

View File

@ -106,58 +106,33 @@ public:
wxString get_wraped_wxString(const wxString& text_in, size_t line_len = 80); wxString get_wraped_wxString(const wxString& text_in, size_t line_len = 80);
#ifdef _WIN32
// Generic static line, used intead of wxStaticLine
class StaticLine: public wxTextCtrl
{
public:
StaticLine( wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxLI_HORIZONTAL,
const wxString& name = wxString::FromAscii(wxTextCtrlNameStr))
: wxTextCtrl(parent, id, wxEmptyString, pos, size!=wxDefaultSize ? size : (style == wxLI_HORIZONTAL ? wxSize(10, 1) : wxSize(1, 10)), wxSIMPLE_BORDER, wxDefaultValidator, name)
{
this->Enable(false);
}
~StaticLine() {}
};
// Generic message dialog, used intead of wxMessageDialog
class MessageDialog : public MsgDialog
{
public:
// NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxMessageDialog
MessageDialog( wxWindow *parent,
const wxString& message,
const wxString& caption = wxEmptyString,
long style = wxOK);
MessageDialog(MessageDialog&&) = delete;
MessageDialog(const MessageDialog&) = delete;
MessageDialog &operator=(MessageDialog&&) = delete;
MessageDialog &operator=(const MessageDialog&) = delete;
virtual ~MessageDialog() = default;
};
// Generic rich message dialog, used intead of wxRichMessageDialog // Generic rich message dialog, used intead of wxRichMessageDialog
class RichMessageDialog : public MsgDialog class RichMessageDialogBase : public MsgDialog
{ {
// Using CheckBox causes some weird sizer-related issues on Linux and macOS. To get around the problem before
// we find a better fix, we will fallback to wxCheckBox in this dialog. This makes little difference for most dialogs,
// We currently only use this class as a base for HtmlCapableRichMessageDialog on Linux and macOS. The normal
// RichMessageDialog is just an alias for wxRichMessageDialog on these platforms.
#ifdef _WIN32
CheckBox* m_checkBox{ nullptr }; CheckBox* m_checkBox{ nullptr };
#else
wxCheckBox* m_checkBox{ nullptr };
#endif
wxString m_checkBoxText; wxString m_checkBoxText;
bool m_checkBoxValue{ false }; bool m_checkBoxValue{ false };
public: public:
// NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxRichMessageDialog // NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxRichMessageDialog
RichMessageDialog( wxWindow *parent, RichMessageDialogBase(wxWindow* parent, const wxString& message, const wxString& caption = wxEmptyString, long style = wxOK);
const wxString& message, RichMessageDialogBase(wxWindow* parent, const HtmlContent& content, const wxString& caption = wxEmptyString, long style = wxOK);
const wxString& caption = wxEmptyString, RichMessageDialogBase(RichMessageDialogBase&&) = delete;
long style = wxOK); RichMessageDialogBase(const RichMessageDialogBase&) = delete;
RichMessageDialog(RichMessageDialog&&) = delete; RichMessageDialogBase &operator=(RichMessageDialogBase&&) = delete;
RichMessageDialog(const RichMessageDialog&) = delete; RichMessageDialogBase &operator=(const RichMessageDialogBase&) = delete;
RichMessageDialog &operator=(RichMessageDialog&&) = delete; virtual ~RichMessageDialogBase() = default;
RichMessageDialog &operator=(const RichMessageDialog&) = delete;
virtual ~RichMessageDialog() = default;
int ShowModal() override; int ShowModal() override;
@ -278,7 +253,47 @@ private:
m_ok, m_ok,
m_cancel, m_cancel,
m_help; m_help;
HtmlContent m_content;
}; };
#ifdef _WIN32
// Generic static line, used intead of wxStaticLine
class StaticLine: public wxTextCtrl
{
public:
StaticLine( wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxLI_HORIZONTAL,
const wxString& name = wxString::FromAscii(wxTextCtrlNameStr))
: wxTextCtrl(parent, id, wxEmptyString, pos, size!=wxDefaultSize ? size : (style == wxLI_HORIZONTAL ? wxSize(10, 1) : wxSize(1, 10)), wxSIMPLE_BORDER, wxDefaultValidator, name)
{
this->Enable(false);
}
~StaticLine() {}
};
// Generic message dialog, used intead of wxMessageDialog
class MessageDialog : public MsgDialog
{
public:
// NOTE! Don't change a signature of contsrucor. It have to be tha same as for wxMessageDialog
MessageDialog(wxWindow *parent,
const wxString& message,
const wxString& caption = wxEmptyString,
long style = wxOK);
MessageDialog(MessageDialog &&) = delete;
MessageDialog(const MessageDialog &) = delete;
MessageDialog &operator=(MessageDialog &&) = delete;
MessageDialog &operator=(const MessageDialog &) = delete;
virtual ~MessageDialog() = default;
};
using RichMessageDialog = RichMessageDialogBase;
#else #else
// just a wrapper for wxStaticLine to use the same code on all platforms // just a wrapper for wxStaticLine to use the same code on all platforms
class StaticLine : public wxStaticLine class StaticLine : public wxStaticLine
@ -320,6 +335,16 @@ public:
}; };
#endif #endif
class HtmlCapableRichMessageDialog : public RichMessageDialogBase
{
public:
HtmlCapableRichMessageDialog(wxWindow *parent, const wxString &msg, const wxString& caption, long style, const std::function<void(const std::string &)> &on_link_clicked);
~HtmlCapableRichMessageDialog() {}
private:
HtmlContent m_content;
};
// Generic info dialog, used for displaying exceptions // Generic info dialog, used for displaying exceptions
class InfoDialog : public MsgDialog class InfoDialog : public MsgDialog
{ {

View File

@ -3343,6 +3343,11 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// bitmap of enum UpdateBackgroundProcessReturnState // bitmap of enum UpdateBackgroundProcessReturnState
unsigned int return_state = 0; unsigned int return_state = 0;
// Get the config ready. The binary gcode flag depends on Preferences, which the backend has no access to.
DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config();
if (full_config.has("binary_gcode")) // needed for SLA
full_config.set("binary_gcode", bool(full_config.opt_bool("binary_gcode") & wxGetApp().app_config->get_bool("use_binary_gcode_when_supported")));
// If the update_background_process() was not called by the timer, kill the timer, // If the update_background_process() was not called by the timer, kill the timer,
// so the update_restart_background_process() will not be called again in vain. // so the update_restart_background_process() will not be called again in vain.
background_process_timer.Stop(); background_process_timer.Stop();
@ -3350,7 +3355,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
update_print_volume_state(); update_print_volume_state();
// Apply new config to the possibly running background task. // Apply new config to the possibly running background task.
bool was_running = background_process.running(); bool was_running = background_process.running();
Print::ApplyStatus invalidated = background_process.apply(q->model(), wxGetApp().preset_bundle->full_config()); Print::ApplyStatus invalidated = background_process.apply(q->model(), full_config);
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
if (view3D->is_layers_editing_enabled()) if (view3D->is_layers_editing_enabled())
@ -6690,14 +6695,14 @@ static wxString check_binary_vs_ascii_gcode_extension(PrinterTechnology pt, cons
if (binary_output && ascii_extension) { if (binary_output && ascii_extension) {
// TRN The placeholder %1% is the file extension the user has selected. // TRN The placeholder %1% is the file extension the user has selected.
err_out = format_wxstr(_L("Cannot save binary G-code with %1% extension.\n\n" err_out = format_wxstr(_L("Cannot save binary G-code with %1% extension.\n\n"
"Use <a href=%2%>a different extension</a> or disable <a href=%3%>binary G-code export</a> " "Use a different extension or disable <a href=%2%>binary G-code export</a> "
"in Print Settings."), ext, "output_filename_format;print", "gcode_binary;print"); "in Printer Settings."), ext, "binary_gcode;printer");
} }
if (!binary_output && binary_extension) { if (!binary_output && binary_extension) {
// TRN The placeholder %1% is the file extension the user has selected. // TRN The placeholder %1% is the file extension the user has selected.
err_out = format_wxstr(_L("Cannot save ASCII G-code with %1% extension.\n\n" err_out = format_wxstr(_L("Cannot save ASCII G-code with %1% extension.\n\n"
"Use <a href=%2%>a different extension</a> or enable <a href=%3%>binary G-code export</a> " "Use a different extension or enable <a href=%2%>binary G-code export</a> "
"in Print Settings."), ext, "output_filename_format;print", "gcode_binary;print"); "in Printer Settings."), ext, "binary_gcode;printer");
} }
} }
return err_out; return err_out;
@ -6721,9 +6726,14 @@ static void alert_when_exporting_binary_gcode(bool binary_output, const std::str
const std::string option_key = "dont_warn_about_firmware_version_when_exporting_binary_gcode"; const std::string option_key = "dont_warn_about_firmware_version_when_exporting_binary_gcode";
if (app_config->get(option_key) != "1") { if (app_config->get(option_key) != "1") {
RichMessageDialog dialog(parent, _L("You are exporting binary G-code for a Prusa printer. Please, make sure that your printer " const wxString url = "https://prusa.io/binary-gcode";
"is running firmware version 5.1.0-alpha2 or later. Older firmwares are not able to handle binary G-codes."), HtmlCapableRichMessageDialog dialog(parent,
_L("Exporting binary G-code"), wxICON_WARNING | wxOK); format_wxstr(_L("You are exporting binary G-code for a Prusa printer. Exporting binary G-code allows faster upload. "
"Ensure your printer runs firmware version 5.1.0 or later, as older versions do not support binary G-codes.\n\n"
"To learn more about binary G-code, visit <a href=%1%>%1%</a>."),
url),
_L("Warning"), wxOK,
[&url](const std::string&) { wxGetApp().open_browser_with_warning_dialog(url); });
dialog.ShowCheckBox(_L("Don't show again")); dialog.ShowCheckBox(_L("Don't show again"));
if (dialog.ShowModal() == wxID_OK && dialog.IsCheckBoxChecked()) if (dialog.ShowModal() == wxID_OK && dialog.IsCheckBoxChecked())
app_config->set(option_key, "1"); app_config->set(option_key, "1");
@ -6797,7 +6807,11 @@ void Plater::export_gcode(bool prefer_removable)
_L("The following characters are not allowed by a FAT file system:") + " <>:/\\|?*\""; _L("The following characters are not allowed by a FAT file system:") + " <>:/\\|?*\"";
return true; return true;
} }
err_out = check_binary_vs_ascii_gcode_extension(printer_technology(), ext, wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("gcode_binary")); if (this->printer_technology() == ptFFF) {
bool supports_binary = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_bool("binary_gcode");
bool uses_binary = wxGetApp().app_config->get_bool("use_binary_gcode_when_supported");
err_out = check_binary_vs_ascii_gcode_extension(printer_technology(), ext, supports_binary && uses_binary);
}
return !err_out.IsEmpty(); return !err_out.IsEmpty();
}; };
@ -6805,8 +6819,10 @@ void Plater::export_gcode(bool prefer_removable)
if (check_for_error(output_path, error_str)) { if (check_for_error(output_path, error_str)) {
ErrorDialog(this, error_str, [this](const std::string& key) -> void { sidebar().jump_to_option(key); }).ShowModal(); ErrorDialog(this, error_str, [this](const std::string& key) -> void { sidebar().jump_to_option(key); }).ShowModal();
output_path.clear(); output_path.clear();
} else { } else if (printer_technology() == ptFFF) {
alert_when_exporting_binary_gcode(wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("gcode_binary"), bool supports_binary = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_bool("binary_gcode");
bool uses_binary = wxGetApp().app_config->get_bool("use_binary_gcode_when_supported");
alert_when_exporting_binary_gcode(supports_binary && uses_binary,
wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_string("printer_notes")); wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_string("printer_notes"));
} }
} }
@ -7356,18 +7372,21 @@ void Plater::send_gcode()
PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage_paths, storage_names); PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage_paths, storage_names);
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
{ if (printer_technology() == ptFFF) {
const std::string ext = boost::algorithm::to_lower_copy(dlg.filename().extension().string()); const std::string ext = boost::algorithm::to_lower_copy(dlg.filename().extension().string());
const bool binary_output = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("gcode_binary"); const bool binary_output = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_bool("binary_gcode") &&
wxGetApp().app_config->get_bool("use_binary_gcode_when_supported");
const wxString error_str = check_binary_vs_ascii_gcode_extension(printer_technology(), ext, binary_output); const wxString error_str = check_binary_vs_ascii_gcode_extension(printer_technology(), ext, binary_output);
if (! error_str.IsEmpty()) { if (! error_str.IsEmpty()) {
ErrorDialog(this, error_str, t_kill_focus([](const std::string& key) -> void { wxGetApp().sidebar().jump_to_option(key); })).ShowModal(); ErrorDialog(this, error_str, t_kill_focus([](const std::string& key) -> void { wxGetApp().sidebar().jump_to_option(key); })).ShowModal();
return; return;
} }
}
alert_when_exporting_binary_gcode(wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("gcode_binary"), bool supports_binary = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_bool("binary_gcode");
wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_string("printer_notes")); bool uses_binary = wxGetApp().app_config->get_bool("use_binary_gcode_when_supported");
alert_when_exporting_binary_gcode(supports_binary && uses_binary,
wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_string("printer_notes"));
}
upload_job.upload_data.upload_path = dlg.filename(); upload_job.upload_data.upload_path = dlg.filename();
upload_job.upload_data.post_action = dlg.post_action(); upload_job.upload_data.post_action = dlg.post_action();

View File

@ -629,6 +629,11 @@ void PreferencesDialog::build()
}; };
append_bool_option(m_optgroup_other, "use_binary_gcode_when_supported", L("Use binary G-code when the printer supports it"),
L("When checked and the 'Supports binary G-code' option is checked in Printer Settings, "
"the G-code will be exported in binary format."),
app_config->get_bool("use_binary_gcode_when_supported"));
append_bool_option(m_optgroup_other, "suppress_hyperlinks", append_bool_option(m_optgroup_other, "suppress_hyperlinks",
L("Suppress to open hyperlink in browser"), L("Suppress to open hyperlink in browser"),
L("If enabled, PrusaSlicer will not open a hyperlinks in your browser."), L("If enabled, PrusaSlicer will not open a hyperlinks in your browser."),

View File

@ -1711,34 +1711,8 @@ void TabPrint::build()
Option option = optgroup->get_option("output_filename_format"); Option option = optgroup->get_option("output_filename_format");
option.opt.full_width = true; option.opt.full_width = true;
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup->append_single_option_line("gcode_binary");
optgroup->m_on_change = [this](const t_config_option_key& opt_key, boost::any value)
{
if (opt_key == "gcode_binary") {
const bool is_binary = m_config->opt_bool("gcode_binary");
std::string output_filename_format = m_config->opt_string("output_filename_format");
bool modified = false;
if (is_binary && boost::iends_with(output_filename_format, ".gcode")) {
output_filename_format = output_filename_format.substr(0, output_filename_format.length() - 5) + "bgcode";
modified = true;
}
else if (!is_binary && boost::iends_with(output_filename_format, ".bgcode")) {
output_filename_format = output_filename_format.substr(0, output_filename_format.length() - 6) + "gcode";
modified = true;
}
if (modified) {
DynamicPrintConfig new_conf = *m_config;
auto off_option = static_cast<ConfigOptionString*>(m_config->option("output_filename_format")->clone());
off_option->value = output_filename_format;
new_conf.set_key_value("output_filename_format", off_option);
load_config(new_conf);
}
}
update_dirty();
update();
};
optgroup = page->new_optgroup(L("Other")); optgroup = page->new_optgroup(L("Other"));
@ -2733,6 +2707,7 @@ void TabPrinter::build_fff()
optgroup->append_single_option_line("silent_mode"); optgroup->append_single_option_line("silent_mode");
optgroup->append_single_option_line("remaining_times"); optgroup->append_single_option_line("remaining_times");
optgroup->append_single_option_line("binary_gcode");
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) { optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
wxTheApp->CallAfter([this, opt_key, value]() { wxTheApp->CallAfter([this, opt_key, value]() {

View File

@ -62,7 +62,7 @@ use Slic3r::Test qw(_eq);
{ {
my $config = Slic3r::Config->new; my $config = Slic3r::Config->new;
$config->set('fill_density', 0); # just for making the test faster $config->set('fill_density', 0); # just for making the test faster
$config->set('gcode_binary', 0); $config->set('binary_gcode', 0);
my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2); my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2);
my @z = (); my @z = ();