diff --git a/resources/ui_layout/printer_fff.ui b/resources/ui_layout/printer_fff.ui index a31081912..4cba9879d 100644 --- a/resources/ui_layout/printer_fff.ui +++ b/resources/ui_layout/printer_fff.ui @@ -23,6 +23,7 @@ group:silent_mode_event:Firmware setting:max_gcode_per_second setting:min_length end_line + setting:gcode_filename_illegal_char group:Cooling fan line:Speedup setting:label$Speedup time:fan_speedup_time diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 0d1008c61..8a2cae080 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -725,8 +725,10 @@ const std::vector& Preset::printer_options() "fan_speedup_overhangs", "fan_speedup_time", "fan_percentage", - "gcode_flavor", + "gcode_filename_illegal_char", + "gcode_flavor", "gcode_precision_xyz", + "gcode_precision_e", "use_relative_e_distances", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "min_length", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 88d36d08a..01fbe16d5 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -122,6 +122,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorplaceholder_parser().process(format, 0, &cfg); - if (filename.extension().empty()) - filename = boost::filesystem::change_extension(filename, default_ext); - return filename.string(); + //remove unwanted characters + std::string forbidden_base; + if (const ConfigOptionString* opt = this->placeholder_parser().external_config()->option("gcode_filename_illegal_char")) { + forbidden_base = opt->value; + } + if (!forbidden_base.empty()) { + const std::string filename_init = filepath.stem().string(); + std::string filename = filename_init; + std::string extension = filepath.extension().string(); + //remove {print_time} and things like that that may be computed after, and re-put them inside it after the replace. + std::regex placehoder = std::regex("\\{[a-z_]+\\}"); + std::smatch matches; + std::string::const_iterator searchStart(filename_init.cbegin()); + while (std::regex_search(searchStart, filename_init.cend(), matches, placehoder)) { + for (int i = 0; i < matches.size(); i++) { + filename.replace(matches.position(i), matches.length(i), matches.length(i), '_'); + } + searchStart = matches.suffix().first; + } + //remove unwanted characters from the cleaned string + bool regexp_used = false; + if (forbidden_base.front() == '(' || forbidden_base.front() == '[') { + try { + filename = std::regex_replace(filename, std::regex(forbidden_base), "_"); + regexp_used = true; + }catch(std::exception){} + } + if (!regexp_used) { + for(int i=0; i< forbidden_base.size(); i++) + std::replace(filename.begin(), filename.end(), forbidden_base.at(i), '_'); + } + //re-put {print_time} and things like that + searchStart = (filename_init.cbegin()); + while (std::regex_search(searchStart, filename_init.cend(), matches, placehoder)) { + for (int i = 0; i < matches.size(); i++) { + filename.replace(matches.position(i), matches.length(i), matches.str()); + } + searchStart = matches.suffix().first; + } + // set the path var + filepath = filename + extension; + } + if (filepath.extension().empty()) + filepath = boost::filesystem::change_extension(filepath, default_ext); + return filepath.string(); } catch (std::runtime_error &err) { throw Slic3r::PlaceholderParserError(L("Failed processing of the output_filename_format template.") + "\n" + err.what()); } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 417af6dbf..bc9f569fa 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1963,6 +1963,15 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBool(0)); + def = this->add("gcode_filename_illegal_char", coString); + def->label = L("Illegal characters"); + def->full_label = L("Illegal characters for filename"); + def->category = OptionCategory::output; + def->tooltip = L("All characters that are written here will be replaced by '_' when writing the gcode file name." + "\nIf the first charater is '[' or '(', then this field will be considered as a regexp (enter '[^a-zA-Z0-9]' to only use ascii char)."); + def->mode = comExpert; + def->set_default_value(new ConfigOptionString("")); + def = this->add("gcode_flavor", coEnum); def->label = L("G-code flavor"); def->category = OptionCategory::general; @@ -1999,6 +2008,15 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(gcfSprinter)); + def = this->add("gcode_filename_illegal_char", coString); + def->label = L("Illegal characters"); + def->full_label = L("Illegal characters for filename"); + def->category = OptionCategory::output; + def->tooltip = L("All characters that are written here will be replaced by '_' when writing the gcode file name." + "\nIf the first charater is '[' or '(', then this field will be considered as a regexp (enter '[^a-zA-Z]' to only use ascii char)."); + def->mode = comExpert; + def->set_default_value(new ConfigOptionString("")); + def = this->add("gcode_label_objects", coBool); def->label = L("Label objects"); def->category = OptionCategory::output; @@ -5568,6 +5586,7 @@ std::unordered_set prusa_export_to_remove_keys = { "gap_fill_min_area", "gap_fill_overlap", "gap_fill", +"gcode_filename_illegal_char", "hole_size_compensation", "hole_size_threshold", "hole_to_polyhole_threshold", diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 25d002515..6b766b76d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1090,6 +1090,7 @@ public: ConfigOptionFloats filament_cooling_final_speed; ConfigOptionStrings filament_ramming_parameters; ConfigOptionBool gcode_comments; + ConfigOptionString gcode_filename_illegal_char; ConfigOptionEnum gcode_flavor; ConfigOptionBool gcode_label_objects; ConfigOptionInt gcode_precision_xyz; @@ -1204,6 +1205,7 @@ protected: OPT_PTR(filament_cooling_final_speed); OPT_PTR(filament_ramming_parameters); OPT_PTR(gcode_comments); + OPT_PTR(gcode_filename_illegal_char); OPT_PTR(gcode_flavor); OPT_PTR(gcode_label_objects); OPT_PTR(gcode_precision_xyz);