Compare commits

..
Author SHA1 Message Date
Hanif Koh 5bf2aa3e50 Keep User Filament Presets on Printers Their Parent Listed in 2.4.2
User presets store only their diff, so they inherit the parent's
compatible_printers. Profile changes since 2.4.2 renamed and narrowed many
system filament presets, so user presets made against them disappear from
printers they were made for and the saved selection silently falls back to
another filament at startup.

orca_profile_tool.py legacy-compat writes, per current system filament
preset, the printers it covered in an older release and no longer lists,
kept only where a preset with the same filament_id still covers the printer
and they share an extruder variant. The loader gives these printers to user
presets that inherit their parent's list, without writing any file; saving
a preset detached, cloned or with its own list drops them.
2026-10-11 20:41:30 +08:00
9 changed files with 1226 additions and 3 deletions
@@ -0,0 +1,795 @@
{
"presets": {
"Bambu ABS @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu ABS @BBL X1C": [
"Bambu Lab P1S 0.4 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu ASA @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PA6-CF @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PA6-CF @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PA6-CF @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PA6-CF @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PA6-CF @BBL X1C": [
"Bambu Lab P1P 0.6 nozzle",
"Bambu Lab P1P 0.8 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab P1S 0.8 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle",
"Bambu Lab X1 Carbon 0.8 nozzle"
],
"Bambu PA6-CF @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PAHT-CF @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PAHT-CF @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PAHT-CF @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PAHT-CF @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle",
"Bambu Lab P1P 0.8 nozzle"
],
"Bambu PAHT-CF @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PAHT-CF @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab P1S 0.8 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle",
"Bambu Lab X1 Carbon 0.8 nozzle"
],
"Bambu PAHT-CF @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PC @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PETG @0.2 nozzle": [
"Qidi Q1 Pro 0.2 nozzle"
],
"Bambu PETG Basic @BBL H2D 0.6 nozzle": [
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PETG Basic @BBL H2DP 0.6 nozzle": [
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PETG Basic @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PETG Basic @BBL P2S 0.6 nozzle": [
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PETG Basic @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PETG HF @BBL P2S 0.6 nozzle": [
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PETG HF @BBL X1C": [
"Bambu Lab P1P 0.4 nozzle",
"Bambu Lab P1S 0.4 nozzle"
],
"Bambu PETG HF @BBL X1C 0.8 nozzle": [
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PETG HF @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PETG Translucent @BBL H2D 0.6 nozzle": [
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PETG Translucent @BBL H2DP 0.6 nozzle": [
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PETG Translucent @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PETG Translucent @BBL P2S 0.6 nozzle": [
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PETG Translucent @BBL X1C 0.8 nozzle": [
"Bambu Lab P1P 0.6 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PETG-CF @BBL H2D 0.6 nozzle": [
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PETG-CF @BBL H2DP 0.6 nozzle": [
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PETG-CF @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PETG-CF @BBL P2S 0.6 nozzle": [
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PLA Basic @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Basic @BBL X1C": [
"Bambu Lab P1S 0.4 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Basic @BBL X2D 0.6 nozzle": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PLA Dynamic @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Dynamic @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Galaxy @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Galaxy @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Glow @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Glow @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Lite @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle"
],
"Bambu PLA Lite @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PLA Lite @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Lite @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Lite @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PLA Marble @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle",
"Bambu Lab P1P 0.8 nozzle"
],
"Bambu PLA Marble @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Matte @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Matte @BBL X1C": [
"Bambu Lab P1S 0.4 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Matte @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PLA Metal @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Metal @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Silk+ @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PLA Silk+ @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PLA Silk+ @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PLA Silk+ @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Silk+ @BBL X1C": [
"Bambu Lab P1S 0.4 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Silk+ @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PLA Sparkle @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Sparkle @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Tough+ @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Tough+ @BBL X1C": [
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA Tough+ @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PLA Translucent @BBL H2D 0.8 nozzle": [
"Bambu Lab H2D 0.6 nozzle"
],
"Bambu PLA Translucent @BBL H2DP 0.8 nozzle": [
"Bambu Lab H2D Pro 0.6 nozzle"
],
"Bambu PLA Translucent @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PLA Wood @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu PLA Wood @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu PLA-CF @BBL H2D 0.6 nozzle": [
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PLA-CF @BBL H2DP 0.6 nozzle": [
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PLA-CF @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PLA-CF @BBL P2S 0.6 nozzle": [
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PLA-CF @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu PPA-CF @BBL X1C": [
"Bambu Lab P1P 0.6 nozzle",
"Bambu Lab P1P 0.8 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab P1S 0.8 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle",
"Bambu Lab X1 Carbon 0.8 nozzle"
],
"Bambu PVA @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu PVA @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu PVA @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu PVA @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu PVA @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu Support For PLA @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu Support For PLA @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu Support For PLA @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu Support For PLA @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu Support For PLA @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu Support For PLA/PETG @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu Support For PLA/PETG @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu Support For PLA/PETG @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu Support For PLA/PETG @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu Support For PLA/PETG @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu Support for ABS @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu Support for ABS @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu Support for ABS @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu Support for ABS @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu Support for ABS @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu TPU 90A @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu TPU 90A @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu TPU 95A HF @BBL H2D": [
"Bambu Lab H2D 0.4 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu TPU 95A HF @BBL H2DP": [
"Bambu Lab H2D Pro 0.4 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu TPU 95A HF @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu TPU 95A HF @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu TPU 95A HF @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Bambu TPU for AMS @BBL H2D": [
"Bambu Lab H2D 0.6 nozzle",
"Bambu Lab H2D 0.8 nozzle"
],
"Bambu TPU for AMS @BBL H2DP": [
"Bambu Lab H2D Pro 0.6 nozzle",
"Bambu Lab H2D Pro 0.8 nozzle"
],
"Bambu TPU for AMS @BBL H2S": [
"Bambu Lab H2S 0.6 nozzle",
"Bambu Lab H2S 0.8 nozzle"
],
"Bambu TPU for AMS @BBL P1P": [
"Bambu Lab P1P 0.6 nozzle"
],
"Bambu TPU for AMS @BBL P2S": [
"Bambu Lab P2S 0.6 nozzle",
"Bambu Lab P2S 0.8 nozzle"
],
"Bambu TPU for AMS @BBL X1C": [
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 Carbon 0.6 nozzle"
],
"Bambu TPU for AMS @BBL X2D": [
"Bambu Lab X2D 0.8 nozzle"
],
"Blocks ABS @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks ASA @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks ASA-CF @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PA @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PA-CF @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PC @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PETG @Blocks_Pro_S100": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PLA @Blocks_Pro_S100": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PLA-CF @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks PVA @Blocks_RD50_V2": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Blocks TPU @Blocks_Pro_S100": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
],
"Cubicon ABS @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon ABS-A100 @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon ABSk @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PA-CF @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PC @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PETG @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PLA @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PLA+ @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Cubicon PLAi21 @Cubicon xCeler-I 0.4 nozzle": [
"Cubicon xCeler-Plus 0.4 nozzle"
],
"Flashforge HS PLA": [
"Flashforge AD5X 0.4 nozzle",
"Flashforge AD5X 0.6 nozzle",
"Flashforge AD5X 0.8 nozzle"
],
"Flashforge PETG-CF": [
"Flashforge AD5X 0.4 nozzle",
"Flashforge AD5X 0.6 nozzle",
"Flashforge AD5X 0.8 nozzle"
],
"Flashforge PLA-CF": [
"Flashforge AD5X 0.4 nozzle",
"Flashforge AD5X 0.6 nozzle",
"Flashforge AD5X 0.8 nozzle"
],
"Flashforge TPU 95A": [
"Flashforge AD5X 0.4 nozzle",
"Flashforge AD5X 0.6 nozzle",
"Flashforge AD5X 0.8 nozzle"
],
"FusRock PAHT-CF": [
"Flashforge Guider 3 Ultra 0.6 Nozzle"
],
"FusRock PET-CF": [
"Flashforge Guider 3 Ultra 0.6 Nozzle"
],
"Generic ABS @Anycubic": [
"Anycubic Kobra 3 0.4 nozzle"
],
"Generic ABS @Creality": [
"Creality CR-10 SE 0.2 nozzle",
"Creality CR-10 SE 0.4 nozzle",
"Creality CR-10 SE 0.6 nozzle",
"Creality CR-10 SE 0.8 nozzle",
"Creality CR-6 SE 0.2 nozzle",
"Creality CR-6 SE 0.4 nozzle",
"Creality CR-6 SE 0.6 nozzle",
"Creality CR-6 SE 0.8 nozzle",
"Creality CR-M4 0.4 nozzle",
"Creality Ender-3 V2 0.4 nozzle"
],
"Generic ABS @Creality Ender-3V3-all": [
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle"
],
"Generic ABS @Creality Hi-all": [
"Creality Hi 0.4 nozzle"
],
"Generic ABS @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic ABS @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Plus 0.6 nozzle",
"Creality K2 Plus 0.8 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"Generic ABS @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle"
],
"Generic ASA @Creality Ender-3V3-all": [
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle"
],
"Generic ASA @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic ASA @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"Generic ASA @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle"
],
"Generic HIPS @Flashforge": [
"Flashforge Guider 3 Ultra 0.6 Nozzle"
],
"Generic PA @Prusa": [
"Prusa MINIIS 0.25 nozzle",
"Prusa MINIIS 0.4 nozzle",
"Prusa MINIIS 0.6 nozzle",
"Prusa MINIIS 0.8 nozzle"
],
"Generic PA-CF @Creality Ender-3V3-all": [
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle"
],
"Generic PA-CF @Creality K1-all": [
"Creality K1C 0.4 nozzle"
],
"Generic PA-CF @Creality K2-all": [
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Plus 0.6 nozzle",
"Creality K2 Plus 0.8 nozzle"
],
"Generic PA-CF @Prusa": [
"Prusa MINIIS 0.25 nozzle",
"Prusa MINIIS 0.4 nozzle",
"Prusa MINIIS 0.6 nozzle",
"Prusa MINIIS 0.8 nozzle"
],
"Generic PC @Creality K1-all": [
"Creality K1C 0.4 nozzle"
],
"Generic PETG @Creality": [
"Creality CR-6 SE 0.2 nozzle",
"Creality CR-6 SE 0.4 nozzle",
"Creality CR-6 SE 0.6 nozzle",
"Creality CR-6 SE 0.8 nozzle",
"Creality CR-M4 0.4 nozzle"
],
"Generic PETG @Creality Ender-3V3-all": [
"Creality Ender-3 V3 0.4 nozzle",
"Creality Ender-3 V3 0.6 nozzle",
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle",
"Creality Ender-3 V3 SE 0.2 nozzle",
"Creality Ender-3 V3 SE 0.4 nozzle",
"Creality Ender-3 V3 SE 0.6 nozzle",
"Creality Ender-3 V3 SE 0.8 nozzle"
],
"Generic PETG @Creality Hi-all": [
"Creality Hi 0.4 nozzle"
],
"Generic PETG @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic PETG @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Plus 0.6 nozzle",
"Creality K2 Plus 0.8 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"Generic PETG @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle",
"Flashforge Guider 3 Ultra 0.8 Nozzle"
],
"Generic PETG @Sovol Zero Hardened Steel nozzle": [
"Sovol Zero 0.4 nozzle"
],
"Generic PETG HF @BBL X1C": [
"Bambu Lab P1S 0.4 nozzle",
"Bambu Lab P1S 0.6 nozzle",
"Bambu Lab X1 0.4 nozzle",
"Bambu Lab X1 0.6 nozzle",
"Bambu Lab X1 0.8 nozzle"
],
"Generic PETG-CF @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle",
"Flashforge Guider 3 Ultra 0.8 Nozzle"
],
"Generic PLA @Creality": [
"Creality CR-10 SE 0.2 nozzle",
"Creality CR-10 SE 0.4 nozzle",
"Creality CR-10 SE 0.6 nozzle",
"Creality CR-10 SE 0.8 nozzle",
"Creality CR-6 SE 0.2 nozzle",
"Creality CR-6 SE 0.4 nozzle",
"Creality CR-6 SE 0.6 nozzle",
"Creality CR-6 SE 0.8 nozzle",
"Creality CR-M4 0.4 nozzle"
],
"Generic PLA @Creality Ender-3V3-all": [
"Creality Ender-3 V3 0.4 nozzle",
"Creality Ender-3 V3 0.6 nozzle",
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle"
],
"Generic PLA @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic PLA @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Plus 0.6 nozzle",
"Creality K2 Plus 0.8 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"Generic PLA @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle",
"Flashforge Guider 3 Ultra 0.8 Nozzle"
],
"Generic PLA @Hi-all": [
"Creality Hi 0.4 nozzle",
"Creality Hi 0.6 nozzle"
],
"Generic PLA @Sovol Zero Hardened Steel nozzle": [
"Sovol Zero 0.4 nozzle"
],
"Generic PLA Silk @Sovol Zero Hardened Steel nozzle": [
"Sovol Zero 0.4 nozzle"
],
"Generic PLA-CF @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic PLA-CF @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"Generic PLA-CF @Flashforge G3U": [
"Flashforge Guider 3 Ultra 0.6 Nozzle",
"Flashforge Guider 3 Ultra 0.8 Nozzle"
],
"Generic PLA-CF @Prusa": [
"Prusa MINIIS 0.25 nozzle",
"Prusa MINIIS 0.4 nozzle",
"Prusa MINIIS 0.6 nozzle",
"Prusa MINIIS 0.8 nozzle"
],
"Generic TPU @Anycubic": [
"Anycubic Kobra 3 0.4 nozzle"
],
"Generic TPU @Creality": [
"Creality CR-10 SE 0.2 nozzle",
"Creality CR-10 SE 0.4 nozzle",
"Creality CR-10 SE 0.6 nozzle",
"Creality CR-10 SE 0.8 nozzle"
],
"Generic TPU @Creality Ender-3V3-all": [
"Creality Ender-3 V3 0.4 nozzle",
"Creality Ender-3 V3 0.6 nozzle",
"Creality Ender-3 V3 Plus 0.4 nozzle",
"Creality Ender-3 V3 Plus 0.6 nozzle",
"Creality Ender-3 V3 SE 0.2 nozzle",
"Creality Ender-3 V3 SE 0.4 nozzle",
"Creality Ender-3 V3 SE 0.6 nozzle",
"Creality Ender-3 V3 SE 0.8 nozzle"
],
"Generic TPU @Creality K1-all": [
"Creality K1 SE 0.4 nozzle",
"Creality K1C 0.4 nozzle"
],
"Generic TPU @Creality K2-all": [
"Creality K2 0.4 nozzle",
"Creality K2 Plus 0.4 nozzle",
"Creality K2 Pro 0.4 nozzle"
],
"HATCHBOX PETG @0.2 nozzle": [
"Qidi Q1 Pro 0.2 nozzle"
],
"QIDI PETG Basic @0.2 nozzle": [
"Qidi Q1 Pro 0.2 nozzle"
],
"QIDI PETG Rapido @0.2 nozzle": [
"Qidi Q1 Pro 0.2 nozzle"
],
"QIDI PETG Translucent @0.2 nozzle": [
"Qidi Q1 Pro 0.2 nozzle"
],
"re3D PC @0.4 nozzle": [
"re3D Gigabot 4 0.8 nozzle",
"re3D Gigabot 4 XLT 0.8 nozzle",
"re3D Terabot 4 0.8 nozzle"
],
"re3D PETG @0.4 nozzle": [
"re3D Gigabot 4 0.8 nozzle",
"re3D Gigabot 4 XLT 0.8 nozzle",
"re3D Terabot 4 0.8 nozzle"
],
"re3D PLA @0.4 nozzle": [
"re3D Gigabot 4 0.8 nozzle",
"re3D Gigabot 4 XLT 0.8 nozzle",
"re3D Terabot 4 0.8 nozzle"
],
"re3D rPETG @0.8 nozzle": [
"re3D GigabotX 2 1.75 nozzle",
"re3D GigabotX 2 XLT 1.75 nozzle",
"re3D TerabotX 2 1.75 nozzle"
],
"re3D rPP @0.8 nozzle": [
"re3D GigabotX 2 1.75 nozzle",
"re3D GigabotX 2 XLT 1.75 nozzle",
"re3D TerabotX 2 1.75 nozzle"
]
}
}
+154
View File
@@ -11,6 +11,7 @@ commands:
normalize rewrite profile files into their canonical shape
trim delete profile files no <vendor>.json list references
update-index regenerate the *_list sections of <vendor>.json
legacy-compat write the printers user presets keep from an older release
options shared by several commands:
--vendor VENDOR act on one vendor bundle only; repeatable, empty means all
@@ -24,6 +25,9 @@ After adding, renaming or deleting profile files, run:
normalize -> update-index -> generate-id -> check
normalize supplies missing types; update-index registers presets before id
generation.
After renaming filament presets or narrowing their compatible_printers, also
rerun legacy-compat --base <2.4.2 profiles> so user presets made against 2.4.2
keep their printers.
Use trim only for deliberate cleanup, previewed with --dry-run: it judges against
the current index and can delete newly added, unindexed presets.
@@ -3072,6 +3076,131 @@ def fix_variant_arrays(profiles_dir=PROFILES_DIR, vendors=None, dry_run=False, s
return len(changed), errors
# ---------------------------------------------------------------------------
# legacy-compat
# ---------------------------------------------------------------------------
LEGACY_COMPAT_PATH = os.path.normpath(
os.path.join(SCRIPTS_DIR, "..", "resources", "info", "legacy_compatible_printers.json"))
def _renamed_from(data):
"""A preset's renamed_from names. Profiles write one ';'-separated string, as the
loader's unescape_strings_cstyle reads it; none of them quote or escape a name."""
value = data.get("renamed_from") or []
return [n for v in _as_list(value) for n in v.split(";") if n]
def _flatten_presets(profiles_dir):
"""Every bundle's composed filament and printer presets, for legacy-compat.
Returns (filaments, printers): filaments maps (vendor, name) to a dict with the
resolved compatible_printers, filament_id, extruder variants, renamed_from and
whether it is instantiated; printers maps each instantiated printer name to a
dict with its renamed_from and extruder variants. instantiation is read from the
preset's own file, as the loader requires every file to state it.
"""
def instantiated(data):
return str(data.get("instantiation", "")).lower() == "true"
ofl = load_vendor_configs(profiles_dir, OFL)["filament"]
filaments, printers = {}, {}
for vendor in list_vendor_names(profiles_dir):
configs = load_vendor_configs(profiles_dir, vendor)
cache = {}
for name, (_rel, data) in configs["filament"].items():
config = compose_config(name, configs["filament"], ofl, cache, vendor == OFL)
filaments[(vendor, name)] = {
"compatible_printers": set(_as_list(config.get("compatible_printers", ([],))[0])),
"filament_id": config.get("filament_id", (None,))[0],
"variants": set(_as_list(config.get("filament_extruder_variant", ([],))[0])),
"instantiation": instantiated(data),
"renamed_from": _renamed_from(data),
}
cache = {}
for name, (_rel, data) in configs["machine"].items():
if instantiated(data):
config = compose_config(name, configs["machine"], {}, cache)
printers[name] = {
"renamed_from": _renamed_from(data),
"variants": set(_as_list(config.get("printer_extruder_variant", ([],))[0])),
}
return filaments, printers
def legacy_compatible_printers(base_dir, profiles_dir=PROFILES_DIR):
"""Printers each current system filament preset covered in the base release
but no longer lists, kept only where a current preset with the same
filament_id still covers that printer.
User presets store only their diff, so they inherit their parent's
compatible_printers; when a profile change narrows that list, a user preset
made against the base release disappears from printers it was used on. The
loader adds these printers back to such user presets. Requiring a same-id
successor leaves out printers a filament was deliberately taken off, and
requiring a shared extruder variant keeps a printer from picking up another
variant's values.
Keyed by the current preset name: the loader resolves a renamed parent
before the map is consulted. Printer names are translated through the
printers' renamed_from. Returns {preset name: sorted printer names}.
"""
old_filaments, _ = _flatten_presets(base_dir)
new_filaments, new_printers = _flatten_presets(profiles_dir)
renamed_printer = {old: new for new, rec in new_printers.items() for old in rec["renamed_from"]}
old_by_name = {}
for (vendor, name), rec in old_filaments.items():
old_by_name.setdefault(name, []).append((vendor, rec))
covering = {} # filament_id -> printers some current instantiated preset covers
for rec in new_filaments.values():
if rec["instantiation"] and rec["filament_id"]:
covering.setdefault(rec["filament_id"], set()).update(rec["compatible_printers"])
def shares_variant(filament, printer):
variants = new_printers[printer]["variants"]
return not filament["variants"] or not variants or bool(filament["variants"] & variants)
result = {}
for (vendor, name), rec in sorted(new_filaments.items()):
# An empty list means every printer, so nothing can have been lost.
if not rec["instantiation"] or not rec["compatible_printers"]:
continue
old_printers = set()
for old_name in [name] + rec["renamed_from"]:
candidates = old_by_name.get(old_name, [])
same_vendor = [r for v, r in candidates if v == vendor]
for old in same_vendor or [r for _, r in candidates]:
old_printers |= old["compatible_printers"]
old_printers = {renamed_printer.get(p, p) for p in old_printers}
lost = old_printers - rec["compatible_printers"]
lost &= covering.get(rec["filament_id"], set()) & set(new_printers)
lost = {p for p in lost if shares_variant(rec, p)}
if lost:
result[name] = sorted(lost)
return result
def run_legacy_compat(base_dir, profiles_dir, output, check):
presets = legacy_compatible_printers(base_dir, profiles_dir)
if check:
try:
with open(output, encoding="utf-8") as f:
current = json.load(f).get("presets")
except (OSError, ValueError, AttributeError):
current = None
if current != presets:
print_error(f"{output} is out of date; rerun legacy-compat --base {base_dir}")
return 1
print_success(f"{output} is up to date")
return 0
with open(output, "w", encoding="utf-8", newline="\n") as f:
f.write(json.dumps({"presets": presets}, indent=4, sort_keys=True, ensure_ascii=False) + "\n")
print_info(f"wrote {len(presets)} presets / {sum(map(len, presets.values()))} printers to {output}")
return 0
# ---------------------------------------------------------------------------
# CLI
# ---------------------------------------------------------------------------
@@ -3093,11 +3222,17 @@ examples:
preview resizing the variant arrays check rejects in that bundle
orca_profile_tool.py check --strict --vendor BBL
also hold every preset's inherited variant arrays to its own width
orca_profile_tool.py legacy-compat --base /tmp/v2.4.2/resources/profiles
rewrite resources/info/legacy_compatible_printers.json against 2.4.2's
profiles (git archive v2.4.2 resources/profiles | tar -x -C /tmp/v2.4.2)
after adding, renaming or deleting profile files, run in this order:
normalize -> update-index -> generate-id -> check
normalize supplies missing types; update-index registers presets before id
generation.
After renaming filament presets or narrowing their compatible_printers, also
rerun legacy-compat --base <2.4.2 profiles> so user presets made against 2.4.2
keep their printers.
Use trim only for deliberate cleanup, previewed with --dry-run: it judges against
the current index and can delete newly added, unindexed presets.
"""
@@ -3227,6 +3362,22 @@ def build_parser():
"Use trim only for deliberate unindexed-file cleanup, previewed with\n"
"--dry-run; it can also delete newly authored presets.")
legacy_cmd = add(
"legacy-compat", [profiles_opt],
"write the printers user presets keep from an older release",
"Compare the tree with an older release's profiles and write, per current\n"
"filament preset, the printers it covered then and no longer lists, where a\n"
"preset with the same filament_id still covers them. The loader adds these\n"
"to user presets that inherit the preset, so a narrowed compatible_printers\n"
"does not hide them on printers they were made for.")
legacy_cmd.add_argument("--base", required=True, metavar="DIR",
help="the older release's resources/profiles directory")
legacy_cmd.add_argument("--output", default=LEGACY_COMPAT_PATH, metavar="FILE",
help="map to write (default: resources/info/"
"legacy_compatible_printers.json)")
legacy_cmd.add_argument("--check", action="store_true",
help="fail if the map differs from what --base implies; write nothing")
return parser
@@ -3260,6 +3411,9 @@ def main(argv=None):
return run_generate_id(profiles_dir, vendors, args.filament_id, args.setting_id,
args.dry_run)
if args.command == "legacy-compat":
return run_legacy_compat(args.base, profiles_dir, args.output, args.check)
if args.command == "fix-variant":
_changed, errors = fix_variant_arrays(profiles_dir, vendors, dry_run=args.dry_run,
strict=args.strict)
+91
View File
@@ -1258,6 +1258,97 @@ class TestVariantNames(TreeCase):
self.assertIn('holds the legacy variant "Direct Drive Normal"', out)
# ---------------------------------------------------------------------------
# legacy-compat
# ---------------------------------------------------------------------------
class TestLegacyCompat(unittest.TestCase):
"""A base release and the current tree, each with one vendor."""
def setUp(self):
self.base, self.cur = Tree(), Tree()
self.addCleanup(self.base.cleanup)
self.addCleanup(self.cur.cleanup)
@staticmethod
def printer(tree, name, **extra):
tree.write("V", f"machine/{name}.json",
{"type": "machine", "name": name, "instantiation": "true", **extra})
tree.index("V", "machine", name, f"machine/{name}.json")
@staticmethod
def filament(tree, name, printers, filament_id="OFpetg01", **extra):
tree.write("V", f"filament/{name}.json",
{"type": "filament", "name": name, "instantiation": "true",
"filament_id": filament_id, "compatible_printers": printers, **extra})
tree.index("V", "filament", name, f"filament/{name}.json")
def generate(self):
return apt.legacy_compatible_printers(self.base.profiles, self.cur.profiles)
def test_renamed_and_narrowed_preset_keeps_printers_a_same_id_sibling_covers(self):
for tree in (self.base, self.cur):
for p in ("A 0.4", "A 0.6", "B 0.4"):
self.printer(tree, p)
self.filament(self.base, "PETG @A-all", ["A 0.4", "A 0.6", "B 0.4"])
self.filament(self.cur, "PETG @V A-all", ["A 0.6"], renamed_from="PETG @A-all;PETG A-all")
self.filament(self.cur, "PETG @A 0.4", ["A 0.4"])
self.assertEqual(self.generate(), {"PETG @V A-all": ["A 0.4"]})
def test_printer_without_a_successor_is_left_out(self):
for tree in (self.base, self.cur):
for p in ("A 0.4", "A 0.6"):
self.printer(tree, p)
self.filament(self.base, "PETG @A", ["A 0.4", "A 0.6"])
self.filament(self.cur, "PETG @A", ["A 0.6"])
self.filament(self.cur, "Other @A", ["A 0.4"], filament_id="OFother1")
self.assertEqual(self.generate(), {})
def test_printer_names_follow_printer_renames(self):
self.printer(self.base, "Old 0.4")
self.printer(self.base, "A 0.6")
self.printer(self.cur, "New 0.4", renamed_from="Old 0.4")
self.printer(self.cur, "A 0.6")
self.filament(self.base, "PETG @A", ["Old 0.4", "A 0.6"])
self.filament(self.cur, "PETG @A", ["A 0.6"])
self.filament(self.cur, "PETG @New", ["New 0.4"])
self.assertEqual(self.generate(), {"PETG @A": ["New 0.4"]})
def test_printer_without_a_shared_extruder_variant_is_left_out(self):
for tree in (self.base, self.cur):
self.printer(tree, "Direct 0.4", printer_extruder_variant=["Direct Drive Standard"])
self.printer(tree, "Bowden 0.4", printer_extruder_variant=["Bowden Standard"])
self.filament(self.base, "PETG @all", ["Direct 0.4", "Bowden 0.4"])
self.filament(self.cur, "PETG @all", ["Direct 0.4"],
filament_extruder_variant=["Direct Drive Standard"])
self.filament(self.cur, "PETG @Bowden", ["Bowden 0.4"])
self.assertEqual(self.generate(), {})
def test_preset_now_listing_no_printer_is_skipped(self):
for tree in (self.base, self.cur):
self.printer(tree, "A 0.4")
self.filament(self.base, "PETG @A", ["A 0.4"])
self.filament(self.cur, "PETG @A", [])
self.assertEqual(self.generate(), {})
def test_check_passes_on_a_current_map_and_fails_on_a_stale_one(self):
for tree in (self.base, self.cur):
for p in ("A 0.4", "A 0.6"):
self.printer(tree, p)
self.filament(self.base, "PETG @A", ["A 0.4", "A 0.6"])
self.filament(self.cur, "PETG @A", ["A 0.6"])
self.filament(self.cur, "PETG @A 0.4", ["A 0.4"])
output = os.path.join(self.cur.dir, "map.json")
argv = ["legacy-compat", "--base", self.base.profiles, "--profiles", self.cur.profiles,
"--output", output]
with contextlib.redirect_stdout(io.StringIO()):
self.assertEqual(apt.main(argv), 0)
self.assertEqual(apt.main(argv + ["--check"]), 0)
with open(output, "w", encoding="utf-8") as f:
json.dump({"presets": {}}, f)
self.assertEqual(apt.main(argv + ["--check"]), 1)
class TestDispatch(TreeCase):
def test_each_command_reaches_its_own_writer(self):
self.t.write("V", "filament/A.json", {"type": "filament", "name": "A"})
+47 -1
View File
@@ -932,10 +932,14 @@ bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const Pre
return true;
}
}
const std::vector<std::string> &legacy = preset.preset.legacy_compatible_printers;
auto is_legacy_printer = [&legacy](const std::string &name) { return std::find(legacy.begin(), legacy.end(), name) != legacy.end(); };
return preset.preset.is_default || active_printer.preset.name.empty() || !has_compatible_printers ||
std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.preset.name) !=
compatible_printers->values.end() ||
(!active_printer.preset.is_system && is_compatible_with_parent_printer(preset, active_printer));
(!active_printer.preset.is_system && is_compatible_with_parent_printer(preset, active_printer)) ||
is_legacy_printer(active_printer.preset.name) ||
(!active_printer.preset.is_system && is_legacy_printer(active_printer.preset.inherits()));
}
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer)
@@ -2728,6 +2732,42 @@ void PresetCollection::update_after_user_presets_loaded()
return;
}
const Preset *PresetCollection::system_parent_with_inherited_printers(const Preset &preset) const
{
if (!preset.is_user() || preset.inherits().empty())
return nullptr;
const Preset *parent = get_preset_parent(preset);
if (parent == nullptr || !parent->is_system)
return nullptr;
// A user preset that sets its own compatible_printers keeps exactly those.
const auto *own = preset.config.option<ConfigOptionStrings>("compatible_printers");
const auto *inherited = parent->config.option<ConfigOptionStrings>("compatible_printers");
return own != nullptr && inherited != nullptr && own->values == inherited->values ? parent : nullptr;
}
void PresetCollection::set_legacy_compatible_printers(const std::map<std::string, std::vector<std::string>> &printers_by_parent)
{
lock();
for (Preset &preset : m_presets) {
preset.legacy_compatible_printers.clear();
const Preset *parent = system_parent_with_inherited_printers(preset);
if (parent == nullptr)
continue;
// The map names the parent as it was when the map was written; a later rename keeps that name in renamed_from.
auto it = printers_by_parent.find(parent->name);
for (auto old_name = parent->renamed_from.begin(); it == printers_by_parent.end() && old_name != parent->renamed_from.end(); ++old_name)
it = printers_by_parent.find(*old_name);
if (it == printers_by_parent.end())
continue;
preset.legacy_compatible_printers = it->second;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": user preset " << preset.name << " keeps " << it->second.size()
<< " printer(s) its parent " << parent->name << " listed in an older release";
}
if (m_idx_selected < m_presets.size() && m_edited_preset.name == m_presets[m_idx_selected].name)
m_edited_preset.legacy_compatible_printers = m_presets[m_idx_selected].legacy_compatible_printers;
unlock();
}
//BBS: validate_preset
bool PresetCollection::validate_preset(const std::string &preset_name, std::string &inherit_name)
{
@@ -3081,6 +3121,7 @@ bool PresetCollection::clone_presets(std::vector<Preset const *> const &presets,
preset.vendor = nullptr;
preset.renamed_from.clear();
preset.m_excluded_from.clear();
preset.legacy_compatible_printers.clear();
preset.setting_id.clear();
preset.inherits().clear();
preset.is_default = false;
@@ -3218,6 +3259,9 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
preset.m_excluded_from.clear();
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": save preset %1% , with detach")%new_name;
}
// Legacy printers belong only to a preset that still inherits its system parent's printer list.
if (system_parent_with_inherited_printers(preset) == nullptr)
preset.legacy_compatible_printers.clear();
//BBS: add lock logic for sync preset in background
if (m_type == Preset::TYPE_PRINT)
@@ -3270,6 +3314,8 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
}
else
preset.is_project_embedded = false;
if (system_parent_with_inherited_printers(preset) == nullptr)
preset.legacy_compatible_printers.clear();
if (m_type == Preset::TYPE_PRINT)
preset.config.option<ConfigOptionString>("print_settings_id", true)->value = new_name;
else if (m_type == Preset::TYPE_FILAMENT)
+13
View File
@@ -311,6 +311,10 @@ public:
// certain printer models defined in the vendor profile as well, in this case we want to hide this generic preset for these printer models.
std::set<std::string> m_excluded_from;
// Printers a user filament preset is also compatible with because its system parent listed them in
// an older release; see PresetCollection::set_legacy_compatible_printers().
std::vector<std::string> legacy_compatible_printers;
// Orca: flag to indicate if this preset is from Orca Filament Library
bool m_from_orca_filament_lib = false;
@@ -601,6 +605,11 @@ public:
void save_user_presets(const std::string& dir_path, const std::string& type, std::map<std::string, std::string>& need_to_delete_list);
bool load_user_preset(std::string name, std::map<std::string, std::string> preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, const PresetOrigin &load_origin = PresetOrigin(PresetOrigin::Kind::User));
void update_after_user_presets_loaded();
// User presets store only their diff, so a user preset inherits its system parent's compatible_printers
// and disappears from a printer once a profile update narrows that list. Give each user preset that
// inherits the list the printers its parent covered in an older release (printers_by_parent, keyed by the
// parent's current name), so it keeps showing on the printers it was made for.
void set_legacy_compatible_printers(const std::map<std::string, std::vector<std::string>> &printers_by_parent);
//BBS: get user presets
int get_user_presets(PresetBundle *preset_bundle, std::vector<Preset> &result_presets);
void set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo, long long update_time, const std::string& user_id);
@@ -893,6 +902,10 @@ public:
size_t num_default_presets() { return m_num_default_presets; }
protected:
// The system parent of a user preset whose compatible_printers is the parent's, or nullptr: the presets
// set_legacy_compatible_printers() gives legacy printers to.
const Preset* system_parent_with_inherited_printers(const Preset &preset) const;
PresetCollection() = default;
// Deleted by the std::recursive_mutex member. PresetBundle copies by assignment.
PresetCollection(const PresetCollection &other) = delete;
+32
View File
@@ -24,6 +24,7 @@
#include <memory>
#include <initializer_list>
#include <map>
#include <mutex>
#include <iterator>
#include <functional>
#include <limits>
@@ -96,6 +97,34 @@ using json = nlohmann::json;
namespace Slic3r {
// Per current system filament preset, the printers it listed in an older release and no longer does
// (resources/info/legacy_compatible_printers.json, written by orca_profile_tool.py legacy-compat).
// The file ships with the build, so it is read once it opens; until then (e.g. presets loaded before
// resources_dir() is set) every call tries again and there are no legacy printers.
static std::map<std::string, std::vector<std::string>> legacy_compatible_printers()
{
static std::mutex mutex;
static std::map<std::string, std::vector<std::string>> printers_by_parent;
static bool read = false;
std::lock_guard<std::mutex> guard(mutex);
if (!read) {
const fs::path path = fs::path(resources_dir()) / "info" / "legacy_compatible_printers.json";
boost::nowide::ifstream in(path.string());
if (!in) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": " << path.string() << " not found";
return {};
}
read = true;
try {
printers_by_parent = json::parse(in).at("presets").get<std::map<std::string, std::vector<std::string>>>();
} catch (const std::exception &err) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": can not read " << path.string() << ": " << err.what();
}
}
return printers_by_parent;
}
// Project-level options imported from a loaded 3MF into project_config. s_project_options_published
// below is the reduced subset that crosses over in "published" 3MF mode; keep both in sync.
// s_project_options_published additionally carries wipe_tower_rotation_angle, which normal
@@ -889,6 +918,7 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward
// raw vendor-JSON references instead of the silently-repaired ones.
if (!validation_mode)
this->normalize_compatible_presets();
filaments.set_legacy_compatible_printers(legacy_compatible_printers());
this->update_multi_material_filament_presets();
this->update_compatible(PresetSelectCompatibleType::Never);
@@ -1517,6 +1547,7 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &
// Rewrite renamed compatible references in synced user presets before compatibility is evaluated.
this->normalize_compatible_presets();
filaments.set_legacy_compatible_printers(legacy_compatible_printers());
this->update_multi_material_filament_presets();
this->update_compatible(PresetSelectCompatibleType::Never);
@@ -2523,6 +2554,7 @@ PresetsConfigSubstitutions PresetBundle::update_subscribed_presets(
// Rewrite renamed compatible references in synced user presets before compatibility is evaluated.
this->normalize_compatible_presets();
filaments.set_legacy_compatible_printers(legacy_compatible_printers());
this->update_multi_material_filament_presets();
this->update_compatible(PresetSelectCompatibleType::Never);
+4 -1
View File
@@ -1,4 +1,5 @@
#pragma once
#ifndef libslic3r_Timer_hpp_
#define libslic3r_Timer_hpp_
#include "TriangleMesh.hpp"
@@ -9,3 +10,5 @@ public:
static TriangleMesh smooth_triangle_mesh(const TriangleMesh &mesh,bool& ok);
};
} // namespace Slic3r
#endif // libslic3r_Timer_hpp_
+4 -1
View File
@@ -1,4 +1,5 @@
#pragma once
#ifndef slic3r_GUI_SingleChoice_hpp_
#define slic3r_GUI_SingleChoice_hpp_
#include "GUI_Utils.hpp"
#include "Plater.hpp"
@@ -32,3 +33,5 @@ private:
};
}} // namespace Slic3r::GUI
#endif
@@ -7161,3 +7161,89 @@ TEST_CASE("A user filament whose derived compatible printer cannot be written ba
CHECK(read_file(file) == before);
}
#endif
TEST_CASE("A user filament keeps the printers its narrowed system parent listed in an older release", "[Preset][Bundle]")
{
PresetBundle bundle;
PresetCollection &filaments = bundle.filaments;
const std::string parent = "Generic PETG @Creality K1-all";
// load_preset inserts in sorted order, so presets are looked up again rather than held by reference.
auto set_printers = [&filaments](const std::string &name, std::vector<std::string> printers) {
filaments.find_preset(name)->config.option<ConfigOptionStrings>("compatible_printers", true)->values = std::move(printers);
};
add_inmemory_preset(filaments, parent).is_system = true;
add_inmemory_preset(filaments, "My PETG", parent);
add_inmemory_preset(filaments, "My PETG own list", parent);
set_printers(parent, { "Creality K1C 0.6 nozzle" });
set_printers("My PETG", { "Creality K1C 0.6 nozzle" });
set_printers("My PETG own list", { "Creality K1C 0.6 nozzle", "Creality K1C 0.8 nozzle" });
filaments.set_legacy_compatible_printers({ { parent, { "Creality K1C 0.4 nozzle" } } });
auto compatible = [&filaments](const std::string &filament, const Preset &printer) {
return is_compatible_with_printer(PresetWithVendorProfile(*filaments.find_preset(filament), nullptr),
PresetWithVendorProfile(printer, nullptr));
};
Preset k1c_04(Preset::TYPE_PRINTER, "Creality K1C 0.4 nozzle");
k1c_04.is_system = true;
Preset k1_max(Preset::TYPE_PRINTER, "Creality K1 Max 0.4 nozzle");
k1_max.is_system = true;
Preset my_k1c(Preset::TYPE_PRINTER, "My K1C");
my_k1c.config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS, true)->value = "Creality K1C 0.4 nozzle";
CHECK(compatible("My PETG", k1c_04));
CHECK(compatible("My PETG", my_k1c));
CHECK_FALSE(compatible("My PETG", k1_max));
// The system preset itself and a user preset with its own list keep exactly their lists.
CHECK_FALSE(compatible(parent, k1c_04));
CHECK_FALSE(compatible("My PETG own list", k1c_04));
// A parent renamed after the map was written is still found under its old name.
add_inmemory_preset(filaments, "Generic PETG @Creality K1 renamed").is_system = true;
add_inmemory_preset(filaments, "My renamed PETG", "Generic PETG @Creality K1 renamed");
set_renamed_from(filaments, "Generic PETG @Creality K1 renamed", { parent });
set_printers("Generic PETG @Creality K1 renamed", { "Creality K1C 0.6 nozzle" });
set_printers("My renamed PETG", { "Creality K1C 0.6 nozzle" });
filaments.set_legacy_compatible_printers({ { parent, { "Creality K1C 0.4 nozzle" } } });
CHECK(compatible("My renamed PETG", k1c_04));
}
TEST_CASE("A saved user filament keeps its legacy printers only while it inherits its parent's printer list", "[Preset][Bundle]")
{
ScopedTemporaryDir temp_dir;
PresetBundle bundle;
PresetCollection &filaments = bundle.filaments;
const std::string parent = "Generic PETG @Creality K1-all";
add_inmemory_preset(filaments, parent).is_system = true;
filaments.find_preset(parent)->config.option<ConfigOptionStrings>("compatible_printers", true)->values = { "Creality K1C 0.6 nozzle" };
// Like a real user preset, the file states only its diff, so the printer list comes from the parent.
fs::create_directories(temp_dir.path() / PRESET_FILAMENT_NAME);
std::ofstream((temp_dir.path() / PRESET_FILAMENT_NAME / "My PETG.json").string())
<< R"({"type":"filament","name":"My PETG","from":"User","version":"1.0.0","inherits":")" << parent << R"("})";
PresetsConfigSubstitutions substitutions;
filaments.load_presets(temp_dir.path().string(), PRESET_FILAMENT_NAME, substitutions,
ForwardCompatibilitySubstitutionRule::EnableSilent);
filaments.set_legacy_compatible_printers({ { parent, { "Creality K1C 0.4 nozzle" } } });
const std::vector<std::string> legacy { "Creality K1C 0.4 nozzle" };
REQUIRE(filaments.find_preset("My PETG")->legacy_compatible_printers == legacy);
auto save_from_my_petg = [&filaments](const std::string &name, bool detach) {
filaments.select_preset_by_name("My PETG", true);
filaments.save_current_preset(name, detach);
return filaments.find_preset(name)->legacy_compatible_printers;
};
CHECK(save_from_my_petg("My PETG copy", false) == legacy);
CHECK(save_from_my_petg("My PETG detached", true).empty());
// A clone is detached from the parent, as "Create filament" makes for another printer.
std::vector<std::string> failures;
REQUIRE(filaments.clone_presets({ filaments.find_preset("My PETG") }, failures,
[](Preset &preset, Preset::Type &) { preset.name = "My PETG clone"; }));
CHECK(filaments.find_preset("My PETG clone")->legacy_compatible_printers.empty());
filaments.select_preset_by_name("My PETG", true);
filaments.get_edited_preset().config.option<ConfigOptionStrings>("compatible_printers")->values = { "Creality K1C 0.8 nozzle" };
filaments.save_current_preset("My PETG", false);
CHECK(filaments.find_preset("My PETG")->legacy_compatible_printers.empty());
}