diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index cd58e90e974..2f3c37e3c1e 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "libslic3r.h" #include "Utils.hpp" @@ -52,78 +54,6 @@ using boost::property_tree::ptree; namespace Slic3r { -namespace { - -struct ParsedName { - PresetOrigin::Kind kind { PresetOrigin::Kind::User }; - std::string bundle_id; - std::string bare; -}; - -// Canonical names are built in-memory with '/' separators, so a straight prefix+split match is enough. -static ParsedName parse_preset_name(const std::string &raw_name) -{ - ParsedName out; - - auto try_prefix = [&](const char *dir, PresetOrigin::Kind kind) { - const std::string prefix = std::string(dir) + "/"; - if (! boost::starts_with(raw_name, prefix)) - return false; - const size_t id_start = prefix.size(); - const size_t id_end = raw_name.find('/', id_start); - if (id_end == std::string::npos || id_end == id_start) - return false; - out.kind = kind; - out.bundle_id = raw_name.substr(id_start, id_end - id_start); - out.bare = raw_name.substr(id_end + 1); - return true; - }; - - if (! try_prefix(PRESET_LOCAL_DIR, PresetOrigin::Kind::LocalBundle) && - ! try_prefix(PRESET_SUBSCRIBED_DIR, PresetOrigin::Kind::SubscribedBundle)) - out.bare = raw_name; - - return out; -} - -} // namespace - -std::string get_preset_canonical_name(const std::string &preset_bare_name, const PresetOrigin &origin) -{ - switch (origin.kind) { - case PresetOrigin::Kind::LocalBundle: - return origin.bundle_id.empty() ? preset_bare_name : std::string(PRESET_LOCAL_DIR) + "/" + origin.bundle_id + "/" + preset_bare_name; - case PresetOrigin::Kind::SubscribedBundle: - return origin.bundle_id.empty() ? preset_bare_name : std::string(PRESET_SUBSCRIBED_DIR) + "/" + origin.bundle_id + "/" + preset_bare_name; - default: - return preset_bare_name; - } -} - -std::string get_preset_bare_name(const std::string &canonical_name) -{ - const auto pos = canonical_name.find_last_of('/'); - return pos == std::string::npos ? canonical_name : canonical_name.substr(pos + 1); -} - -PresetOrigin detect_origin_from_path(const boost::filesystem::path &path, const PresetOrigin &explicit_origin) -{ - if (explicit_origin.kind != PresetOrigin::Kind::Auto) - return explicit_origin; - - for (auto it = path.begin(); it != path.end(); ++ it) { - const auto next = std::next(it); - if (next == path.end()) - break; - const std::string segment = it->string(); - if (segment == PRESET_LOCAL_DIR) - return PresetOrigin(PresetOrigin::Kind::LocalBundle, next->string()); - if (segment == PRESET_SUBSCRIBED_DIR) - return PresetOrigin(PresetOrigin::Kind::SubscribedBundle, next->string()); - } - return PresetOrigin(PresetOrigin::Kind::User); -} - //BBS: add a function to load the version from xxx.json Semver get_version_from_json(std::string file_path) { @@ -581,12 +511,20 @@ void Preset::load_info(const std::string& file) catch (...) { return; } + + //TODO: workaround for current info file convert, will remove it later + if (this->updated_time == 0) { + this->updated_time = (long long)Slic3r::Utils::get_current_time_utc(); + //this->sync_info = "update"; + BOOST_LOG_TRIVIAL(info) << boost::format("old info file, updated time to %1%") % this->updated_time; + save_info(); + } } void Preset::save_info(std::string file) { //BBS: add project embedded preset logic - if (this->is_project_embedded || this->is_from_bundle()) + if (this->is_project_embedded) return; if (file.empty()) { fs::path idx_file(this->file); @@ -608,26 +546,17 @@ void Preset::save_info(std::string file) c.close(); } -void Preset::remove_files(bool cloud_already_deleted) +void Preset::remove_files() { //BBS: add project embedded preset logic - if (this->is_project_embedded) { + if (this->is_project_embedded) return; - } // Erase the preset file. boost::nowide::remove(this->file.c_str()); fs::path idx_path(this->file); idx_path.replace_extension(".info"); - if (fs::exists(idx_path)) { - if (!this->setting_id.empty() && !cloud_already_deleted) { - // Cloud-synced preset - mark for deletion and keep .info file until sync confirms - this->sync_info = "delete"; - this->save_info(idx_path.string()); - } else { - // Local-only preset or cloud already confirmed deletion - safe to delete .info immediately - boost::nowide::remove(idx_path.string().c_str()); - } - } + if (fs::exists(idx_path)) + boost::nowide::remove(idx_path.string().c_str()); } //BBS: add logic for only difference save @@ -643,15 +572,12 @@ void Preset::save(DynamicPrintConfig* parent_config) from_str = std::string("User"); else if (this->is_project_embedded) from_str = std::string("Project"); - else if (this->is_from_bundle()) - from_str = std::string("Bundle"); else if (this->is_system) from_str = std::string("System"); else from_str = std::string("Default"); boost::filesystem::create_directories(fs::path(this->file).parent_path()); - const std::string bare_name = get_preset_bare_name(this->name); //BBS: only save difference if it has parent if (parent_config) { @@ -691,22 +617,24 @@ void Preset::save(DynamicPrintConfig* parent_config) opt_dst->set(opt_src); } } - temp_config.save_to_json(this->file, bare_name, from_str, this->version.to_string()); + + if (!filament_id.empty()) { + temp_config.set_key_value(BBL_JSON_KEY_FILAMENT_ID, new ConfigOptionString(filament_id)); + } + + temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string()); } else if (!filament_id.empty() && inherits().empty()) { DynamicPrintConfig temp_config = config; temp_config.set_key_value(BBL_JSON_KEY_FILAMENT_ID, new ConfigOptionString(filament_id)); - temp_config.save_to_json(this->file, bare_name, from_str, this->version.to_string()); + temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string()); } else { - this->config.save_to_json(this->file, bare_name, from_str, this->version.to_string()); + this->config.save_to_json(this->file, this->name, from_str, this->version.to_string()); } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " save config for: " << this->name << " and filament_id: " << filament_id << " and base_id: " << this->base_id; - // Bundle presets are synced via bundle_id and don't need individual .info files. - if (! this->is_from_bundle()) { - fs::path idx_file(this->file); - idx_file.replace_extension(".info"); - this->save_info(idx_file.string()); - } + fs::path idx_file(this->file); + idx_file.replace_extension(".info"); + this->save_info(idx_file.string()); } void Preset::reload(Preset const &parent) @@ -782,8 +710,7 @@ bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const Pre if (preset.vendor != nullptr && preset.preset.type == Preset::TYPE_FILAMENT) { const auto& excluded_printers = preset.preset.m_excluded_from; const auto excluded = preset.vendor->name == PresetBundle::ORCA_FILAMENT_LIBRARY && - (excluded_printers.find(active_printer.preset.name) != excluded_printers.end() || - excluded_printers.find(active_printer.preset.inherits()) != excluded_printers.end()); + excluded_printers.find(active_printer.preset.name) != excluded_printers.end(); if (excluded) return false; } @@ -967,300 +894,74 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle) return false; } -static std::vector s_Preset_print_options{ - "layer_height", - "initial_layer_print_height", - "wall_loops", - "alternate_extra_wall", - "slice_closing_radius", - "spiral_mode", - "spiral_mode_smooth", - "spiral_mode_max_xy_smoothing", - "spiral_starting_flow_ratio", - "spiral_finishing_flow_ratio", - "slicing_mode", - "top_shell_layers", - "top_shell_thickness", - "top_surface_density", - "bottom_surface_density", - "bottom_shell_layers", - "bottom_shell_thickness", - "extra_perimeters_on_overhangs", - "ensure_vertical_shell_thickness", - "reduce_crossing_wall", - "detect_thin_wall", - "detect_overhang_wall", - "overhang_reverse", - "overhang_reverse_threshold", - "overhang_reverse_internal_only", - "wall_direction", - "seam_position", - "staggered_inner_seams", - "wall_sequence", - "is_infill_first", - "sparse_infill_density", - "fill_multiline", - "gyroid_optimized", - "sparse_infill_pattern", - "lateral_lattice_angle_1", - "lateral_lattice_angle_2", - "infill_overhang_angle", - "top_surface_pattern", - "bottom_surface_pattern", - "infill_direction", - "solid_infill_direction", - "counterbore_hole_bridging", - "infill_shift_step", - "sparse_infill_rotate_template", - "solid_infill_rotate_template", - "symmetric_infill_y_axis", - "skeleton_infill_density", - "infill_lock_depth", - "skin_infill_depth", - "skin_infill_density", - "align_infill_direction_to_model", - "extra_solid_infills", - "minimum_sparse_infill_area", - "reduce_infill_retraction", - "internal_solid_infill_pattern", - "gap_fill_target", - "ironing_type", - "ironing_pattern", - "ironing_flow", - "ironing_speed", - "ironing_spacing", - "ironing_angle", - "ironing_angle_fixed", - "ironing_inset", - "support_ironing", - "support_ironing_pattern", - "support_ironing_flow", - "support_ironing_spacing", +static std::vector s_Preset_print_options { + "layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode", + "top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness", + "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction", + "seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern", + "infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density", + "align_infill_direction_to_model", "extra_solid_infills", + "minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target", + "ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_angle_fixed", "ironing_inset", + "support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing", "max_travel_detour_distance", - "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", "fuzzy_skin_ripples_per_layer", "fuzzy_skin_ripple_offset", "fuzzy_skin_layers_between_ripple_offset", + "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", "max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only", "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap", "support_interface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height","single_loop_draft_shield", "draft_shield", - "brim_width", "brim_object_gap", "brim_flow_ratio", "brim_use_efc_outline", "combine_brims", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers", + "brim_width", "brim_object_gap", "brim_use_efc_outline", "combine_brims", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style", // BBS - "print_extruder_id", - "print_extruder_variant", + "print_extruder_id", "print_extruder_variant", "independent_support_layer_height", - "support_angle", - "support_interface_top_layers", - "support_interface_bottom_layers", - "support_interface_pattern", - "support_interface_spacing", - "support_interface_loop_pattern", - "support_top_z_distance", - "support_on_build_plate_only", - "support_critical_regions_only", - "bridge_no_support", - "thick_bridges", - "thick_internal_bridges", - "dont_filter_internal_bridges", - "enable_extra_bridge_layer", - "max_bridge_length", - "print_sequence", - "print_order", - "support_remove_small_overhang", - "filename_format", - "wall_filament", - "support_bottom_z_distance", - "sparse_infill_filament", - "solid_infill_filament", - "support_filament", - "support_interface_filament", - "support_interface_not_for_body", - "ooze_prevention", - "standby_temperature_delta", - "preheat_time", - "preheat_steps", - "interface_shells", - "line_width", - "initial_layer_line_width", - "inner_wall_line_width", - "outer_wall_line_width", - "sparse_infill_line_width", - "internal_solid_infill_line_width", - "skin_infill_line_width", - "skeleton_infill_line_width", - "top_surface_line_width", - "support_line_width", - "infill_wall_overlap", - "top_bottom_infill_wall_overlap", - "bridge_flow", - "internal_bridge_flow", - "elefant_foot_compensation", - "elefant_foot_compensation_layers", - "elefant_foot_layers_density", - "xy_contour_compensation", - "xy_hole_compensation", - "resolution", - "enable_prime_tower", - "prime_tower_enable_framework", - "prime_tower_width", - "prime_tower_brim_width", - "prime_tower_skip_points", - "prime_volume", + "support_angle", "support_interface_top_layers", "support_interface_bottom_layers", + "support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern", + "support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges","enable_extra_bridge_layer", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang", + "filename_format", "wall_filament", "support_bottom_z_distance", + "sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body", + "ooze_prevention", "standby_temperature_delta", "preheat_time","preheat_steps", "interface_shells", "line_width", "initial_layer_line_width", "inner_wall_line_width", + "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width", + "skin_infill_line_width","skeleton_infill_line_width", + "top_surface_line_width", "support_line_width", "infill_wall_overlap","top_bottom_infill_wall_overlap", "bridge_flow", "internal_bridge_flow", + "elefant_foot_compensation", "elefant_foot_compensation_layers", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower", "prime_tower_enable_framework", + "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_volume", "prime_tower_infill_gap", "prime_tower_flat_ironing", "enable_tower_interface_features", "enable_tower_interface_cooldown_during_tower", - "wipe_tower_no_sparse_layers", - "compatible_printers", - "compatible_printers_condition", - "inherits", - "flush_into_infill", - "flush_into_objects", - "flush_into_support", - "tree_support_branch_angle", - "tree_support_angle_slow", - "tree_support_wall_count", - "tree_support_top_rate", - "tree_support_branch_distance", - "tree_support_tip_diameter", - "tree_support_branch_diameter", - "tree_support_branch_diameter_angle", - "detect_narrow_internal_solid_infill", - "gcode_add_line_number", - "enable_arc_fitting", - "precise_z_height", - "infill_combination", - "infill_combination_max_layer_height", /*"adaptive_layer_height",*/ - "support_bottom_interface_spacing", - "enable_overhang_speed", - "slowdown_for_curled_perimeters", - "overhang_1_4_speed", - "overhang_2_4_speed", - "overhang_3_4_speed", - "overhang_4_4_speed", - "initial_layer_infill_speed", - "only_one_wall_top", - "timelapse_type", - "wall_generator", - "wall_transition_length", - "wall_transition_filter_deviation", - "wall_transition_angle", - "wall_distribution_count", - "min_feature_size", - "min_bead_width", - "post_process", - "process_change_extrusion_role_gcode", - "min_length_factor", - "wall_maximum_resolution", - "wall_maximum_deviation", - "small_perimeter_speed", - "small_perimeter_threshold", - "bridge_angle", - "internal_bridge_angle", - "filter_out_gap_fill", - "travel_acceleration", - "inner_wall_acceleration", - "min_width_top_surface", - "default_jerk", - "outer_wall_jerk", - "inner_wall_jerk", - "infill_jerk", - "top_surface_jerk", - "initial_layer_jerk", - "travel_jerk", - "default_junction_deviation", - "top_solid_infill_flow_ratio", - "bottom_solid_infill_flow_ratio", - "only_one_wall_first_layer", - "print_flow_ratio", - "seam_gap", - "set_other_flow_ratios", - "first_layer_flow_ratio", - "outer_wall_flow_ratio", - "inner_wall_flow_ratio", - "overhang_flow_ratio", - "sparse_infill_flow_ratio", - "internal_solid_infill_flow_ratio", - "gap_fill_flow_ratio", - "support_flow_ratio", - "support_interface_flow_ratio", - "role_based_wipe_speed", - "wipe_speed", - "accel_to_decel_enable", - "accel_to_decel_factor", - "wipe_on_loops", - "wipe_before_external_loop", - "bridge_density", - "internal_bridge_density", - "precise_outer_wall", - "bridge_acceleration", - "sparse_infill_acceleration", - "internal_solid_infill_acceleration", - "tree_support_auto_brim", - "tree_support_brim_width", - "gcode_comments", - "gcode_label_objects", - "initial_layer_travel_speed", - "initial_layer_travel_acceleration", - "initial_layer_travel_jerk", - "exclude_object", - "slow_down_layers", - "infill_anchor", - "infill_anchor_max", - "initial_layer_min_bead_width", - "make_overhang_printable", - "make_overhang_printable_angle", - "make_overhang_printable_hole_size", - "notes", - "wipe_tower_cone_angle", - "wipe_tower_extra_spacing", - "wipe_tower_max_purge_speed", - "wipe_tower_wall_type", - "wipe_tower_extra_rib_length", - "wipe_tower_rib_width", - "wipe_tower_fillet_wall", - "wipe_tower_filament", - "wiping_volumes_extruders", - "wipe_tower_bridging", - "wipe_tower_extra_flow", - "single_extruder_multi_material_priming", - "wipe_tower_rotation_angle", - "tree_support_branch_distance_organic", - "tree_support_branch_diameter_organic", - "tree_support_branch_angle_organic", - "hole_to_polyhole", - "hole_to_polyhole_threshold", - "hole_to_polyhole_twisted", - "mmu_segmented_region_max_width", - "mmu_segmented_region_interlocking_depth", - "small_area_infill_flow_compensation", - "small_area_infill_flow_compensation_model", - "enable_wrapping_detection", - "seam_slope_type", - "seam_slope_conditional", - "scarf_angle_threshold", - "scarf_joint_speed", - "scarf_joint_flow_ratio", - "seam_slope_start_height", - "seam_slope_entire_loop", - "seam_slope_min_length", - "seam_slope_steps", - "seam_slope_inner_walls", - "scarf_overhang_threshold", - "interlocking_beam", - "interlocking_orientation", - "interlocking_beam_layer_count", - "interlocking_depth", - "interlocking_boundary_avoidance", - "interlocking_beam_width", - "calib_flowrate_topinfill_special_order", - // Z Anti-Aliasing (ZAA) - "zaa_enabled", - "zaa_minimize_perimeter_height", - "zaa_dont_alternate_fill_direction", - "zaa_min_z", - "ironing_expansion", + "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits", + "flush_into_infill", "flush_into_objects", "flush_into_support", + "tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter", + "tree_support_branch_diameter", "tree_support_branch_diameter_angle", + "detect_narrow_internal_solid_infill", + "gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination","infill_combination_max_layer_height", /*"adaptive_layer_height",*/ + "support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed", + "initial_layer_infill_speed", "only_one_wall_top", + "timelapse_type", + "wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", + "wall_distribution_count", "min_feature_size", "min_bead_width", "post_process", "min_length_factor", + "small_perimeter_speed", "small_perimeter_threshold","bridge_angle","internal_bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface", + "default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk","default_junction_deviation", + "top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap", + "set_other_flow_ratios", "first_layer_flow_ratio", "outer_wall_flow_ratio", "inner_wall_flow_ratio", "overhang_flow_ratio", "sparse_infill_flow_ratio", "internal_solid_infill_flow_ratio", "gap_fill_flow_ratio", "support_flow_ratio", "support_interface_flow_ratio", + "role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop", + "bridge_density","internal_bridge_density", "precise_outer_wall", "bridge_acceleration", + "sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_auto_brim", + "tree_support_brim_width", "gcode_comments", "gcode_label_objects", + "initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width", + "make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size" ,"notes", + "wipe_tower_cone_angle", "wipe_tower_extra_spacing","wipe_tower_max_purge_speed", + "wipe_tower_wall_type", "wipe_tower_extra_rib_length", "wipe_tower_rib_width", "wipe_tower_fillet_wall", + "wipe_tower_filament", "wiping_volumes_extruders","wipe_tower_bridging", "wipe_tower_extra_flow","single_extruder_multi_material_priming", + "wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic", + "hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", + "small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model", + "enable_wrapping_detection", + "seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold", + "interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order", }; static std::vector s_Preset_filament_options {/*"filament_colour", */ "default_filament_colour", "required_nozzle_HRC", "filament_diameter", "pellet_flow_coefficient", "volumetric_speed_coefficients", "filament_type", @@ -1275,10 +976,10 @@ static std::vector s_Preset_filament_options {/*"filament_colour", // "bed_type", //BBS:temperature_vitrification "temperature_vitrification", "reduce_fan_stop_start_freq","dont_slow_down_outer_wall", "slow_down_for_layer_cooling", "fan_min_speed", - "fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "close_additional_fan_first_x_layers", "first_x_layer_fan_speed", "full_fan_speed_layer", "additional_fan_full_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed", - "filament_start_gcode", "filament_end_gcode", "filament_change_extrusion_role_gcode", + "fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed", + "filament_start_gcode", "filament_end_gcode", //exhaust fan control - "activate_air_filtration","activate_air_filtration_during_print","activate_air_filtration_on_completion","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed", + "activate_air_filtration","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed", // Retract overrides "filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel", "filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe", @@ -1299,7 +1000,7 @@ static std::vector s_Preset_filament_options {/*"filament_colour", "filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control", "filament_long_retractions_when_cut","filament_retraction_distances_when_cut", "idle_temperature", //BBS filament change length while the extruder color - "filament_change_length","filament_flush_volumetric_speed","filament_flush_temp", "filament_cooling_before_tower", + "filament_change_length","filament_flush_volumetric_speed","filament_flush_temp", "long_retractions_when_ec", "retraction_distances_when_ec" }; @@ -1312,14 +1013,12 @@ static std::vector s_Preset_machine_limits_options { "machine_max_junction_deviation", //resonance avoidance ported from qidi slicer "resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed", - // Orca: input shaping - "input_shaping_emit", "input_shaping_type", "input_shaping_freq_x", "input_shaping_freq_y", "input_shaping_damp_x", "input_shaping_damp_y", }; static std::vector s_Preset_printer_options { "printer_technology", "printable_area", "extruder_printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor", - "fan_kickstart", "part_cooling_fan_min_pwm", "fan_speedup_time", "fan_speedup_overhangs", + "fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs", "single_extruder_multi_material", "manual_filament_change", "file_start_gcode", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode", "change_filament_gcode", "change_extrusion_role_gcode", "printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type", "printable_height", "extruder_printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", @@ -1336,7 +1035,7 @@ static std::vector s_Preset_printer_options { "use_relative_e_distances", "extruder_type", "use_firmware_retraction", "printer_notes", "grab_length", "support_object_skip_flush", "physical_extruder_map", "cooling_tube_retraction", - "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "wipe_tower_type", "purge_in_prime_tower", "enable_filament_ramming", "tool_change_on_wipe_tower", + "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "wipe_tower_type", "purge_in_prime_tower", "enable_filament_ramming", "z_offset", "disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "pellet_modded_printer", "support_multi_bed_types", "default_bed_type", "bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "enable_long_retraction_when_cut","long_retractions_when_cut","retraction_distances_when_cut", "bed_temperature_formula", "nozzle_flush_dataset" @@ -1512,34 +1211,19 @@ void PresetCollection::add_default_preset(const std::vector &keys, ++ m_num_default_presets; } -std::string PresetCollection::canonical_preset_name(const std::string &name, const PresetOrigin &load_origin) const -{ - const ParsedName parsed = parse_preset_name(name); - PresetOrigin origin = load_origin; - if (origin.kind == PresetOrigin::Kind::Auto) { - origin.kind = parsed.kind; - origin.bundle_id = parsed.bundle_id; - } else if (origin.is_bundle() && origin.bundle_id.empty()) { - origin.bundle_id = parsed.bundle_id; - } - return get_preset_canonical_name(parsed.bare, origin); -} - // Load all presets found in dir_path. // Throws an exception on error. void PresetCollection::load_presets( const std::string &dir_path, const std::string &subdir, - PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule substitution_rule, - std::function preset_loaded_fn, const PresetOrigin &load_origin) + PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule substitution_rule) { // 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(); - const PresetOrigin resolved_origin = detect_origin_from_path(dir, load_origin); // Load custom roots first if (fs::exists(dir / "base")) { - load_presets(dir.string(), "base", substitutions, substitution_rule, nullptr, resolved_origin); + load_presets(dir.string(), "base", substitutions, substitution_rule); } //BBS: add config related logs @@ -1569,16 +1253,14 @@ void PresetCollection::load_presets( if (Slic3r::is_json_file(file_name)) { // Remove the .ini suffix. std::string name = file_name.erase(file_name.size() - 5); - std::string canonical_name = this->canonical_preset_name(name, resolved_origin); - if (this->find_preset(canonical_name, false)) { + if (this->find_preset(name, false)) { // This happens when there's is a preset (most likely legacy one) with the same name as a system preset // that's already been loaded from a bundle. - BOOST_LOG_TRIVIAL(warning) << "Preset already present, not loading: " << canonical_name; + BOOST_LOG_TRIVIAL(warning) << "Preset already present, not loading: " << name; continue; } try { - Preset preset(m_type, canonical_name, false); - preset.bundle_id = resolved_origin.bundle_id; + Preset preset(m_type, name, false); preset.file = dir_entry.path().string(); // Load the preset file, apply preset values on top of defaults. try { @@ -1629,6 +1311,7 @@ void PresetCollection::load_presets( std::string inherits_value = option_str->value; // Orca: try to find if the parent preset has been renamed inherit_preset = this->find_preset2(inherits_value); + } else { ; } @@ -1706,9 +1389,6 @@ void PresetCollection::load_presets( fs::remove(file_path); } - if (preset_loaded_fn != nullptr) - preset_loaded_fn(preset); - presets_loaded.emplace_back(preset); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " load config successful and preset name is:" << preset.name; } catch (const std::runtime_error &err) { @@ -1827,9 +1507,9 @@ int PresetCollection::get_differed_values_to_update(Preset& preset, std::map& proje inherits_value.replace(pos, 1, 1, '~'); option_str->value = inherits_value; }*/ - inherit_preset = this->find_preset2(inherits_value, true); + inherit_preset = this->find_preset(inherits_value, false, true); } const Preset& default_preset = this->default_preset_for(config); if (inherit_preset) { @@ -1981,10 +1661,9 @@ bool PresetCollection::reset_project_embedded_presets() void PresetCollection::set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo, long long update_time) { lock(); - const std::string canonical_name = this->canonical_preset_name(name); for (auto it = m_presets.begin(); it != m_presets.end(); it++) { Preset* preset = &m_presets[it - m_presets.begin()]; - if (preset->name == canonical_name) { + if (preset->name == name) { if (syncinfo.empty()) preset->sync_info.clear(); else @@ -2049,7 +1728,7 @@ void PresetCollection::update_user_presets_directory(const std::string& dir_path } //BBS: save user presets to local -void PresetCollection::save_user_presets(const std::string& dir_path, const std::string& type, std::map& need_to_delete_list) +void PresetCollection::save_user_presets(const std::string& dir_path, const std::string& type, std::vector& need_to_delete_list) { boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / type).make_preferred(); @@ -2103,37 +1782,31 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std: } //BBS: load one user preset from key-values -bool PresetCollection::load_user_preset(std::string name, std::map preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, const PresetOrigin &load_origin) +bool PresetCollection::load_user_preset(std::string name, std::map preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule) { std::string errors_cummulative; // Store the loaded presets into a new vector, otherwise the binary search for already existing presets would be broken. // (see the "Preset already present, not loading" message). //std::deque presets_loaded; int count = 0; - const std::string canonical_name = this->canonical_preset_name(name, load_origin); - auto update_alias = [this](Preset &preset) { - if (! preset.alias.empty()) - return; - set_custom_preset_alias(preset); - }; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, name %1% , total value counts %2%")%canonical_name %preset_values.size(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, name %1% , total value counts %2%")%name %preset_values.size(); //if the version is not matching, skip it if (preset_values.find(BBL_JSON_KEY_VERSION) == preset_values.end()) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find version, not loading for user preset %1%")%canonical_name; + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find version, not loading for user preset %1%")%name; return false; } std::string version_str = preset_values[BBL_JSON_KEY_VERSION]; boost::optional cloud_version = Semver::parse(version_str); if (!cloud_version) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid version %1%, not loading for user preset %2%")%version_str %canonical_name; + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid version %1%, not loading for user preset %2%")%version_str %name; return false; } //setting_id if (preset_values.find(BBL_JSON_KEY_SETTING_ID) == preset_values.end()) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find setting_id, not loading for user preset %1%")%canonical_name; + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find setting_id, not loading for user preset %1%")%name; return false; } std::string cloud_setting_id = preset_values[BBL_JSON_KEY_SETTING_ID]; @@ -2146,17 +1819,17 @@ bool PresetCollection::load_user_preset(std::string name, std::mapname; - auto iter = this->find_preset_internal(canonical_name); + auto iter = this->find_preset_internal(name); bool need_update = false; - if ((iter != m_presets.end()) && (iter->name == canonical_name)) { - BOOST_LOG_TRIVIAL(info) << "Found the Preset locally: " << canonical_name; + if ((iter != m_presets.end()) && (iter->name == name)) { + BOOST_LOG_TRIVIAL(info) << "Found the Preset locally: " << name; //BBS: we should compare the time between cloud and local if ((cloud_update_time == 0) || (cloud_update_time <= iter->updated_time)) { if (cloud_update_time < iter->updated_time) @@ -2168,7 +1841,7 @@ bool PresetCollection::load_user_preset(std::string name, std::mapfile); idx_file.replace_extension(".info"); iter->save_info(idx_file.string()); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("preset %1%'s update_time is eqaul or newer, cloud update_time %2%, local update_time %3%")%canonical_name %cloud_update_time %iter->updated_time; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("preset %1%'s update_time is eqaul or newer, cloud update_time %2%, local update_time %3%")%name %cloud_update_time %iter->updated_time; unlock(); return false; } @@ -2178,36 +1851,26 @@ bool PresetCollection::load_user_preset(std::string name, std::mapsecond; - } else { - const auto inherits_iter = preset_values.find(BBL_JSON_KEY_INHERITS); - const bool preset_inherits_from_parent = inherits_iter != preset_values.end() && !inherits_iter->second.empty(); - if (preset_inherits_from_parent) { - // This indicates that there is inherits exists but there is no base_id - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ - << boost::format("can not find base_id, not loading for user preset %1%") % canonical_name; - unlock(); - return false; - } + // base_id + if (preset_values.find(BBL_JSON_KEY_BASE_ID) == preset_values.end()) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find base_id, not loading for user preset %1%") % name; + unlock(); + return false; } + std::string cloud_base_id = preset_values[BBL_JSON_KEY_BASE_ID]; //filament_id std::string cloud_filament_id; if ((m_type == Preset::TYPE_FILAMENT) && preset_values.find(BBL_JSON_KEY_FILAMENT_ID) != preset_values.end()) { cloud_filament_id = preset_values[BBL_JSON_KEY_FILAMENT_ID]; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << canonical_name << " filament_id: " << cloud_filament_id << " base_id: " << based_id; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << name << " filament_id: " << cloud_filament_id << " base_id: " << cloud_base_id; } DynamicPrintConfig new_config, cloud_config; try { ConfigSubstitutions config_substitutions = cloud_config.load_string_map(preset_values, rule); if (! config_substitutions.empty()) - substitutions.push_back({ canonical_name, m_type, PresetConfigSubstitutions::Source::UserCloud, canonical_name, std::move(config_substitutions) }); + substitutions.push_back({ name, m_type, PresetConfigSubstitutions::Source::UserCloud, name, std::move(config_substitutions) }); //BBS: use inherit config as the base Preset* inherit_preset = nullptr; @@ -2215,7 +1878,12 @@ bool PresetCollection::load_user_preset(std::string name, std::map (inherits_config); std::string inherits_value = option_str->value; - inherit_preset = this->find_preset2(inherits_value, true); + /*size_t pos = inherits_value.find_first_of('*'); + if (pos != std::string::npos) { + inherits_value.replace(pos, 1, 1, '~'); + option_str->value = inherits_value; + }*/ + inherit_preset = this->find_preset(inherits_value, false, true); } const Preset& default_preset = this->default_preset_for(cloud_config); if (inherit_preset) { @@ -2229,7 +1897,7 @@ bool PresetCollection::load_user_preset(std::string name, std::map(inherits_config); if (inherits_config2 && !inherits_config2->value.empty()) { //we should skip this preset here - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip")%canonical_name; + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip")%name; unlock(); return false; } @@ -2255,17 +1923,13 @@ bool PresetCollection::load_user_preset(std::string name, std::mapname == m_edited_preset.name && iter->is_dirty) { // Keep modifies when update from remote new_config.apply_only(m_edited_preset.config, m_edited_preset.config.diff(iter->config)); - } else if (iter->name == m_edited_preset.name) { - // Preset is not dirty (no local unsaved changes) — also update the edited preset - // to prevent a false "dirty" indication (orange highlight) after a silent cloud sync - m_edited_preset.config = new_config; } iter->config = new_config; iter->updated_time = cloud_update_time; @@ -2273,28 +1937,25 @@ bool PresetCollection::load_user_preset(std::string name, std::mapversion = cloud_version.value(); iter->user_id = cloud_user_id; iter->setting_id = cloud_setting_id; - iter->base_id = based_id; + iter->base_id = cloud_base_id; iter->filament_id = cloud_filament_id; - update_alias(*iter); //presets_loaded.emplace_back(*it->second); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", update the user preset %1% from cloud, type %2%, setting_id %3%, base_id %4%, sync_info %5% inherits %6%, filament_id %7%") % iter->name %Preset::get_type_string(m_type) %iter->setting_id %iter->base_id %iter->sync_info %iter->inherits() % iter->filament_id; } else { //create a new one - Preset preset(m_type, canonical_name, false); + Preset preset(m_type, name, false); preset.is_system = false; preset.loaded = true; - preset.bundle_id = load_origin.bundle_id; preset.config = new_config; preset.updated_time = cloud_update_time; preset.sync_info = "save"; preset.version = cloud_version.value(); preset.user_id = cloud_user_id; preset.setting_id = cloud_setting_id; - preset.base_id = based_id; + preset.base_id = cloud_base_id; preset.filament_id = cloud_filament_id; - update_alias(preset); size_t cur_index = iter - m_presets.begin(); m_presets.insert(iter, preset); @@ -2316,7 +1977,7 @@ bool PresetCollection::load_user_preset(std::string name, std::mapcanonical_preset_name(preset_name); - std::deque::iterator it = this->find_preset_internal(canonical_name); - bool found = (it != m_presets.end()) && (it->name == canonical_name) && is_trusted(*it); + std::deque::iterator it = this->find_preset_internal(preset_name); + bool found = (it != m_presets.end()) && (it->name == preset_name) && (it->is_system || it->is_default); if (!found) { - it = this->find_preset_renamed(canonical_name); - found = it != m_presets.end() && is_trusted(*it); + it = this->find_preset_renamed(preset_name); + found = it != m_presets.end() && (it->is_system || it->is_default); } if (!found) { if (!inherit_name.empty()) { - const std::string canonical_inherit_name = this->canonical_preset_name(inherit_name); - it = this->find_preset_internal(canonical_inherit_name); - found = it != m_presets.end() && it->name == canonical_inherit_name && is_trusted(*it); + it = this->find_preset_internal(inherit_name); + found = it != m_presets.end() && it->name == inherit_name && (it->is_system || it->is_default); if (found) BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": preset_name %1%, inherit_name %2%, found inherit in list")%preset_name %inherit_name; else @@ -2430,7 +2084,7 @@ std::pair PresetCollection::load_external_preset( cfg.apply_only(combined_config, keys, true); std::string &inherits = Preset::inherits(cfg); - //add different settings check logic, replace the old system preset's default value with new system preset's default values + //BBS: add different settings check logic, replace the old system preset's default value with new system preset's default values std::deque::iterator it = this->find_preset_internal(original_name); bool found = it != m_presets.end() && it->name == original_name; if (! found) { @@ -2770,7 +2424,7 @@ std::map> PresetCollection::get_filamen std::map> filament_presets; for (auto &preset : m_presets) { if (preset.is_user()) { - if (preset.inherits() == "") { filament_presets[preset.filament_id].push_back(&preset); } + if (preset.inherits() == "" || !preset.filament_id.empty()) { filament_presets[preset.filament_id].push_back(&preset); } continue; } if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); } @@ -2792,7 +2446,7 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det // Preset with the same name found. Preset &preset = *it; //BBS: add project embedded preset logic - if (!preset.can_overwrite()) { + if (preset.is_default || preset.is_system) { //if (preset.is_default || preset.is_external || preset.is_system) // Cannot overwrite the default preset. //BBS: add lock logic for sync preset in background @@ -2851,9 +2505,6 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det preset.is_default = false; preset.is_system = false; preset.is_external = false; - - preset.bundle_id.clear(); - preset.file = this->path_for_preset(preset); // The newly saved preset will be activated -> make it visible. preset.is_visible = true; @@ -2867,8 +2518,18 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det preset.is_project_embedded = false; if (m_type == Preset::TYPE_PRINT) preset.config.option("print_settings_id", true)->value = new_name; - else if (m_type == Preset::TYPE_FILAMENT) + else if (m_type == Preset::TYPE_FILAMENT) { preset.config.option("filament_settings_id", true)->values[0] = new_name; + + boost::uuids::detail::md5 hash; + boost::uuids::detail::md5::digest_type digest; + hash.process_bytes(new_name.data(), new_name.size()); + hash.get_digest(digest); + const auto char_digest = reinterpret_cast(&digest); + std::string result; + boost::algorithm::hex(char_digest, char_digest + sizeof(boost::uuids::detail::md5::digest_type), std::back_inserter(result)); + preset.filament_id = "P" + result.substr(0, 7); + } else if (m_type == Preset::TYPE_PRINTER) preset.config.option("printer_settings_id", true)->value = new_name; //BBS: add lock logic for sync preset in background @@ -2896,7 +2557,7 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det bool PresetCollection::delete_current_preset() { Preset &selected = this->get_selected_preset(); - if (!selected.can_overwrite()) + if (selected.is_default) return false; if (get_preset_base(selected) == &selected) { @@ -2927,24 +2588,18 @@ bool PresetCollection::delete_current_preset() return true; } -bool PresetCollection::delete_preset(const std::string& name, bool force) +bool PresetCollection::delete_preset(const std::string& name) { - Preset *preset_ptr = this->find_preset(name, false, true); - if (preset_ptr == nullptr) - return false; - - auto it = this->find_preset_internal(preset_ptr->name); - if (it == m_presets.end() || it->name != preset_ptr->name) - return false; + auto it = this->find_preset_internal(name); Preset& preset = *it; - // ORCA: if the preset can't be overridden then don't allow deletion - // force=true bypasses this for bundle preset cleanup from cloud sync - if (!force && !preset.can_overwrite()) + if (preset.is_default) return false; - - preset.remove_files(); - + //BBS: add project embedded preset logic and refine is_external + //if (!preset.is_external && !preset.is_system) { + if (! preset.is_system) { + preset.remove_files(); + } //BBS: add lock logic for sync preset in background lock(); set_printer_hold_alias(it->alias, *it, true); @@ -2954,30 +2609,6 @@ bool PresetCollection::delete_preset(const std::string& name, bool force) return true; } -void PresetCollection::check_and_fix_syncinfo(Preset& preset, const std::string& user_id) -{ - // user id can't be empty - if (user_id.empty()) - return; - // correct the sync info if preset.user_id is empty(the profile json file is copied to the user folder with missing .info file) or preset.user_id - // is not equal to the current user id or preset.setting_id is not in expected format(the .info is copied from the older format) - if (preset.user_id.empty() || preset.user_id != user_id || preset.setting_id.find('-') == std::string::npos) { - preset.user_id = user_id; - preset.setting_id = ""; - - if (preset.base_id.empty()) { - const std::string inherits = Preset::inherits(preset.config); - Preset* parent_preset = find_preset2(inherits, true); - if (parent_preset) - preset.base_id = parent_preset->setting_id; - } - // tell the sync logic to sync it as a new preset - preset.updated_time = 0; - preset.sync_info = "create"; - preset.save_info(); - } -} - const Preset* PresetCollection::get_selected_preset_parent() const { if (this->get_selected_idx() == size_t(-1)) @@ -3040,7 +2671,7 @@ const Preset *PresetCollection::get_preset_base(const Preset &child) const // Handle user preset if (child.inherits().empty()) return &child; // this is user root - auto inherits = find_preset2(child.inherits(), true); + auto inherits = find_preset2(child.inherits(),true); return inherits ? get_preset_base(*inherits) : nullptr; } @@ -3114,21 +2745,20 @@ const std::string& PresetCollection::get_suffix_modified() { // If a preset was not found by its name, null is returned. Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found, bool real, bool only_from_library) { - const ParsedName parsed = parse_preset_name(name); - const std::string canonical = get_preset_canonical_name(parsed.bare, PresetOrigin(parsed.kind, parsed.bundle_id)); - auto it = this->find_preset_internal(canonical, only_from_library); - if (it != m_presets.end() && it->name == canonical) - return &this->preset(it - m_presets.begin(), real); - return first_visible_if_not_found ? &this->first_visible() : nullptr; + Preset key(m_type, name, false); + auto it = this->find_preset_internal(name, only_from_library); + // Ensure that a temporary copy is returned if the preset found is currently selected. + return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin(), real) : + first_visible_if_not_found ? &this->first_visible() : nullptr; } Preset* PresetCollection::find_preset2(const std::string& name, bool auto_match/* = true */) { - auto preset = find_preset(name, false, true); + auto preset = find_preset(name,false,true); if (preset == nullptr) { auto _name = get_preset_name_renamed(name); if (_name != nullptr) - preset = find_preset(*_name, false, true); + preset = find_preset(*_name,false,true); if (auto_match && preset == nullptr) { //Orca: one more try, find the most likely preset in OrcaFilamentLibrary if (name.find("Generic") != std::string::npos) { @@ -3144,6 +2774,7 @@ Preset* PresetCollection::find_preset2(const std::string& name, bool auto_match/ } } } + return preset; } @@ -3495,11 +3126,10 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b //BBS: add config related logs BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1%, try to select by name %2%, force %3%")%Preset::get_type_string(m_type) %name_w_suffix %force; std::string name = Preset::remove_suffix_modified(name_w_suffix); - const std::string normalized_name = this->canonical_preset_name(name); // 1) Try to find the preset by its name. - auto it = this->find_preset_internal(normalized_name); + auto it = this->find_preset_internal(name); size_t idx = 0; - if (it != m_presets.end() && it->name == normalized_name && it->is_visible) + if (it != m_presets.end() && it->name == name && it->is_visible) // Preset found by its name and it is visible. idx = it - m_presets.begin(); else { @@ -3532,12 +3162,11 @@ bool PresetCollection::select_preset_by_name_strict(const std::string &name) { //BBS: add config related logs BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1%, try to select by name %2%")%Preset::get_type_string(m_type) %name; - const std::string canonical_name = this->canonical_preset_name(name); // 1) Try to find the preset by its name. - auto it = this->find_preset_internal(canonical_name); + auto it = this->find_preset_internal(name); size_t idx = (size_t)-1; - if (it != m_presets.end() && it->name == canonical_name && it->is_visible) + if (it != m_presets.end() && it->name == name && it->is_visible) // Preset found by its name. idx = it - m_presets.begin(); // 2) Select the new preset. @@ -3649,30 +3278,24 @@ void PresetCollection::update_map_system_profile_renamed() void PresetCollection::set_custom_preset_alias(Preset &preset) { - // For filaments, remove the postfix - // For printers, there is nothing to remove - // For prints AKA processes, the postfix should be kept - // Alias should be set here, as the preset name may be augmented further later (i.e., prefixing relative path for bundles) - std::string bare_preset_name = get_preset_bare_name(preset.name); - std::string alias_name = bare_preset_name; - - const bool is_root_filament_preset = - m_type == Preset::Type::TYPE_FILAMENT && - preset.config.has(BBL_JSON_KEY_INHERITS) && - preset.config.option(BBL_JSON_KEY_INHERITS)->value.empty(); - if (is_root_filament_preset) { - const size_t suffix_separator_pos = bare_preset_name.find_first_of("@"); - if (suffix_separator_pos != std::string::npos) { - alias_name = bare_preset_name.substr(0, suffix_separator_pos); - boost::trim_right(alias_name); - if (alias_name.empty()) - alias_name = bare_preset_name; + if (m_type == Preset::Type::TYPE_FILAMENT && preset.config.has(BBL_JSON_KEY_INHERITS) && preset.config.option(BBL_JSON_KEY_INHERITS)->value.empty()) { + std::string alias_name; + std::string preset_name = preset.name; + if (alias_name.empty()) { + size_t end_pos = preset_name.find_first_of("@"); + if (end_pos != std::string::npos) { + alias_name = preset_name.substr(0, end_pos); + boost::trim_right(alias_name); + } + } + if (alias_name.empty() || is_alias_exist(alias_name, &preset)) + preset.alias = ""; + else { + preset.alias = std::move(alias_name); + m_map_alias_to_profile_name[preset.alias].push_back(preset.name); + set_printer_hold_alias(preset.alias, preset); } } - - preset.alias = std::move(alias_name); - m_map_alias_to_profile_name[preset.alias].push_back(preset.name); - set_printer_hold_alias(preset.alias, preset); } void PresetCollection::set_printer_hold_alias(const std::string &alias, Preset &preset, bool remove) @@ -3773,7 +3396,7 @@ std::string PresetCollection::path_from_name(const std::string &new_name, bool d std::string PresetCollection::path_for_preset(const Preset &preset) const { - return path_from_name(get_preset_bare_name(preset.name), is_base_preset(preset)); + return path_from_name(preset.name, is_base_preset(preset)); } const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 5e0ab158499..f85b0103c7f 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -3101,7 +3101,7 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info) continue; } auto iter = std::find_if(filaments.begin(), filaments.end(), - [this, &filament_id](auto &f) { return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; }); + [this, &filament_id](auto &f) { return f.is_compatible && (filaments.get_preset_base(f) == &f || (f.is_user() && !f.filament_id.empty())) && f.filament_id == filament_id; }); if (iter == filaments.end()) { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id; auto filament_type = ams.opt_string("filament_type", 0u); @@ -3203,7 +3203,7 @@ unsigned int PresetBundle::sync_ams_list(std::vector