From 6b81f43206b1a83b4bc8d6d830b31f7c9c477cc2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 18 Dec 2017 15:07:38 +0100 Subject: [PATCH] First implementation of the "compatible_printers_condition" for the print and filament profiles. Added documentation for building the boost library for Slic3r on Linux. --- doc/How_to_build_Slic3r.txt | 11 ++++++++++ lib/Slic3r/GUI/Tab.pm | 15 ++++++++++++-- xs/src/libslic3r/PrintConfig.cpp | 7 +++++++ xs/src/slic3r/GUI/Preset.cpp | 33 +++++++++++++++++++++--------- xs/src/slic3r/GUI/Preset.hpp | 6 +++--- xs/src/slic3r/GUI/PresetBundle.cpp | 6 ++++-- xs/xsp/GUI_Preset.xsp | 3 ++- 7 files changed, 63 insertions(+), 18 deletions(-) diff --git a/doc/How_to_build_Slic3r.txt b/doc/How_to_build_Slic3r.txt index 6c261d652..a1d112981 100644 --- a/doc/How_to_build_Slic3r.txt +++ b/doc/How_to_build_Slic3r.txt @@ -302,3 +302,14 @@ Debugging the C++ code works fine using the latest Eclipse for C++ and the gdb o It is yet a bit more complicated. The Strawberry MINGW is compiled for a different C++ exception passing model (SJLJ) than the other MINGWs, so one cannot simply combine MINGWs on Windows. For an unknown reason the nice debugger of the QT Creator hangs when debugging the C++ compiled by the Strawberry MINGW. Mabe it is because of the different exception passing models. And to disable optimization of the C/C++ code, one has to manually modify Config_heavy.pl in the Perl central installation. The SLIC3R_DEBUG environment variable did not override all the -O2 and -O3 flags that the perl build adds the gcc execution line. + +---------------------------------------------------------------------- + +Building boost. + +One may save compilation time by compiling just what Slic3r needs. +./bootstrap.sh --with-libraries=system,filesystem,thread,log,locale,regex +The -fPIC flag is required on Linux to make the static libraries rellocatable, +so they could be embedded into a shared library. +./bjam -a link=static variant=release threading=multi cxxflags=-fPIC cflags=-fPIC +To install on Linux to /usr/local/..., run the line above with the additional install keyword and with sudo. diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 223c06749..f7ea01a6f 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -150,6 +150,8 @@ sub save_preset { # Save the preset into Slic3r::data_dir/presets/section_name/preset_name.ini eval { $self->{presets}->save_current_preset($name); }; Slic3r::GUI::catch_error($self) and return; + # Mark the print & filament enabled if they are compatible with the currently selected preset. + wxTheApp->{preset_bundle}->update_compatible_with_printer(0); # Add the new item into the UI component, remove dirty flags and activate the saved item. $self->update_tab_ui; # Update the selection boxes at the platter. @@ -285,12 +287,12 @@ sub select_preset { my $new_printer_preset = $presets->find_preset($new_printer_name, 1); my $print_presets = wxTheApp->{preset_bundle}->print; my $print_preset_dirty = $print_presets->current_is_dirty; - my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); $canceled = $print_preset_dirty && ! $print_preset_compatible && ! $self->may_discard_current_dirty_preset($print_presets, $new_printer_name); my $filament_presets = wxTheApp->{preset_bundle}->filament; my $filament_preset_dirty = $filament_presets->current_is_dirty; - my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name); + my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_preset); if (! $canceled) { $canceled = $filament_preset_dirty && ! $filament_preset_compatible && ! $self->may_discard_current_dirty_preset($filament_presets, $new_printer_name); @@ -442,6 +444,7 @@ sub _load_key_value { $self->{config}->set($opt_key, $value); # Mark the print & filament enabled if they are compatible with the currently selected preset. if ($opt_key eq 'compatible_printers') { +# $opt_key eq 'compatible_printers_condition') { wxTheApp->{preset_bundle}->update_compatible_with_printer(0); } $self->{presets}->update_dirty_ui($self->{presets_choice}); @@ -838,6 +841,10 @@ sub build { widget => $self->_compatible_printers_widget, ); $optgroup->append_line($line); + + my $option = $optgroup->get_option('compatible_printers_condition'); + $option->full_width(1); + $optgroup->append_single_option_line($option); } } } @@ -1207,6 +1214,10 @@ sub build { widget => $self->_compatible_printers_widget, ); $optgroup->append_line($line); + + my $option = $optgroup->get_option('compatible_printers_condition'); + $option->full_width(1); + $optgroup->append_single_option_line($option); } } } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index f9edc9b2f..902914536 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -139,6 +139,13 @@ PrintConfigDef::PrintConfigDef() def->label = "Compatible printers"; def->default_value = new ConfigOptionStrings(); + def = this->add("compatible_printers_condition", coString); + def->label = "Compatible printers condition"; + def->tooltip = "A boolean expression using the configuration values of an active printer profile. " + "If this expression evaluates to true, this profile is considered compatible " + "with the active printer profile."; + def->default_value = new ConfigOptionString(); + def = this->add("complete_objects", coBool); def->label = "Complete individual objects"; def->tooltip = "When printing multiple objects or copies, this feature will complete " diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 5f4afc8d2..a132af133 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -21,6 +21,7 @@ #include "../../libslic3r/libslic3r.h" #include "../../libslic3r/Utils.hpp" +#include "../../libslic3r/PlaceholderParser.hpp" namespace Slic3r { @@ -141,16 +142,26 @@ std::string Preset::label() const return this->name + (this->is_dirty ? g_suffix_modified : ""); } -bool Preset::is_compatible_with_printer(const std::string &active_printer) const +bool Preset::is_compatible_with_printer(const Preset &active_printer) const { + auto *condition = dynamic_cast(this->config.option("compatible_printers_condition")); + if (condition != nullptr && ! condition->value.empty()) { + try { + return PlaceholderParser::evaluate_boolean_expression(condition->value, active_printer.config); + } catch (const std::runtime_error &err) { + //FIXME in case of an error, return "compatible with everything". + printf("Preset::is_compatible_with_printer - parsing error of compatible_printers_condition %s:\n%s\n", active_printer.name.c_str(), err.what()); + return true; + } + } auto *compatible_printers = dynamic_cast(this->config.option("compatible_printers")); - return this->is_default || active_printer.empty() || + return this->is_default || active_printer.name.empty() || compatible_printers == nullptr || compatible_printers->values.empty() || - std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer) != + std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != compatible_printers->values.end(); } -bool Preset::update_compatible_with_printer(const std::string &active_printer) +bool Preset::update_compatible_with_printer(const Preset &active_printer) { return this->is_compatible = is_compatible_with_printer(active_printer); } @@ -180,7 +191,7 @@ const std::vector& Preset::print_options() "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_per_color_wipe", - "compatible_printers" + "compatible_printers", "compatible_printers_condition" }; return s_opts; } @@ -193,7 +204,7 @@ const std::vector& Preset::filament_options() "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode", - "compatible_printers" + "compatible_printers", "compatible_printers_condition" }; return s_opts; } @@ -395,7 +406,7 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) } } -void PresetCollection::update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible) +void PresetCollection::update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible) { for (size_t idx_preset = 1; idx_preset < m_presets.size(); ++ idx_preset) { bool selected = idx_preset == m_idx_selected; @@ -490,9 +501,11 @@ std::vector PresetCollection::current_dirty_options() const // The "compatible_printers" option key is handled differently from the others: // It is not mandatory. If the key is missing, it means it is compatible with any printer. // If the key exists and it is empty, it means it is compatible with no printer. - const char compatible_printers[] = "compatible_printers"; - if (this->get_selected_preset().config.has(compatible_printers) != this->get_edited_preset().config.has(compatible_printers)) - changed.emplace_back(compatible_printers); + std::initializer_list optional_keys { "compatible_printers", "compatible_printers_condition" }; + for (auto &opt_key : optional_keys) { + if (this->get_selected_preset().config.has(opt_key) != this->get_edited_preset().config.has(opt_key)) + changed.emplace_back(opt_key); + } return changed; } diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index 196c13599..36bc0b335 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -79,9 +79,9 @@ public: void set_dirty(bool dirty = true) { this->is_dirty = dirty; } void reset_dirty() { this->is_dirty = false; } - bool is_compatible_with_printer(const std::string &active_printer) const; + bool is_compatible_with_printer(const Preset &active_printer) const; // Mark this preset as compatible if it is compatible with active_printer. - bool update_compatible_with_printer(const std::string &active_printer); + bool update_compatible_with_printer(const Preset &active_printer); // Resize the extruder specific fields, initialize them with the content of the 1st extruder. void set_num_extruders(unsigned int n) { set_num_extruders(this->config, n); } @@ -180,7 +180,7 @@ public: size_t size() const { return this->m_presets.size(); } // For Print / Filament presets, disable those, which are not compatible with the printer. - void update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible); + void update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible); size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 9fb0f21bf..4dc2e56ce 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -47,7 +47,9 @@ PresetBundle::PresetBundle() : this->printers.preset(0).config.opt_string("print_settings_id", true); // Create the "compatible printers" keys, as they are not part of the Static print config classes. this->filaments.preset(0).config.optptr("compatible_printers", true); + this->filaments.preset(0).config.optptr("compatible_printers_condition", true); this->prints.preset(0).config.optptr("compatible_printers", true); + this->prints.preset(0).config.optptr("compatible_printers_condition", true); this->prints .load_bitmap_default("cog.png"); this->filaments.load_bitmap_default("spool.png"); @@ -537,8 +539,8 @@ void PresetBundle::update_multi_material_filament_presets() void PresetBundle::update_compatible_with_printer(bool select_other_if_incompatible) { - this->prints.update_compatible_with_printer(this->printers.get_selected_preset().name, select_other_if_incompatible); - this->filaments.update_compatible_with_printer(this->printers.get_selected_preset().name, select_other_if_incompatible); + this->prints.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); + this->filaments.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); if (select_other_if_incompatible) { // Verify validity of the current filament presets. for (std::string &filament_name : this->filament_presets) { diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 675b06eaf..905ff4ecd 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -15,7 +15,8 @@ bool visible() %code%{ RETVAL = THIS->is_visible; %}; bool dirty() %code%{ RETVAL = THIS->is_dirty; %}; bool compatible() %code%{ RETVAL = THIS->is_compatible; %}; - bool is_compatible_with_printer(char *active_printer) const; + bool is_compatible_with_printer(Preset *active_printer) + %code%{ RETVAL = THIS->is_compatible_with_printer(*active_printer); %}; const char* name() %code%{ RETVAL = THIS->name.c_str(); %}; const char* file() %code%{ RETVAL = THIS->file.c_str(); %};