import os def load_valid_keys(): valid = set() if os.path.exists('valid_keys.txt'): with open('valid_keys.txt', 'r') as f: for line in f: if line.strip(): valid.add(line.strip()) # 补充一些在 PrusaSlicer ini常见但可能在cli中缺失的原生合法字段 valid.update([ "start_gcode", "end_gcode", "before_layer_gcode", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "printer_model", "family", "z_offset", "printer_technology", "gcode_flavor", "silent_mode", "printer_variant", "max_print_height", "nozzle_diameter", "extruder_colour", "extruder_offset", "use_relative_e_distances", "use_firmware_retraction", "retract_layer_change", "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_before_travel", "retract_before_wipe", "wipe", "machine_limits_usage", "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e", "machine_max_speed_x", "machine_max_speed_y", "machine_max_speed_z", "machine_max_speed_e", "machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e", "machine_min_travel_rate", "default_filament_colour", "filament_type", "filament_diameter", "filament_density", "filament_cost", "fan_always_on", "cooling", "support_material", "support_material_auto", "support_material_style" ]) return valid VALID_KEYS = load_valid_keys() # 基于全量 all_keys.txt 逐一梳理的语义映射字典 SEMANTIC_MAP = { # 打印层高相关 "adaptive_layer_height": "variable_layer_height", "initial_layer_print_height": "first_layer_height", "layer_height": "layer_height", "min_layer_height": "min_layer_height", "max_layer_height": "max_layer_height", "print_sequence": "complete_objects", # 线宽相关 "line_width": "extrusion_width", "initial_layer_line_width": "first_layer_extrusion_width", "outer_wall_line_width": "external_perimeter_extrusion_width", "inner_wall_line_width": "perimeter_extrusion_width", "top_surface_line_width": "top_infill_extrusion_width", "sparse_infill_line_width": "infill_extrusion_width", "internal_solid_infill_line_width": "solid_infill_extrusion_width", # 墙/外壳相关 "wall_loops": "perimeters", "top_shell_layers": "top_solid_layers", "bottom_shell_layers": "bottom_solid_layers", "top_shell_thickness": "top_solid_min_thickness", "bottom_shell_thickness": "bottom_solid_min_thickness", "only_one_wall_top": "top_one_perimeter_type", "detect_thin_wall": "thin_walls", # "detect_narrow_internal_solid_infill": "thin_walls", "reduce_crossing_wall": "avoid_crossing_perimeters", # 填充相关 "sparse_infill_density": "fill_density", "sparse_infill_pattern": "fill_pattern", "infill_direction": "fill_angle", "infill_wall_overlap": "infill_overlap", "infill_combination": "solid_infill_every_layers", "bottom_surface_pattern": "bottom_fill_pattern", "top_surface_pattern": "top_fill_pattern", "gap_fill_target": "gap_fill_enabled", # 速度相关 "initial_layer_speed": "first_layer_speed", "initial_layer_infill_speed": "first_layer_infill_speed", "outer_wall_speed": "external_perimeter_speed", "inner_wall_speed": "perimeter_speed", "top_surface_speed": "top_solid_infill_speed", "sparse_infill_speed": "infill_speed", "internal_solid_infill_speed": "solid_infill_speed", "gap_infill_speed": "gap_fill_speed", "bridge_speed": "bridge_speed", "travel_speed": "travel_speed", "travel_speed_z": "travel_speed_z", "small_perimeter_speed": "small_perimeter_speed", "support_speed": "support_material_speed", "support_interface_speed": "support_material_interface_speed", # 加速度相关 "default_acceleration": "default_acceleration", "initial_layer_acceleration": "first_layer_acceleration", "outer_wall_acceleration": "external_perimeter_acceleration", "inner_wall_acceleration": "perimeter_acceleration", "top_surface_acceleration": "top_solid_infill_acceleration", "travel_acceleration": "travel_acceleration", "bridge_acceleration": "bridge_acceleration", # 支撑相关 "support_angle": "support_material_angle", "support_top_z_distance": "support_material_contact_distance", "support_bottom_z_distance": "support_material_bottom_contact_distance", "support_interface_top_layers": "support_material_interface_layers", "support_interface_bottom_layers": "support_material_bottom_interface_layers", "support_interface_spacing": "support_material_interface_spacing", # "support_remove_small_overhang": "support_material_threshold", "support_interface_pattern": "support_material_interface_pattern", # 底座/附着相关 "brim_width": "brim_width", "raft_layers": "raft_layers", "raft_contact_distance": "raft_contact_distance", "raft_expansion": "raft_expansion", "raft_first_layer_density": "raft_first_layer_density", "raft_first_layer_expansion": "raft_first_layer_expansion", "skirt_distance": "skirt_distance", "skirt_height": "skirt_height", "skirt_loops": "skirts", "elefant_foot_compensation": "elefant_foot_compensation", # 回抽与耗材相关 "z_hop": "retract_lift", "retract_length": "retract_length", "retract_speed": "retract_speed", "retract_before_wipe": "retract_before_wipe", "retract_before_travel": "retract_before_travel", "retract_layer_change": "retract_layer_change", "retract_lift_above": "retract_lift_above", "retract_lift_below": "retract_lift_below", "filament_deretraction_speed": "filament_deretract_speed", "filament_retraction_length": "filament_retract_length", "filament_retraction_speed": "filament_retract_speed", "material_type": "filament_type", "nozzle_temperature": "temperature", "nozzle_temperature_initial_layer": "first_layer_temperature", "filament_flow_ratio": "extrusion_multiplier", # 其他属性 "bridge_flow": "bridge_flow_ratio", # "idle_temperature": "standby_temperature_delta", "enable_arc_fitting": "arc_fitting", "slowdown_for_curled_perimeters": "avoid_crossing_curled_overhangs", "slow_down_layer_time": "slowdown_below_layer_time", "fan_max_speed": "max_fan_speed", "fan_min_speed": "min_fan_speed", "spiral_mode": "spiral_vase", "prime_tower_brim_width": "wipe_tower_brim_width", "prime_tower_width": "wipe_tower_width", "bridge_no_support": "dont_support_bridges", "minimum_sparse_infill_area": "solid_infill_below_area", "xy_hole_compensation": "xy_size_compensation", "enable_prime_tower": "wipe_tower", "ironing_flow": "ironing_flowrate", "overhang_1_4_speed": "overhang_speed_0", "overhang_2_4_speed": "overhang_speed_1", "overhang_3_4_speed": "overhang_speed_2", "overhang_4_4_speed": "overhang_speed_3", "enable_overhang_speed": "enable_dynamic_overhang_speeds", "enforce_support_layers": "support_material_enforce_layers", "fuzzy_skin_point_distance": "fuzzy_skin_point_dist", # "initial_layer_min_bead_width": "min_bead_width", # "internal_bridge_flow": "bridge_flow_ratio", # "internal_bridge_speed": "bridge_speed", "internal_solid_infill_acceleration": "solid_infill_acceleration", "internal_solid_infill_pattern": "solid_fill_pattern", "is_infill_first": "infill_first", "seam_gap": "seam_gap_distance", "seam_slope_entire_loop": "scarf_seam_entire_loop", "seam_slope_inner_walls": "scarf_seam_on_inner_perimeters", "seam_slope_min_length": "scarf_seam_length", "seam_slope_start_height": "scarf_seam_start_height", "sparse_infill_acceleration": "infill_acceleration", "internal_solid_infill_acceleration": "solid_infill_acceleration", "wall_generator": "perimeter_generator", # "wipe_tower_rotation_angle": "wipe_tower_cone_angle" } def process_file(filepath): with open(filepath, 'r') as f: lines = f.readlines() new_lines = [] changed = False for line in lines: stripped = line.strip() # 忽略空行、段名和已经是原生的配置行 if not stripped or stripped.startswith('[') or stripped.startswith(';') or stripped.startswith('show_name'): new_lines.append(line) continue if '=' in line: parts = line.split('=', 1) raw_key = parts[0].strip() # 兼容前面可能被加了;;;的key重新解开的情况(以防跑多次) key = raw_key.lstrip(';') val = parts[1].strip() # 处理一些特有的布尔值或字符串转义差异 if key == "print_sequence" and val == "by layer": val = "0" elif key == "print_sequence" and val == "by object": val = "1" if key == "spiral_mode": val = "1" if val != "0" else "0" if key == "support_type" and "auto" in val: val = "1" if val == "zig-zag": val = "zigzag" if key == "enable_arc_fitting": if str(val) == "1": val = "emit_center" else: val = "disabled" if key == "only_one_wall_top": if str(val) == "1": val = "top" else: val = "none" if key in SEMANTIC_MAP: new_key = SEMANTIC_MAP[key] new_lines.append(f"{new_key} = {val}\n") changed = True elif key in VALID_KEYS: # 已经是PrusaSlicer的原生可用属性 new_lines.append(f"{key} = {val}\n") else: # 在 all_keys.txt 中但找不到任何对应 PrusaSlicer 语义的属性 new_lines.append(f";;;{raw_key} = {val}\n") changed = True else: new_lines.append(line) if changed: with open(filepath, 'w') as f: f.writelines(new_lines) for root, dirs, files in os.walk('print_config/prusa_slicer'): for file in files: if file.endswith('.ini'): process_file(os.path.join(root, file)) print("All keys mapped exhaustively.")