diff --git a/resources/ui_layout/default/print.ui b/resources/ui_layout/default/print.ui index b07794e5d28..a919f86d471 100644 --- a/resources/ui_layout/default/print.ui +++ b/resources/ui_layout/default/print.ui @@ -408,22 +408,22 @@ group:Extrusion width line:perimeter setting:sidetext_width$10:label$width:perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:perimeter_extrusion_change_odd_layers end_line line:external perimeter setting:sidetext_width$10:label$width:external_perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$width&spacing combo:external_perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:external_perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:external_perimeter_extrusion_change_odd_layers end_line line:infill setting:sidetext_width$10:label$width:infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:infill_extrusion_change_odd_layers end_line line:solid infill setting:sidetext_width$10:label$width:solid_infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:solid_infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:solid_infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:solid_infill_extrusion_change_odd_layers end_line line:top infill setting:sidetext_width$10:label$width:top_infill_extrusion_width diff --git a/resources/ui_layout/example/print.ui b/resources/ui_layout/example/print.ui index 86badd553a9..5d90c54bdaf 100644 --- a/resources/ui_layout/example/print.ui +++ b/resources/ui_layout/example/print.ui @@ -393,22 +393,22 @@ group:Extrusion width line:perimeter setting:sidetext_width$10:label$width:perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:perimeter_extrusion_change_odd_layers end_line line:external perimeter setting:sidetext_width$10:label$width:external_perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$width&spacing combo:external_perimeter_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:external_perimeter_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:external_perimeter_extrusion_change_odd_layers end_line line:infill setting:sidetext_width$10:label$width:infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:infill_extrusion_change_odd_layers end_line line:solid infill setting:sidetext_width$10:label$width:solid_infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:solid_infill_extrusion_spacing - setting:sidetext_width$10:label_width$15:label$odd layers:solid_infill_extrusion_change_odd_layers + setting:sidetext_width$10:label_width$15:label$even layers:solid_infill_extrusion_change_odd_layers end_line line:top infill setting:sidetext_width$10:label$width:top_infill_extrusion_width diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index fd6774661a5..25ff8a77273 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -60,17 +60,45 @@ struct SurfaceFillParams : FillParams RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, connection); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust); - RETURN_COMPARE_NON_EQUAL(anchor_length); RETURN_COMPARE_NON_EQUAL(fill_exactly); + RETURN_COMPARE_NON_EQUAL(anchor_length); + RETURN_COMPARE_NON_EQUAL(fill_exactly); RETURN_COMPARE_NON_EQUAL(flow.width()); RETURN_COMPARE_NON_EQUAL(flow.height()); RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter()); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, flow.bridge()); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, role); RETURN_COMPARE_NON_EQUAL_TYPED(int32_t, priority); + assert(this->config != nullptr); + assert(rhs.config != nullptr); + if (config != nullptr && rhs.config != nullptr) { + RETURN_COMPARE_NON_EQUAL(config->infill_speed); + RETURN_COMPARE_NON_EQUAL(config->solid_infill_speed); + RETURN_COMPARE_NON_EQUAL(config->top_solid_infill_speed); + RETURN_COMPARE_NON_EQUAL(config->ironing_speed); + RETURN_COMPARE_NON_EQUAL(config->default_speed); + RETURN_COMPARE_NON_EQUAL(config->bridge_speed); + RETURN_COMPARE_NON_EQUAL(config->bridge_speed_internal); + RETURN_COMPARE_NON_EQUAL(config->gap_fill_speed); + } + assert(*this == rhs); return false; } bool operator==(const SurfaceFillParams &rhs) const { + // first check speed via config + if ((config != nullptr) != (rhs.config != nullptr)) + return false; + if(config != nullptr && ( + config->infill_speed != rhs.config->infill_speed + || config->solid_infill_speed != rhs.config->solid_infill_speed + || config->top_solid_infill_speed != rhs.config->top_solid_infill_speed + || config->ironing_speed != rhs.config->ironing_speed + || config->default_speed != rhs.config->default_speed + || config->bridge_speed != rhs.config->bridge_speed + || config->bridge_speed_internal != rhs.config->bridge_speed_internal + || config->gap_fill_speed != rhs.config->gap_fill_speed)) + return false; + // then check params return this->extruder == rhs.extruder && this->pattern == rhs.pattern && this->spacing == rhs.spacing && diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ce20991b3a2..c87f6233760 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1538,7 +1538,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene } } } - if (print.config().complete_objects.value) { + if (print.config().complete_objects.value || print.config().parallel_objects_step.value > 0) { // Order object instances for sequential print. if(print.config().complete_objects_sort.value == cosObject) print_object_instances_ordering = sort_object_instances_by_model_order(print); @@ -1848,24 +1848,7 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); this->set_origin(unscale((*print_object_instance_sequential_active)->shift)); if (finished_objects > 0) { - // Move to the origin position for the copy we're going to print. - // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. - m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer - m_avoid_crossing_perimeters.use_external_mp_once(); - set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id); - file.write(this->retract()); - std::string gcode; - //go to origin of the next object (it's 0,0 because we shifted the origin to it) - Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); - this->write_travel_to(gcode, polyline, "move to origin position for next object"); - file.write(gcode); - m_enable_cooling_markers = true; - // Disable motion planner when traveling to first object point. - m_avoid_crossing_perimeters.disable_once(); - // Ff we are printing the bottom layer of an object, and we have already finished - // another one, set first layer temperatures. This happens before the Z move - // is triggered, so machine has more time to reach such temperatures. - m_placeholder_parser.set("current_object_idx", int(finished_objects)); + _move_to_print_object(file, print, finished_objects, initial_extruder_id); std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id); // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); @@ -1894,57 +1877,50 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene } else { /////////////////////////////////////////////// begin parallel_objects_step if (print.config().parallel_objects_step > 0 && !has_wipe_tower) { - - float range = print.config().parallel_objects_step + EPSILON; - print_object_instances_ordering = sort_object_instances_by_model_order(print); - std::vector::const_iterator prev_object = print_object_instances_ordering.begin(); - - bool first_layer = true; - proceed_layers: + double range = std::min(print.config().parallel_objects_step, print.config().extruder_clearance_height) + EPSILON; + print_object_instances_ordering = chain_print_object_instances(print); + bool first_layers = true; for (coordf_t Rstart = 0, Rend = range;; Rstart += range, Rend += range) { + proceed_layers: bool is_layers = false; - print_object_instance_sequential_active = print_object_instances_ordering.begin(); - - for (size_t i = 0; i < print.objects().size(); ++i, ++print_object_instance_sequential_active) { - std::vector>> layers_to_print_range; - { - std::vector object_layers = collect_layers_to_print(*print.objects()[i], status_monitor); - int layer_num = 0; - for (LayerToPrint& ltp : object_layers) { - layer_num++; - if (!first_layer && layer_num == 1) - continue; - - if (ltp.print_z() >= Rstart && ltp.print_z() < Rend) { - std::pair> merged; - merged.first = ltp.print_z(); - merged.second.push_back(std::move(ltp)); - layers_to_print_range.emplace_back(merged); - if (first_layer) - break; - } - } + for (auto it_print_object_instance = print_object_instances_ordering.begin(); + it_print_object_instance != print_object_instances_ordering.end(); + ++it_print_object_instance) { + std::vector layers_to_print_range; + const PrintObject & object = *(*it_print_object_instance)->print_object; + std::vector object_layers = collect_layers_to_print(object, status_monitor); + + for (const LayerToPrint <p : object_layers) { + if (ltp.print_z() < Rstart || ltp.print_z() >= Rend) + continue; + + if (!first_layers && ltp.layer()->id() == 0) + continue; + + layers_to_print_range.push_back(ltp); + if (first_layers) + break; } - if (!layers_to_print_range.empty()) - { - if (print_object_instance_sequential_active != prev_object) { - this->set_origin(unscale((*print_object_instance_sequential_active)->shift)); - std::string gcode; - //go to origin of the next object (it's 0,0 because we shifted the origin to it) - Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); - this->write_travel_to(gcode, polyline, "move to origin position for next object"); - file.write(gcode); - } - this->process_layers(print, status_monitor, tool_ordering, print_object_instances_ordering, - layers_to_print_range, file); - prev_object = print_object_instance_sequential_active; + if (!layers_to_print_range.empty()) { + this->set_origin(unscale((*it_print_object_instance)->shift)); + + size_t finished_objects = 1 + (it_print_object_instance - + print_object_instances_ordering.begin()); + if (finished_objects > 1) + _move_to_print_object(file, print, finished_objects, initial_extruder_id); + + assert(!object.instances().empty()); + assert(*it_print_object_instance >= &*object.instances().begin() && + *it_print_object_instance <= &*(object.instances().end()-1)); + this->process_layers(print, status_monitor, tool_ordering, layers_to_print_range, + *it_print_object_instance - object.instances().data(), file); is_layers = true; } } - if (first_layer) { - first_layer = false; + if (first_layers) { + first_layers = false; goto proceed_layers; } if (!is_layers) { @@ -2107,6 +2083,28 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene print.throw_if_canceled(); } +void GCode::_move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id) +{ + // Move to the origin position for the copy we're going to print. + // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. + m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer + m_avoid_crossing_perimeters.use_external_mp_once(); + set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id); + file.write(this->retract()); + std::string gcode; + //go to origin of the next object (it's 0,0 because we shifted the origin to it) + Polyline polyline = this->travel_to(gcode, Point(0, 0), erTravel); + this->write_travel_to(gcode, polyline, "move to origin position for next object"); + file.write(gcode); + m_enable_cooling_markers = true; + // Disable motion planner when traveling to first object point. + m_avoid_crossing_perimeters.disable_once(); + // Ff we are printing the bottom layer of an object, and we have already finished + // another one, set first layer temperatures. This happens before the Z move + // is triggered, so machine has more time to reach such temperatures. + m_placeholder_parser.set("current_object_idx", int(finished_objects)); +} + // For unknown reasons and in sporadic cases when GCode export is processing, some participating thread // in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned. // So in this class method on_scheduler_entry is called for every thread before it starts participating diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 5a42e0bfe87..ee39812c0a9 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -245,7 +245,7 @@ class GCode : ExtrusionVisitorConst { GCode &m_gcodegen; }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); - + void _move_to_print_object(GCodeOutputStream& file, const Print& print, size_t finished_objects, uint16_t initial_extruder_id); void _init_multiextruders(const Print& print, GCodeOutputStream& file, GCodeWriter& writer, const ToolOrdering& tool_ordering, const std::string& custom_gcode); static std::vector collect_layers_to_print(const PrintObject &object, Print::StatusMonitor &status_monitor); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index d3f01c621f4..c8a903166b0 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -253,7 +253,7 @@ ProcessSurfaceResult PerimeterGenerator::process_arachne(int& loop_number, const // svg.draw(to_polylines(last), "brown"); // svg.Close(); //} - loop_number = 0; + loop_number--; } else { // Give up the outer shell because we don't have any meaningful top surface out_shell.clear(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 609366e7c21..65e10799ab9 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1524,11 +1524,11 @@ void PrintConfigDef::init_fff_params() def = this->add("external_perimeter_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("External perimeters"); - def->full_label = L("External perimeters spacing change on odd layers"); + def->full_label = L("External perimeters spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign for external and internal perimeters." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -1661,10 +1661,10 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(false)); def = this->add("extra_perimeters_odd_layers", coBool); - def->label = L("On odd layers"); - def->full_label = L("Extra perimeter on odd layers"); + def->label = L("On even layers"); + def->full_label = L("Extra perimeter on even layers"); def->category = OptionCategory::perimeter; - def->tooltip = L("Add one perimeter every odd layer. With this, infill is taken into the sandwich" + def->tooltip = L("Add one perimeter every even layer (and not on odd layers like the first one). With this, infill is taken into the sandwich" " and you may be able to reduce drastically the infill/perimeter overlap setting. "); def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionBool(false)); @@ -3149,11 +3149,11 @@ void PrintConfigDef::init_fff_params() def = this->add("infill_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Infill"); - def->full_label = L("Infill spacing change on odd layers"); + def->full_label = L("Infill spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -4001,10 +4001,11 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(75, true)); def = this->add("overhangs_reverse", coBool); - def->label = L("Reverse on odd"); + def->label = L("Reverse on even"); def->full_label = L("Overhang reversal"); def->category = OptionCategory::perimeter; - def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating pattern can drastically improve steep overhang." + def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction on even layers (and not on odd layers like the first one)." + " This alternating pattern can drastically improve steep overhang." "\n!! this is a very slow algorithm (it uses the same results as extra_perimeters_overhangs) !!"); def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionBool(false)); @@ -4142,11 +4143,11 @@ void PrintConfigDef::init_fff_params() def = this->add("perimeter_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Perimeters"); - def->full_label = L("Perimeters spacing change on odd layers"); + def->full_label = L("Perimeters spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign for external and internal perimeters." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); @@ -4968,11 +4969,11 @@ void PrintConfigDef::init_fff_params() def = this->add("solid_infill_extrusion_change_odd_layers", coFloatOrPercent); def->label = L("Infill"); - def->full_label = L("Solid infill spacing change on odd layers"); + def->full_label = L("Solid infill spacing change on even layers"); def->category = OptionCategory::width; - def->tooltip = L("Change width on every odd layer for better overlap with adjacent layers and getting stringer shells. " + def->tooltip = L("Change width on every even layer (and not on odd layers like the first one) for better overlap with adjacent layers and getting stringer shells. " "Try values about +/- 0.1 with different sign." - "\nThis could be combined with extra permeters on odd layers." + "\nThis could be combined with extra permeters on even layers." "\nWorks as absolute spacing or a % of the spacing." "\nset 0 to disable"); def->sidetext = L("mm or %"); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a6c7b580ed8..a234e67b69a 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2004,18 +2004,6 @@ std::vector Tab::create_pages(std::string setting_type_nam continue; } - if (setting_id == "compatible_printers") { - create_line_with_widget(current_group.get(), "compatible_printers", "", [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_printers); - }); - continue; - } else if (setting_id == "compatible_prints") { - create_line_with_widget(current_group.get(), "compatible_prints", "", [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_prints); - }); - continue; - } - int id = -1; for (int i = 1; i < params.size() - 1; i++) { if (boost::starts_with(params[i], "id$")) @@ -2024,6 +2012,18 @@ std::vector Tab::create_pages(std::string setting_type_nam id = idx_page; } + if (setting_id == "compatible_printers") { + create_line_with_widget(current_group.get(), "compatible_printers", "", [this, id](wxWindow* parent) { + return compatible_widget_create(parent, m_compatible_printers, id); + }); + continue; + } else if (setting_id == "compatible_prints") { + create_line_with_widget(current_group.get(), "compatible_prints", "", [this, id](wxWindow* parent) { + return compatible_widget_create(parent, m_compatible_prints, id); + }); + continue; + } + Option option = is_script ? Option(ConfigOptionDef{}, setting_id) : current_group->create_option_from_def(setting_id, id); @@ -4485,7 +4485,7 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin } // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. -wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps) +wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps, int setting_idx) { deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -4499,13 +4499,13 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL); - deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps](wxCommandEvent e) + deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps, setting_idx](wxCommandEvent e) { deps.btn->Enable(! deps.checkbox->GetValue()); // All printers have been made compatible with this preset. if (deps.checkbox->GetValue()) this->load_key_value(deps.key_list, std::vector {}); - this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); + this->get_field(deps.key_condition, setting_idx)->toggle(deps.checkbox->GetValue()); this->update_changed_ui(); }) ); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index c3bf7b6dc16..f601c01d59d 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -482,7 +482,7 @@ class Tab: public wxPanel static t_change set_or_add(t_change previous, t_change toadd); protected: void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget); - wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps); + wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps, int setting_idx); void compatible_widget_reload(PresetDependencies &deps); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false);