diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index b6929b839f..688b253f79 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -154,7 +154,10 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime // detect overhanging/bridging perimeters ExtrusionPaths paths; - if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > 0 + if ( ( (perimeter_generator.config->overhangs && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) + || (perimeter_generator.object_config->raft_overhangs + && perimeter_generator.object_config->raft_layers > 0 + && perimeter_generator.layer_id == perimeter_generator.object_config->raft_layers)) // RaftingEdition && !(perimeter_generator.object_config->support_material && perimeter_generator.object_config->support_material_contact_distance.value == 0)) { // get non-overhang paths by intersecting this loop with the grown lower slices extrusion_paths_append( diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index b7e966c9e7..9b98e87cb9 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -15,7 +15,7 @@ // !!! If you needed to translate some string, // !!! please use _L(string) // !!! _() - is a standard wxWidgets macro to translate -// !!! L() is used only for marking localizable string +// !!! L() is used only for marking localizable string // !!! It will be used in "xgettext" to create a Locating Message Catalog. #define L(s) s #endif /* L */ @@ -386,7 +386,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config) } else if (type == TYPE_FILAMENT || type == TYPE_SLA_MATERIAL) { const std::string §ion_name = (type == TYPE_FILAMENT) ? AppConfig::SECTION_FILAMENTS : AppConfig::SECTION_MATERIALS; if (app_config.has_section(section_name)) { - // Check whether this profile is marked as "installed" in PrusaSlicer.ini, + // Check whether this profile is marked as "installed" in PrusaSlicer.ini, // or whether a profile is marked as "installed", which this profile may have been renamed from. const std::map &installed = app_config.get_section(section_name); auto has = [&installed](const std::string &name) { @@ -403,12 +403,12 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config) const std::vector& Preset::print_options() { static std::vector s_opts { - "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", + "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness", "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", - "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", + "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", "max_print_speed", "max_volumetric_speed", "avoid_crossing_perimeters_max_detour", "fuzzy_skin_perimeter_mode", /* "fuzzy_skin_shape", */ "fuzzy_skin_thickness", "fuzzy_skin_point_dist", @@ -420,6 +420,7 @@ const std::vector& Preset::print_options() "bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", "min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "raft_overhangs", "raft_contact_distance", "raft_xy_size_compensation", "raft_size_adjust", "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", @@ -485,7 +486,7 @@ const std::vector& Preset::printer_options() "between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction", "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits", - "remaining_times", "silent_mode", + "remaining_times", "silent_mode", "machine_limits_usage", "thumbnails" }; s_opts.insert(s_opts.end(), Preset::machine_limits_options().begin(), Preset::machine_limits_options().end()); @@ -646,7 +647,7 @@ void PresetCollection::add_default_preset(const std::vector &keys, // Throws an exception on error. void PresetCollection::load_presets(const std::string &dir_path, const std::string &subdir) { - // Don't use boost::filesystem::canonical() on Windows, it is broken in regard to reparse points, + // Don't use boost::filesystem::canonical() on Windows, it is broken in regard to reparse points, // see https://github.com/prusa3d/PrusaSlicer/issues/732 boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred(); m_dir_path = dir.string(); @@ -970,7 +971,7 @@ const Preset* PresetCollection::get_selected_preset_parent() const // Resolve the "renamed_from" field. assert(! inherits.empty()); auto it = this->find_preset_renamed(inherits); - if (it != m_presets.end()) + if (it != m_presets.end()) preset = &(*it); } return (preset == nullptr/* || preset->is_default*/ || preset->is_external) ? nullptr : preset; @@ -985,17 +986,17 @@ const Preset* PresetCollection::get_preset_parent(const Preset& child) const const Preset* preset = this->find_preset(inherits, false); if (preset == nullptr) { auto it = this->find_preset_renamed(inherits); - if (it != m_presets.end()) + if (it != m_presets.end()) preset = &(*it); } - return + return // not found - (preset == nullptr/* || preset->is_default */|| + (preset == nullptr/* || preset->is_default */|| // this should not happen, user profile should not derive from an external profile preset->is_external || // this should not happen, however people are creative, see GH #4996 - preset == &child) ? - nullptr : + preset == &child) ? + nullptr : preset; } @@ -1022,7 +1023,7 @@ const std::string& PresetCollection::get_preset_name_by_alias(const std::string& // Continue over all profile names with the same alias. it != m_map_alias_to_profile_name.end() && it->first == alias; ++ it) if (auto it_preset = this->find_preset_internal(it->second); - it_preset != m_presets.end() && it_preset->name == it->second && + it_preset != m_presets.end() && it_preset->name == it->second && it_preset->is_visible && (it_preset->is_compatible || size_t(it_preset - m_presets.begin()) == m_idx_selected)) return it_preset->name; return alias; @@ -1092,7 +1093,7 @@ size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfil some_compatible |= preset_edited.is_compatible; if (active_print != nullptr) preset_edited.is_compatible &= is_compatible_with_print(this_preset_with_vendor_profile, *active_print, active_printer); - if (! preset_edited.is_compatible && selected && + if (! preset_edited.is_compatible && selected && (unselect_if_incompatible == PresetSelectCompatibleType::Always || (unselect_if_incompatible == PresetSelectCompatibleType::OnlyIfWasCompatible && was_compatible))) m_idx_selected = size_t(-1); if (selected) @@ -1433,13 +1434,13 @@ const std::set& PhysicalPrinter::get_preset_names() const return preset_names; } -bool PhysicalPrinter::has_empty_config() const +bool PhysicalPrinter::has_empty_config() const { - return config.opt_string("print_host" ).empty() && - config.opt_string("printhost_apikey" ).empty() && - config.opt_string("printhost_cafile" ).empty() && + return config.opt_string("print_host" ).empty() && + config.opt_string("printhost_apikey" ).empty() && + config.opt_string("printhost_cafile" ).empty() && config.opt_string("printhost_port" ).empty() && - config.opt_string("printhost_user" ).empty() && + config.opt_string("printhost_user" ).empty() && config.opt_string("printhost_password").empty(); } @@ -1451,7 +1452,7 @@ void PhysicalPrinter::update_preset_names_in_config() name += el + ";"; name.pop_back(); config.set_key_value("preset_name", new ConfigOptionString(name)); - } + } } void PhysicalPrinter::save(const std::string& file_name_from, const std::string& file_name_to) @@ -1500,7 +1501,7 @@ bool PhysicalPrinter::delete_preset(const std::string& preset_name) return preset_names.erase(preset_name) > 0; } -PhysicalPrinter::PhysicalPrinter(const std::string& name, const DynamicPrintConfig& default_config) : +PhysicalPrinter::PhysicalPrinter(const std::string& name, const DynamicPrintConfig& default_config) : name(name), config(default_config) { update_from_config(config); @@ -1557,7 +1558,7 @@ PhysicalPrinterCollection::PhysicalPrinterCollection( const std::vector PhysicalPrinterCollection::get_printers_with_preset(con for (auto printer : m_printers) { if (printer.preset_names.size() == 1) - continue; + continue; if (printer.preset_names.find(preset_name) != printer.preset_names.end()) printers.emplace_back(printer.name); } @@ -1887,7 +1888,7 @@ void PhysicalPrinterCollection::unselect_printer() bool PhysicalPrinterCollection::is_selected(PhysicalPrinterCollection::ConstIterator it, const std::string& preset_name) const { - return m_idx_selected == size_t(it - m_printers.begin()) && + return m_idx_selected == size_t(it - m_printers.begin()) && m_selected_preset == preset_name; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7aaacc4c74..6c0b648da9 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1809,6 +1809,48 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionInt(0)); + // RaftingEdition + def = this->add("raft_overhangs", coBool); + def->label = L("Bridge flow above raft"); + def->category = L("Support material"); + def->tooltip = L("Use bridge flow and speed for the bottom layer. Quality of the layer improves significantly when this setting is off, however it could be difficult to remove the object from raft. Ignored for soluble interface."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("raft_contact_distance", coFloat); + def->label = L("Raft contact Z distance"); + def->category = L("Support material"); + def->tooltip = L("The vertical distance between object and raft. Ignored for soluble interface."); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0.1)); + + def = this->add("raft_xy_size_compensation", coFloat); + def->label = L("Bottom layer expansion"); + def->category = L("Support material"); + def->tooltip = L("XY plane expansion of the bottom layer. This is useful to compensate shrinking, especially for higher contact Z distances and / or specific materials."); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0.0)); + + def = this->add("raft_size_adjust", coEnum); + def->label = L("Raft size"); + def->category = L("Support material"); + def->tooltip = L("Raft size adjustment. Can be used to improve adhesion or reduce material consumption / save some printing area."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("small"); + def->enum_values.push_back("normal"); + def->enum_values.push_back("large"); + def->enum_values.push_back("extralarge"); + def->enum_labels.push_back("Small"); + def->enum_labels.push_back("Normal"); + def->enum_labels.push_back("Large"); + def->enum_labels.push_back("Extra large"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(rsaNormal)); + def = this->add("resolution", coFloat); def->label = L("Resolution"); def->tooltip = L("Minimum detail resolution, used to simplify the input file for speeding up " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5189baab2d..3ae70facca 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -110,6 +110,13 @@ enum BrimType { btOuterAndInner, }; +enum RaftSizeAdjust { + rsaSmall, + rsaNormal, + rsaLarge, + rsaExtraLarge +}; + template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -282,6 +289,18 @@ template<> inline const t_config_enum_values& ConfigOptionEnum::get_en return keys_map; } +template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static const t_config_enum_values keys_map = { + { "small", rsaSmall }, + { "normal", rsaNormal }, + { "large", rsaLarge }, + { "extralarge", rsaExtraLarge } + }; + + return keys_map; +} + + // Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs. // Does not store the actual values, but defines default values. class PrintConfigDef : public ConfigDef @@ -512,6 +531,10 @@ public: ConfigOptionBool interface_shells; ConfigOptionFloat layer_height; ConfigOptionInt raft_layers; + ConfigOptionBool raft_overhangs; + ConfigOptionFloat raft_contact_distance; + ConfigOptionFloat raft_xy_size_compensation; + ConfigOptionEnum raft_size_adjust; ConfigOptionEnum seam_position; // ConfigOptionFloat seam_preferred_direction; // ConfigOptionFloat seam_preferred_direction_jitter; @@ -563,6 +586,10 @@ protected: OPT_PTR(interface_shells); OPT_PTR(layer_height); OPT_PTR(raft_layers); + OPT_PTR(raft_overhangs); + OPT_PTR(raft_contact_distance); + OPT_PTR(raft_xy_size_compensation); + OPT_PTR(raft_size_adjust); OPT_PTR(seam_position); OPT_PTR(slice_closing_radius); // OPT_PTR(seam_preferred_direction); @@ -1120,7 +1147,7 @@ public: // The percentage of smaller pillars compared to the normal pillar diameter // which are used in problematic areas where a normal pilla cannot fit. ConfigOptionPercent support_small_pillar_diameter_percent; - + // How much bridge (supporting another pinhead) can be placed on a pillar. ConfigOptionInt support_max_bridges_on_pillar; @@ -1172,7 +1199,7 @@ public: // The height of the pad from the bottom to the top not considering the pit ConfigOptionFloat pad_wall_height /*= 5*/; - + // How far should the pad extend around the contained geometry ConfigOptionFloat pad_brim_size; @@ -1196,7 +1223,7 @@ public: // Disable the elevation (ignore its value) and use the zero elevation mode ConfigOptionBool pad_around_object; - + ConfigOptionBool pad_around_object_everywhere; // This is the gap between the object bottom and the generated pad @@ -1210,7 +1237,7 @@ public: // How much should the tiny connectors penetrate into the model body ConfigOptionFloat pad_object_connector_penetration; - + // ///////////////////////////////////////////////////////////////////////// // Model hollowing parameters: // - Models can be hollowed out as part of the SLA print process @@ -1219,17 +1246,17 @@ public: // - Additional holes will be drilled into the hollow model to allow for // - resin removal. // ///////////////////////////////////////////////////////////////////////// - + ConfigOptionBool hollowing_enable; - - // The minimum thickness of the model walls to maintain. Note that the + + // The minimum thickness of the model walls to maintain. Note that the // resulting walls may be thicker due to smoothing out fine cavities where // resin could stuck. ConfigOptionFloat hollowing_min_thickness; - + // Indirectly controls the voxel size (resolution) used by openvdb ConfigOptionFloat hollowing_quality; - + // Indirectly controls the minimum size of created cavities. ConfigOptionFloat hollowing_closing_distance; @@ -1451,13 +1478,13 @@ Points get_bed_shape(const SLAPrinterConfig &cfg); // ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp. // Each change of ModelConfig is tracked by assigning a new timestamp from a global counter. // The counter is used for faster synchronization of the background slicing thread -// with the front end by skipping synchronization of equal config dictionaries. -// The global counter is also used for avoiding unnecessary serialization of config +// with the front end by skipping synchronization of equal config dictionaries. +// The global counter is also used for avoiding unnecessary serialization of config // dictionaries when taking an Undo snapshot. // // The global counter is NOT thread safe, therefore it is recommended to use ModelConfig from // the main thread only. -// +// // As there is a global counter and it is being increased with each change to any ModelConfig, // if two ModelConfig dictionaries differ, they should differ with their timestamp as well. // Therefore copying the ModelConfig including its timestamp is safe as there is no harm diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 233f693e3c..a747485888 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -535,6 +535,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector& range) { // If we have raft layers, consider bottom layer as a bridge just like any other bottom surface lying on the void. SurfaceType surface_type_bottom_1st = - (m_config.raft_layers.value > 0 && m_config.support_material_contact_distance.value > 0) ? + (m_config.raft_layers.value > 0 && m_config.support_material_contact_distance.value > 0 && + /* RaftingEdition */ m_config.raft_overhangs.value) ? stBottomBridge : stBottom; // If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating // the support from the print. @@ -1937,7 +1942,10 @@ end: BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin"; { // Compensation value, scaled. - const float xy_compensation_scaled = float(scale_(m_config.xy_size_compensation.value)); + const float _xy_compensation_scaled = float(scale_(m_config.xy_size_compensation.value)); + const float _xy_compensation_1st_scaled = _xy_compensation_scaled + (m_config.raft_layers > 0) ? + // Apply optional compensation / expand the first layer above the raft. (RaftingEdition) + float(scale_(m_config.raft_xy_size_compensation.value)) : 0.f; const float elephant_foot_compensation_scaled = (m_config.raft_layers == 0) ? // Only enable Elephant foot compensation if printing directly on the print bed. float(scale_(m_config.elefant_foot_compensation.value)) : @@ -1946,13 +1954,14 @@ end: ExPolygons lslices_1st_layer; tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), - [this, upscaled, clipped, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer] + [this, upscaled, clipped, _xy_compensation_scaled, _xy_compensation_1st_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer] (const tbb::blocked_range& range) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { m_print->throw_if_canceled(); Layer *layer = m_layers[layer_id]; // Apply size compensation and perform clipping of multi-part objects. float elfoot = (layer_id == 0) ? elephant_foot_compensation_scaled : 0.f; + float xy_compensation_scaled = (layer_id == 0) ? _xy_compensation_1st_scaled : _xy_compensation_scaled; // RaftingEdition if (layer->m_regions.size() == 1) { assert(! upscaled); assert(! clipped); diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 16068dde44..95fa4c9d08 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -110,8 +110,9 @@ SlicingParameters SlicingParameters::create_from_config( params.min_layer_height = std::min(params.min_layer_height, params.layer_height); params.max_layer_height = std::max(params.max_layer_height, params.layer_height); + // RaftingEdition: independent contact distance for raft, first object layer height not messed up if (! soluble_interface) { - params.gap_raft_object = object_config.support_material_contact_distance.value; + params.gap_raft_object = object_config.raft_contact_distance.value; params.gap_object_support = object_config.support_material_contact_distance.value; params.gap_support_object = object_config.support_material_contact_distance.value; } @@ -127,16 +128,18 @@ SlicingParameters SlicingParameters::create_from_config( #if 1 params.contact_raft_layer_height = std::max(params.layer_height, 0.75 * support_material_interface_extruder_dmr); if (! soluble_interface) { - // Compute the average of all nozzles used for printing the object over a raft. - //FIXME It is expected, that the 1st layer of the object is printed with a bridging flow over a full raft. Shall it not be vice versa? - coordf_t average_object_extruder_dmr = 0.; - if (! object_extruders.empty()) { - for (unsigned int extruder_id : object_extruders) - average_object_extruder_dmr += print_config.nozzle_diameter.get_at(extruder_id); - average_object_extruder_dmr /= coordf_t(object_extruders.size()); + if (object_config.raft_overhangs.value) { + // Compute the average of all nozzles used for printing the object over a raft. + //FIXME It is expected, that the 1st layer of the object is printed with a bridging flow over a full raft. Shall it not be vice versa? + coordf_t average_object_extruder_dmr = 0.; + if (! object_extruders.empty()) { + for (unsigned int extruder_id : object_extruders) + average_object_extruder_dmr += print_config.nozzle_diameter.get_at(extruder_id); + average_object_extruder_dmr /= coordf_t(object_extruders.size()); + } + params.first_object_layer_height = average_object_extruder_dmr; + params.first_object_layer_bridging = true; } - params.first_object_layer_height = average_object_extruder_dmr; - params.first_object_layer_bridging = true; } #else params.contact_raft_layer_height = soluble_interface ? support_material_interface_extruder_dmr : 0.75 * support_material_interface_extruder_dmr; @@ -150,13 +153,13 @@ SlicingParameters SlicingParameters::create_from_config( //FIXME The last raft layer is the contact layer, which shall be printed with a bridging flow for ease of separation. Currently it is not the case. if (params.raft_layers() == 1) { // There is only the contact layer. - params.contact_raft_layer_height = first_layer_height; - params.raft_contact_top_z = first_layer_height; + params.first_print_layer_height = params.contact_raft_layer_height; + params.raft_contact_top_z = params.contact_raft_layer_height; } else { assert(params.base_raft_layers > 0); assert(params.interface_raft_layers > 0); - // Number of the base raft layers is decreased by the first layer. - params.raft_base_top_z = first_layer_height + coordf_t(params.base_raft_layers - 1) * params.base_raft_layer_height; + params.first_print_layer_height = params.base_raft_layer_height; + params.raft_base_top_z = coordf_t(params.base_raft_layers) * params.base_raft_layer_height; // Number of the interface raft layers is decreased by the contact layer. params.raft_interface_top_z = params.raft_base_top_z + coordf_t(params.interface_raft_layers - 1) * params.interface_raft_layer_height; params.raft_contact_top_z = params.raft_interface_top_z + params.contact_raft_layer_height; diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 8f653b99d6..91a48a3e08 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -1040,8 +1040,17 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // we're here just to get the object footprint for the raft. // We only consider contours and discard holes to get a more continuous raft. overhang_polygons = collect_slices_outer(layer); - // Extend by SUPPORT_MATERIAL_MARGIN, which is 1.5mm - contact_polygons = offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN)); + // RaftingEdition + float adjust; + switch (m_object_config->raft_size_adjust.value) { + case rsaSmall: adjust = scale_(SUPPORT_MATERIAL_MARGIN / 2); break; + default: + case rsaNormal: adjust = scale_(SUPPORT_MATERIAL_MARGIN * 1); break; + case rsaLarge: adjust = scale_(SUPPORT_MATERIAL_MARGIN * 3); break; + case rsaExtraLarge: adjust = scale_(SUPPORT_MATERIAL_MARGIN * 4); break; + } + // Extend by a multiple of SUPPORT_MATERIAL_MARGIN, which is 1.5mm + contact_polygons = offset(overhang_polygons, adjust); } else { // Generate overhang / contact_polygons for non-raft layers. const Layer &lower_layer = *object.layers()[layer_id-1]; @@ -1841,7 +1850,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int assert(extr2z > extr1z || (extr1 != nullptr && extr2->layer_type == sltBottomContact)); if (std::abs(extr1z) < EPSILON) { // This layer interval starts with the 1st layer. Print the 1st layer using the prescribed 1st layer thickness. - assert(! m_slicing_params.has_raft()); + // assert(! m_slicing_params.has_raft()); RaftingEdition: unclear where the issue is: assert fails with 1-layer raft & base supports assert(intermediate_layers.empty() || intermediate_layers.back()->print_z <= m_slicing_params.first_print_layer_height); // At this point only layers above first_print_layer_heigth + EPSILON are expected as the other cases were captured earlier. assert(extr2z >= m_slicing_params.first_print_layer_height + EPSILON); @@ -2169,7 +2178,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf { // How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed. const float inflate_factor_fine = float(scale_((m_slicing_params.raft_layers() > 1) ? 0.5 : EPSILON)); - const float inflate_factor_1st_layer = float(scale_(3.)) - inflate_factor_fine; + const float inflate_factor_1st_layer = float(scale_((m_slicing_params.raft_layers() > 0 && + m_object_config->raft_size_adjust.value == rsaSmall) ? + 1.5 /* RaftingEdition */ : 3.)) - inflate_factor_fine; MyLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front(); MyLayer *interfaces = interface_layers.empty() ? nullptr : interface_layers.front(); MyLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front(); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 1f67f87929..c3ca156ed1 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -294,6 +294,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("support_material_extruder", have_support_material || have_skirt); toggle_field("support_material_speed", have_support_material || have_brim || have_skirt); + for (auto el : { "raft_xy_size_compensation", "raft_size_adjust" }) + toggle_field(el, have_raft); + for (auto el : { "raft_overhangs", "raft_contact_distance" }) + toggle_field(el, have_raft && !have_support_soluble); + bool has_ironing = config->opt_bool("ironing"); for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" }) toggle_field(el, has_ironing); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index be7d7c1c76..bbe565bb40 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -92,8 +92,8 @@ void Field::PostInitialize() { case coPercents: case coFloats: - case coStrings: - case coBools: + case coStrings: + case coBools: case coInts: { auto tag_pos = m_opt_id.find("#"); if (tag_pos != std::string::npos) @@ -111,7 +111,7 @@ void Field::PostInitialize() BUILD(); // For the mode, when settings are in non-modal dialog, neither dialog nor tabpanel doesn't receive wxEVT_KEY_UP event, when some field is selected. - // So, like a workaround check wxEVT_KEY_UP event for the Filed and switch between tabs if Ctrl+(1-4) was pressed + // So, like a workaround check wxEVT_KEY_UP event for the Filed and switch between tabs if Ctrl+(1-4) was pressed if (getWindow()) getWindow()->Bind(wxEVT_KEY_UP, [](wxKeyEvent& evt) { if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) { @@ -135,7 +135,7 @@ void Field::PostInitialize() // tab panel should be focused for correct navigation between tabs wxGetApp().tab_panel()->SetFocus(); } - + evt.Skip(); }); } @@ -148,7 +148,7 @@ int Field::def_width_thinner() { return 4; } void Field::on_kill_focus() { // call the registered function if it is available - if (m_on_kill_focus!=nullptr) + if (m_on_kill_focus!=nullptr) m_on_kill_focus(m_opt_id); } @@ -157,7 +157,7 @@ void Field::on_set_focus(wxEvent& event) // to allow the default behavior event.Skip(); // call the registered function if it is available - if (m_on_set_focus!=nullptr) + if (m_on_set_focus!=nullptr) m_on_set_focus(m_opt_id); } @@ -196,7 +196,7 @@ wxString Field::get_tooltip_text(const wxString& default_string) if (tooltip.length() > 0) tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " + (boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string + - (boost::iends_with(opt_id, "_gcode") ? "" : "\n") + + (boost::iends_with(opt_id, "_gcode") ? "" : "\n") + _(L("parameter name")) + "\t: " + opt_id; return tooltip_text; @@ -220,7 +220,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true case coPercents: case coFloats: case coFloat:{ - if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%') + if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%') str.RemoveLast(); else if (!str.IsEmpty() && str.Last() == '%') { @@ -332,7 +332,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "." } } - + m_value = std::string(str.ToUTF8().data()); break; } @@ -359,8 +359,8 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true out_of_range_val = true; break; } - } - } + } + } invalid_val = true; break; } @@ -413,7 +413,7 @@ void TextCtrl::BUILD() { if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - wxString text_value = wxString(""); + wxString text_value = wxString(""); switch (m_opt.type) { case coFloatOrPercent: @@ -428,21 +428,21 @@ void TextCtrl::BUILD() { text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); text_value += "%"; break; - } + } case coPercents: case coFloats: case coFloat: { double val = m_opt.type == coFloats ? m_opt.get_default_value()->get_at(m_opt_idx) : - m_opt.type == coFloat ? + m_opt.type == coFloat ? m_opt.default_value->getFloat() : m_opt.get_default_value()->get_at(m_opt_idx); text_value = double_to_string(val); m_last_meaningful_value = text_value; break; } - case coString: + case coString: text_value = m_opt.get_default_value()->value; break; case coStrings: @@ -456,7 +456,7 @@ void TextCtrl::BUILD() { text_value = get_thumbnails_string(m_opt.get_default_value()->values); break; default: - break; + break; } const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/; @@ -490,7 +490,7 @@ void TextCtrl::BUILD() { } temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId()); - + temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event) { //! to allow the default handling @@ -508,7 +508,7 @@ void TextCtrl::BUILD() { { e.Skip(); #ifdef __WXOSX__ - // OSX issue: For some unknown reason wxEVT_KILL_FOCUS is emitted twice in a row in some cases + // OSX issue: For some unknown reason wxEVT_KILL_FOCUS is emitted twice in a row in some cases // (like when information dialog is shown during an update of the option value) // Thus, suppress its second call if (bKilledFocus) @@ -539,7 +539,7 @@ void TextCtrl::BUILD() { */ // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); -} +} bool TextCtrl::value_was_changed() { @@ -559,7 +559,7 @@ bool TextCtrl::value_was_changed() case coPercents: case coFloats: case coFloat: { - if (m_opt.nullable && std::isnan(boost::any_cast(m_value)) && + if (m_opt.nullable && std::isnan(boost::any_cast(m_value)) && std::isnan(boost::any_cast(val))) return false; return boost::any_cast(m_value) != boost::any_cast(val); @@ -597,9 +597,9 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) if (!change_event) { wxString ret_str = static_cast(window)->GetValue(); - /* Update m_value to correct work of next value_was_changed(). - * But after checking of entered value, don't fix the "incorrect" value and don't show a warning message, - * just clear m_value in this case. + /* Update m_value to correct work of next value_was_changed(). + * But after checking of entered value, don't fix the "incorrect" value and don't show a warning message, + * just clear m_value in this case. */ get_value_by_opt_type(ret_str, false); } @@ -631,7 +631,7 @@ void TextCtrl::msw_rescale() Field::msw_rescale(); auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); - if (m_opt.height >= 0) + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); else if (parent_is_custom_ctrl && opt_height > 0) size.SetHeight(lround(opt_height*m_em_unit)); @@ -665,15 +665,15 @@ void CheckBox::BUILD() { if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - bool check_value = m_opt.type == coBool ? - m_opt.default_value->getBool() : m_opt.type == coBools ? - m_opt.get_default_value()->get_at(m_opt_idx) : + bool check_value = m_opt.type == coBool ? + m_opt.default_value->getBool() : m_opt.type == coBools ? + m_opt.get_default_value()->get_at(m_opt_idx) : false; m_last_meaningful_value = static_cast(check_value); - // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox - auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); + // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox + auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); temp->SetValue(check_value); @@ -684,7 +684,7 @@ void CheckBox::BUILD() { on_change_field(); }), temp->GetId()); - temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); + temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); @@ -770,14 +770,14 @@ void SpinCtrl::BUILD() { break; } - const int min_val = m_opt.min == INT_MIN + const int min_val = m_opt.min == INT_MIN #ifdef __WXOSX__ - // We will forcibly set the input value for SpinControl, since the value + // We will forcibly set the input value for SpinControl, since the value // inserted from the keyboard is not updated under OSX. // So, we can't set min control value bigger then 0. - // Otherwise, it couldn't be possible to input from keyboard value + // Otherwise, it couldn't be possible to input from keyboard value // less then min_val. - || m_opt.min > 0 + || m_opt.min > 0 #endif ? 0 : m_opt.min; const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; @@ -813,8 +813,8 @@ void SpinCtrl::BUILD() { propagate_value(); })); - temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { propagate_value(); }), temp->GetId()); - + temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { propagate_value(); }), temp->GetId()); + temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { e.Skip(); @@ -835,7 +835,7 @@ void SpinCtrl::BUILD() { tmp_value = parsed && value >= INT_MIN && value <= INT_MAX ? (int)value : UNDEF_VALUE; #ifdef __WXOSX__ - // Forcibly set the input value for SpinControl, since the value + // Forcibly set the input value for SpinControl, since the value // inserted from the keyboard or clipboard is not updated under OSX if (tmp_value != UNDEF_VALUE) { wxSpinCtrl* spin = static_cast(window); @@ -847,7 +847,7 @@ void SpinCtrl::BUILD() { } #endif }), temp->GetId()); - + temp->SetToolTip(get_tooltip_text(text_value)); // recast as a wxWindow to fit the calling convention @@ -899,7 +899,7 @@ void Choice::BUILD() { if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - choice_ctrl* temp; + choice_ctrl* temp; if (!m_opt.gui_type.empty() && m_opt.gui_type.compare("select_open") != 0) { m_is_editable = true; temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); @@ -1051,10 +1051,10 @@ void Choice::set_value(const std::string& value, bool change_event) //! Redunda } choice_ctrl* field = dynamic_cast(window); - idx == m_opt.enum_values.size() ? + idx == m_opt.enum_values.size() ? field->SetValue(value) : field->SetSelection(idx); - + m_disable_change_event = false; } @@ -1072,7 +1072,7 @@ void Choice::set_value(const boost::any& value, bool change_event) case coString: case coStrings: { wxString text_value; - if (m_opt.type == coInt) + if (m_opt.type == coInt) text_value = wxString::Format(_T("%i"), int(boost::any_cast(value))); else text_value = boost::any_cast(value); @@ -1100,7 +1100,7 @@ void Choice::set_value(const boost::any& value, bool change_event) { if (!m_opt.enum_values.empty()) { std::string key; - t_config_enum_values map_names = ConfigOptionEnum::get_enum_values(); + t_config_enum_values map_names = ConfigOptionEnum::get_enum_values(); for (auto it : map_names) { if (val == it.second) { key = it.first; @@ -1175,7 +1175,7 @@ boost::any& Choice::get_value() { choice_ctrl* field = dynamic_cast(window); - wxString ret_str = field->GetValue(); + wxString ret_str = field->GetValue(); // options from right panel std::vector right_panel_options{ "support", "pad", "scale_unit" }; @@ -1185,7 +1185,7 @@ boost::any& Choice::get_value() if (m_opt.type == coEnum) { - int ret_enum = field->GetSelection(); + int ret_enum = field->GetSelection(); if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "fill_pattern") { if (!m_opt.enum_values.empty()) { @@ -1222,6 +1222,9 @@ boost::any& Choice::get_value() m_value = static_cast(ret_enum); else if (m_opt_id == "brim_type") m_value = static_cast(ret_enum); + else if (m_opt_id == "raft_size_adjust") + m_value = static_cast(ret_enum); + } else if (m_opt.gui_type == "f_enum_open") { const int ret_enum = field->GetSelection(); @@ -1234,7 +1237,7 @@ boost::any& Choice::get_value() else m_value = atof(m_opt.enum_values[ret_enum].c_str()); } - else + else // modifies ret_string! get_value_by_opt_type(ret_str); @@ -1252,8 +1255,8 @@ void Choice::msw_rescale() #ifdef __WXOSX__ const wxString selection = field->GetValue();// field->GetString(index); - /* To correct scaling (set new controll size) of a wxBitmapCombobox - * we need to refill control with new bitmaps. So, in our case : + /* To correct scaling (set new controll size) of a wxBitmapCombobox + * we need to refill control with new bitmaps. So, in our case : * 1. clear control * 2. add content * 3. add scaled "empty" bitmap to the at least one item @@ -1261,7 +1264,7 @@ void Choice::msw_rescale() field->Clear(); wxSize size(wxDefaultSize); size.SetWidth((m_opt.width > 0 ? m_opt.width : def_width_wider()) * m_em_unit); - + // Set rescaled min height to correct layout field->SetMinSize(wxSize(-1, int(1.5f*field->GetFont().GetPixelSize().y + 0.5f))); // Set rescaled size @@ -1373,7 +1376,7 @@ void ColourPicker::msw_rescale() wxColourPickerCtrl* field = dynamic_cast(window); auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); - if (m_opt.height >= 0) + if (m_opt.height >= 0) size.SetHeight(m_opt.height * m_em_unit); else if (parent_is_custom_ctrl && opt_height > 0) size.SetHeight(lround(opt_height * m_em_unit)); @@ -1509,7 +1512,7 @@ boost::any& PointCtrl::get_value() else if (m_opt.min > x || x > m_opt.max || m_opt.min > y || y > m_opt.max) - { + { if (m_opt.min > x) x = m_opt.min; if (x > m_opt.max) x = m_opt.max; if (m_opt.min > y) y = m_opt.min; @@ -1575,7 +1578,7 @@ void SliderCtrl::BUILD() m_slider->SetBackgroundStyle(wxBG_STYLE_PAINT); wxSize field_size(40, -1); - m_textctrl = new wxTextCtrl(m_parent, wxID_ANY, wxString::Format("%d", m_slider->GetValue()/m_scale), + m_textctrl = new wxTextCtrl(m_parent, wxID_ANY, wxString::Format("%d", m_slider->GetValue()/m_scale), wxDefaultPosition, field_size); m_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font()); m_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT); @@ -1625,5 +1628,3 @@ boost::any& SliderCtrl::get_value() } // GUI } // Slic3r - - diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 3b44f20696..afd9fc7d80 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -36,7 +36,7 @@ void disable_screensaver() #if __APPLE__ CFStringRef reasonForActivity = CFSTR("Slic3r"); [[maybe_unused]]IOReturn success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, - kIOPMAssertionLevelOn, reasonForActivity, &assertionID); + kIOPMAssertionLevelOn, reasonForActivity, &assertionID); // ignore result: success == kIOReturnSuccess #elif _WIN32 SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS); @@ -71,7 +71,7 @@ void break_to_debugger() const std::string& shortkey_ctrl_prefix() { - static const std::string str = + static const std::string str = #ifdef __APPLE__ "⌘" #else @@ -83,7 +83,7 @@ const std::string& shortkey_ctrl_prefix() const std::string& shortkey_alt_prefix() { - static const std::string str = + static const std::string str = #ifdef __APPLE__ "⌥" #else @@ -132,13 +132,13 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt ConfigOptionFloats* vec_new = new ConfigOptionFloats{ boost::any_cast(value) }; config.option(opt_key)->set_at(vec_new, opt_index, opt_index); break; - } + } case coString: config.set_key_value(opt_key, new ConfigOptionString(boost::any_cast(value))); break; case coStrings:{ if (opt_key == "compatible_prints" || opt_key == "compatible_printers") { - config.option(opt_key)->values = + config.option(opt_key)->values = boost::any_cast>(value); } else if (config.def()->get(opt_key)->gui_flags.compare("serialized") == 0) { @@ -179,17 +179,17 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt if (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern") - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("ironing_type") == 0) - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("fuzzy_skin_perimeter_mode") == 0) - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); // else if (opt_key.compare("fuzzy_skin_shape") == 0) -// config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); +// config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("gcode_flavor") == 0) - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("machine_limits_usage") == 0) - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("support_material_pattern") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("seam_position") == 0) @@ -204,6 +204,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if(opt_key == "brim_type") config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key == "raft_size_adjust") + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); } break; case coPoints:{ diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index d077c81f60..f2dd4dcc2e 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -30,7 +30,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co m_fields.emplace(id, Choice::Create(this->ctrl_parent(), opt, id)); } else if (opt.gui_type == "color") { m_fields.emplace(id, ColourPicker::Create(this->ctrl_parent(), opt, id)); - } else if (opt.gui_type == "f_enum_open" || + } else if (opt.gui_type == "f_enum_open" || opt.gui_type == "i_enum_open" || opt.gui_type == "i_enum_closed") { m_fields.emplace(id, Choice::Create(this->ctrl_parent(), opt, id)); @@ -41,7 +41,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co m_fields.emplace(id, StaticText::Create(this->ctrl_parent(), opt, id)); } else if (opt.gui_type == "one_string") { m_fields.emplace(id, TextCtrl::Create(this->ctrl_parent(), opt, id)); - } else { + } else { switch (opt.type) { case coFloatOrPercent: case coFloat: @@ -74,19 +74,19 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co // Grab a reference to fields for convenience const t_field& field = m_fields[id]; field->m_on_change = [this](const std::string& opt_id, const boost::any& value) { - //! This function will be called from Field. + //! This function will be called from Field. //! Call OptionGroup._on_change(...) - if (!m_disabled) + if (!m_disabled) this->on_change_OG(opt_id, value); }; field->m_on_kill_focus = [this](const std::string& opt_id) { - //! This function will be called from Field. - if (!m_disabled) + //! This function will be called from Field. + if (!m_disabled) this->on_kill_focus(opt_id); }; field->m_on_set_focus = [this](const std::string& opt_id) { - //! This function will be called from Field. - if (!m_disabled) + //! This function will be called from Field. + if (!m_disabled) this->on_set_focus(opt_id); }; field->m_parent = parent(); @@ -99,7 +99,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co if (!this->m_disabled) this->back_to_sys_value(opt_id); }; - + // assign function objects for callbacks, etc. return field; } @@ -178,7 +178,7 @@ void OptionsGroup::append_line(const Line& line) return; auto option_set = line.get_options(); - for (auto opt : option_set) + for (auto opt : option_set) m_options.emplace(opt.opt_id, opt); // add mode value for current line to m_options_mode @@ -232,7 +232,7 @@ void OptionsGroup::activate_line(Line& line) // if we have a single option with no label, no sidetext just add it directly to sizer if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && option_set.front().opt.label.empty() && - option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && + option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { const auto& option = option_set.front(); @@ -334,7 +334,7 @@ void OptionsGroup::activate_line(Line& line) wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? _CTX(option.label, "Layers") : _(option.label); - label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, //wxDefaultSize); + label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, //wxDefaultSize); wxSize(sublabel_width != -1 ? sublabel_width * wxGetApp().em_unit() : -1, -1), wxALIGN_RIGHT); label->SetBackgroundStyle(wxBG_STYLE_PAINT); label->SetFont(wxGetApp().normal_font()); @@ -379,7 +379,7 @@ void OptionsGroup::activate_line(Line& line) } // add extra sizers if any - for (auto extra_widget : line.get_extra_widgets()) + for (auto extra_widget : line.get_extra_widgets()) { if (line.get_extra_widgets().size() == 1 && !staticbox) { @@ -504,7 +504,7 @@ void OptionsGroup::clear_fields_except_of(const std::vector left_fi while (it != m_fields.end()) { if (std::find(left_fields.begin(), left_fields.end(), it->first) == left_fields.end()) it = m_fields.erase(it); - else + else it++; } } @@ -530,7 +530,7 @@ Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index std::pair pair(opt_key, opt_index); m_opt_map.emplace(opt_id, pair); - if (m_use_custom_ctrl) // fill group and category values just for options from Settings Tab + if (m_use_custom_ctrl) // fill group and category values just for options from Settings Tab wxGetApp().sidebar().get_searcher().add_key(opt_id, title, this->config_category()); return Option(*m_config->def()->get(opt_key), opt_id); @@ -545,7 +545,7 @@ void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const b { OptionsGroup::on_change_OG(opt_id, value); return; - } + } auto itOption = it->second; const std::string &opt_key = itOption.first; @@ -554,7 +554,7 @@ void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const b this->change_opt_value(opt_key, value, opt_index == -1 ? 0 : opt_index); } - OptionsGroup::on_change_OG(opt_id, value); + OptionsGroup::on_change_OG(opt_id, value); } void ConfigOptionsGroup::back_to_initial_value(const std::string& opt_key) @@ -582,7 +582,7 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config, } else if (m_opt_map.find(opt_key) == m_opt_map.end() || // This option don't have corresponded field - opt_key == "bed_shape" || opt_key == "filament_ramming_parameters" || + opt_key == "bed_shape" || opt_key == "filament_ramming_parameters" || opt_key == "compatible_printers" || opt_key == "compatible_prints" ) { value = get_config_value(config, opt_key); this->change_opt_value(opt_key, value); @@ -765,7 +765,7 @@ boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index /*= -1*/) { size_t idx = opt_index == -1 ? 0 : opt_index; - + boost::any ret; wxString text_value = wxString(""); const ConfigOptionDef* opt = config.def()->get(opt_key); @@ -901,6 +901,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config } else if (opt_key == "brim_type") { ret = static_cast(config.option>(opt_key)->value); + } + else if (opt_key == "raft_size_adjust") { + ret = static_cast(config.option>(opt_key)->value); } } break; @@ -958,7 +961,7 @@ void ConfigOptionsGroup::change_opt_value(const t_config_option_key& opt_key, co m_modelconfig->touch(); } -ogStaticText::ogStaticText(wxWindow* parent, const wxString& text) : +ogStaticText::ogStaticText(wxWindow* parent, const wxString& text) : wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize) { if (!text.IsEmpty()) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9912e7aa01..cb9a92b59e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1941,7 +1941,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. "layer_height", "first_layer_height", "min_layer_height", "max_layer_height", "brim_width", "perimeters", "perimeter_extruder", "fill_density", "infill_extruder", "top_solid_layers", - "support_material", "support_material_extruder", "support_material_interface_extruder", "support_material_contact_distance", "raft_layers" + "support_material", "support_material_extruder", "support_material_interface_extruder", "support_material_contact_distance", "raft_layers", + "raft_overhangs", "raft_contact_distance", "raft_xy_size_compensation", "raft_size_adjust" })) , sidebar(new Sidebar(q)) , m_ui_jobs(this) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6f371d1752..c7aeacf337 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1500,7 +1500,11 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Raft")); optgroup->append_single_option_line("raft_layers", category_path + "raft-layers"); -// # optgroup->append_single_option_line(get_option_("raft_contact_distance"); + // RaftingEdition + optgroup->append_single_option_line("raft_overhangs"); + optgroup->append_single_option_line("raft_contact_distance"); + optgroup->append_single_option_line("raft_xy_size_compensation"); + optgroup->append_single_option_line("raft_size_adjust"); optgroup = page->new_optgroup(L("Options for support material and raft")); optgroup->append_single_option_line("support_material_contact_distance", category_path + "contact-z-distance");