From 38a79b24a16b3c4e78e69d65b20d4971c2cf1ec3 Mon Sep 17 00:00:00 2001 From: Rad Date: Sun, 19 Apr 2026 21:34:15 +0200 Subject: [PATCH] fix manual remap, send nozzle diam --- src/libslic3r/PerimeterGenerator.cpp | 99 ---------------------------- src/slic3r/GUI/GUI_App.cpp | 32 +++++++++ src/slic3r/GUI/SSWCP.cpp | 16 +++++ 3 files changed, 48 insertions(+), 99 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index aa74e8c4bd..4e0ddd0f3f 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -30,75 +30,6 @@ namespace Slic3r { using namespace Slic3r::Feature::FuzzySkin; -static bool is_gap_fill_allowed_for_surface(const PrintObjectConfig* config, const SurfaceType surface_type) -{ - if (config == nullptr || config->gap_fill_target.value == gftNowhere) - return false; - - return surface_type != stInternalSolid || config->gap_fill_target.value == gftEverywhere; -} - -static void append_collapsed_infill_gap_fill(const ExPolygons &areas, - const Flow &flow, - const double simplify_resolution, - const float filter_out_gap_fill, - ExtrusionEntityCollection *gap_fill) -{ - if (gap_fill == nullptr || areas.empty()) - return; - - const double min = 0.2 * flow.scaled_spacing() * (1 - INSET_OVERLAP_TOLERANCE); - const double max = 2.0 * flow.scaled_spacing(); - ExPolygons gaps_ex = diff_ex( - opening_ex(areas, float(min / 2.0)), - offset2_ex(areas, -float(max / 2.0), float(max / 2.0 + ClipperSafetyOffset))); - if (gaps_ex.empty()) - gaps_ex = union_ex(areas); - - ThickPolylines polylines; - for (ExPolygon &ex : gaps_ex) { - ex.douglas_peucker(simplify_resolution); - try { - ex.medial_axis(min, max, &polylines); - } catch (...) { - } - } - - auto filter_short_polylines = [&](ThickPolylines &src) { - src.erase(std::remove_if(src.begin(), - src.end(), - [&](const ThickPolyline &p) { return p.length() < scale_(filter_out_gap_fill); }), - src.end()); - }; - - filter_short_polylines(polylines); - - if (polylines.empty()) { - for (const double inset_factor : {0.25, 0.125}) { - ExPolygons inset_loops = offset_ex(areas, -float(flow.scaled_width() * inset_factor)); - if (inset_loops.empty()) - continue; - - ThickPolylines inset_polylines = to_thick_polylines(to_polylines(std::move(inset_loops)), flow.scaled_width()); - filter_short_polylines(inset_polylines); - if (inset_polylines.empty()) - continue; - - ExtrusionEntityCollection gap_fill_entities; - variable_width(inset_polylines, erGapFill, flow, gap_fill_entities.entities); - gap_fill->append(std::move(gap_fill_entities.entities)); - return; - } - } - - if (polylines.empty()) - return; - - ExtrusionEntityCollection gap_fill_entities; - variable_width(polylines, erGapFill, flow, gap_fill_entities.entities); - gap_fill->append(std::move(gap_fill_entities.entities)); -} - // Hierarchy of perimeters. class PerimeterGeneratorLoop { public: @@ -1284,7 +1215,6 @@ void PerimeterGenerator::process_classic() ExPolygons gaps; ExPolygons top_fills; ExPolygons fill_clip; - ExPolygons collapsed_gap_fill_source; if (loop_number >= 0) { // In case no perimeters are to be generated, loop_number will equal to -1. std::vector contours(loop_number+1); // depth => loops @@ -1613,10 +1543,6 @@ void PerimeterGenerator::process_classic() } } } - collapsed_gap_fill_source = entities.empty() ? - ExPolygons() : - diff_ex(ExPolygons { surface.expolygon }, entities.polygons_covered_by_width(10.f)); - // append perimeters for this slice as a collection if (! entities.empty()) this->loops->append(entities); @@ -1714,17 +1640,6 @@ void PerimeterGenerator::process_classic() not_filled_exp, float(-inset - min_perimeter_infill_spacing / 2.), float(min_perimeter_infill_spacing / 2.)); - if (infill_exp.empty() && has_gap_fill && is_gap_fill_allowed_for_surface(object_config, surface.surface_type)) { - ExPolygons gap_fill_source = not_filled_exp.empty() ? collapsed_gap_fill_source : not_filled_exp; - if (gap_fill_source.empty()) - gap_fill_source = ExPolygons { surface.expolygon }; - append_collapsed_infill_gap_fill(gap_fill_source, - this->solid_infill_flow, - surface_simplify_resolution, - config->filter_out_gap_fill.value, - this->gap_fill); - } - // append infill areas to fill_surfaces //if any top_fills, grow them by ext_perimeter_spacing/2 to have the real un-anchored fill ExPolygons top_infill_exp = intersection_ex(fill_clip, offset_ex(top_fills, double(ext_perimeter_spacing / 2))); @@ -2541,7 +2456,6 @@ void PerimeterGenerator::process_arachne() steep_overhang_contour = true; steep_overhang_hole = true; } - ExPolygons collapsed_gap_fill_source; if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions, steep_overhang_contour, steep_overhang_hole); !extrusion_coll.empty()) { // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want if (wall_direction != WallDirection::CounterClockwise) { @@ -2549,7 +2463,6 @@ void PerimeterGenerator::process_arachne() // Reverse internal only if the wall direction is auto this->config->overhang_reverse_internal_only && wall_direction == WallDirection::Auto); } - collapsed_gap_fill_source = diff_ex(ExPolygons { surface.expolygon }, extrusion_coll.polygons_covered_by_width(10.f)); this->loops->append(extrusion_coll); } @@ -2589,18 +2502,6 @@ void PerimeterGenerator::process_arachne() not_filled_exp, float(-min_perimeter_infill_spacing / 2.), float(inset + min_perimeter_infill_spacing / 2.)); - if (infill_exp.empty() && this->config->gap_infill_speed.value > 0 && - is_gap_fill_allowed_for_surface(object_config, surface.surface_type)) { - ExPolygons gap_fill_source = not_filled_exp.empty() ? collapsed_gap_fill_source : not_filled_exp; - if (gap_fill_source.empty()) - gap_fill_source = ExPolygons { surface.expolygon }; - append_collapsed_infill_gap_fill(gap_fill_source, - this->solid_infill_flow, - surface_simplify_resolution, - config->filter_out_gap_fill.value, - this->gap_fill); - } - // append infill areas to fill_surfaces if (!top_expolygons.empty()) { infill_exp = union_ex(infill_exp, offset_ex(top_expolygons, double(top_inset))); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e4645aef08..caf0cb9510 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -6397,6 +6397,38 @@ void GUI_App::load_current_presets(bool active_preset_combox/*= false*/, bool ch if (tab->supports_printer_technology(printer_technology)) { tab->rebuild_page_tree(); } + + if (printer_technology == ptFFF && preset_bundle != nullptr) { + static const t_config_option_keys mixed_project_option_keys = { + "mixed_filament_gradient_mode", + "mixed_filament_height_lower_bound", + "mixed_filament_height_upper_bound", + "mixed_filament_advanced_dithering", + "mixed_filament_component_bias_enabled", + "mixed_filament_surface_indentation", + "mixed_filament_region_collapse", + "mixed_color_layer_height_a", + "mixed_color_layer_height_b", + "dithering_z_step_size", + "dithering_local_z_mode", + "dithering_step_painted_zones_only", + "mixed_filament_pointillism_pixel_size", + "mixed_filament_pointillism_line_gap", + "mixed_filament_definitions" + }; + + // Keep the Mixed Filaments sidebar state in sync when presets are reloaded + // programmatically (for example after New Project). These options are also + // mirrored on manual edits in Tab::on_value_change(), but that path does + // not run when the current preset is simply reloaded. + preset_bundle->project_config.apply_only( + preset_bundle->prints.get_edited_preset().config, + mixed_project_option_keys, + true); + + if (plater_ != nullptr) + sidebar().update_mixed_filament_panel(false); + } } static std::mutex mutex_delete_cache_presets; diff --git a/src/slic3r/GUI/SSWCP.cpp b/src/slic3r/GUI/SSWCP.cpp index f2c61c2ee3..b3a9e9fb0f 100644 --- a/src/slic3r/GUI/SSWCP.cpp +++ b/src/slic3r/GUI/SSWCP.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -3110,6 +3111,21 @@ void SSWCP_MachineOption_Instance::sw_GetFileFilamentMapping() } response["filament_type"] = filament_types; } + + // file nozzle diameters + if (full_config.has("nozzle_diameter")) { + const auto *opt_nozzle_diameters = full_config.option("nozzle_diameter"); + if (opt_nozzle_diameters != nullptr) { + std::vector nozzle_diameters; + nozzle_diameters.reserve(opt_nozzle_diameters->values.size()); + for (double diameter : opt_nozzle_diameters->values) { + std::ostringstream stream; + stream << std::fixed << std::setprecision(1) << diameter; + nozzle_diameters.emplace_back(stream.str()); + } + response["nozzle_diameters"] = nozzle_diameters; + } + } // filament used