diff --git a/resources/icons/eye_closed.svg b/resources/icons/eye_closed.svg new file mode 100644 index 0000000000..127d53ca3b --- /dev/null +++ b/resources/icons/eye_closed.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/resources/icons/eye_open.svg b/resources/icons/eye_open.svg new file mode 100644 index 0000000000..a87cf3a83f --- /dev/null +++ b/resources/icons/eye_open.svg @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/resources/localization/PrusaSlicer.pot b/resources/localization/PrusaSlicer.pot index 30c41434f8..bdad4a76d8 100644 --- a/resources/localization/PrusaSlicer.pot +++ b/resources/localization/PrusaSlicer.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-20 15:59+0200\n" +"POT-Creation-Date: 2019-08-06 09:54+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,46 +17,46 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: src/slic3r/GUI/AboutDialog.cpp:39 src/slic3r/GUI/AboutDialog.cpp:286 +#: src/slic3r/GUI/AboutDialog.cpp:39 src/slic3r/GUI/AboutDialog.cpp:289 msgid "Portions copyright" msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:122 src/slic3r/GUI/AboutDialog.cpp:251 +#: src/slic3r/GUI/AboutDialog.cpp:125 src/slic3r/GUI/AboutDialog.cpp:254 msgid "Copyright" msgstr "" #. TRN "Slic3r _is licensed under the_ License" -#: src/slic3r/GUI/AboutDialog.cpp:124 +#: src/slic3r/GUI/AboutDialog.cpp:127 msgid "" "License agreements of all following programs (libraries) are part of " "application license agreement" msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:194 +#: src/slic3r/GUI/AboutDialog.cpp:197 #, possible-c-format msgid "About %s" msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:226 src/slic3r/GUI/MainFrame.cpp:59 +#: src/slic3r/GUI/AboutDialog.cpp:229 src/slic3r/GUI/MainFrame.cpp:60 msgid "Version" msgstr "" #. TRN "Slic3r _is licensed under the_ License" -#: src/slic3r/GUI/AboutDialog.cpp:253 +#: src/slic3r/GUI/AboutDialog.cpp:256 msgid "is licensed under the" msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:254 +#: src/slic3r/GUI/AboutDialog.cpp:257 msgid "GNU Affero General Public License, version 3" msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:255 +#: src/slic3r/GUI/AboutDialog.cpp:258 msgid "" "PrusaSlicer is based on Slic3r by Alessandro Ranellucci and the RepRap " "community." msgstr "" -#: src/slic3r/GUI/AboutDialog.cpp:256 +#: src/slic3r/GUI/AboutDialog.cpp:259 msgid "" "Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, " "Petr Ledvina, Joseph Lenox, Y. Sapir, Mike Sheldrake, Vojtech Bubnik and " @@ -64,8 +64,9 @@ msgid "" msgstr "" #: src/slic3r/GUI/BackgroundSlicingProcess.cpp:92 -#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:408 -msgid "Copying of the temporary G-code to the output G-code failed" +msgid "" +"Copying of the temporary G-code to the output G-code failed. Maybe the SD " +"card is write locked?" msgstr "" #: src/slic3r/GUI/BackgroundSlicingProcess.cpp:93 @@ -86,115 +87,152 @@ msgstr "" msgid "Masked SLA file exported to %1%" msgstr "" +#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:408 +msgid "Copying of the temporary G-code to the output G-code failed" +msgstr "" + #: src/slic3r/GUI/BackgroundSlicingProcess.cpp:417 msgid "Scheduling upload to `%1%`. See Window -> Print Host Upload Queue" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:60 +#: src/slic3r/GUI/BedShapeDialog.cpp:65 msgid "Shape" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:68 +#: src/slic3r/GUI/BedShapeDialog.cpp:72 msgid "Rectangular" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:72 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:232 src/slic3r/GUI/Plater.cpp:136 -#: src/slic3r/GUI/Tab.cpp:2294 +#: src/slic3r/GUI/BedShapeDialog.cpp:76 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:391 src/slic3r/GUI/Plater.cpp:145 +#: src/slic3r/GUI/Tab.cpp:2469 msgid "Size" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:73 +#: src/slic3r/GUI/BedShapeDialog.cpp:77 msgid "Size in X and Y of the rectangular plate." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:79 +#: src/slic3r/GUI/BedShapeDialog.cpp:83 msgid "Origin" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:80 +#: src/slic3r/GUI/BedShapeDialog.cpp:84 msgid "" "Distance of the 0,0 G-code coordinate from the front left corner of the " "rectangle." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:84 +#: src/slic3r/GUI/BedShapeDialog.cpp:88 msgid "Circular" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:87 src/slic3r/GUI/ConfigWizard.cpp:118 -#: src/slic3r/GUI/ConfigWizard.cpp:565 src/slic3r/GUI/ConfigWizard.cpp:579 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:229 -#: src/slic3r/GUI/WipeTowerDialog.cpp:84 src/libslic3r/PrintConfig.cpp:60 -#: src/libslic3r/PrintConfig.cpp:67 src/libslic3r/PrintConfig.cpp:76 -#: src/libslic3r/PrintConfig.cpp:211 src/libslic3r/PrintConfig.cpp:286 -#: src/libslic3r/PrintConfig.cpp:294 src/libslic3r/PrintConfig.cpp:344 -#: src/libslic3r/PrintConfig.cpp:354 src/libslic3r/PrintConfig.cpp:474 -#: src/libslic3r/PrintConfig.cpp:485 src/libslic3r/PrintConfig.cpp:503 -#: src/libslic3r/PrintConfig.cpp:681 src/libslic3r/PrintConfig.cpp:1201 -#: src/libslic3r/PrintConfig.cpp:1262 src/libslic3r/PrintConfig.cpp:1280 -#: src/libslic3r/PrintConfig.cpp:1298 src/libslic3r/PrintConfig.cpp:1350 -#: src/libslic3r/PrintConfig.cpp:1360 src/libslic3r/PrintConfig.cpp:1481 -#: src/libslic3r/PrintConfig.cpp:1489 src/libslic3r/PrintConfig.cpp:1530 -#: src/libslic3r/PrintConfig.cpp:1538 src/libslic3r/PrintConfig.cpp:1548 -#: src/libslic3r/PrintConfig.cpp:1556 src/libslic3r/PrintConfig.cpp:1564 -#: src/libslic3r/PrintConfig.cpp:1647 src/libslic3r/PrintConfig.cpp:1863 -#: src/libslic3r/PrintConfig.cpp:1933 src/libslic3r/PrintConfig.cpp:1967 -#: src/libslic3r/PrintConfig.cpp:2160 src/libslic3r/PrintConfig.cpp:2167 -#: src/libslic3r/PrintConfig.cpp:2174 src/libslic3r/PrintConfig.cpp:2204 -#: src/libslic3r/PrintConfig.cpp:2214 src/libslic3r/PrintConfig.cpp:2224 -#: src/libslic3r/PrintConfig.cpp:2332 src/libslic3r/PrintConfig.cpp:2407 -#: src/libslic3r/PrintConfig.cpp:2416 src/libslic3r/PrintConfig.cpp:2425 -#: src/libslic3r/PrintConfig.cpp:2435 src/libslic3r/PrintConfig.cpp:2479 -#: src/libslic3r/PrintConfig.cpp:2489 src/libslic3r/PrintConfig.cpp:2508 -#: src/libslic3r/PrintConfig.cpp:2518 src/libslic3r/PrintConfig.cpp:2527 -#: src/libslic3r/PrintConfig.cpp:2545 src/libslic3r/PrintConfig.cpp:2560 -#: src/libslic3r/PrintConfig.cpp:2574 src/libslic3r/PrintConfig.cpp:2587 -#: src/libslic3r/PrintConfig.cpp:2597 +#: src/slic3r/GUI/BedShapeDialog.cpp:91 src/slic3r/GUI/ConfigWizard.cpp:118 +#: src/slic3r/GUI/ConfigWizard.cpp:571 src/slic3r/GUI/ConfigWizard.cpp:585 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:388 +#: src/slic3r/GUI/WipeTowerDialog.cpp:84 src/slic3r/GUI/wxExtensions.cpp:486 +#: src/libslic3r/PrintConfig.cpp:70 src/libslic3r/PrintConfig.cpp:77 +#: src/libslic3r/PrintConfig.cpp:86 src/libslic3r/PrintConfig.cpp:220 +#: src/libslic3r/PrintConfig.cpp:295 src/libslic3r/PrintConfig.cpp:303 +#: src/libslic3r/PrintConfig.cpp:353 src/libslic3r/PrintConfig.cpp:363 +#: src/libslic3r/PrintConfig.cpp:488 src/libslic3r/PrintConfig.cpp:499 +#: src/libslic3r/PrintConfig.cpp:517 src/libslic3r/PrintConfig.cpp:695 +#: src/libslic3r/PrintConfig.cpp:1215 src/libslic3r/PrintConfig.cpp:1276 +#: src/libslic3r/PrintConfig.cpp:1294 src/libslic3r/PrintConfig.cpp:1312 +#: src/libslic3r/PrintConfig.cpp:1364 src/libslic3r/PrintConfig.cpp:1374 +#: src/libslic3r/PrintConfig.cpp:1495 src/libslic3r/PrintConfig.cpp:1503 +#: src/libslic3r/PrintConfig.cpp:1544 src/libslic3r/PrintConfig.cpp:1552 +#: src/libslic3r/PrintConfig.cpp:1562 src/libslic3r/PrintConfig.cpp:1570 +#: src/libslic3r/PrintConfig.cpp:1578 src/libslic3r/PrintConfig.cpp:1661 +#: src/libslic3r/PrintConfig.cpp:1878 src/libslic3r/PrintConfig.cpp:1948 +#: src/libslic3r/PrintConfig.cpp:1982 src/libslic3r/PrintConfig.cpp:2176 +#: src/libslic3r/PrintConfig.cpp:2183 src/libslic3r/PrintConfig.cpp:2190 +#: src/libslic3r/PrintConfig.cpp:2220 src/libslic3r/PrintConfig.cpp:2230 +#: src/libslic3r/PrintConfig.cpp:2240 src/libslic3r/PrintConfig.cpp:2403 +#: src/libslic3r/PrintConfig.cpp:2478 src/libslic3r/PrintConfig.cpp:2487 +#: src/libslic3r/PrintConfig.cpp:2496 src/libslic3r/PrintConfig.cpp:2506 +#: src/libslic3r/PrintConfig.cpp:2550 src/libslic3r/PrintConfig.cpp:2560 +#: src/libslic3r/PrintConfig.cpp:2572 src/libslic3r/PrintConfig.cpp:2592 +#: src/libslic3r/PrintConfig.cpp:2602 src/libslic3r/PrintConfig.cpp:2613 +#: src/libslic3r/PrintConfig.cpp:2631 src/libslic3r/PrintConfig.cpp:2646 +#: src/libslic3r/PrintConfig.cpp:2660 src/libslic3r/PrintConfig.cpp:2673 +#: src/libslic3r/PrintConfig.cpp:2683 src/libslic3r/PrintConfig.cpp:2704 +#: src/libslic3r/PrintConfig.cpp:2715 src/libslic3r/PrintConfig.cpp:2725 +#: src/libslic3r/PrintConfig.cpp:2735 msgid "mm" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:88 src/libslic3r/PrintConfig.cpp:678 +#: src/slic3r/GUI/BedShapeDialog.cpp:92 src/libslic3r/PrintConfig.cpp:692 msgid "Diameter" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:89 +#: src/slic3r/GUI/BedShapeDialog.cpp:93 msgid "" "Diameter of the print bed. It is assumed that origin (0,0) is located in the " "center." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:93 src/slic3r/GUI/GUI_Preview.cpp:245 +#: src/slic3r/GUI/BedShapeDialog.cpp:97 src/slic3r/GUI/GUI_Preview.cpp:246 #: src/libslic3r/GCode/PreviewData.cpp:175 msgid "Custom" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:97 +#: src/slic3r/GUI/BedShapeDialog.cpp:101 msgid "Load shape from STL..." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:143 +#: src/slic3r/GUI/BedShapeDialog.cpp:154 msgid "Settings" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:316 -msgid "Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):" +#: src/slic3r/GUI/BedShapeDialog.cpp:171 +msgid "Texture" msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:333 src/slic3r/GUI/GUI_ObjectList.cpp:1442 -msgid "Error!" +#: src/slic3r/GUI/BedShapeDialog.cpp:181 src/slic3r/GUI/BedShapeDialog.cpp:249 +msgid "Load..." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:342 +#: src/slic3r/GUI/BedShapeDialog.cpp:189 src/slic3r/GUI/BedShapeDialog.cpp:257 +#: src/slic3r/GUI/Tab.cpp:3204 +msgid "Remove" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:239 +msgid "Model" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:464 +msgid "Choose an STL file to import bed shape from:" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:471 src/slic3r/GUI/BedShapeDialog.cpp:520 +#: src/slic3r/GUI/BedShapeDialog.cpp:543 +msgid "Invalid file format." +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:482 +msgid "Error! Invalid model" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:490 msgid "The selected file contains no geometry." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.cpp:346 +#: src/slic3r/GUI/BedShapeDialog.cpp:494 msgid "" "The selected file contains several disjoint areas. This is not supported." msgstr "" -#: src/slic3r/GUI/BedShapeDialog.hpp:45 src/slic3r/GUI/ConfigWizard.cpp:530 +#: src/slic3r/GUI/BedShapeDialog.cpp:509 +msgid "Choose a file to import bed texture from (PNG/SVG):" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.cpp:532 +msgid "Choose an STL file to import bed model from:" +msgstr "" + +#: src/slic3r/GUI/BedShapeDialog.hpp:59 src/slic3r/GUI/ConfigWizard.cpp:530 msgid "Bed Shape" msgstr "" @@ -268,7 +306,7 @@ msgstr "" msgid "slic3r version" msgstr "" -#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:46 src/slic3r/GUI/Preset.cpp:1282 +#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:46 src/slic3r/GUI/Preset.cpp:1307 msgid "print" msgstr "" @@ -276,11 +314,11 @@ msgstr "" msgid "filaments" msgstr "" -#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:48 src/slic3r/GUI/Preset.cpp:1286 +#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:48 src/slic3r/GUI/Preset.cpp:1311 msgid "printer" msgstr "" -#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:52 src/slic3r/GUI/Tab.cpp:934 +#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:52 src/slic3r/GUI/Tab.cpp:939 msgid "vendor" msgstr "" @@ -329,11 +367,11 @@ msgstr "" msgid "All standard" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:189 src/slic3r/GUI/Tab.cpp:3038 +#: src/slic3r/GUI/ConfigWizard.cpp:189 src/slic3r/GUI/Tab.cpp:3254 msgid "All" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:190 src/slic3r/GUI/Plater.cpp:432 +#: src/slic3r/GUI/ConfigWizard.cpp:190 src/slic3r/GUI/Plater.cpp:470 #: src/libslic3r/GCode/PreviewData.cpp:162 msgid "None" msgstr "" @@ -352,7 +390,7 @@ msgstr "" msgid "Welcome" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:304 src/slic3r/GUI/GUI_App.cpp:713 +#: src/slic3r/GUI/ConfigWizard.cpp:304 src/slic3r/GUI/GUI_App.cpp:747 #, possible-c-format msgid "Run %s" msgstr "" @@ -399,7 +437,7 @@ msgstr "" msgid "Updates" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:415 src/slic3r/GUI/Preferences.cpp:61 +#: src/slic3r/GUI/ConfigWizard.cpp:415 src/slic3r/GUI/Preferences.cpp:69 msgid "Check for application updates" msgstr "" @@ -412,7 +450,7 @@ msgid "" "notification mechanisms, no automatic installation is done." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:425 src/slic3r/GUI/Preferences.cpp:69 +#: src/slic3r/GUI/ConfigWizard.cpp:425 src/slic3r/GUI/Preferences.cpp:77 msgid "Update built-in Presets automatically" msgstr "" @@ -450,7 +488,7 @@ msgstr "" msgid "Firmware Type" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:492 src/slic3r/GUI/Tab.cpp:1957 +#: src/slic3r/GUI/ConfigWizard.cpp:492 src/slic3r/GUI/Tab.cpp:2100 msgid "Firmware" msgstr "" @@ -466,180 +504,183 @@ msgstr "" msgid "Set the shape of your printer's bed." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:547 +#: src/slic3r/GUI/ConfigWizard.cpp:553 msgid "Filament and Nozzle Diameters" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:547 +#: src/slic3r/GUI/ConfigWizard.cpp:553 msgid "Print Diameters" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:561 +#: src/slic3r/GUI/ConfigWizard.cpp:567 msgid "Enter the diameter of your printer's hot end nozzle." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:564 +#: src/slic3r/GUI/ConfigWizard.cpp:570 msgid "Nozzle Diameter:" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:574 +#: src/slic3r/GUI/ConfigWizard.cpp:580 msgid "Enter the diameter of your filament." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:575 +#: src/slic3r/GUI/ConfigWizard.cpp:581 msgid "" "Good precision is required, so use a caliper and do multiple measurements " "along the filament, then compute the average." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:578 +#: src/slic3r/GUI/ConfigWizard.cpp:584 msgid "Filament Diameter:" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:612 +#: src/slic3r/GUI/ConfigWizard.cpp:618 msgid "Extruder and Bed Temperatures" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:612 +#: src/slic3r/GUI/ConfigWizard.cpp:618 msgid "Temperatures" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:628 +#: src/slic3r/GUI/ConfigWizard.cpp:634 msgid "Enter the temperature needed for extruding your filament." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:629 +#: src/slic3r/GUI/ConfigWizard.cpp:635 msgid "A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:632 +#: src/slic3r/GUI/ConfigWizard.cpp:638 msgid "Extrusion Temperature:" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:633 src/slic3r/GUI/ConfigWizard.cpp:647 +#: src/slic3r/GUI/ConfigWizard.cpp:639 src/slic3r/GUI/ConfigWizard.cpp:653 msgid "°C" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:642 +#: src/slic3r/GUI/ConfigWizard.cpp:648 msgid "" "Enter the bed temperature needed for getting your filament to stick to your " "heated bed." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:643 +#: src/slic3r/GUI/ConfigWizard.cpp:649 msgid "" "A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have " "no heated bed." msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:646 +#: src/slic3r/GUI/ConfigWizard.cpp:652 msgid "Bed Temperature:" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1109 +#: src/slic3r/GUI/ConfigWizard.cpp:1115 msgid "Select all standard printers" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1112 +#: src/slic3r/GUI/ConfigWizard.cpp:1118 msgid "< &Back" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1113 +#: src/slic3r/GUI/ConfigWizard.cpp:1119 msgid "&Next >" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1114 +#: src/slic3r/GUI/ConfigWizard.cpp:1120 msgid "&Finish" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1115 src/slic3r/GUI/FirmwareDialog.cpp:147 -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:37 -#: src/slic3r/GUI/ProgressStatusBar.cpp:28 +#: src/slic3r/GUI/ConfigWizard.cpp:1121 src/slic3r/GUI/FirmwareDialog.cpp:151 +#: src/slic3r/GUI/ProgressStatusBar.cpp:27 msgid "Cancel" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1129 +#: src/slic3r/GUI/ConfigWizard.cpp:1135 msgid "Prusa FFF Technology Printers" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1132 +#: src/slic3r/GUI/ConfigWizard.cpp:1138 msgid "Prusa MSLA Technology Printers" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1201 +#: src/slic3r/GUI/ConfigWizard.cpp:1207 msgid "Configuration Assistant" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1202 +#: src/slic3r/GUI/ConfigWizard.cpp:1208 msgid "Configuration &Assistant" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1204 +#: src/slic3r/GUI/ConfigWizard.cpp:1210 msgid "Configuration Wizard" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:1205 +#: src/slic3r/GUI/ConfigWizard.cpp:1211 msgid "Configuration &Wizard" msgstr "" -#: src/slic3r/GUI/Field.cpp:117 +#: src/slic3r/GUI/Field.cpp:125 msgid "default value" msgstr "" -#: src/slic3r/GUI/Field.cpp:120 +#: src/slic3r/GUI/Field.cpp:128 msgid "parameter name" msgstr "" -#: src/slic3r/GUI/Field.cpp:148 +#: src/slic3r/GUI/Field.cpp:139 +msgid "N/A" +msgstr "" + +#: src/slic3r/GUI/Field.cpp:158 #, possible-c-format msgid "%s doesn't support percentage" msgstr "" -#: src/slic3r/GUI/Field.cpp:162 src/slic3r/GUI/Field.cpp:185 +#: src/slic3r/GUI/Field.cpp:174 src/slic3r/GUI/Field.cpp:197 msgid "Invalid numeric input." msgstr "" -#: src/slic3r/GUI/Field.cpp:167 +#: src/slic3r/GUI/Field.cpp:179 msgid "Input value is out of range" msgstr "" -#: src/slic3r/GUI/Field.cpp:193 +#: src/slic3r/GUI/Field.cpp:206 #, possible-c-format msgid "" -"Do you mean %d%% instead of %d %s?\n" -"Select YES if you want to change this value to %d%%, \n" -"or NO if you are sure that %d %s is a correct value." +"Do you mean %s%% instead of %s %s?\n" +"Select YES if you want to change this value to %s%%, \n" +"or NO if you are sure that %s %s is a correct value." msgstr "" -#: src/slic3r/GUI/Field.cpp:196 +#: src/slic3r/GUI/Field.cpp:209 msgid "Parameter validation" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:146 +#: src/slic3r/GUI/FirmwareDialog.cpp:150 msgid "Flash!" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:148 +#: src/slic3r/GUI/FirmwareDialog.cpp:152 msgid "Flashing in progress. Please do not disconnect the printer!" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:192 +#: src/slic3r/GUI/FirmwareDialog.cpp:199 msgid "Flashing failed" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:273 +#: src/slic3r/GUI/FirmwareDialog.cpp:282 msgid "Flashing succeeded!" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:274 +#: src/slic3r/GUI/FirmwareDialog.cpp:283 msgid "Flashing failed. Please see the avrdude log below." msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:275 +#: src/slic3r/GUI/FirmwareDialog.cpp:284 msgid "Flashing cancelled." msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:313 +#: src/slic3r/GUI/FirmwareDialog.cpp:332 #, possible-c-format msgid "" "This firmware hex file does not match the printer model.\n" @@ -650,13 +691,13 @@ msgid "" "Please only continue if you are sure this is the right thing to do." msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:400 src/slic3r/GUI/FirmwareDialog.cpp:436 +#: src/slic3r/GUI/FirmwareDialog.cpp:419 src/slic3r/GUI/FirmwareDialog.cpp:454 #, possible-c-format msgid "" "Multiple %s devices found. Please only connect one at a time for flashing." msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:417 +#: src/slic3r/GUI/FirmwareDialog.cpp:436 #, possible-c-format msgid "" "The %s device was not found.\n" @@ -664,947 +705,1198 @@ msgid "" "connector ..." msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:530 +#: src/slic3r/GUI/FirmwareDialog.cpp:548 #, possible-c-format msgid "The %s device could not have been found" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:608 +#: src/slic3r/GUI/FirmwareDialog.cpp:645 #, possible-c-format msgid "Error accessing port at %s: %s" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:610 +#: src/slic3r/GUI/FirmwareDialog.cpp:647 #, possible-c-format msgid "Error: %s" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:740 +#: src/slic3r/GUI/FirmwareDialog.cpp:777 msgid "Firmware flasher" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:765 +#: src/slic3r/GUI/FirmwareDialog.cpp:802 msgid "Firmware image:" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:768 src/slic3r/GUI/Tab.cpp:1718 -#: src/slic3r/GUI/Tab.cpp:1774 +#: src/slic3r/GUI/FirmwareDialog.cpp:805 src/slic3r/GUI/Tab.cpp:1824 +#: src/slic3r/GUI/Tab.cpp:1880 msgid "Browse" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:770 +#: src/slic3r/GUI/FirmwareDialog.cpp:807 msgid "Serial port:" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:772 +#: src/slic3r/GUI/FirmwareDialog.cpp:809 msgid "Autodetected" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:773 +#: src/slic3r/GUI/FirmwareDialog.cpp:810 msgid "Rescan" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:780 +#: src/slic3r/GUI/FirmwareDialog.cpp:817 msgid "Progress:" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:783 +#: src/slic3r/GUI/FirmwareDialog.cpp:820 msgid "Status:" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:784 +#: src/slic3r/GUI/FirmwareDialog.cpp:821 msgid "Ready" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:804 +#: src/slic3r/GUI/FirmwareDialog.cpp:841 msgid "Advanced: Output log" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:815 +#: src/slic3r/GUI/FirmwareDialog.cpp:852 #: src/slic3r/GUI/PrintHostDialogs.cpp:161 msgid "Close" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:863 +#: src/slic3r/GUI/FirmwareDialog.cpp:903 msgid "" "Are you sure you want to cancel firmware flashing?\n" "This could leave your printer in an unusable state!" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:864 +#: src/slic3r/GUI/FirmwareDialog.cpp:904 msgid "Confirmation" msgstr "" -#: src/slic3r/GUI/FirmwareDialog.cpp:867 +#: src/slic3r/GUI/FirmwareDialog.cpp:907 msgid "Cancelling..." msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:720 +#: src/slic3r/GUI/GLCanvas3D.cpp:526 +msgid "Layers heights" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:623 msgid "An object outside the print area was detected" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:721 +#: src/slic3r/GUI/GLCanvas3D.cpp:624 msgid "A toolpath outside the print area was detected" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:722 +#: src/slic3r/GUI/GLCanvas3D.cpp:625 msgid "SLA supports outside the print area were detected" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:723 +#: src/slic3r/GUI/GLCanvas3D.cpp:626 msgid "Some objects are not visible when editing supports" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:725 +#: src/slic3r/GUI/GLCanvas3D.cpp:628 msgid "" "An object outside the print area was detected\n" "Resolve the current problem to continue slicing" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:1694 -msgid "Last frame" +#: src/slic3r/GUI/GLCanvas3D.cpp:1711 +msgid "Mirror Object" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:1698 -msgid "ms" +#: src/slic3r/GUI/GLCanvas3D.cpp:2872 +msgid "Move Object" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3434 +#: src/slic3r/GUI/GLCanvas3D.cpp:3389 src/slic3r/GUI/GLCanvas3D.cpp:3609 +#: src/slic3r/GUI/MainFrame.cpp:559 +msgid "Undo" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:3389 src/slic3r/GUI/GLCanvas3D.cpp:3639 +#: src/slic3r/GUI/MainFrame.cpp:562 +msgid "Redo" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:3395 +#, possible-c-format +msgid "%s Stack" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:3413 +#, possible-c-format +msgid "%s %d Action" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:3460 msgid "Add..." msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3444 src/slic3r/GUI/GUI_ObjectList.cpp:1277 -#: src/slic3r/GUI/Plater.cpp:2994 src/slic3r/GUI/Plater.cpp:3013 -#: src/slic3r/GUI/Tab.cpp:2988 +#: src/slic3r/GUI/GLCanvas3D.cpp:3468 src/slic3r/GUI/GUI_ObjectList.cpp:1434 +#: src/slic3r/GUI/Plater.cpp:3467 src/slic3r/GUI/Plater.cpp:3486 +#: src/slic3r/GUI/Tab.cpp:3204 msgid "Delete" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3455 src/slic3r/GUI/Plater.cpp:3375 +#: src/slic3r/GUI/GLCanvas3D.cpp:3477 src/slic3r/GUI/Plater.cpp:4075 msgid "Delete all" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3466 src/slic3r/GUI/KBShortcutsDialog.cpp:134 +#: src/slic3r/GUI/GLCanvas3D.cpp:3486 src/slic3r/GUI/KBShortcutsDialog.cpp:134 +#: src/slic3r/GUI/Plater.cpp:2636 msgid "Arrange" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3480 +#: src/slic3r/GUI/GLCanvas3D.cpp:3486 +msgid "Arrange selection" +msgstr "" + +#: src/slic3r/GUI/GLCanvas3D.cpp:3498 msgid "Copy" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3491 +#: src/slic3r/GUI/GLCanvas3D.cpp:3507 msgid "Paste" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3505 +#: src/slic3r/GUI/GLCanvas3D.cpp:3519 msgid "Add instance" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3517 +#: src/slic3r/GUI/GLCanvas3D.cpp:3530 msgid "Remove instance" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3532 +#: src/slic3r/GUI/GLCanvas3D.cpp:3543 msgid "Split to objects" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3544 src/slic3r/GUI/GUI_ObjectList.cpp:1129 +#: src/slic3r/GUI/GLCanvas3D.cpp:3553 src/slic3r/GUI/GUI_ObjectList.cpp:1280 msgid "Split to parts" msgstr "" -#: src/slic3r/GUI/GLCanvas3D.cpp:3559 +#: src/slic3r/GUI/GLCanvas3D.cpp:3566 msgid "Layers editing" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:35 -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:195 -msgid "Rotate lower part upwards" +#: src/slic3r/GUI/GLCanvas3D.cpp:5623 +msgid "Selection-Add from rectangle" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:36 -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:198 -msgid "Perform cut" +#: src/slic3r/GUI/GLCanvas3D.cpp:5642 +msgid "Selection-Remove from rectangle" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:43 -msgid "Cut object:" -msgstr "" - -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:88 -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:188 src/libslic3r/PrintConfig.cpp:3049 +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:40 +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:144 src/libslic3r/PrintConfig.cpp:3176 msgid "Cut" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:193 +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:149 msgid "Keep upper part" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:194 +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:150 msgid "Keep lower part" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp:32 +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:151 +msgid "Rotate lower part upwards" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:154 +msgid "Perform cut" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp:45 msgid "Place on face" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:52 +#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:48 msgid "Move" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:178 +#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:177 msgid "Position (mm)" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:178 +#: src/slic3r/GUI/Gizmos/GLGizmoMove.cpp:177 msgid "Displacement (mm)" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp:458 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:305 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:324 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:342 -#: src/libslic3r/PrintConfig.cpp:3098 +#: src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp:449 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:466 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:485 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:503 +#: src/libslic3r/PrintConfig.cpp:3225 msgid "Rotate" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp:491 +#: src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp:482 msgid "Rotation (deg)" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoScale.cpp:53 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:231 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:325 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:343 -#: src/libslic3r/PrintConfig.cpp:3113 +#: src/slic3r/GUI/Gizmos/GLGizmoScale.cpp:47 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:390 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:486 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:504 +#: src/libslic3r/PrintConfig.cpp:3240 msgid "Scale" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoScale.cpp:291 +#: src/slic3r/GUI/Gizmos/GLGizmoScale.cpp:292 msgid "Scale (%)" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:840 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:44 msgid "Head diameter" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:856 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:45 msgid "Lock supports under new islands" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:860 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1249 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:46 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1427 msgid "Remove selected points" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:864 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:921 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:47 msgid "Remove all points" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:869 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1252 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:48 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1430 msgid "Apply changes" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:874 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1253 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:49 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1431 msgid "Discard changes" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:881 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:50 msgid "Minimal points distance" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:882 -#: src/libslic3r/PrintConfig.cpp:2534 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:51 +#: src/libslic3r/PrintConfig.cpp:2620 msgid "Support points density" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:911 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1255 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:52 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1433 msgid "Auto-generate points" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:917 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:53 msgid "Manual editing" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:934 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:54 msgid "Clipping of view" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:935 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:55 msgid "Reset direction" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1007 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:531 +msgid "Add support point" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:720 +msgid "Delete support point" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:925 +msgid "Change point head diameter" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:991 +msgid "Support parameter change" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1099 msgid "SLA Support Points" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1034 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1138 msgid "Do you want to save your manually edited support points?" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1035 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1139 msgid "Save changes?" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1178 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1183 +msgid "Move support point" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1282 +msgid "Support points edit" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1333 msgid "" "Autogeneration will erase all manually edited points.\n" "\n" "Are you sure you want to do it?\n" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1180 src/slic3r/GUI/GUI.cpp:283 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1335 src/slic3r/GUI/GUI.cpp:289 #: src/slic3r/GUI/WipeTowerDialog.cpp:44 src/slic3r/GUI/WipeTowerDialog.cpp:328 msgid "Warning" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1212 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1338 +msgid "Autogenerate support points" +msgstr "" + +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1390 msgid "SLA gizmo keyboard shortcuts" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1223 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1401 msgid "Note: some shortcuts work in (non)editing mode only." msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1241 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1244 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1245 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1419 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1422 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1423 msgid "Left click" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1241 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1419 msgid "Add point" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1242 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1420 msgid "Right click" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1242 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1420 msgid "Remove point" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1243 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1246 -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1247 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1421 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1424 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1425 msgid "Drag" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1243 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1421 msgid "Move point" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1244 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1422 msgid "Add point to selection" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1245 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1423 msgid "Remove point from selection" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1246 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1424 msgid "Select by rectangle" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1247 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1425 msgid "Deselect by rectangle" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1248 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1426 msgid "Select all points" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1250 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1428 msgid "Mouse wheel" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1250 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1428 msgid "Move clipping plane" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1251 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1429 msgid "Reset clipping plane" msgstr "" -#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1254 +#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1432 msgid "Switch to editing mode" msgstr "" -#: src/slic3r/GUI/GUI.cpp:142 src/slic3r/GUI/Tab.cpp:2847 +#: src/slic3r/GUI/GUI.cpp:141 src/slic3r/GUI/Tab.cpp:3063 msgid "It's impossible to print multi-part object(s) with SLA technology." msgstr "" -#: src/slic3r/GUI/GUI.cpp:143 +#: src/slic3r/GUI/GUI.cpp:142 msgid "Please check and fix your object list." msgstr "" -#: src/slic3r/GUI/GUI.cpp:144 src/slic3r/GUI/Tab.cpp:2849 +#: src/slic3r/GUI/GUI.cpp:143 src/slic3r/GUI/Plater.cpp:2213 +#: src/slic3r/GUI/Tab.cpp:3065 msgid "Attention!" msgstr "" -#: src/slic3r/GUI/GUI.cpp:277 +#: src/slic3r/GUI/GUI.cpp:283 msgid "Notice" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:401 +#: src/slic3r/GUI/GUI_App.cpp:435 msgid "Changing of an application language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:409 src/slic3r/GUI/GUI_App.cpp:418 +#: src/slic3r/GUI/GUI_App.cpp:443 src/slic3r/GUI/GUI_App.cpp:452 msgid "Recreating" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:422 +#: src/slic3r/GUI/GUI_App.cpp:456 msgid "Loading of current presets" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:430 +#: src/slic3r/GUI/GUI_App.cpp:464 msgid "Loading of a mode view" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:510 +#: src/slic3r/GUI/GUI_App.cpp:544 msgid "Choose one file (3MF/AMF):" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:522 +#: src/slic3r/GUI/GUI_App.cpp:556 msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:564 +#: src/slic3r/GUI/GUI_App.cpp:598 msgid "Select the language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:565 +#: src/slic3r/GUI/GUI_App.cpp:599 msgid "Language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:716 +#: src/slic3r/GUI/GUI_App.cpp:750 msgid "&Configuration Snapshots" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:716 +#: src/slic3r/GUI/GUI_App.cpp:750 msgid "Inspect / activate configuration snapshots" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:717 +#: src/slic3r/GUI/GUI_App.cpp:751 msgid "Take Configuration &Snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:717 +#: src/slic3r/GUI/GUI_App.cpp:751 msgid "Capture a configuration snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:720 +#: src/slic3r/GUI/GUI_App.cpp:754 msgid "&Preferences" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:726 +#: src/slic3r/GUI/GUI_App.cpp:760 msgid "Application preferences" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:729 src/slic3r/GUI/wxExtensions.cpp:2555 +#: src/slic3r/GUI/GUI_App.cpp:763 src/slic3r/GUI/wxExtensions.cpp:2882 msgid "Simple" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:729 +#: src/slic3r/GUI/GUI_App.cpp:763 msgid "Simple View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:730 src/slic3r/GUI/GUI_ObjectList.cpp:85 -#: src/slic3r/GUI/GUI_ObjectList.cpp:541 src/slic3r/GUI/Tab.cpp:1032 -#: src/slic3r/GUI/Tab.cpp:1047 src/slic3r/GUI/Tab.cpp:1145 -#: src/slic3r/GUI/Tab.cpp:1148 src/slic3r/GUI/Tab.cpp:1551 -#: src/slic3r/GUI/Tab.cpp:1977 src/slic3r/GUI/Tab.cpp:3492 -#: src/slic3r/GUI/wxExtensions.cpp:2556 src/libslic3r/PrintConfig.cpp:73 -#: src/libslic3r/PrintConfig.cpp:188 src/libslic3r/PrintConfig.cpp:351 -#: src/libslic3r/PrintConfig.cpp:999 src/libslic3r/PrintConfig.cpp:2210 +#: src/slic3r/GUI/GUI_App.cpp:764 src/slic3r/GUI/GUI_ObjectList.cpp:93 +#: src/slic3r/GUI/GUI_ObjectList.cpp:567 src/slic3r/GUI/Tab.cpp:1037 +#: src/slic3r/GUI/Tab.cpp:1052 src/slic3r/GUI/Tab.cpp:1150 +#: src/slic3r/GUI/Tab.cpp:1153 src/slic3r/GUI/Tab.cpp:1649 +#: src/slic3r/GUI/Tab.cpp:2120 src/slic3r/GUI/Tab.cpp:3699 +#: src/slic3r/GUI/wxExtensions.cpp:2883 src/libslic3r/PrintConfig.cpp:83 +#: src/libslic3r/PrintConfig.cpp:197 src/libslic3r/PrintConfig.cpp:360 +#: src/libslic3r/PrintConfig.cpp:1013 src/libslic3r/PrintConfig.cpp:2226 msgid "Advanced" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:730 +#: src/slic3r/GUI/GUI_App.cpp:764 msgid "Advanced View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:731 src/slic3r/GUI/wxExtensions.cpp:2557 +#: src/slic3r/GUI/GUI_App.cpp:765 src/slic3r/GUI/wxExtensions.cpp:2884 msgid "Expert" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:731 +#: src/slic3r/GUI/GUI_App.cpp:765 msgid "Expert View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:736 +#: src/slic3r/GUI/GUI_App.cpp:770 msgid "Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:736 +#: src/slic3r/GUI/GUI_App.cpp:770 #, possible-c-format msgid "%s View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:738 +#: src/slic3r/GUI/GUI_App.cpp:772 msgid "Change Application &Language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:740 +#: src/slic3r/GUI/GUI_App.cpp:774 msgid "Flash printer &firmware" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:740 +#: src/slic3r/GUI/GUI_App.cpp:774 msgid "Upload a firmware image into an Arduino based printer" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:752 +#: src/slic3r/GUI/GUI_App.cpp:786 msgid "Taking configuration snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:752 +#: src/slic3r/GUI/GUI_App.cpp:786 msgid "Snapshot name" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:795 +#: src/slic3r/GUI/GUI_App.cpp:829 msgid "" "Switching the language will trigger application restart.\n" "You will lose content of the plater." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:797 +#: src/slic3r/GUI/GUI_App.cpp:831 msgid "Do you want to proceed?" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:798 +#: src/slic3r/GUI/GUI_App.cpp:832 msgid "Language selection" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:817 +#: src/slic3r/GUI/GUI_App.cpp:855 msgid "&Configuration" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:837 +#: src/slic3r/GUI/GUI_App.cpp:877 msgid "The presets on the following tabs were modified" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:837 src/slic3r/GUI/Tab.cpp:2835 +#: src/slic3r/GUI/GUI_App.cpp:877 src/slic3r/GUI/Tab.cpp:3051 msgid "Discard changes and continue anyway?" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:838 +#: src/slic3r/GUI/GUI_App.cpp:880 msgid "Unsaved Presets" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:28 src/slic3r/GUI/GUI_ObjectList.cpp:77 -#: src/slic3r/GUI/GUI_ObjectList.cpp:533 src/libslic3r/PrintConfig.cpp:57 -#: src/libslic3r/PrintConfig.cpp:151 src/libslic3r/PrintConfig.cpp:382 -#: src/libslic3r/PrintConfig.cpp:439 src/libslic3r/PrintConfig.cpp:447 -#: src/libslic3r/PrintConfig.cpp:853 src/libslic3r/PrintConfig.cpp:1037 -#: src/libslic3r/PrintConfig.cpp:1340 src/libslic3r/PrintConfig.cpp:1406 -#: src/libslic3r/PrintConfig.cpp:1587 src/libslic3r/PrintConfig.cpp:2022 -#: src/libslic3r/PrintConfig.cpp:2079 +#: src/slic3r/GUI/GUI_ObjectList.cpp:30 src/slic3r/GUI/GUI_ObjectList.cpp:84 +#: src/slic3r/GUI/GUI_ObjectList.cpp:558 src/libslic3r/PrintConfig.cpp:67 +#: src/libslic3r/PrintConfig.cpp:160 src/libslic3r/PrintConfig.cpp:392 +#: src/libslic3r/PrintConfig.cpp:453 src/libslic3r/PrintConfig.cpp:461 +#: src/libslic3r/PrintConfig.cpp:867 src/libslic3r/PrintConfig.cpp:1051 +#: src/libslic3r/PrintConfig.cpp:1354 src/libslic3r/PrintConfig.cpp:1420 +#: src/libslic3r/PrintConfig.cpp:1601 src/libslic3r/PrintConfig.cpp:2037 +#: src/libslic3r/PrintConfig.cpp:2095 msgid "Layers and Perimeters" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:29 src/slic3r/GUI/GUI_ObjectList.cpp:78 -#: src/slic3r/GUI/GUI_ObjectList.cpp:534 src/slic3r/GUI/Plater.cpp:446 -#: src/slic3r/GUI/Tab.cpp:1036 src/slic3r/GUI/Tab.cpp:1037 -#: src/slic3r/GUI/Tab.cpp:1395 src/libslic3r/PrintConfig.cpp:168 -#: src/libslic3r/PrintConfig.cpp:390 src/libslic3r/PrintConfig.cpp:740 -#: src/libslic3r/PrintConfig.cpp:754 src/libslic3r/PrintConfig.cpp:791 -#: src/libslic3r/PrintConfig.cpp:944 src/libslic3r/PrintConfig.cpp:954 -#: src/libslic3r/PrintConfig.cpp:972 src/libslic3r/PrintConfig.cpp:990 -#: src/libslic3r/PrintConfig.cpp:1009 src/libslic3r/PrintConfig.cpp:1694 -#: src/libslic3r/PrintConfig.cpp:1711 +#: src/slic3r/GUI/GUI_ObjectList.cpp:31 src/slic3r/GUI/GUI_ObjectList.cpp:85 +#: src/slic3r/GUI/GUI_ObjectList.cpp:559 src/slic3r/GUI/Plater.cpp:498 +#: src/slic3r/GUI/Tab.cpp:1041 src/slic3r/GUI/Tab.cpp:1042 +#: src/slic3r/GUI/Tab.cpp:1394 src/libslic3r/PrintConfig.cpp:177 +#: src/libslic3r/PrintConfig.cpp:400 src/libslic3r/PrintConfig.cpp:420 +#: src/libslic3r/PrintConfig.cpp:754 src/libslic3r/PrintConfig.cpp:768 +#: src/libslic3r/PrintConfig.cpp:805 src/libslic3r/PrintConfig.cpp:958 +#: src/libslic3r/PrintConfig.cpp:968 src/libslic3r/PrintConfig.cpp:986 +#: src/libslic3r/PrintConfig.cpp:1004 src/libslic3r/PrintConfig.cpp:1023 +#: src/libslic3r/PrintConfig.cpp:1708 src/libslic3r/PrintConfig.cpp:1725 msgid "Infill" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:30 src/slic3r/GUI/GUI_ObjectList.cpp:79 -#: src/slic3r/GUI/GUI_ObjectList.cpp:535 src/slic3r/GUI/GUI_Preview.cpp:242 -#: src/slic3r/GUI/Tab.cpp:1065 src/slic3r/GUI/Tab.cpp:1066 -#: src/libslic3r/PrintConfig.cpp:335 src/libslic3r/PrintConfig.cpp:1467 -#: src/libslic3r/PrintConfig.cpp:1815 src/libslic3r/PrintConfig.cpp:1821 -#: src/libslic3r/PrintConfig.cpp:1829 src/libslic3r/PrintConfig.cpp:1841 -#: src/libslic3r/PrintConfig.cpp:1851 src/libslic3r/PrintConfig.cpp:1859 -#: src/libslic3r/PrintConfig.cpp:1874 src/libslic3r/PrintConfig.cpp:1895 -#: src/libslic3r/PrintConfig.cpp:1906 src/libslic3r/PrintConfig.cpp:1922 -#: src/libslic3r/PrintConfig.cpp:1931 src/libslic3r/PrintConfig.cpp:1940 -#: src/libslic3r/PrintConfig.cpp:1951 src/libslic3r/PrintConfig.cpp:1965 -#: src/libslic3r/PrintConfig.cpp:1973 src/libslic3r/PrintConfig.cpp:1974 -#: src/libslic3r/PrintConfig.cpp:1983 src/libslic3r/PrintConfig.cpp:1991 -#: src/libslic3r/PrintConfig.cpp:2005 src/libslic3r/GCode/PreviewData.cpp:172 +#: src/slic3r/GUI/GUI_ObjectList.cpp:32 src/slic3r/GUI/GUI_ObjectList.cpp:86 +#: src/slic3r/GUI/GUI_ObjectList.cpp:560 src/slic3r/GUI/GUI_Preview.cpp:243 +#: src/slic3r/GUI/Tab.cpp:1070 src/slic3r/GUI/Tab.cpp:1071 +#: src/libslic3r/PrintConfig.cpp:344 src/libslic3r/PrintConfig.cpp:1481 +#: src/libslic3r/PrintConfig.cpp:1830 src/libslic3r/PrintConfig.cpp:1836 +#: src/libslic3r/PrintConfig.cpp:1844 src/libslic3r/PrintConfig.cpp:1856 +#: src/libslic3r/PrintConfig.cpp:1866 src/libslic3r/PrintConfig.cpp:1874 +#: src/libslic3r/PrintConfig.cpp:1889 src/libslic3r/PrintConfig.cpp:1910 +#: src/libslic3r/PrintConfig.cpp:1921 src/libslic3r/PrintConfig.cpp:1937 +#: src/libslic3r/PrintConfig.cpp:1946 src/libslic3r/PrintConfig.cpp:1955 +#: src/libslic3r/PrintConfig.cpp:1966 src/libslic3r/PrintConfig.cpp:1980 +#: src/libslic3r/PrintConfig.cpp:1988 src/libslic3r/PrintConfig.cpp:1989 +#: src/libslic3r/PrintConfig.cpp:1998 src/libslic3r/PrintConfig.cpp:2006 +#: src/libslic3r/PrintConfig.cpp:2020 src/libslic3r/GCode/PreviewData.cpp:172 msgid "Support material" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:33 src/slic3r/GUI/GUI_ObjectList.cpp:81 -#: src/slic3r/GUI/GUI_ObjectList.cpp:537 src/slic3r/GUI/Tab.cpp:1125 -#: src/slic3r/GUI/Tab.cpp:1881 src/libslic3r/PrintConfig.cpp:457 -#: src/libslic3r/PrintConfig.cpp:965 src/libslic3r/PrintConfig.cpp:1375 -#: src/libslic3r/PrintConfig.cpp:1703 src/libslic3r/PrintConfig.cpp:1887 -#: src/libslic3r/PrintConfig.cpp:1913 src/libslic3r/PrintConfig.cpp:2186 -#: src/libslic3r/PrintConfig.cpp:2194 -msgid "Extruders" +#: src/slic3r/GUI/GUI_ObjectList.cpp:35 src/slic3r/GUI/GUI_ObjectList.cpp:90 +#: src/slic3r/GUI/GUI_ObjectList.cpp:564 src/libslic3r/PrintConfig.cpp:2202 +#: src/libslic3r/PrintConfig.cpp:2210 +msgid "Wipe options" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:39 +#: src/slic3r/GUI/GUI_ObjectList.cpp:41 msgid "Pad and Support" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:45 +#: src/slic3r/GUI/GUI_ObjectList.cpp:47 msgid "Add part" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:46 +#: src/slic3r/GUI/GUI_ObjectList.cpp:48 msgid "Add modifier" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:47 +#: src/slic3r/GUI/GUI_ObjectList.cpp:49 msgid "Add support enforcer" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:48 +#: src/slic3r/GUI/GUI_ObjectList.cpp:50 msgid "Add support blocker" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:80 src/slic3r/GUI/GUI_ObjectList.cpp:536 -#: src/slic3r/GUI/GUI_Preview.cpp:221 src/slic3r/GUI/Tab.cpp:1090 -#: src/libslic3r/PrintConfig.cpp:200 src/libslic3r/PrintConfig.cpp:427 -#: src/libslic3r/PrintConfig.cpp:882 src/libslic3r/PrintConfig.cpp:1010 -#: src/libslic3r/PrintConfig.cpp:1396 src/libslic3r/PrintConfig.cpp:1633 -#: src/libslic3r/PrintConfig.cpp:1682 src/libslic3r/PrintConfig.cpp:1733 -#: src/libslic3r/PrintConfig.cpp:2064 +#: src/slic3r/GUI/GUI_ObjectList.cpp:87 src/slic3r/GUI/GUI_ObjectList.cpp:561 +#: src/slic3r/GUI/GUI_Preview.cpp:222 src/slic3r/GUI/Tab.cpp:1095 +#: src/libslic3r/PrintConfig.cpp:209 src/libslic3r/PrintConfig.cpp:441 +#: src/libslic3r/PrintConfig.cpp:896 src/libslic3r/PrintConfig.cpp:1024 +#: src/libslic3r/PrintConfig.cpp:1410 src/libslic3r/PrintConfig.cpp:1647 +#: src/libslic3r/PrintConfig.cpp:1696 src/libslic3r/PrintConfig.cpp:1747 +#: src/libslic3r/PrintConfig.cpp:2080 msgid "Speed" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:82 src/slic3r/GUI/GUI_ObjectList.cpp:538 -#: src/libslic3r/PrintConfig.cpp:417 src/libslic3r/PrintConfig.cpp:524 -#: src/libslic3r/PrintConfig.cpp:841 src/libslic3r/PrintConfig.cpp:973 -#: src/libslic3r/PrintConfig.cpp:1384 src/libslic3r/PrintConfig.cpp:1723 -#: src/libslic3r/PrintConfig.cpp:1896 src/libslic3r/PrintConfig.cpp:2053 +#: src/slic3r/GUI/GUI_ObjectList.cpp:88 src/slic3r/GUI/GUI_ObjectList.cpp:562 +#: src/slic3r/GUI/Tab.cpp:1130 src/slic3r/GUI/Tab.cpp:1997 +#: src/libslic3r/PrintConfig.cpp:471 src/libslic3r/PrintConfig.cpp:979 +#: src/libslic3r/PrintConfig.cpp:1389 src/libslic3r/PrintConfig.cpp:1717 +#: src/libslic3r/PrintConfig.cpp:1902 src/libslic3r/PrintConfig.cpp:1928 +msgid "Extruders" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:89 src/slic3r/GUI/GUI_ObjectList.cpp:563 +#: src/libslic3r/PrintConfig.cpp:431 src/libslic3r/PrintConfig.cpp:538 +#: src/libslic3r/PrintConfig.cpp:855 src/libslic3r/PrintConfig.cpp:987 +#: src/libslic3r/PrintConfig.cpp:1398 src/libslic3r/PrintConfig.cpp:1737 +#: src/libslic3r/PrintConfig.cpp:1911 src/libslic3r/PrintConfig.cpp:2069 msgid "Extrusion Width" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:87 src/slic3r/GUI/GUI_ObjectList.cpp:543 -#: src/slic3r/GUI/Plater.cpp:428 src/slic3r/GUI/Tab.cpp:3454 -#: src/slic3r/GUI/Tab.cpp:3455 src/libslic3r/PrintConfig.cpp:2398 -#: src/libslic3r/PrintConfig.cpp:2405 src/libslic3r/PrintConfig.cpp:2414 -#: src/libslic3r/PrintConfig.cpp:2423 src/libslic3r/PrintConfig.cpp:2433 -#: src/libslic3r/PrintConfig.cpp:2459 src/libslic3r/PrintConfig.cpp:2466 -#: src/libslic3r/PrintConfig.cpp:2477 src/libslic3r/PrintConfig.cpp:2487 -#: src/libslic3r/PrintConfig.cpp:2496 src/libslic3r/PrintConfig.cpp:2506 -#: src/libslic3r/PrintConfig.cpp:2515 src/libslic3r/PrintConfig.cpp:2525 -#: src/libslic3r/PrintConfig.cpp:2535 src/libslic3r/PrintConfig.cpp:2543 +#: src/slic3r/GUI/GUI_ObjectList.cpp:95 src/slic3r/GUI/GUI_ObjectList.cpp:569 +#: src/slic3r/GUI/Plater.cpp:466 src/slic3r/GUI/Tab.cpp:3655 +#: src/slic3r/GUI/Tab.cpp:3656 src/libslic3r/PrintConfig.cpp:2469 +#: src/libslic3r/PrintConfig.cpp:2476 src/libslic3r/PrintConfig.cpp:2485 +#: src/libslic3r/PrintConfig.cpp:2494 src/libslic3r/PrintConfig.cpp:2504 +#: src/libslic3r/PrintConfig.cpp:2530 src/libslic3r/PrintConfig.cpp:2537 +#: src/libslic3r/PrintConfig.cpp:2548 src/libslic3r/PrintConfig.cpp:2558 +#: src/libslic3r/PrintConfig.cpp:2567 src/libslic3r/PrintConfig.cpp:2580 +#: src/libslic3r/PrintConfig.cpp:2590 src/libslic3r/PrintConfig.cpp:2599 +#: src/libslic3r/PrintConfig.cpp:2609 src/libslic3r/PrintConfig.cpp:2621 +#: src/libslic3r/PrintConfig.cpp:2629 msgid "Supports" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:88 src/slic3r/GUI/GUI_ObjectList.cpp:544 -#: src/slic3r/GUI/Tab.cpp:3482 src/slic3r/GUI/Tab.cpp:3483 -#: src/libslic3r/PrintConfig.cpp:2551 src/libslic3r/PrintConfig.cpp:2558 -#: src/libslic3r/PrintConfig.cpp:2572 src/libslic3r/PrintConfig.cpp:2582 -#: src/libslic3r/PrintConfig.cpp:2595 src/libslic3r/PrintConfig.cpp:2604 +#: src/slic3r/GUI/GUI_ObjectList.cpp:96 src/slic3r/GUI/GUI_ObjectList.cpp:570 +#: src/slic3r/GUI/Tab.cpp:3684 src/slic3r/GUI/Tab.cpp:3685 +#: src/libslic3r/PrintConfig.cpp:2637 src/libslic3r/PrintConfig.cpp:2644 +#: src/libslic3r/PrintConfig.cpp:2658 src/libslic3r/PrintConfig.cpp:2668 +#: src/libslic3r/PrintConfig.cpp:2681 src/libslic3r/PrintConfig.cpp:2690 +#: src/libslic3r/PrintConfig.cpp:2701 src/libslic3r/PrintConfig.cpp:2712 +#: src/libslic3r/PrintConfig.cpp:2722 src/libslic3r/PrintConfig.cpp:2732 msgid "Pad" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:205 +#: src/slic3r/GUI/GUI_ObjectList.cpp:217 msgid "Name" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:259 +#: src/slic3r/GUI/GUI_ObjectList.cpp:271 #, possible-c-format msgid "Auto-repaired (%d errors):\n" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:266 +#: src/slic3r/GUI/GUI_ObjectList.cpp:278 msgid "degenerate facets" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:267 +#: src/slic3r/GUI/GUI_ObjectList.cpp:279 msgid "edges fixed" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:268 +#: src/slic3r/GUI/GUI_ObjectList.cpp:280 msgid "facets removed" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:269 +#: src/slic3r/GUI/GUI_ObjectList.cpp:281 msgid "facets added" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:270 +#: src/slic3r/GUI/GUI_ObjectList.cpp:282 msgid "facets reversed" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:271 +#: src/slic3r/GUI/GUI_ObjectList.cpp:283 msgid "backwards edges" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:279 +#: src/slic3r/GUI/GUI_ObjectList.cpp:291 msgid "Right button click the icon to fix STL through Netfabb" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:308 +#: src/slic3r/GUI/GUI_ObjectList.cpp:325 msgid "Right button click the icon to change the object settings" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:359 src/slic3r/GUI/GUI_ObjectList.cpp:380 -#: src/slic3r/GUI/GUI_ObjectList.cpp:392 src/slic3r/GUI/GUI_ObjectList.cpp:2850 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2860 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2892 src/slic3r/GUI/wxExtensions.cpp:543 -#: src/slic3r/GUI/wxExtensions.cpp:568 +#: src/slic3r/GUI/GUI_ObjectList.cpp:375 src/slic3r/GUI/GUI_ObjectList.cpp:396 +#: src/slic3r/GUI/GUI_ObjectList.cpp:408 src/slic3r/GUI/GUI_ObjectList.cpp:3508 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3518 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3550 src/slic3r/GUI/wxExtensions.cpp:576 +#: src/slic3r/GUI/wxExtensions.cpp:633 src/slic3r/GUI/wxExtensions.cpp:658 +#: src/slic3r/GUI/wxExtensions.cpp:794 msgid "default" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:364 src/slic3r/GUI/Tab.cpp:1515 -#: src/libslic3r/PrintConfig.cpp:456 +#: src/slic3r/GUI/GUI_ObjectList.cpp:380 src/slic3r/GUI/Tab.cpp:1613 +#: src/libslic3r/PrintConfig.cpp:470 msgid "Extruder" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:883 src/slic3r/GUI/GUI_ObjectList.cpp:1159 -#: src/slic3r/GUI/GUI_ObjectList.cpp:1165 -#: src/slic3r/GUI/GUI_ObjectList.cpp:1388 +#: src/slic3r/GUI/GUI_ObjectList.cpp:493 +msgid "Rename Object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:493 +msgid "Rename Sub-object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:934 src/slic3r/GUI/GUI_ObjectList.cpp:3346 +msgid "Instances to Separated Objects" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:952 +msgid "Remove Volume(s)" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1007 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1316 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1322 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1556 #, possible-c-format msgid "Quick Add Settings (%s)" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:946 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1077 msgid "Select showing settings" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1079 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1126 +msgid "Add Settings for Layers" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1127 +msgid "Add Settings for Sub-object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1128 +msgid "Add Settings for Object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1189 +msgid "Add Settings Bundle for Layers" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1190 +msgid "Add Settings Bundle for Sub-object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1191 +msgid "Add Settings Bundle for Object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1230 msgid "Load" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1084 -#: src/slic3r/GUI/GUI_ObjectList.cpp:1109 -#: src/slic3r/GUI/GUI_ObjectList.cpp:1112 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1235 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1260 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1263 msgid "Box" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1084 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1235 msgid "Cylinder" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1084 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1235 msgid "Sphere" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1084 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1235 msgid "Slab" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1138 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1287 +msgid "Edit Layers" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1295 msgid "Add settings" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1205 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1362 msgid "Change type" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1212 -#: src/slic3r/GUI/GUI_ObjectList.cpp:1342 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1369 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1510 msgid "Set as a Separated Object" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1218 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1375 msgid "Rename" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1229 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1386 msgid "Fix through the Netfabb" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1239 src/slic3r/GUI/Plater.cpp:3023 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1396 src/slic3r/GUI/Plater.cpp:3496 msgid "Export as STL" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1246 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1403 msgid "Change extruder" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1265 src/libslic3r/PrintConfig.cpp:300 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1422 src/libslic3r/PrintConfig.cpp:309 msgid "Default" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1271 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1428 msgid "Select new extruder for the object/part" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1342 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1440 +msgid "Scale to print volume" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1440 +msgid "Scale the selected object to fit the print volume" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1510 msgid "Set as a Separated Objects" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1555 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1585 +msgid "Load Part" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1617 +msgid "Error!" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1662 +msgid "Add Generic Subobject" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1669 msgid "Generic" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1698 -msgid "You can't delete the last solid part from object." +#: src/slic3r/GUI/GUI_ObjectList.cpp:1770 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1872 +msgid "Last instance of an object cannot be deleted." msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1715 -msgid "You can't delete the last intance from object." +#: src/slic3r/GUI/GUI_ObjectList.cpp:1782 +msgid "Delete Settings" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1741 src/slic3r/GUI/Plater.cpp:2343 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1806 +msgid "Delete All Instances from Object" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1822 +msgid "Delete Layers Range" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1853 +msgid "From Object List You can't delete the last solid part from object." +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1857 +msgid "Delete Subobject" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1876 +msgid "Delete Instance" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1900 src/slic3r/GUI/Plater.cpp:2793 msgid "" "The selected object couldn't be split because it contains only one part." msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1850 +#: src/slic3r/GUI/GUI_ObjectList.cpp:1904 +msgid "Split to Parts" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:1950 +msgid "Add Layers" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2075 msgid "Group manipulation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1862 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2087 msgid "Object manipulation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1872 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2100 msgid "Object Settings to modify" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1876 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2104 msgid "Part Settings to modify" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1885 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2109 +msgid "Layer range Settings to modify" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2115 msgid "Part manipulation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:1891 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2121 msgid "Instance manipulation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2416 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2128 +msgid "Layers Editing" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2128 +msgid "Layer Editing" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2303 +msgid "Delete Selected Item" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2415 +msgid "Delete Selected" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2484 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2513 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2531 +msgid "Add New Layers Range" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2590 +msgid "Edit Layers Range" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2867 +msgid "Selection-Remove from list" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2875 +msgid "Selection-Add from list" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2993 msgid "Object or Instance" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2416 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2547 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2994 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3127 msgid "Part" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2418 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2994 +msgid "Layer" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:2996 msgid "Unsupported selection" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2419 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2997 #, possible-c-format msgid "You started your selection with %s Item." msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2420 +#: src/slic3r/GUI/GUI_ObjectList.cpp:2998 #, possible-c-format msgid "In this mode you can select only other %s Items%s" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2423 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3001 msgid "of a current Object" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2428 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2501 src/slic3r/GUI/Plater.cpp:117 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3006 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3081 src/slic3r/GUI/Plater.cpp:126 msgid "Info" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2542 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3122 msgid "You can't change a type of the last solid part of the object." msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2547 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3127 msgid "Modifier" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2547 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3127 msgid "Support Enforcer" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2547 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3127 msgid "Support Blocker" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2549 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3129 msgid "Type:" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2549 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3129 msgid "Select type of part" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2713 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3134 +msgid "Change Part Type" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectList.cpp:3368 msgid "Enter new name" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2713 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3368 msgid "Renaming" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2729 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2823 src/slic3r/GUI/Tab.cpp:3335 -#: src/slic3r/GUI/Tab.cpp:3339 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3384 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3480 src/slic3r/GUI/Tab.cpp:3536 +#: src/slic3r/GUI/Tab.cpp:3540 msgid "The supplied name is not valid;" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2730 -#: src/slic3r/GUI/GUI_ObjectList.cpp:2824 src/slic3r/GUI/Tab.cpp:3336 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3385 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3481 src/slic3r/GUI/Tab.cpp:3537 msgid "the following characters are not allowed:" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2840 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3498 msgid "Set extruder for selected items" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2841 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3499 msgid "Select extruder number for selected objects and/or parts" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2854 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3512 msgid "Select extruder number:" msgstr "" -#: src/slic3r/GUI/GUI_ObjectList.cpp:2855 +#: src/slic3r/GUI/GUI_ObjectList.cpp:3513 msgid "This extruder will be set for selected items" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:40 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:83 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:62 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:105 msgid "World coordinates" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:41 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:84 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:63 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:106 msgid "Local coordinates" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:60 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:82 msgid "Select coordinate space, in which the transformation will be performed." msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:102 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:125 msgid "Object Manipulation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:153 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:176 msgid "Object name" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:229 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:282 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:212 +#, possible-c-format +msgid "Toggle %c axis mirroring" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:245 +msgid "Set Mirror" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:285 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:290 +msgid "Reset scale" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:303 +msgid "Reset rotation" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:328 +msgid "Reset Rotation" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:340 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:355 +msgid "Drop to bed" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:388 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:443 msgid "Position" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:230 -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:283 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:389 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:444 msgid "Rotation" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:284 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:445 msgid "Scale factors" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:341 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:502 msgid "Translate" msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:640 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:554 +msgid "" +"You cann't use non-uniform scaling mode for multiple objects/parts selection" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:715 +msgid "Set Position" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:746 +msgid "Set Orientation" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:811 +msgid "Set Scale" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:895 msgid "" "The currently manipulated object is tilted (rotation angles are not " "multiples of 90°).\n" @@ -1613,7 +1905,7 @@ msgid "" "once the rotation is embedded into the object coordinates." msgstr "" -#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:643 +#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:898 msgid "" "This operation is irreversible.\n" "Do you want to proceed?" @@ -1623,117 +1915,127 @@ msgstr "" msgid "Additional Settings" msgstr "" -#: src/slic3r/GUI/GUI_ObjectSettings.cpp:83 +#: src/slic3r/GUI/GUI_ObjectSettings.cpp:94 msgid "Remove parameter" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:215 +#: src/slic3r/GUI/GUI_ObjectSettings.cpp:100 +#, possible-c-format +msgid "Delete Option %s" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectSettings.cpp:144 +#, possible-c-format +msgid "Change Option %s" +msgstr "" + +#: src/slic3r/GUI/GUI_Preview.cpp:216 msgid "View" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:218 src/slic3r/GUI/GUI_Preview.cpp:544 +#: src/slic3r/GUI/GUI_Preview.cpp:219 src/slic3r/GUI/GUI_Preview.cpp:554 #: src/libslic3r/GCode/PreviewData.cpp:394 msgid "Feature type" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:219 src/libslic3r/PrintConfig.cpp:469 +#: src/slic3r/GUI/GUI_Preview.cpp:220 src/libslic3r/PrintConfig.cpp:483 msgid "Height" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:220 src/libslic3r/PrintConfig.cpp:2172 +#: src/slic3r/GUI/GUI_Preview.cpp:221 src/libslic3r/PrintConfig.cpp:2188 msgid "Width" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:222 +#: src/slic3r/GUI/GUI_Preview.cpp:223 msgid "Volumetric flow rate" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:223 src/slic3r/GUI/GUI_Preview.cpp:321 -#: src/slic3r/GUI/GUI_Preview.cpp:487 src/slic3r/GUI/GUI_Preview.cpp:544 -#: src/slic3r/GUI/GUI_Preview.cpp:720 src/libslic3r/GCode/PreviewData.cpp:404 +#: src/slic3r/GUI/GUI_Preview.cpp:224 src/slic3r/GUI/GUI_Preview.cpp:328 +#: src/slic3r/GUI/GUI_Preview.cpp:506 src/slic3r/GUI/GUI_Preview.cpp:553 +#: src/slic3r/GUI/GUI_Preview.cpp:749 src/libslic3r/GCode/PreviewData.cpp:404 msgid "Tool" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:224 src/slic3r/GUI/GUI_Preview.cpp:542 +#: src/slic3r/GUI/GUI_Preview.cpp:225 src/slic3r/GUI/GUI_Preview.cpp:551 #: src/libslic3r/GCode/PreviewData.cpp:406 msgid "Color Print" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:227 +#: src/slic3r/GUI/GUI_Preview.cpp:228 msgid "Show" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:230 src/slic3r/GUI/GUI_Preview.cpp:231 +#: src/slic3r/GUI/GUI_Preview.cpp:231 src/slic3r/GUI/GUI_Preview.cpp:232 msgid "Feature types" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:233 src/libslic3r/GCode/PreviewData.cpp:163 +#: src/slic3r/GUI/GUI_Preview.cpp:234 src/libslic3r/GCode/PreviewData.cpp:163 msgid "Perimeter" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:234 src/libslic3r/GCode/PreviewData.cpp:164 +#: src/slic3r/GUI/GUI_Preview.cpp:235 src/libslic3r/GCode/PreviewData.cpp:164 msgid "External perimeter" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:235 src/libslic3r/GCode/PreviewData.cpp:165 +#: src/slic3r/GUI/GUI_Preview.cpp:236 src/libslic3r/GCode/PreviewData.cpp:165 msgid "Overhang perimeter" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:236 src/libslic3r/GCode/PreviewData.cpp:166 +#: src/slic3r/GUI/GUI_Preview.cpp:237 src/libslic3r/GCode/PreviewData.cpp:166 msgid "Internal infill" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:237 src/libslic3r/PrintConfig.cpp:1722 -#: src/libslic3r/PrintConfig.cpp:1732 src/libslic3r/GCode/PreviewData.cpp:167 +#: src/slic3r/GUI/GUI_Preview.cpp:238 src/libslic3r/PrintConfig.cpp:1736 +#: src/libslic3r/PrintConfig.cpp:1746 src/libslic3r/GCode/PreviewData.cpp:167 msgid "Solid infill" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:238 src/libslic3r/PrintConfig.cpp:2052 -#: src/libslic3r/PrintConfig.cpp:2063 src/libslic3r/GCode/PreviewData.cpp:168 +#: src/slic3r/GUI/GUI_Preview.cpp:239 src/libslic3r/PrintConfig.cpp:2068 +#: src/libslic3r/PrintConfig.cpp:2079 src/libslic3r/GCode/PreviewData.cpp:168 msgid "Top solid infill" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:239 src/libslic3r/GCode/PreviewData.cpp:169 +#: src/slic3r/GUI/GUI_Preview.cpp:240 src/libslic3r/GCode/PreviewData.cpp:169 msgid "Bridge infill" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:240 src/libslic3r/PrintConfig.cpp:881 +#: src/slic3r/GUI/GUI_Preview.cpp:241 src/libslic3r/PrintConfig.cpp:895 #: src/libslic3r/GCode/PreviewData.cpp:170 msgid "Gap fill" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:241 src/slic3r/GUI/Tab.cpp:1056 +#: src/slic3r/GUI/GUI_Preview.cpp:242 src/slic3r/GUI/Tab.cpp:1061 #: src/libslic3r/GCode/PreviewData.cpp:171 msgid "Skirt" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:243 src/libslic3r/PrintConfig.cpp:1939 +#: src/slic3r/GUI/GUI_Preview.cpp:244 src/libslic3r/PrintConfig.cpp:1954 #: src/libslic3r/GCode/PreviewData.cpp:173 msgid "Support material interface" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:244 src/slic3r/GUI/Tab.cpp:1136 +#: src/slic3r/GUI/GUI_Preview.cpp:245 src/slic3r/GUI/Tab.cpp:1141 #: src/libslic3r/GCode/PreviewData.cpp:174 msgid "Wipe tower" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:249 src/libslic3r/PrintConfig.cpp:2086 +#: src/slic3r/GUI/GUI_Preview.cpp:250 src/libslic3r/PrintConfig.cpp:2102 msgid "Travel" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:250 +#: src/slic3r/GUI/GUI_Preview.cpp:251 msgid "Retractions" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:251 +#: src/slic3r/GUI/GUI_Preview.cpp:252 msgid "Unretractions" msgstr "" -#: src/slic3r/GUI/GUI_Preview.cpp:252 +#: src/slic3r/GUI/GUI_Preview.cpp:253 msgid "Shells" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:13 src/slic3r/GUI/MainFrame.cpp:608 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:13 src/slic3r/GUI/MainFrame.cpp:672 msgid "Keyboard Shortcuts" msgstr "" @@ -1749,8 +2051,8 @@ msgstr "" msgid "Load Config from .ini/amf/3mf/gcode" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:107 src/slic3r/GUI/Plater.cpp:740 -#: src/slic3r/GUI/Plater.cpp:3907 src/libslic3r/PrintConfig.cpp:3000 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:107 src/slic3r/GUI/Plater.cpp:822 +#: src/slic3r/GUI/Plater.cpp:4687 src/libslic3r/PrintConfig.cpp:3127 msgid "Export G-code" msgstr "" @@ -1877,642 +2179,675 @@ msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:147 msgid "" +"Press to scale selection to fit print volume\n" +"in Gizmo scale" +msgstr "" + +#: src/slic3r/GUI/KBShortcutsDialog.cpp:148 +msgid "" "Press to activate deselection rectangle\n" "or to scale or rotate selected objects\n" "around their own center" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:148 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:149 msgid "Press to activate one direction scaling in Gizmo scale" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:149 -msgid "Zoom to Bed" -msgstr "" - #: src/slic3r/GUI/KBShortcutsDialog.cpp:150 -msgid "Zoom to all objects in scene, if none selected" +msgid "Change camera type" msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:151 -msgid "Zoom to selected object" +msgid "Zoom to Bed" msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:152 -msgid "Zoom in" +msgid "Zoom to all objects in scene, if none selected" msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:153 -msgid "Zoom out" +msgid "Zoom to selected object" msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:154 -msgid "Unselect gizmo / Clear selection" +msgid "Zoom in" +msgstr "" + +#: src/slic3r/GUI/KBShortcutsDialog.cpp:155 +msgid "Zoom out" msgstr "" #: src/slic3r/GUI/KBShortcutsDialog.cpp:156 +msgid "Unselect gizmo / Clear selection" +msgstr "" + +#: src/slic3r/GUI/KBShortcutsDialog.cpp:158 +msgid "Toggle picking pass texture rendering on/off" +msgstr "" + +#: src/slic3r/GUI/KBShortcutsDialog.cpp:161 msgid "Plater Shortcuts" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:171 -#: src/slic3r/GUI/KBShortcutsDialog.cpp:182 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:176 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:187 msgid "Arrow Up" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:171 -#: src/slic3r/GUI/KBShortcutsDialog.cpp:173 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:176 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:178 msgid "Upper Layer" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:172 -#: src/slic3r/GUI/KBShortcutsDialog.cpp:183 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:177 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:188 msgid "Arrow Down" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:172 -#: src/slic3r/GUI/KBShortcutsDialog.cpp:174 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:177 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:179 msgid "Lower Layer" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:176 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:181 msgid "Preview Shortcuts" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:182 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:187 msgid "Move current slider thumb Up" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:183 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:188 msgid "Move current slider thumb Down" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:184 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:189 msgid "Arrow Left" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:184 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:189 msgid "Set upper thumb to current slider thumb" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:185 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:190 msgid "Arrow Right" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:185 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:190 msgid "Set lower thumb to current slider thumb" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:186 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:191 msgid "Add color change marker for current layer" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:187 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:192 msgid "Delete color change marker for current layer" msgstr "" -#: src/slic3r/GUI/KBShortcutsDialog.cpp:189 +#: src/slic3r/GUI/KBShortcutsDialog.cpp:194 msgid "Layers Slider Shortcuts" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:61 +#: src/slic3r/GUI/MainFrame.cpp:62 msgid "" " - Remember to check for updates at http://github.com/prusa3d/PrusaSlicer/" "releases" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:150 +#: src/slic3r/GUI/MainFrame.cpp:157 msgid "based on Slic3r" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:180 +#: src/slic3r/GUI/MainFrame.cpp:187 msgid "Plater" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:374 +#: src/slic3r/GUI/MainFrame.cpp:393 msgid "&New Project" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:374 +#: src/slic3r/GUI/MainFrame.cpp:393 msgid "Start a new project" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:377 +#: src/slic3r/GUI/MainFrame.cpp:396 msgid "&Open Project" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:377 +#: src/slic3r/GUI/MainFrame.cpp:396 msgid "Open a project file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:380 +#: src/slic3r/GUI/MainFrame.cpp:401 +msgid "Recent projects" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:410 +msgid "The selected project is no more available" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:410 src/slic3r/GUI/MainFrame.cpp:747 +#: src/slic3r/GUI/PrintHostDialogs.cpp:231 +msgid "Error" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:434 msgid "&Save Project" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:380 +#: src/slic3r/GUI/MainFrame.cpp:434 msgid "Save current project file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:384 src/slic3r/GUI/MainFrame.cpp:386 +#: src/slic3r/GUI/MainFrame.cpp:438 src/slic3r/GUI/MainFrame.cpp:440 msgid "Save Project &as" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:384 src/slic3r/GUI/MainFrame.cpp:386 +#: src/slic3r/GUI/MainFrame.cpp:438 src/slic3r/GUI/MainFrame.cpp:440 msgid "Save current project file as" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:394 +#: src/slic3r/GUI/MainFrame.cpp:448 msgid "Import STL/OBJ/AM&F/3MF" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:394 +#: src/slic3r/GUI/MainFrame.cpp:448 msgid "Load a model" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:398 +#: src/slic3r/GUI/MainFrame.cpp:452 msgid "Import &Config" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:398 +#: src/slic3r/GUI/MainFrame.cpp:452 msgid "Load exported configuration file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:400 +#: src/slic3r/GUI/MainFrame.cpp:454 msgid "Import Config from &project" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:400 +#: src/slic3r/GUI/MainFrame.cpp:454 msgid "Load configuration from project file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:403 +#: src/slic3r/GUI/MainFrame.cpp:457 msgid "Import Config &Bundle" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:403 +#: src/slic3r/GUI/MainFrame.cpp:457 msgid "Load presets from a bundle" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:405 +#: src/slic3r/GUI/MainFrame.cpp:459 msgid "&Import" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:408 src/slic3r/GUI/MainFrame.cpp:644 +#: src/slic3r/GUI/MainFrame.cpp:462 src/slic3r/GUI/MainFrame.cpp:708 msgid "Export &G-code" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:408 +#: src/slic3r/GUI/MainFrame.cpp:462 msgid "Export current plate as G-code" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:413 +#: src/slic3r/GUI/MainFrame.cpp:466 src/slic3r/GUI/MainFrame.cpp:709 +msgid "S&end G-code" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:466 +msgid "Send to print current plate as G-code" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:471 msgid "Export plate as &STL" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:413 +#: src/slic3r/GUI/MainFrame.cpp:471 msgid "Export current plate as STL" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:416 +#: src/slic3r/GUI/MainFrame.cpp:474 msgid "Export plate as STL including supports" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:416 +#: src/slic3r/GUI/MainFrame.cpp:474 msgid "Export current plate as STL including supports" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:419 +#: src/slic3r/GUI/MainFrame.cpp:477 msgid "Export plate as &AMF" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:419 +#: src/slic3r/GUI/MainFrame.cpp:477 msgid "Export current plate as AMF" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:423 +#: src/slic3r/GUI/MainFrame.cpp:481 msgid "Export &Config" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:423 +#: src/slic3r/GUI/MainFrame.cpp:481 msgid "Export current configuration to file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:425 +#: src/slic3r/GUI/MainFrame.cpp:483 msgid "Export Config &Bundle" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:425 +#: src/slic3r/GUI/MainFrame.cpp:483 msgid "Export all presets to file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:427 +#: src/slic3r/GUI/MainFrame.cpp:485 msgid "&Export" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:433 +#: src/slic3r/GUI/MainFrame.cpp:491 msgid "Quick Slice" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:433 +#: src/slic3r/GUI/MainFrame.cpp:491 msgid "Slice a file into a G-code" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:439 +#: src/slic3r/GUI/MainFrame.cpp:497 msgid "Quick Slice and Save As" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:439 +#: src/slic3r/GUI/MainFrame.cpp:497 msgid "Slice a file into a G-code, save as" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:445 +#: src/slic3r/GUI/MainFrame.cpp:503 msgid "Repeat Last Quick Slice" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:445 +#: src/slic3r/GUI/MainFrame.cpp:503 msgid "Repeat last quick slice" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:453 +#: src/slic3r/GUI/MainFrame.cpp:511 msgid "(Re)Slice No&w" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:453 +#: src/slic3r/GUI/MainFrame.cpp:511 msgid "Start new slicing process" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:457 +#: src/slic3r/GUI/MainFrame.cpp:515 msgid "&Repair STL file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:457 +#: src/slic3r/GUI/MainFrame.cpp:515 msgid "Automatically repair an STL file" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:460 +#: src/slic3r/GUI/MainFrame.cpp:518 msgid "&Quit" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:460 +#: src/slic3r/GUI/MainFrame.cpp:518 #, possible-c-format msgid "Quit %s" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:485 +#: src/slic3r/GUI/MainFrame.cpp:543 msgid "&Select all" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:488 +#: src/slic3r/GUI/MainFrame.cpp:544 msgid "Selects all objects" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:491 +#: src/slic3r/GUI/MainFrame.cpp:546 msgid "D&eselect all" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:492 +#: src/slic3r/GUI/MainFrame.cpp:547 msgid "Deselects all objects" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:496 +#: src/slic3r/GUI/MainFrame.cpp:550 msgid "&Delete selected" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:497 +#: src/slic3r/GUI/MainFrame.cpp:551 msgid "Deletes the current selection" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:499 +#: src/slic3r/GUI/MainFrame.cpp:553 msgid "Delete &all" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:500 +#: src/slic3r/GUI/MainFrame.cpp:554 msgid "Deletes all objects" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:504 +#: src/slic3r/GUI/MainFrame.cpp:558 +msgid "&Undo" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:561 +msgid "&Redo" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:566 msgid "&Copy" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:505 +#: src/slic3r/GUI/MainFrame.cpp:567 msgid "Copy selection to clipboard" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:507 +#: src/slic3r/GUI/MainFrame.cpp:569 msgid "&Paste" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:508 +#: src/slic3r/GUI/MainFrame.cpp:570 msgid "Paste clipboard" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:517 +#: src/slic3r/GUI/MainFrame.cpp:579 msgid "&Plater Tab" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:517 +#: src/slic3r/GUI/MainFrame.cpp:579 msgid "Show the plater" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:524 +#: src/slic3r/GUI/MainFrame.cpp:586 msgid "P&rint Settings Tab" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:524 +#: src/slic3r/GUI/MainFrame.cpp:586 msgid "Show the print settings" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:526 src/slic3r/GUI/MainFrame.cpp:648 +#: src/slic3r/GUI/MainFrame.cpp:588 src/slic3r/GUI/MainFrame.cpp:711 msgid "&Filament Settings Tab" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:526 +#: src/slic3r/GUI/MainFrame.cpp:588 msgid "Show the filament settings" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:529 +#: src/slic3r/GUI/MainFrame.cpp:591 msgid "Print&er Settings Tab" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:529 +#: src/slic3r/GUI/MainFrame.cpp:591 msgid "Show the printer settings" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:533 +#: src/slic3r/GUI/MainFrame.cpp:595 msgid "3&D" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:533 +#: src/slic3r/GUI/MainFrame.cpp:595 msgid "Show the 3D editing view" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:536 +#: src/slic3r/GUI/MainFrame.cpp:598 msgid "Pre&view" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:536 +#: src/slic3r/GUI/MainFrame.cpp:598 msgid "Show the 3D slices preview" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:555 +#: src/slic3r/GUI/MainFrame.cpp:617 msgid "Print &Host Upload Queue" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:555 +#: src/slic3r/GUI/MainFrame.cpp:617 msgid "Display the Print Host Upload Queue window" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:564 +#: src/slic3r/GUI/MainFrame.cpp:626 msgid "Iso" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:564 +#: src/slic3r/GUI/MainFrame.cpp:626 msgid "Iso View" msgstr "" #. TRN To be shown in the main menu View->Top -#: src/slic3r/GUI/MainFrame.cpp:568 -msgid "Top" -msgstr "" - #. TRN To be shown in Print Settings "Top solid layers" -#: src/libslic3r/PrintConfig.cpp:2078 -msgctxt "Layers" +#: src/slic3r/GUI/MainFrame.cpp:630 src/libslic3r/PrintConfig.cpp:2094 msgid "Top" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:568 +#: src/slic3r/GUI/MainFrame.cpp:630 msgid "Top View" msgstr "" #. TRN To be shown in the main menu View->Bottom -#: src/slic3r/GUI/MainFrame.cpp:571 -msgid "Bottom" -msgstr "" - #. TRN To be shown in Print Settings "Bottom solid layers" -#: src/libslic3r/PrintConfig.cpp:150 -msgctxt "Layers" +#: src/slic3r/GUI/MainFrame.cpp:633 src/libslic3r/PrintConfig.cpp:159 msgid "Bottom" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:571 +#: src/slic3r/GUI/MainFrame.cpp:633 msgid "Bottom View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:573 +#: src/slic3r/GUI/MainFrame.cpp:635 msgid "Front" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:573 +#: src/slic3r/GUI/MainFrame.cpp:635 msgid "Front View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:575 src/libslic3r/PrintConfig.cpp:1597 +#: src/slic3r/GUI/MainFrame.cpp:637 src/libslic3r/PrintConfig.cpp:1611 msgid "Rear" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:575 +#: src/slic3r/GUI/MainFrame.cpp:637 msgid "Rear View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:577 +#: src/slic3r/GUI/MainFrame.cpp:639 msgid "Left" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:577 +#: src/slic3r/GUI/MainFrame.cpp:639 msgid "Left View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:579 +#: src/slic3r/GUI/MainFrame.cpp:641 msgid "Right" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:579 +#: src/slic3r/GUI/MainFrame.cpp:641 msgid "Right View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:586 +#: src/slic3r/GUI/MainFrame.cpp:648 msgid "Prusa 3D &Drivers" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:586 +#: src/slic3r/GUI/MainFrame.cpp:648 msgid "Open the Prusa3D drivers download page in your browser" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:588 +#: src/slic3r/GUI/MainFrame.cpp:650 msgid "Software &Releases" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:588 +#: src/slic3r/GUI/MainFrame.cpp:650 msgid "Open the software releases page in your browser" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:594 +#: src/slic3r/GUI/MainFrame.cpp:656 #, possible-c-format msgid "%s &Website" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:595 +#: src/slic3r/GUI/MainFrame.cpp:657 #, possible-c-format msgid "Open the %s website in your browser" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:601 +#: src/slic3r/GUI/MainFrame.cpp:663 msgid "System &Info" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:601 +#: src/slic3r/GUI/MainFrame.cpp:663 msgid "Show system information" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:603 +#: src/slic3r/GUI/MainFrame.cpp:665 msgid "Show &Configuration Folder" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:603 +#: src/slic3r/GUI/MainFrame.cpp:665 msgid "Show user configuration folder (datadir)" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:605 +#: src/slic3r/GUI/MainFrame.cpp:667 msgid "Report an I&ssue" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:605 +#: src/slic3r/GUI/MainFrame.cpp:667 #, possible-c-format msgid "Report an issue on %s" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:607 +#: src/slic3r/GUI/MainFrame.cpp:669 #, possible-c-format msgid "&About %s" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:607 +#: src/slic3r/GUI/MainFrame.cpp:669 msgid "Show about dialog" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:610 +#: src/slic3r/GUI/MainFrame.cpp:672 msgid "Show the list of the keyboard shortcuts" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:618 +#: src/slic3r/GUI/MainFrame.cpp:680 msgid "&File" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:619 +#: src/slic3r/GUI/MainFrame.cpp:681 msgid "&Edit" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:620 +#: src/slic3r/GUI/MainFrame.cpp:682 msgid "&Window" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:621 +#: src/slic3r/GUI/MainFrame.cpp:683 msgid "&View" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:624 +#: src/slic3r/GUI/MainFrame.cpp:686 msgid "&Help" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:646 src/slic3r/GUI/Plater.cpp:3907 -msgid "Export" +#: src/slic3r/GUI/MainFrame.cpp:708 +msgid "E&xport" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:648 +#: src/slic3r/GUI/MainFrame.cpp:709 +msgid "S&end to print" +msgstr "" + +#: src/slic3r/GUI/MainFrame.cpp:711 msgid "Mate&rial Settings Tab" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:669 +#: src/slic3r/GUI/MainFrame.cpp:732 msgid "Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:683 +#: src/slic3r/GUI/MainFrame.cpp:746 msgid "No previously sliced file." msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:684 src/slic3r/GUI/PrintHostDialogs.cpp:231 -msgid "Error" -msgstr "" - -#: src/slic3r/GUI/MainFrame.cpp:689 +#: src/slic3r/GUI/MainFrame.cpp:752 msgid "Previously sliced file (" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:689 +#: src/slic3r/GUI/MainFrame.cpp:752 msgid ") not found." msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:690 +#: src/slic3r/GUI/MainFrame.cpp:753 msgid "File Not Found" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:725 +#: src/slic3r/GUI/MainFrame.cpp:788 #, possible-c-format msgid "Save %s file as:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:725 +#: src/slic3r/GUI/MainFrame.cpp:788 msgid "SVG" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:725 +#: src/slic3r/GUI/MainFrame.cpp:788 msgid "G-code" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:740 +#: src/slic3r/GUI/MainFrame.cpp:803 msgid "Save zip file as:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:750 src/slic3r/GUI/Plater.cpp:2476 -#: src/slic3r/GUI/Plater.cpp:3695 src/slic3r/GUI/Tab.cpp:1165 -#: src/slic3r/GUI/Tab.cpp:3493 +#: src/slic3r/GUI/MainFrame.cpp:815 src/slic3r/GUI/Plater.cpp:2933 +#: src/slic3r/GUI/Plater.cpp:4418 src/slic3r/GUI/Tab.cpp:1170 +#: src/slic3r/GUI/Tab.cpp:3700 msgid "Slicing" msgstr "" #. TRN "Processing input_file_basename" -#: src/slic3r/GUI/MainFrame.cpp:754 +#: src/slic3r/GUI/MainFrame.cpp:817 #, possible-c-format msgid "Processing %s" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:777 +#: src/slic3r/GUI/MainFrame.cpp:840 msgid " was successfully sliced." msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:779 +#: src/slic3r/GUI/MainFrame.cpp:842 msgid "Slicing Done!" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:794 +#: src/slic3r/GUI/MainFrame.cpp:857 msgid "Select the STL file to repair:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:807 +#: src/slic3r/GUI/MainFrame.cpp:870 msgid "Save OBJ file (less prone to coordinate errors than STL) as:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:822 +#: src/slic3r/GUI/MainFrame.cpp:885 msgid "Your file was repaired." msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:822 src/libslic3r/PrintConfig.cpp:3094 +#: src/slic3r/GUI/MainFrame.cpp:885 src/libslic3r/PrintConfig.cpp:3221 msgid "Repair" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:836 +#: src/slic3r/GUI/MainFrame.cpp:899 msgid "Save configuration as:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:856 src/slic3r/GUI/MainFrame.cpp:920 +#: src/slic3r/GUI/MainFrame.cpp:919 src/slic3r/GUI/MainFrame.cpp:983 msgid "Select configuration to load:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:893 +#: src/slic3r/GUI/MainFrame.cpp:956 msgid "Save presets bundle as:" msgstr "" -#: src/slic3r/GUI/MainFrame.cpp:944 +#: src/slic3r/GUI/MainFrame.cpp:1007 #, possible-c-format msgid "%d presets successfully imported." msgstr "" @@ -2527,493 +2862,590 @@ msgstr "" msgid "%s has encountered an error" msgstr "" -#: src/slic3r/GUI/Plater.cpp:137 +#: src/slic3r/GUI/Plater.cpp:146 msgid "Volume" msgstr "" -#: src/slic3r/GUI/Plater.cpp:138 +#: src/slic3r/GUI/Plater.cpp:147 msgid "Facets" msgstr "" -#: src/slic3r/GUI/Plater.cpp:139 +#: src/slic3r/GUI/Plater.cpp:148 msgid "Materials" msgstr "" -#: src/slic3r/GUI/Plater.cpp:142 +#: src/slic3r/GUI/Plater.cpp:151 msgid "Manifold" msgstr "" -#: src/slic3r/GUI/Plater.cpp:192 +#: src/slic3r/GUI/Plater.cpp:201 msgid "Sliced Info" msgstr "" -#: src/slic3r/GUI/Plater.cpp:211 src/slic3r/GUI/Plater.cpp:1049 +#: src/slic3r/GUI/Plater.cpp:220 src/slic3r/GUI/Plater.cpp:1135 msgid "Used Filament (m)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:212 +#: src/slic3r/GUI/Plater.cpp:221 msgid "Used Filament (mm³)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:213 +#: src/slic3r/GUI/Plater.cpp:222 msgid "Used Filament (g)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:214 +#: src/slic3r/GUI/Plater.cpp:223 msgid "Used Material (unit)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:215 src/slic3r/GUI/Plater.cpp:1064 -#: src/libslic3r/PrintConfig.cpp:728 +#: src/slic3r/GUI/Plater.cpp:224 src/slic3r/GUI/Plater.cpp:1150 +#: src/libslic3r/PrintConfig.cpp:742 msgid "Cost" msgstr "" -#: src/slic3r/GUI/Plater.cpp:216 src/slic3r/GUI/Plater.cpp:1036 -#: src/slic3r/GUI/Plater.cpp:1078 +#: src/slic3r/GUI/Plater.cpp:225 src/slic3r/GUI/Plater.cpp:1122 +#: src/slic3r/GUI/Plater.cpp:1164 msgid "Estimated printing time" msgstr "" -#: src/slic3r/GUI/Plater.cpp:217 +#: src/slic3r/GUI/Plater.cpp:226 msgid "Number of tool changes" msgstr "" -#: src/slic3r/GUI/Plater.cpp:291 +#: src/slic3r/GUI/Plater.cpp:317 msgid "Click to edit preset" msgstr "" -#: src/slic3r/GUI/Plater.cpp:431 +#: src/slic3r/GUI/Plater.cpp:469 msgid "Select what kind of support do you need" msgstr "" -#: src/slic3r/GUI/Plater.cpp:433 src/libslic3r/PrintConfig.cpp:1850 -#: src/libslic3r/PrintConfig.cpp:2458 +#: src/slic3r/GUI/Plater.cpp:471 src/libslic3r/PrintConfig.cpp:1865 +#: src/libslic3r/PrintConfig.cpp:2529 msgid "Support on build plate only" msgstr "" -#: src/slic3r/GUI/Plater.cpp:434 src/slic3r/GUI/Plater.cpp:527 +#: src/slic3r/GUI/Plater.cpp:472 src/slic3r/GUI/Plater.cpp:587 msgid "For support enforcers only" msgstr "" -#: src/slic3r/GUI/Plater.cpp:435 +#: src/slic3r/GUI/Plater.cpp:473 msgid "Everywhere" msgstr "" -#: src/slic3r/GUI/Plater.cpp:453 src/slic3r/GUI/Tab.cpp:1062 +#: src/slic3r/GUI/Plater.cpp:505 src/slic3r/GUI/Tab.cpp:1067 msgid "Brim" msgstr "" -#: src/slic3r/GUI/Plater.cpp:455 +#: src/slic3r/GUI/Plater.cpp:507 msgid "" "This flag enables the brim that will be printed around each object on the " "first layer." msgstr "" -#: src/slic3r/GUI/Plater.cpp:463 +#: src/slic3r/GUI/Plater.cpp:515 msgid "Purging volumes" msgstr "" -#: src/slic3r/GUI/Plater.cpp:688 +#: src/slic3r/GUI/Plater.cpp:766 msgid "Print settings" msgstr "" -#: src/slic3r/GUI/Plater.cpp:689 src/slic3r/GUI/Tab.cpp:1506 -#: src/slic3r/GUI/Tab.cpp:1507 +#: src/slic3r/GUI/Plater.cpp:767 src/slic3r/GUI/Tab.cpp:1604 +#: src/slic3r/GUI/Tab.cpp:1605 msgid "Filament" msgstr "" -#: src/slic3r/GUI/Plater.cpp:690 +#: src/slic3r/GUI/Plater.cpp:768 msgid "SLA print settings" msgstr "" -#: src/slic3r/GUI/Plater.cpp:691 src/slic3r/GUI/Preset.cpp:1285 +#: src/slic3r/GUI/Plater.cpp:769 src/slic3r/GUI/Preset.cpp:1310 msgid "SLA material" msgstr "" -#: src/slic3r/GUI/Plater.cpp:692 +#: src/slic3r/GUI/Plater.cpp:770 msgid "Printer" msgstr "" -#: src/slic3r/GUI/Plater.cpp:738 src/slic3r/GUI/Plater.cpp:3908 +#: src/slic3r/GUI/Plater.cpp:820 src/slic3r/GUI/Plater.cpp:4688 msgid "Send to printer" msgstr "" -#: src/slic3r/GUI/Plater.cpp:741 src/slic3r/GUI/Plater.cpp:2476 -#: src/slic3r/GUI/Plater.cpp:3698 +#: src/slic3r/GUI/Plater.cpp:823 src/slic3r/GUI/Plater.cpp:2933 +#: src/slic3r/GUI/Plater.cpp:4421 msgid "Slice now" msgstr "" -#: src/slic3r/GUI/Plater.cpp:881 +#: src/slic3r/GUI/Plater.cpp:963 msgid "Hold Shift to Slice & Export G-code" msgstr "" -#: src/slic3r/GUI/Plater.cpp:982 +#: src/slic3r/GUI/Plater.cpp:1068 #, possible-c-format msgid "%d (%d shells)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:987 +#: src/slic3r/GUI/Plater.cpp:1073 #, possible-c-format msgid "Auto-repaired (%d errors)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:990 +#: src/slic3r/GUI/Plater.cpp:1076 #, possible-c-format msgid "" "%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d " "facets reversed, %d backwards edges" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1000 +#: src/slic3r/GUI/Plater.cpp:1086 msgid "Yes" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1023 +#: src/slic3r/GUI/Plater.cpp:1109 msgid "Used Material (ml)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1026 +#: src/slic3r/GUI/Plater.cpp:1112 msgid "object(s)" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1026 +#: src/slic3r/GUI/Plater.cpp:1112 msgid "supports and pad" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1051 src/slic3r/GUI/Plater.cpp:1066 +#: src/slic3r/GUI/Plater.cpp:1137 src/slic3r/GUI/Plater.cpp:1152 msgid "objects" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1051 src/slic3r/GUI/Plater.cpp:1066 +#: src/slic3r/GUI/Plater.cpp:1137 src/slic3r/GUI/Plater.cpp:1152 msgid "wipe tower" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1081 +#: src/slic3r/GUI/Plater.cpp:1167 msgid "normal mode" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1085 +#: src/slic3r/GUI/Plater.cpp:1171 src/slic3r/GUI/Plater.cpp:1180 +msgid "Color " +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:1176 msgid "stealth mode" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1631 +#: src/slic3r/GUI/Plater.cpp:1271 +msgid "Load File" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:1275 +msgid "Load Files" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:1503 +msgid "ERROR: not enough resources to execute a new job." +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2056 +msgid "New Project" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2173 msgid "Loading" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1641 +#: src/slic3r/GUI/Plater.cpp:2183 #, possible-c-format msgid "Processing input file %s\n" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1699 +#: src/slic3r/GUI/Plater.cpp:2211 +msgid "" +"You can't to load SLA project if there is at least one multi-part object on " +"the bed" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2212 src/slic3r/GUI/Tab.cpp:3064 +msgid "Please check your object list before preset changing." +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2255 msgid "" "This file contains several objects positioned at multiple heights. Instead " "of considering them as multiple objects, should I consider\n" "this file as a single object having multiple parts?\n" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1702 src/slic3r/GUI/Plater.cpp:1810 +#: src/slic3r/GUI/Plater.cpp:2258 src/slic3r/GUI/Plater.cpp:2310 msgid "Multi-part object detected" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1753 +#: src/slic3r/GUI/Plater.cpp:2265 msgid "" "This file cannot be loaded in a simple mode. Do you want to switch to an " "advanced mode?\n" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1754 +#: src/slic3r/GUI/Plater.cpp:2266 msgid "Detected advanced data" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1787 +#: src/slic3r/GUI/Plater.cpp:2287 #, possible-c-format msgid "" "You can't to add the object(s) from %s because of one or some of them " "is(are) multi-part" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1807 +#: src/slic3r/GUI/Plater.cpp:2307 msgid "" "Multiple objects were loaded for a multi-material printer.\n" "Instead of considering them as multiple objects, should I consider\n" "these files to represent a single object having multiple parts?\n" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1823 +#: src/slic3r/GUI/Plater.cpp:2323 msgid "Loaded" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1921 +#: src/slic3r/GUI/Plater.cpp:2418 msgid "" "Your object appears to be too large, so it was automatically scaled down to " "fit your print bed." msgstr "" -#: src/slic3r/GUI/Plater.cpp:1922 +#: src/slic3r/GUI/Plater.cpp:2419 msgid "Object too large?" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1979 +#: src/slic3r/GUI/Plater.cpp:2476 msgid "Export STL file:" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1986 +#: src/slic3r/GUI/Plater.cpp:2483 msgid "Export AMF file:" msgstr "" -#: src/slic3r/GUI/Plater.cpp:1992 +#: src/slic3r/GUI/Plater.cpp:2489 msgid "Save file as:" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2160 -msgid "Arranging canceled" +#: src/slic3r/GUI/Plater.cpp:2592 +msgid "Delete Object" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2163 +#: src/slic3r/GUI/Plater.cpp:2603 +msgid "Reset Project" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2630 src/slic3r/GUI/Plater.cpp:3517 +msgid "Mirror" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2643 +msgid "Optimize Rotation" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2689 msgid "Arranging" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2200 +#: src/slic3r/GUI/Plater.cpp:2712 msgid "Could not arrange model objects! Some geometries may be invalid." msgstr "" -#: src/slic3r/GUI/Plater.cpp:2207 +#: src/slic3r/GUI/Plater.cpp:2718 +msgid "Arranging canceled." +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2719 msgid "Arranging done." msgstr "" -#: src/slic3r/GUI/Plater.cpp:2248 -msgid "Orientation search canceled" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:2253 +#: src/slic3r/GUI/Plater.cpp:2735 msgid "Searching for optimal orientation" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2315 +#: src/slic3r/GUI/Plater.cpp:2768 +msgid "Orientation search canceled." +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2769 msgid "Orientation found." msgstr "" -#: src/slic3r/GUI/Plater.cpp:2335 +#: src/slic3r/GUI/Plater.cpp:2785 msgid "" "The selected object can't be split because it contains more than one volume/" "material." msgstr "" -#: src/slic3r/GUI/Plater.cpp:2461 +#: src/slic3r/GUI/Plater.cpp:2796 +msgid "Split to Objects" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:2918 msgid "Invalid data" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2470 +#: src/slic3r/GUI/Plater.cpp:2927 msgid "Ready to slice" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2508 src/slic3r/GUI/PrintHostDialogs.cpp:232 +#: src/slic3r/GUI/Plater.cpp:2965 src/slic3r/GUI/PrintHostDialogs.cpp:232 msgid "Cancelling" msgstr "" -#: src/slic3r/GUI/Plater.cpp:2525 +#: src/slic3r/GUI/Plater.cpp:2982 msgid "Another export job is currently running." msgstr "" -#: src/slic3r/GUI/Plater.cpp:2786 -msgid "Export failed" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:2791 src/slic3r/GUI/PrintHostDialogs.cpp:233 -msgid "Cancelled" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:2877 src/slic3r/GUI/Plater.cpp:2889 -#: src/slic3r/GUI/Plater.cpp:3000 -msgid "Increase copies" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:2994 src/slic3r/GUI/Plater.cpp:3013 -msgid "Remove the selected object" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3000 -msgid "Place one more copy of the selected object" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3002 -msgid "Decrease copies" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3002 -msgid "Remove one copy of the selected object" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3004 -msgid "Set number of copies" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3004 -msgid "Change the number of copies of the selected object" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3020 +#: src/slic3r/GUI/Plater.cpp:3036 src/slic3r/GUI/Plater.cpp:3493 msgid "Reload from Disk" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3020 +#: src/slic3r/GUI/Plater.cpp:3072 +msgid "Fix Throught NetFabb" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3254 +msgid "Export failed" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3259 src/slic3r/GUI/PrintHostDialogs.cpp:233 +msgid "Cancelled" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3347 src/slic3r/GUI/Plater.cpp:3359 +#: src/slic3r/GUI/Plater.cpp:3473 +msgid "Increase copies" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3467 src/slic3r/GUI/Plater.cpp:3486 +msgid "Remove the selected object" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3473 +msgid "Place one more copy of the selected object" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3475 +msgid "Decrease copies" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3475 +msgid "Remove one copy of the selected object" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3477 +msgid "Set number of copies" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3477 +msgid "Change the number of copies of the selected object" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3493 msgid "Reload the selected file from Disk" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3023 +#: src/slic3r/GUI/Plater.cpp:3496 msgid "Export the selected object as STL file" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3035 +#: src/slic3r/GUI/Plater.cpp:3510 msgid "Along X axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3035 +#: src/slic3r/GUI/Plater.cpp:3510 msgid "Mirror the selected object along the X axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3037 +#: src/slic3r/GUI/Plater.cpp:3512 msgid "Along Y axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3037 +#: src/slic3r/GUI/Plater.cpp:3512 msgid "Mirror the selected object along the Y axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3039 +#: src/slic3r/GUI/Plater.cpp:3514 msgid "Along Z axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3039 +#: src/slic3r/GUI/Plater.cpp:3514 msgid "Mirror the selected object along the Z axis" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3042 -msgid "Mirror" -msgstr "" - -#: src/slic3r/GUI/Plater.cpp:3042 +#: src/slic3r/GUI/Plater.cpp:3517 msgid "Mirror the selected object" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3054 +#: src/slic3r/GUI/Plater.cpp:3529 msgid "To objects" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3054 src/slic3r/GUI/Plater.cpp:3070 +#: src/slic3r/GUI/Plater.cpp:3529 src/slic3r/GUI/Plater.cpp:3549 msgid "Split the selected object into individual objects" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3056 +#: src/slic3r/GUI/Plater.cpp:3531 msgid "To parts" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3056 src/slic3r/GUI/Plater.cpp:3084 +#: src/slic3r/GUI/Plater.cpp:3531 src/slic3r/GUI/Plater.cpp:3563 msgid "Split the selected object into individual sub-parts" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3059 src/slic3r/GUI/Plater.cpp:3070 -#: src/slic3r/GUI/Plater.cpp:3084 src/libslic3r/PrintConfig.cpp:3118 +#: src/slic3r/GUI/Plater.cpp:3534 src/slic3r/GUI/Plater.cpp:3549 +#: src/slic3r/GUI/Plater.cpp:3563 src/libslic3r/PrintConfig.cpp:3245 msgid "Split" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3059 +#: src/slic3r/GUI/Plater.cpp:3534 msgid "Split the selected object" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3076 +#: src/slic3r/GUI/Plater.cpp:3555 msgid "Optimize orientation" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3076 +#: src/slic3r/GUI/Plater.cpp:3555 msgid "Optimize the rotation of the object for better print results." msgstr "" -#: src/slic3r/GUI/Plater.cpp:3127 +#: src/slic3r/GUI/Plater.cpp:3595 msgid "3D editor view" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3138 src/slic3r/GUI/Tab.cpp:2325 +#: src/slic3r/GUI/Plater.cpp:3603 src/slic3r/GUI/Tab.cpp:2534 msgid "Preview" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3375 +#: src/slic3r/GUI/Plater.cpp:3831 +msgid "" +"%1% printer was active at the time the target Undo / Redo snapshot was " +"taken. Switching to %1% printer requires reloading of %1% presets." +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:3992 +msgid "Load Project" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4016 +msgid "Import Object" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4020 +msgid "Import Objects" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4075 msgid "All objects will be removed, continue ?" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3511 +#: src/slic3r/GUI/Plater.cpp:4083 +msgid "Delete Selected Objects" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4091 +msgid "Increase Instances" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4127 +msgid "Decrease Instances" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4163 +#, possible-c-format +msgid "Set numbers of copies to %d" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4193 +msgid "Cut by Plane" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4225 msgid "Save G-code file as:" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3511 +#: src/slic3r/GUI/Plater.cpp:4225 msgid "Save SL1 file as:" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3623 +#: src/slic3r/GUI/Plater.cpp:4337 #, possible-c-format msgid "STL file exported to %s" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3639 +#: src/slic3r/GUI/Plater.cpp:4353 #, possible-c-format msgid "AMF file exported to %s" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3642 +#: src/slic3r/GUI/Plater.cpp:4356 #, possible-c-format msgid "Error exporting AMF file %s" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3668 +#: src/slic3r/GUI/Plater.cpp:4382 #, possible-c-format msgid "3MF file exported to %s" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3673 +#: src/slic3r/GUI/Plater.cpp:4387 #, possible-c-format msgid "Error exporting 3MF file %s" msgstr "" -#: src/slic3r/GUI/Plater.cpp:3908 +#: src/slic3r/GUI/Plater.cpp:4687 +msgid "Export" +msgstr "" + +#: src/slic3r/GUI/Plater.cpp:4688 msgid "Send G-code" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:19 src/slic3r/GUI/Tab.cpp:1849 -#: src/slic3r/GUI/Tab.cpp:2050 +#: src/slic3r/GUI/Plater.cpp:4772 +msgid "Paste From Clipboard" +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:22 src/slic3r/GUI/Tab.cpp:1955 +#: src/slic3r/GUI/Tab.cpp:2193 msgid "General" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:36 +#: src/slic3r/GUI/Preferences.cpp:44 msgid "Remember output directory" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:38 +#: src/slic3r/GUI/Preferences.cpp:46 msgid "" "If this is enabled, Slic3r will prompt the last output directory instead of " "the one containing the input files." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:44 +#: src/slic3r/GUI/Preferences.cpp:52 msgid "Auto-center parts" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:46 +#: src/slic3r/GUI/Preferences.cpp:54 msgid "" "If this is enabled, Slic3r will auto-center objects around the print bed " "center." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:52 +#: src/slic3r/GUI/Preferences.cpp:60 msgid "Background processing" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:54 +#: src/slic3r/GUI/Preferences.cpp:62 msgid "" "If this is enabled, Slic3r will pre-process objects as soon as they're " "loaded in order to save time when exporting G-code." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:63 +#: src/slic3r/GUI/Preferences.cpp:71 msgid "" "If enabled, PrusaSlicer will check for the new versions of itself online. " "When a new version becomes available a notification is displayed at the next " @@ -3021,7 +3453,7 @@ msgid "" "notification mechanisms, no automatic installation is done." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:71 +#: src/slic3r/GUI/Preferences.cpp:79 msgid "" "If enabled, Slic3r downloads updates of built-in system presets in the " "background. These updates are downloaded into a separate temporary location. " @@ -3029,76 +3461,90 @@ msgid "" "startup." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:76 +#: src/slic3r/GUI/Preferences.cpp:84 msgid "Suppress \" - default - \" presets" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:78 +#: src/slic3r/GUI/Preferences.cpp:86 msgid "" "Suppress \" - default - \" presets in the Print / Filament / Printer " "selections once there are any other valid presets available." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:84 +#: src/slic3r/GUI/Preferences.cpp:92 msgid "Show incompatible print and filament presets" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:86 +#: src/slic3r/GUI/Preferences.cpp:94 msgid "" "When checked, the print and filament presets are shown in the preset editor " "even if they are marked as incompatible with the active printer" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:93 -msgid "Use legacy OpenGL 1.1 rendering" -msgstr "" - -#: src/slic3r/GUI/Preferences.cpp:95 -msgid "" -"If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may " -"try to check this checkbox. This will disable the layer height editing and " -"anti aliasing, so it is likely better to upgrade your graphics driver." -msgstr "" - -#: src/slic3r/GUI/Preferences.cpp:103 +#: src/slic3r/GUI/Preferences.cpp:101 msgid "Use Retina resolution for the 3D scene" msgstr "" -#: src/slic3r/GUI/Preferences.cpp:105 +#: src/slic3r/GUI/Preferences.cpp:103 msgid "" "If enabled, the 3D scene will be rendered in Retina resolution. If you are " "experiencing 3D performance problems, disabling this option may help." msgstr "" -#: src/slic3r/GUI/Preferences.cpp:130 +#: src/slic3r/GUI/Preferences.cpp:110 +msgid "Use perspective camera" +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:112 +msgid "" +"If enabled, use perspective camera. If not enabled, use orthographic camera." +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:117 +msgid "Use custom size for toolbar icons" +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:119 +msgid "If enabled, you can change size of toolbar icons manually." +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:144 #, possible-c-format msgid "You need to restart %s to make the changes effective." msgstr "" +#: src/slic3r/GUI/Preferences.cpp:192 +msgid "Icon size in a respect to the default size" +msgstr "" + +#: src/slic3r/GUI/Preferences.cpp:207 +msgid "Select toolbar icon size in respect to the default one." +msgstr "" + #: src/slic3r/GUI/Preset.cpp:212 msgid "modified" msgstr "" -#: src/slic3r/GUI/Preset.cpp:938 src/slic3r/GUI/Preset.cpp:978 -#: src/slic3r/GUI/Preset.cpp:1043 src/slic3r/GUI/Preset.cpp:1075 -#: src/slic3r/GUI/PresetBundle.cpp:1478 src/slic3r/GUI/PresetBundle.cpp:1543 +#: src/slic3r/GUI/Preset.cpp:963 src/slic3r/GUI/Preset.cpp:1003 +#: src/slic3r/GUI/Preset.cpp:1068 src/slic3r/GUI/Preset.cpp:1100 +#: src/slic3r/GUI/PresetBundle.cpp:1480 src/slic3r/GUI/PresetBundle.cpp:1545 msgid "System presets" msgstr "" -#: src/slic3r/GUI/Preset.cpp:982 src/slic3r/GUI/Preset.cpp:1079 -#: src/slic3r/GUI/PresetBundle.cpp:1548 +#: src/slic3r/GUI/Preset.cpp:1007 src/slic3r/GUI/Preset.cpp:1104 +#: src/slic3r/GUI/PresetBundle.cpp:1550 msgid "User presets" msgstr "" -#: src/slic3r/GUI/Preset.cpp:1011 src/slic3r/GUI/Tab.cpp:241 +#: src/slic3r/GUI/Preset.cpp:1036 src/slic3r/GUI/Tab.cpp:241 msgid "Add a new printer" msgstr "" -#: src/slic3r/GUI/Preset.cpp:1283 +#: src/slic3r/GUI/Preset.cpp:1308 msgid "filament" msgstr "" -#: src/slic3r/GUI/Preset.cpp:1284 +#: src/slic3r/GUI/Preset.cpp:1309 msgid "SLA print" msgstr "" @@ -3293,10 +3739,10 @@ msgid "Time" msgstr "" #: src/slic3r/GUI/RammingChart.cpp:76 src/slic3r/GUI/WipeTowerDialog.cpp:82 -#: src/libslic3r/PrintConfig.cpp:613 src/libslic3r/PrintConfig.cpp:657 -#: src/libslic3r/PrintConfig.cpp:672 src/libslic3r/PrintConfig.cpp:2278 -#: src/libslic3r/PrintConfig.cpp:2287 src/libslic3r/PrintConfig.cpp:2347 -#: src/libslic3r/PrintConfig.cpp:2354 +#: src/libslic3r/PrintConfig.cpp:627 src/libslic3r/PrintConfig.cpp:671 +#: src/libslic3r/PrintConfig.cpp:686 src/libslic3r/PrintConfig.cpp:2349 +#: src/libslic3r/PrintConfig.cpp:2358 src/libslic3r/PrintConfig.cpp:2418 +#: src/libslic3r/PrintConfig.cpp:2425 msgid "s" msgstr "" @@ -3304,20 +3750,20 @@ msgstr "" msgid "Volumetric speed" msgstr "" -#: src/slic3r/GUI/RammingChart.cpp:81 src/libslic3r/PrintConfig.cpp:570 -#: src/libslic3r/PrintConfig.cpp:1220 +#: src/slic3r/GUI/RammingChart.cpp:81 src/libslic3r/PrintConfig.cpp:584 +#: src/libslic3r/PrintConfig.cpp:1234 msgid "mm³/s" msgstr "" -#: src/slic3r/GUI/SysInfoDialog.cpp:44 +#: src/slic3r/GUI/SysInfoDialog.cpp:78 msgid "System Information" msgstr "" -#: src/slic3r/GUI/SysInfoDialog.cpp:120 +#: src/slic3r/GUI/SysInfoDialog.cpp:154 msgid "Copy to Clipboard" msgstr "" -#: src/slic3r/GUI/Tab.cpp:52 src/libslic3r/PrintConfig.cpp:230 +#: src/slic3r/GUI/Tab.cpp:52 src/libslic3r/PrintConfig.cpp:239 msgid "Compatible printers" msgstr "" @@ -3325,7 +3771,7 @@ msgstr "" msgid "Select the printers this profile is compatible with." msgstr "" -#: src/slic3r/GUI/Tab.cpp:58 src/libslic3r/PrintConfig.cpp:245 +#: src/slic3r/GUI/Tab.cpp:58 src/libslic3r/PrintConfig.cpp:254 msgid "Compatible print profiles" msgstr "" @@ -3349,204 +3795,206 @@ msgid "" "or click this button." msgstr "" -#: src/slic3r/GUI/Tab.cpp:920 -msgid "It's a default preset." -msgstr "" - #: src/slic3r/GUI/Tab.cpp:921 -msgid "It's a system preset." -msgstr "" - -#: src/slic3r/GUI/Tab.cpp:922 -#, possible-c-format -msgid "Current preset is inherited from %s" +msgid "This is a default preset." msgstr "" #: src/slic3r/GUI/Tab.cpp:923 -msgid "default preset" +msgid "This is a system preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:927 -msgid "It can't be deleted or modified." +#: src/slic3r/GUI/Tab.cpp:925 +msgid "Current preset is inherited from the default preset." msgstr "" #: src/slic3r/GUI/Tab.cpp:928 +#, possible-c-format +msgid "" +"Current preset is inherited from:\n" +"\t%s" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:932 +msgid "It can't be deleted or modified." +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:933 msgid "" "Any modifications should be saved as a new preset inherited from this one." msgstr "" -#: src/slic3r/GUI/Tab.cpp:929 +#: src/slic3r/GUI/Tab.cpp:934 msgid "To do that please specify a new name for the preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:933 +#: src/slic3r/GUI/Tab.cpp:938 msgid "Additional information:" msgstr "" -#: src/slic3r/GUI/Tab.cpp:939 +#: src/slic3r/GUI/Tab.cpp:944 msgid "printer model" msgstr "" -#: src/slic3r/GUI/Tab.cpp:947 +#: src/slic3r/GUI/Tab.cpp:952 msgid "default print profile" msgstr "" -#: src/slic3r/GUI/Tab.cpp:950 +#: src/slic3r/GUI/Tab.cpp:955 msgid "default filament profile" msgstr "" -#: src/slic3r/GUI/Tab.cpp:964 +#: src/slic3r/GUI/Tab.cpp:969 msgid "default SLA material profile" msgstr "" -#: src/slic3r/GUI/Tab.cpp:968 +#: src/slic3r/GUI/Tab.cpp:973 msgid "default SLA print profile" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1003 src/slic3r/GUI/Tab.cpp:3419 +#: src/slic3r/GUI/Tab.cpp:1008 src/slic3r/GUI/Tab.cpp:3649 msgid "Layers and perimeters" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1004 src/slic3r/GUI/Tab.cpp:1253 -#: src/libslic3r/PrintConfig.cpp:56 +#: src/slic3r/GUI/Tab.cpp:1009 src/slic3r/GUI/Tab.cpp:1257 +#: src/libslic3r/PrintConfig.cpp:66 msgid "Layer height" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1008 +#: src/slic3r/GUI/Tab.cpp:1013 msgid "Vertical shells" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1019 +#: src/slic3r/GUI/Tab.cpp:1024 msgid "Horizontal shells" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1020 src/libslic3r/PrintConfig.cpp:1745 +#: src/slic3r/GUI/Tab.cpp:1025 src/libslic3r/PrintConfig.cpp:1759 msgid "Solid layers" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1025 +#: src/slic3r/GUI/Tab.cpp:1030 msgid "Quality (slower slicing)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1043 +#: src/slic3r/GUI/Tab.cpp:1048 msgid "Reducing printing time" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1055 +#: src/slic3r/GUI/Tab.cpp:1060 msgid "Skirt and brim" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1072 +#: src/slic3r/GUI/Tab.cpp:1077 msgid "Raft" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1076 +#: src/slic3r/GUI/Tab.cpp:1081 msgid "Options for support material and raft" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1091 +#: src/slic3r/GUI/Tab.cpp:1096 msgid "Speed for print moves" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1103 +#: src/slic3r/GUI/Tab.cpp:1108 msgid "Speed for non-print moves" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1106 +#: src/slic3r/GUI/Tab.cpp:1111 msgid "Modifiers" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1109 +#: src/slic3r/GUI/Tab.cpp:1114 msgid "Acceleration control (advanced)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1116 +#: src/slic3r/GUI/Tab.cpp:1121 msgid "Autospeed (advanced)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1124 +#: src/slic3r/GUI/Tab.cpp:1129 msgid "Multiple Extruders" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1132 +#: src/slic3r/GUI/Tab.cpp:1137 msgid "Ooze prevention" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1149 +#: src/slic3r/GUI/Tab.cpp:1154 msgid "Extrusion width" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1159 +#: src/slic3r/GUI/Tab.cpp:1164 msgid "Overlap" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1162 +#: src/slic3r/GUI/Tab.cpp:1167 msgid "Flow" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1171 +#: src/slic3r/GUI/Tab.cpp:1176 msgid "Other" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1174 src/slic3r/GUI/Tab.cpp:3496 +#: src/slic3r/GUI/Tab.cpp:1179 src/slic3r/GUI/Tab.cpp:3703 msgid "Output options" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1175 +#: src/slic3r/GUI/Tab.cpp:1180 msgid "Sequential printing" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1177 +#: src/slic3r/GUI/Tab.cpp:1182 msgid "Extruder clearance (mm)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1186 src/slic3r/GUI/Tab.cpp:3497 +#: src/slic3r/GUI/Tab.cpp:1191 src/slic3r/GUI/Tab.cpp:3704 msgid "Output file" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1193 src/libslic3r/PrintConfig.cpp:1418 +#: src/slic3r/GUI/Tab.cpp:1198 src/libslic3r/PrintConfig.cpp:1432 msgid "Post-processing scripts" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1199 src/slic3r/GUI/Tab.cpp:1200 -#: src/slic3r/GUI/Tab.cpp:1612 src/slic3r/GUI/Tab.cpp:1613 -#: src/slic3r/GUI/Tab.cpp:2022 src/slic3r/GUI/Tab.cpp:2023 -#: src/slic3r/GUI/Tab.cpp:2116 src/slic3r/GUI/Tab.cpp:2117 -#: src/slic3r/GUI/Tab.cpp:3385 src/slic3r/GUI/Tab.cpp:3386 +#: src/slic3r/GUI/Tab.cpp:1204 src/slic3r/GUI/Tab.cpp:1205 +#: src/slic3r/GUI/Tab.cpp:1716 src/slic3r/GUI/Tab.cpp:1717 +#: src/slic3r/GUI/Tab.cpp:2165 src/slic3r/GUI/Tab.cpp:2166 +#: src/slic3r/GUI/Tab.cpp:2273 src/slic3r/GUI/Tab.cpp:2274 +#: src/slic3r/GUI/Tab.cpp:3586 src/slic3r/GUI/Tab.cpp:3587 msgid "Notes" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1206 src/slic3r/GUI/Tab.cpp:1620 -#: src/slic3r/GUI/Tab.cpp:2029 src/slic3r/GUI/Tab.cpp:2123 -#: src/slic3r/GUI/Tab.cpp:3393 src/slic3r/GUI/Tab.cpp:3502 +#: src/slic3r/GUI/Tab.cpp:1211 src/slic3r/GUI/Tab.cpp:1724 +#: src/slic3r/GUI/Tab.cpp:2172 src/slic3r/GUI/Tab.cpp:2280 +#: src/slic3r/GUI/Tab.cpp:3594 src/slic3r/GUI/Tab.cpp:3709 msgid "Dependencies" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1207 src/slic3r/GUI/Tab.cpp:1621 -#: src/slic3r/GUI/Tab.cpp:2030 src/slic3r/GUI/Tab.cpp:2124 -#: src/slic3r/GUI/Tab.cpp:3394 src/slic3r/GUI/Tab.cpp:3503 +#: src/slic3r/GUI/Tab.cpp:1212 src/slic3r/GUI/Tab.cpp:1725 +#: src/slic3r/GUI/Tab.cpp:2173 src/slic3r/GUI/Tab.cpp:2281 +#: src/slic3r/GUI/Tab.cpp:3595 src/slic3r/GUI/Tab.cpp:3710 msgid "Profile dependencies" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1253 +#: src/slic3r/GUI/Tab.cpp:1256 msgid "" -"Layer height can't be equal to zero.\n" +"Zero layer height is not valid.\n" "\n" -"Shall I set its value to minimum (0.01)?" +"The layer height will be reset to 0.01." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1266 +#: src/slic3r/GUI/Tab.cpp:1268 msgid "" -"First layer height can't be equal to zero.\n" +"Zero first layer height is not valid.\n" "\n" -"Shall I set its value to minimum (0.01)?" +"The first layer height will be reset to 0.01." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1268 src/libslic3r/PrintConfig.cpp:852 +#: src/slic3r/GUI/Tab.cpp:1269 src/libslic3r/PrintConfig.cpp:866 msgid "First layer height" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1284 +#: src/slic3r/GUI/Tab.cpp:1283 #, possible-c-format msgid "" "The Spiral Vase mode requires:\n" @@ -3559,11 +4007,11 @@ msgid "" "Shall I adjust those settings in order to enable Spiral Vase?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1291 +#: src/slic3r/GUI/Tab.cpp:1290 msgid "Spiral Vase" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1312 +#: src/slic3r/GUI/Tab.cpp:1311 msgid "" "The Wipe Tower currently supports the non-soluble supports only\n" "if they are printed with the current extruder without triggering a tool " @@ -3574,11 +4022,11 @@ msgid "" "Shall I adjust those settings in order to enable the Wipe Tower?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1316 src/slic3r/GUI/Tab.cpp:1333 +#: src/slic3r/GUI/Tab.cpp:1315 src/slic3r/GUI/Tab.cpp:1332 msgid "Wipe Tower" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1330 +#: src/slic3r/GUI/Tab.cpp:1329 msgid "" "For the Wipe Tower to work with the soluble supports, the support layers\n" "need to be synchronized with the object layers.\n" @@ -3586,7 +4034,7 @@ msgid "" "Shall I synchronize support layers in order to enable the Wipe Tower?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1348 +#: src/slic3r/GUI/Tab.cpp:1347 msgid "" "Supports work better, if the following feature is enabled:\n" "- Detect bridging perimeters\n" @@ -3594,103 +4042,116 @@ msgid "" "Shall I adjust those settings for supports?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1351 +#: src/slic3r/GUI/Tab.cpp:1350 msgid "Support Generator" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1393 +#: src/slic3r/GUI/Tab.cpp:1392 msgid "" "The %1% infill pattern is not supposed to work at 100%% density.\n" "\n" "Shall I switch to rectilinear fill pattern?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1514 src/libslic3r/PrintConfig.cpp:2015 +#: src/slic3r/GUI/Tab.cpp:1502 src/slic3r/GUI/Tab.cpp:1557 +msgid "Filament Overrides" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:1503 src/slic3r/GUI/Tab.cpp:1562 +#: src/slic3r/GUI/Tab.cpp:2514 +msgid "Retraction" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:1612 src/libslic3r/PrintConfig.cpp:2030 msgid "Temperature" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1520 +#: src/slic3r/GUI/Tab.cpp:1618 msgid "Bed" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1525 +#: src/slic3r/GUI/Tab.cpp:1623 msgid "Cooling" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1526 src/libslic3r/PrintConfig.cpp:1321 -#: src/libslic3r/PrintConfig.cpp:2134 +#: src/slic3r/GUI/Tab.cpp:1624 src/libslic3r/PrintConfig.cpp:1335 +#: src/libslic3r/PrintConfig.cpp:2150 msgid "Enable" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1537 +#: src/slic3r/GUI/Tab.cpp:1635 msgid "Fan settings" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1538 +#: src/slic3r/GUI/Tab.cpp:1636 msgid "Fan speed" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1546 +#: src/slic3r/GUI/Tab.cpp:1644 msgid "Cooling thresholds" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1552 +#: src/slic3r/GUI/Tab.cpp:1650 msgid "Filament properties" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1556 +#: src/slic3r/GUI/Tab.cpp:1654 msgid "Print speed override" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1566 +#: src/slic3r/GUI/Tab.cpp:1664 +msgid "Wipe tower parameters" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:1667 msgid "Toolchange parameters with single extruder MM printers" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1581 +#: src/slic3r/GUI/Tab.cpp:1681 msgid "Ramming settings" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1599 src/slic3r/GUI/Tab.cpp:1985 +#: src/slic3r/GUI/Tab.cpp:1703 src/slic3r/GUI/Tab.cpp:2128 msgid "Custom G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1600 src/slic3r/GUI/Tab.cpp:1986 -#: src/libslic3r/PrintConfig.cpp:1771 src/libslic3r/PrintConfig.cpp:1786 +#: src/slic3r/GUI/Tab.cpp:1704 src/slic3r/GUI/Tab.cpp:2129 +#: src/libslic3r/PrintConfig.cpp:1785 src/libslic3r/PrintConfig.cpp:1800 msgid "Start G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1606 src/slic3r/GUI/Tab.cpp:1992 -#: src/libslic3r/PrintConfig.cpp:360 src/libslic3r/PrintConfig.cpp:370 +#: src/slic3r/GUI/Tab.cpp:1710 src/slic3r/GUI/Tab.cpp:2135 +#: src/libslic3r/PrintConfig.cpp:369 src/libslic3r/PrintConfig.cpp:379 msgid "End G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1737 src/slic3r/GUI/Tab.cpp:1925 +#: src/slic3r/GUI/Tab.cpp:1843 src/slic3r/GUI/Tab.cpp:2068 msgid "Test" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1747 +#: src/slic3r/GUI/Tab.cpp:1853 msgid "Could not get a valid Printer Host reference" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1753 src/slic3r/GUI/Tab.cpp:1938 +#: src/slic3r/GUI/Tab.cpp:1859 src/slic3r/GUI/Tab.cpp:2081 msgid "Success!" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1768 +#: src/slic3r/GUI/Tab.cpp:1874 msgid "" "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-" "signed certificate." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1781 +#: src/slic3r/GUI/Tab.cpp:1887 msgid "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1782 +#: src/slic3r/GUI/Tab.cpp:1888 msgid "Open CA certificate file" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1810 +#: src/slic3r/GUI/Tab.cpp:1916 #, possible-c-format msgid "" "HTTPS CA File:\n" @@ -3700,278 +4161,283 @@ msgid "" "Store / Keychain." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1850 src/slic3r/GUI/Tab.cpp:2051 +#: src/slic3r/GUI/Tab.cpp:1956 src/slic3r/GUI/Tab.cpp:2194 msgid "Size and coordinates" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1855 src/slic3r/GUI/Tab.cpp:2056 -#: src/slic3r/GUI/Tab.cpp:3040 +#: src/slic3r/GUI/Tab.cpp:1961 src/slic3r/GUI/Tab.cpp:2199 +#: src/slic3r/GUI/Tab.cpp:3256 msgid "Set" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1877 +#: src/slic3r/GUI/Tab.cpp:1993 msgid "Capabilities" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1882 +#: src/slic3r/GUI/Tab.cpp:1998 msgid "Number of extruders of the printer." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1910 +#: src/slic3r/GUI/Tab.cpp:2023 +msgid "" +"Single Extruder Multi Material is selected, \n" +"and all extruders must have the same diameter.\n" +"Do you want to change the diameter for all extruders to first extruder " +"nozzle diameter value?" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:2026 src/slic3r/GUI/Tab.cpp:2484 +#: src/libslic3r/PrintConfig.cpp:1310 +msgid "Nozzle diameter" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:2053 msgid "USB/Serial connection" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1911 src/libslic3r/PrintConfig.cpp:1626 +#: src/slic3r/GUI/Tab.cpp:2054 src/libslic3r/PrintConfig.cpp:1640 msgid "Serial port" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1916 +#: src/slic3r/GUI/Tab.cpp:2059 msgid "Rescan serial ports" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1938 +#: src/slic3r/GUI/Tab.cpp:2081 msgid "Connection to printer works correctly." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1941 +#: src/slic3r/GUI/Tab.cpp:2084 msgid "Connection failed." msgstr "" -#: src/slic3r/GUI/Tab.cpp:1954 src/slic3r/GUI/Tab.cpp:2111 +#: src/slic3r/GUI/Tab.cpp:2097 src/slic3r/GUI/Tab.cpp:2268 msgid "Print Host upload" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1998 src/libslic3r/PrintConfig.cpp:129 +#: src/slic3r/GUI/Tab.cpp:2141 src/libslic3r/PrintConfig.cpp:138 msgid "Before layer change G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2004 src/libslic3r/PrintConfig.cpp:1042 +#: src/slic3r/GUI/Tab.cpp:2147 src/libslic3r/PrintConfig.cpp:1056 msgid "After layer change G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2010 src/libslic3r/PrintConfig.cpp:2041 +#: src/slic3r/GUI/Tab.cpp:2153 src/libslic3r/PrintConfig.cpp:2056 msgid "Tool change G-code" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2016 +#: src/slic3r/GUI/Tab.cpp:2159 msgid "Between objects G-code (for sequential printing)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2078 +#: src/slic3r/GUI/Tab.cpp:2231 msgid "Display" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2089 +#: src/slic3r/GUI/Tab.cpp:2246 msgid "Tilt" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2090 +#: src/slic3r/GUI/Tab.cpp:2247 msgid "Tilt time" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2096 src/slic3r/GUI/Tab.cpp:3367 +#: src/slic3r/GUI/Tab.cpp:2253 src/slic3r/GUI/Tab.cpp:3568 msgid "Corrections" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2173 src/slic3r/GUI/Tab.cpp:2246 -#: src/libslic3r/PrintConfig.cpp:1092 src/libslic3r/PrintConfig.cpp:1110 -#: src/libslic3r/PrintConfig.cpp:1128 src/libslic3r/PrintConfig.cpp:1145 -#: src/libslic3r/PrintConfig.cpp:1156 src/libslic3r/PrintConfig.cpp:1167 -#: src/libslic3r/PrintConfig.cpp:1178 +#: src/slic3r/GUI/Tab.cpp:2333 src/slic3r/GUI/Tab.cpp:2418 +#: src/libslic3r/PrintConfig.cpp:1106 src/libslic3r/PrintConfig.cpp:1124 +#: src/libslic3r/PrintConfig.cpp:1142 src/libslic3r/PrintConfig.cpp:1159 +#: src/libslic3r/PrintConfig.cpp:1170 src/libslic3r/PrintConfig.cpp:1181 +#: src/libslic3r/PrintConfig.cpp:1192 msgid "Machine limits" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2187 +#: src/slic3r/GUI/Tab.cpp:2347 msgid "Values in this column are for Normal mode" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2188 +#: src/slic3r/GUI/Tab.cpp:2348 msgid "Normal" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2193 +#: src/slic3r/GUI/Tab.cpp:2353 msgid "Values in this column are for Stealth mode" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2194 +#: src/slic3r/GUI/Tab.cpp:2354 msgid "Stealth" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2202 +#: src/slic3r/GUI/Tab.cpp:2362 msgid "Maximum feedrates" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2207 +#: src/slic3r/GUI/Tab.cpp:2367 msgid "Maximum accelerations" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2214 +#: src/slic3r/GUI/Tab.cpp:2374 msgid "Jerk limits" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2219 +#: src/slic3r/GUI/Tab.cpp:2379 msgid "Minimum feedrates" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2268 src/slic3r/GUI/Tab.cpp:2276 +#: src/slic3r/GUI/Tab.cpp:2443 src/slic3r/GUI/Tab.cpp:2451 msgid "Single extruder MM setup" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2277 +#: src/slic3r/GUI/Tab.cpp:2452 msgid "Single extruder multimaterial parameters" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2290 src/libslic3r/GCode/PreviewData.cpp:475 +#: src/slic3r/GUI/Tab.cpp:2465 src/libslic3r/GCode/PreviewData.cpp:477 #, possible-c-format msgid "Extruder %d" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2297 +#: src/slic3r/GUI/Tab.cpp:2483 +msgid "Do you want to change the diameter for all extruders?" +msgstr "" + +#: src/slic3r/GUI/Tab.cpp:2506 msgid "Layer height limits" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2302 +#: src/slic3r/GUI/Tab.cpp:2511 msgid "Position (for multi-extruder printers)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2305 -msgid "Retraction" -msgstr "" - -#: src/slic3r/GUI/Tab.cpp:2308 +#: src/slic3r/GUI/Tab.cpp:2517 msgid "Only lift Z" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2321 +#: src/slic3r/GUI/Tab.cpp:2530 msgid "" "Retraction when tool is disabled (advanced settings for multi-extruder " "setups)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2480 +#: src/slic3r/GUI/Tab.cpp:2693 msgid "" "The Wipe option is not available when using the Firmware Retraction mode.\n" "\n" "Shall I disable it in order to enable Firmware Retraction?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2482 +#: src/slic3r/GUI/Tab.cpp:2695 msgid "Firmware Retraction" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2808 +#: src/slic3r/GUI/Tab.cpp:3024 #, possible-c-format msgid "Default preset (%s)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2809 +#: src/slic3r/GUI/Tab.cpp:3025 #, possible-c-format msgid "Preset (%s)" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2826 +#: src/slic3r/GUI/Tab.cpp:3042 msgid "has the following unsaved changes:" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2829 +#: src/slic3r/GUI/Tab.cpp:3045 msgid "is not compatible with printer" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2830 +#: src/slic3r/GUI/Tab.cpp:3046 msgid "is not compatible with print profile" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2832 +#: src/slic3r/GUI/Tab.cpp:3048 msgid "and it has the following unsaved changes:" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2836 +#: src/slic3r/GUI/Tab.cpp:3052 msgid "Unsaved Changes" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2848 -msgid "Please check your object list before preset changing." -msgstr "" - -#: src/slic3r/GUI/Tab.cpp:2927 +#: src/slic3r/GUI/Tab.cpp:3143 msgid "%1% - Copy" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2950 +#: src/slic3r/GUI/Tab.cpp:3166 msgid "The supplied name is empty. It can't be saved." msgstr "" -#: src/slic3r/GUI/Tab.cpp:2955 +#: src/slic3r/GUI/Tab.cpp:3171 msgid "Cannot overwrite a system profile." msgstr "" -#: src/slic3r/GUI/Tab.cpp:2959 +#: src/slic3r/GUI/Tab.cpp:3175 msgid "Cannot overwrite an external profile." msgstr "" -#: src/slic3r/GUI/Tab.cpp:2985 +#: src/slic3r/GUI/Tab.cpp:3201 msgid "remove" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2985 +#: src/slic3r/GUI/Tab.cpp:3201 msgid "delete" msgstr "" #. TRN remove/delete -#: src/slic3r/GUI/Tab.cpp:2987 +#: src/slic3r/GUI/Tab.cpp:3203 msgid "Are you sure you want to %1% the selected preset?" msgstr "" -#: src/slic3r/GUI/Tab.cpp:2988 -msgid "Remove" -msgstr "" - #. TRN Remove/Delete -#: src/slic3r/GUI/Tab.cpp:2990 +#: src/slic3r/GUI/Tab.cpp:3206 msgid "%1% Preset" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3116 +#: src/slic3r/GUI/Tab.cpp:3332 msgid "LOCKED LOCK" msgstr "" #. TRN Description for "LOCKED LOCK" -#: src/slic3r/GUI/Tab.cpp:3118 +#: src/slic3r/GUI/Tab.cpp:3334 msgid "" -"indicates that the settings are the same as the system values for the " -"current option group" +"indicates that the settings are the same as the system (or default) values " +"for the current option group" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3120 +#: src/slic3r/GUI/Tab.cpp:3336 msgid "UNLOCKED LOCK" msgstr "" #. TRN Description for "UNLOCKED LOCK" -#: src/slic3r/GUI/Tab.cpp:3122 +#: src/slic3r/GUI/Tab.cpp:3338 msgid "" "indicates that some settings were changed and are not equal to the system " -"values for the current option group.\n" +"(or default) values for the current option group.\n" "Click the UNLOCKED LOCK icon to reset all settings for current option group " -"to the system values." +"to the system (or default) values." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3127 +#: src/slic3r/GUI/Tab.cpp:3343 msgid "WHITE BULLET" msgstr "" #. TRN Description for "WHITE BULLET" -#: src/slic3r/GUI/Tab.cpp:3129 +#: src/slic3r/GUI/Tab.cpp:3345 msgid "" -"for the left button: \tindicates a non-system preset,\n" +"for the left button: \tindicates a non-system (or non-default) preset,\n" "for the right button: \tindicates that the settings hasn't been modified." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3103 +#: src/slic3r/GUI/Tab.cpp:3348 msgid "BACK ARROW" msgstr "" #. TRN Description for "BACK ARROW" -#: src/slic3r/GUI/Tab.cpp:3134 +#: src/slic3r/GUI/Tab.cpp:3350 msgid "" "indicates that the settings were changed and are not equal to the last saved " "preset for the current option group.\n" @@ -3979,30 +4445,31 @@ msgid "" "to the last saved preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3159 +#: src/slic3r/GUI/Tab.cpp:3360 msgid "" -"LOCKED LOCK icon indicates that the settings are the same as the system " -"values for the current option group" +"LOCKED LOCK icon indicates that the settings are the same as the system (or " +"default) values for the current option group" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3161 +#: src/slic3r/GUI/Tab.cpp:3362 msgid "" "UNLOCKED LOCK icon indicates that some settings were changed and are not " -"equal to the system values for the current option group.\n" -"Click to reset all settings for current option group to the system values." +"equal to the system (or default) values for the current option group.\n" +"Click to reset all settings for current option group to the system (or " +"default) values." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3164 -msgid "WHITE BULLET icon indicates a non system preset." +#: src/slic3r/GUI/Tab.cpp:3365 +msgid "WHITE BULLET icon indicates a non system (or non default) preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3167 +#: src/slic3r/GUI/Tab.cpp:3368 msgid "" "WHITE BULLET icon indicates that the settings are the same as in the last " "saved preset for the current option group." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3169 +#: src/slic3r/GUI/Tab.cpp:3370 msgid "" "BACK ARROW icon indicates that the settings were changed and are not equal " "to the last saved preset for the current option group.\n" @@ -4010,25 +4477,26 @@ msgid "" "preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3175 +#: src/slic3r/GUI/Tab.cpp:3376 msgid "" -"LOCKED LOCK icon indicates that the value is the same as the system value." +"LOCKED LOCK icon indicates that the value is the same as the system (or " +"default) value." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3176 +#: src/slic3r/GUI/Tab.cpp:3377 msgid "" "UNLOCKED LOCK icon indicates that the value was changed and is not equal to " -"the system value.\n" -"Click to reset current value to the system value." +"the system (or default) value.\n" +"Click to reset current value to the system (or default) value." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3182 +#: src/slic3r/GUI/Tab.cpp:3383 msgid "" "WHITE BULLET icon indicates that the value is the same as in the last saved " "preset." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3183 +#: src/slic3r/GUI/Tab.cpp:3384 msgid "" "BACK ARROW icon indicates that the value was changed and is not equal to the " "last saved preset.\n" @@ -4036,80 +4504,81 @@ msgid "" msgstr "" #. TRN Preset -#: src/slic3r/GUI/Tab.cpp:3296 +#: src/slic3r/GUI/Tab.cpp:3497 #, possible-c-format msgid "Save %s as:" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3340 +#: src/slic3r/GUI/Tab.cpp:3541 msgid "the following suffix is not allowed:" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3344 +#: src/slic3r/GUI/Tab.cpp:3545 msgid "The supplied name is not available." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3357 +#: src/slic3r/GUI/Tab.cpp:3558 msgid "Material" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3359 src/slic3r/GUI/Tab.cpp:3450 +#: src/slic3r/GUI/Tab.cpp:3560 src/slic3r/GUI/Tab.cpp:3651 +#: src/slic3r/GUI/wxExtensions.cpp:454 msgid "Layers" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3363 +#: src/slic3r/GUI/Tab.cpp:3564 msgid "Exposure" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3458 +#: src/slic3r/GUI/Tab.cpp:3659 msgid "Support head" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3463 +#: src/slic3r/GUI/Tab.cpp:3664 msgid "Support pillar" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3473 +#: src/slic3r/GUI/Tab.cpp:3675 msgid "Connection of the support sticks and junctions" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3478 +#: src/slic3r/GUI/Tab.cpp:3680 msgid "Automatic generation" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3540 +#: src/slic3r/GUI/Tab.cpp:3747 msgid "Head penetration should not be greater than the head width." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3541 +#: src/slic3r/GUI/Tab.cpp:3751 msgid "Invalid Head penetration" msgstr "" -#: src/slic3r/GUI/Tab.cpp:3553 +#: src/slic3r/GUI/Tab.cpp:3767 msgid "Pinhead diameter should be smaller than the pillar diameter." msgstr "" -#: src/slic3r/GUI/Tab.cpp:3554 +#: src/slic3r/GUI/Tab.cpp:3771 msgid "Invalid pinhead diameter" msgstr "" -#: src/slic3r/GUI/Tab.hpp:318 src/slic3r/GUI/Tab.hpp:411 +#: src/slic3r/GUI/Tab.hpp:324 src/slic3r/GUI/Tab.hpp:422 msgid "Print Settings" msgstr "" -#: src/slic3r/GUI/Tab.hpp:337 +#: src/slic3r/GUI/Tab.hpp:348 msgid "Filament Settings" msgstr "" -#: src/slic3r/GUI/Tab.hpp:372 +#: src/slic3r/GUI/Tab.hpp:383 msgid "Printer Settings" msgstr "" -#: src/slic3r/GUI/Tab.hpp:396 +#: src/slic3r/GUI/Tab.hpp:407 msgid "Material Settings" msgstr "" -#: src/slic3r/GUI/Tab.hpp:423 +#: src/slic3r/GUI/Tab.hpp:434 msgid "Save preset" msgstr "" @@ -4122,39 +4591,39 @@ msgstr "" msgid "New version of %s is available" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:46 +#: src/slic3r/GUI/UpdateDialogs.cpp:45 msgid "Current version:" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:48 +#: src/slic3r/GUI/UpdateDialogs.cpp:47 msgid "New version:" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:56 +#: src/slic3r/GUI/UpdateDialogs.cpp:55 msgid "Changelog && Download" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:63 src/slic3r/GUI/UpdateDialogs.cpp:126 +#: src/slic3r/GUI/UpdateDialogs.cpp:62 src/slic3r/GUI/UpdateDialogs.cpp:125 msgid "Open changelog page" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:68 +#: src/slic3r/GUI/UpdateDialogs.cpp:67 msgid "Open download page" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:74 +#: src/slic3r/GUI/UpdateDialogs.cpp:73 msgid "Don't notify about new releases any more" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:92 src/slic3r/GUI/UpdateDialogs.cpp:206 +#: src/slic3r/GUI/UpdateDialogs.cpp:91 src/slic3r/GUI/UpdateDialogs.cpp:205 msgid "Configuration update" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:92 +#: src/slic3r/GUI/UpdateDialogs.cpp:91 msgid "Configuration update is available" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:95 +#: src/slic3r/GUI/UpdateDialogs.cpp:94 msgid "" "Would you like to install it?\n" "\n" @@ -4164,21 +4633,21 @@ msgid "" "Updated configuration bundles:" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:116 +#: src/slic3r/GUI/UpdateDialogs.cpp:115 msgid "Comment:" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:150 +#: src/slic3r/GUI/UpdateDialogs.cpp:149 #, possible-c-format msgid "%s incompatibility" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:151 +#: src/slic3r/GUI/UpdateDialogs.cpp:150 #, possible-c-format msgid "%s configuration is incompatible" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:156 +#: src/slic3r/GUI/UpdateDialogs.cpp:155 #, possible-c-format msgid "" "This version of %s is not compatible with currently installed configuration " @@ -4191,25 +4660,25 @@ msgid "" "existing configuration before installing files compatible with this %s.\n" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:165 +#: src/slic3r/GUI/UpdateDialogs.cpp:164 #, possible-c-format msgid "This %s version: %s" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:170 +#: src/slic3r/GUI/UpdateDialogs.cpp:169 msgid "Incompatible bundles:" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:186 +#: src/slic3r/GUI/UpdateDialogs.cpp:185 #, possible-c-format msgid "Exit %s" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:189 +#: src/slic3r/GUI/UpdateDialogs.cpp:188 msgid "Re-configure" msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:210 +#: src/slic3r/GUI/UpdateDialogs.cpp:209 #, possible-c-format msgid "" "%s now uses an updated configuration structure.\n" @@ -4225,7 +4694,7 @@ msgid "" "choose whether to enable automatic preset updates." msgstr "" -#: src/slic3r/GUI/UpdateDialogs.cpp:226 +#: src/slic3r/GUI/UpdateDialogs.cpp:225 msgid "For more information please visit our wiki page:" msgstr "" @@ -4318,21 +4787,37 @@ msgstr "" msgid "Show advanced settings" msgstr "" -#: src/slic3r/GUI/wxExtensions.cpp:444 +#: src/slic3r/GUI/wxExtensions.cpp:443 msgid "Instances" msgstr "" -#: src/slic3r/GUI/wxExtensions.cpp:451 src/slic3r/GUI/wxExtensions.cpp:518 +#: src/slic3r/GUI/wxExtensions.cpp:447 src/slic3r/GUI/wxExtensions.cpp:592 #, possible-c-format msgid "Instance %d" msgstr "" -#: src/slic3r/GUI/wxExtensions.cpp:2508 +#: src/slic3r/GUI/wxExtensions.cpp:486 +msgid "Range" +msgstr "" + +#: src/slic3r/GUI/wxExtensions.cpp:2570 +msgid "One layer mode" +msgstr "" + +#: src/slic3r/GUI/wxExtensions.cpp:2571 +msgid "Add/Del color change" +msgstr "" + +#: src/slic3r/GUI/wxExtensions.cpp:2572 +msgid "Discard all color changes" +msgstr "" + +#: src/slic3r/GUI/wxExtensions.cpp:2832 #, possible-c-format msgid "Switch to the %s mode" msgstr "" -#: src/slic3r/GUI/wxExtensions.cpp:2509 +#: src/slic3r/GUI/wxExtensions.cpp:2833 #, possible-c-format msgid "Current mode is %s" msgstr "" @@ -4382,17 +4867,17 @@ msgstr "" msgid "Could not connect to Prusa SLA" msgstr "" -#: src/slic3r/Utils/PresetUpdater.cpp:584 +#: src/slic3r/Utils/PresetUpdater.cpp:614 #, possible-c-format msgid "requires min. %s and max. %s" msgstr "" -#: src/slic3r/Utils/PresetUpdater.cpp:589 +#: src/slic3r/Utils/PresetUpdater.cpp:619 #, possible-c-format msgid "requires min. %s" msgstr "" -#: src/slic3r/Utils/PresetUpdater.cpp:591 +#: src/slic3r/Utils/PresetUpdater.cpp:621 #, possible-c-format msgid "requires max. %s" msgstr "" @@ -4478,215 +4963,219 @@ msgstr "" msgid "Model repair failed: \n" msgstr "" -#: src/libslic3r/Zipper.cpp:35 +#: src/libslic3r/Zipper.cpp:32 msgid "undefined error" msgstr "" -#: src/libslic3r/Zipper.cpp:37 +#: src/libslic3r/Zipper.cpp:34 msgid "too many files" msgstr "" -#: src/libslic3r/Zipper.cpp:39 +#: src/libslic3r/Zipper.cpp:36 msgid "file too large" msgstr "" -#: src/libslic3r/Zipper.cpp:41 +#: src/libslic3r/Zipper.cpp:38 msgid "unsupported method" msgstr "" -#: src/libslic3r/Zipper.cpp:43 +#: src/libslic3r/Zipper.cpp:40 msgid "unsupported encryption" msgstr "" -#: src/libslic3r/Zipper.cpp:45 +#: src/libslic3r/Zipper.cpp:42 msgid "unsupported feature" msgstr "" -#: src/libslic3r/Zipper.cpp:47 +#: src/libslic3r/Zipper.cpp:44 msgid "failed finding central directory" msgstr "" -#: src/libslic3r/Zipper.cpp:49 +#: src/libslic3r/Zipper.cpp:46 msgid "not a ZIP archive" msgstr "" -#: src/libslic3r/Zipper.cpp:51 +#: src/libslic3r/Zipper.cpp:48 msgid "invalid header or archive is corrupted" msgstr "" -#: src/libslic3r/Zipper.cpp:53 +#: src/libslic3r/Zipper.cpp:50 msgid "unsupported multidisk archive" msgstr "" -#: src/libslic3r/Zipper.cpp:55 +#: src/libslic3r/Zipper.cpp:52 msgid "decompression failed or archive is corrupted" msgstr "" -#: src/libslic3r/Zipper.cpp:57 +#: src/libslic3r/Zipper.cpp:54 msgid "compression failed" msgstr "" -#: src/libslic3r/Zipper.cpp:59 +#: src/libslic3r/Zipper.cpp:56 msgid "unexpected decompressed size" msgstr "" -#: src/libslic3r/Zipper.cpp:61 +#: src/libslic3r/Zipper.cpp:58 msgid "CRC-32 check failed" msgstr "" -#: src/libslic3r/Zipper.cpp:63 +#: src/libslic3r/Zipper.cpp:60 msgid "unsupported central directory size" msgstr "" -#: src/libslic3r/Zipper.cpp:65 +#: src/libslic3r/Zipper.cpp:62 msgid "allocation failed" msgstr "" -#: src/libslic3r/Zipper.cpp:67 +#: src/libslic3r/Zipper.cpp:64 msgid "file open failed" msgstr "" -#: src/libslic3r/Zipper.cpp:69 +#: src/libslic3r/Zipper.cpp:66 msgid "file create failed" msgstr "" -#: src/libslic3r/Zipper.cpp:71 +#: src/libslic3r/Zipper.cpp:68 msgid "file write failed" msgstr "" -#: src/libslic3r/Zipper.cpp:73 +#: src/libslic3r/Zipper.cpp:70 msgid "file read failed" msgstr "" -#: src/libslic3r/Zipper.cpp:75 +#: src/libslic3r/Zipper.cpp:72 msgid "file close failed" msgstr "" -#: src/libslic3r/Zipper.cpp:77 +#: src/libslic3r/Zipper.cpp:74 msgid "file seek failed" msgstr "" -#: src/libslic3r/Zipper.cpp:79 +#: src/libslic3r/Zipper.cpp:76 msgid "file stat failed" msgstr "" -#: src/libslic3r/Zipper.cpp:81 +#: src/libslic3r/Zipper.cpp:78 msgid "invalid parameter" msgstr "" -#: src/libslic3r/Zipper.cpp:83 +#: src/libslic3r/Zipper.cpp:80 msgid "invalid filename" msgstr "" -#: src/libslic3r/Zipper.cpp:85 +#: src/libslic3r/Zipper.cpp:82 msgid "buffer too small" msgstr "" -#: src/libslic3r/Zipper.cpp:87 +#: src/libslic3r/Zipper.cpp:84 msgid "internal error" msgstr "" -#: src/libslic3r/Zipper.cpp:89 +#: src/libslic3r/Zipper.cpp:86 msgid "file not found" msgstr "" -#: src/libslic3r/Zipper.cpp:91 +#: src/libslic3r/Zipper.cpp:88 msgid "archive is too large" msgstr "" -#: src/libslic3r/Zipper.cpp:93 +#: src/libslic3r/Zipper.cpp:90 msgid "validation failed" msgstr "" -#: src/libslic3r/Zipper.cpp:95 +#: src/libslic3r/Zipper.cpp:92 msgid "write calledback failed" msgstr "" -#: src/libslic3r/Zipper.cpp:105 +#: src/libslic3r/Zipper.cpp:102 msgid "Error with zip archive" msgstr "" -#: src/libslic3r/Print.cpp:1135 +#: src/libslic3r/Print.cpp:1093 msgid "All objects are outside of the print volume." msgstr "" -#: src/libslic3r/Print.cpp:1162 +#: src/libslic3r/Print.cpp:1120 msgid "Some objects are too close; your extruder will collide with them." msgstr "" -#: src/libslic3r/Print.cpp:1177 +#: src/libslic3r/Print.cpp:1135 msgid "" "Some objects are too tall and cannot be printed without extruder collisions." msgstr "" -#: src/libslic3r/Print.cpp:1187 +#: src/libslic3r/Print.cpp:1145 msgid "The Spiral Vase option can only be used when printing a single object." msgstr "" -#: src/libslic3r/Print.cpp:1189 +#: src/libslic3r/Print.cpp:1147 msgid "" "The Spiral Vase option can only be used when printing single material " "objects." msgstr "" -#: src/libslic3r/Print.cpp:1195 +#: src/libslic3r/Print.cpp:1155 msgid "" -"All extruders must have the same diameter for single extruder multimaterial " -"printer." +"The wipe tower is only supported if all extruders have the same nozzle " +"diameter and use filaments of the same diameter." msgstr "" -#: src/libslic3r/Print.cpp:1200 +#: src/libslic3r/Print.cpp:1159 msgid "" "The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter " "and Repetier G-code flavors." msgstr "" -#: src/libslic3r/Print.cpp:1202 +#: src/libslic3r/Print.cpp:1161 msgid "" "The Wipe Tower is currently only supported with the relative extruder " "addressing (use_relative_e_distances=1)." msgstr "" -#: src/libslic3r/Print.cpp:1223 +#: src/libslic3r/Print.cpp:1165 +msgid "All extruders must have the same diameter for the Wipe Tower." +msgstr "" + +#: src/libslic3r/Print.cpp:1186 msgid "" "The Wipe Tower is only supported for multiple objects if they have equal " "layer heights" msgstr "" -#: src/libslic3r/Print.cpp:1225 +#: src/libslic3r/Print.cpp:1188 msgid "" "The Wipe Tower is only supported for multiple objects if they are printed " "over an equal number of raft layers" msgstr "" -#: src/libslic3r/Print.cpp:1227 +#: src/libslic3r/Print.cpp:1190 msgid "" "The Wipe Tower is only supported for multiple objects if they are printed " "with the same support_material_contact_distance" msgstr "" -#: src/libslic3r/Print.cpp:1229 +#: src/libslic3r/Print.cpp:1192 msgid "" "The Wipe Tower is only supported for multiple objects if they are sliced " "equally." msgstr "" -#: src/libslic3r/Print.cpp:1258 +#: src/libslic3r/Print.cpp:1220 msgid "" "The Wipe tower is only supported if all objects have the same layer height " "profile" msgstr "" -#: src/libslic3r/Print.cpp:1268 +#: src/libslic3r/Print.cpp:1230 msgid "The supplied settings will cause an empty print." msgstr "" -#: src/libslic3r/Print.cpp:1285 +#: src/libslic3r/Print.cpp:1247 msgid "" "One or more object were assigned an extruder that the printer does not have." msgstr "" -#: src/libslic3r/Print.cpp:1294 +#: src/libslic3r/Print.cpp:1256 msgid "" "Printing with multiple extruders of differing nozzle diameters. If support " "is to be printed with the current extruder (support_material_extruder == 0 " @@ -4694,13 +5183,13 @@ msgid "" "same diameter." msgstr "" -#: src/libslic3r/Print.cpp:1302 +#: src/libslic3r/Print.cpp:1264 msgid "" "For the Wipe Tower to work with the soluble supports, the support layers " "need to be synchronized with the object layers." msgstr "" -#: src/libslic3r/Print.cpp:1306 +#: src/libslic3r/Print.cpp:1268 msgid "" "The Wipe Tower currently supports the non-soluble supports only if they are " "printed with the current extruder without triggering a tool change. (both " @@ -4708,83 +5197,90 @@ msgid "" "set to 0)." msgstr "" -#: src/libslic3r/Print.cpp:1328 +#: src/libslic3r/Print.cpp:1290 msgid "First layer height can't be greater than nozzle diameter" msgstr "" -#: src/libslic3r/Print.cpp:1332 +#: src/libslic3r/Print.cpp:1294 msgid "Layer height can't be greater than nozzle diameter" msgstr "" -#: src/libslic3r/Print.cpp:1476 +#: src/libslic3r/Print.cpp:1438 msgid "Infilling layers" msgstr "" -#: src/libslic3r/Print.cpp:1484 +#: src/libslic3r/Print.cpp:1446 msgid "Generating skirt" msgstr "" -#: src/libslic3r/Print.cpp:1492 +#: src/libslic3r/Print.cpp:1454 msgid "Generating brim" msgstr "" -#: src/libslic3r/Print.cpp:1520 +#: src/libslic3r/Print.cpp:1482 msgid "Exporting G-code" msgstr "" -#: src/libslic3r/Print.cpp:1524 +#: src/libslic3r/Print.cpp:1486 msgid "Generating G-code" msgstr "" -#: src/libslic3r/SLAPrint.cpp:57 +#: src/libslic3r/SLAPrint.cpp:58 msgid "Slicing model" msgstr "" -#: src/libslic3r/SLAPrint.cpp:58 src/libslic3r/SLAPrint.cpp:819 +#: src/libslic3r/SLAPrint.cpp:59 src/libslic3r/SLAPrint.cpp:871 msgid "Generating support points" msgstr "" -#: src/libslic3r/SLAPrint.cpp:59 +#: src/libslic3r/SLAPrint.cpp:60 msgid "Generating support tree" msgstr "" -#: src/libslic3r/SLAPrint.cpp:60 +#: src/libslic3r/SLAPrint.cpp:61 msgid "Generating pad" msgstr "" -#: src/libslic3r/SLAPrint.cpp:61 +#: src/libslic3r/SLAPrint.cpp:62 msgid "Slicing supports" msgstr "" -#: src/libslic3r/SLAPrint.cpp:78 +#: src/libslic3r/SLAPrint.cpp:79 msgid "Merging slices and calculating statistics" msgstr "" -#: src/libslic3r/SLAPrint.cpp:79 +#: src/libslic3r/SLAPrint.cpp:80 msgid "Rasterizing layers" msgstr "" -#: src/libslic3r/SLAPrint.cpp:622 +#: src/libslic3r/SLAPrint.cpp:650 msgid "" "Cannot proceed without support points! Add support points or disable support " "generation." msgstr "" -#: src/libslic3r/SLAPrint.cpp:634 +#: src/libslic3r/SLAPrint.cpp:664 msgid "Elevation is too low for object." msgstr "" -#. TRN To be shown at the status bar on SLA slicing error. -#: src/libslic3r/SLAPrint.cpp:719 -msgid "Slicing had to be stopped due to an internal error." +#: src/libslic3r/SLAPrint.cpp:670 +msgid "" +"The endings of the support pillars will be deployed on the gap between the " +"object and the pad. 'Support base safety distance' has to be greater than " +"the 'Pad object gap' parameter to avoid this." msgstr "" -#: src/libslic3r/SLAPrint.cpp:867 src/libslic3r/SLAPrint.cpp:877 -#: src/libslic3r/SLAPrint.cpp:925 +#: src/libslic3r/SLAPrint.cpp:759 +msgid "" +"Slicing had to be stopped due to an internal error: Inconsistent slice index." +msgstr "" + +#: src/libslic3r/SLAPrint.cpp:954 src/libslic3r/SLAPrint.cpp:964 +#: src/libslic3r/SLAPrint.cpp:1005 msgid "Visualizing supports" msgstr "" -#: src/libslic3r/SLAPrint.cpp:1463 +#: src/libslic3r/SLAPrint.cpp:1537 msgid "Slicing done" msgstr "" @@ -4800,101 +5296,109 @@ msgstr "" msgid "Bed shape" msgstr "" -#: src/libslic3r/PrintConfig.cpp:58 +#: src/libslic3r/PrintConfig.cpp:56 +msgid "Bed custom texture" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:61 +msgid "Bed custom model" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:68 msgid "" "This setting controls the height (and thus the total number) of the slices/" "layers. Thinner layers give better accuracy but take more time to print." msgstr "" -#: src/libslic3r/PrintConfig.cpp:65 +#: src/libslic3r/PrintConfig.cpp:75 msgid "Max print height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:66 +#: src/libslic3r/PrintConfig.cpp:76 msgid "" "Set this to the maximum height that can be reached by your extruder while " "printing." msgstr "" -#: src/libslic3r/PrintConfig.cpp:72 +#: src/libslic3r/PrintConfig.cpp:82 msgid "Slice gap closing radius" msgstr "" -#: src/libslic3r/PrintConfig.cpp:74 +#: src/libslic3r/PrintConfig.cpp:84 msgid "" "Cracks smaller than 2x gap closing radius are being filled during the " "triangle mesh slicing. The gap closing operation may reduce the final print " "resolution, therefore it is advisable to keep the value reasonably low." msgstr "" -#: src/libslic3r/PrintConfig.cpp:82 +#: src/libslic3r/PrintConfig.cpp:92 msgid "Hostname, IP or URL" msgstr "" -#: src/libslic3r/PrintConfig.cpp:83 +#: src/libslic3r/PrintConfig.cpp:93 msgid "" "Slic3r can upload G-code files to a printer host. This field should contain " "the hostname, IP address or URL of the printer host instance." msgstr "" -#: src/libslic3r/PrintConfig.cpp:89 +#: src/libslic3r/PrintConfig.cpp:99 msgid "API Key / Password" msgstr "" -#: src/libslic3r/PrintConfig.cpp:90 +#: src/libslic3r/PrintConfig.cpp:100 msgid "" "Slic3r can upload G-code files to a printer host. This field should contain " "the API Key or the password required for authentication." msgstr "" -#: src/libslic3r/PrintConfig.cpp:96 +#: src/libslic3r/PrintConfig.cpp:106 msgid "HTTPS CA File" msgstr "" -#: src/libslic3r/PrintConfig.cpp:97 +#: src/libslic3r/PrintConfig.cpp:107 msgid "" "Custom CA certificate file can be specified for HTTPS OctoPrint connections, " "in crt/pem format. If left blank, the default OS CA certificate repository " "is used." msgstr "" -#: src/libslic3r/PrintConfig.cpp:112 +#: src/libslic3r/PrintConfig.cpp:121 msgid "Avoid crossing perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:113 +#: src/libslic3r/PrintConfig.cpp:122 msgid "" "Optimize travel moves in order to minimize the crossing of perimeters. This " "is mostly useful with Bowden extruders which suffer from oozing. This " "feature slows down both the print and the G-code generation." msgstr "" -#: src/libslic3r/PrintConfig.cpp:120 src/libslic3r/PrintConfig.cpp:2012 +#: src/libslic3r/PrintConfig.cpp:129 src/libslic3r/PrintConfig.cpp:2027 msgid "Other layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:121 +#: src/libslic3r/PrintConfig.cpp:130 msgid "" "Bed temperature for layers after the first one. Set this to zero to disable " "bed temperature control commands in the output." msgstr "" -#: src/libslic3r/PrintConfig.cpp:123 +#: src/libslic3r/PrintConfig.cpp:132 msgid "Bed temperature" msgstr "" -#: src/libslic3r/PrintConfig.cpp:130 +#: src/libslic3r/PrintConfig.cpp:139 msgid "" "This custom code is inserted at every layer change, right before the Z move. " "Note that you can use placeholder variables for all Slic3r settings as well " "as [layer_num] and [layer_z]." msgstr "" -#: src/libslic3r/PrintConfig.cpp:140 +#: src/libslic3r/PrintConfig.cpp:149 msgid "Between objects G-code" msgstr "" -#: src/libslic3r/PrintConfig.cpp:141 +#: src/libslic3r/PrintConfig.cpp:150 msgid "" "This code is inserted between objects when using sequential printing. By " "default extruder and bed temperature are reset using non-wait command; " @@ -4904,70 +5408,70 @@ msgid "" "S[first_layer_temperature]\" command wherever you want." msgstr "" -#: src/libslic3r/PrintConfig.cpp:152 +#: src/libslic3r/PrintConfig.cpp:161 msgid "Number of solid layers to generate on bottom surfaces." msgstr "" -#: src/libslic3r/PrintConfig.cpp:153 +#: src/libslic3r/PrintConfig.cpp:162 msgid "Bottom solid layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:158 +#: src/libslic3r/PrintConfig.cpp:167 msgid "Bridge" msgstr "" -#: src/libslic3r/PrintConfig.cpp:159 +#: src/libslic3r/PrintConfig.cpp:168 msgid "" "This is the acceleration your printer will use for bridges. Set zero to " "disable acceleration control for bridges." msgstr "" -#: src/libslic3r/PrintConfig.cpp:161 src/libslic3r/PrintConfig.cpp:304 -#: src/libslic3r/PrintConfig.cpp:826 src/libslic3r/PrintConfig.cpp:947 -#: src/libslic3r/PrintConfig.cpp:1116 src/libslic3r/PrintConfig.cpp:1169 -#: src/libslic3r/PrintConfig.cpp:1180 src/libslic3r/PrintConfig.cpp:1369 +#: src/libslic3r/PrintConfig.cpp:170 src/libslic3r/PrintConfig.cpp:313 +#: src/libslic3r/PrintConfig.cpp:840 src/libslic3r/PrintConfig.cpp:961 +#: src/libslic3r/PrintConfig.cpp:1130 src/libslic3r/PrintConfig.cpp:1183 +#: src/libslic3r/PrintConfig.cpp:1194 src/libslic3r/PrintConfig.cpp:1383 msgid "mm/s²" msgstr "" -#: src/libslic3r/PrintConfig.cpp:167 +#: src/libslic3r/PrintConfig.cpp:176 msgid "Bridging angle" msgstr "" -#: src/libslic3r/PrintConfig.cpp:169 +#: src/libslic3r/PrintConfig.cpp:178 msgid "" "Bridging angle override. If left to zero, the bridging angle will be " "calculated automatically. Otherwise the provided angle will be used for all " "bridges. Use 180° for zero angle." msgstr "" -#: src/libslic3r/PrintConfig.cpp:172 src/libslic3r/PrintConfig.cpp:744 -#: src/libslic3r/PrintConfig.cpp:1605 src/libslic3r/PrintConfig.cpp:1615 -#: src/libslic3r/PrintConfig.cpp:1843 src/libslic3r/PrintConfig.cpp:1997 -#: src/libslic3r/PrintConfig.cpp:2181 src/libslic3r/PrintConfig.cpp:2498 -#: src/libslic3r/PrintConfig.cpp:2607 +#: src/libslic3r/PrintConfig.cpp:181 src/libslic3r/PrintConfig.cpp:758 +#: src/libslic3r/PrintConfig.cpp:1619 src/libslic3r/PrintConfig.cpp:1629 +#: src/libslic3r/PrintConfig.cpp:1858 src/libslic3r/PrintConfig.cpp:2012 +#: src/libslic3r/PrintConfig.cpp:2197 src/libslic3r/PrintConfig.cpp:2582 +#: src/libslic3r/PrintConfig.cpp:2693 msgid "°" msgstr "" -#: src/libslic3r/PrintConfig.cpp:178 +#: src/libslic3r/PrintConfig.cpp:187 msgid "Bridges fan speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:179 +#: src/libslic3r/PrintConfig.cpp:188 msgid "This fan speed is enforced during all bridges and overhangs." msgstr "" -#: src/libslic3r/PrintConfig.cpp:180 src/libslic3r/PrintConfig.cpp:756 -#: src/libslic3r/PrintConfig.cpp:1189 src/libslic3r/PrintConfig.cpp:1252 -#: src/libslic3r/PrintConfig.cpp:1497 src/libslic3r/PrintConfig.cpp:2295 -#: src/libslic3r/PrintConfig.cpp:2537 +#: src/libslic3r/PrintConfig.cpp:189 src/libslic3r/PrintConfig.cpp:770 +#: src/libslic3r/PrintConfig.cpp:1203 src/libslic3r/PrintConfig.cpp:1266 +#: src/libslic3r/PrintConfig.cpp:1511 src/libslic3r/PrintConfig.cpp:2366 +#: src/libslic3r/PrintConfig.cpp:2623 msgid "%" msgstr "" -#: src/libslic3r/PrintConfig.cpp:187 +#: src/libslic3r/PrintConfig.cpp:196 msgid "Bridge flow ratio" msgstr "" -#: src/libslic3r/PrintConfig.cpp:189 +#: src/libslic3r/PrintConfig.cpp:198 msgid "" "This factor affects the amount of plastic for bridging. You can decrease it " "slightly to pull the extrudates and prevent sagging, although default " @@ -4975,83 +5479,83 @@ msgid "" "before tweaking this." msgstr "" -#: src/libslic3r/PrintConfig.cpp:199 +#: src/libslic3r/PrintConfig.cpp:208 msgid "Bridges" msgstr "" -#: src/libslic3r/PrintConfig.cpp:201 +#: src/libslic3r/PrintConfig.cpp:210 msgid "Speed for printing bridges." msgstr "" -#: src/libslic3r/PrintConfig.cpp:202 src/libslic3r/PrintConfig.cpp:578 -#: src/libslic3r/PrintConfig.cpp:586 src/libslic3r/PrintConfig.cpp:595 -#: src/libslic3r/PrintConfig.cpp:603 src/libslic3r/PrintConfig.cpp:630 -#: src/libslic3r/PrintConfig.cpp:649 src/libslic3r/PrintConfig.cpp:885 -#: src/libslic3r/PrintConfig.cpp:1012 src/libslic3r/PrintConfig.cpp:1098 -#: src/libslic3r/PrintConfig.cpp:1134 src/libslic3r/PrintConfig.cpp:1147 -#: src/libslic3r/PrintConfig.cpp:1158 src/libslic3r/PrintConfig.cpp:1211 -#: src/libslic3r/PrintConfig.cpp:1270 src/libslic3r/PrintConfig.cpp:1398 -#: src/libslic3r/PrintConfig.cpp:1572 src/libslic3r/PrintConfig.cpp:1581 -#: src/libslic3r/PrintConfig.cpp:1976 src/libslic3r/PrintConfig.cpp:2088 +#: src/libslic3r/PrintConfig.cpp:211 src/libslic3r/PrintConfig.cpp:592 +#: src/libslic3r/PrintConfig.cpp:600 src/libslic3r/PrintConfig.cpp:609 +#: src/libslic3r/PrintConfig.cpp:617 src/libslic3r/PrintConfig.cpp:644 +#: src/libslic3r/PrintConfig.cpp:663 src/libslic3r/PrintConfig.cpp:899 +#: src/libslic3r/PrintConfig.cpp:1026 src/libslic3r/PrintConfig.cpp:1112 +#: src/libslic3r/PrintConfig.cpp:1148 src/libslic3r/PrintConfig.cpp:1161 +#: src/libslic3r/PrintConfig.cpp:1172 src/libslic3r/PrintConfig.cpp:1225 +#: src/libslic3r/PrintConfig.cpp:1284 src/libslic3r/PrintConfig.cpp:1412 +#: src/libslic3r/PrintConfig.cpp:1586 src/libslic3r/PrintConfig.cpp:1595 +#: src/libslic3r/PrintConfig.cpp:1991 src/libslic3r/PrintConfig.cpp:2104 msgid "mm/s" msgstr "" -#: src/libslic3r/PrintConfig.cpp:209 +#: src/libslic3r/PrintConfig.cpp:218 msgid "Brim width" msgstr "" -#: src/libslic3r/PrintConfig.cpp:210 +#: src/libslic3r/PrintConfig.cpp:219 msgid "" "Horizontal width of the brim that will be printed around each object on the " "first layer." msgstr "" -#: src/libslic3r/PrintConfig.cpp:217 +#: src/libslic3r/PrintConfig.cpp:226 msgid "Clip multi-part objects" msgstr "" -#: src/libslic3r/PrintConfig.cpp:218 +#: src/libslic3r/PrintConfig.cpp:227 msgid "" "When printing multi-material objects, this settings will make Slic3r to clip " "the overlapping object parts one by the other (2nd part will be clipped by " "the 1st, 3rd part will be clipped by the 1st and 2nd etc)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:225 +#: src/libslic3r/PrintConfig.cpp:234 msgid "Colorprint height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:226 +#: src/libslic3r/PrintConfig.cpp:235 msgid "Heights at which a filament change is to occur." msgstr "" -#: src/libslic3r/PrintConfig.cpp:236 +#: src/libslic3r/PrintConfig.cpp:245 msgid "Compatible printers condition" msgstr "" -#: src/libslic3r/PrintConfig.cpp:237 +#: src/libslic3r/PrintConfig.cpp:246 msgid "" "A boolean expression using the configuration values of an active printer " "profile. If this expression evaluates to true, this profile is considered " "compatible with the active printer profile." msgstr "" -#: src/libslic3r/PrintConfig.cpp:251 +#: src/libslic3r/PrintConfig.cpp:260 msgid "Compatible print profiles condition" msgstr "" -#: src/libslic3r/PrintConfig.cpp:252 +#: src/libslic3r/PrintConfig.cpp:261 msgid "" "A boolean expression using the configuration values of an active print " "profile. If this expression evaluates to true, this profile is considered " "compatible with the active print profile." msgstr "" -#: src/libslic3r/PrintConfig.cpp:269 +#: src/libslic3r/PrintConfig.cpp:278 msgid "Complete individual objects" msgstr "" -#: src/libslic3r/PrintConfig.cpp:270 +#: src/libslic3r/PrintConfig.cpp:279 msgid "" "When printing multiple objects or copies, this feature will complete each " "object before moving onto next one (and starting it from its bottom layer). " @@ -5059,177 +5563,178 @@ msgid "" "warn and prevent you from extruder collisions, but beware." msgstr "" -#: src/libslic3r/PrintConfig.cpp:278 +#: src/libslic3r/PrintConfig.cpp:287 msgid "Enable auto cooling" msgstr "" -#: src/libslic3r/PrintConfig.cpp:279 +#: src/libslic3r/PrintConfig.cpp:288 msgid "" "This flag enables the automatic cooling logic that adjusts print speed and " "fan speed according to layer printing time." msgstr "" -#: src/libslic3r/PrintConfig.cpp:284 +#: src/libslic3r/PrintConfig.cpp:293 msgid "Cooling tube position" msgstr "" -#: src/libslic3r/PrintConfig.cpp:285 +#: src/libslic3r/PrintConfig.cpp:294 msgid "Distance of the center-point of the cooling tube from the extruder tip." msgstr "" -#: src/libslic3r/PrintConfig.cpp:292 +#: src/libslic3r/PrintConfig.cpp:301 msgid "Cooling tube length" msgstr "" -#: src/libslic3r/PrintConfig.cpp:293 +#: src/libslic3r/PrintConfig.cpp:302 msgid "Length of the cooling tube to limit space for cooling moves inside it." msgstr "" -#: src/libslic3r/PrintConfig.cpp:301 +#: src/libslic3r/PrintConfig.cpp:310 msgid "" "This is the acceleration your printer will be reset to after the role-" "specific acceleration values are used (perimeter/infill). Set zero to " "prevent resetting acceleration at all." msgstr "" -#: src/libslic3r/PrintConfig.cpp:310 +#: src/libslic3r/PrintConfig.cpp:319 msgid "Default filament profile" msgstr "" -#: src/libslic3r/PrintConfig.cpp:311 +#: src/libslic3r/PrintConfig.cpp:320 msgid "" "Default filament profile associated with the current printer profile. On " "selection of the current printer profile, this filament profile will be " "activated." msgstr "" -#: src/libslic3r/PrintConfig.cpp:317 +#: src/libslic3r/PrintConfig.cpp:326 msgid "Default print profile" msgstr "" -#: src/libslic3r/PrintConfig.cpp:318 src/libslic3r/PrintConfig.cpp:2376 -#: src/libslic3r/PrintConfig.cpp:2387 +#: src/libslic3r/PrintConfig.cpp:327 src/libslic3r/PrintConfig.cpp:2447 +#: src/libslic3r/PrintConfig.cpp:2458 msgid "" "Default print profile associated with the current printer profile. On " "selection of the current printer profile, this print profile will be " "activated." msgstr "" -#: src/libslic3r/PrintConfig.cpp:324 +#: src/libslic3r/PrintConfig.cpp:333 msgid "Disable fan for the first" msgstr "" -#: src/libslic3r/PrintConfig.cpp:325 +#: src/libslic3r/PrintConfig.cpp:334 msgid "" "You can set this to a positive value to disable fan at all during the first " "layers, so that it does not make adhesion worse." msgstr "" -#: src/libslic3r/PrintConfig.cpp:327 src/libslic3r/PrintConfig.cpp:957 -#: src/libslic3r/PrintConfig.cpp:1470 src/libslic3r/PrintConfig.cpp:1655 -#: src/libslic3r/PrintConfig.cpp:1716 src/libslic3r/PrintConfig.cpp:1879 -#: src/libslic3r/PrintConfig.cpp:1924 +#: src/libslic3r/PrintConfig.cpp:336 src/libslic3r/PrintConfig.cpp:971 +#: src/libslic3r/PrintConfig.cpp:1484 src/libslic3r/PrintConfig.cpp:1669 +#: src/libslic3r/PrintConfig.cpp:1730 src/libslic3r/PrintConfig.cpp:1894 +#: src/libslic3r/PrintConfig.cpp:1939 msgid "layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:334 +#: src/libslic3r/PrintConfig.cpp:343 msgid "Don't support bridges" msgstr "" -#: src/libslic3r/PrintConfig.cpp:336 +#: src/libslic3r/PrintConfig.cpp:345 msgid "" "Experimental option for preventing support material from being generated " "under bridged areas." msgstr "" -#: src/libslic3r/PrintConfig.cpp:342 +#: src/libslic3r/PrintConfig.cpp:351 msgid "Distance between copies" msgstr "" -#: src/libslic3r/PrintConfig.cpp:343 +#: src/libslic3r/PrintConfig.cpp:352 msgid "Distance used for the auto-arrange feature of the plater." msgstr "" -#: src/libslic3r/PrintConfig.cpp:350 +#: src/libslic3r/PrintConfig.cpp:359 msgid "Elephant foot compensation" msgstr "" -#: src/libslic3r/PrintConfig.cpp:352 +#: src/libslic3r/PrintConfig.cpp:361 msgid "" "The first layer will be shrunk in the XY plane by the configured value to " "compensate for the 1st layer squish aka an Elephant Foot effect." msgstr "" -#: src/libslic3r/PrintConfig.cpp:361 +#: src/libslic3r/PrintConfig.cpp:370 msgid "" "This end procedure is inserted at the end of the output file. Note that you " "can use placeholder variables for all Slic3r settings." msgstr "" -#: src/libslic3r/PrintConfig.cpp:371 +#: src/libslic3r/PrintConfig.cpp:380 msgid "" "This end procedure is inserted at the end of the output file, before the " -"printer end gcode. Note that you can use placeholder variables for all " +"printer end gcode (and before any toolchange from this filament in case of " +"multimaterial printers). Note that you can use placeholder variables for all " "Slic3r settings. If you have multiple extruders, the gcode is processed in " "extruder order." msgstr "" -#: src/libslic3r/PrintConfig.cpp:381 +#: src/libslic3r/PrintConfig.cpp:391 msgid "Ensure vertical shell thickness" msgstr "" -#: src/libslic3r/PrintConfig.cpp:383 +#: src/libslic3r/PrintConfig.cpp:393 msgid "" "Add solid infill near sloping surfaces to guarantee the vertical shell " "thickness (top+bottom solid layers)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:389 +#: src/libslic3r/PrintConfig.cpp:399 msgid "Top fill pattern" msgstr "" -#: src/libslic3r/PrintConfig.cpp:391 +#: src/libslic3r/PrintConfig.cpp:401 msgid "" "Fill pattern for top infill. This only affects the top visible layer, and " "not its adjacent solid shells." msgstr "" -#: src/libslic3r/PrintConfig.cpp:399 src/libslic3r/PrintConfig.cpp:807 -#: src/libslic3r/PrintConfig.cpp:1957 +#: src/libslic3r/PrintConfig.cpp:409 src/libslic3r/PrintConfig.cpp:821 +#: src/libslic3r/PrintConfig.cpp:1972 msgid "Rectilinear" msgstr "" -#: src/libslic3r/PrintConfig.cpp:400 src/libslic3r/PrintConfig.cpp:813 +#: src/libslic3r/PrintConfig.cpp:410 src/libslic3r/PrintConfig.cpp:827 msgid "Concentric" msgstr "" -#: src/libslic3r/PrintConfig.cpp:401 src/libslic3r/PrintConfig.cpp:817 +#: src/libslic3r/PrintConfig.cpp:411 src/libslic3r/PrintConfig.cpp:831 msgid "Hilbert Curve" msgstr "" -#: src/libslic3r/PrintConfig.cpp:402 src/libslic3r/PrintConfig.cpp:818 +#: src/libslic3r/PrintConfig.cpp:412 src/libslic3r/PrintConfig.cpp:832 msgid "Archimedean Chords" msgstr "" -#: src/libslic3r/PrintConfig.cpp:403 src/libslic3r/PrintConfig.cpp:819 +#: src/libslic3r/PrintConfig.cpp:413 src/libslic3r/PrintConfig.cpp:833 msgid "Octagram Spiral" msgstr "" -#: src/libslic3r/PrintConfig.cpp:410 +#: src/libslic3r/PrintConfig.cpp:419 msgid "Bottom fill pattern" msgstr "" -#: src/libslic3r/PrintConfig.cpp:411 +#: src/libslic3r/PrintConfig.cpp:421 msgid "" "Fill pattern for bottom infill. This only affects the bottom external " "visible layer, and not its adjacent solid shells." msgstr "" -#: src/libslic3r/PrintConfig.cpp:416 src/libslic3r/PrintConfig.cpp:426 +#: src/libslic3r/PrintConfig.cpp:430 src/libslic3r/PrintConfig.cpp:440 msgid "External perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:418 +#: src/libslic3r/PrintConfig.cpp:432 msgid "" "Set this to a non-zero value to set a manual extrusion width for external " "perimeters. If left zero, default extrusion width will be used if set, " @@ -5237,43 +5742,43 @@ msgid "" "(for example 200%), it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:421 src/libslic3r/PrintConfig.cpp:529 -#: src/libslic3r/PrintConfig.cpp:846 src/libslic3r/PrintConfig.cpp:858 -#: src/libslic3r/PrintConfig.cpp:978 src/libslic3r/PrintConfig.cpp:1003 -#: src/libslic3r/PrintConfig.cpp:1389 src/libslic3r/PrintConfig.cpp:1727 -#: src/libslic3r/PrintConfig.cpp:1832 src/libslic3r/PrintConfig.cpp:1900 -#: src/libslic3r/PrintConfig.cpp:2058 +#: src/libslic3r/PrintConfig.cpp:435 src/libslic3r/PrintConfig.cpp:543 +#: src/libslic3r/PrintConfig.cpp:860 src/libslic3r/PrintConfig.cpp:872 +#: src/libslic3r/PrintConfig.cpp:992 src/libslic3r/PrintConfig.cpp:1017 +#: src/libslic3r/PrintConfig.cpp:1403 src/libslic3r/PrintConfig.cpp:1741 +#: src/libslic3r/PrintConfig.cpp:1847 src/libslic3r/PrintConfig.cpp:1915 +#: src/libslic3r/PrintConfig.cpp:2074 msgid "mm or %" msgstr "" -#: src/libslic3r/PrintConfig.cpp:428 +#: src/libslic3r/PrintConfig.cpp:442 msgid "" "This separate setting will affect the speed of external perimeters (the " "visible ones). If expressed as percentage (for example: 80%) it will be " "calculated on the perimeters speed setting above. Set to zero for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:431 src/libslic3r/PrintConfig.cpp:867 -#: src/libslic3r/PrintConfig.cpp:1686 src/libslic3r/PrintConfig.cpp:1737 -#: src/libslic3r/PrintConfig.cpp:1943 src/libslic3r/PrintConfig.cpp:2070 +#: src/libslic3r/PrintConfig.cpp:445 src/libslic3r/PrintConfig.cpp:881 +#: src/libslic3r/PrintConfig.cpp:1700 src/libslic3r/PrintConfig.cpp:1751 +#: src/libslic3r/PrintConfig.cpp:1958 src/libslic3r/PrintConfig.cpp:2086 msgid "mm/s or %" msgstr "" -#: src/libslic3r/PrintConfig.cpp:438 +#: src/libslic3r/PrintConfig.cpp:452 msgid "External perimeters first" msgstr "" -#: src/libslic3r/PrintConfig.cpp:440 +#: src/libslic3r/PrintConfig.cpp:454 msgid "" "Print contour perimeters from the outermost one to the innermost one instead " "of the default inverse order." msgstr "" -#: src/libslic3r/PrintConfig.cpp:446 +#: src/libslic3r/PrintConfig.cpp:460 msgid "Extra perimeters if needed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:448 +#: src/libslic3r/PrintConfig.cpp:462 #, possible-c-format msgid "" "Add more perimeters when needed for avoiding gaps in sloping walls. Slic3r " @@ -5281,14 +5786,14 @@ msgid "" "is supported." msgstr "" -#: src/libslic3r/PrintConfig.cpp:458 +#: src/libslic3r/PrintConfig.cpp:472 msgid "" "The extruder to use (unless more specific extruder settings are specified). " "This value overrides perimeter and infill extruders, but not the support " "extruders." msgstr "" -#: src/libslic3r/PrintConfig.cpp:470 +#: src/libslic3r/PrintConfig.cpp:484 msgid "" "Set this to the vertical distance between your nozzle tip and (usually) the " "X carriage rods. In other words, this is the height of the clearance " @@ -5296,30 +5801,30 @@ msgid "" "extruder can peek before colliding with other printed objects." msgstr "" -#: src/libslic3r/PrintConfig.cpp:480 +#: src/libslic3r/PrintConfig.cpp:494 msgid "Radius" msgstr "" -#: src/libslic3r/PrintConfig.cpp:481 +#: src/libslic3r/PrintConfig.cpp:495 msgid "" "Set this to the clearance radius around your extruder. If the extruder is " "not centered, choose the largest value for safety. This setting is used to " "check for collisions and to display the graphical preview in the plater." msgstr "" -#: src/libslic3r/PrintConfig.cpp:491 +#: src/libslic3r/PrintConfig.cpp:505 msgid "Extruder Color" msgstr "" -#: src/libslic3r/PrintConfig.cpp:492 src/libslic3r/PrintConfig.cpp:552 +#: src/libslic3r/PrintConfig.cpp:506 src/libslic3r/PrintConfig.cpp:566 msgid "This is only used in the Slic3r interface as a visual help." msgstr "" -#: src/libslic3r/PrintConfig.cpp:498 +#: src/libslic3r/PrintConfig.cpp:512 msgid "Extruder offset" msgstr "" -#: src/libslic3r/PrintConfig.cpp:499 +#: src/libslic3r/PrintConfig.cpp:513 msgid "" "If your firmware doesn't handle the extruder displacement you need the G-" "code to take it into account. This option lets you specify the displacement " @@ -5327,21 +5832,21 @@ msgid "" "coordinates (they will be subtracted from the XY coordinate)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:508 +#: src/libslic3r/PrintConfig.cpp:522 msgid "Extrusion axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:509 +#: src/libslic3r/PrintConfig.cpp:523 msgid "" "Use this option to set the axis letter associated to your printer's extruder " "(usually E but some printers use A)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:514 +#: src/libslic3r/PrintConfig.cpp:528 msgid "Extrusion multiplier" msgstr "" -#: src/libslic3r/PrintConfig.cpp:515 +#: src/libslic3r/PrintConfig.cpp:529 msgid "" "This factor changes the amount of flow proportionally. You may need to tweak " "this setting to get nice surface finish and correct single wall widths. " @@ -5349,11 +5854,11 @@ msgid "" "more, check filament diameter and your firmware E steps." msgstr "" -#: src/libslic3r/PrintConfig.cpp:523 +#: src/libslic3r/PrintConfig.cpp:537 msgid "Default extrusion width" msgstr "" -#: src/libslic3r/PrintConfig.cpp:525 +#: src/libslic3r/PrintConfig.cpp:539 msgid "" "Set this to a non-zero value to allow a manual extrusion width. If left to " "zero, Slic3r derives extrusion widths from the nozzle diameter (see the " @@ -5362,123 +5867,123 @@ msgid "" "height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:534 +#: src/libslic3r/PrintConfig.cpp:548 msgid "Keep fan always on" msgstr "" -#: src/libslic3r/PrintConfig.cpp:535 +#: src/libslic3r/PrintConfig.cpp:549 msgid "" "If this is enabled, fan will never be disabled and will be kept running at " "least at its minimum speed. Useful for PLA, harmful for ABS." msgstr "" -#: src/libslic3r/PrintConfig.cpp:540 +#: src/libslic3r/PrintConfig.cpp:554 msgid "Enable fan if layer print time is below" msgstr "" -#: src/libslic3r/PrintConfig.cpp:541 +#: src/libslic3r/PrintConfig.cpp:555 msgid "" "If layer print time is estimated below this number of seconds, fan will be " "enabled and its speed will be calculated by interpolating the minimum and " "maximum speeds." msgstr "" -#: src/libslic3r/PrintConfig.cpp:543 src/libslic3r/PrintConfig.cpp:1673 +#: src/libslic3r/PrintConfig.cpp:557 src/libslic3r/PrintConfig.cpp:1687 msgid "approximate seconds" msgstr "" -#: src/libslic3r/PrintConfig.cpp:551 +#: src/libslic3r/PrintConfig.cpp:565 msgid "Color" msgstr "" -#: src/libslic3r/PrintConfig.cpp:557 +#: src/libslic3r/PrintConfig.cpp:571 msgid "Filament notes" msgstr "" -#: src/libslic3r/PrintConfig.cpp:558 +#: src/libslic3r/PrintConfig.cpp:572 msgid "You can put your notes regarding the filament here." msgstr "" -#: src/libslic3r/PrintConfig.cpp:566 src/libslic3r/PrintConfig.cpp:1217 +#: src/libslic3r/PrintConfig.cpp:580 src/libslic3r/PrintConfig.cpp:1231 msgid "Max volumetric speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:567 +#: src/libslic3r/PrintConfig.cpp:581 msgid "" "Maximum volumetric speed allowed for this filament. Limits the maximum " "volumetric speed of a print to the minimum of print and filament volumetric " "speed. Set to zero for no limit." msgstr "" -#: src/libslic3r/PrintConfig.cpp:576 +#: src/libslic3r/PrintConfig.cpp:590 msgid "Loading speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:577 +#: src/libslic3r/PrintConfig.cpp:591 msgid "Speed used for loading the filament on the wipe tower." msgstr "" -#: src/libslic3r/PrintConfig.cpp:584 +#: src/libslic3r/PrintConfig.cpp:598 msgid "Loading speed at the start" msgstr "" -#: src/libslic3r/PrintConfig.cpp:585 +#: src/libslic3r/PrintConfig.cpp:599 msgid "Speed used at the very beginning of loading phase." msgstr "" -#: src/libslic3r/PrintConfig.cpp:592 +#: src/libslic3r/PrintConfig.cpp:606 msgid "Unloading speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:593 +#: src/libslic3r/PrintConfig.cpp:607 msgid "" "Speed used for unloading the filament on the wipe tower (does not affect " "initial part of unloading just after ramming)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:601 +#: src/libslic3r/PrintConfig.cpp:615 msgid "Unloading speed at the start" msgstr "" -#: src/libslic3r/PrintConfig.cpp:602 +#: src/libslic3r/PrintConfig.cpp:616 msgid "" "Speed used for unloading the tip of the filament immediately after ramming." msgstr "" -#: src/libslic3r/PrintConfig.cpp:609 +#: src/libslic3r/PrintConfig.cpp:623 msgid "Delay after unloading" msgstr "" -#: src/libslic3r/PrintConfig.cpp:610 +#: src/libslic3r/PrintConfig.cpp:624 msgid "" "Time to wait after the filament is unloaded. May help to get reliable " "toolchanges with flexible materials that may need more time to shrink to " "original dimensions." msgstr "" -#: src/libslic3r/PrintConfig.cpp:619 +#: src/libslic3r/PrintConfig.cpp:633 msgid "Number of cooling moves" msgstr "" -#: src/libslic3r/PrintConfig.cpp:620 +#: src/libslic3r/PrintConfig.cpp:634 msgid "" "Filament is cooled by being moved back and forth in the cooling tubes. " "Specify desired number of these moves." msgstr "" -#: src/libslic3r/PrintConfig.cpp:628 +#: src/libslic3r/PrintConfig.cpp:642 msgid "Speed of the first cooling move" msgstr "" -#: src/libslic3r/PrintConfig.cpp:629 +#: src/libslic3r/PrintConfig.cpp:643 msgid "Cooling moves are gradually accelerating beginning at this speed." msgstr "" -#: src/libslic3r/PrintConfig.cpp:636 +#: src/libslic3r/PrintConfig.cpp:650 msgid "Minimal purge on wipe tower" msgstr "" -#: src/libslic3r/PrintConfig.cpp:637 +#: src/libslic3r/PrintConfig.cpp:651 msgid "" "After a tool change, the exact position of the newly loaded filament inside " "the nozzle may not be known, and the filament pressure is likely not yet " @@ -5487,62 +5992,62 @@ msgid "" "to produce successive infill or sacrificial object extrusions reliably." msgstr "" -#: src/libslic3r/PrintConfig.cpp:641 +#: src/libslic3r/PrintConfig.cpp:655 msgid "mm³" msgstr "" -#: src/libslic3r/PrintConfig.cpp:647 +#: src/libslic3r/PrintConfig.cpp:661 msgid "Speed of the last cooling move" msgstr "" -#: src/libslic3r/PrintConfig.cpp:648 +#: src/libslic3r/PrintConfig.cpp:662 msgid "Cooling moves are gradually accelerating towards this speed." msgstr "" -#: src/libslic3r/PrintConfig.cpp:655 +#: src/libslic3r/PrintConfig.cpp:669 msgid "Filament load time" msgstr "" -#: src/libslic3r/PrintConfig.cpp:656 +#: src/libslic3r/PrintConfig.cpp:670 msgid "" "Time for the printer firmware (or the Multi Material Unit 2.0) to load a new " "filament during a tool change (when executing the T code). This time is " "added to the total print time by the G-code time estimator." msgstr "" -#: src/libslic3r/PrintConfig.cpp:663 +#: src/libslic3r/PrintConfig.cpp:677 msgid "Ramming parameters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:664 +#: src/libslic3r/PrintConfig.cpp:678 msgid "" "This string is edited by RammingDialog and contains ramming specific " "parameters." msgstr "" -#: src/libslic3r/PrintConfig.cpp:670 +#: src/libslic3r/PrintConfig.cpp:684 msgid "Filament unload time" msgstr "" -#: src/libslic3r/PrintConfig.cpp:671 +#: src/libslic3r/PrintConfig.cpp:685 msgid "" "Time for the printer firmware (or the Multi Material Unit 2.0) to unload a " "filament during a tool change (when executing the T code). This time is " "added to the total print time by the G-code time estimator." msgstr "" -#: src/libslic3r/PrintConfig.cpp:679 +#: src/libslic3r/PrintConfig.cpp:693 msgid "" "Enter your filament diameter here. Good precision is required, so use a " "caliper and do multiple measurements along the filament, then compute the " "average." msgstr "" -#: src/libslic3r/PrintConfig.cpp:686 +#: src/libslic3r/PrintConfig.cpp:700 msgid "Density" msgstr "" -#: src/libslic3r/PrintConfig.cpp:687 +#: src/libslic3r/PrintConfig.cpp:701 msgid "" "Enter your filament density here. This is only for statistical information. " "A decent way is to weigh a known length of filament and compute the ratio of " @@ -5550,113 +6055,113 @@ msgid "" "displacement." msgstr "" -#: src/libslic3r/PrintConfig.cpp:690 +#: src/libslic3r/PrintConfig.cpp:704 msgid "g/cm³" msgstr "" -#: src/libslic3r/PrintConfig.cpp:695 +#: src/libslic3r/PrintConfig.cpp:709 msgid "Filament type" msgstr "" -#: src/libslic3r/PrintConfig.cpp:696 +#: src/libslic3r/PrintConfig.cpp:710 msgid "The filament material type for use in custom G-codes." msgstr "" -#: src/libslic3r/PrintConfig.cpp:722 +#: src/libslic3r/PrintConfig.cpp:736 msgid "Soluble material" msgstr "" -#: src/libslic3r/PrintConfig.cpp:723 +#: src/libslic3r/PrintConfig.cpp:737 msgid "Soluble material is most likely used for a soluble support." msgstr "" -#: src/libslic3r/PrintConfig.cpp:729 +#: src/libslic3r/PrintConfig.cpp:743 msgid "" "Enter your filament cost per kg here. This is only for statistical " "information." msgstr "" -#: src/libslic3r/PrintConfig.cpp:730 +#: src/libslic3r/PrintConfig.cpp:744 msgid "money/kg" msgstr "" -#: src/libslic3r/PrintConfig.cpp:739 +#: src/libslic3r/PrintConfig.cpp:753 msgid "Fill angle" msgstr "" -#: src/libslic3r/PrintConfig.cpp:741 +#: src/libslic3r/PrintConfig.cpp:755 msgid "" "Default base angle for infill orientation. Cross-hatching will be applied to " "this. Bridges will be infilled using the best direction Slic3r can detect, " "so this setting does not affect them." msgstr "" -#: src/libslic3r/PrintConfig.cpp:753 +#: src/libslic3r/PrintConfig.cpp:767 msgid "Fill density" msgstr "" -#: src/libslic3r/PrintConfig.cpp:755 +#: src/libslic3r/PrintConfig.cpp:769 msgid "Density of internal infill, expressed in the range 0% - 100%." msgstr "" -#: src/libslic3r/PrintConfig.cpp:790 +#: src/libslic3r/PrintConfig.cpp:804 msgid "Fill pattern" msgstr "" -#: src/libslic3r/PrintConfig.cpp:792 +#: src/libslic3r/PrintConfig.cpp:806 msgid "Fill pattern for general low-density infill." msgstr "" -#: src/libslic3r/PrintConfig.cpp:808 +#: src/libslic3r/PrintConfig.cpp:822 msgid "Grid" msgstr "" -#: src/libslic3r/PrintConfig.cpp:809 +#: src/libslic3r/PrintConfig.cpp:823 msgid "Triangles" msgstr "" -#: src/libslic3r/PrintConfig.cpp:810 +#: src/libslic3r/PrintConfig.cpp:824 msgid "Stars" msgstr "" -#: src/libslic3r/PrintConfig.cpp:811 +#: src/libslic3r/PrintConfig.cpp:825 msgid "Cubic" msgstr "" -#: src/libslic3r/PrintConfig.cpp:812 +#: src/libslic3r/PrintConfig.cpp:826 msgid "Line" msgstr "" -#: src/libslic3r/PrintConfig.cpp:814 src/libslic3r/PrintConfig.cpp:1959 +#: src/libslic3r/PrintConfig.cpp:828 src/libslic3r/PrintConfig.cpp:1974 msgid "Honeycomb" msgstr "" -#: src/libslic3r/PrintConfig.cpp:815 +#: src/libslic3r/PrintConfig.cpp:829 msgid "3D Honeycomb" msgstr "" -#: src/libslic3r/PrintConfig.cpp:816 +#: src/libslic3r/PrintConfig.cpp:830 msgid "Gyroid" msgstr "" -#: src/libslic3r/PrintConfig.cpp:823 src/libslic3r/PrintConfig.cpp:832 -#: src/libslic3r/PrintConfig.cpp:840 src/libslic3r/PrintConfig.cpp:873 +#: src/libslic3r/PrintConfig.cpp:837 src/libslic3r/PrintConfig.cpp:846 +#: src/libslic3r/PrintConfig.cpp:854 src/libslic3r/PrintConfig.cpp:887 msgid "First layer" msgstr "" -#: src/libslic3r/PrintConfig.cpp:824 +#: src/libslic3r/PrintConfig.cpp:838 msgid "" "This is the acceleration your printer will use for first layer. Set zero to " "disable acceleration control for first layer." msgstr "" -#: src/libslic3r/PrintConfig.cpp:833 +#: src/libslic3r/PrintConfig.cpp:847 msgid "" "Heated build plate temperature for the first layer. Set this to zero to " "disable bed temperature control commands in the output." msgstr "" -#: src/libslic3r/PrintConfig.cpp:842 +#: src/libslic3r/PrintConfig.cpp:856 msgid "" "Set this to a non-zero value to set a manual extrusion width for first " "layer. You can use this to force fatter extrudates for better adhesion. If " @@ -5664,7 +6169,7 @@ msgid "" "layer height. If set to zero, it will use the default extrusion width." msgstr "" -#: src/libslic3r/PrintConfig.cpp:854 +#: src/libslic3r/PrintConfig.cpp:868 msgid "" "When printing with very low layer heights, you might still want to print a " "thicker bottom layer to improve adhesion and tolerance for non perfect build " @@ -5672,47 +6177,47 @@ msgid "" "example: 150%) over the default layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:863 +#: src/libslic3r/PrintConfig.cpp:877 msgid "First layer speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:864 +#: src/libslic3r/PrintConfig.cpp:878 msgid "" "If expressed as absolute value in mm/s, this speed will be applied to all " "the print moves of the first layer, regardless of their type. If expressed " "as a percentage (for example: 40%) it will scale the default speeds." msgstr "" -#: src/libslic3r/PrintConfig.cpp:874 +#: src/libslic3r/PrintConfig.cpp:888 msgid "" "Extruder temperature for first layer. If you want to control temperature " "manually during print, set this to zero to disable temperature control " "commands in the output file." msgstr "" -#: src/libslic3r/PrintConfig.cpp:883 +#: src/libslic3r/PrintConfig.cpp:897 msgid "" "Speed for filling small gaps using short zigzag moves. Keep this reasonably " "low to avoid too much shaking and resonance issues. Set zero to disable gaps " "filling." msgstr "" -#: src/libslic3r/PrintConfig.cpp:891 +#: src/libslic3r/PrintConfig.cpp:905 msgid "Verbose G-code" msgstr "" -#: src/libslic3r/PrintConfig.cpp:892 +#: src/libslic3r/PrintConfig.cpp:906 msgid "" "Enable this to get a commented G-code file, with each line explained by a " "descriptive text. If you print from SD card, the additional weight of the " "file could make your firmware slow down." msgstr "" -#: src/libslic3r/PrintConfig.cpp:899 +#: src/libslic3r/PrintConfig.cpp:913 msgid "G-code flavor" msgstr "" -#: src/libslic3r/PrintConfig.cpp:900 +#: src/libslic3r/PrintConfig.cpp:914 msgid "" "Some G/M-code commands, including temperature control and others, are not " "universal. Set this option to your printer's firmware to get a compatible " @@ -5720,15 +6225,15 @@ msgid "" "extrusion value at all." msgstr "" -#: src/libslic3r/PrintConfig.cpp:923 +#: src/libslic3r/PrintConfig.cpp:937 msgid "No extrusion" msgstr "" -#: src/libslic3r/PrintConfig.cpp:928 +#: src/libslic3r/PrintConfig.cpp:942 msgid "Label objects" msgstr "" -#: src/libslic3r/PrintConfig.cpp:929 +#: src/libslic3r/PrintConfig.cpp:943 msgid "" "Enable this to add comments into the G-Code labeling print moves with what " "object they belong to, which is useful for the Octoprint CancelObject " @@ -5736,46 +6241,46 @@ msgid "" "setup and Wipe into Object / Wipe into Infill." msgstr "" -#: src/libslic3r/PrintConfig.cpp:936 +#: src/libslic3r/PrintConfig.cpp:950 msgid "High extruder current on filament swap" msgstr "" -#: src/libslic3r/PrintConfig.cpp:937 +#: src/libslic3r/PrintConfig.cpp:951 msgid "" "It may be beneficial to increase the extruder motor current during the " "filament exchange sequence to allow for rapid ramming feed rates and to " "overcome resistance when loading a filament with an ugly shaped tip." msgstr "" -#: src/libslic3r/PrintConfig.cpp:945 +#: src/libslic3r/PrintConfig.cpp:959 msgid "" "This is the acceleration your printer will use for infill. Set zero to " "disable acceleration control for infill." msgstr "" -#: src/libslic3r/PrintConfig.cpp:953 +#: src/libslic3r/PrintConfig.cpp:967 msgid "Combine infill every" msgstr "" -#: src/libslic3r/PrintConfig.cpp:955 +#: src/libslic3r/PrintConfig.cpp:969 msgid "" "This feature allows to combine infill and speed up your print by extruding " "thicker infill layers while preserving thin perimeters, thus accuracy." msgstr "" -#: src/libslic3r/PrintConfig.cpp:958 +#: src/libslic3r/PrintConfig.cpp:972 msgid "Combine infill every n layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:964 +#: src/libslic3r/PrintConfig.cpp:978 msgid "Infill extruder" msgstr "" -#: src/libslic3r/PrintConfig.cpp:966 +#: src/libslic3r/PrintConfig.cpp:980 msgid "The extruder to use when printing infill." msgstr "" -#: src/libslic3r/PrintConfig.cpp:974 +#: src/libslic3r/PrintConfig.cpp:988 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill. If " "left zero, default extrusion width will be used if set, otherwise 1.125 x " @@ -5784,32 +6289,32 @@ msgid "" "example 90%) it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:983 +#: src/libslic3r/PrintConfig.cpp:997 msgid "Infill before perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:984 +#: src/libslic3r/PrintConfig.cpp:998 msgid "" "This option will switch the print order of perimeters and infill, making the " "latter first." msgstr "" -#: src/libslic3r/PrintConfig.cpp:989 +#: src/libslic3r/PrintConfig.cpp:1003 msgid "Only infill where needed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:991 +#: src/libslic3r/PrintConfig.cpp:1005 msgid "" "This option will limit infill to the areas actually needed for supporting " "ceilings (it will act as internal support material). If enabled, slows down " "the G-code generation due to the multiple checks involved." msgstr "" -#: src/libslic3r/PrintConfig.cpp:998 +#: src/libslic3r/PrintConfig.cpp:1012 msgid "Infill/perimeters overlap" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1000 +#: src/libslic3r/PrintConfig.cpp:1014 msgid "" "This setting applies an additional overlap between infill and perimeters for " "better bonding. Theoretically this shouldn't be needed, but backlash might " @@ -5817,30 +6322,30 @@ msgid "" "perimeter extrusion width." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1011 +#: src/libslic3r/PrintConfig.cpp:1025 msgid "Speed for printing the internal fill. Set to zero for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1019 +#: src/libslic3r/PrintConfig.cpp:1033 msgid "Inherits profile" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1020 +#: src/libslic3r/PrintConfig.cpp:1034 msgid "Name of the profile, from which this profile inherits." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1033 +#: src/libslic3r/PrintConfig.cpp:1047 msgid "Interface shells" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1034 +#: src/libslic3r/PrintConfig.cpp:1048 msgid "" "Force the generation of solid shells between adjacent materials/volumes. " "Useful for multi-extruder prints with translucent materials or manual " "soluble support material." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1043 +#: src/libslic3r/PrintConfig.cpp:1057 msgid "" "This custom code is inserted at every layer change, right after the Z move " "and before the extruder moves to the first layer point. Note that you can " @@ -5848,11 +6353,11 @@ msgid "" "[layer_z]." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1054 +#: src/libslic3r/PrintConfig.cpp:1068 msgid "Supports remaining times" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1055 +#: src/libslic3r/PrintConfig.cpp:1069 msgid "" "Emit M73 P[percent printed] R[remaining time in minutes] at 1 minute " "intervals into the G-code to let the firmware show accurate remaining time. " @@ -5860,151 +6365,151 @@ msgid "" "firmware supports M73 Qxx Sxx for the silent mode." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1063 +#: src/libslic3r/PrintConfig.cpp:1077 msgid "Supports stealth mode" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1064 +#: src/libslic3r/PrintConfig.cpp:1078 msgid "The firmware supports stealth mode" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1088 +#: src/libslic3r/PrintConfig.cpp:1102 msgid "Maximum feedrate X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1089 +#: src/libslic3r/PrintConfig.cpp:1103 msgid "Maximum feedrate Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1090 +#: src/libslic3r/PrintConfig.cpp:1104 msgid "Maximum feedrate Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1091 +#: src/libslic3r/PrintConfig.cpp:1105 msgid "Maximum feedrate E" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1094 +#: src/libslic3r/PrintConfig.cpp:1108 msgid "Maximum feedrate of the X axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1095 +#: src/libslic3r/PrintConfig.cpp:1109 msgid "Maximum feedrate of the Y axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1096 +#: src/libslic3r/PrintConfig.cpp:1110 msgid "Maximum feedrate of the Z axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1097 +#: src/libslic3r/PrintConfig.cpp:1111 msgid "Maximum feedrate of the E axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1106 +#: src/libslic3r/PrintConfig.cpp:1120 msgid "Maximum acceleration X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1107 +#: src/libslic3r/PrintConfig.cpp:1121 msgid "Maximum acceleration Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1108 +#: src/libslic3r/PrintConfig.cpp:1122 msgid "Maximum acceleration Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1109 +#: src/libslic3r/PrintConfig.cpp:1123 msgid "Maximum acceleration E" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1112 +#: src/libslic3r/PrintConfig.cpp:1126 msgid "Maximum acceleration of the X axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1113 +#: src/libslic3r/PrintConfig.cpp:1127 msgid "Maximum acceleration of the Y axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1114 +#: src/libslic3r/PrintConfig.cpp:1128 msgid "Maximum acceleration of the Z axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1115 +#: src/libslic3r/PrintConfig.cpp:1129 msgid "Maximum acceleration of the E axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1124 +#: src/libslic3r/PrintConfig.cpp:1138 msgid "Maximum jerk X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1125 +#: src/libslic3r/PrintConfig.cpp:1139 msgid "Maximum jerk Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1126 +#: src/libslic3r/PrintConfig.cpp:1140 msgid "Maximum jerk Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1127 +#: src/libslic3r/PrintConfig.cpp:1141 msgid "Maximum jerk E" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1130 +#: src/libslic3r/PrintConfig.cpp:1144 msgid "Maximum jerk of the X axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1131 +#: src/libslic3r/PrintConfig.cpp:1145 msgid "Maximum jerk of the Y axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1132 +#: src/libslic3r/PrintConfig.cpp:1146 msgid "Maximum jerk of the Z axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1133 +#: src/libslic3r/PrintConfig.cpp:1147 msgid "Maximum jerk of the E axis" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1144 +#: src/libslic3r/PrintConfig.cpp:1158 msgid "Minimum feedrate when extruding" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1146 +#: src/libslic3r/PrintConfig.cpp:1160 msgid "Minimum feedrate when extruding (M205 S)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1155 +#: src/libslic3r/PrintConfig.cpp:1169 msgid "Minimum travel feedrate" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1157 +#: src/libslic3r/PrintConfig.cpp:1171 msgid "Minimum travel feedrate (M205 T)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1166 +#: src/libslic3r/PrintConfig.cpp:1180 msgid "Maximum acceleration when extruding" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1168 +#: src/libslic3r/PrintConfig.cpp:1182 msgid "Maximum acceleration when extruding (M204 S)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1177 +#: src/libslic3r/PrintConfig.cpp:1191 msgid "Maximum acceleration when retracting" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1179 +#: src/libslic3r/PrintConfig.cpp:1193 msgid "Maximum acceleration when retracting (M204 T)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1187 src/libslic3r/PrintConfig.cpp:1196 +#: src/libslic3r/PrintConfig.cpp:1201 src/libslic3r/PrintConfig.cpp:1210 msgid "Max" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1188 +#: src/libslic3r/PrintConfig.cpp:1202 msgid "This setting represents the maximum speed of your fan." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1197 +#: src/libslic3r/PrintConfig.cpp:1211 #, possible-c-format msgid "" "This is the highest printable layer height for this extruder, used to cap " @@ -6013,28 +6518,28 @@ msgid "" "adhesion. If set to 0, layer height is limited to 75% of the nozzle diameter." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1207 +#: src/libslic3r/PrintConfig.cpp:1221 msgid "Max print speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1208 +#: src/libslic3r/PrintConfig.cpp:1222 msgid "" "When setting other speed settings to 0 Slic3r will autocalculate the optimal " "speed in order to keep constant extruder pressure. This experimental setting " "is used to set the highest print speed you want to allow." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1218 +#: src/libslic3r/PrintConfig.cpp:1232 msgid "" "This experimental setting is used to set the maximum volumetric speed your " "extruder supports." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1227 +#: src/libslic3r/PrintConfig.cpp:1241 msgid "Max volumetric slope positive" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1228 src/libslic3r/PrintConfig.cpp:1239 +#: src/libslic3r/PrintConfig.cpp:1242 src/libslic3r/PrintConfig.cpp:1253 msgid "" "This experimental setting is used to limit the speed of change in extrusion " "rate. A value of 1.8 mm³/s² ensures, that a change from the extrusion rate " @@ -6042,99 +6547,95 @@ msgid "" "s) to 5.4 mm³/s (feedrate 60 mm/s) will take at least 2 seconds." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1232 src/libslic3r/PrintConfig.cpp:1243 +#: src/libslic3r/PrintConfig.cpp:1246 src/libslic3r/PrintConfig.cpp:1257 msgid "mm³/s²" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1238 +#: src/libslic3r/PrintConfig.cpp:1252 msgid "Max volumetric slope negative" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1250 src/libslic3r/PrintConfig.cpp:1259 +#: src/libslic3r/PrintConfig.cpp:1264 src/libslic3r/PrintConfig.cpp:1273 msgid "Min" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1251 +#: src/libslic3r/PrintConfig.cpp:1265 msgid "This setting represents the minimum PWM your fan needs to work." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1260 +#: src/libslic3r/PrintConfig.cpp:1274 msgid "" "This is the lowest printable layer height for this extruder and limits the " "resolution for variable layer height. Typical values are between 0.05 mm and " "0.1 mm." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1268 +#: src/libslic3r/PrintConfig.cpp:1282 msgid "Min print speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1269 +#: src/libslic3r/PrintConfig.cpp:1283 msgid "Slic3r will not scale speed down below this speed." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1276 +#: src/libslic3r/PrintConfig.cpp:1290 msgid "Minimal filament extrusion length" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1277 +#: src/libslic3r/PrintConfig.cpp:1291 msgid "" "Generate no less than the number of skirt loops required to consume the " "specified amount of filament on the bottom layer. For multi-extruder " "machines, this minimum applies to each extruder." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1286 +#: src/libslic3r/PrintConfig.cpp:1300 msgid "Configuration notes" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1287 +#: src/libslic3r/PrintConfig.cpp:1301 msgid "" "You can put here your personal notes. This text will be added to the G-code " "header comments." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1296 -msgid "Nozzle diameter" -msgstr "" - -#: src/libslic3r/PrintConfig.cpp:1297 +#: src/libslic3r/PrintConfig.cpp:1311 msgid "" "This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1302 +#: src/libslic3r/PrintConfig.cpp:1316 msgid "Host Type" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1303 +#: src/libslic3r/PrintConfig.cpp:1317 msgid "" "Slic3r can upload G-code files to a printer host. This field must contain " "the kind of the host." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1314 +#: src/libslic3r/PrintConfig.cpp:1328 msgid "Only retract when crossing perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1315 +#: src/libslic3r/PrintConfig.cpp:1329 msgid "" "Disables retraction when the travel path does not exceed the upper layer's " "perimeters (and thus any ooze will be probably invisible)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1322 +#: src/libslic3r/PrintConfig.cpp:1336 msgid "" "This option will drop the temperature of the inactive extruders to prevent " "oozing. It will enable a tall skirt automatically and move extruders outside " "such skirt when changing temperatures." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1329 +#: src/libslic3r/PrintConfig.cpp:1343 msgid "Output filename format" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1330 +#: src/libslic3r/PrintConfig.cpp:1344 msgid "" "You can use all configuration options as variables inside this template. For " "example: [layer_height], [fill_density] etc. You can also use [timestamp], " @@ -6142,31 +6643,31 @@ msgid "" "[input_filename], [input_filename_base]." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1339 +#: src/libslic3r/PrintConfig.cpp:1353 msgid "Detect bridging perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1341 +#: src/libslic3r/PrintConfig.cpp:1355 msgid "" "Experimental option to adjust flow for overhangs (bridge flow will be used), " "to apply bridge speed to them and enable fan." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1347 +#: src/libslic3r/PrintConfig.cpp:1361 msgid "Filament parking position" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1348 +#: src/libslic3r/PrintConfig.cpp:1362 msgid "" "Distance of the extruder tip from the position where the filament is parked " "when unloaded. This should match the value in printer firmware." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1356 +#: src/libslic3r/PrintConfig.cpp:1370 msgid "Extra loading distance" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1357 +#: src/libslic3r/PrintConfig.cpp:1371 msgid "" "When set to zero, the distance the filament is moved from parking position " "during load is exactly the same as it was moved back during unload. When " @@ -6174,28 +6675,28 @@ msgid "" "than unloading." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1365 src/libslic3r/PrintConfig.cpp:1383 -#: src/libslic3r/PrintConfig.cpp:1395 src/libslic3r/PrintConfig.cpp:1405 +#: src/libslic3r/PrintConfig.cpp:1379 src/libslic3r/PrintConfig.cpp:1397 +#: src/libslic3r/PrintConfig.cpp:1409 src/libslic3r/PrintConfig.cpp:1419 msgid "Perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1366 +#: src/libslic3r/PrintConfig.cpp:1380 msgid "" "This is the acceleration your printer will use for perimeters. A high value " "like 9000 usually gives good results if your hardware is up to the job. Set " "zero to disable acceleration control for perimeters." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1374 +#: src/libslic3r/PrintConfig.cpp:1388 msgid "Perimeter extruder" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1376 +#: src/libslic3r/PrintConfig.cpp:1390 msgid "" "The extruder to use when printing perimeters and brim. First extruder is 1." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1385 +#: src/libslic3r/PrintConfig.cpp:1399 msgid "" "Set this to a non-zero value to set a manual extrusion width for perimeters. " "You may want to use thinner extrudates to get more accurate surfaces. If " @@ -6204,12 +6705,12 @@ msgid "" "it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1397 +#: src/libslic3r/PrintConfig.cpp:1411 msgid "" "Speed for perimeters (contours, aka vertical shells). Set to zero for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1407 +#: src/libslic3r/PrintConfig.cpp:1421 msgid "" "This option sets the number of perimeters to generate for each layer. Note " "that Slic3r may increase this number automatically when it detects sloping " @@ -6217,11 +6718,11 @@ msgid "" "Perimeters option is enabled." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1411 +#: src/libslic3r/PrintConfig.cpp:1425 msgid "(minimum)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1419 +#: src/libslic3r/PrintConfig.cpp:1433 msgid "" "If you want to process the output G-code through custom scripts, just list " "their absolute paths here. Separate multiple scripts with a semicolon. " @@ -6230,55 +6731,55 @@ msgid "" "environment variables." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1431 +#: src/libslic3r/PrintConfig.cpp:1445 msgid "Printer type" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1432 +#: src/libslic3r/PrintConfig.cpp:1446 msgid "Type of the printer." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1437 +#: src/libslic3r/PrintConfig.cpp:1451 msgid "Printer notes" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1438 +#: src/libslic3r/PrintConfig.cpp:1452 msgid "You can put your notes regarding the printer here." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1446 +#: src/libslic3r/PrintConfig.cpp:1460 msgid "Printer vendor" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1447 +#: src/libslic3r/PrintConfig.cpp:1461 msgid "Name of the printer vendor." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1452 +#: src/libslic3r/PrintConfig.cpp:1466 msgid "Printer variant" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1453 +#: src/libslic3r/PrintConfig.cpp:1467 msgid "" "Name of the printer variant. For example, the printer variants may be " "differentiated by a nozzle diameter." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1466 +#: src/libslic3r/PrintConfig.cpp:1480 msgid "Raft layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1468 +#: src/libslic3r/PrintConfig.cpp:1482 msgid "" "The object will be raised by this number of layers, and support material " "will be generated under it." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1476 +#: src/libslic3r/PrintConfig.cpp:1490 msgid "Resolution" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1477 +#: src/libslic3r/PrintConfig.cpp:1491 msgid "" "Minimum detail resolution, used to simplify the input file for speeding up " "the slicing job and reducing memory usage. High-resolution models often " @@ -6286,278 +6787,278 @@ msgid "" "simplification and use full resolution from input." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1487 +#: src/libslic3r/PrintConfig.cpp:1501 msgid "Minimum travel after retraction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1488 +#: src/libslic3r/PrintConfig.cpp:1502 msgid "" "Retraction is not triggered when travel moves are shorter than this length." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1494 +#: src/libslic3r/PrintConfig.cpp:1508 msgid "Retract amount before wipe" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1495 +#: src/libslic3r/PrintConfig.cpp:1509 msgid "" "With bowden extruders, it may be wise to do some amount of quick retract " "before doing the wipe movement." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1502 +#: src/libslic3r/PrintConfig.cpp:1516 msgid "Retract on layer change" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1503 +#: src/libslic3r/PrintConfig.cpp:1517 msgid "This flag enforces a retraction whenever a Z move is done." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1508 src/libslic3r/PrintConfig.cpp:1516 +#: src/libslic3r/PrintConfig.cpp:1522 src/libslic3r/PrintConfig.cpp:1530 msgid "Length" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1509 +#: src/libslic3r/PrintConfig.cpp:1523 msgid "Retraction Length" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1510 +#: src/libslic3r/PrintConfig.cpp:1524 msgid "" "When retraction is triggered, filament is pulled back by the specified " "amount (the length is measured on raw filament, before it enters the " "extruder)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1512 src/libslic3r/PrintConfig.cpp:1521 +#: src/libslic3r/PrintConfig.cpp:1526 src/libslic3r/PrintConfig.cpp:1535 msgid "mm (zero to disable)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1517 +#: src/libslic3r/PrintConfig.cpp:1531 msgid "Retraction Length (Toolchange)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1518 +#: src/libslic3r/PrintConfig.cpp:1532 msgid "" "When retraction is triggered before changing tool, filament is pulled back " "by the specified amount (the length is measured on raw filament, before it " "enters the extruder)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1526 +#: src/libslic3r/PrintConfig.cpp:1540 msgid "Lift Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1527 +#: src/libslic3r/PrintConfig.cpp:1541 msgid "" "If you set this to a positive value, Z is quickly raised every time a " "retraction is triggered. When using multiple extruders, only the setting for " "the first extruder will be considered." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1534 +#: src/libslic3r/PrintConfig.cpp:1548 msgid "Above Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1535 +#: src/libslic3r/PrintConfig.cpp:1549 msgid "Only lift Z above" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1536 +#: src/libslic3r/PrintConfig.cpp:1550 msgid "" "If you set this to a positive value, Z lift will only take place above the " "specified absolute Z. You can tune this setting for skipping lift on the " "first layers." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1543 +#: src/libslic3r/PrintConfig.cpp:1557 msgid "Below Z" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1544 +#: src/libslic3r/PrintConfig.cpp:1558 msgid "Only lift Z below" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1545 +#: src/libslic3r/PrintConfig.cpp:1559 msgid "" "If you set this to a positive value, Z lift will only take place below the " "specified absolute Z. You can tune this setting for limiting lift to the " "first layers." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1553 src/libslic3r/PrintConfig.cpp:1561 +#: src/libslic3r/PrintConfig.cpp:1567 src/libslic3r/PrintConfig.cpp:1575 msgid "Extra length on restart" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1554 +#: src/libslic3r/PrintConfig.cpp:1568 msgid "" "When the retraction is compensated after the travel move, the extruder will " "push this additional amount of filament. This setting is rarely needed." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1562 +#: src/libslic3r/PrintConfig.cpp:1576 msgid "" "When the retraction is compensated after changing tool, the extruder will " "push this additional amount of filament." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1569 src/libslic3r/PrintConfig.cpp:1570 +#: src/libslic3r/PrintConfig.cpp:1583 src/libslic3r/PrintConfig.cpp:1584 msgid "Retraction Speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1571 +#: src/libslic3r/PrintConfig.cpp:1585 msgid "The speed for retractions (it only applies to the extruder motor)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1577 src/libslic3r/PrintConfig.cpp:1578 +#: src/libslic3r/PrintConfig.cpp:1591 src/libslic3r/PrintConfig.cpp:1592 msgid "Deretraction Speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1579 +#: src/libslic3r/PrintConfig.cpp:1593 msgid "" "The speed for loading of a filament into extruder after retraction (it only " "applies to the extruder motor). If left to zero, the retraction speed is " "used." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1586 +#: src/libslic3r/PrintConfig.cpp:1600 msgid "Seam position" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1588 +#: src/libslic3r/PrintConfig.cpp:1602 msgid "Position of perimeters starting points." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1594 +#: src/libslic3r/PrintConfig.cpp:1608 msgid "Random" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1595 +#: src/libslic3r/PrintConfig.cpp:1609 msgid "Nearest" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1596 +#: src/libslic3r/PrintConfig.cpp:1610 msgid "Aligned" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1604 +#: src/libslic3r/PrintConfig.cpp:1618 msgid "Direction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1606 +#: src/libslic3r/PrintConfig.cpp:1620 msgid "Preferred direction of the seam" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1607 +#: src/libslic3r/PrintConfig.cpp:1621 msgid "Seam preferred direction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1614 +#: src/libslic3r/PrintConfig.cpp:1628 msgid "Jitter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1616 +#: src/libslic3r/PrintConfig.cpp:1630 msgid "Seam preferred direction jitter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1617 +#: src/libslic3r/PrintConfig.cpp:1631 msgid "Preferred direction of the seam - jitter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1627 +#: src/libslic3r/PrintConfig.cpp:1641 msgid "USB/serial port for printer connection." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1634 +#: src/libslic3r/PrintConfig.cpp:1648 msgid "Serial port speed" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1635 +#: src/libslic3r/PrintConfig.cpp:1649 msgid "Speed (baud) of USB/serial port for printer connection." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1644 +#: src/libslic3r/PrintConfig.cpp:1658 msgid "Distance from object" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1645 +#: src/libslic3r/PrintConfig.cpp:1659 msgid "" "Distance between skirt and object(s). Set this to zero to attach the skirt " "to the object(s) and get a brim for better adhesion." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1652 +#: src/libslic3r/PrintConfig.cpp:1666 msgid "Skirt height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1653 +#: src/libslic3r/PrintConfig.cpp:1667 msgid "" "Height of skirt expressed in layers. Set this to a tall value to use skirt " "as a shield against drafts." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1660 +#: src/libslic3r/PrintConfig.cpp:1674 msgid "Loops (minimum)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1661 +#: src/libslic3r/PrintConfig.cpp:1675 msgid "Skirt Loops" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1662 +#: src/libslic3r/PrintConfig.cpp:1676 msgid "" "Number of loops for the skirt. If the Minimum Extrusion Length option is " "set, the number of loops might be greater than the one configured here. Set " "this to zero to disable skirt completely." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1670 +#: src/libslic3r/PrintConfig.cpp:1684 msgid "Slow down if layer print time is below" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1671 +#: src/libslic3r/PrintConfig.cpp:1685 msgid "" "If layer print time is estimated below this number of seconds, print moves " "speed will be scaled down to extend duration to this value." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1681 +#: src/libslic3r/PrintConfig.cpp:1695 msgid "Small perimeters" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1683 +#: src/libslic3r/PrintConfig.cpp:1697 msgid "" "This separate setting will affect the speed of perimeters having radius <= " "6.5mm (usually holes). If expressed as percentage (for example: 80%) it will " "be calculated on the perimeters speed setting above. Set to zero for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1693 +#: src/libslic3r/PrintConfig.cpp:1707 msgid "Solid infill threshold area" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1695 +#: src/libslic3r/PrintConfig.cpp:1709 msgid "" "Force solid infill for regions having a smaller area than the specified " "threshold." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1696 +#: src/libslic3r/PrintConfig.cpp:1710 msgid "mm²" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1702 +#: src/libslic3r/PrintConfig.cpp:1716 msgid "Solid infill extruder" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1704 +#: src/libslic3r/PrintConfig.cpp:1718 msgid "The extruder to use when printing solid infill." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1710 +#: src/libslic3r/PrintConfig.cpp:1724 msgid "Solid infill every" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1712 +#: src/libslic3r/PrintConfig.cpp:1726 msgid "" "This feature allows to force a solid layer every given number of layers. " "Zero to disable. You can set this to any value (for example 9999); Slic3r " @@ -6565,7 +7066,7 @@ msgid "" "according to nozzle diameter and layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1724 +#: src/libslic3r/PrintConfig.cpp:1738 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill for " "solid surfaces. If left zero, default extrusion width will be used if set, " @@ -6573,22 +7074,22 @@ msgid "" "(for example 90%) it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1734 +#: src/libslic3r/PrintConfig.cpp:1748 msgid "" "Speed for printing solid regions (top/bottom/internal horizontal shells). " "This can be expressed as a percentage (for example: 80%) over the default " "infill speed above. Set to zero for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1746 +#: src/libslic3r/PrintConfig.cpp:1760 msgid "Number of solid layers to generate on top and bottom surfaces." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1752 +#: src/libslic3r/PrintConfig.cpp:1766 msgid "Spiral vase" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1753 +#: src/libslic3r/PrintConfig.cpp:1767 msgid "" "This feature will raise Z gradually while printing a single-walled object in " "order to remove any visible seam. This option requires a single perimeter, " @@ -6597,18 +7098,18 @@ msgid "" "when printing more than an object." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1761 +#: src/libslic3r/PrintConfig.cpp:1775 msgid "Temperature variation" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1762 +#: src/libslic3r/PrintConfig.cpp:1776 msgid "" "Temperature difference to be applied when an extruder is not active. Enables " "a full-height \"sacrificial\" skirt on which the nozzles are periodically " "wiped." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1772 +#: src/libslic3r/PrintConfig.cpp:1786 msgid "" "This start procedure is inserted at the beginning, after bed has reached the " "target temperature and extruder just started heating, and before extruder " @@ -6619,105 +7120,106 @@ msgid "" "\"M109 S[first_layer_temperature]\" command wherever you want." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1787 +#: src/libslic3r/PrintConfig.cpp:1801 msgid "" "This start procedure is inserted at the beginning, after any printer start " -"gcode. This is used to override settings for a specific filament. If Slic3r " -"detects M104, M109, M140 or M190 in your custom codes, such commands will " -"not be prepended automatically so you're free to customize the order of " +"gcode (and after any toolchange to this filament in case of multi-material " +"printers). This is used to override settings for a specific filament. If " +"Slic3r detects M104, M109, M140 or M190 in your custom codes, such commands " +"will not be prepended automatically so you're free to customize the order of " "heating commands and other custom actions. Note that you can use placeholder " "variables for all Slic3r settings, so you can put a \"M109 " "S[first_layer_temperature]\" command wherever you want. If you have multiple " "extruders, the gcode is processed in extruder order." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1802 +#: src/libslic3r/PrintConfig.cpp:1817 msgid "Single Extruder Multi Material" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1803 +#: src/libslic3r/PrintConfig.cpp:1818 msgid "The printer multiplexes filaments into a single hot end." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1808 +#: src/libslic3r/PrintConfig.cpp:1823 msgid "Prime all printing extruders" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1809 +#: src/libslic3r/PrintConfig.cpp:1824 msgid "" "If enabled, all printing extruders will be primed at the front edge of the " "print bed at the start of the print." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1814 +#: src/libslic3r/PrintConfig.cpp:1829 msgid "Generate support material" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1816 +#: src/libslic3r/PrintConfig.cpp:1831 msgid "Enable support material generation." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1820 +#: src/libslic3r/PrintConfig.cpp:1835 msgid "Auto generated supports" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1822 +#: src/libslic3r/PrintConfig.cpp:1837 msgid "" "If checked, supports will be generated automatically based on the overhang " "threshold value. If unchecked, supports will be generated inside the " "\"Support Enforcer\" volumes only." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1828 +#: src/libslic3r/PrintConfig.cpp:1843 msgid "XY separation between an object and its support" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1830 +#: src/libslic3r/PrintConfig.cpp:1845 msgid "" "XY separation between an object and its support. If expressed as percentage " "(for example 50%), it will be calculated over external perimeter width." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1840 +#: src/libslic3r/PrintConfig.cpp:1855 msgid "Pattern angle" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1842 +#: src/libslic3r/PrintConfig.cpp:1857 msgid "" "Use this setting to rotate the support material pattern on the horizontal " "plane." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1852 src/libslic3r/PrintConfig.cpp:2460 +#: src/libslic3r/PrintConfig.cpp:1867 src/libslic3r/PrintConfig.cpp:2531 msgid "" "Only create support if it lies on a build plate. Don't create support on a " "print." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1858 +#: src/libslic3r/PrintConfig.cpp:1873 msgid "Contact Z distance" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1860 +#: src/libslic3r/PrintConfig.cpp:1875 msgid "" "The vertical distance between object and support material interface. Setting " "this to 0 will also prevent Slic3r from using bridge flow and speed for the " "first object layer." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1867 +#: src/libslic3r/PrintConfig.cpp:1882 msgid "0 (soluble)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1868 +#: src/libslic3r/PrintConfig.cpp:1883 msgid "0.2 (detachable)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1873 +#: src/libslic3r/PrintConfig.cpp:1888 msgid "Enforce support for the first" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1875 +#: src/libslic3r/PrintConfig.cpp:1890 msgid "" "Generate support material for the specified number of layers counting from " "bottom, regardless of whether normal support material is enabled or not and " @@ -6725,21 +7227,21 @@ msgid "" "of objects having a very thin or poor footprint on the build plate." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1880 +#: src/libslic3r/PrintConfig.cpp:1895 msgid "Enforce support for the first n layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1886 +#: src/libslic3r/PrintConfig.cpp:1901 msgid "Support material/raft/skirt extruder" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1888 +#: src/libslic3r/PrintConfig.cpp:1903 msgid "" "The extruder to use when printing support material, raft and skirt (1+, 0 to " "use the current extruder to minimize tool changes)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1897 +#: src/libslic3r/PrintConfig.cpp:1912 msgid "" "Set this to a non-zero value to set a manual extrusion width for support " "material. If left zero, default extrusion width will be used if set, " @@ -6747,89 +7249,89 @@ msgid "" "example 90%) it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1905 +#: src/libslic3r/PrintConfig.cpp:1920 msgid "Interface loops" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1907 +#: src/libslic3r/PrintConfig.cpp:1922 msgid "" "Cover the top contact layer of the supports with loops. Disabled by default." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1912 +#: src/libslic3r/PrintConfig.cpp:1927 msgid "Support material/raft interface extruder" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1914 +#: src/libslic3r/PrintConfig.cpp:1929 msgid "" "The extruder to use when printing support material interface (1+, 0 to use " "the current extruder to minimize tool changes). This affects raft too." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1921 +#: src/libslic3r/PrintConfig.cpp:1936 msgid "Interface layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1923 +#: src/libslic3r/PrintConfig.cpp:1938 msgid "" "Number of interface layers to insert between the object(s) and support " "material." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1930 +#: src/libslic3r/PrintConfig.cpp:1945 msgid "Interface pattern spacing" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1932 +#: src/libslic3r/PrintConfig.cpp:1947 msgid "Spacing between interface lines. Set zero to get a solid interface." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1941 +#: src/libslic3r/PrintConfig.cpp:1956 msgid "" "Speed for printing support material interface layers. If expressed as " "percentage (for example 50%) it will be calculated over support material " "speed." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1950 +#: src/libslic3r/PrintConfig.cpp:1965 msgid "Pattern" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1952 +#: src/libslic3r/PrintConfig.cpp:1967 msgid "Pattern used to generate support material." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1958 +#: src/libslic3r/PrintConfig.cpp:1973 msgid "Rectilinear grid" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1964 +#: src/libslic3r/PrintConfig.cpp:1979 msgid "Pattern spacing" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1966 +#: src/libslic3r/PrintConfig.cpp:1981 msgid "Spacing between support material lines." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1975 +#: src/libslic3r/PrintConfig.cpp:1990 msgid "Speed for printing support material." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1982 +#: src/libslic3r/PrintConfig.cpp:1997 msgid "Synchronize with object layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1984 +#: src/libslic3r/PrintConfig.cpp:1999 msgid "" "Synchronize support layers with the object print layers. This is useful with " "multi-material printers, where the extruder switch is expensive." msgstr "" -#: src/libslic3r/PrintConfig.cpp:1990 +#: src/libslic3r/PrintConfig.cpp:2005 msgid "Overhang threshold" msgstr "" -#: src/libslic3r/PrintConfig.cpp:1992 +#: src/libslic3r/PrintConfig.cpp:2007 msgid "" "Support material will not be generated for overhangs whose slope angle (90° " "= vertical) is above the given threshold. In other words, this value " @@ -6838,50 +7340,53 @@ msgid "" "detection (recommended)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2004 +#: src/libslic3r/PrintConfig.cpp:2019 msgid "With sheath around the support" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2006 +#: src/libslic3r/PrintConfig.cpp:2021 msgid "" "Add a sheath (a single perimeter line) around the base support. This makes " "the support more reliable, but also more difficult to remove." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2013 +#: src/libslic3r/PrintConfig.cpp:2028 msgid "" "Extruder temperature for layers after the first one. Set this to zero to " "disable temperature control commands in the output." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2021 +#: src/libslic3r/PrintConfig.cpp:2036 msgid "Detect thin walls" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2023 +#: src/libslic3r/PrintConfig.cpp:2038 msgid "" "Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2029 +#: src/libslic3r/PrintConfig.cpp:2044 msgid "Threads" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2030 +#: src/libslic3r/PrintConfig.cpp:2045 msgid "" "Threads are used to parallelize long-running tasks. Optimal threads number " "is slightly above the number of available cores/processors." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2042 +#: src/libslic3r/PrintConfig.cpp:2057 msgid "" -"This custom code is inserted right before every extruder change. Note that " -"you can use placeholder variables for all Slic3r settings as well as " -"[previous_extruder] and [next_extruder]." +"This custom code is inserted at every extruder change. If you don't leave " +"this empty, you are expected to take care of the toolchange yourself - " +"PrusaSlicer will not output any other G-code to change the filament. You can " +"use placeholder variables for all Slic3r settings as well as " +"[previous_extruder] and [next_extruder], so e.g. the standard toolchange " +"command can be scripted as T[next_extruder]." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2054 +#: src/libslic3r/PrintConfig.cpp:2070 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill for " "top surfaces. You may want to use thinner extrudates to fill all narrow " @@ -6890,7 +7395,7 @@ msgid "" "percentage (for example 90%) it will be computed over layer height." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2065 +#: src/libslic3r/PrintConfig.cpp:2081 msgid "" "Speed for printing top solid layers (it only applies to the uppermost " "external layers and not to their internal solid layers). You may want to " @@ -6899,43 +7404,43 @@ msgid "" "for auto." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2080 +#: src/libslic3r/PrintConfig.cpp:2096 msgid "Number of solid layers to generate on top surfaces." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2081 +#: src/libslic3r/PrintConfig.cpp:2097 msgid "Top solid layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2087 +#: src/libslic3r/PrintConfig.cpp:2103 msgid "Speed for travel moves (jumps between distant extrusion points)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2095 +#: src/libslic3r/PrintConfig.cpp:2111 msgid "Use firmware retraction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2096 +#: src/libslic3r/PrintConfig.cpp:2112 msgid "" "This experimental setting uses G10 and G11 commands to have the firmware " "handle the retraction. This is only supported in recent Marlin." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2102 +#: src/libslic3r/PrintConfig.cpp:2118 msgid "Use relative E distances" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2103 +#: src/libslic3r/PrintConfig.cpp:2119 msgid "" "If your firmware requires relative E values, check this, otherwise leave it " "unchecked. Most firmwares use absolute values." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2109 +#: src/libslic3r/PrintConfig.cpp:2125 msgid "Use volumetric E" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2110 +#: src/libslic3r/PrintConfig.cpp:2126 msgid "" "This experimental setting uses outputs the E values in cubic millimeters " "instead of linear millimeters. If your firmware doesn't already know " @@ -6945,127 +7450,127 @@ msgid "" "only supported in recent Marlin." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2120 +#: src/libslic3r/PrintConfig.cpp:2136 msgid "Enable variable layer height feature" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2121 +#: src/libslic3r/PrintConfig.cpp:2137 msgid "" "Some printers or printer setups may have difficulties printing with a " "variable layer height. Enabled by default." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2127 +#: src/libslic3r/PrintConfig.cpp:2143 msgid "Wipe while retracting" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2128 +#: src/libslic3r/PrintConfig.cpp:2144 msgid "" "This flag will move the nozzle while retracting to minimize the possible " "blob on leaky extruders." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2135 +#: src/libslic3r/PrintConfig.cpp:2151 msgid "" "Multi material printers may need to prime or purge extruders on tool " "changes. Extrude the excess material into the wipe tower." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2141 +#: src/libslic3r/PrintConfig.cpp:2157 msgid "Purging volumes - load/unload volumes" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2142 +#: src/libslic3r/PrintConfig.cpp:2158 msgid "" "This vector saves required volumes to change from/to each tool used on the " "wipe tower. These values are used to simplify creation of the full purging " "volumes below." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2148 +#: src/libslic3r/PrintConfig.cpp:2164 msgid "Purging volumes - matrix" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2149 +#: src/libslic3r/PrintConfig.cpp:2165 msgid "" "This matrix describes volumes (in cubic milimetres) required to purge the " "new filament on the wipe tower for any given pair of tools." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2158 +#: src/libslic3r/PrintConfig.cpp:2174 msgid "Position X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2159 +#: src/libslic3r/PrintConfig.cpp:2175 msgid "X coordinate of the left front corner of a wipe tower" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2165 +#: src/libslic3r/PrintConfig.cpp:2181 msgid "Position Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2166 +#: src/libslic3r/PrintConfig.cpp:2182 msgid "Y coordinate of the left front corner of a wipe tower" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2173 +#: src/libslic3r/PrintConfig.cpp:2189 msgid "Width of a wipe tower" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2179 +#: src/libslic3r/PrintConfig.cpp:2195 msgid "Wipe tower rotation angle" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2180 +#: src/libslic3r/PrintConfig.cpp:2196 msgid "Wipe tower rotation angle with respect to x-axis." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2187 +#: src/libslic3r/PrintConfig.cpp:2203 msgid "Wipe into this object's infill" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2188 +#: src/libslic3r/PrintConfig.cpp:2204 msgid "" "Purging after toolchange will done inside this object's infills. This lowers " "the amount of waste but may result in longer print time due to additional " "travel moves." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2195 +#: src/libslic3r/PrintConfig.cpp:2211 msgid "Wipe into this object" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2196 +#: src/libslic3r/PrintConfig.cpp:2212 msgid "" "Object will be used to purge the nozzle after a toolchange to save material " "that would otherwise end up in the wipe tower and decrease print time. " "Colours of the objects will be mixed as a result." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2202 +#: src/libslic3r/PrintConfig.cpp:2218 msgid "Maximal bridging distance" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2203 +#: src/libslic3r/PrintConfig.cpp:2219 msgid "Maximal distance between supports on sparse infill sections." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2209 +#: src/libslic3r/PrintConfig.cpp:2225 msgid "XY Size Compensation" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2211 +#: src/libslic3r/PrintConfig.cpp:2227 msgid "" "The object will be grown/shrunk in the XY plane by the configured value " "(negative = inwards, positive = outwards). This might be useful for fine-" "tuning hole sizes." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2219 +#: src/libslic3r/PrintConfig.cpp:2235 msgid "Z offset" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2220 +#: src/libslic3r/PrintConfig.cpp:2236 msgid "" "This value will be added (or subtracted) from all the Z coordinates in the " "output G-code. It is used to compensate for bad Z endstop position: for " @@ -7073,308 +7578,345 @@ msgid "" "print bed, set this to -0.3 (or fix your endstop)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2237 +#: src/libslic3r/PrintConfig.cpp:2294 msgid "Display width" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2238 +#: src/libslic3r/PrintConfig.cpp:2295 msgid "Width of the display" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2243 +#: src/libslic3r/PrintConfig.cpp:2300 msgid "Display height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2244 +#: src/libslic3r/PrintConfig.cpp:2301 msgid "Height of the display" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2249 +#: src/libslic3r/PrintConfig.cpp:2306 msgid "Number of pixels in" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2251 +#: src/libslic3r/PrintConfig.cpp:2308 msgid "Number of pixels in X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2257 +#: src/libslic3r/PrintConfig.cpp:2314 msgid "Number of pixels in Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2262 +#: src/libslic3r/PrintConfig.cpp:2319 +msgid "Display horizontal mirroring" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2320 +msgid "Mirror horizontally" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2321 +msgid "Enable horizontal mirroring of output images" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2326 +msgid "Display vertical mirroring" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2327 +msgid "Mirror vertically" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2328 +msgid "Enable vertical mirroring of output images" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2333 msgid "Display orientation" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2263 +#: src/libslic3r/PrintConfig.cpp:2334 msgid "" "Set the actual LCD display orientation inside the SLA printer. Portrait mode " "will flip the meaning of display width and height parameters and the output " "images will be rotated by 90 degrees." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2269 +#: src/libslic3r/PrintConfig.cpp:2340 msgid "Landscape" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2270 +#: src/libslic3r/PrintConfig.cpp:2341 msgid "Portrait" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2275 +#: src/libslic3r/PrintConfig.cpp:2346 msgid "Fast" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2276 +#: src/libslic3r/PrintConfig.cpp:2347 msgid "Fast tilt" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2277 +#: src/libslic3r/PrintConfig.cpp:2348 msgid "Time of the fast tilt" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2284 +#: src/libslic3r/PrintConfig.cpp:2355 msgid "Slow" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2285 +#: src/libslic3r/PrintConfig.cpp:2356 msgid "Slow tilt" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2286 +#: src/libslic3r/PrintConfig.cpp:2357 msgid "Time of the slow tilt" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2293 +#: src/libslic3r/PrintConfig.cpp:2364 msgid "Area fill" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2294 +#: src/libslic3r/PrintConfig.cpp:2365 msgid "" "The percentage of the bed area. \n" "If the print area exceeds the specified value, \n" "then a slow tilt will be used, otherwise - a fast tilt" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2301 src/libslic3r/PrintConfig.cpp:2302 -#: src/libslic3r/PrintConfig.cpp:2303 +#: src/libslic3r/PrintConfig.cpp:2372 src/libslic3r/PrintConfig.cpp:2373 +#: src/libslic3r/PrintConfig.cpp:2374 msgid "Printer scaling correction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2309 src/libslic3r/PrintConfig.cpp:2310 +#: src/libslic3r/PrintConfig.cpp:2380 src/libslic3r/PrintConfig.cpp:2381 msgid "Printer absolute correction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2311 +#: src/libslic3r/PrintConfig.cpp:2382 msgid "" "Will inflate or deflate the sliced 2D polygons according to the sign of the " "correction." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2317 src/libslic3r/PrintConfig.cpp:2318 +#: src/libslic3r/PrintConfig.cpp:2388 src/libslic3r/PrintConfig.cpp:2389 msgid "Printer gamma correction" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2319 +#: src/libslic3r/PrintConfig.cpp:2390 msgid "" "This will apply a gamma correction to the rasterized 2D polygons. A gamma " "value of zero means thresholding with the threshold in the middle. This " "behaviour eliminates antialiasing without losing holes in polygons." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2330 src/libslic3r/PrintConfig.cpp:2331 +#: src/libslic3r/PrintConfig.cpp:2401 src/libslic3r/PrintConfig.cpp:2402 msgid "Initial layer height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2337 +#: src/libslic3r/PrintConfig.cpp:2408 msgid "Faded layers" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2338 +#: src/libslic3r/PrintConfig.cpp:2409 msgid "" "Number of the layers needed for the exposure time fade from initial exposure " "time to the exposure time" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2345 src/libslic3r/PrintConfig.cpp:2346 +#: src/libslic3r/PrintConfig.cpp:2416 src/libslic3r/PrintConfig.cpp:2417 msgid "Exposure time" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2352 src/libslic3r/PrintConfig.cpp:2353 +#: src/libslic3r/PrintConfig.cpp:2423 src/libslic3r/PrintConfig.cpp:2424 msgid "Initial exposure time" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2359 src/libslic3r/PrintConfig.cpp:2360 +#: src/libslic3r/PrintConfig.cpp:2430 src/libslic3r/PrintConfig.cpp:2431 msgid "Correction for expansion" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2366 +#: src/libslic3r/PrintConfig.cpp:2437 msgid "SLA print material notes" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2367 +#: src/libslic3r/PrintConfig.cpp:2438 msgid "You can put your notes regarding the SLA print material here." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2375 src/libslic3r/PrintConfig.cpp:2386 +#: src/libslic3r/PrintConfig.cpp:2446 src/libslic3r/PrintConfig.cpp:2457 msgid "Default SLA material profile" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2397 +#: src/libslic3r/PrintConfig.cpp:2468 msgid "Generate supports" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2399 +#: src/libslic3r/PrintConfig.cpp:2470 msgid "Generate supports for the models" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2404 +#: src/libslic3r/PrintConfig.cpp:2475 msgid "Support head front diameter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2406 +#: src/libslic3r/PrintConfig.cpp:2477 msgid "Diameter of the pointing side of the head" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2413 +#: src/libslic3r/PrintConfig.cpp:2484 msgid "Support head penetration" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2415 +#: src/libslic3r/PrintConfig.cpp:2486 msgid "How much the pinhead has to penetrate the model surface" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2422 +#: src/libslic3r/PrintConfig.cpp:2493 msgid "Support head width" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2424 +#: src/libslic3r/PrintConfig.cpp:2495 msgid "Width from the back sphere center to the front sphere center" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2432 +#: src/libslic3r/PrintConfig.cpp:2503 msgid "Support pillar diameter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2434 +#: src/libslic3r/PrintConfig.cpp:2505 msgid "Diameter in mm of the support pillars" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2442 +#: src/libslic3r/PrintConfig.cpp:2513 msgid "Support pillar connection mode" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2443 +#: src/libslic3r/PrintConfig.cpp:2514 msgid "" "Controls the bridge type between two neighboring pillars. Can be zig-zag, " "cross (double zig-zag) or dynamic which will automatically switch between " "the first two depending on the distance of the two pillars." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2451 +#: src/libslic3r/PrintConfig.cpp:2522 msgid "Zig-Zag" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2452 +#: src/libslic3r/PrintConfig.cpp:2523 msgid "Cross" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2453 +#: src/libslic3r/PrintConfig.cpp:2524 msgid "Dynamic" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2465 +#: src/libslic3r/PrintConfig.cpp:2536 msgid "Pillar widening factor" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2467 +#: src/libslic3r/PrintConfig.cpp:2538 msgid "" "Merging bridges or pillars into another pillars can increase the radius. " "Zero means no increase, one means full increase." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2476 +#: src/libslic3r/PrintConfig.cpp:2547 msgid "Support base diameter" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2478 +#: src/libslic3r/PrintConfig.cpp:2549 msgid "Diameter in mm of the pillar base" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2486 +#: src/libslic3r/PrintConfig.cpp:2557 msgid "Support base height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2488 +#: src/libslic3r/PrintConfig.cpp:2559 msgid "The height of the pillar base cone" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2495 +#: src/libslic3r/PrintConfig.cpp:2566 +msgid "Support base safety distance" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2569 +msgid "" +"The minimum distance of the pillar base from the model in mm. Makes sense in " +"zero elevation mode where a gap according to this parameter is inserted " +"between the model and the pad." +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2579 msgid "Critical angle" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2497 +#: src/libslic3r/PrintConfig.cpp:2581 msgid "The default angle for connecting support sticks and junctions." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2505 +#: src/libslic3r/PrintConfig.cpp:2589 msgid "Max bridge length" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2507 +#: src/libslic3r/PrintConfig.cpp:2591 msgid "The max length of a bridge" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2514 +#: src/libslic3r/PrintConfig.cpp:2598 msgid "Max pillar linking distance" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2516 +#: src/libslic3r/PrintConfig.cpp:2600 msgid "" "The max distance of two pillars to get linked with each other. A zero value " "will prohibit pillar cascading." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2524 +#: src/libslic3r/PrintConfig.cpp:2608 msgid "Object elevation" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2526 -msgid "How much the supports should lift up the supported object." +#: src/libslic3r/PrintConfig.cpp:2610 +msgid "" +"How much the supports should lift up the supported object. If this value is " +"zero, the bottom of the model geometry will be considered as part of the pad." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2536 +#: src/libslic3r/PrintConfig.cpp:2622 msgid "This is a relative measure of support points density." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2542 +#: src/libslic3r/PrintConfig.cpp:2628 msgid "Minimal distance of the support points" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2544 +#: src/libslic3r/PrintConfig.cpp:2630 msgid "No support points will be placed closer than this threshold." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2550 +#: src/libslic3r/PrintConfig.cpp:2636 msgid "Use pad" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2552 +#: src/libslic3r/PrintConfig.cpp:2638 msgid "Add a pad underneath the supported model" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2557 +#: src/libslic3r/PrintConfig.cpp:2643 msgid "Pad wall thickness" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2559 +#: src/libslic3r/PrintConfig.cpp:2645 msgid "The thickness of the pad and its optional cavity walls." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2567 +#: src/libslic3r/PrintConfig.cpp:2653 msgid "Pad wall height" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2568 +#: src/libslic3r/PrintConfig.cpp:2654 msgid "" "Defines the pad cavity depth. Set to zero to disable the cavity. Be careful " "when enabling this feature, as some resins may produce an extreme suction " @@ -7382,279 +7924,317 @@ msgid "" "difficult." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2581 +#: src/libslic3r/PrintConfig.cpp:2667 msgid "Max merge distance" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2583 +#: src/libslic3r/PrintConfig.cpp:2669 msgid "" "Some objects can get along with a few smaller pads instead of a single big " "one. This parameter defines how far the center of two smaller pads should " "be. If theyare closer, they will get merged into one pad." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2594 +#: src/libslic3r/PrintConfig.cpp:2680 msgid "Pad edge radius" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2603 +#: src/libslic3r/PrintConfig.cpp:2689 msgid "Pad wall slope" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2605 +#: src/libslic3r/PrintConfig.cpp:2691 msgid "" "The slope of the pad wall relative to the bed plane. 90 degrees means " "straight walls." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2967 +#: src/libslic3r/PrintConfig.cpp:2700 +msgid "Pad object gap" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2702 +msgid "" +"The gap between the object bottom and the generated pad in zero elevation " +"mode." +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2711 +msgid "Pad object connector stride" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2713 +msgid "" +"Distance between two connector sticks between the object pad and the " +"generated pad." +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2721 +msgid "Pad object connector width" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2723 +msgid "" +"The width of the connectors sticks which connect the object pad and the " +"generated pad." +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2731 +msgid "Pad object connector penetration" +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:2734 +msgid "How much should the tiny connectors penetrate into the model body." +msgstr "" + +#: src/libslic3r/PrintConfig.cpp:3094 msgid "Export OBJ" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2968 +#: src/libslic3r/PrintConfig.cpp:3095 msgid "Export the model(s) as OBJ." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2979 +#: src/libslic3r/PrintConfig.cpp:3106 msgid "Export SLA" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2980 +#: src/libslic3r/PrintConfig.cpp:3107 msgid "Slice the model and export SLA printing layers as PNG." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2985 +#: src/libslic3r/PrintConfig.cpp:3112 msgid "Export 3MF" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2986 +#: src/libslic3r/PrintConfig.cpp:3113 msgid "Export the model(s) as 3MF." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2990 +#: src/libslic3r/PrintConfig.cpp:3117 msgid "Export AMF" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2991 +#: src/libslic3r/PrintConfig.cpp:3118 msgid "Export the model(s) as AMF." msgstr "" -#: src/libslic3r/PrintConfig.cpp:2995 +#: src/libslic3r/PrintConfig.cpp:3122 msgid "Export STL" msgstr "" -#: src/libslic3r/PrintConfig.cpp:2996 +#: src/libslic3r/PrintConfig.cpp:3123 msgid "Export the model(s) as STL." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3001 +#: src/libslic3r/PrintConfig.cpp:3128 msgid "Slice the model and export toolpaths as G-code." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3006 +#: src/libslic3r/PrintConfig.cpp:3133 msgid "Slice" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3007 +#: src/libslic3r/PrintConfig.cpp:3134 msgid "" "Slice the model as FFF or SLA based on the printer_technology configuration " "value." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3012 +#: src/libslic3r/PrintConfig.cpp:3139 msgid "Help" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3013 +#: src/libslic3r/PrintConfig.cpp:3140 msgid "Show this help." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3018 +#: src/libslic3r/PrintConfig.cpp:3145 msgid "Help (FFF options)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3019 +#: src/libslic3r/PrintConfig.cpp:3146 msgid "Show the full list of print/G-code configuration options." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3023 +#: src/libslic3r/PrintConfig.cpp:3150 msgid "Help (SLA options)" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3024 +#: src/libslic3r/PrintConfig.cpp:3151 msgid "Show the full list of SLA print configuration options." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3028 +#: src/libslic3r/PrintConfig.cpp:3155 msgid "Output Model Info" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3029 +#: src/libslic3r/PrintConfig.cpp:3156 msgid "Write information about the model to the console." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3033 +#: src/libslic3r/PrintConfig.cpp:3160 msgid "Save config file" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3034 +#: src/libslic3r/PrintConfig.cpp:3161 msgid "Save configuration to the specified file." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3044 +#: src/libslic3r/PrintConfig.cpp:3171 msgid "Align XY" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3045 +#: src/libslic3r/PrintConfig.cpp:3172 msgid "Align the model to the given point." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3050 +#: src/libslic3r/PrintConfig.cpp:3177 msgid "Cut model at the given Z." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3071 +#: src/libslic3r/PrintConfig.cpp:3198 msgid "Center" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3072 +#: src/libslic3r/PrintConfig.cpp:3199 msgid "Center the print around the given center." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3076 +#: src/libslic3r/PrintConfig.cpp:3203 msgid "Don't arrange" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3077 +#: src/libslic3r/PrintConfig.cpp:3204 msgid "" "Do not rearrange the given models before merging and keep their original XY " "coordinates." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3080 +#: src/libslic3r/PrintConfig.cpp:3207 msgid "Duplicate" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3081 +#: src/libslic3r/PrintConfig.cpp:3208 msgid "Multiply copies by this factor." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3085 +#: src/libslic3r/PrintConfig.cpp:3212 msgid "Duplicate by grid" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3086 +#: src/libslic3r/PrintConfig.cpp:3213 msgid "Multiply copies by creating a grid." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3089 +#: src/libslic3r/PrintConfig.cpp:3216 msgid "Merge" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3090 +#: src/libslic3r/PrintConfig.cpp:3217 msgid "" "Arrange the supplied models in a plate and merge them in a single model in " "order to perform actions once." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3095 +#: src/libslic3r/PrintConfig.cpp:3222 msgid "" "Try to repair any non-manifold meshes (this option is implicitly added " "whenever we need to slice the model to perform the requested action)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3099 +#: src/libslic3r/PrintConfig.cpp:3226 msgid "Rotation angle around the Z axis in degrees." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3103 +#: src/libslic3r/PrintConfig.cpp:3230 msgid "Rotate around X" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3104 +#: src/libslic3r/PrintConfig.cpp:3231 msgid "Rotation angle around the X axis in degrees." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3108 +#: src/libslic3r/PrintConfig.cpp:3235 msgid "Rotate around Y" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3109 +#: src/libslic3r/PrintConfig.cpp:3236 msgid "Rotation angle around the Y axis in degrees." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3114 +#: src/libslic3r/PrintConfig.cpp:3241 msgid "Scaling factor or percentage." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3119 +#: src/libslic3r/PrintConfig.cpp:3246 msgid "" "Detect unconnected parts in the given model(s) and split them into separate " "objects." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3122 +#: src/libslic3r/PrintConfig.cpp:3249 msgid "Scale to Fit" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3123 +#: src/libslic3r/PrintConfig.cpp:3250 msgid "Scale to fit the given volume." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3132 +#: src/libslic3r/PrintConfig.cpp:3259 msgid "Ignore non-existent config files" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3133 +#: src/libslic3r/PrintConfig.cpp:3260 msgid "Do not fail if a file supplied to --load does not exist." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3136 +#: src/libslic3r/PrintConfig.cpp:3263 msgid "Load config file" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3137 +#: src/libslic3r/PrintConfig.cpp:3264 msgid "" "Load configuration from the specified file. It can be used more than once to " "load options from multiple files." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3140 +#: src/libslic3r/PrintConfig.cpp:3267 msgid "Output File" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3141 +#: src/libslic3r/PrintConfig.cpp:3268 msgid "" "The file where the output will be written (if not specified, it will be " "based on the input file)." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3151 +#: src/libslic3r/PrintConfig.cpp:3278 msgid "Data directory" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3152 +#: src/libslic3r/PrintConfig.cpp:3279 msgid "" "Load and store settings at the given directory. This is useful for " "maintaining different profiles or including configurations from a network " "storage." msgstr "" -#: src/libslic3r/PrintConfig.cpp:3155 +#: src/libslic3r/PrintConfig.cpp:3282 msgid "Logging level" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3156 +#: src/libslic3r/PrintConfig.cpp:3283 msgid "" "Messages with severity lower or eqal to the loglevel will be printed out. 0:" "trace, 1:debug, 2:info, 3:warning, 4:error, 5:fatal" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3161 +#: src/libslic3r/PrintConfig.cpp:3288 msgid "Render with a software renderer" msgstr "" -#: src/libslic3r/PrintConfig.cpp:3162 +#: src/libslic3r/PrintConfig.cpp:3289 msgid "" "Render with a software renderer. The bundled MESA software renderer is " "loaded instead of the default OpenGL driver." @@ -7696,21 +8276,21 @@ msgstr "" msgid "Volumetric flow rate (mm3/s)" msgstr "" -#: src/libslic3r/GCode/PreviewData.cpp:491 +#: src/libslic3r/GCode/PreviewData.cpp:493 msgid "Default print color" msgstr "" -#: src/libslic3r/GCode/PreviewData.cpp:495 +#: src/libslic3r/GCode/PreviewData.cpp:500 #, possible-c-format msgid "up to %.2f mm" msgstr "" -#: src/libslic3r/GCode/PreviewData.cpp:499 +#: src/libslic3r/GCode/PreviewData.cpp:504 #, possible-c-format msgid "above %.2f mm" msgstr "" -#: src/libslic3r/GCode/PreviewData.cpp:504 +#: src/libslic3r/GCode/PreviewData.cpp:509 #, possible-c-format msgid "%.2f - %.2f mm" msgstr "" diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index c8cf9b42d8..8ec0e1d8ed 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in @@ -59,8 +60,11 @@ PrinterTechnology get_printer_technology(const DynamicConfig &config) int CLI::run(int argc, char **argv) { - if (! this->setup(argc, argv)) - return 1; + // Switch boost::filesystem to utf8. + boost::nowide::nowide_filesystem(); + + if (! this->setup(argc, argv)) + return 1; m_extra_config.apply(m_config, true); m_extra_config.normalize(); @@ -499,6 +503,7 @@ int CLI::run(int argc, char **argv) bool CLI::setup(int argc, char **argv) { { + Slic3r::set_logging_level(1); const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL"); if (loglevel != nullptr) { if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0) diff --git a/src/libigl/igl/ray_box_intersect.cpp b/src/libigl/igl/ray_box_intersect.cpp index 8c6346d86d..088273f255 100644 --- a/src/libigl/igl/ray_box_intersect.cpp +++ b/src/libigl/igl/ray_box_intersect.cpp @@ -1,12 +1,12 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "ray_box_intersect.h" -#include +#include template < typename Derivedsource, @@ -27,7 +27,7 @@ IGL_INLINE bool igl::ray_box_intersect( const Eigen::Vector3f& rayo, const Eigen::Vector3f& rayd, const Eigen::Vector3f& bmin, - const Eigen::Vector3f& bmax, + const Eigen::Vector3f& bmax, float & tnear, float & tfar )->bool @@ -35,12 +35,12 @@ IGL_INLINE bool igl::ray_box_intersect( Eigen::Vector3f bnear; Eigen::Vector3f bfar; // Checks for intersection testing on each direction coordinate - // Computes + // Computes float t1, t2; tnear = -1e+6f, tfar = 1e+6f; //, tCube; bool intersectFlag = true; for (int i = 0; i < 3; ++i) { - // std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl; + // std::cout << "coordinate " << i << ": bmin " << bmin(i) << ", bmax " << bmax(i) << std::endl; assert(bmin(i) <= bmax(i)); if (::fabs(rayd(i)) < 1e-6) { // Ray parallel to axis i-th if (rayo(i) < bmin(i) || rayo(i) > bmax(i)) { @@ -59,12 +59,12 @@ IGL_INLINE bool igl::ray_box_intersect( } // std::cout << " bnear " << bnear(i) << ", bfar " << bfar(i) << std::endl; // Finds the distance parameters t1 and t2 of the two ray-box intersections: - // t1 must be the closest to the ray origin rayo. + // t1 must be the closest to the ray origin rayo. t1 = (bnear(i) - rayo(i)) / rayd(i); t2 = (bfar(i) - rayo(i)) / rayd(i); if (t1 > t2) { std::swap(t1,t2); - } + } // The two intersection values are used to saturate tnear and tfar if (t1 > tnear) { tnear = t1; @@ -72,7 +72,7 @@ IGL_INLINE bool igl::ray_box_intersect( if (t2 < tfar) { tfar = t2; } - // std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar + // std::cout << " t1 " << t1 << ", t2 " << t2 << ", tnear " << tnear << ", tfar " << tfar // << " tnear > tfar? " << (tnear > tfar) << ", tfar < 0? " << (tfar < 0) << std::endl; if(tnear > tfar) { intersectFlag = false; @@ -101,11 +101,11 @@ IGL_INLINE bool igl::ray_box_intersect( // This should be precomputed and provided as input typedef Matrix RowVector3S; const RowVector3S inv_dir( 1./dir(0),1./dir(1),1./dir(2)); - const std::vector sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0}; + const std::array sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0}; // http://people.csail.mit.edu/amy/papers/box-jgt.pdf // "An Efficient and Robust Ray–Box Intersection Algorithm" Scalar tymin, tymax, tzmin, tzmax; - std::vector bounds = {box.min(),box.max()}; + std::array bounds = {box.min(),box.max()}; tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0); tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0); tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1); @@ -146,4 +146,4 @@ IGL_INLINE bool igl::ray_box_intersect( #ifdef IGL_STATIC_LIBRARY template bool igl::ray_box_intersect, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::AlignedBox const&, double const&, double const&, double&, double&); -#endif \ No newline at end of file +#endif diff --git a/src/libigl/igl/ray_mesh_intersect.cpp b/src/libigl/igl/ray_mesh_intersect.cpp index 512a35c461..18060fbadb 100644 --- a/src/libigl/igl/ray_mesh_intersect.cpp +++ b/src/libigl/igl/ray_mesh_intersect.cpp @@ -29,7 +29,9 @@ IGL_INLINE bool igl::ray_mesh_intersect( // Should be but can't be const Vector3d s_d = s.template cast(); Vector3d dir_d = dir.template cast(); - hits.clear(); + hits.clear(); + hits.reserve(F.rows()); + // loop over all triangles for(int f = 0;fvalues[i] = rhs_vec->values[i]; modified = true; } - return false; + return modified; } private: diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index e71b935dbb..6069677a1b 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -76,10 +76,14 @@ float Flow::spacing() const return this->width + BRIDGE_EXTRA_SPACING; // rectangle with semicircles at the ends float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI); - return this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing); + float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing); #else - return float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING) : (this->width - this->height * (1. - 0.25 * PI))); + float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING) : (this->width - this->height * (1. - 0.25 * PI))); #endif +// assert(res > 0.f); + if (res <= 0.f) + throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?"); + return res; } // This method returns the centerline spacing between an extrusion using this @@ -89,20 +93,26 @@ float Flow::spacing(const Flow &other) const { assert(this->height == other.height); assert(this->bridge == other.bridge); - return float(this->bridge ? + float res = float(this->bridge ? 0.5 * this->width + 0.5 * other.width + BRIDGE_EXTRA_SPACING : 0.5 * this->spacing() + 0.5 * other.spacing()); +// assert(res > 0.f); + if (res <= 0.f) + throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?"); + return res; } // This method returns extrusion volume per head move unit. double Flow::mm3_per_mm() const { - double res = this->bridge ? + float res = this->bridge ? // Area of a circle with dmr of this->width. (this->width * this->width) * 0.25 * PI : // Rectangle with semicircles at the ends. ~ h (w - 0.215 h) this->height * (this->width - this->height * (1. - 0.25 * PI)); - assert(res > 0.); + //assert(res > 0.); + if (res <= 0.) + throw std::runtime_error("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?"); return res; } diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 0cc0a9d584..fd1d11c2fb 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -71,6 +71,7 @@ const char* V2_ATTR = "v2"; const char* V3_ATTR = "v3"; const char* OBJECTID_ATTR = "objectid"; const char* TRANSFORM_ATTR = "transform"; +const char* PRINTABLE_ATTR = "printable"; const char* KEY_ATTR = "key"; const char* VALUE_ATTR = "value"; @@ -131,6 +132,12 @@ int get_attribute_value_int(const char** attributes, unsigned int attributes_siz return (text != nullptr) ? ::atoi(text) : 0; } +bool get_attribute_value_bool(const char** attributes, unsigned int attributes_size, const char* attribute_key) +{ + const char* text = get_attribute_value_charptr(attributes, attributes_size, attribute_key); + return (text != nullptr) ? (bool)::atoi(text) : true; +} + Slic3r::Transform3d get_transform_from_string(const std::string& mat_str) { if (mat_str.empty()) @@ -428,7 +435,7 @@ namespace Slic3r { bool _handle_start_metadata(const char** attributes, unsigned int num_attributes); bool _handle_end_metadata(); - bool _create_object_instance(int object_id, const Transform3d& transform, unsigned int recur_counter); + bool _create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter); void _apply_transform(ModelInstance& instance, const Transform3d& transform); @@ -1367,8 +1374,9 @@ namespace Slic3r { int object_id = get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR); Transform3d transform = get_transform_from_string(get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR)); + int printable = get_attribute_value_bool(attributes, num_attributes, PRINTABLE_ATTR); - return _create_object_instance(object_id, transform, 1); + return _create_object_instance(object_id, transform, printable, 1); } bool _3MF_Importer::_handle_end_item() @@ -1396,7 +1404,7 @@ namespace Slic3r { return true; } - bool _3MF_Importer::_create_object_instance(int object_id, const Transform3d& transform, unsigned int recur_counter) + bool _3MF_Importer::_create_object_instance(int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter) { static const unsigned int MAX_RECURSIONS = 10; @@ -1432,6 +1440,7 @@ namespace Slic3r { add_error("Unable to add object instance"); return false; } + instance->printable = printable; m_instances.emplace_back(instance, transform); } @@ -1441,7 +1450,7 @@ namespace Slic3r { // recursively process nested components for (const Component& component : it->second) { - if (!_create_object_instance(component.object_id, transform * component.transform, recur_counter + 1)) + if (!_create_object_instance(component.object_id, transform * component.transform, printable, recur_counter + 1)) return false; } } @@ -1655,10 +1664,12 @@ namespace Slic3r { { unsigned int id; Transform3d transform; + bool printable; - BuildItem(unsigned int id, const Transform3d& transform) + BuildItem(unsigned int id, const Transform3d& transform, const bool printable) : id(id) , transform(transform) + , printable(printable) { } }; @@ -1951,7 +1962,7 @@ namespace Slic3r { Transform3d t = instance->get_matrix(); // instance_id is just a 1 indexed index in build_items. assert(instance_id == build_items.size() + 1); - build_items.emplace_back(instance_id, t); + build_items.emplace_back(instance_id, t, instance->printable); stream << " \n"; @@ -2059,7 +2070,7 @@ namespace Slic3r { stream << " "; } } - stream << "\" />\n"; + stream << "\" printable =\"" << item.printable << "\" />\n"; } stream << " \n"; diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 4370a2e1c0..08820f2ea1 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -137,6 +137,7 @@ struct AMFParserContext NODE_TYPE_MIRRORX, // amf/constellation/instance/mirrorx NODE_TYPE_MIRRORY, // amf/constellation/instance/mirrory NODE_TYPE_MIRRORZ, // amf/constellation/instance/mirrorz + NODE_TYPE_PRINTABLE, // amf/constellation/instance/mirrorz NODE_TYPE_METADATA, // anywhere under amf/*/metadata }; @@ -145,7 +146,8 @@ struct AMFParserContext : deltax_set(false), deltay_set(false), deltaz_set(false) , rx_set(false), ry_set(false), rz_set(false) , scalex_set(false), scaley_set(false), scalez_set(false) - , mirrorx_set(false), mirrory_set(false), mirrorz_set(false) {} + , mirrorx_set(false), mirrory_set(false), mirrorz_set(false) + , printable(true) {} // Shift in the X axis. float deltax; bool deltax_set; @@ -178,6 +180,8 @@ struct AMFParserContext bool mirrory_set; float mirrorz; bool mirrorz_set; + // printable property + bool printable; bool anything_set() const { return deltax_set || deltay_set || deltaz_set || rx_set || ry_set || rz_set || @@ -321,6 +325,8 @@ void AMFParserContext::startElement(const char *name, const char **atts) node_type_new = NODE_TYPE_MIRRORY; else if (strcmp(name, "mirrorz") == 0) node_type_new = NODE_TYPE_MIRRORZ; + else if (strcmp(name, "printable") == 0) + node_type_new = NODE_TYPE_PRINTABLE; } else if (m_path[2] == NODE_TYPE_LAYER_CONFIG && strcmp(name, "range") == 0) { assert(m_object); @@ -397,7 +403,8 @@ void AMFParserContext::characters(const XML_Char *s, int len) m_path.back() == NODE_TYPE_SCALE || m_path.back() == NODE_TYPE_MIRRORX || m_path.back() == NODE_TYPE_MIRRORY || - m_path.back() == NODE_TYPE_MIRRORZ) + m_path.back() == NODE_TYPE_MIRRORZ || + m_path.back() == NODE_TYPE_PRINTABLE) m_value[0].append(s, len); break; case 6: @@ -507,6 +514,11 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->mirrorz_set = true; m_value[0].clear(); break; + case NODE_TYPE_PRINTABLE: + assert(m_instance); + m_instance->printable = bool(atoi(m_value[0].c_str())); + m_value[0].clear(); + break; // Object vertices: case NODE_TYPE_VERTEX: @@ -685,6 +697,7 @@ void AMFParserContext::endDocument() mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0)); mi->set_mirror(Vec3d(instance.mirrorx_set ? (double)instance.mirrorx : 1.0, instance.mirrory_set ? (double)instance.mirrory : 1.0, instance.mirrorz_set ? (double)instance.mirrorz : 1.0)); + mi->printable = instance.printable; } } } @@ -1037,6 +1050,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) " %lf\n" " %lf\n" " %lf\n" + " %d\n" " \n", object_id, instance->get_offset(X), @@ -1050,7 +1064,8 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) instance->get_scaling_factor(Z), instance->get_mirror(X), instance->get_mirror(Y), - instance->get_mirror(Z)); + instance->get_mirror(Z), + instance->printable); //FIXME missing instance->scaling_factor instances.append(buf); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index bc37300269..b691203c97 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1,4 +1,5 @@ #include "libslic3r.h" +#include "I18N.hpp" #include "GCode.hpp" #include "ExtrusionEntity.hpp" #include "EdgeGrid.hpp" @@ -36,6 +37,11 @@ namespace Slic3r { +//! macro used to mark string used at localization, +//! return same string +#define L(s) (s) +#define _(s) Slic3r::I18N::translate(s) + // Only add a newline in case the current G-code does not end with a newline. static inline void check_add_eol(std::string &gcode) { @@ -405,7 +411,8 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, assert(m_layer_idx >= 0 && size_t(m_layer_idx) <= m_tool_changes.size()); if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) { if (m_layer_idx < (int)m_tool_changes.size()) { - assert(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()); + if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size())) + throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer."); gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id); } m_brim_done = true; @@ -435,6 +442,7 @@ std::vector GCode::collect_layers_to_print(const PrintObjec // Pair the object layers with the support layers by z. size_t idx_object_layer = 0; size_t idx_support_layer = 0; + const LayerToPrint* last_extrusion_layer = nullptr; while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { LayerToPrint layer_to_print; layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer ++] : nullptr; @@ -448,7 +456,29 @@ std::vector GCode::collect_layers_to_print(const PrintObjec -- idx_object_layer; } } + layers_to_print.emplace_back(layer_to_print); + + // In case there are extrusions on this layer, check there is a layer to lay it on. + if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) + || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions())) { + double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) + ? object.config().support_material_contact_distance + : 0.; + double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) + + layer_to_print.layer()->height + + std::max(0., support_contact_z); + // Negative support_contact_z is not taken into account, it can result in false positives in cases + // where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752) + + + if (layer_to_print.print_z() > maximal_print_z + EPSILON) + throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" + + _(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) + + std::to_string(layers_to_print.back().print_z())); + // Remember last layer with extrusions. + last_extrusion_layer = &layers_to_print.back(); + } } return layers_to_print; @@ -561,11 +591,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ } if (print->config().remaining_times.value) { - BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode"; + BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info(); m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f); m_normal_time_estimator.reset(); if (m_silent_time_estimator_enabled) { - BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode"; + BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info(); m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f); m_silent_time_estimator.reset(); } @@ -573,7 +603,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ // starts analyzer calculations if (m_enable_analyzer) { - BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data"; + BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info(); m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); }); m_analyzer.reset(); } @@ -748,7 +778,7 @@ void GCode::_do_export(Print &print, FILE *file) mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [](double v) { return v < 0.000001; }), mm3_per_mm.end()); if (! mm3_per_mm.empty()) { // In order to honor max_print_speed we need to find a target volumetric - // speed that we can use throughout the print. So we define this target + // speed that we can use throughout the print. So we define this target // volumetric speed as the volumetric speed produced by printing the // smallest cross-section at the maximum speed: any larger cross-section // will need slower feedrates. @@ -815,7 +845,7 @@ void GCode::_do_export(Print &print, FILE *file) _writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag); } - // Prepare the helper object for replacing placeholders in custom G-code and output filename. + // Prepare the helper object for replacing placeholders in custom G-code and output filename. m_placeholder_parser = print.placeholder_parser(); m_placeholder_parser.update_timestamp(); print.update_object_placeholders(m_placeholder_parser.config_writable(), ".gcode"); @@ -1138,9 +1168,9 @@ void GCode::_do_export(Print &print, FILE *file) print.m_print_statistics.clear(); print.m_print_statistics.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms(); print.m_print_statistics.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A"; - print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(); + print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(true); if (m_silent_time_estimator_enabled) - print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(); + print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(true); std::vector extruders = m_writer.extruders(); if (! extruders.empty()) { @@ -1820,7 +1850,8 @@ void GCode::process_layer( ", time estimator memory: " << format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) << ", analyzer memory: " << - format_memsize_MB(m_analyzer.memory_used()); + format_memsize_MB(m_analyzer.memory_used()) << + log_memory_info(); } void GCode::apply_print_config(const PrintConfig &print_config) @@ -2598,7 +2629,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm ); } - double F = speed * 60; // convert mm/sec to mm/min + double F = speed * 60; // convert mm/sec to mm/min // extrude arc or line if (m_enable_extrusion_role_markers) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 2d7b90442b..9280aa33a4 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -78,8 +78,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool zs.emplace_back(layer->print_z); for (auto layer : object->support_layers()) zs.emplace_back(layer->print_z); - if (! object->layers().empty()) - object_bottom_z = object->layers().front()->print_z - object->layers().front()->height; + + // Find first object layer that is not empty and save its print_z + for (const Layer* layer : object->layers()) + if (layer->has_extrusions()) { + object_bottom_z = layer->print_z - layer->height; + break; + } } this->initialize_layers(zs); } @@ -303,10 +308,11 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z)); // Find the 1st layer above lt_new. for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z - EPSILON; ++ j); - if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) { - m_layer_tools[j].has_wipe_tower = true; - } else { - LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); + if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) { + m_layer_tools[j].has_wipe_tower = true; + } else { + LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); + //LayerTools <_prev = m_layer_tools[j]; LayerTools <_next = m_layer_tools[j + 1]; assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty()); // FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now. diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp index 33dc9f4b7d..8a2e1266a8 100644 --- a/src/libslic3r/GCodeTimeEstimator.cpp +++ b/src/libslic3r/GCodeTimeEstimator.cpp @@ -694,22 +694,39 @@ namespace Slic3r { return m_color_times; } - std::vector GCodeTimeEstimator::get_color_times_dhms() const + std::vector GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const { std::vector ret; + float total_time = 0.0f; for (float t : m_color_times) { - ret.push_back(_get_time_dhms(t)); + std::string time = _get_time_dhms(t); + if (include_remaining) + { + time += " ("; + time += _get_time_dhms(m_time - total_time); + time += ")"; + } + total_time += t; + ret.push_back(time); } return ret; } - std::vector GCodeTimeEstimator::get_color_times_minutes() const + std::vector GCodeTimeEstimator::get_color_times_minutes(bool include_remaining) const { std::vector ret; + float total_time = 0.0f; for (float t : m_color_times) { - ret.push_back(_get_time_minutes(t)); + std::string time = _get_time_minutes(t); + if (include_remaining) + { + time += " ("; + time += _get_time_minutes(m_time - total_time); + time += ")"; + } + total_time += t; } return ret; } diff --git a/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp index 840d587784..8d794af1e4 100644 --- a/src/libslic3r/GCodeTimeEstimator.hpp +++ b/src/libslic3r/GCodeTimeEstimator.hpp @@ -346,14 +346,16 @@ namespace Slic3r { // Returns the estimated time, in minutes (integer) std::string get_time_minutes() const; - // Returns the estimated time, in seconds, for each color + // Returns the estimated time, in seconds, for each color std::vector get_color_times() const; // Returns the estimated time, in format DDd HHh MMm SSs, for each color - std::vector get_color_times_dhms() const; + // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" + std::vector get_color_times_dhms(bool include_remaining) const; // Returns the estimated time, in minutes (integer), for each color - std::vector get_color_times_minutes() const; + // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" + std::vector get_color_times_minutes(bool include_remaining) const; // Return an estimate of the memory consumed by the time estimator. size_t memory_used() const; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 858ae52b29..606af246f9 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -21,8 +21,6 @@ namespace Slic3r { -unsigned int Model::s_auto_extruder_id = 1; - Model& Model::assign_copy(const Model &rhs) { this->copy_id(rhs); @@ -99,8 +97,7 @@ Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *c result = load_stl(input_file.c_str(), &model); else if (boost::algorithm::iends_with(input_file, ".obj")) result = load_obj(input_file.c_str(), &model); - else if (!boost::algorithm::iends_with(input_file, ".zip.amf") && (boost::algorithm::iends_with(input_file, ".amf") || - boost::algorithm::iends_with(input_file, ".amf.xml"))) + else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml")) result = load_amf(input_file.c_str(), config, &model); else if (boost::algorithm::iends_with(input_file, ".3mf")) result = load_3mf(input_file.c_str(), config, &model); @@ -486,9 +483,20 @@ bool Model::looks_like_multipart_object() const return false; } +// Generate next extruder ID string, in the range of (1, max_extruders). +static inline std::string auto_extruder_id(unsigned int max_extruders, unsigned int &cntr) +{ + char str_extruder[64]; + sprintf(str_extruder, "%ud", cntr + 1); + if (++ cntr == max_extruders) + cntr = 0; + return str_extruder; +} + void Model::convert_multipart_object(unsigned int max_extruders) { - if (this->objects.empty()) + assert(this->objects.size() >= 2); + if (this->objects.size() < 2) return; ModelObject* object = new ModelObject(this); @@ -496,58 +504,32 @@ void Model::convert_multipart_object(unsigned int max_extruders) object->name = this->objects.front()->name; //FIXME copy the config etc? - reset_auto_extruder_id(); - - bool is_single_object = (this->objects.size() == 1); - - for (const ModelObject* o : this->objects) - { - for (const ModelVolume* v : o->volumes) - { - if (is_single_object) - { - // If there is only one object, just copy the volumes - ModelVolume* new_v = object->add_volume(*v); - if (new_v != nullptr) - { - new_v->name = o->name; - new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders)); - new_v->translate(-o->origin_translation); - } - } - else - { - // If there are more than one object, put all volumes together - // Each object may contain any number of volumes and instances - // The volumes transformations are relative to the object containing them... - int counter = 1; - for (const ModelInstance* i : o->instances) - { - ModelVolume* new_v = object->add_volume(*v); - if (new_v != nullptr) - { - new_v->name = o->name + "_" + std::to_string(counter++); - new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders)); - new_v->translate(-o->origin_translation); - // ...so, transform everything to a common reference system (world) - new_v->set_transformation(i->get_transformation() * v->get_transformation()); - } - } + unsigned int extruder_counter = 0; + for (const ModelObject* o : this->objects) + for (const ModelVolume* v : o->volumes) { + // If there are more than one object, put all volumes together + // Each object may contain any number of volumes and instances + // The volumes transformations are relative to the object containing them... + Geometry::Transformation trafo_volume = v->get_transformation(); + // Revert the centering operation. + trafo_volume.set_offset(trafo_volume.get_offset() - o->origin_translation); + int counter = 1; + auto copy_volume = [o, max_extruders, &counter, &extruder_counter](ModelVolume *new_v) { + assert(new_v != nullptr); + new_v->name = o->name + "_" + std::to_string(counter++); + new_v->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter)); + return new_v; + }; + if (o->instances.empty()) { + copy_volume(object->add_volume(*v))->set_transformation(trafo_volume); + } else { + for (const ModelInstance* i : o->instances) + // ...so, transform everything to a common reference system (world) + copy_volume(object->add_volume(*v))->set_transformation(i->get_transformation() * trafo_volume); } } - } - - if (is_single_object) - { - // If there is only one object, keep its instances - for (const ModelInstance* i : this->objects.front()->instances) - { - object->add_instance(*i); - } - } - else - // If there are more than one object, create a single instance - object->add_instance(); + // If there are more than one object, create a single instance + object->add_instance(); this->clear_objects(); this->objects.push_back(object); @@ -572,32 +554,6 @@ void Model::adjust_min_z() } } -unsigned int Model::get_auto_extruder_id(unsigned int max_extruders) -{ - unsigned int id = s_auto_extruder_id; - if (id > max_extruders) { - // The current counter is invalid, likely due to switching the printer profiles - // to a profile with a lower number of extruders. - reset_auto_extruder_id(); - id = s_auto_extruder_id; - } else if (++ s_auto_extruder_id > max_extruders) { - reset_auto_extruder_id(); - } - return id; -} - -std::string Model::get_auto_extruder_id_as_string(unsigned int max_extruders) -{ - char str_extruder[64]; - sprintf(str_extruder, "%ud", get_auto_extruder_id(max_extruders)); - return str_extruder; -} - -void Model::reset_auto_extruder_id() -{ - s_auto_extruder_id = 1; -} - // Propose a filename including path derived from the ModelObject's input path. // If object's name is filled in, use the object name, otherwise use the input name. std::string Model::propose_export_file_name_and_path() const @@ -644,6 +600,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->sla_points_status = rhs.sla_points_status; this->layer_config_ranges = rhs.layer_config_ranges; // #ys_FIXME_experiment this->layer_height_profile = rhs.layer_height_profile; + this->printable = rhs.printable; this->origin_translation = rhs.origin_translation; m_bounding_box = rhs.m_bounding_box; m_bounding_box_valid = rhs.m_bounding_box_valid; @@ -1662,7 +1619,7 @@ size_t ModelVolume::split(unsigned int max_extruders) size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin(); std::string name = this->name; - Model::reset_auto_extruder_id(); + unsigned int extruder_counter = 0; Vec3d offset = this->get_offset(); for (TriangleMesh *mesh : meshptrs) { @@ -1681,7 +1638,7 @@ size_t ModelVolume::split(unsigned int max_extruders) this->object->volumes[ivolume]->center_geometry_after_creation(); this->object->volumes[ivolume]->translate(offset); this->object->volumes[ivolume]->name = name + "_" + std::to_string(idx + 1); - this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string(max_extruders)); + this->object->volumes[ivolume]->config.set_deserialize("extruder", auto_extruder_id(max_extruders, extruder_counter)); delete mesh; ++ idx; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index a3281e5222..2678ddfcc6 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -192,6 +192,8 @@ public: // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers. // The pairs of are packed into a 1D array. std::vector layer_height_profile; + // Whether or not this object is printable + bool printable; // This vector holds position of selected support points for SLA. The data are // saved in mesh coordinates to allow using them for several instances. @@ -304,11 +306,11 @@ public: private: friend class Model; // This constructor assigns new ID to this ModelObject and its config. - explicit ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()), + explicit ModelObject(Model* model) : m_model(model), printable(true), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) - { assert(this->id().valid()); } - explicit ModelObject(int) : ObjectBase(-1), config(-1), m_model(nullptr), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) - { assert(this->id().invalid()); assert(this->config.id().invalid()); } + { assert(this->id().valid()); } + explicit ModelObject(int) : ObjectBase(-1), config(-1), m_model(nullptr), printable(true), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) + { assert(this->id().invalid()); assert(this->config.id().invalid()); } ~ModelObject(); void assign_new_unique_ids_recursive() override; @@ -370,8 +372,8 @@ private: template void serialize(Archive &ar) { ar(cereal::base_class(this)); Internal::StaticSerializationWrapper config_wrapper(config); - ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation, - m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid); + ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, printable, origin_translation, + m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid); } }; @@ -595,6 +597,8 @@ private: public: // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) EPrintVolumeState print_volume_state; + // Whether or not this instance is printable + bool printable; ModelObject* get_object() const { return this->object; } @@ -639,8 +643,8 @@ public: const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } - bool is_printable() const { return print_volume_state == PVS_Inside; } - + bool is_printable() const { return object->printable && printable && (print_volume_state == PVS_Inside); } + // Getting the input polygon for arrange arrangement::ArrangePolygon get_arrange_polygon() const; @@ -667,10 +671,10 @@ private: ModelObject* object; // Constructor, which assigns a new unique ID. - explicit ModelInstance(ModelObject *object) : print_volume_state(PVS_Inside), object(object) { assert(this->id().valid()); } + explicit ModelInstance(ModelObject* object) : print_volume_state(PVS_Inside), printable(true), object(object) { assert(this->id().valid()); } // Constructor, which assigns a new unique ID. explicit ModelInstance(ModelObject *object, const ModelInstance &other) : - m_transformation(other.m_transformation), print_volume_state(PVS_Inside), object(object) { assert(this->id().valid() && this->id() != other.id()); } + m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(true), object(object) {assert(this->id().valid() && this->id() != other.id());} explicit ModelInstance(ModelInstance &&rhs) = delete; ModelInstance& operator=(const ModelInstance &rhs) = delete; @@ -681,8 +685,8 @@ private: // Used for deserialization, therefore no IDs are allocated. ModelInstance() : ObjectBase(-1), object(nullptr) { assert(this->id().invalid()); } template void serialize(Archive &ar) { - ar(m_transformation, print_volume_state); - } + ar(m_transformation, print_volume_state, printable); + } }; class ModelWipeTower final : public ObjectBase @@ -721,8 +725,6 @@ private: // all objects may share mutliple materials. class Model final : public ObjectBase { - static unsigned int s_auto_extruder_id; - public: // Materials are owned by a model and referenced by objects through t_model_material_id. // Single material may be shared by multiple models. @@ -791,14 +793,10 @@ public: void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); } - static unsigned int get_auto_extruder_id(unsigned int max_extruders); - static std::string get_auto_extruder_id_as_string(unsigned int max_extruders); - static void reset_auto_extruder_id(); - // Propose an output file name & path based on the first printable object's name and source input file's path. - std::string propose_export_file_name_and_path() const; + std::string propose_export_file_name_and_path() const; // Propose an output path, replace extension. The new_extension shall contain the initial dot. - std::string propose_export_file_name_and_path(const std::string &new_extension) const; + std::string propose_export_file_name_and_path(const std::string &new_extension) const; private: explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); }; diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index c3ac22e968..530d849072 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -175,6 +175,11 @@ void PlaceholderParser::apply_env_variables() } namespace spirit = boost::spirit; +// Using an encoding, which accepts unsigned chars. +// Don't use boost::spirit::ascii, as it crashes internally due to indexing with negative char values for UTF8 characters into some 7bit character classification tables. +//namespace spirit_encoding = boost::spirit::ascii; +//FIXME iso8859_1 is just a workaround for the problem above. Replace it with UTF8 support! +namespace spirit_encoding = boost::spirit::iso8859_1; namespace qi = boost::spirit::qi; namespace px = boost::phoenix; @@ -931,7 +936,7 @@ namespace client /////////////////////////////////////////////////////////////////////////// // Inspired by the C grammar rules https://www.lysator.liu.se/c/ANSI-C-grammar-y.html template - struct macro_processor : qi::grammar, spirit::ascii::space_type> + struct macro_processor : qi::grammar, spirit_encoding::space_type> { macro_processor() : macro_processor::base_type(start) { @@ -944,12 +949,12 @@ namespace client qi::lexeme_type lexeme; qi::no_skip_type no_skip; qi::real_parser strict_double; - spirit::ascii::char_type char_; + spirit_encoding::char_type char_; utf8_char_skipper_parser utf8char; spirit::bool_type bool_; spirit::int_type int_; spirit::double_type double_; - spirit::ascii::string_type string; + spirit_encoding::string_type string; spirit::eoi_type eoi; spirit::repository::qi::iter_pos_type iter_pos; auto kw = spirit::repository::qi::distinct(qi::copy(alnum | '_')); @@ -1178,20 +1183,20 @@ namespace client } // Generic expression over expr. - typedef qi::rule(const MyContext*), spirit::ascii::space_type> RuleExpression; + typedef qi::rule(const MyContext*), spirit_encoding::space_type> RuleExpression; // The start of the grammar. - qi::rule, spirit::ascii::space_type> start; + qi::rule, spirit_encoding::space_type> start; // A free-form text. - qi::rule text; + qi::rule text; // A free-form text, possibly empty, possibly containing macro expansions. - qi::rule text_block; + qi::rule text_block; // Statements enclosed in curely braces {} - qi::rule macro; + qi::rule macro; // Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index]. - qi::rule legacy_variable_expansion; + qi::rule legacy_variable_expansion; // Parsed identifier name. - qi::rule(), spirit::ascii::space_type> identifier; + qi::rule(), spirit_encoding::space_type> identifier; // Ternary operator (?:) over logical_or_expression. RuleExpression conditional_expression; // Logical or over logical_and_expressions. @@ -1209,16 +1214,16 @@ namespace client // Number literals, functions, braced expressions, variable references, variable indexing references. RuleExpression unary_expression; // Rule to capture a regular expression enclosed in //. - qi::rule(), spirit::ascii::space_type> regular_expression; + qi::rule(), spirit_encoding::space_type> regular_expression; // Evaluate boolean expression into bool. - qi::rule bool_expr_eval; + qi::rule bool_expr_eval; // Reference of a scalar variable, or reference to a field of a vector variable. - qi::rule(const MyContext*), qi::locals, int>, spirit::ascii::space_type> scalar_variable_reference; + qi::rule(const MyContext*), qi::locals, int>, spirit_encoding::space_type> scalar_variable_reference; // Rule to translate an identifier to a ConfigOption, or to fail. - qi::rule(const MyContext*), spirit::ascii::space_type> variable_reference; + qi::rule(const MyContext*), spirit_encoding::space_type> variable_reference; - qi::rule, spirit::ascii::space_type> if_else_output; -// qi::rule, bool, std::string>, spirit::ascii::space_type> switch_output; + qi::rule, spirit_encoding::space_type> if_else_output; +// qi::rule, bool, std::string>, spirit_encoding::space_type> switch_output; qi::symbols keywords; }; @@ -1230,7 +1235,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co typedef client::macro_processor macro_processor; // Our whitespace skipper. - spirit::ascii::space_type space; + spirit_encoding::space_type space; // Our grammar, statically allocated inside the method, meaning it will be allocated the first time // PlaceholderParser::process() runs. //FIXME this kind of initialization is not thread safe! diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c423afeb94..e376f54c30 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include //! macro used to mark string used at localization, @@ -1148,11 +1149,17 @@ std::string Print::validate() const } if (this->has_wipe_tower() && ! m_objects.empty()) { - // make sure all extruders use same diameter filament and have the same nozzle diameter + // Make sure all extruders use same diameter filament and have the same nozzle diameter + // EPSILON comparison is used for nozzles and 10 % tolerance is used for filaments + double first_nozzle_diam = m_config.nozzle_diameter.get_at(extruders().front()); + double first_filament_diam = m_config.filament_diameter.get_at(extruders().front()); for (const auto& extruder_idx : extruders()) { - if (m_config.nozzle_diameter.get_at(extruder_idx) != m_config.nozzle_diameter.get_at(extruders().front()) - || m_config.filament_diameter.get_at(extruder_idx) != m_config.filament_diameter.get_at(extruders().front())) - return L("The wipe tower is only supported if all extruders have the same nozzle diameter and use filaments of the same diameter."); + double nozzle_diam = m_config.nozzle_diameter.get_at(extruder_idx); + double filament_diam = m_config.filament_diameter.get_at(extruder_idx); + if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam + || std::abs((filament_diam-first_filament_diam)/first_filament_diam) > 0.1) + return L("The wipe tower is only supported if all extruders have the same nozzle diameter " + "and use filaments of the same diameter."); } if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin) @@ -1160,15 +1167,11 @@ std::string Print::validate() const if (! m_config.use_relative_e_distances) return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."); - for (size_t i=1; i 1) { bool has_custom_layering = false; std::vector> layer_height_profiles; for (const PrintObject *object : m_objects) { - has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); // #ys_FIXME_experiment + has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); if (has_custom_layering) { layer_height_profiles.assign(m_objects.size(), std::vector()); break; @@ -1247,6 +1250,20 @@ std::string Print::validate() const return L("One or more object were assigned an extruder that the printer does not have."); #endif + auto validate_extrusion_width = [min_nozzle_diameter, max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool { + double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter); + double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter); + if (extrusion_width_min == 0) { + // Default "auto-generated" extrusion width is always valid. + } else if (extrusion_width_min <= layer_height) { + err_msg = (boost::format(L("%1%=%2% mm is too low to be printable at a layer height %3% mm")) % opt_key % extrusion_width_min % layer_height).str(); + return false; + } else if (extrusion_width_max >= max_nozzle_diameter * 2.) { + err_msg = (boost::format(L("Excessive %1%=%2% mm to be printable with a nozzle diameter %3% mm")) % opt_key % extrusion_width_max % max_nozzle_diameter).str(); + return false; + } + return true; + }; for (PrintObject *object : m_objects) { if (object->config().raft_layers > 0 || object->config().support_material.value) { if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) { @@ -1290,8 +1307,20 @@ std::string Print::validate() const return L("First layer height can't be greater than nozzle diameter"); // validate layer_height - if (object->config().layer_height.value > min_nozzle_diameter) + double layer_height = object->config().layer_height.value; + if (layer_height > min_nozzle_diameter) return L("Layer height can't be greater than nozzle diameter"); + + // Validate extrusion widths. + std::string err_msg; + if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg)) + return err_msg; + if ((object->config().support_material || object->config().raft_layers > 0) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg)) + return err_msg; + for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" }) + for (size_t i = 0; i < object->region_volumes.size(); ++ i) + if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg)) + return err_msg; } } @@ -1723,7 +1752,7 @@ void Print::_make_wipe_tower() break; lt.has_support = true; // Insert the new support layer. - double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z; + double height = lt.print_z - (i == 0 ? 0. : m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z); //FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway. it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height); ++ it_layer; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f38ef662d2..31de80e8be 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -422,6 +422,7 @@ void PrintConfigDef::init_fff_params() def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern"; def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values = def_top_fill_pattern->enum_values; + def->enum_labels = def_top_fill_pattern->enum_labels; def->aliases = def_top_fill_pattern->aliases; def->set_default_value(new ConfigOptionEnum(ipRectilinear)); @@ -2675,14 +2676,14 @@ void PrintConfigDef::init_sla_params() def->set_default_value(new ConfigOptionFloat(50.0)); // This is disabled on the UI. I hope it will never be enabled. - def = this->add("pad_edge_radius", coFloat); - def->label = L("Pad edge radius"); - def->category = L("Pad"); -// def->tooltip = L(""); - def->sidetext = L("mm"); - def->min = 0; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloat(1.0)); +// def = this->add("pad_edge_radius", coFloat); +// def->label = L("Pad edge radius"); +// def->category = L("Pad"); +//// def->tooltip = L(""); +// def->sidetext = L("mm"); +// def->min = 0; +// def->mode = comAdvanced; +// def->set_default_value(new ConfigOptionFloat(1.0)); def = this->add("pad_wall_slope", coFloat); def->label = L("Pad wall slope"); @@ -2695,6 +2696,13 @@ void PrintConfigDef::init_sla_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(45.0)); + def = this->add("pad_zero_elevation", coBool); + def->label = L("Pad around object"); + def->category = L("Pad"); + def->tooltip = L("Create pad around object and ignore the support elevation"); + def->mode = comSimple; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("pad_object_gap", coFloat); def->label = L("Pad object gap"); def->category = L("Pad"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f2d0775fa0..081f670e15 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -740,7 +740,7 @@ protected: class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig { STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig) - PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); } + PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); } public: double min_object_distance() const; static double min_object_distance(const ConfigBase *config); @@ -812,7 +812,7 @@ public: ConfigOptionFloat z_offset; protected: - PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {} + PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {} void initialize(StaticCacheBase &cache, const char *base_ptr) { this->MachineEnvelopeConfig::initialize(cache, base_ptr); @@ -991,7 +991,7 @@ public: // The height of the pillar base cone in mm. ConfigOptionFloat support_base_height /*= 1.0*/; - + // The minimum distance of the pillar base from the model in mm. ConfigOptionFloat support_base_safety_distance; /*= 1.0*/; @@ -1007,7 +1007,7 @@ public: // The elevation in Z direction upwards. This is the space between the pad // and the model object's bounding box bottom. Units in mm. ConfigOptionFloat support_object_elevation /*= 5.0*/; - + /////// Following options influence automatic support points placement: ConfigOptionInt support_points_density_relative; ConfigOptionFloat support_points_minimal_distance; @@ -1028,11 +1028,11 @@ public: ConfigOptionFloat pad_max_merge_distance /*= 50*/; // The smoothing radius of the pad edges - ConfigOptionFloat pad_edge_radius /*= 1*/; + // ConfigOptionFloat pad_edge_radius /*= 1*/; // The slope of the pad wall... ConfigOptionFloat pad_wall_slope; - + // ///////////////////////////////////////////////////////////////////////// // Zero elevation mode parameters: // - The object pad will be derived from the the model geometry. @@ -1040,16 +1040,19 @@ public: // according to the support_base_safety_distance parameter. // - The two pads will be connected with tiny connector sticks // ///////////////////////////////////////////////////////////////////////// - + + // Disable the elevation (ignore its value) and use the zero elevation mode + ConfigOptionBool pad_zero_elevation; + // This is the gap between the object bottom and the generated pad ConfigOptionFloat pad_object_gap; - + // How far to place the connector sticks on the object pad perimeter ConfigOptionFloat pad_object_connector_stride; - + // The width of the connectors sticks ConfigOptionFloat pad_object_connector_width; - + // How much should the tiny connectors penetrate into the model body ConfigOptionFloat pad_object_connector_penetration; @@ -1080,8 +1083,9 @@ protected: OPT_PTR(pad_wall_thickness); OPT_PTR(pad_wall_height); OPT_PTR(pad_max_merge_distance); - OPT_PTR(pad_edge_radius); + // OPT_PTR(pad_edge_radius); OPT_PTR(pad_wall_slope); + OPT_PTR(pad_zero_elevation); OPT_PTR(pad_object_gap); OPT_PTR(pad_object_connector_stride); OPT_PTR(pad_object_connector_width); @@ -1205,8 +1209,8 @@ extern const CLIMiscConfigDef cli_misc_config_def; class DynamicPrintAndCLIConfig : public DynamicPrintConfig { public: - DynamicPrintAndCLIConfig() {} - DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {} + DynamicPrintAndCLIConfig() {} + DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {} // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here. const ConfigDef* def() const override { return &s_def; } @@ -1227,7 +1231,7 @@ private: this->options.insert(cli_transform_config_def.options.begin(), cli_transform_config_def.options.end()); this->options.insert(cli_misc_config_def.options.begin(), cli_misc_config_def.options.end()); for (const auto &kvp : this->options) - this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second; + this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second; } // Do not release the default values, they are handled by print_config_def & cli_actions_config_def / cli_transform_config_def / cli_misc_config_def. ~PrintAndCLIConfigDef() { this->options.clear(); } @@ -1239,36 +1243,36 @@ private: // Serialization through the Cereal library namespace cereal { - // Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig. - template struct specialize {}; + // Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig. + template struct specialize {}; - template void load(Archive& archive, Slic3r::DynamicPrintConfig &config) - { - size_t cnt; - archive(cnt); - config.clear(); - for (size_t i = 0; i < cnt; ++ i) { - size_t serialization_key_ordinal; - archive(serialization_key_ordinal); - assert(serialization_key_ordinal > 0); - auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal); - assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end()); - config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive)); - } - } + template void load(Archive& archive, Slic3r::DynamicPrintConfig &config) + { + size_t cnt; + archive(cnt); + config.clear(); + for (size_t i = 0; i < cnt; ++ i) { + size_t serialization_key_ordinal; + archive(serialization_key_ordinal); + assert(serialization_key_ordinal > 0); + auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal); + assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end()); + config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive)); + } + } - template void save(Archive& archive, const Slic3r::DynamicPrintConfig &config) - { - size_t cnt = config.size(); - archive(cnt); - for (auto it = config.cbegin(); it != config.cend(); ++it) { - const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first); - assert(optdef != nullptr); - assert(optdef->serialization_key_ordinal > 0); - archive(optdef->serialization_key_ordinal); - optdef->save_option_to_archive(archive, it->second.get()); - } - } + template void save(Archive& archive, const Slic3r::DynamicPrintConfig &config) + { + size_t cnt = config.size(); + archive(cnt); + for (auto it = config.cbegin(); it != config.cend(); ++it) { + const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first); + assert(optdef != nullptr); + assert(optdef->serialization_key_ordinal > 0); + archive(optdef->serialization_key_ordinal); + optdef->save_option_to_archive(archive, it->second.get()); + } + } } #endif diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 1838514f31..5e0ac1c956 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -713,7 +713,7 @@ struct Pad { } tmesh.translate(0, 0, float(zlevel)); - tmesh.require_shared_vertices(); + if (!tmesh.empty()) tmesh.require_shared_vertices(); } bool empty() const { return tmesh.facets_count() == 0; } @@ -2597,39 +2597,51 @@ void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const { } std::vector SLASupportTree::slice( - const std::vector &heights, float cr) const + const std::vector &grid, float cr) const { const TriangleMesh &sup_mesh = m_impl->merged_mesh(); const TriangleMesh &pad_mesh = get_pad(); - std::vector sup_slices; + using Slices = std::vector; + auto slices = reserve_vector(2); + if (!sup_mesh.empty()) { + slices.emplace_back(); + TriangleMeshSlicer sup_slicer(&sup_mesh); - sup_slicer.slice(heights, cr, &sup_slices, m_impl->ctl().cancelfn); + sup_slicer.slice(grid, cr, &slices.back(), m_impl->ctl().cancelfn); } - auto bb = pad_mesh.bounding_box(); - auto maxzit = std::upper_bound(heights.begin(), heights.end(), bb.max.z()); - - auto padgrid = reserve_vector(heights.end() - maxzit); - std::copy(heights.begin(), maxzit, std::back_inserter(padgrid)); - - std::vector pad_slices; if (!pad_mesh.empty()) { + slices.emplace_back(); + + auto bb = pad_mesh.bounding_box(); + auto maxzit = std::upper_bound(grid.begin(), grid.end(), bb.max.z()); + + auto padgrid = reserve_vector(grid.end() - maxzit); + std::copy(grid.begin(), maxzit, std::back_inserter(padgrid)); + TriangleMeshSlicer pad_slicer(&pad_mesh); - pad_slicer.slice(padgrid, cr, &pad_slices, m_impl->ctl().cancelfn); + pad_slicer.slice(padgrid, cr, &slices.back(), m_impl->ctl().cancelfn); } - size_t len = std::min(heights.size(), pad_slices.size()); - len = std::min(len, sup_slices.size()); + size_t len = grid.size(); + for (const Slices &slv : slices) { len = std::min(len, slv.size()); } - for (size_t i = 0; i < len; ++i) { - std::copy(pad_slices[i].begin(), pad_slices[i].end(), - std::back_inserter(sup_slices[i])); - pad_slices[i] = {}; + // Either the support or the pad or both has to be non empty + if (slices.empty()) return {}; + + Slices &mrg = slices.front(); + + for (auto it = std::next(slices.begin()); it != slices.end(); ++it) { + for (size_t i = 0; i < len; ++i) { + Slices &slv = *it; + std::copy(slv[i].begin(), slv[i].end(), std::back_inserter(mrg[i])); + slv[i] = {}; // clear and delete + } } - return sup_slices; + return mrg; } const TriangleMesh &SLASupportTree::add_pad(const ExPolygons& modelbase, diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 46fa281b5e..1529f4bafc 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -575,6 +575,16 @@ std::string SLAPrint::output_filename(const std::string &filename_base) const } namespace { + +bool is_zero_elevation(const SLAPrintObjectConfig &c) { + bool en_implicit = c.support_object_elevation.getFloat() <= EPSILON && + c.pad_enable.getBool() && c.supports_enable.getBool(); + bool en_explicit = c.pad_zero_elevation.getBool() && + c.supports_enable.getBool(); + + return en_implicit || en_explicit; +} + // Compile the argument for support creation from the static print config. sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { sla::SupportConfig scfg; @@ -583,7 +593,8 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { scfg.head_back_radius_mm = 0.5*c.support_pillar_diameter.getFloat(); scfg.head_penetration_mm = c.support_head_penetration.getFloat(); scfg.head_width_mm = c.support_head_width.getFloat(); - scfg.object_elevation_mm = c.support_object_elevation.getFloat(); + scfg.object_elevation_mm = is_zero_elevation(c) ? + 0. : c.support_object_elevation.getFloat(); scfg.bridge_slope = c.support_critical_angle.getFloat() * PI / 180.0 ; scfg.max_bridge_length_mm = c.support_max_bridge_length.getFloat(); scfg.max_pillar_link_distance_mm = c.support_max_pillar_link_distance.getFloat(); @@ -609,8 +620,7 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { sla::PoolConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c) { sla::PoolConfig::EmbedObject ret; - ret.enabled = c.support_object_elevation.getFloat() <= EPSILON && - c.pad_enable.getBool() && c.supports_enable.getBool(); + ret.enabled = is_zero_elevation(c); if(ret.enabled) { ret.object_gap_mm = c.pad_object_gap.getFloat(); @@ -667,7 +677,9 @@ std::string SLAPrint::validate() const double elv = cfg.object_elevation_mm; if(supports_en && elv > EPSILON && elv < pinhead_width ) - return L("Elevation is too low for object."); + return L( + "Elevation is too low for object. Use the \"Pad around " + "obect\" feature to print the object without elevation."); sla::PoolConfig::EmbedObject builtinpad = builtin_pad_cfg(po->config()); if(supports_en && builtinpad.enabled && @@ -755,7 +767,7 @@ void SLAPrint::process() for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) po.m_slice_index.emplace_back(h, unscaled(h) - lh / 2.f, lh); - // Just get the first record that is form the model: + // Just get the first record that is from the model: auto slindex_it = po.closest_slice_record(po.m_slice_index, float(bb3d.min(Z))); @@ -885,7 +897,7 @@ void SLAPrint::process() // If the zero elevation mode is engaged, we have to filter out all the // points that are on the bottom of the object - if (po.config().support_object_elevation.getFloat() <= EPSILON) { + if (is_zero_elevation(po.config())) { double gnd = po.m_supportdata->emesh.ground_level(); auto & pts = po.m_supportdata->support_points; double tolerance = po.config().pad_enable.getBool() @@ -1668,6 +1680,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector= info (3). -extern std::string log_memory_info(); +// The string is non-empty if the loglevel >= info (3) or ignore_loglevel==true. +// Latter is used to get the memory info from SysInfoDialog. +extern std::string log_memory_info(bool ignore_loglevel = false); extern void disable_multi_threading(); // Returns the size of physical memory (RAM) in bytes. extern size_t total_physical_memory(); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index f9a0443380..8fcd611acc 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -13,9 +13,13 @@ #include #include #include + #include #ifdef BSD #include #endif + #ifdef __APPLE__ + #include + #endif #endif #include @@ -29,7 +33,6 @@ #include #include #include -#include #include #include @@ -89,10 +92,10 @@ unsigned get_logging_level() } // Force set_logging_level(<=error) after loading of the DLL. -// Switch boost::filesystem to utf8. +// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter +// to perform unit and integration tests. static struct RunOnInit { RunOnInit() { - boost::nowide::nowide_filesystem(); set_logging_level(1); } } g_RunOnInit; @@ -431,47 +434,82 @@ std::string format_memsize_MB(size_t n) return out + "MB"; } -#ifdef WIN32 - -#ifndef PROCESS_MEMORY_COUNTERS_EX - // MingW32 doesn't have this struct in psapi.h - typedef struct _PROCESS_MEMORY_COUNTERS_EX { - DWORD cb; - DWORD PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivateUsage; - } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; -#endif /* PROCESS_MEMORY_COUNTERS_EX */ - -std::string log_memory_info() +// Returns platform-specific string to be used as log output or parsed in SysInfoDialog. +// The latter parses the string with (semi)colons as separators, it should look about as +// "desc1: value1; desc2: value2" or similar (spaces should not matter). +std::string log_memory_info(bool ignore_loglevel) { std::string out; - if (logSeverity <= boost::log::trivial::info) { + if (ignore_loglevel || logSeverity <= boost::log::trivial::info) { +#ifdef WIN32 + #ifndef PROCESS_MEMORY_COUNTERS_EX + // MingW32 doesn't have this struct in psapi.h + typedef struct _PROCESS_MEMORY_COUNTERS_EX { + DWORD cb; + DWORD PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivateUsage; + } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; + #endif /* PROCESS_MEMORY_COUNTERS_EX */ + + HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); if (hProcess != nullptr) { PROCESS_MEMORY_COUNTERS_EX pmc; if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + " PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + " Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + else + out += " Used memory: N/A"; CloseHandle(hProcess); } +#elif defined(__linux__) or defined(__APPLE__) + // Get current memory usage. + #ifdef __APPLE__ + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + out += " Resident memory: "; + if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount ) == KERN_SUCCESS ) + out += format_memsize_MB((size_t)info.resident_size); + else + out += "N/A"; + #else // i.e. __linux__ + size_t tSize = 0, resident = 0, share = 0; + std::ifstream buffer("/proc/self/statm"); + if (buffer && (buffer >> tSize >> resident >> share)) { + size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE); // in case x86-64 is configured to use 2MB pages + size_t rss = resident * page_size; + out += " Resident memory: " + format_memsize_MB(rss); + out += "; Shared memory: " + format_memsize_MB(share * page_size); + out += "; Private memory: " + format_memsize_MB(rss - share * page_size); + } + else + out += " Used memory: N/A"; + #endif + // Now get peak memory usage. + out += "; Peak memory usage: "; + rusage memory_info; + if (getrusage(RUSAGE_SELF, &memory_info) == 0) + { + size_t peak_mem_usage = (size_t)memory_info.ru_maxrss; + #ifdef __linux__ + peak_mem_usage *= 1024;// getrusage returns the value in kB on linux + #endif + out += format_memsize_MB(peak_mem_usage); + } + else + out += "N/A"; +#endif } return out; } -#else -std::string log_memory_info() -{ - return std::string(); -} -#endif - // Returns the size of physical memory (RAM) in bytes. // http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system size_t total_physical_memory() diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index dba5958466..ad2d9305f8 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -12,6 +12,7 @@ #include "libslic3r/GCode/Analyzer.hpp" #include "slic3r/GUI/PresetBundle.hpp" #include "libslic3r/Format/STL.hpp" +#include "libslic3r/Utils.hpp" #include #include @@ -74,15 +75,19 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh) } } -void GLIndexedVertexArray::finalize_geometry() const +void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized) { assert(this->vertices_and_normals_interleaved_VBO_id == 0); assert(this->triangle_indices_VBO_id == 0); assert(this->quad_indices_VBO_id == 0); - this->shrink_to_fit(); + if (! opengl_initialized) { + // Shrink the data vectors to conserve memory in case the data cannot be transfered to the OpenGL driver yet. + this->shrink_to_fit(); + return; + } - if (! empty()) { + if (! this->vertices_and_normals_interleaved.empty()) { glsafe(::glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW)); @@ -124,13 +129,8 @@ void GLIndexedVertexArray::release_geometry() void GLIndexedVertexArray::render() const { - if (this->vertices_and_normals_interleaved_VBO_id == 0) - { - // sends data to gpu, if not done yet - finalize_geometry(); - if (this->vertices_and_normals_interleaved_VBO_id == 0) - return; - } + assert(this->vertices_and_normals_interleaved_VBO_id != 0); + assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); @@ -161,13 +161,8 @@ void GLIndexedVertexArray::render( const std::pair& tverts_range, const std::pair& qverts_range) const { - if (this->vertices_and_normals_interleaved_VBO_id == 0) - { - // sends data to gpu, if not done yet - finalize_geometry(); - if (this->vertices_and_normals_interleaved_VBO_id == 0) - return; - } + assert(this->vertices_and_normals_interleaved_VBO_id != 0); + assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); // Render using the Vertex Buffer Objects. glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); @@ -218,6 +213,7 @@ GLVolume::GLVolume(float r, float g, float b, float a) , extruder_id(0) , selected(false) , disabled(false) + , printable(true) , is_active(true) , zoom_to_volumes(true) , shader_outside_printer_detection_enabled(false) @@ -275,6 +271,13 @@ void GLVolume::set_render_color() set_render_color(color, 4); } + if (!printable) + { + render_color[0] /= 4; + render_color[1] /= 4; + render_color[2] /= 4; + } + if (force_transparent) render_color[3] = color[3]; } @@ -415,30 +418,32 @@ bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == - bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposBasePool); } std::vector GLVolumeCollection::load_object( - const ModelObject* model_object, + const ModelObject *model_object, int obj_idx, - const std::vector& instance_idxs, - const std::string& color_by) + const std::vector &instance_idxs, + const std::string &color_by, + bool opengl_initialized) { std::vector volumes_idx; for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx) for (int instance_idx : instance_idxs) - volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by)); + volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized)); return volumes_idx; } int GLVolumeCollection::load_object_volume( - const ModelObject* model_object, - int obj_idx, - int volume_idx, - int instance_idx, - const std::string& color_by) + const ModelObject *model_object, + int obj_idx, + int volume_idx, + int instance_idx, + const std::string &color_by, + bool opengl_initialized) { - const ModelVolume* model_volume = model_object->volumes[volume_idx]; - const int extruder_id = model_volume->extruder_id(); - const ModelInstance* instance = model_object->instances[instance_idx]; - const TriangleMesh& mesh = model_volume->mesh(); - float color[4]; + const ModelVolume *model_volume = model_object->volumes[volume_idx]; + const int extruder_id = model_volume->extruder_id(); + const ModelInstance *instance = model_object->instances[instance_idx]; + const TriangleMesh &mesh = model_volume->mesh(); + float color[4]; memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3); /* if (model_volume->is_support_blocker()) { color[0] = 1.0f; @@ -455,6 +460,7 @@ int GLVolumeCollection::load_object_volume( GLVolume& v = *this->volumes.back(); v.set_color_from_model_volume(model_volume); v.indexed_vertex_array.load_mesh(mesh); + v.indexed_vertex_array.finalize_geometry(opengl_initialized); v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx); if (model_volume->is_model_part()) { @@ -475,13 +481,14 @@ int GLVolumeCollection::load_object_volume( // This function produces volumes for multiple instances in a single shot, // as some object specific mesh conversions may be expensive. void GLVolumeCollection::load_object_auxiliary( - const SLAPrintObject* print_object, + const SLAPrintObject *print_object, int obj_idx, // pairs of const std::vector>& instances, SLAPrintObjectStep milestone, // Timestamp of the last change of the milestone - size_t timestamp) + size_t timestamp, + bool opengl_initialized) { assert(print_object->is_step_done(milestone)); Transform3d mesh_trafo_inv = print_object->trafo().inverse(); @@ -495,6 +502,7 @@ void GLVolumeCollection::load_object_auxiliary( this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR)); GLVolume& v = *this->volumes.back(); v.indexed_vertex_array.load_mesh(mesh); + v.indexed_vertex_array.finalize_geometry(opengl_initialized); v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first); v.geometry_id = std::pair(timestamp, model_instance.id().id); // Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance. @@ -511,7 +519,7 @@ void GLVolumeCollection::load_object_auxiliary( } int GLVolumeCollection::load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized) { if (depth < 0.01f) return int(this->volumes.size() - 1); @@ -564,6 +572,7 @@ int GLVolumeCollection::load_wipe_tower_preview( this->volumes.emplace_back(new GLVolume(color)); GLVolume& v = *this->volumes.back(); v.indexed_vertex_array.load_mesh(mesh); + v.indexed_vertex_array.finalize_geometry(opengl_initialized); v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle)); v.composite_id = GLVolume::CompositeID(obj_idx, 0, 0); @@ -823,6 +832,27 @@ std::vector GLVolumeCollection::get_current_print_zs(bool active_only) c return print_zs; } +size_t GLVolumeCollection::cpu_memory_used() const +{ + size_t memsize = sizeof(*this) + this->volumes.capacity() * sizeof(GLVolume); + for (const GLVolume *volume : this->volumes) + memsize += volume->cpu_memory_used(); + return memsize; +} + +size_t GLVolumeCollection::gpu_memory_used() const +{ + size_t memsize = 0; + for (const GLVolume *volume : this->volumes) + memsize += volume->gpu_memory_used(); + return memsize; +} + +std::string GLVolumeCollection::log_memory_info() const +{ + return " (GLVolumeCollection RAM: " + format_memsize_MB(this->cpu_memory_used()) + " GPU: " + format_memsize_MB(this->gpu_memory_used()) + " Both: " + format_memsize_MB(this->gpu_memory_used()) + ")"; +} + // caller is responsible for supplying NO lines with zero length static void thick_lines_to_indexed_vertex_array( const Lines &lines, @@ -1598,6 +1628,7 @@ bool GLArrow::on_init() triangles.emplace_back(7, 13, 6); m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles)); + m_volume.indexed_vertex_array.finalize_geometry(true); return true; } @@ -1711,6 +1742,7 @@ bool GLCurvedArrow::on_init() triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1); m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles)); + m_volume.indexed_vertex_array.finalize_geometry(true); return true; } @@ -1737,6 +1769,7 @@ bool GLBed::on_init_from_file(const std::string& filename) m_filename = filename; m_volume.indexed_vertex_array.load_mesh(model.mesh()); + m_volume.indexed_vertex_array.finalize_geometry(true); float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f }; set_color(color, 4); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 8ae57eeaea..482c2f5805 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -64,7 +64,7 @@ public: vertices_and_normals_interleaved_VBO_id(0), triangle_indices_VBO_id(0), quad_indices_VBO_id(0) - {} + { assert(! rhs.has_VBOs()); } GLIndexedVertexArray(GLIndexedVertexArray &&rhs) : vertices_and_normals_interleaved(std::move(rhs.vertices_and_normals_interleaved)), triangle_indices(std::move(rhs.triangle_indices)), @@ -72,7 +72,7 @@ public: vertices_and_normals_interleaved_VBO_id(0), triangle_indices_VBO_id(0), quad_indices_VBO_id(0) - {} + { assert(! rhs.has_VBOs()); } ~GLIndexedVertexArray() { release_geometry(); } @@ -80,14 +80,17 @@ public: { assert(vertices_and_normals_interleaved_VBO_id == 0); assert(triangle_indices_VBO_id == 0); - assert(triangle_indices_VBO_id == 0); - this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved; - this->triangle_indices = rhs.triangle_indices; - this->quad_indices = rhs.quad_indices; - this->m_bounding_box = rhs.m_bounding_box; - vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size; - triangle_indices_size = rhs.triangle_indices_size; - quad_indices_size = rhs.quad_indices_size; + assert(quad_indices_VBO_id == 0); + assert(rhs.vertices_and_normals_interleaved_VBO_id == 0); + assert(rhs.triangle_indices_VBO_id == 0); + assert(rhs.quad_indices_VBO_id == 0); + this->vertices_and_normals_interleaved = rhs.vertices_and_normals_interleaved; + this->triangle_indices = rhs.triangle_indices; + this->quad_indices = rhs.quad_indices; + this->m_bounding_box = rhs.m_bounding_box; + this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size; + this->triangle_indices_size = rhs.triangle_indices_size; + this->quad_indices_size = rhs.quad_indices_size; return *this; } @@ -95,21 +98,24 @@ public: { assert(vertices_and_normals_interleaved_VBO_id == 0); assert(triangle_indices_VBO_id == 0); - assert(triangle_indices_VBO_id == 0); - this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved); - this->triangle_indices = std::move(rhs.triangle_indices); - this->quad_indices = std::move(rhs.quad_indices); - this->m_bounding_box = std::move(rhs.m_bounding_box); - vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size; - triangle_indices_size = rhs.triangle_indices_size; - quad_indices_size = rhs.quad_indices_size; + assert(quad_indices_VBO_id == 0); + assert(rhs.vertices_and_normals_interleaved_VBO_id == 0); + assert(rhs.triangle_indices_VBO_id == 0); + assert(rhs.quad_indices_VBO_id == 0); + this->vertices_and_normals_interleaved = std::move(rhs.vertices_and_normals_interleaved); + this->triangle_indices = std::move(rhs.triangle_indices); + this->quad_indices = std::move(rhs.quad_indices); + this->m_bounding_box = std::move(rhs.m_bounding_box); + this->vertices_and_normals_interleaved_size = rhs.vertices_and_normals_interleaved_size; + this->triangle_indices_size = rhs.triangle_indices_size; + this->quad_indices_size = rhs.quad_indices_size; return *this; } // Vertices and their normals, interleaved to be used by void glInterleavedArrays(GL_N3F_V3F, 0, x) - mutable std::vector vertices_and_normals_interleaved; - mutable std::vector triangle_indices; - mutable std::vector quad_indices; + std::vector vertices_and_normals_interleaved; + std::vector triangle_indices; + std::vector quad_indices; // When the geometry data is loaded into the graphics card as Vertex Buffer Objects, // the above mentioned std::vectors are cleared and the following variables keep their original length. @@ -119,9 +125,9 @@ public: // IDs of the Vertex Array Objects, into which the geometry has been loaded. // Zero if the VBOs are not sent to GPU yet. - mutable unsigned int vertices_and_normals_interleaved_VBO_id{ 0 }; - mutable unsigned int triangle_indices_VBO_id{ 0 }; - mutable unsigned int quad_indices_VBO_id{ 0 }; + unsigned int vertices_and_normals_interleaved_VBO_id{ 0 }; + unsigned int triangle_indices_VBO_id{ 0 }; + unsigned int quad_indices_VBO_id{ 0 }; void load_mesh_full_shading(const TriangleMesh &mesh); void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); } @@ -141,12 +147,12 @@ public: if (this->vertices_and_normals_interleaved.size() + 6 > this->vertices_and_normals_interleaved.capacity()) this->vertices_and_normals_interleaved.reserve(next_highest_power_of_2(this->vertices_and_normals_interleaved.size() + 6)); - this->vertices_and_normals_interleaved.push_back(nx); - this->vertices_and_normals_interleaved.push_back(ny); - this->vertices_and_normals_interleaved.push_back(nz); - this->vertices_and_normals_interleaved.push_back(x); - this->vertices_and_normals_interleaved.push_back(y); - this->vertices_and_normals_interleaved.push_back(z); + this->vertices_and_normals_interleaved.emplace_back(nx); + this->vertices_and_normals_interleaved.emplace_back(ny); + this->vertices_and_normals_interleaved.emplace_back(nz); + this->vertices_and_normals_interleaved.emplace_back(x); + this->vertices_and_normals_interleaved.emplace_back(y); + this->vertices_and_normals_interleaved.emplace_back(z); this->vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size(); m_bounding_box.merge(Vec3f(x, y, z).cast()); @@ -167,9 +173,9 @@ public: if (this->triangle_indices.size() + 3 > this->vertices_and_normals_interleaved.capacity()) this->triangle_indices.reserve(next_highest_power_of_2(this->triangle_indices.size() + 3)); - this->triangle_indices.push_back(idx1); - this->triangle_indices.push_back(idx2); - this->triangle_indices.push_back(idx3); + this->triangle_indices.emplace_back(idx1); + this->triangle_indices.emplace_back(idx2); + this->triangle_indices.emplace_back(idx3); this->triangle_indices_size = this->triangle_indices.size(); }; @@ -180,17 +186,17 @@ public: if (this->quad_indices.size() + 4 > this->vertices_and_normals_interleaved.capacity()) this->quad_indices.reserve(next_highest_power_of_2(this->quad_indices.size() + 4)); - this->quad_indices.push_back(idx1); - this->quad_indices.push_back(idx2); - this->quad_indices.push_back(idx3); - this->quad_indices.push_back(idx4); + this->quad_indices.emplace_back(idx1); + this->quad_indices.emplace_back(idx2); + this->quad_indices.emplace_back(idx3); + this->quad_indices.emplace_back(idx4); this->quad_indices_size = this->quad_indices.size(); }; // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects // and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs. - void finalize_geometry() const; + void finalize_geometry(bool opengl_initialized); // Release the geometry data, release OpenGL VBOs. void release_geometry(); @@ -211,7 +217,7 @@ public: } // Shrink the internal storage to tighly fit the data stored. - void shrink_to_fit() const { + void shrink_to_fit() { this->vertices_and_normals_interleaved.shrink_to_fit(); this->triangle_indices.shrink_to_fit(); this->quad_indices.shrink_to_fit(); @@ -219,6 +225,22 @@ public: const BoundingBoxf3& bounding_box() const { return m_bounding_box; } + // Return an estimate of the memory consumed by this class. + size_t cpu_memory_used() const { return sizeof(*this) + vertices_and_normals_interleaved.capacity() * sizeof(float) + triangle_indices.capacity() * sizeof(int) + quad_indices.capacity() * sizeof(int); } + // Return an estimate of the memory held by GPU vertex buffers. + size_t gpu_memory_used() const + { + size_t memsize = 0; + if (this->vertices_and_normals_interleaved_VBO_id != 0) + memsize += this->vertices_and_normals_interleaved_size * 4; + if (this->triangle_indices_VBO_id != 0) + memsize += this->triangle_indices_size * 4; + if (this->quad_indices_VBO_id != 0) + memsize += this->quad_indices_size * 4; + return memsize; + } + size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); } + private: BoundingBoxf3 m_bounding_box; }; @@ -250,7 +272,7 @@ private: Geometry::Transformation m_volume_transformation; // Shift in z required by sla supports+pad - double m_sla_shift_z; + double m_sla_shift_z; // Bounding box of this volume, in unscaled coordinates. mutable BoundingBoxf3 m_transformed_bounding_box; // Whether or not is needed to recalculate the transformed bounding box. @@ -294,6 +316,8 @@ public: bool selected; // Is this object disabled from selection? bool disabled; + // Is this object printable? + bool printable; // Whether or not this volume is active for rendering bool is_active; // Whether or not to use this volume when applying zoom_to_volumes() @@ -420,13 +444,22 @@ public: void render() const; void render(int color_id, int detection_id, int worldmatrix_id) const; - void finalize_geometry() { this->indexed_vertex_array.finalize_geometry(); } + void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); } void release_geometry() { this->indexed_vertex_array.release_geometry(); } void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; } bool is_sla_support() const; bool is_sla_pad() const; + + // Return an estimate of the memory consumed by this class. + size_t cpu_memory_used() const { + //FIXME what to do wih m_convex_hull? + return sizeof(*this) - sizeof(this->indexed_vertex_array) + this->indexed_vertex_array.cpu_memory_used() + this->print_zs.capacity() * sizeof(coordf_t) + this->offsets.capacity() * sizeof(size_t); + } + // Return an estimate of the memory held by GPU vertex buffers. + size_t gpu_memory_used() const { return this->indexed_vertex_array.gpu_memory_used(); } + size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); } }; typedef std::vector GLVolumePtrs; @@ -461,30 +494,33 @@ public: ~GLVolumeCollection() { clear(); }; std::vector load_object( - const ModelObject* model_object, + const ModelObject *model_object, int obj_idx, - const std::vector& instance_idxs, - const std::string& color_by); + const std::vector &instance_idxs, + const std::string &color_by, + bool opengl_initialized); int load_object_volume( - const ModelObject* model_object, - int obj_idx, - int volume_idx, - int instance_idx, - const std::string& color_by); + const ModelObject *model_object, + int obj_idx, + int volume_idx, + int instance_idx, + const std::string &color_by, + bool opengl_initialized); // Load SLA auxiliary GLVolumes (for support trees or pad). void load_object_auxiliary( - const SLAPrintObject* print_object, + const SLAPrintObject *print_object, int obj_idx, // pairs of const std::vector>& instances, SLAPrintObjectStep milestone, // Timestamp of the last change of the milestone - size_t timestamp); + size_t timestamp, + bool opengl_initialized); int load_wipe_tower_preview( - int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized); // Render the volumes by OpenGL. void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function filter_func = std::function()) const; @@ -492,7 +528,7 @@ public: // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects // and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs. - void finalize_geometry() { for (auto* v : volumes) v->finalize_geometry(); } + void finalize_geometry(bool opengl_initialized) { for (auto* v : volumes) v->finalize_geometry(opengl_initialized); } // Release the geometry data assigned to the volumes. // If OpenGL VBOs were allocated, an OpenGL context has to be active to release them. void release_geometry() { for (auto *v : volumes) v->release_geometry(); } @@ -520,6 +556,14 @@ public: // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection std::vector get_current_print_zs(bool active_only) const; + // Return an estimate of the memory consumed by this class. + size_t cpu_memory_used() const; + // Return an estimate of the memory held by GPU vertex buffers. + size_t gpu_memory_used() const; + size_t total_memory_used() const { return this->cpu_memory_used() + this->gpu_memory_used(); } + // Return CPU, GPU and total memory log line. + std::string log_memory_info() const; + private: GLVolumeCollection(const GLVolumeCollection &other); GLVolumeCollection& operator=(const GLVolumeCollection &); @@ -537,6 +581,7 @@ public: GLModel(); virtual ~GLModel(); + // init() / init_from_file() shall be called with the OpenGL context active! bool init() { return on_init(); } bool init_from_file(const std::string& filename) { return on_init_from_file(filename); } @@ -566,7 +611,7 @@ protected: class GLArrow : public GLModel { protected: - virtual bool on_init(); + bool on_init() override; }; class GLCurvedArrow : public GLModel @@ -577,13 +622,13 @@ public: explicit GLCurvedArrow(unsigned int resolution); protected: - virtual bool on_init(); + bool on_init() override; }; class GLBed : public GLModel { protected: - virtual bool on_init_from_file(const std::string& filename); + bool on_init_from_file(const std::string& filename) override; }; class _3DScene diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 1177c91804..a9be260bd5 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -212,7 +212,7 @@ wxPanel* BedShapePanel::init_texture_panel() wxStaticText* lbl = dynamic_cast(e.GetEventObject()); if (lbl != nullptr) { - wxString tooltip_text = (m_custom_texture == NONE) ? _(L("")) : _(m_custom_texture); + wxString tooltip_text = (m_custom_texture == NONE) ? "" : _(m_custom_texture); wxToolTip* tooltip = lbl->GetToolTip(); if ((tooltip == nullptr) || (tooltip->GetTip() != tooltip_text)) lbl->SetToolTip(tooltip_text); @@ -280,7 +280,7 @@ wxPanel* BedShapePanel::init_model_panel() wxStaticText* lbl = dynamic_cast(e.GetEventObject()); if (lbl != nullptr) { - wxString tooltip_text = (m_custom_model == NONE) ? _(L("")) : _(m_custom_model); + wxString tooltip_text = (m_custom_model == NONE) ? "" : _(m_custom_model); wxToolTip* tooltip = lbl->GetToolTip(); if ((tooltip == nullptr) || (tooltip->GetTip() != tooltip_text)) lbl->SetToolTip(tooltip_text); diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 242d00a071..8e3a6d1f12 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -22,10 +22,10 @@ namespace Slic3r { namespace GUI { const double Camera::DefaultDistance = 1000.0; -double Camera::FrustrumMinZSize = 50.0; +double Camera::FrustrumMinZRange = 50.0; +double Camera::FrustrumMinNearZ = 100.0; double Camera::FrustrumZMargin = 10.0; -double Camera::FovMinDeg = 0.5; -double Camera::FovMaxDeg = 75.0; +double Camera::MaxFovDeg = 60.0; Camera::Camera() : phi(45.0f) @@ -186,7 +186,8 @@ void Camera::apply_view_matrix() const void Camera::apply_projection(const BoundingBoxf3& box) const { - m_distance = DefaultDistance; + set_distance(DefaultDistance); + double w = 0.0; double h = 0.0; @@ -194,15 +195,14 @@ void Camera::apply_projection(const BoundingBoxf3& box) const { m_frustrum_zs = calc_tight_frustrum_zs_around(box); - w = (double)m_viewport[2]; - h = (double)m_viewport[3]; + w = 0.5 * (double)m_viewport[2]; + h = 0.5 * (double)m_viewport[3]; - double two_zoom = 2.0 * m_zoom; - if (two_zoom != 0.0) + if (m_zoom != 0.0) { - double inv_two_zoom = 1.0 / two_zoom; - w *= inv_two_zoom; - h *= inv_two_zoom; + double inv_zoom = 1.0 / m_zoom; + w *= inv_zoom; + h *= inv_zoom; } switch (m_type) @@ -226,21 +226,16 @@ void Camera::apply_projection(const BoundingBoxf3& box) const if (m_type == Perspective) { - double fov_rad = 2.0 * std::atan(h / m_frustrum_zs.first); - double fov_deg = Geometry::rad2deg(fov_rad); + double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first)); // adjust camera distance to keep fov in a limited range - if (fov_deg > FovMaxDeg + 0.001) + if (fov_deg > MaxFovDeg) { - double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMaxDeg)); - m_distance += (new_near_z - m_frustrum_zs.first); - apply_view_matrix(); - } - else if (fov_deg < FovMinDeg - 0.001) - { - double new_near_z = h / ::tan(0.5 * Geometry::deg2rad(FovMinDeg)); - m_distance += (new_near_z - m_frustrum_zs.first); - apply_view_matrix(); + double delta_z = h / ::tan(0.5 * Geometry::deg2rad(MaxFovDeg)) - m_frustrum_zs.first; + if (delta_z > 0.001) + set_distance(m_distance + delta_z); + else + break; } else break; @@ -328,42 +323,50 @@ void Camera::debug_render() const std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const { - std::pair ret = std::make_pair(DBL_MAX, -DBL_MAX); + std::pair ret; - Vec3d bb_min = box.min; - Vec3d bb_max = box.max; - - // box vertices in world space - std::vector vertices; - vertices.reserve(8); - vertices.push_back(bb_min); - vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2)); - vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2)); - vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2)); - vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2)); - vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2)); - vertices.push_back(bb_max); - vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2)); - - // set the Z range in eye coordinates (negative Zs are in front of the camera) - for (const Vec3d& v : vertices) + while (true) { - double z = -(m_view_matrix * v)(2); - ret.first = std::min(ret.first, z); - ret.second = std::max(ret.second, z); - } + ret = std::make_pair(DBL_MAX, -DBL_MAX); - // apply margin - ret.first -= FrustrumZMargin; - ret.second += FrustrumZMargin; + // box vertices in world space + std::vector vertices; + vertices.reserve(8); + vertices.push_back(box.min); + vertices.emplace_back(box.max(0), box.min(1), box.min(2)); + vertices.emplace_back(box.max(0), box.max(1), box.min(2)); + vertices.emplace_back(box.min(0), box.max(1), box.min(2)); + vertices.emplace_back(box.min(0), box.min(1), box.max(2)); + vertices.emplace_back(box.max(0), box.min(1), box.max(2)); + vertices.push_back(box.max); + vertices.emplace_back(box.min(0), box.max(1), box.max(2)); - // ensure min size - if (ret.second - ret.first < FrustrumMinZSize) - { - double mid_z = 0.5 * (ret.first + ret.second); - double half_size = 0.5 * FrustrumMinZSize; - ret.first = mid_z - half_size; - ret.second = mid_z + half_size; + // set the Z range in eye coordinates (negative Zs are in front of the camera) + for (const Vec3d& v : vertices) + { + double z = -(m_view_matrix * v)(2); + ret.first = std::min(ret.first, z); + ret.second = std::max(ret.second, z); + } + + // apply margin + ret.first -= FrustrumZMargin; + ret.second += FrustrumZMargin; + + // ensure min size + if (ret.second - ret.first < FrustrumMinZRange) + { + double mid_z = 0.5 * (ret.first + ret.second); + double half_size = 0.5 * FrustrumMinZRange; + ret.first = mid_z - half_size; + ret.second = mid_z + half_size; + } + + if (ret.first >= FrustrumMinNearZ) + break; + + // ensure min Near Z + set_distance(m_distance + FrustrumMinNearZ - ret.first); } return ret; @@ -385,21 +388,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca Vec3d up = get_dir_up(); Vec3d forward = get_dir_forward(); - Vec3d bb_min = box.min; - Vec3d bb_max = box.max; Vec3d bb_center = box.center(); // box vertices in world space std::vector vertices; vertices.reserve(8); - vertices.push_back(bb_min); - vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2)); - vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2)); - vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2)); - vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2)); - vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2)); - vertices.push_back(bb_max); - vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2)); + vertices.push_back(box.min); + vertices.emplace_back(box.max(0), box.min(1), box.min(2)); + vertices.emplace_back(box.max(0), box.max(1), box.min(2)); + vertices.emplace_back(box.min(0), box.max(1), box.min(2)); + vertices.emplace_back(box.min(0), box.min(1), box.max(2)); + vertices.emplace_back(box.max(0), box.min(1), box.max(2)); + vertices.push_back(box.max); + vertices.emplace_back(box.min(0), box.max(1), box.max(2)); double max_x = 0.0; double max_y = 0.0; @@ -430,6 +431,12 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y)); } +void Camera::set_distance(double distance) const +{ + m_distance = distance; + apply_view_matrix(); +} + } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 79e87c7264..839d0d6cf1 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -10,10 +10,10 @@ namespace GUI { struct Camera { static const double DefaultDistance; - static double FrustrumMinZSize; + static double FrustrumMinZRange; + static double FrustrumMinNearZ; static double FrustrumZMargin; - static double FovMinDeg; - static double FovMaxDeg; + static double MaxFovDeg; enum EType : unsigned char { @@ -101,6 +101,7 @@ private: // the camera MUST be outside of the bounding box in eye coordinate of the given box std::pair calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const; double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const; + void set_distance(double distance) const; }; } // GUI diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 39fa9c54b2..39924e44c5 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -393,6 +393,12 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) else dynamic_cast(window)->SetValue(boost::any_cast(value)); m_disable_change_event = false; + + if (!change_event) { + wxString ret_str = static_cast(window)->GetValue(); + // update m_value to correct work of next value_was_changed() + get_value_by_opt_type(ret_str); + } } void TextCtrl::set_last_meaningful_value() @@ -410,7 +416,7 @@ void TextCtrl::set_na_value() boost::any& TextCtrl::get_value() { wxString ret_str = static_cast(window)->GetValue(); - // modifies ret_string! + // update m_value get_value_by_opt_type(ret_str); return m_value; @@ -905,7 +911,7 @@ boost::any& Choice::get_value() wxString ret_str = field->GetValue(); // options from right panel - std::vector right_panel_options{ "support", "scale_unit" }; + std::vector right_panel_options{ "support", "pad", "scale_unit" }; for (auto rp_option: right_panel_options) if (m_opt_id == rp_option) return m_value = boost::any(ret_str); diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 7865aecf2e..d1f2da040c 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -354,7 +354,7 @@ bool FirmwareDialog::priv::check_model_id() // Therefore, regretably, so far the check cannot be used and we just return true here. // TODO: Rewrite Serial using more platform-native code. return true; - + // if (hex_file.model_id.empty()) { // // No data to check against, assume it's ok // return true; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5e505bb416..a5906f619b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1234,10 +1234,9 @@ bool GLCanvas3D::init() return false; } -// // on linux the gl context is not valid until the canvas is not shown on screen -// // we defer the geometry finalization of volumes until the first call to render() -// if (!m_volumes.empty()) -// m_volumes.finalize_geometry(); + // on linux the gl context is not valid until the canvas is not shown on screen + // we defer the geometry finalization of volumes until the first call to render() + m_volumes.finalize_geometry(true); if (m_gizmos.is_enabled() && !m_gizmos.init()) std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl; @@ -1320,6 +1319,26 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject _set_warning_texture(WarningTexture::SomethingNotShown, false); } +void GLCanvas3D::update_instance_printable_state_for_object(const size_t obj_idx) +{ + ModelObject* model_object = m_model->objects[obj_idx]; + for (int inst_idx = 0; inst_idx < model_object->instances.size(); inst_idx++) + { + ModelInstance* instance = model_object->instances[inst_idx]; + + for (GLVolume* volume : m_volumes.volumes) + { + if ((volume->object_idx() == obj_idx) && (volume->instance_idx() == inst_idx)) + volume->printable = instance->printable; + } + } +} + +void GLCanvas3D::update_instance_printable_state_for_objects(std::vector& object_idxs) +{ + for (size_t obj_idx : object_idxs) + update_instance_printable_state_for_object(obj_idx); +} void GLCanvas3D::set_config(const DynamicPrintConfig* config) { @@ -1529,7 +1548,7 @@ void GLCanvas3D::render() } m_camera.apply_view_matrix(); - m_camera.apply_projection(_max_bounding_box(true)); + m_camera.apply_projection(_max_bounding_box(true, true)); GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam)); @@ -1691,7 +1710,7 @@ std::vector GLCanvas3D::load_object(const ModelObject& model_object, int ob instance_idxs.push_back(i); } } - return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by); + return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_initialized); } std::vector GLCanvas3D::load_object(const Model& model, int obj_idx) @@ -1879,7 +1898,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id); if (it->new_geometry()) { // New volume. - m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by); + m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized); m_volumes.volumes.back()->geometry_id = key.geometry_id; update_object_list = true; } else { @@ -1952,7 +1971,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re for (size_t istep = 0; istep < sla_steps.size(); ++istep) if (!instances[istep].empty()) - m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp); + m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized); } // Shift-up all volumes of the object so that it has the right elevation with respect to the print bed @@ -1992,7 +2011,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re depth = (900.f/w) * (float)(extruders_count - 1); int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), - brim_spacing * 4.5f); + brim_spacing * 4.5f, m_initialized); if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new; } @@ -2110,8 +2129,7 @@ void GLCanvas3D::load_sla_preview() if ((m_canvas != nullptr) && (print != nullptr)) { _set_current(); - // Reload the SLA support structures into GLVolumes. - this->reload_scene(true, true); + _load_sla_shells(); _update_sla_shells_outside_state(); _show_warning_texture_if_needed(WarningTexture::SlaSupportsOutside); } @@ -2906,7 +2924,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) // disable context menu when the gizmo is open { // forces the selection of the volume - m_selection.add(volume_idx); + /* m_selection.add(volume_idx); // #et_FIXME_if_needed + * To avoid extra "Add-Selection" snapshots, + * call add() with check_for_already_contained=true + * */ + m_selection.add(volume_idx, true, true); m_gizmos.refresh_on_off_state(); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); m_gizmos.update_data(); @@ -2929,7 +2951,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (evt.Moving()) { m_mouse.position = pos.cast(); - std::string tooltip = L(""); + std::string tooltip = ""; if (tooltip.empty()) tooltip = m_gizmos.get_tooltip(); @@ -3217,7 +3239,7 @@ void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_typ wxGetApp().plater()->take_snapshot(_(snapshot_type)); m_selection.flattening_rotate(normal); - do_rotate(L("")); // avoid taking another snapshot + do_rotate(""); // avoid taking another snapshot } void GLCanvas3D::do_mirror(const std::string& snapshot_type) @@ -3273,7 +3295,7 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type) void GLCanvas3D::set_camera_zoom(double zoom) { const Size& cnv_size = get_canvas_size(); - m_camera.set_zoom(zoom, _max_bounding_box(false), cnv_size.get_width(), cnv_size.get_height()); + m_camera.set_zoom(zoom, _max_bounding_box(false, false), cnv_size.get_width(), cnv_size.get_height()); m_dirty = true; } @@ -3620,14 +3642,14 @@ bool GLCanvas3D::_init_undoredo_toolbar() std::string curr_additional_tooltip; m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); - std::string new_additional_tooltip = L(""); + std::string new_additional_tooltip = ""; if (can_undo) wxGetApp().plater()->undo_redo_topmost_string_getter(true, new_additional_tooltip); if (new_additional_tooltip != curr_additional_tooltip) { m_undoredo_toolbar.set_additional_tooltip(id, new_additional_tooltip); - set_tooltip(L("")); + set_tooltip(""); } return can_undo; }; @@ -3649,14 +3671,14 @@ bool GLCanvas3D::_init_undoredo_toolbar() std::string curr_additional_tooltip; m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip); - std::string new_additional_tooltip = L(""); + std::string new_additional_tooltip = ""; if (can_redo) wxGetApp().plater()->undo_redo_topmost_string_getter(false, new_additional_tooltip); if (new_additional_tooltip != curr_additional_tooltip) { m_undoredo_toolbar.set_additional_tooltip(id, new_additional_tooltip); - set_tooltip(L("")); + set_tooltip(""); } return can_redo; }; @@ -3699,9 +3721,20 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) m_dirty = false; } -BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_bed_model) const +BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_bed_model) const { BoundingBoxf3 bb = volumes_bounding_box(); + + // The following is a workaround for gizmos not being taken in account when calculating the tight camera frustrum + // A better solution would ask the gizmo manager for the bounding box of the current active gizmo, if any + if (include_gizmos && m_gizmos.is_running()) + { + BoundingBoxf3 sel_bb = m_selection.get_bounding_box(); + Vec3d sel_bb_center = sel_bb.center(); + Vec3d extend_by = sel_bb.max_size() * Vec3d::Ones(); + bb.merge(BoundingBoxf3(sel_bb_center - extend_by, sel_bb_center + extend_by)); + } + bb.merge(m_bed.get_bounding_box(include_bed_model)); return bb; } @@ -3737,6 +3770,7 @@ void GLCanvas3D::_picking_pass() const // Better to use software ray - casting on a bounding - box hierarchy. if (m_multisample_allowed) + // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. glsafe(::glDisable(GL_MULTISAMPLE)); glsafe(::glDisable(GL_BLEND)); @@ -3766,7 +3800,9 @@ void GLCanvas3D::_picking_pass() const if (inside) { glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color)); - volume_id = color[0] + (color[1] << 8) + (color[2] << 16); + if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + volume_id = color[0] + (color[1] << 8) + (color[2] << 16); } if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { @@ -3789,6 +3825,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const if (m_picking_enabled) { if (m_multisample_allowed) + // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. glsafe(::glDisable(GL_MULTISAMPLE)); glsafe(::glDisable(GL_BLEND)); @@ -3814,6 +3851,8 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const struct Pixel { std::array data; + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + bool valid() const { return picking_checksum_alpha_channel(data[0], data[1], data[2]) == data[3]; } int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); } }; @@ -3824,17 +3863,15 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const tbb::parallel_for(tbb::blocked_range(0, frame.size(), (size_t)width), [this, &frame, &idxs, &mutex](const tbb::blocked_range& range) { for (size_t i = range.begin(); i < range.end(); ++i) - { - int volume_id = frame[i].id(); - if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) - { - mutex.lock(); - idxs.insert(volume_id); - mutex.unlock(); - } - } - } - ); + if (frame[i].valid()) { + int volume_id = frame[i].id(); + if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { + mutex.lock(); + idxs.insert(volume_id); + mutex.unlock(); + } + } + }); #else std::vector frame(4 * px_count); glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data())); @@ -4013,42 +4050,27 @@ void GLCanvas3D::_render_volumes_for_picking() const // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - glsafe(::glEnable(GL_BLEND)); - glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); const Transform3d& view_matrix = m_camera.get_view_matrix(); - GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Opaque, view_matrix); - for (const GLVolumeWithIdAndZ& volume : to_render) - { - // Object picking mode. Render the object with a color encoding the object index. - unsigned int r = (volume.second.first & 0x000000FF) >> 0; - unsigned int g = (volume.second.first & 0x0000FF00) >> 8; - unsigned int b = (volume.second.first & 0x00FF0000) >> 16; - glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); - - if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) - volume.first->render(); - } - - to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Transparent, view_matrix); - for (const GLVolumeWithIdAndZ& volume : to_render) - { - // Object picking mode. Render the object with a color encoding the object index. - unsigned int r = (volume.second.first & 0x000000FF) >> 0; - unsigned int g = (volume.second.first & 0x0000FF00) >> 8; - unsigned int b = (volume.second.first & 0x00FF0000) >> 16; - glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); - - if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) - volume.first->render(); - } + for (size_t type = 0; type < 2; ++ type) { + GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::Opaque : GLVolumeCollection::Transparent, view_matrix); + for (const GLVolumeWithIdAndZ& volume : to_render) + if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) { + // Object picking mode. Render the object with a color encoding the object index. + unsigned int id = volume.second.first; + unsigned int r = (id & (0x000000FF << 0)) << 0; + unsigned int g = (id & (0x000000FF << 8)) >> 8; + unsigned int b = (id & (0x000000FF << 16)) >> 16; + unsigned int a = picking_checksum_alpha_channel(r, g, b); + glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); + volume.first->render(); + } + } glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisable(GL_BLEND)); glsafe(::glEnable(GL_CULL_FACE)); } @@ -4511,6 +4533,7 @@ void GLCanvas3D::_load_print_toolpaths() _3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), volume); } + volume.indexed_vertex_array.finalize_geometry(m_initialized); } void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector& str_tool_colors, const std::vector& color_print_values) @@ -4576,7 +4599,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; }); // Maximum size of an allocation block: 32MB / sizeof(float) - BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start"; + BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start" << m_volumes.log_memory_info() << log_memory_info(); //FIXME Improve the heuristics for a grain size. size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1)); @@ -4682,16 +4705,22 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c } } } + for (GLVolume *vol : vols) + // Ideally one would call vol->indexed_vertex_array.finalize() here to move the buffers to the OpenGL driver, + // but this code runs in parallel and the OpenGL driver is not thread safe. + vol->indexed_vertex_array.shrink_to_fit(); }); - BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results"; + BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info(); // Remove empty volumes from the newly added volumes. m_volumes.volumes.erase( std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(), [](const GLVolume *volume) { return volume->empty(); }), m_volumes.volumes.end()); + for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) + m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized); - BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info(); } void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector& str_tool_colors) @@ -4748,7 +4777,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector& str_ ctxt.wipe_tower_angle = ctxt.print->config().wipe_tower_rotation_angle.value/180.f * PI; ctxt.wipe_tower_pos = Vec2f(ctxt.print->config().wipe_tower_x.value, ctxt.print->config().wipe_tower_y.value); - BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start"; + BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start" << m_volumes.log_memory_info() << log_memory_info(); //FIXME Improve the heuristics for a grain size. size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1); @@ -4846,16 +4875,20 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector& str_ vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve()); } } + for (GLVolume *vol : vols) + vol->indexed_vertex_array.shrink_to_fit(); }); - BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results"; + BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results" << m_volumes.log_memory_info() << log_memory_info(); // Remove empty volumes from the newly added volumes. m_volumes.volumes.erase( std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(), [](const GLVolume *volume) { return volume->empty(); }), m_volumes.volumes.end()); + for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i) + m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized); - BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end" << m_volumes.log_memory_info() << log_memory_info(); } static inline int hex_digit_to_int(const char c) @@ -4868,6 +4901,8 @@ static inline int hex_digit_to_int(const char c) void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector& tool_colors) { + BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - start" << m_volumes.log_memory_info() << log_memory_info(); + // helper functions to select data in dependence of the extrusion view type struct Helper { @@ -4983,6 +5018,8 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat if (filters.empty()) return; + BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - create volumes" << m_volumes.log_memory_info() << log_memory_info(); + // creates a new volume for each filter for (Filter& filter : filters) { @@ -5013,6 +5050,8 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat } } + BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - populate volumes" << m_volumes.log_memory_info() << log_memory_info(); + // populates volumes for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers) { @@ -5030,6 +5069,12 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat } } } + + // finalize volumes and sends geometry to gpu + for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i) + m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized); + + BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - end" << m_volumes.log_memory_info() << log_memory_info(); } void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector& tool_colors) @@ -5074,6 +5119,10 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, return; } + + // finalize volumes and sends geometry to gpu + for (size_t i = initial_volumes_count; i < m_volumes.volumes.size(); ++i) + m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_initialized); } bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data) @@ -5302,6 +5351,7 @@ void GLCanvas3D::_load_gcode_retractions(const GCodePreviewData& preview_data) _3DScene::point3_to_verts(position.position, position.width, position.height, *volume); } + volume->indexed_vertex_array.finalize_geometry(m_initialized); } } @@ -5329,6 +5379,7 @@ void GLCanvas3D::_load_gcode_unretractions(const GCodePreviewData& preview_data) _3DScene::point3_to_verts(position.position, position.width, position.height, *volume); } + volume->indexed_vertex_array.finalize_geometry(m_initialized); } } @@ -5354,7 +5405,7 @@ void GLCanvas3D::_load_fff_shells() instance_ids[i] = i; } - m_volumes.load_object(model_obj, object_id, instance_ids, "object"); + m_volumes.load_object(model_obj, object_id, instance_ids, "object", m_initialized); ++object_id; } @@ -5376,11 +5427,63 @@ void GLCanvas3D::_load_fff_shells() if (!print->is_step_done(psWipeTower)) depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1); m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, - !print->is_step_done(psWipeTower), brim_spacing * 4.5f); + !print->is_step_done(psWipeTower), brim_spacing * 4.5f, m_initialized); } } } +// While it looks like we can call +// this->reload_scene(true, true) +// the two functions are quite different: +// 1) This function only loads objects, for which the step slaposSliceSupports already finished. Therefore objects outside of the print bed never load. +// 2) This function loads object mesh with the relative scaling correction (the "relative_correction" parameter) was applied, +// therefore the mesh may be slightly larger or smaller than the mesh shown in the 3D scene. +void GLCanvas3D::_load_sla_shells() +{ + const SLAPrint* print = this->sla_print(); + if (print->objects().empty()) + // nothing to render, return + return; + + auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance, + const TriangleMesh &mesh, const float color[4], bool outside_printer_detection_enabled) { + m_volumes.volumes.emplace_back(new GLVolume(color)); + GLVolume& v = *m_volumes.volumes.back(); + v.indexed_vertex_array.load_mesh(mesh); + v.indexed_vertex_array.finalize_geometry(this->m_initialized); + v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled; + v.composite_id.volume_id = volume_id; + v.set_instance_offset(unscale(instance.shift(0), instance.shift(1), 0)); + v.set_instance_rotation(Vec3d(0.0, 0.0, (double)instance.rotation)); + v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.); + v.set_convex_hull(mesh.convex_hull_3d()); + }; + + // adds objects' volumes + for (const SLAPrintObject* obj : print->objects()) + if (obj->is_step_done(slaposSliceSupports)) { + unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size(); + for (const SLAPrintObject::Instance& instance : obj->instances()) { + add_volume(*obj, 0, instance, obj->transformed_mesh(), GLVolume::MODEL_COLOR[0], true); + // Set the extruder_id and volume_id to achieve the same color as in the 3D scene when + // through the update_volumes_colors_by_extruder() call. + m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id(); + if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree)) + add_volume(*obj, -int(slaposSupportTree), instance, obj->support_mesh(), GLVolume::SLA_SUPPORT_COLOR, true); + if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool)) + add_volume(*obj, -int(slaposBasePool), instance, obj->pad_mesh(), GLVolume::SLA_PAD_COLOR, false); + } + double shift_z = obj->get_current_elevation(); + for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) { + GLVolume& v = *m_volumes.volumes[i]; + // apply shift z + v.set_sla_shift_z(shift_z); + } + } + + update_volumes_colors_by_extruder(); +} + void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data) { unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c9803f9db8..577682fe22 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -482,6 +482,8 @@ public: void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); + void update_instance_printable_state_for_object(size_t obj_idx); + void update_instance_printable_state_for_objects(std::vector& object_idxs); void set_config(const DynamicPrintConfig* config); void set_process(BackgroundSlicingProcess* process); @@ -652,7 +654,7 @@ private: bool _set_current(); void _resize(unsigned int w, unsigned int h); - BoundingBoxf3 _max_bounding_box(bool include_bed_model) const; + BoundingBoxf3 _max_bounding_box(bool include_gizmos, bool include_bed_model) const; void _zoom_to_box(const BoundingBoxf3& box); @@ -721,6 +723,8 @@ private: void _load_gcode_unretractions(const GCodePreviewData& preview_data); // generates objects and wipe tower geometry void _load_fff_shells(); + // Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished. + void _load_sla_shells(); // sets gcode geometry visibility according to user selection void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data); void _update_toolpath_volumes_outside_state(); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index b2a3161e89..c096c0e9fc 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -290,7 +290,21 @@ GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas) wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) { - int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; + int attribList[] = { + WX_GL_RGBA, + WX_GL_DOUBLEBUFFER, + // RGB channels each should be allocated with 8 bit depth. One should almost certainly get these bit depths by default. + WX_GL_MIN_RED, 8, + WX_GL_MIN_GREEN, 8, + WX_GL_MIN_BLUE, 8, + // Requesting an 8 bit alpha channel. Interestingly, the NVIDIA drivers would most likely work with some alpha plane, but glReadPixels would not return + // the alpha channel on NVIDIA if not requested when the GL context is created. + WX_GL_MIN_ALPHA, 8, + WX_GL_DEPTH_SIZE, 24, + WX_GL_SAMPLE_BUFFERS, GL_TRUE, + WX_GL_SAMPLES, 4, + 0 + }; if (s_multisample == MS_Unknown) { @@ -300,7 +314,7 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) } if (! can_multisample()) - attribList[4] = 0; + attribList[12] = 0; return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); } diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 516f8b934f..4fdf12489d 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -27,49 +27,57 @@ namespace GUI { void GLTexture::Compressor::reset() { - if (m_is_compressing) - { - // force compression completion, if any + if (m_thread.joinable()) { m_abort_compressing = true; - // wait for compression completion, if any - while (m_is_compressing) {} - } - - m_levels.clear(); -} - -void GLTexture::Compressor::add_level(unsigned int w, unsigned int h, const std::vector& data) -{ - m_levels.emplace_back(w, h, data); + m_thread.join(); + m_levels.clear(); + m_num_levels_compressed = 0; + m_abort_compressing = false; + } + assert(m_levels.empty()); + assert(m_abort_compressing == false); + assert(m_num_levels_compressed == 0); } void GLTexture::Compressor::start_compressing() { - std::thread t(&GLTexture::Compressor::compress, this); - t.detach(); + // The worker thread should be stopped already. + assert(! m_thread.joinable()); + assert(! m_levels.empty()); + assert(m_abort_compressing == false); + assert(m_num_levels_compressed == 0); + if (! m_levels.empty()) { + std::thread thrd(&GLTexture::Compressor::compress, this); + m_thread = std::move(thrd); + } } bool GLTexture::Compressor::unsent_compressed_data_available() const { - for (const Level& level : m_levels) - { - if (!level.sent_to_gpu && level.compressed) + if (m_levels.empty()) + return false; + // Querying the atomic m_num_levels_compressed value synchronizes processor caches, so that the dat of m_levels modified by the worker thread are accessible to the calling thread. + unsigned int num_compressed = m_num_levels_compressed; + for (unsigned int i = 0; i < num_compressed; ++ i) + if (! m_levels[i].sent_to_gpu && ! m_levels[i].compressed_data.empty()) return true; - } - return false; } void GLTexture::Compressor::send_compressed_data_to_gpu() { // this method should be called inside the main thread of Slicer or a new OpenGL context (sharing resources) would be needed + if (m_levels.empty()) + return; glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); glsafe(::glBindTexture(GL_TEXTURE_2D, m_texture.m_id)); - for (int i = 0; i < (int)m_levels.size(); ++i) + // Querying the atomic m_num_levels_compressed value synchronizes processor caches, so that the dat of m_levels modified by the worker thread are accessible to the calling thread. + int num_compressed = (int)m_num_levels_compressed; + for (int i = 0; i < num_compressed; ++ i) { Level& level = m_levels[i]; - if (!level.sent_to_gpu && level.compressed) + if (! level.sent_to_gpu && ! level.compressed_data.empty()) { glsafe(::glCompressedTexSubImage2D(GL_TEXTURE_2D, (GLint)i, 0, 0, (GLsizei)level.w, (GLsizei)level.h, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)level.compressed_data.size(), (const GLvoid*)level.compressed_data.data())); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i)); @@ -77,29 +85,21 @@ void GLTexture::Compressor::send_compressed_data_to_gpu() level.sent_to_gpu = true; // we are done with the compressed data, we can discard it level.compressed_data.clear(); - level.compressed = false; } } glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); -} -bool GLTexture::Compressor::all_compressed_data_sent_to_gpu() const -{ - for (const Level& level : m_levels) - { - if (!level.sent_to_gpu) - return false; - } - - return true; + if (num_compressed == (unsigned int)m_levels.size()) + // Finalize the worker thread, close it. + this->reset(); } void GLTexture::Compressor::compress() { // reference: https://github.com/Cyan4973/RygsDXTc - m_is_compressing = true; - m_abort_compressing = false; + assert(m_num_levels_compressed == 0); + assert(m_abort_compressing == false); for (Level& level : m_levels) { @@ -115,11 +115,8 @@ void GLTexture::Compressor::compress() // we are done with the source data, we can discard it level.src_data.clear(); - level.compressed = true; + ++ m_num_levels_compressed; } - - m_is_compressing = false; - m_abort_compressing = false; } GLTexture::Quad_UVs GLTexture::FullTextureUVs = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } }; diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index ec362944d4..c4063b93d4 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -1,8 +1,10 @@ #ifndef slic3r_GLTexture_hpp_ #define slic3r_GLTexture_hpp_ +#include #include #include +#include class wxImage; @@ -19,30 +21,34 @@ namespace GUI { unsigned int h; std::vector src_data; std::vector compressed_data; - bool compressed; bool sent_to_gpu; - Level(unsigned int w, unsigned int h, const std::vector& data) : w(w), h(h), src_data(data), compressed(false), sent_to_gpu(false) {} + Level(unsigned int w, unsigned int h, const std::vector& data) : w(w), h(h), src_data(data), sent_to_gpu(false) {} }; GLTexture& m_texture; std::vector m_levels; - bool m_is_compressing; - bool m_abort_compressing; + std::thread m_thread; + // Does the caller want the background thread to stop? + // This atomic also works as a memory barrier for synchronizing the cancel event with the worker thread. + std::atomic m_abort_compressing; + // How many levels were compressed since the start of the background processing thread? + // This atomic also works as a memory barrier for synchronizing results of the worker thread with the calling thread. + std::atomic m_num_levels_compressed; public: - explicit Compressor(GLTexture& texture) : m_texture(texture), m_is_compressing(false), m_abort_compressing(false) {} + explicit Compressor(GLTexture& texture) : m_texture(texture), m_abort_compressing(false), m_num_levels_compressed(0) {} ~Compressor() { reset(); } void reset(); - void add_level(unsigned int w, unsigned int h, const std::vector& data); + void add_level(unsigned int w, unsigned int h, const std::vector& data) { m_levels.emplace_back(w, h, data); } void start_compressing(); bool unsent_compressed_data_available() const; void send_compressed_data_to_gpu(); - bool all_compressed_data_sent_to_gpu() const; + bool all_compressed_data_sent_to_gpu() const { return m_levels.empty(); } private: void compress(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8a785760c6..066dab90fd 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -173,7 +173,8 @@ bool GUI_App::on_init_inner() wxCHECK_MSG(wxDirExists(resources_dir), false, wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir)); - SetAppName(SLIC3R_APP_KEY); + //SetAppName(SLIC3R_APP_KEY); + SetAppName(SLIC3R_APP_KEY "-alpha"); SetAppDisplayName(SLIC3R_APP_NAME); // Enable this to get the default Win32 COMCTRL32 behavior of static boxes. @@ -986,6 +987,7 @@ wxString GUI_App::current_language_code_safe() const language_code = language_code.substr(0, idx_underscore); const std::map mapping { { "cs", "cs_CZ", }, + { "sk", "cs_CZ", }, { "de", "de_DE", }, { "es", "es_ES", }, { "fr", "fr_FR", }, diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index fede48166c..3d5efe63fc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -186,7 +186,18 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, [this](wxCommandEvent& e) { last_volume_is_deleted(e.GetInt()); }); - Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { this->EnsureVisible(this->GetCurrentItem()); e.Skip(); })); + Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { +#ifdef __WXGTK__ + // On GTK, the EnsureVisible call is postponed to Idle processing (see wxDataViewCtrl::m_ensureVisibleDefered). + // So the postponed EnsureVisible() call is planned for an item, which may not exist at the Idle processing time, if this wxEVT_SIZE + // event is succeeded by a delete of the currently active item. We are trying our luck by postponing the wxEVT_SIZE triggered EnsureVisible(), + // which seems to be working as of now. + this->CallAfter([this](){ this->EnsureVisible(this->GetCurrentItem()); }); +#else + this->EnsureVisible(this->GetCurrentItem()); +#endif + e.Skip(); + })); } ObjectList::~ObjectList() @@ -212,16 +223,20 @@ void ObjectList::create_objects_ctrl() EnableDropTarget(wxDF_UNICODETEXT); #endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE - // column 0(Icon+Text) of the view control: + // column ItemName(Icon+Text) of the view control: // And Icon can be consisting of several bitmaps AppendColumn(new wxDataViewColumn(_(L("Name")), new BitmapTextRenderer(), - 0, 20*wxGetApp().em_unit()/*200*/, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); + colName, 20*wxGetApp().em_unit()/*200*/, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); - // column 1 of the view control: + // column PrintableProperty (Icon) of the view control: + AppendBitmapColumn(" ", colPrint, wxDATAVIEW_CELL_INERT, int(2 * wxGetApp().em_unit()), + wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); + + // column Extruder of the view control: AppendColumn(create_objects_list_extruder_column(4)); - // column 2 of the view control: - AppendBitmapColumn(" ", 2, wxDATAVIEW_CELL_INERT, int(2.5 * wxGetApp().em_unit())/*25*/, + // column ItemEditing of the view control: + AppendBitmapColumn("Editing", colEditing, wxDATAVIEW_CELL_INERT, int(2.5 * wxGetApp().em_unit())/*25*/, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } @@ -321,7 +336,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) return; } - if (col->GetTitle() == " " && GetSelectedItemsCount()<2) + if (col->GetTitle() == _(L("Editing")) && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name")) { @@ -377,7 +392,7 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_ choices.Add(wxString::Format("%d", i)); wxDataViewChoiceRenderer *c = new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL); - wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 1, + wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, colExtruder, 8*wxGetApp().em_unit()/*80*/, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); return column; } @@ -397,7 +412,7 @@ void ObjectList::update_extruder_values_for_items(const int max_extruder) else extruder = wxString::Format("%d", object->config.option("extruder")->value); - m_objects_model->SetValue(extruder, item, 1); + m_objects_model->SetValue(extruder, item, colExtruder); if (object->volumes.size() > 1) { for (auto id = 0; id < object->volumes.size(); id++) { @@ -409,7 +424,7 @@ void ObjectList::update_extruder_values_for_items(const int max_extruder) else extruder = wxString::Format("%d", object->volumes[id]->config.option("extruder")->value); - m_objects_model->SetValue(extruder, item, 1); + m_objects_model->SetValue(extruder, item, colExtruder); } } } @@ -421,7 +436,7 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count) if (printer_technology() == ptSLA) extruders_count = 1; - wxDataViewChoiceRenderer* ch_render = dynamic_cast(GetColumn(1)->GetRenderer()); + wxDataViewChoiceRenderer* ch_render = dynamic_cast(GetColumn(colExtruder)->GetRenderer()); if (ch_render->GetChoices().GetCount() - 1 == extruders_count) return; @@ -430,21 +445,21 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count) if (m_objects && extruders_count > 1) update_extruder_values_for_items(extruders_count); - // delete old 2nd column - DeleteColumn(GetColumn(1)); - // insert new created 3rd column - InsertColumn(1, create_objects_list_extruder_column(extruders_count)); + // delete old extruder column + DeleteColumn(GetColumn(colExtruder)); + // insert new created extruder column + InsertColumn(colExtruder, create_objects_list_extruder_column(extruders_count)); // set show/hide for this column set_extruder_column_hidden(extruders_count <= 1); //a workaround for a wrong last column width updating under OSX - GetColumn(2)->SetWidth(25); + GetColumn(colEditing)->SetWidth(25); m_prevent_update_extruder_in_config = false; } void ObjectList::set_extruder_column_hidden(const bool hide) const { - GetColumn(1)->SetHidden(hide); + GetColumn(colExtruder)->SetHidden(hide); } void ObjectList::update_extruder_in_config(const wxDataViewItem& item) @@ -471,7 +486,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) } wxVariant variant; - m_objects_model->GetValue(variant, item, 1); + m_objects_model->GetValue(variant, item, colExtruder); const wxString selection = variant.GetString(); if (!m_config || selection.empty()) @@ -734,21 +749,21 @@ void ObjectList::OnContextMenu(wxDataViewEvent&) wxDataViewColumn* col; const wxPoint pt = get_mouse_position_in_control(); HitTest(pt, item, col); - if (!item) #ifdef __WXOSX__ // temporary workaround for OSX - // after Yosemite OS X version, HitTest return undefined item - item = GetSelection(); - if (item) - show_context_menu(); - else - printf("undefined item\n"); - return; -#else - return; + // after Yosemite OS X version, HitTest return undefined item + if (!item) item = GetSelection(); #endif // __WXOSX__ + + if (!item) { + printf("undefined item\n"); + return; + } + const wxString title = col->GetTitle(); if (title == " ") + toggle_printable_state(item); + else if (title == _("Editing")) show_context_menu(); else if (title == _("Name")) { @@ -1013,6 +1028,11 @@ const std::vector& ObjectList::get_options_for_bundle(const wxStrin return empty; } +static bool improper_category(const std::string& category, const int extruders_cnt) +{ + return category.empty() || (extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" )); +} + void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) { auto options = get_options(is_part); @@ -1024,8 +1044,8 @@ void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const { auto const opt = config.def()->get(option); auto category = opt->category; - if (category.empty() || - (category == "Extruders" && extruders_cnt == 1)) continue; + if (improper_category(category, extruders_cnt)) + continue; const std::string& label = !opt->full_label.empty() ? opt->full_label : opt->label; std::pair option_label(option, label); @@ -1370,6 +1390,13 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu, wxWind [this](wxCommandEvent&) { split_instances(); }, "", menu, [](){return wxGetApp().plater()->can_set_instance_to_object(); }, parent); } +wxMenuItem* ObjectList::append_menu_item_printable(wxMenu* menu, wxWindow* parent) +{ + return append_menu_check_item(menu, wxID_ANY, _(L("Printable")), "", [this](wxCommandEvent&) { + wxGetApp().plater()->canvas3D()->get_selection().toggle_instance_printable_state(); + }, menu); +} + void ObjectList::append_menu_items_osx(wxMenu* menu) { append_menu_item(menu, wxID_ANY, _(L("Rename")), "", @@ -1537,7 +1564,7 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) const int extruders_cnt = extruders_count(); for (auto& it : bundle) { - if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1) + if (improper_category(it.first, extruders_cnt)) continue; append_menu_item(menu, wxID_ANY, _(it.first), "", @@ -1550,7 +1577,7 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu) m_freq_settings_fff : m_freq_settings_sla; for (auto& it : bundle_quick) { - if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1) + if (improper_category(it.first, extruders_cnt)) continue; append_menu_item(menu, wxID_ANY, wxString::Format(_(L("Quick Add Settings (%s)")), _(it.first)), "", @@ -1589,6 +1616,9 @@ void ObjectList::load_subobject(ModelVolumeType type) changed_object(obj_idx); + if (type == ModelVolumeType::MODEL_PART) + // update printable state on canvas + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx); wxDataViewItem sel_item; for (const auto& volume : volumes_info ) @@ -1712,6 +1742,9 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); changed_object(obj_idx); + if (type == ModelVolumeType::MODEL_PART) + // update printable state on canvas + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx); const auto object_item = m_objects_model->GetTopParent(GetSelection()); select_item(m_objects_model->AddVolumeChild(object_item, name, type, @@ -1755,7 +1788,19 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0) m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item)); + // If last two Instances of object is selected, show the message about impossible action + bool show_msg = false; + if (type & itInstance) { + wxDataViewItemArray instances; + m_objects_model->GetChildren(m_objects_model->GetParent(item), instances); + if (instances.Count() == 2 && IsSelected(instances[0]) && IsSelected(instances[1])) + show_msg = true; + } + m_objects_model->Delete(item); + + if (show_msg) + Slic3r::GUI::show_error(nullptr, _(L("Last instance of an object cannot be deleted."))); } void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item) @@ -1838,7 +1883,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con if (vol->is_model_part()) ++solid_cnt; if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from object."))); + Slic3r::GUI::show_error(nullptr, _(L("From Object List You can't delete the last solid part from object."))); return false; } @@ -1857,7 +1902,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con } else if (type == itInstance) { if (object->instances.size() == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object."))); + Slic3r::GUI::show_error(nullptr, _(L("Last instance of an object cannot be deleted."))); return false; } @@ -2172,7 +2217,7 @@ SettingsBundle ObjectList::get_item_settings_bundle(const DynamicPrintConfig* co for (auto& opt_key : opt_keys) { auto category = config->def()->get(opt_key)->category; - if (category.empty() || (category == "Extruders" && extruders_cnt == 1)) + if (improper_category(category, extruders_cnt)) continue; std::vector< std::string > new_category; @@ -2243,7 +2288,17 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed) // add instances to the object, if it has those if (model_object->instances.size()>1) - increase_object_instances(obj_idx, model_object->instances.size()); + { + std::vector print_idicator(model_object->instances.size()); + for (int i = 0; i < model_object->instances.size(); ++i) + print_idicator[i] = model_object->instances[i]->is_printable(); + + const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx); + m_objects_model->AddInstanceChild(object_item, print_idicator); + Expand(m_objects_model->GetInstanceRootItem(object_item)); + } + else + m_objects_model->SetPrintableState(model_object->instances[0]->is_printable() ? piPrintable : piUnprintable, obj_idx); // add settings to the object, if it has those add_settings_item(item, &model_object->config); @@ -2325,7 +2380,7 @@ void ObjectList::delete_from_model_and_list(const std::vector& it (*m_objects)[item->obj_idx]->config.has("extruder")) { const wxString extruder = wxString::Format("%d", (*m_objects)[item->obj_idx]->config.option("extruder")->value); - m_objects_model->SetValue(extruder, m_objects_model->GetItemById(item->obj_idx), 1); + m_objects_model->SetValue(extruder, m_objects_model->GetItemById(item->obj_idx), colExtruder); } wxGetApp().plater()->canvas3D()->ensure_on_bed(item->obj_idx); } @@ -2404,6 +2459,8 @@ void ObjectList::remove() for (auto& item : sels) { + if (m_objects_model->InvalidItem(item)) // item can be deleted for this moment (like last 2 Instances or Volumes) + continue; if (m_objects_model->GetParent(item) == wxDataViewItem(0)) delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1); else { @@ -2442,13 +2499,13 @@ void ObjectList::del_layer_range(const t_layer_height_range& range) select_item(selectable_item); } -double get_min_layer_height(const int extruder_idx) +static double get_min_layer_height(const int extruder_idx) { const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; return config.opt_float("min_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); } -double get_max_layer_height(const int extruder_idx) +static double get_max_layer_height(const int extruder_idx) { const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; return config.opt_float("max_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); @@ -2585,6 +2642,9 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay ranges[new_range] = config; wxDataViewItem root_item = m_objects_model->GetLayerRootItem(m_objects_model->GetItemById(obj_idx)); + // To avoid update selection after deleting of a selected item (under GTK) + // set m_prevent_list_events to true + m_prevent_list_events = true; m_objects_model->DeleteChildren(root_item); if (root_item.IsOk()) @@ -2835,6 +2895,9 @@ void ObjectList::update_selections_on_canvas() wxDataViewItemArray sels; GetSelections(sels); + // clear selection before adding new elements + selection.clear(); //OR remove_all()? + for (auto item : sels) { add_to_selection(item, selection, instance_idx, mode); @@ -3150,33 +3213,6 @@ void ObjectList::last_volume_is_deleted(const int obj_idx) volume->config.set_key_value("extruder", new ConfigOptionInt(0)); } -/* #lm_FIXME_delete_after_testing -void ObjectList::update_settings_items() -{ - m_prevent_canvas_selection_update = true; - wxDataViewItemArray sel; - GetSelections(sel); // stash selection - - wxDataViewItemArray items; - m_objects_model->GetChildren(wxDataViewItem(0), items); - - for (auto& item : items) { - const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item); - select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); - - // If settings item was deleted from the list, - // it's need to be deleted from selection array, if it was there - if (settings_item != m_objects_model->GetSettingsItem(item) && - sel.Index(settings_item) != wxNOT_FOUND) { - sel.Remove(settings_item); - } - } - - // restore selection: - SetSelections(sel); - m_prevent_canvas_selection_update = false; -} -*/ void ObjectList::update_and_show_object_settings_item() { const wxDataViewItem item = GetSelection(); @@ -3311,7 +3347,8 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set } // Add new object to the object_list - add_object_to_list(m_objects->size() - 1); + const size_t new_obj_indx = static_cast(m_objects->size() - 1); + add_object_to_list(new_obj_indx); for (std::set::const_reverse_iterator it = inst_idxs.rbegin(); it != inst_idxs.rend(); ++it) { @@ -3319,12 +3356,17 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set del_subobject_from_object(obj_idx, *it, itInstance); delete_instance_from_list(obj_idx, *it); } + + // update printable state for new volumes on canvas3D + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object(new_obj_indx); } void ObjectList::instances_to_separated_objects(const int obj_idx) { const int inst_cnt = (*m_objects)[obj_idx]->instances.size(); + std::vector object_idxs; + for (int i = inst_cnt-1; i > 0 ; i--) { // create new object from initial @@ -3338,12 +3380,17 @@ void ObjectList::instances_to_separated_objects(const int obj_idx) } // Add new object to the object_list - add_object_to_list(m_objects->size() - 1); + const size_t new_obj_indx = static_cast(m_objects->size() - 1); + add_object_to_list(new_obj_indx); + object_idxs.push_back(new_obj_indx); // delete current instance from the initial object del_subobject_from_object(obj_idx, i, itInstance); delete_instance_from_list(obj_idx, i); } + + // update printable state for new volumes on canvas3D + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(object_idxs); } void ObjectList::split_instances() @@ -3398,7 +3445,7 @@ void ObjectList::rename_item() // The icon can't be edited so get its old value and reuse it. wxVariant valueOld; - m_objects_model->GetValue(valueOld, item, 0); + m_objects_model->GetValue(valueOld, item, colName); DataViewBitmapText bmpText; bmpText << valueOld; @@ -3408,7 +3455,7 @@ void ObjectList::rename_item() wxVariant value; value << bmpText; - m_objects_model->SetValue(value, item, 0); + m_objects_model->SetValue(value, item, colName); m_objects_model->ItemChanged(item); update_name_in_model(item); @@ -3449,9 +3496,10 @@ void ObjectList::msw_rescale() // update min size !!! A width of control shouldn't be a wxDefaultCoord SetMinSize(wxSize(1, 15 * em)); - GetColumn(0)->SetWidth(19 * em); - GetColumn(1)->SetWidth( 8 * em); - GetColumn(2)->SetWidth( 2 * em); + GetColumn(colName)->SetWidth(19 * em); + GetColumn(colPrint)->SetWidth( 2 * em); + GetColumn(colExtruder)->SetWidth( 8 * em); + GetColumn(colEditing)->SetWidth( 2 * em); // rescale all icons, used by ObjectList msw_rescale_icons(); @@ -3472,18 +3520,18 @@ void ObjectList::msw_rescale() void ObjectList::ItemValueChanged(wxDataViewEvent &event) { - if (event.GetColumn() == 0) + if (event.GetColumn() == colName) update_name_in_model(event.GetItem()); - else if (event.GetColumn() == 1) + else if (event.GetColumn() == colExtruder) update_extruder_in_config(event.GetItem()); } void ObjectList::OnEditingDone(wxDataViewEvent &event) { - if (event.GetColumn() != 0) + if (event.GetColumn() != colName) return; - const auto renderer = dynamic_cast(GetColumn(0)->GetRenderer()); + const auto renderer = dynamic_cast(GetColumn(colName)->GetRenderer()); if (renderer->WasCanceled()) wxTheApp->CallAfter([this]{ @@ -3565,7 +3613,7 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const /* We can change extruder for Object/Volume only. * So, if Instance is selected, get its Object item and change it */ - m_objects_model->SetValue(extruder_str, type & itInstance ? m_objects_model->GetTopParent(item) : item, 1); + m_objects_model->SetValue(extruder_str, type & itInstance ? m_objects_model->GetTopParent(item) : item, colExtruder); const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) : m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); @@ -3588,18 +3636,69 @@ void ObjectList::update_after_undo_redo() m_objects_model->DeleteAll(); size_t obj_idx = 0; + std::vector obj_idxs; + obj_idxs.reserve(m_objects->size()); while (obj_idx < m_objects->size()) { add_object_to_list(obj_idx, false); + obj_idxs.push_back(obj_idx); ++obj_idx; } -#ifndef __WXOSX__ -// selection_changed(); -#endif /* __WXOSX__ */ - update_selections(); m_prevent_canvas_selection_update = false; + + // update printable states on canvas + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs); + // update scene + wxGetApp().plater()->update(); +} + +void ObjectList::update_printable_state(int obj_idx, int instance_idx) +{ + ModelObject* object = (*m_objects)[obj_idx]; + + const PrintIndicator printable = object->instances[instance_idx]->printable ? piPrintable : piUnprintable; + if (object->instances.size() == 1) + instance_idx = -1; + + m_objects_model->SetPrintableState(printable, obj_idx, instance_idx); +} + +void ObjectList::toggle_printable_state(wxDataViewItem item) +{ + const ItemType type = m_objects_model->GetItemType(item); + if (!(type&(itObject|itInstance/*|itVolume*/))) + return; + + if (type & itObject) + { + const int obj_idx = m_objects_model->GetObjectIdByItem(item); + ModelObject* object = (*m_objects)[obj_idx]; + + // get object's printable and change it + const bool printable = !m_objects_model->IsPrintable(item); + + const wxString snapshot_text = wxString::Format("%s %s", + printable ? _(L("Set Printable")) : _(L("Set Unprintable")), + object->name); + take_snapshot(snapshot_text); + + // set printable value for all instances in object + for (auto inst : object->instances) + inst->printable = printable; + + // update printable state on canvas + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx); + + // update printable state in ObjectList + m_objects_model->SetObjectPrintableState(printable ? piPrintable : piUnprintable , item); + } + else + wxGetApp().plater()->canvas3D()->get_selection().toggle_instance_printable_state(); + + // update scene + wxGetApp().plater()->update(); } ModelObject* ObjectList::object(const int obj_idx) const @@ -3611,4 +3710,4 @@ ModelObject* ObjectList::object(const int obj_idx) const } } //namespace GUI -} //namespace Slic3r \ No newline at end of file +} //namespace Slic3r diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 39558d1c54..bdec060818 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -225,6 +225,7 @@ public: wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent); + wxMenuItem* append_menu_item_printable(wxMenu* menu, wxWindow* parent); void append_menu_items_osx(wxMenu* menu); wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu); void append_menu_item_export_stl(wxMenu* menu) const ; @@ -348,6 +349,9 @@ public: void msw_rescale(); void update_after_undo_redo(); + //update printable state for item from objects model + void update_printable_state(int obj_idx, int instance_idx); + void toggle_printable_state(wxDataViewItem item); private: #ifdef __WXOSX__ diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 36354ab240..64218d08f6 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -176,6 +176,7 @@ Preview::Preview( , m_checkbox_retractions(nullptr) , m_checkbox_unretractions(nullptr) , m_checkbox_shells(nullptr) + , m_checkbox_legend(nullptr) , m_config(config) , m_process(process) , m_gcode_preview_data(gcode_preview_data) @@ -252,6 +253,9 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view m_checkbox_unretractions = new wxCheckBox(this, wxID_ANY, _(L("Unretractions"))); m_checkbox_shells = new wxCheckBox(this, wxID_ANY, _(L("Shells"))); + m_checkbox_legend = new wxCheckBox(this, wxID_ANY, _(L("Legend"))); + m_checkbox_legend->SetValue(true); + wxBoxSizer* top_sizer = new wxBoxSizer(wxHORIZONTAL); top_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); top_sizer->Add(m_double_slider_sizer, 0, wxEXPAND, 0); @@ -270,6 +274,8 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view bottom_sizer->Add(m_checkbox_unretractions, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(10); bottom_sizer->Add(m_checkbox_shells, 0, wxEXPAND | wxALL, 5); + bottom_sizer->AddSpacer(20); + bottom_sizer->Add(m_checkbox_legend, 0, wxEXPAND | wxALL, 5); wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(top_sizer, 1, wxALL | wxEXPAND, 0); @@ -442,6 +448,7 @@ void Preview::bind_event_handlers() m_checkbox_retractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this); m_checkbox_unretractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this); m_checkbox_shells->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this); + m_checkbox_legend->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_legend, this); } void Preview::unbind_event_handlers() @@ -453,6 +460,7 @@ void Preview::unbind_event_handlers() m_checkbox_retractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this); m_checkbox_unretractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this); m_checkbox_shells->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this); + m_checkbox_legend->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_legend, this); } void Preview::show_hide_ui_elements(const std::string& what) @@ -464,6 +472,7 @@ void Preview::show_hide_ui_elements(const std::string& what) m_checkbox_retractions->Enable(enable); m_checkbox_unretractions->Enable(enable); m_checkbox_shells->Enable(enable); + m_checkbox_legend->Enable(enable); enable = (what != "none"); m_label_view_type->Enable(enable); @@ -476,6 +485,7 @@ void Preview::show_hide_ui_elements(const std::string& what) m_checkbox_retractions->Show(visible); m_checkbox_unretractions->Show(visible); m_checkbox_shells->Show(visible); + m_checkbox_legend->Show(visible); m_label_view_type->Show(visible); m_choice_view_type->Show(visible); } @@ -542,6 +552,12 @@ void Preview::on_checkbox_shells(wxCommandEvent& evt) refresh_print(); } +void Preview::on_checkbox_legend(wxCommandEvent& evt) +{ + m_canvas->enable_legend_texture(m_checkbox_legend->IsChecked()); + m_canvas_widget->Refresh(); +} + void Preview::update_view_type() { const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config; @@ -702,6 +718,11 @@ void Preview::update_double_slider_from_canvas(wxKeyEvent& event) m_slider->SetHigherValue(new_pos); if (event.ShiftDown() || m_slider->is_one_layer()) m_slider->SetLowerValue(m_slider->GetHigherValue()); } + else if (key == 'L') { + m_checkbox_legend->SetValue(!m_checkbox_legend->GetValue()); + auto evt = wxCommandEvent(); + on_checkbox_legend(evt); + } else if (key == 'S') m_slider->ChangeOneLayerLock(); else diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index e86d0e4306..b626bd7bde 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -80,6 +80,7 @@ class Preview : public wxPanel wxCheckBox* m_checkbox_retractions; wxCheckBox* m_checkbox_unretractions; wxCheckBox* m_checkbox_shells; + wxCheckBox* m_checkbox_legend; DynamicPrintConfig* m_config; BackgroundSlicingProcess* m_process; @@ -147,6 +148,7 @@ private: void on_checkbox_retractions(wxCommandEvent& evt); void on_checkbox_unretractions(wxCommandEvent& evt); void on_checkbox_shells(wxCommandEvent& evt); + void on_checkbox_legend(wxCommandEvent& evt); // Create/Update/Reset double slider on 3dPreview void create_double_slider(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index a650746468..29e5e5686d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -29,19 +29,21 @@ GLGizmoBase::Grabber::Grabber() color[0] = 1.0f; color[1] = 1.0f; color[2] = 1.0f; + color[3] = 1.0f; } void GLGizmoBase::Grabber::render(bool hover, float size) const { - float render_color[3]; + float render_color[4]; if (hover) { render_color[0] = 1.0f - color[0]; render_color[1] = 1.0f - color[1]; render_color[2] = 1.0f - color[2]; + render_color[3] = color[3]; } else - ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); + ::memcpy((void*)render_color, (const void*)color, 4 * sizeof(float)); render(size, render_color, true); } @@ -63,7 +65,7 @@ void GLGizmoBase::Grabber::render(float size, const float* render_color, bool us if (use_lighting) glsafe(::glEnable(GL_LIGHTING)); - glsafe(::glColor3fv(render_color)); + glsafe(::glColor4fv(render_color)); glsafe(::glPushMatrix()); glsafe(::glTranslated(center(0), center(1), center(2))); @@ -144,9 +146,9 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u , m_dragging(false) , m_imgui(wxGetApp().imgui()) { - ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); - ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); - ::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 3 * sizeof(float)); + ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 4 * sizeof(float)); + ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 4 * sizeof(float)); + ::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 4 * sizeof(float)); } void GLGizmoBase::set_hover_id(int id) @@ -161,7 +163,7 @@ void GLGizmoBase::set_hover_id(int id) void GLGizmoBase::set_highlight_color(const float* color) { if (color != nullptr) - ::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); + ::memcpy((void*)m_highlight_color, (const void*)color, 4 * sizeof(float)); } void GLGizmoBase::enable_grabber(unsigned int id) @@ -210,7 +212,7 @@ void GLGizmoBase::update(const UpdateData& data) on_update(data); } -std::array GLGizmoBase::picking_color_component(unsigned int id) const +std::array GLGizmoBase::picking_color_component(unsigned int id) const { static const float INV_255 = 1.0f / 255.0f; @@ -220,9 +222,12 @@ std::array GLGizmoBase::picking_color_component(unsigned int id) const id -= m_group_id; // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() - return std::array { (float)((id >> 0) & 0xff) * INV_255, // red - (float)((id >> 8) & 0xff) * INV_255, // green - (float)((id >> 16) & 0xff) * INV_255 }; // blue + return std::array { + float((id >> 0) & 0xff) * INV_255, // red + float((id >> 8) & 0xff) * INV_255, // green + float((id >> 16) & 0xff) * INV_255, // blue + float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff))* INV_255 // checksum for validating against unwanted alpha blending and multi sampling + }; } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const @@ -247,10 +252,11 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { if (m_grabbers[i].enabled) { - std::array color = picking_color_component(i); + std::array color = picking_color_component(i); m_grabbers[i].color[0] = color[0]; m_grabbers[i].color[1] = color[1]; m_grabbers[i].color[2] = color[2]; + m_grabbers[i].color[3] = color[3]; m_grabbers[i].render_for_picking(mean_size); } } @@ -267,5 +273,20 @@ std::string GLGizmoBase::format(float value, unsigned int decimals) const return Slic3r::string_printf("%.*f", decimals, value); } +// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components +// were not interpolated by alpha blending or multi sampling. +unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue) +{ + // 8 bit hash for the color + unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff; + // Increase enthropy by a bit reversal + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + // Flip every second bit to increase the enthropy even more. + b ^= 0x55; + return b; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index b84442b94d..7b73c62c25 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -21,11 +21,11 @@ class ModelObject; namespace GUI { -static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f }; -static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f }; -static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f }; -static const float AXES_COLOR[3][3] = { { 0.75f, 0.0f, 0.0f }, { 0.0f, 0.75f, 0.0f }, { 0.0f, 0.0f, 0.75f } }; -static const float CONSTRAINED_COLOR[3] = { 0.5f, 0.5f, 0.5f }; +static const float DEFAULT_BASE_COLOR[4] = { 0.625f, 0.625f, 0.625f, 1.0f }; +static const float DEFAULT_DRAG_COLOR[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float DEFAULT_HIGHLIGHT_COLOR[4] = { 1.0f, 0.38f, 0.0f, 1.0f }; +static const float AXES_COLOR[][4] = { { 0.75f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.75f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.75f, 1.0f } }; +static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; @@ -48,7 +48,7 @@ protected: Vec3d center; Vec3d angles; - float color[3]; + float color[4]; bool enabled; bool dragging; @@ -94,9 +94,9 @@ protected: unsigned int m_sprite_id; int m_hover_id; bool m_dragging; - float m_base_color[3]; - float m_drag_color[3]; - float m_highlight_color[3]; + float m_base_color[4]; + float m_drag_color[4]; + float m_highlight_color[4]; mutable std::vector m_grabbers; ImGuiWrapper* m_imgui; @@ -166,7 +166,7 @@ protected: // Returns the picking color for the given id, based on the BASE_ID constant // No check is made for clashing with other picking color (i.e. GLVolumes) - std::array picking_color_component(unsigned int id) const; + std::array picking_color_component(unsigned int id) const; void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(float size) const; void render_grabbers_for_picking(const BoundingBoxf3& box) const; @@ -175,6 +175,10 @@ protected: std::string format(float value, unsigned int decimals) const; }; +// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components +// were not interpolated by alpha blending or multi sampling. +extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue); + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 39399fc0d3..481bec9562 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -17,7 +17,7 @@ namespace GUI { const double GLGizmoCut::Offset = 10.0; const double GLGizmoCut::Margin = 20.0; -const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 }; +const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0, 1.0 }; GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 5bfeda526a..6e5738a422 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -11,7 +11,7 @@ class GLGizmoCut : public GLGizmoBase { static const double Offset; static const double Margin; - static const std::array GrabberColor; + static const std::array GrabberColor; mutable double m_cut_z; double m_start_z; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 5a42cbd31f..9fae8893ac 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -115,7 +115,7 @@ void GLGizmoFlatten::on_render_for_picking() const const_cast(this)->update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { - glsafe(::glColor3fv(picking_color_component(i).data())); + glsafe(::glColor4fv(picking_color_component(i).data())); ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 11bdcd4f83..862ffe41af 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -104,15 +104,15 @@ void GLGizmoMove3D::on_render() const // x axis m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2)); - ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 4 * sizeof(float)); // y axis m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2)); - ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 4 * sizeof(float)); // z axis m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset); - ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 4 * sizeof(float)); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); @@ -123,7 +123,7 @@ void GLGizmoMove3D::on_render() const { if (m_grabbers[i].enabled) { - glsafe(::glColor3fv(AXES_COLOR[i])); + glsafe(::glColor4fv(AXES_COLOR[i])); ::glBegin(GL_LINES); ::glVertex3dv(center.data()); ::glVertex3dv(m_grabbers[i].center.data()); @@ -142,7 +142,7 @@ void GLGizmoMove3D::on_render() const else { // draw axis - glsafe(::glColor3fv(AXES_COLOR[m_hover_id])); + glsafe(::glColor4fv(AXES_COLOR[m_hover_id])); ::glBegin(GL_LINES); ::glVertex3dv(center.data()); ::glVertex3dv(m_grabbers[m_hover_id].center.data()); @@ -220,19 +220,20 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); - float color[3]; - ::memcpy((void*)color, (const void*)m_grabbers[axis].color, 3 * sizeof(float)); + float color[4]; + ::memcpy((void*)color, (const void*)m_grabbers[axis].color, 4 * sizeof(float)); if (!picking && (m_hover_id != -1)) { color[0] = 1.0f - color[0]; color[1] = 1.0f - color[1]; color[2] = 1.0f - color[2]; + color[3] = color[3]; } if (!picking) glsafe(::glEnable(GL_LIGHTING)); - glsafe(::glColor3fv(color)); + glsafe(::glColor4fv(color)); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2))); if (axis == X) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index f481bb5d74..9a2c72633e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -155,7 +155,7 @@ void GLGizmoRotate::on_render() const transform_to_local(selection); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); - glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); + glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); render_circle(); @@ -166,7 +166,7 @@ void GLGizmoRotate::on_render() const render_reference_radius(); } - glsafe(::glColor3fv(m_highlight_color)); + glsafe(::glColor4fv(m_highlight_color)); if (m_hover_id != -1) render_angle(); @@ -287,14 +287,14 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); m_grabbers[0].angles(2) = m_angle; - glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); + glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); ::glBegin(GL_LINES); ::glVertex3f(0.0f, 0.0f, 0.0f); ::glVertex3dv(m_grabbers[0].center.data()); glsafe(::glEnd()); - ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 4 * sizeof(float)); render_grabbers(box); } @@ -306,8 +306,8 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size); - float color[3]; - ::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float)); + float color[4]; + ::memcpy((void*)color, (const void*)m_grabbers[0].color, 4 * sizeof(float)); if (!picking && (m_hover_id != -1)) { color[0] = 1.0f - color[0]; @@ -318,7 +318,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick if (!picking) glsafe(::glEnable(GL_LIGHTING)); - glsafe(::glColor3fv(color)); + glsafe(::glColor4fv(color)); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2))); glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 7dc38b8011..bf540cb00c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -172,20 +172,20 @@ void GLGizmoScale3D::on_render() const // x axis m_grabbers[0].center = m_transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x; m_grabbers[1].center = m_transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x; - ::memcpy((void*)m_grabbers[0].color, (ctrl_down && (m_hover_id == 1)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[1].color, (ctrl_down && (m_hover_id == 0)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[0].color, (ctrl_down && (m_hover_id == 1)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 4 * sizeof(float)); + ::memcpy((void*)m_grabbers[1].color, (ctrl_down && (m_hover_id == 0)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 4 * sizeof(float)); // y axis m_grabbers[2].center = m_transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y; m_grabbers[3].center = m_transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y; - ::memcpy((void*)m_grabbers[2].color, (ctrl_down && (m_hover_id == 3)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[3].color, (ctrl_down && (m_hover_id == 2)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[2].color, (ctrl_down && (m_hover_id == 3)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 4 * sizeof(float)); + ::memcpy((void*)m_grabbers[3].color, (ctrl_down && (m_hover_id == 2)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 4 * sizeof(float)); // z axis m_grabbers[4].center = m_transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z; m_grabbers[5].center = m_transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z; - ::memcpy((void*)m_grabbers[4].color, (ctrl_down && (m_hover_id == 5)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[5].color, (ctrl_down && (m_hover_id == 4)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[4].color, (ctrl_down && (m_hover_id == 5)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 4 * sizeof(float)); + ::memcpy((void*)m_grabbers[5].color, (ctrl_down && (m_hover_id == 4)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 4 * sizeof(float)); // uniform m_grabbers[6].center = m_transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y; @@ -194,7 +194,7 @@ void GLGizmoScale3D::on_render() const m_grabbers[9].center = m_transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y; for (int i = 6; i < 10; ++i) { - ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 4 * sizeof(float)); } // sets grabbers orientation @@ -214,20 +214,20 @@ void GLGizmoScale3D::on_render() const // draw connections if (m_grabbers[0].enabled && m_grabbers[1].enabled) { - glsafe(::glColor3fv(m_grabbers[0].color)); + glsafe(::glColor4fv(m_grabbers[0].color)); render_grabbers_connection(0, 1); } if (m_grabbers[2].enabled && m_grabbers[3].enabled) { - glsafe(::glColor3fv(m_grabbers[2].color)); + glsafe(::glColor4fv(m_grabbers[2].color)); render_grabbers_connection(2, 3); } if (m_grabbers[4].enabled && m_grabbers[5].enabled) { - glsafe(::glColor3fv(m_grabbers[4].color)); + glsafe(::glColor4fv(m_grabbers[4].color)); render_grabbers_connection(4, 5); } - glsafe(::glColor3fv(m_base_color)); + glsafe(::glColor4fv(m_base_color)); render_grabbers_connection(6, 7); render_grabbers_connection(7, 8); render_grabbers_connection(8, 9); @@ -238,7 +238,7 @@ void GLGizmoScale3D::on_render() const else if ((m_hover_id == 0) || (m_hover_id == 1)) { // draw connection - glsafe(::glColor3fv(m_grabbers[0].color)); + glsafe(::glColor4fv(m_grabbers[0].color)); render_grabbers_connection(0, 1); // draw grabbers m_grabbers[0].render(true, grabber_mean_size); @@ -247,7 +247,7 @@ void GLGizmoScale3D::on_render() const else if ((m_hover_id == 2) || (m_hover_id == 3)) { // draw connection - glsafe(::glColor3fv(m_grabbers[2].color)); + glsafe(::glColor4fv(m_grabbers[2].color)); render_grabbers_connection(2, 3); // draw grabbers m_grabbers[2].render(true, grabber_mean_size); @@ -256,7 +256,7 @@ void GLGizmoScale3D::on_render() const else if ((m_hover_id == 4) || (m_hover_id == 5)) { // draw connection - glsafe(::glColor3fv(m_grabbers[4].color)); + glsafe(::glColor4fv(m_grabbers[4].color)); render_grabbers_connection(4, 5); // draw grabbers m_grabbers[4].render(true, grabber_mean_size); @@ -265,7 +265,7 @@ void GLGizmoScale3D::on_render() const else if (m_hover_id >= 6) { // draw connection - glsafe(::glColor3fv(m_drag_color)); + glsafe(::glColor4fv(m_drag_color)); render_grabbers_connection(6, 7); render_grabbers_connection(7, 8); render_grabbers_connection(8, 9); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 19b0c791ca..4976520fa5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -286,7 +286,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glTranslated(0.0, 0.0, m_z_shift)); glsafe(::glMultMatrixd(instance_matrix.data())); - float render_color[3]; + float render_color[4]; size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); for (size_t i = 0; i < cache_size; ++i) { @@ -298,12 +298,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // First decide about the color of the point. if (picking) { - std::array color = picking_color_component(i); + std::array color = picking_color_component(i); render_color[0] = color[0]; render_color[1] = color[1]; render_color[2] = color[2]; + render_color[3] = color[3]; } else { + render_color[3] = 1.f; if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active render_color[0] = 0.f; render_color[1] = 1.0f; @@ -320,7 +322,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f; } } - glsafe(::glColor3fv(render_color)); + glsafe(::glColor4fv(render_color)); float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f}; glsafe(::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive)); @@ -422,9 +424,9 @@ void GLGizmoSlaSupports::update_mesh() -// Unprojects the mouse position on the mesh and return the hit point and normal of the facet. -// The function throws if no intersection if found. -std::pair GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) +// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal +// Return false if no intersection was found, true otherwise. +bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair& pos_and_normal) { // if the gizmo doesn't have the V, F structures for igl, calculate them first: if (m_its == nullptr) @@ -457,7 +459,7 @@ std::pair GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse MapMatrixXfUnaligned(m_its->vertices.front().data(), m_its->vertices.size(), 3), MapMatrixXiUnaligned(m_its->indices.front().data(), m_its->indices.size(), 3), point1.cast(), (point2-point1).cast(), hits)) - throw std::invalid_argument("unproject_on_mesh(): No intersection found."); + return false; // no intersection found std::sort(hits.begin(), hits.end(), [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; }); @@ -481,14 +483,12 @@ std::pair GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse if (i==hits.size() || (hits.size()-i) % 2 != 0) { // All hits are either clipped, or there is an odd number of unclipped // hits - meaning the nearest must be from inside the mesh. - throw std::invalid_argument("unproject_on_mesh(): No intersection found."); + return false; } // Calculate and return both the point and the facet normal. - return std::make_pair( - result, - a.cross(b) - ); + pos_and_normal = std::make_pair(result, a.cross(b)); + return true; } // Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event. @@ -526,16 +526,15 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous // If there is some selection, don't add new point and deselect everything instead. if (m_selection_empty) { - try { - std::pair pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws + std::pair pos_and_normal; + if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection wxGetApp().plater()->take_snapshot(_(L("Add support point"))); m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); m_parent.set_as_dirty(); m_wait_for_up_event = true; } - catch (...) { // not clicked on object + else return false; - } } else select_point(NoPoints); @@ -739,10 +738,8 @@ void GLGizmoSlaSupports::on_update(const UpdateData& data) else { if (m_hover_id != -1 && (! m_editing_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { std::pair pos_and_normal; - try { - pos_and_normal = unproject_on_mesh(data.mouse_pos.cast()); - } - catch (...) { return; } + if (! unproject_on_mesh(data.mouse_pos.cast(), pos_and_normal)) + return; m_editing_cache[m_hover_id].support_point.pos = pos_and_normal.first; m_editing_cache[m_hover_id].support_point.is_new_island = false; m_editing_cache[m_hover_id].normal = pos_and_normal.second; @@ -1448,4 +1445,4 @@ SlaGizmoHelpDialog::SlaGizmoHelpDialog() } // namespace GUI -} // namespace Slic3r \ No newline at end of file +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index fb312e6644..fa3facf4b5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -32,7 +32,7 @@ private: int m_active_instance = -1; float m_active_instance_bb_radius; // to cache the bb mutable float m_z_shift = 0.f; - std::pair unproject_on_mesh(const Vec2d& mouse_pos); + bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair& pos_and_normal); const float RenderPointScale = 1.f; diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index f58266a5df..8e4d9eebfa 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -354,7 +354,7 @@ bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool ( ImGui::Selectable(item_text, i < hovered); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(item_text); + ImGui::SetTooltip("%s", item_text); hovered = i; is_hovered = true; } diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 955c4b60b9..08d46444c4 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -6,23 +6,23 @@ #include "GUI_App.hpp" #include "wxExtensions.hpp" -namespace Slic3r { +namespace Slic3r { namespace GUI { KBShortcutsDialog::KBShortcutsDialog() - : DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Keyboard Shortcuts")), + : DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Keyboard Shortcuts")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - auto main_sizer = new wxBoxSizer(wxVERTICAL); + auto main_sizer = new wxBoxSizer(wxVERTICAL); // logo m_logo_bmp = ScalableBitmap(this, "PrusaSlicer_32px.png", 32); // fonts const wxFont& font = wxGetApp().normal_font(); - const wxFont& bold_font = wxGetApp().bold_font(); + const wxFont& bold_font = wxGetApp().bold_font(); SetFont(font); wxFont head_font = bold_font; @@ -78,17 +78,17 @@ KBShortcutsDialog::KBShortcutsDialog() grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL); } } - + wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); this->SetEscapeId(wxID_OK); this->Bind(wxEVT_BUTTON, &KBShortcutsDialog::onCloseDialog, this, wxID_OK); main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 15); - + this->Bind(wxEVT_LEFT_DOWN, &KBShortcutsDialog::onCloseDialog, this); - SetSizer(main_sizer); - main_sizer->SetSizeHints(this); + SetSizer(main_sizer); + main_sizer->SetSizeHints(this); } void KBShortcutsDialog::fill_shortcuts() @@ -132,6 +132,7 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.reserve(20); plater_shortcuts.push_back(Shortcut("A", L("Arrange"))); + plater_shortcuts.push_back(Shortcut("Shift+A", L("Arrange selection"))); plater_shortcuts.push_back(Shortcut(ctrl+"A", L("Select All objects"))); plater_shortcuts.push_back(Shortcut("Del", L("Delete selected"))); plater_shortcuts.push_back(Shortcut(ctrl+"Del", L("Delete All"))); @@ -163,10 +164,10 @@ void KBShortcutsDialog::fill_shortcuts() // Shortcuts gizmo_shortcuts; // gizmo_shortcuts.reserve(2); -// +// // gizmo_shortcuts.push_back(Shortcut("Shift+", L("Press to snap by 5% in Gizmo Scale\n or by 1mm in Gizmo Move"))); // gizmo_shortcuts.push_back(Shortcut(alt, L("Press to scale or rotate selected objects around their own center"))); -// +// // m_full_shortcuts.push_back(std::make_pair(_(L("Gizmo Shortcuts")), std::make_pair(gizmo_shortcuts, 1))); @@ -177,6 +178,7 @@ void KBShortcutsDialog::fill_shortcuts() preview_shortcuts.push_back(Shortcut(L("Arrow Down"), L("Lower Layer"))); preview_shortcuts.push_back(Shortcut("U", L("Upper Layer"))); preview_shortcuts.push_back(Shortcut("D", L("Lower Layer"))); + preview_shortcuts.push_back(Shortcut("L", L("Show/Hide (L)egend"))); m_full_shortcuts.push_back(std::make_pair(_(L("Preview Shortcuts")), std::make_pair(preview_shortcuts, szLeft))); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index d3da148a05..b0945aea83 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -279,6 +279,18 @@ bool MainFrame::can_export_gcode() const return true; } +bool MainFrame::can_send_gcode() const +{ + if (m_plater == nullptr) + return false; + + if (m_plater->model().objects.empty()) + return false; + + const auto print_host_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option("print_host"); + return print_host_opt != nullptr && !print_host_opt->value.empty(); +} + bool MainFrame::can_slice() const { bool bg_proc = wxGetApp().app_config->get("background_processing") == "1"; @@ -451,6 +463,10 @@ void MainFrame::init_menubar() [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, menu_icon("export_gcode"), nullptr, [this](){return can_export_gcode(); }, this); m_changeable_menu_items.push_back(item_export_gcode); + wxMenuItem* item_send_gcode = append_menu_item(export_menu, wxID_ANY, _(L("S&end G-code")) + dots +"\tCtrl+Shift+G", _(L("Send to print current plate as G-code")), + [this](wxCommandEvent&) { if (m_plater) m_plater->send_gcode(); }, menu_icon("export_gcode"), nullptr, + [this](){return can_send_gcode(); }, this); + m_changeable_menu_items.push_back(item_send_gcode); export_menu->AppendSeparator(); append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")), [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater"), nullptr, @@ -689,7 +705,8 @@ void MainFrame::update_menubar() { const bool is_fff = plater()->printer_technology() == ptFFF; - m_changeable_menu_items[miExport] ->SetItemLabel((is_fff ? _(L("Export &G-code")) : _(L("Export")) ) + dots + "\tCtrl+G"); + m_changeable_menu_items[miExport] ->SetItemLabel((is_fff ? _(L("Export &G-code")) : _(L("E&xport")) ) + dots + "\tCtrl+G"); + m_changeable_menu_items[miSend] ->SetItemLabel((is_fff ? _(L("S&end G-code")) : _(L("S&end to print"))) + dots + "\tCtrl+Shift+G"); m_changeable_menu_items[miMaterialTab] ->SetItemLabel((is_fff ? _(L("&Filament Settings Tab")) : _(L("Mate&rial Settings Tab"))) + "\tCtrl+3"); m_changeable_menu_items[miMaterialTab] ->SetBitmap(create_scaled_bitmap(this, menu_icon(is_fff ? "spool": "resin"))); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index a41f33824d..5d34be48ef 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -67,6 +67,7 @@ class MainFrame : public DPIFrame bool can_export_model() const; bool can_export_supports() const; bool can_export_gcode() const; + bool can_send_gcode() const; bool can_slice() const; bool can_change_view() const; bool can_select() const; @@ -79,6 +80,7 @@ class MainFrame : public DPIFrame enum MenuItems { // FFF SLA miExport = 0, // Export G-code Export + miSend, // Send G-code Send to print miMaterialTab, // Filament Settings Material Settings }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7c494b4dcd..99f63da8a1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -256,7 +256,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * evt.StopPropagation(); if (marker == LABEL_ITEM_CONFIG_WIZARD) wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); - } else if ( this->last_selected != selected_item || + } else if ( this->last_selected != selected_item || wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) { this->last_selected = selected_item; evt.SetInt(this->preset_type); @@ -265,7 +265,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * evt.StopPropagation(); } }); - + if (preset_type == Slic3r::Preset::TYPE_FILAMENT) { Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) { @@ -282,7 +282,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * event.Skip(); return; } - + // Swallow the mouse click and open the color picker. // get current color @@ -302,7 +302,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * { colors->values[extruder_idx] = dialog->GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX); - DynamicPrintConfig cfg_new = *cfg; + DynamicPrintConfig cfg_new = *cfg; cfg_new.set_key_value("extruder_colour", colors); wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new); @@ -328,14 +328,14 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * wxGetApp().tab_panel()->ChangeSelection(page_id); - /* In a case of a multi-material printing, for editing another Filament Preset - * it's needed to select this preset for the "Filament settings" Tab + /* In a case of a multi-material printing, for editing another Filament Preset + * it's needed to select this preset for the "Filament settings" Tab */ - if (preset_type == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1) + if (preset_type == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1) { const std::string& selected_preset = GetString(GetSelection()).ToUTF8().data(); - // Call select_preset() only if there is new preset and not just modified + // Call select_preset() only if there is new preset and not just modified if ( !boost::algorithm::ends_with(selected_preset, Preset::suffix_modified()) ) tab->select_preset(selected_preset); } @@ -459,7 +459,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : tab_print->update_dirty(); }; - + Line line = Line { "", "" }; ConfigOptionDef support_def; @@ -491,7 +491,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : m_og->append_line(line); - + line = Line { "", "" }; option = m_og->get_option("fill_density"); @@ -533,7 +533,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : } })); - auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_transparent.png", wxEmptyString, + auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_transparent.png", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW); sizer->Add(btn , 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, int(0.3 * wxGetApp().em_unit())); @@ -556,14 +556,21 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : Tab* tab = wxGetApp().get_tab(Preset::TYPE_SLA_PRINT); if (!tab) return; - if (opt_key == "pad_enable") { - tab->set_value(opt_key, value); - tab->update(); + DynamicPrintConfig new_conf = *config_sla; + if (opt_key == "pad") { + const wxString& selection = boost::any_cast(value); + + const bool pad_enable = selection == _("None") ? false : true; + new_conf.set_key_value("pad_enable", new ConfigOptionBool(pad_enable)); + + if (selection == _("Below object")) + new_conf.set_key_value("pad_zero_elevation", new ConfigOptionBool(false)); + else if (selection == _("Around object")) + new_conf.set_key_value("pad_zero_elevation", new ConfigOptionBool(true)); } else { assert(opt_key == "support"); - DynamicPrintConfig new_conf = *config_sla; const wxString& selection = boost::any_cast(value); const bool supports_enable = selection == _("None") ? false : true; @@ -573,10 +580,9 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : new_conf.set_key_value("support_buildplate_only", new ConfigOptionBool(false)); else if (selection == _("Support on build plate only")) new_conf.set_key_value("support_buildplate_only", new ConfigOptionBool(true)); - - tab->load_config(new_conf); } + tab->load_config(new_conf); tab->update_dirty(); }; @@ -588,15 +594,25 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : support_def_sla.enum_labels.erase(support_def_sla.enum_labels.begin() + 2); option = Option(support_def_sla, "support"); option.opt.full_width = true; - line.append_option(option); + line.append_option(option); line.append_widget(empty_widget); m_og_sla->append_line(line); line = Line{ "", "" }; - option = m_og_sla->get_option("pad_enable"); - option.opt.sidetext = " "; + ConfigOptionDef pad_def; + pad_def.label = L("Pad"); + pad_def.type = coStrings; + pad_def.gui_type = "select_open"; + pad_def.tooltip = L("Select what kind of pad do you need"); + pad_def.enum_labels.push_back(L("None")); + pad_def.enum_labels.push_back(L("Below object")); + pad_def.enum_labels.push_back(L("Around object")); + pad_def.set_default_value(new ConfigOptionStrings{ "Below object" }); + option = Option(pad_def, "pad"); + option.opt.full_width = true; line.append_option(option); + line.append_widget(empty_widget); m_og_sla->append_line(line); @@ -617,7 +633,7 @@ void FreqChangedParams::Show(const bool is_fff) m_og->Show(is_fff); m_og_sla->Show(!is_fff); - // correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden + // correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden if (is_fff && !is_wdb_shown) m_wiping_dialog_button->Hide(); } @@ -747,7 +763,7 @@ Sidebar::Sidebar(Plater *parent) auto combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL); combo_and_btn_sizer->Add(*combo, 1, wxEXPAND); if ((*combo)->edit_btn) - combo_and_btn_sizer->Add((*combo)->edit_btn, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, + combo_and_btn_sizer->Add((*combo)->edit_btn, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, int(0.3*wxGetApp().em_unit())); auto *sizer_presets = this->p->sizer_presets; @@ -776,11 +792,11 @@ Sidebar::Sidebar(Plater *parent) // Frequently changed parameters p->frequently_changed_parameters = new FreqChangedParams(p->scrolled); p->sizer_params->Add(p->frequently_changed_parameters->get_sizer(), 0, wxEXPAND | wxTOP | wxBOTTOM, wxOSX ? 1 : margin_5); - + // Object List p->object_list = new ObjectList(p->scrolled); p->sizer_params->Add(p->object_list->get_sizer(), 1, wxEXPAND); - + // Object Manipulations p->object_manipulation = new ObjectManipulation(p->scrolled); p->object_manipulation->Hide(); @@ -790,7 +806,7 @@ Sidebar::Sidebar(Plater *parent) p->object_settings = new ObjectSettings(p->scrolled); p->object_settings->Hide(); p->sizer_params->Add(p->object_settings->get_sizer(), 0, wxEXPAND | wxTOP, margin_5); - + // Object Layers p->object_layers = new ObjectLayers(p->scrolled); p->object_layers->Hide(); @@ -803,7 +819,7 @@ Sidebar::Sidebar(Plater *parent) // Sizer in the scrolled area scrolled_sizer->Add(p->mode_sizer, 0, wxALIGN_CENTER_HORIZONTAL/*RIGHT | wxBOTTOM | wxRIGHT, 5*/); is_msw ? - scrolled_sizer->Add(p->presets_panel, 0, wxEXPAND | wxLEFT, margin_5) : + scrolled_sizer->Add(p->presets_panel, 0, wxEXPAND | wxLEFT, margin_5) : scrolled_sizer->Add(p->sizer_presets, 0, wxEXPAND | wxLEFT, margin_5); scrolled_sizer->Add(p->sizer_params, 1, wxEXPAND | wxLEFT, margin_5); scrolled_sizer->Add(p->object_info, 0, wxEXPAND | wxTOP | wxLEFT, margin_5); @@ -812,7 +828,7 @@ Sidebar::Sidebar(Plater *parent) // Buttons underneath the scrolled area auto init_btn = [this](wxButton **btn, wxString label) { - *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, + *btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); (*btn)->SetFont(wxGetApp().bold_font()); }; @@ -842,7 +858,7 @@ Sidebar::Sidebar(Plater *parent) p->plater->export_gcode(); else p->plater->reslice(); - p->plater->select_view_3D("Preview"); + p->plater->select_view_3D("Preview"); }); p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); }); } @@ -902,11 +918,11 @@ void Sidebar::update_all_preset_comboboxes() void Sidebar::update_presets(Preset::Type preset_type) { - PresetBundle &preset_bundle = *wxGetApp().preset_bundle; + PresetBundle &preset_bundle = *wxGetApp().preset_bundle; const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology(); switch (preset_type) { - case Preset::TYPE_FILAMENT: + case Preset::TYPE_FILAMENT: { const int extruder_cnt = print_tech != ptFFF ? 1 : dynamic_cast(preset_bundle.printers.get_edited_preset().config.option("nozzle_diameter"))->values.size(); @@ -926,23 +942,23 @@ void Sidebar::update_presets(Preset::Type preset_type) } case Preset::TYPE_PRINT: - preset_bundle.prints.update_platter_ui(p->combo_print); + preset_bundle.prints.update_platter_ui(p->combo_print); break; case Preset::TYPE_SLA_PRINT: - preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print); + preset_bundle.sla_prints.update_platter_ui(p->combo_sla_print); break; case Preset::TYPE_SLA_MATERIAL: - preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); + preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material); break; - case Preset::TYPE_PRINTER: - { + case Preset::TYPE_PRINTER: + { update_all_preset_comboboxes(); - p->show_preset_comboboxes(); - break; - } + p->show_preset_comboboxes(); + break; + } default: break; } @@ -960,11 +976,11 @@ void Sidebar::update_reslice_btn_tooltip() const { wxString tooltip = wxString("Slice") + " [" + GUI::shortkey_ctrl_prefix() + "R]"; if (m_mode != comSimple) - tooltip += wxString("\n") + _(L("Hold Shift to Slice & Export G-code")); + tooltip += wxString("\n") + _(L("Hold Shift to Slice & Export G-code")); p->btn_reslice->SetToolTip(tooltip); } -void Sidebar::msw_rescale() +void Sidebar::msw_rescale() { SetMinSize(wxSize(40 * wxGetApp().em_unit(), -1)); @@ -1072,7 +1088,7 @@ void Sidebar::show_info_sizer() if (errors > 0) { wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors)")), errors); p->object_info->info_manifold->SetLabel(tooltip); - + tooltip += ":\n" + wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " "%d facets added, %d facets reversed, %d backwards edges")), stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, @@ -1081,7 +1097,7 @@ void Sidebar::show_info_sizer() p->object_info->showing_manifold_warning_icon = true; p->object_info->info_manifold->SetToolTip(tooltip); p->object_info->manifold_warning_icon->SetToolTip(tooltip); - } + } else { p->object_info->info_manifold->SetLabel(_(L("Yes"))); p->object_info->showing_manifold_warning_icon = false; @@ -1097,7 +1113,7 @@ void Sidebar::show_info_sizer() } } -void Sidebar::show_sliced_info_sizer(const bool show) +void Sidebar::show_sliced_info_sizer(const bool show) { wxWindowUpdateLocker freeze_guard(this); @@ -1128,7 +1144,7 @@ void Sidebar::show_sliced_info_sizer(const bool show) p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, "N/A"); } else - { + { const PrintStatistics& ps = p->plater->fff_print().print_statistics(); const bool is_wipe_tower = ps.total_wipe_tower_filament > 0; @@ -1138,7 +1154,7 @@ void Sidebar::show_sliced_info_sizer(const bool show) wxString info_text = is_wipe_tower ? wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000, - (ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, + (ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, ps.total_wipe_tower_filament / 1000) : wxString::Format("%.2f", ps.total_used_filament / 1000); p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); @@ -1150,10 +1166,10 @@ void Sidebar::show_sliced_info_sizer(const bool show) new_label = _(L("Cost")); if (is_wipe_tower) new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower"))); - + info_text = is_wipe_tower ? wxString::Format("%.2f \n%.2f \n%.2f", ps.total_cost, - (ps.total_cost - ps.total_wipe_tower_cost), + (ps.total_cost - ps.total_wipe_tower_cost), ps.total_wipe_tower_cost) : wxString::Format("%.2f", ps.total_cost); p->sliced_info->SetTextAndShow(siCost, info_text, new_label); @@ -1175,10 +1191,10 @@ void Sidebar::show_sliced_info_sizer(const bool show) if (ps.estimated_silent_print_time != "N/A") { new_label += wxString::Format("\n - %s", _(L("stealth mode"))); info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); - for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i) + for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i) { new_label += wxString::Format("\n - %s%d", _(L("Color ")), i + 1); - info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]); + info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]); } } p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label); @@ -1189,7 +1205,7 @@ void Sidebar::show_sliced_info_sizer(const bool show) // Hide non-FFF sliced info parameters p->sliced_info->SetTextAndShow(siMateril_unit, "N/A"); - } + } } Layout(); @@ -1227,7 +1243,7 @@ void Sidebar::update_mode() p->object_list->unselect_objects(); p->object_list->update_selections(); p->object_list->update_object_menu(); - + Layout(); } @@ -1241,7 +1257,7 @@ std::vector& Sidebar::combos_filament() class PlaterDropTarget : public wxFileDropTarget { public: - PlaterDropTarget(Plater *plater) : plater(plater) { this->SetDefaultAction(wxDragCopy); } + PlaterDropTarget(Plater *plater) : plater(plater) { this->SetDefaultAction(wxDragCopy); } virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames); @@ -1265,22 +1281,22 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi } } - wxString snapshot_label; - assert(! paths.empty()); - if (paths.size() == 1) { - snapshot_label = _(L("Load File")); - snapshot_label += ": "; - snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); - } else { - snapshot_label = _(L("Load Files")); - snapshot_label += ": "; - snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); - for (size_t i = 1; i < paths.size(); ++ i) { - snapshot_label += ", "; - snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); - } - } - Plater::TakeSnapshot snapshot(plater, snapshot_label); + wxString snapshot_label; + assert(! paths.empty()); + if (paths.size() == 1) { + snapshot_label = _(L("Load File")); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + } else { + snapshot_label = _(L("Load Files")); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + for (size_t i = 1; i < paths.size(); ++ i) { + snapshot_label += ", "; + snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); + } + } + Plater::TakeSnapshot snapshot(plater, snapshot_label); // FIXME: when drag and drop is done on a .3mf or a .amf file we should clear the plater for consistence with the open project command // (the following call to plater->load_files() will load the config data, if present) @@ -1331,7 +1347,7 @@ struct Plater::priv // Data Slic3r::DynamicPrintConfig *config; // FIXME: leak? Slic3r::Print fff_print; - Slic3r::SLAPrint sla_print; + Slic3r::SLAPrint sla_print; Slic3r::Model model; PrinterTechnology printer_technology = ptFFF; Slic3r::GCodePreviewData gcode_preview_data; @@ -1349,19 +1365,19 @@ struct Plater::priv BackgroundSlicingProcess background_process; bool suppressed_backround_processing_update { false }; - + // Cache the wti info class WipeTower: public GLCanvas3D::WipeTowerInfo { using ArrangePolygon = arrangement::ArrangePolygon; friend priv; public: - + void apply_arrange_result(const Vec2crd& tr, double rotation) { m_pos = unscaled(tr); m_rotation = rotation; apply_wipe_tower(); } - + ArrangePolygon get_arrange_polygon() const { Polygon p({ @@ -1371,7 +1387,7 @@ struct Plater::priv {coord_t(0), scaled(m_bb_size(Y))}, {coord_t(0), coord_t(0)}, }); - + ArrangePolygon ret; ret.poly.contour = std::move(p); ret.translation = scaled(m_pos); @@ -1379,7 +1395,7 @@ struct Plater::priv return ret; } } wipetower; - + WipeTower& updated_wipe_tower() { auto wti = view3D->get_canvas3d()->get_wipe_tower_info(); wipetower.m_pos = wti.pos(); @@ -1387,10 +1403,10 @@ struct Plater::priv wipetower.m_bb_size = wti.bb_size(); return wipetower; } - + // A class to handle UI jobs like arranging and optimizing rotation. // These are not instant jobs, the user has to be informed about their - // state in the status progress indicator. On the other hand they are + // state in the status progress indicator. On the other hand they are // separated from the background slicing process. Ideally, these jobs should // run when the background process is not running. // @@ -1534,35 +1550,35 @@ struct Plater::priv Arrange, Rotoptimize }; - + class ArrangeJob : public Job { using ArrangePolygon = arrangement::ArrangePolygon; using ArrangePolygons = arrangement::ArrangePolygons; - + // The gap between logical beds in the x axis expressed in ratio of // the current bed width. static const constexpr double LOGICAL_BED_GAP = 1. / 5.; - + ArrangePolygons m_selected, m_unselected; - + // clear m_selected and m_unselected, reserve space for next usage void clear_input() { const Model &model = plater().model; - + size_t count = 0; // To know how much space to reserve for (auto obj : model.objects) count += obj->instances.size(); m_selected.clear(), m_unselected.clear(); m_selected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */); } - + // Stride between logical beds coord_t bed_stride() const { double bedwidth = plater().bed_shape_bb().size().x(); return scaled((1. + LOGICAL_BED_GAP) * bedwidth); } - + // Set up arrange polygon for a ModelInstance and Wipe tower template ArrangePolygon get_arrange_poly(T *obj) const { ArrangePolygon ap = obj->get_arrange_polygon(); @@ -1576,109 +1592,109 @@ struct Plater::priv }; return ap; } - + // Prepare all objects on the bed regardless of the selection void prepare_all() { clear_input(); - + for (ModelObject *obj: plater().model.objects) for (ModelInstance *mi : obj->instances) m_selected.emplace_back(get_arrange_poly(mi)); - + auto& wti = plater().updated_wipe_tower(); if (wti) m_selected.emplace_back(get_arrange_poly(&wti)); } - + // Prepare the selected and unselected items separately. If nothing is // selected, behaves as if everything would be selected. void prepare_selected() { clear_input(); - + Model &model = plater().model; coord_t stride = bed_stride(); - + std::vector obj_sel(model.objects.size(), nullptr); - + for (auto &s : plater().get_selection().get_content()) - if (s.first < int(obj_sel.size())) obj_sel[s.first] = &s.second; - + if (s.first < int(obj_sel.size())) obj_sel[s.first] = &s.second; + // Go through the objects and check if inside the selection for (size_t oidx = 0; oidx < model.objects.size(); ++oidx) { const Selection::InstanceIdxsList * instlist = obj_sel[oidx]; ModelObject *mo = model.objects[oidx]; - + std::vector inst_sel(mo->instances.size(), false); - + if (instlist) for (auto inst_id : *instlist) inst_sel[inst_id] = true; - + for (size_t i = 0; i < inst_sel.size(); ++i) { ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]); - + inst_sel[i] ? m_selected.emplace_back(std::move(ap)) : m_unselected.emplace_back(std::move(ap)); } } - + auto& wti = plater().updated_wipe_tower(); if (wti) { ArrangePolygon &&ap = get_arrange_poly(&wti); - + plater().get_selection().is_wipe_tower() ? m_selected.emplace_back(std::move(ap)) : m_unselected.emplace_back(std::move(ap)); } - + // If the selection was empty arrange everything if (m_selected.empty()) m_selected.swap(m_unselected); - + // The strides have to be removed from the fixed items. For the // arrangeable (selected) items bed_idx is ignored and the // translation is irrelevant. for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; } - + protected: - + void prepare() override { wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all(); } - + public: using Job::Job; - + int status_range() const override { return int(m_selected.size()); } - + void process() override; - + void finalize() override { // Ignore the arrange result if aborted. if (was_canceled()) return; - + // Apply the arrange result to all selected objects for (ArrangePolygon &ap : m_selected) ap.apply(); plater().update(false /*dont force_full_scene_refresh*/); } }; - + class RotoptimizeJob : public Job { public: using Job::Job; void process() override; }; - + // Jobs defined inside the group class will be managed so that only one can // run at a time. Also, the background process will be stopped if a job is // started. class ExclusiveJobGroup { - + static const int ABORT_WAIT_MAX_MS = 10000; - + priv * m_plater; ArrangeJob arrange_job{m_plater}; @@ -1687,7 +1703,7 @@ struct Plater::priv // To create a new job, just define a new subclass of Job, implement // the process and the optional prepare() and finalize() methods // Register the instance of the class in the m_jobs container - // if it cannot run concurrently with other jobs in this group + // if it cannot run concurrently with other jobs in this group std::vector> m_jobs{arrange_job, rotoptimize_job}; @@ -1700,22 +1716,22 @@ struct Plater::priv stop_all(); m_jobs[size_t(jid)].get().start(); } - + void cancel_all() { for (Job& j : m_jobs) j.cancel(); } void join_all(int wait_ms = 0) { std::vector aborted(m_jobs.size(), false); - + for (size_t jid = 0; jid < m_jobs.size(); ++jid) aborted[jid] = m_jobs[jid].get().join(wait_ms); if (!all_of(aborted)) BOOST_LOG_TRIVIAL(error) << "Could not abort a job!"; } - + void stop_all() { cancel_all(); join_all(ABORT_WAIT_MAX_MS); } - + const Job& get(Jobs jobid) const { return m_jobs[size_t(jobid)]; } bool is_any_running() const @@ -1724,7 +1740,7 @@ struct Plater::priv m_jobs.end(), [](const Job &j) { return j.is_running(); }); } - + } m_ui_jobs{this}; bool delayed_scene_refresh; @@ -1755,7 +1771,7 @@ struct Plater::priv BoundingBoxf bed_shape_bb() const; BoundingBox scaled_bed_shape_bb() const; arrangement::BedShapeHint get_bed_shape_hint() const; - + void find_new_position(const ModelInstancePtrs &instances, coord_t min_d); std::vector load_files(const std::vector& input_files, bool load_model, bool load_config); std::vector load_model_objects(const ModelObjectPtrs &model_objects); @@ -1786,8 +1802,8 @@ struct Plater::priv void enter_gizmos_stack(); void leave_gizmos_stack(); - void take_snapshot(const std::string& snapshot_name); - void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } + void take_snapshot(const std::string& snapshot_name); + void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } int get_active_snapshot_index(); void undo(); @@ -1807,7 +1823,7 @@ struct Plater::priv UPDATE_BACKGROUND_PROCESS_RESTART = 1, // update_background_process() reports, that the Print / SLAPrint was updated in a way, // that a scene needs to be refreshed (you should call _3DScene::reload_scene(canvas3Dwidget, false)) - UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2, + UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2, // update_background_process() reports, that the Print / SLAPrint is invalid, and the error message // was sent to the status line. UPDATE_BACKGROUND_PROCESS_INVALID = 4, @@ -1820,8 +1836,8 @@ struct Plater::priv unsigned int update_background_process(bool force_validation = false); // Restart background processing thread based on a bitmask of UpdateBackgroundProcessReturnState. bool restart_background_process(unsigned int state); - // returns bit mask of UpdateBackgroundProcessReturnState - unsigned int update_restart_background_process(bool force_scene_update, bool force_preview_update); + // returns bit mask of UpdateBackgroundProcessReturnState + unsigned int update_restart_background_process(bool force_scene_update, bool force_preview_update); void export_gcode(fs::path output_path, PrintHostJob upload_job); void reload_from_disk(); void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); @@ -1887,7 +1903,7 @@ private: void update_fff_scene(); void update_sla_scene(); - void undo_redo_to(std::vector::const_iterator it_snapshot); + void undo_redo_to(std::vector::const_iterator it_snapshot); void update_after_undo_redo(bool temp_snapshot_was_taken = false); // path to project file stored with no extension @@ -1895,9 +1911,9 @@ private: Slic3r::UndoRedo::Stack m_undo_redo_stack_main; Slic3r::UndoRedo::Stack m_undo_redo_stack_gizmos; Slic3r::UndoRedo::Stack *m_undo_redo_stack_active = &m_undo_redo_stack_main; - int m_prevent_snapshots = 0; /* Used for avoid of excess "snapshoting". + int m_prevent_snapshots = 0; /* Used for avoid of excess "snapshoting". * Like for "delete selected" or "set numbers of copies" - * we should call tack_snapshot just ones + * we should call tack_snapshot just ones * instead of calls for each action separately * */ std::string m_last_fff_printer_profile_name; @@ -1929,14 +1945,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , view_toolbar(GLToolbar::Radio, "View") , m_project_filename(wxEmptyString) { - this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); background_process.set_fff_print(&fff_print); - background_process.set_sla_print(&sla_print); + background_process.set_sla_print(&sla_print); background_process.set_gcode_preview_data(&gcode_preview_data); background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED); background_process.set_finished_event(EVT_PROCESS_COMPLETED); - // Default printer technology for default config. + // Default printer technology for default config. background_process.select_technology(this->printer_technology); // Register progress callback from the Print class to the Platter. @@ -1989,7 +2005,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); view3D_canvas->Bind(EVT_GLCANVAS_SELECT_ALL, [this](SimpleEvent&) { this->q->select_all(); }); view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); }); - view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event &evt) + view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event &evt) { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); @@ -2053,7 +2069,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) camera.set_type(get_config("use_perspective_camera")); // Initialize the Undo / Redo stack with a first snapshot. - this->take_snapshot(_(L("New Project"))); + this->take_snapshot(_(L("New Project"))); } Plater::priv::~priv() @@ -2080,7 +2096,7 @@ void Plater::priv::update(bool force_full_scene_refresh, bool force_background_p // pulls the correct data. update_status = this->update_background_process(false); this->view3D->reload_scene(false, force_full_scene_refresh); - this->preview->reload_print(); + this->preview->reload_print(); if (this->printer_technology == ptSLA) this->restart_background_process(update_status); else @@ -2198,7 +2214,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ model = Slic3r::Model::read_from_archive(path.string(), &config_loaded, false); if (load_config && !config_loaded.empty()) { // Based on the printer technology field found in the loaded config, select the base for the config, - PrinterTechnology printer_technology = Preset::printer_technology(config_loaded); + PrinterTechnology printer_technology = Preset::printer_technology(config_loaded); // We can't to load SLA project if there is at least one multi-part object on the bed if (printer_technology == ptSLA) @@ -2215,8 +2231,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } - config.apply(printer_technology == ptFFF ? - static_cast(FullPrintConfig::defaults()) : + config.apply(printer_technology == ptFFF ? + static_cast(FullPrintConfig::defaults()) : static_cast(SLAFullPrintConfig::defaults())); // and place the loaded config over the base. config += std::move(config_loaded); @@ -2283,8 +2299,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ { for (auto obj : model.objects) if ( obj->volumes.size()>1 ) { - Slic3r::GUI::show_error(nullptr, - wxString::Format(_(L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part")), + Slic3r::GUI::show_error(nullptr, + wxString::Format(_(L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part")), from_path(filename))); return obj_idxs; } @@ -2302,7 +2318,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } - if (new_model != nullptr) { + if (new_model != nullptr && new_model->objects.size() > 1) { wxMessageDialog dlg(q, _(L( "Multiple objects were loaded for a multi-material printer.\n" "Instead of considering them as multiple objects, should I consider\n" @@ -2326,6 +2342,9 @@ std::vector Plater::priv::load_files(const std::vector& input_ // automatic selection of added objects if (!obj_idxs.empty() && (view3D != nullptr)) { + // update printable state for new volumes on canvas3D + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs); + Selection& selection = view3D->get_canvas3d()->get_selection(); selection.clear(); for (size_t idx : obj_idxs) @@ -2366,9 +2385,9 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode #else /* AUTOPLACEMENT_ON_LOAD */ // if object has no defined position(s) we need to rearrange everything after loading need_arrange = true; - // add a default instance and center object around origin - object->center_around_origin(); // also aligns object to Z = 0 - ModelInstance* instance = object->add_instance(); + // add a default instance and center object around origin + object->center_around_origin(); // also aligns object to Z = 0 + ModelInstance* instance = object->add_instance(); instance->set_offset(Slic3r::to_3d(bed_shape.center().cast(), -object->origin_translation(2))); #endif /* AUTOPLACEMENT_ON_LOAD */ } @@ -2379,7 +2398,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode if (max_ratio > 10000) { // the size of the object is too big -> this could lead to overflow when moving to clipper coordinates, // so scale down the mesh - double inv = 1. / max_ratio; + double inv = 1. / max_ratio; object->scale_mesh_after_creation(Vec3d(inv, inv, inv)); object->origin_translation = Vec3d::Zero(); object->center_around_origin(); @@ -2403,9 +2422,9 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode auto& bedpoints = bed_shape_opt->values; Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1))); - + std::pair wti = view3D->get_canvas3d()->get_wipe_tower_info(); - + arr::find_new_position(model, new_instances, min_obj_distance, bed, wti); // it remains to move the wipe tower: @@ -2527,7 +2546,7 @@ int Plater::priv::get_selected_volume_idx() const { auto& selection = get_selection(); int idx = selection.get_object_idx(); - if ((0 > idx) || (idx > 1000)) + if ((0 > idx) || (idx > 1000)) return-1; const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); if (model.objects[idx]->volumes.size() > 1) @@ -2589,10 +2608,10 @@ void Plater::priv::remove(size_t obj_idx) void Plater::priv::delete_object_from_model(size_t obj_idx) { - wxString snapshot_label = _(L("Delete Object")); - if (! model.objects[obj_idx]->name.empty()) - snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str()); - Plater::TakeSnapshot snapshot(q, snapshot_label); + wxString snapshot_label = _(L("Delete Object")); + if (! model.objects[obj_idx]->name.empty()) + snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str()); + Plater::TakeSnapshot snapshot(q, snapshot_label); model.delete_object(obj_idx); update(); object_list_changed(); @@ -2600,7 +2619,7 @@ void Plater::priv::delete_object_from_model(size_t obj_idx) void Plater::priv::reset() { - Plater::TakeSnapshot snapshot(q, _(L("Reset Project"))); + Plater::TakeSnapshot snapshot(q, _(L("Reset Project"))); set_project_filename(wxEmptyString); @@ -2627,7 +2646,6 @@ void Plater::priv::reset() void Plater::priv::mirror(Axis axis) { - this->take_snapshot(_(L("Mirror"))); view3D->mirror_selection(axis); } @@ -2645,16 +2663,16 @@ void Plater::priv::sla_optimize_rotation() { } arrangement::BedShapeHint Plater::priv::get_bed_shape_hint() const { - + const auto *bed_shape_opt = config->opt("bed_shape"); assert(bed_shape_opt); - + if (!bed_shape_opt) return {}; - + auto &bedpoints = bed_shape_opt->values; Polyline bedpoly; bedpoly.points.reserve(bedpoints.size()); for (auto &v : bedpoints) bedpoly.append(scaled(v)); - + return arrangement::BedShapeHint(bedpoly); } @@ -2662,23 +2680,23 @@ void Plater::priv::find_new_position(const ModelInstancePtrs &instances, coord_t min_d) { arrangement::ArrangePolygons movable, fixed; - + for (const ModelObject *mo : model.objects) for (const ModelInstance *inst : mo->instances) { auto it = std::find(instances.begin(), instances.end(), inst); auto arrpoly = inst->get_arrange_polygon(); - + if (it == instances.end()) fixed.emplace_back(std::move(arrpoly)); else movable.emplace_back(std::move(arrpoly)); } - + if (updated_wipe_tower()) fixed.emplace_back(wipetower.get_arrange_polygon()); - + arrangement::arrange(movable, fixed, min_d, get_bed_shape_hint()); - + for (size_t i = 0; i < instances.size(); ++i) if (movable[i].bed_idx == 0) instances[i]->apply_arrange_result(movable[i].translation, @@ -2687,18 +2705,18 @@ void Plater::priv::find_new_position(const ModelInstancePtrs &instances, void Plater::priv::ArrangeJob::process() { static const auto arrangestr = _(L("Arranging")); - + // FIXME: I don't know how to obtain the minimum distance, it depends // on printer technology. I guess the following should work but it crashes. double dist = 6; // PrintConfig::min_object_distance(config); if (plater().printer_technology == ptFFF) { dist = PrintConfig::min_object_distance(plater().config); } - + coord_t min_d = scaled(dist); auto count = unsigned(m_selected.size()); arrangement::BedShapeHint bedshape = plater().get_bed_shape_hint(); - + try { arrangement::arrange(m_selected, m_unselected, min_d, bedshape, [this, count](unsigned st) { @@ -2712,7 +2730,7 @@ void Plater::priv::ArrangeJob::process() { _(L("Could not arrange model objects! " "Some geometries may be invalid."))); } - + // finalize just here. update_status(int(count), was_canceled() ? _(L("Arranging canceled.")) @@ -2738,25 +2756,25 @@ void Plater::priv::RotoptimizeJob::process() double mindist = 6.0; // FIXME - + if (!was_canceled()) { for(ModelInstance * oi : o->instances) { oi->set_rotation({r[X], r[Y], r[Z]}); - + auto trmatrix = oi->get_transformation().get_matrix(); Polygon trchull = o->convex_hull_2d(trmatrix); - + MinAreaBoundigBox rotbb(trchull, MinAreaBoundigBox::pcConvex); double r = rotbb.angle_to_X(); - + // The box should be landscape if(rotbb.width() < rotbb.height()) r += PI / 2; - + Vec3d rt = oi->get_rotation(); rt(Z) += r; - + oi->set_rotation(rt); } - + plater().find_new_position(o->instances, scaled(mindist)); // Correct the z offset of the object which was corrupted be @@ -2793,7 +2811,7 @@ void Plater::priv::split_object() Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part."))); else { - Plater::TakeSnapshot snapshot(q, _(L("Split to Objects"))); + Plater::TakeSnapshot snapshot(q, _(L("Split to Objects"))); unsigned int counter = 1; for (ModelObject* m : new_objects) @@ -2848,7 +2866,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation) // bitmap of enum UpdateBackgroundProcessReturnState unsigned int return_state = 0; - // If the update_background_process() was not called by the timer, kill the timer, + // If the update_background_process() was not called by the timer, kill the timer, // so the update_restart_background_process() will not be called again in vain. this->background_process_timer.Stop(); // Update the "out of print bed" state of ModelInstances. @@ -2869,21 +2887,21 @@ unsigned int Plater::priv::update_background_process(bool force_validation) this->sidebar->show_sliced_info_sizer(false); // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared. // Otherwise they will be just refreshed. - if (this->preview != nullptr) - // If the preview is not visible, the following line just invalidates the preview, - // but the G-code paths or SLA preview are calculated first once the preview is made visible. - this->preview->reload_print(); - // In FDM mode, we need to reload the 3D scene because of the wipe tower preview box. - // In SLA mode, we need to reload the 3D scene every time to show the support structures. - if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower"))) - return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE; + if (this->preview != nullptr) + // If the preview is not visible, the following line just invalidates the preview, + // but the G-code paths or SLA preview are calculated first once the preview is made visible. + this->preview->reload_print(); + // In FDM mode, we need to reload the 3D scene because of the wipe tower preview box. + // In SLA mode, we need to reload the 3D scene every time to show the support structures. + if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower"))) + return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE; } if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! this->background_process.empty()) { // The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors. std::string err = this->background_process.validate(); if (err.empty()) { - if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled()) + if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled()) return_state |= UPDATE_BACKGROUND_PROCESS_RESTART; } else { // The print is not valid. @@ -2905,12 +2923,12 @@ unsigned int Plater::priv::update_background_process(bool force_validation) if (invalidated != Print::APPLY_STATUS_UNCHANGED && was_running && ! this->background_process.running() && (return_state & UPDATE_BACKGROUND_PROCESS_RESTART) == 0) { - // The background processing was killed and it will not be restarted. - wxCommandEvent evt(EVT_PROCESS_COMPLETED); - evt.SetInt(-1); - // Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages. - wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); - } + // The background processing was killed and it will not be restarted. + wxCommandEvent evt(EVT_PROCESS_COMPLETED); + evt.SetInt(-1); + // Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages. + wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); + } if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0) { @@ -2928,17 +2946,17 @@ unsigned int Plater::priv::update_background_process(bool force_validation) sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export)); sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send)); - - const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ? + + const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ? _(L("Slicing")) + dots : _(L("Slice now")); sidebar->set_btn_label(ActionButtonType::abReslice, slice_string); if (background_process.finished()) show_action_buttons(false); - else if (!background_process.empty() && + else if (!background_process.empty() && !background_process.running()) /* Do not update buttons if background process is running - * This condition is important for SLA mode especially, - * when this function is called several times during calculations + * This condition is important for SLA mode especially, + * when this function is called several times during calculations * */ show_action_buttons(true); } @@ -2954,9 +2972,9 @@ bool Plater::priv::restart_background_process(unsigned int state) return false; } - if ( ! this->background_process.empty() && - (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) == 0 && - ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) || + if ( ! this->background_process.empty() && + (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) == 0 && + ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) || (state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 || (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) { // The print is valid and it can be started. @@ -3012,7 +3030,7 @@ unsigned int Plater::priv::update_restart_background_process(bool force_update_s if (force_update_preview) this->preview->reload_print(); this->restart_background_process(state); - return state; + return state; } void Plater::priv::update_fff_scene() @@ -3020,7 +3038,7 @@ void Plater::priv::update_fff_scene() if (this->preview != nullptr) this->preview->reload_print(); // In case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth: - view3D->reload_scene(true); + view3D->reload_scene(true); } void Plater::priv::update_sla_scene() @@ -3033,7 +3051,7 @@ void Plater::priv::update_sla_scene() void Plater::priv::reload_from_disk() { - Plater::TakeSnapshot snapshot(q, _(L("Reload from Disk"))); + Plater::TakeSnapshot snapshot(q, _(L("Reload from Disk"))); const auto &selection = get_selection(); const auto obj_orig_idx = selection.get_object_idx(); @@ -3069,7 +3087,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = if (obj_idx < 0) return; - Plater::TakeSnapshot snapshot(q, _(L("Fix Throught NetFabb"))); + Plater::TakeSnapshot snapshot(q, _(L("Fix Throught NetFabb"))); fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx); this->update(); @@ -3136,7 +3154,7 @@ void Plater::priv::set_current_panel(wxPanel* panel) } else if (current_panel == preview) { - this->q->reslice(); + this->q->reslice(); // keeps current gcode preview, if any preview->reload_print(true); preview->set_canvas_as_dirty(); @@ -3153,12 +3171,12 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) auto idx = combo->get_extruder_idx(); - //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, + //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, //! but the OSX version derived from wxOwnerDrawnCombo. - //! So, to get selected string we do - //! combo->GetString(combo->GetSelection()) - //! instead of - //! combo->GetStringSelection().ToUTF8().data()); + //! So, to get selected string we do + //! combo->GetString(combo->GetSelection()) + //! instead of + //! combo->GetStringSelection().ToUTF8().data()); const std::string& selected_string = combo->GetString(combo->GetSelection()).ToUTF8().data(); @@ -3170,7 +3188,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) { // Only update the platter UI for the 2nd and other filaments. wxGetApp().preset_bundle->update_platter_filament_ui(idx, combo); - } + } else { wxWindowUpdateLocker noUpdates(sidebar->presets_panel()); wxGetApp().get_tab(preset_type)->select_preset(selected_string); @@ -3180,7 +3198,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); /* Settings list can be changed after printer preset changing, so * update all settings items for all item had it. - * Furthermore, Layers editing is implemented only for FFF printers + * Furthermore, Layers editing is implemented only for FFF printers * and for SLA presets they should be deleted */ if (preset_type == Preset::TYPE_PRINTER) @@ -3241,9 +3259,9 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) this->background_process.stop(); this->statusbar()->reset_cancel_callback(); this->statusbar()->stop_busy(); - + const bool canceled = evt.GetInt() < 0; - const bool error = evt.GetInt() == 0; + const bool error = evt.GetInt() == 0; const bool success = evt.GetInt() > 0; // Reset the "export G-code path" name, so that the automatic background processing will be enabled again. this->background_process.reset_export(); @@ -3255,8 +3273,8 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) show_error(q, message); this->statusbar()->set_status_text(message); } - if (canceled) - this->statusbar()->set_status_text(_(L("Cancelled"))); + if (canceled) + this->statusbar()->set_status_text(_(L("Cancelled"))); this->sidebar->show_sliced_info_sizer(success); @@ -3264,7 +3282,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) // Namely, it refreshes the "Out of print bed" property of all the ModelObjects, and it enables // the "Slice now" and "Export G-code" buttons based on their "out of bed" status. this->object_list_changed(); - + // refresh preview switch (this->printer_technology) { case ptFFF: @@ -3399,7 +3417,7 @@ void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) // TODO } -// Update the scene from the background processing, +// Update the scene from the background processing, // if the update message was received during mouse manipulation. void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&) { @@ -3490,6 +3508,9 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ sidebar->obj_list()->append_menu_item_instance_to_object(menu, q); menu->AppendSeparator(); + wxMenuItem* menu_item_printable = sidebar->obj_list()->append_menu_item_printable(menu, q); + menu->AppendSeparator(); + append_menu_item(menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")), [this](wxCommandEvent&) { reload_from_disk(); }); @@ -3497,6 +3518,17 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ [this](wxCommandEvent&) { q->export_stl(false, true); }); menu->AppendSeparator(); + + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + const Selection& selection = get_selection(); + int instance_idx = selection.get_instance_idx(); + evt.Enable(instance_idx != -1); + if (instance_idx != -1) + { + evt.Check(model.objects[selection.get_object_idx()]->instances[instance_idx]->printable); + view3D->set_as_dirty(); + } + }, menu_item_printable->GetId()); } sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); @@ -3531,7 +3563,7 @@ bool Plater::priv::complit_init_object_menu() append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q); - append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "", + append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "", [this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q); object_menu.AppendSeparator(); @@ -3709,49 +3741,49 @@ void Plater::priv::update_object_menu() sidebar->obj_list()->append_menu_items_add_volume(&object_menu); } -void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const +void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const { wxWindowUpdateLocker noUpdater(sidebar); const auto prin_host_opt = config->option("print_host"); const bool send_gcode_shown = prin_host_opt != nullptr && !prin_host_opt->value.empty(); - // when a background processing is ON, export_btn and/or send_btn are showing + // when a background processing is ON, export_btn and/or send_btn are showing if (wxGetApp().app_config->get("background_processing") == "1") { if (sidebar->show_reslice(false) | - sidebar->show_export(true) | - sidebar->show_send(send_gcode_shown)) - sidebar->Layout(); - } + sidebar->show_export(true) | + sidebar->show_send(send_gcode_shown)) + sidebar->Layout(); + } else { - if (sidebar->show_reslice(is_ready_to_slice) | - sidebar->show_export(!is_ready_to_slice) | - sidebar->show_send(send_gcode_shown && !is_ready_to_slice)) - sidebar->Layout(); - } + if (sidebar->show_reslice(is_ready_to_slice) | + sidebar->show_export(!is_ready_to_slice) | + sidebar->show_send(send_gcode_shown && !is_ready_to_slice)) + sidebar->Layout(); + } } void Plater::priv::enter_gizmos_stack() { - assert(m_undo_redo_stack_active == &m_undo_redo_stack_main); - if (m_undo_redo_stack_active == &m_undo_redo_stack_main) { - m_undo_redo_stack_active = &m_undo_redo_stack_gizmos; - assert(m_undo_redo_stack_active->empty()); - // Take the initial snapshot of the gizmos. - // Not localized on purpose, the text will never be shown to the user. - this->take_snapshot(std::string("Gizmos-Initial")); - } + assert(m_undo_redo_stack_active == &m_undo_redo_stack_main); + if (m_undo_redo_stack_active == &m_undo_redo_stack_main) { + m_undo_redo_stack_active = &m_undo_redo_stack_gizmos; + assert(m_undo_redo_stack_active->empty()); + // Take the initial snapshot of the gizmos. + // Not localized on purpose, the text will never be shown to the user. + this->take_snapshot(std::string("Gizmos-Initial")); + } } void Plater::priv::leave_gizmos_stack() { - assert(m_undo_redo_stack_active == &m_undo_redo_stack_gizmos); - if (m_undo_redo_stack_active == &m_undo_redo_stack_gizmos) { - assert(! m_undo_redo_stack_active->empty()); - m_undo_redo_stack_active->clear(); - m_undo_redo_stack_active = &m_undo_redo_stack_main; - } + assert(m_undo_redo_stack_active == &m_undo_redo_stack_gizmos); + if (m_undo_redo_stack_active == &m_undo_redo_stack_gizmos) { + assert(! m_undo_redo_stack_active->empty()); + m_undo_redo_stack_active->clear(); + m_undo_redo_stack_active = &m_undo_redo_stack_main; + } } int Plater::priv::get_active_snapshot_index() @@ -3764,13 +3796,13 @@ int Plater::priv::get_active_snapshot_index() void Plater::priv::take_snapshot(const std::string& snapshot_name) { - if (this->m_prevent_snapshots > 0) + if (this->m_prevent_snapshots > 0) return; assert(this->m_prevent_snapshots >= 0); UndoRedo::SnapshotData snapshot_data; snapshot_data.printer_technology = this->printer_technology; if (this->view3D->is_layers_editing_enabled()) - snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; + snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; if (this->sidebar->obj_list()->is_selected(itSettings)) { snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR; snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx(); @@ -3792,46 +3824,46 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) this->undo_redo_stack().release_least_recently_used(); // Save the last active preset name of a particular printer technology. ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); - BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info(); + BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info(); } void Plater::priv::undo() { - const std::vector &snapshots = this->undo_redo_stack().snapshots(); - auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); - if (-- it_current != snapshots.begin()) - this->undo_redo_to(it_current); + const std::vector &snapshots = this->undo_redo_stack().snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); + if (-- it_current != snapshots.begin()) + this->undo_redo_to(it_current); } void Plater::priv::redo() -{ - const std::vector &snapshots = this->undo_redo_stack().snapshots(); - auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); - if (++ it_current != snapshots.end()) - this->undo_redo_to(it_current); +{ + const std::vector &snapshots = this->undo_redo_stack().snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); + if (++ it_current != snapshots.end()) + this->undo_redo_to(it_current); } void Plater::priv::undo_redo_to(size_t time_to_load) { - const std::vector &snapshots = this->undo_redo_stack().snapshots(); - auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(time_to_load)); - assert(it_current != snapshots.end()); - this->undo_redo_to(it_current); + const std::vector &snapshots = this->undo_redo_stack().snapshots(); + auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(time_to_load)); + assert(it_current != snapshots.end()); + this->undo_redo_to(it_current); } void Plater::priv::undo_redo_to(std::vector::const_iterator it_snapshot) { - bool temp_snapshot_was_taken = this->undo_redo_stack().temp_snapshot_active(); - PrinterTechnology new_printer_technology = it_snapshot->snapshot_data.printer_technology; - bool printer_technology_changed = this->printer_technology != new_printer_technology; - if (printer_technology_changed) { - // Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type. - std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA"; - if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8( - L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str()))) - // Don't switch the profiles. - return; - } + bool temp_snapshot_was_taken = this->undo_redo_stack().temp_snapshot_active(); + PrinterTechnology new_printer_technology = it_snapshot->snapshot_data.printer_technology; + bool printer_technology_changed = this->printer_technology != new_printer_technology; + if (printer_technology_changed) { + // Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type. + std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA"; + if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8( + L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str()))) + // Don't switch the profiles. + return; + } // Save the last active preset name of a particular printer technology. ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config. @@ -3844,12 +3876,12 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator const int layer_range_idx = it_snapshot->snapshot_data.layer_range_idx; // Flags made of Snapshot::Flags enum values. unsigned int new_flags = it_snapshot->snapshot_data.flags; - UndoRedo::SnapshotData top_snapshot_data; + UndoRedo::SnapshotData top_snapshot_data; top_snapshot_data.printer_technology = this->printer_technology; if (this->view3D->is_layers_editing_enabled()) - top_snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; + top_snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; if (this->sidebar->obj_list()->is_selected(itSettings)) { - top_snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR; + top_snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR; top_snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx(); } else if (this->sidebar->obj_list()->is_selected(itLayer)) { @@ -3858,26 +3890,26 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator } else if (this->sidebar->obj_list()->is_selected(itLayerRoot)) top_snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR; - bool new_variable_layer_editing_active = (new_flags & UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE) != 0; + bool new_variable_layer_editing_active = (new_flags & UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE) != 0; bool new_selected_settings_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR) != 0; bool new_selected_layer_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR) != 0; bool new_selected_layerroot_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR) != 0; - // Disable layer editing before the Undo / Redo jump. + // Disable layer editing before the Undo / Redo jump. if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled()) view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting")); // Do the jump in time. if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ? - this->undo_redo_stack().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, it_snapshot->timestamp) : - this->undo_redo_stack().redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { - if (printer_technology_changed) { - // Switch to the other printer technology. Switch to the last printer active for that particular technology. - AppConfig *app_config = wxGetApp().app_config; - app_config->set("presets", "printer", (new_printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name); - wxGetApp().preset_bundle->load_presets(*app_config); - // Load the currently selected preset into the GUI, update the preset selection box. - // This also switches the printer technology based on the printer technology of the active printer profile. - wxGetApp().load_current_presets(); + this->undo_redo_stack().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, it_snapshot->timestamp) : + this->undo_redo_stack().redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { + if (printer_technology_changed) { + // Switch to the other printer technology. Switch to the last printer active for that particular technology. + AppConfig *app_config = wxGetApp().app_config; + app_config->set("presets", "printer", (new_printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name); + wxGetApp().preset_bundle->load_presets(*app_config); + // Load the currently selected preset into the GUI, update the preset selection box. + // This also switches the printer technology based on the printer technology of the active printer profile. + wxGetApp().load_current_presets(); } //FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower. // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config. @@ -3898,43 +3930,43 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator // set selection mode for ObjectList on sidebar this->sidebar->obj_list()->set_selection_mode(new_selected_settings_on_sidebar ? ObjectList::SELECTION_MODE::smSettings : new_selected_layer_on_sidebar ? ObjectList::SELECTION_MODE::smLayer : - new_selected_layerroot_on_sidebar ? ObjectList::SELECTION_MODE::smLayerRoot : + new_selected_layerroot_on_sidebar ? ObjectList::SELECTION_MODE::smLayerRoot : ObjectList::SELECTION_MODE::smUndef); if (new_selected_settings_on_sidebar || new_selected_layer_on_sidebar) this->sidebar->obj_list()->set_selected_layers_range_idx(layer_range_idx); this->update_after_undo_redo(temp_snapshot_was_taken); - // Enable layer editing after the Undo / Redo jump. - if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active) + // Enable layer editing after the Undo / Redo jump. + if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active) view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting")); } } void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) { - this->view3D->get_canvas3d()->get_selection().clear(); - // Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies). - this->update(false, true); - // Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot. - //if (temp_snapshot_was_taken) - // Release the old snapshots always, as it may have happened, that some of the triangle meshes got deserialized from the snapshot, while some - // triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size. - this->undo_redo_stack().release_least_recently_used(); - //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time) + this->view3D->get_canvas3d()->get_selection().clear(); + // Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies). + this->update(false, true); + // Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot. + //if (temp_snapshot_was_taken) + // Release the old snapshots always, as it may have happened, that some of the triangle meshes got deserialized from the snapshot, while some + // triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size. + this->undo_redo_stack().release_least_recently_used(); + //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time) this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances); this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(); wxGetApp().obj_list()->update_after_undo_redo(); if (wxGetApp().get_mode() == comSimple && model_has_advanced_features(this->model)) { - // If the user jumped to a snapshot that require user interface with advanced features, switch to the advanced mode without asking. - // There is a little risk of surprising the user, as he already must have had the advanced or expert mode active for such a snapshot to be taken. + // If the user jumped to a snapshot that require user interface with advanced features, switch to the advanced mode without asking. + // There is a little risk of surprising the user, as he already must have had the advanced or expert mode active for such a snapshot to be taken. Slic3r::GUI::wxGetApp().save_mode(comAdvanced); view3D->set_as_dirty(); } - //FIXME what about the state of the manipulators? - //FIXME what about the focus? Cursor in the side panel? + //FIXME what about the state of the manipulators? + //FIXME what about the focus? Cursor in the side panel? BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot reloaded. Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info(); } @@ -4010,23 +4042,23 @@ void Plater::add_model() for (const auto &file : input_files) paths.push_back(into_path(file)); - wxString snapshot_label; - assert(! paths.empty()); - if (paths.size() == 1) { - snapshot_label = _(L("Import Object")); - snapshot_label += ": "; - snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); - } else { - snapshot_label = _(L("Import Objects")); - snapshot_label += ": "; - snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); - for (size_t i = 1; i < paths.size(); ++ i) { - snapshot_label += ", "; - snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); - } - } + wxString snapshot_label; + assert(! paths.empty()); + if (paths.size() == 1) { + snapshot_label = _(L("Import Object")); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + } else { + snapshot_label = _(L("Import Objects")); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + for (size_t i = 1; i < paths.size(); ++ i) { + snapshot_label += ", "; + snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); + } + } - Plater::TakeSnapshot snapshot(this, snapshot_label); + Plater::TakeSnapshot snapshot(this, snapshot_label); load_files(paths, true, false); } @@ -4047,7 +4079,7 @@ void Plater::load_files(const std::vector& input_files, bool load_mode // To be called when providing a list of files to the GUI slic3r on command line. void Plater::load_files(const std::vector& input_files, bool load_model, bool load_config) -{ +{ std::vector paths; paths.reserve(input_files.size()); for (const std::string &path : input_files) @@ -4072,7 +4104,7 @@ void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } void Plater::reset() { p->reset(); } void Plater::reset_with_confirm() { - if (wxMessageDialog((wxWindow*)this, _(L("All objects will be removed, continue ?")), wxString(SLIC3R_APP_NAME) + " - " + _(L("Delete all")), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) + if (wxMessageDialog((wxWindow*)this, _(L("All objects will be removed, continue ?")), wxString(SLIC3R_APP_NAME) + " - " + _(L("Delete all")), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) reset(); } @@ -4080,7 +4112,7 @@ void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_mo void Plater::remove_selected() { - Plater::TakeSnapshot snapshot(this, _(L("Delete Selected Objects"))); + Plater::TakeSnapshot snapshot(this, _(L("Delete Selected Objects"))); this->p->view3D->delete_selected(); } @@ -4088,7 +4120,7 @@ void Plater::increase_instances(size_t num) { if (! can_increase_instances()) { return; } - Plater::TakeSnapshot snapshot(this, _(L("Increase Instances"))); + Plater::TakeSnapshot snapshot(this, _(L("Increase Instances"))); int obj_idx = p->get_selected_object_idx(); @@ -4096,7 +4128,7 @@ void Plater::increase_instances(size_t num) ModelInstance* model_instance = model_object->instances.back(); bool was_one_instance = model_object->instances.size()==1; - + double offset_base = canvas3D()->get_size_proportional_to_max_bed_size(0.05); double offset = offset_base; for (size_t i = 0; i < num; i++, offset += offset_base) { @@ -4124,7 +4156,7 @@ void Plater::decrease_instances(size_t num) { if (! can_decrease_instances()) { return; } - Plater::TakeSnapshot snapshot(this, _(L("Decrease Instances"))); + Plater::TakeSnapshot snapshot(this, _(L("Decrease Instances"))); int obj_idx = p->get_selected_object_idx(); @@ -4155,12 +4187,12 @@ void Plater::set_number_of_copies(/*size_t num*/) ModelObject* model_object = p->model.objects[obj_idx]; - const auto num = wxGetNumberFromUser( " ", _("Enter the number of copies:"), + const auto num = wxGetNumberFromUser( " ", _("Enter the number of copies:"), _("Copies of the selected object"), model_object->instances.size(), 0, 1000, this ); if (num < 0) return; - Plater::TakeSnapshot snapshot(this, wxString::Format(_(L("Set numbers of copies to %d")), num)); + Plater::TakeSnapshot snapshot(this, wxString::Format(_(L("Set numbers of copies to %d")), num)); int diff = (int)num - (int)model_object->instances.size(); if (diff > 0) @@ -4190,7 +4222,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe return; } - Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane"))); + Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane"))); wxBusyCursor wait; const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower); @@ -4208,11 +4240,11 @@ void Plater::export_gcode() // This function is useful for generating file names to be processed by legacy firmwares. fs::path default_output_file; try { - // Update the background processing, so that the placeholder parser will get the correct values for the ouput file template. - // Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed. - unsigned int state = this->p->update_restart_background_process(false, false); - if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) - return; + // Update the background processing, so that the placeholder parser will get the correct values for the ouput file template. + // Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed. + unsigned int state = this->p->update_restart_background_process(false, false); + if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) + return; default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf"))); } catch (const std::exception &ex) { @@ -4398,7 +4430,7 @@ void Plater::reslice() if (object->sla_points_status == sla::PointsStatus::NoPoints) object->sla_points_status = sla::PointsStatus::Generating; } - + //FIXME Don't reslice if export of G-code or sending to OctoPrint is running. // bitmask of UpdateBackgroundProcessReturnState unsigned int state = this->p->update_background_process(true); @@ -4446,10 +4478,10 @@ void Plater::reslice_SLA_supports(const ModelObject &object) task.single_model_object = object.id(); // If the background processing is not enabled, calculate supports just for the single instance. // Otherwise calculate everything, but start with the provided object. - if (!this->p->background_processing_enabled()) { - task.single_model_instance_only = true; - task.to_object_step = slaposBasePool; - } + if (!this->p->background_processing_enabled()) { + task.single_model_instance_only = true; + task.to_object_step = slaposBasePool; + } this->p->background_process.set_task(task); // and let the background processing start. this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART); @@ -4465,11 +4497,11 @@ void Plater::send_gcode() // Obtain default output path fs::path default_output_file; try { - // Update the background processing, so that the placeholder parser will get the correct values for the ouput file template. - // Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed. - unsigned int state = this->p->update_restart_background_process(false, false); - if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) - return; + // Update the background processing, so that the placeholder parser will get the correct values for the ouput file template. + // Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed. + unsigned int state = this->p->update_restart_background_process(false, false); + if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) + return; default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf"))); } catch (const std::exception &ex) { @@ -4499,7 +4531,7 @@ void Plater::undo_to(int selection) p->undo(); return; } - + const int idx = p->get_active_snapshot_index() - selection - 1; p->undo_redo_to(p->undo_redo_stack().snapshots()[idx].timestamp); } @@ -4509,7 +4541,7 @@ void Plater::redo_to(int selection) p->redo(); return; } - + const int idx = p->get_active_snapshot_index() + selection + 1; p->undo_redo_to(p->undo_redo_stack().snapshots()[idx].timestamp); } @@ -4536,7 +4568,7 @@ void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& ou return; } - out_text = L(""); + out_text = ""; } void Plater::on_extruders_change(int num_extruders) @@ -4578,12 +4610,12 @@ void Plater::on_config_change(const DynamicPrintConfig &config) else if ((opt_key == "bed_shape") || (opt_key == "bed_custom_texture") || (opt_key == "bed_custom_model")) { bed_shape_changed = true; update_scheduled = true; - } + } else if (boost::starts_with(opt_key, "wipe_tower") || // opt_key == "filament_minimal_purge_on_wipe_tower" // ? #ys_FIXME opt_key == "single_extruder_multi_material") { update_scheduled = true; - } + } else if(opt_key == "variable_layer_height") { if (p->config->opt_bool("variable_layer_height") != true) { p->view3D->enable_layers_editing(false); @@ -4613,7 +4645,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config) p->config->option("bed_custom_texture")->value, p->config->option("bed_custom_model")->value); - if (update_scheduled) + if (update_scheduled) update(); if (p->main_frame->is_loaded()) @@ -4634,10 +4666,10 @@ void Plater::on_activate() #endif if (! this->p->delayed_error_message.empty()) { - std::string msg = std::move(this->p->delayed_error_message); - this->p->delayed_error_message.clear(); + std::string msg = std::move(this->p->delayed_error_message); + this->p->delayed_error_message.clear(); GUI::show_error(this, msg); - } + } } wxString Plater::get_project_filename(const wxString& extension) const @@ -4681,7 +4713,7 @@ void Plater::set_printer_technology(PrinterTechnology printer_technology) if (p->background_process.select_technology(printer_technology)) { // Update the active presets. } - //FIXME for SLA synchronize + //FIXME for SLA synchronize //p->background_process.apply(Model)! p->label_btn_export = printer_technology == ptFFF ? L("Export G-code") : L("Export"); @@ -4741,7 +4773,7 @@ void Plater::schedule_background_process(bool schedule/* = true*/) this->p->suppressed_backround_processing_update = false; } -bool Plater::is_background_process_running() const +bool Plater::is_background_process_running() const { return this->p->background_process_timer.IsRunning(); } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index fa8b5baeec..833da238a5 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -162,11 +162,11 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem if (from_pre_map != pre_family_model_map.end()) { model.family = from_pre_map->second; } } #if 0 - // Remove SLA printers from the initial alpha. - if (model.technology == ptSLA) - continue; + // Remove SLA printers from the initial alpha. + if (model.technology == ptSLA) + continue; #endif - section.second.get("variants", ""); + section.second.get("variants", ""); const auto variants_field = section.second.get("variants", ""); std::vector variants; if (Slic3r::unescape_strings_cstyle(variants_field, variants)) { @@ -209,7 +209,7 @@ const std::string& Preset::suffix_modified() void Preset::update_suffix_modified() { - g_suffix_modified = (" (" + _(L("modified")) + ")").ToUTF8().data(); + g_suffix_modified = (" (" + _(L("modified")) + ")").ToUTF8().data(); } // Remove an optional "(modified)" suffix from a name. // This converts a UI name to a unique preset identifier. @@ -224,8 +224,8 @@ void Preset::set_num_extruders(DynamicPrintConfig &config, unsigned int num_extr { const auto &defaults = FullPrintConfig::defaults(); for (const std::string &key : Preset::nozzle_options()) { - if (key == "default_filament_profile") - continue; + if (key == "default_filament_profile") + continue; auto *opt = config.option(key, false); assert(opt != nullptr); assert(opt->is_vector()); @@ -247,8 +247,8 @@ void Preset::normalize(DynamicPrintConfig &config) size_t n = (nozzle_diameter == nullptr) ? 1 : nozzle_diameter->values.size(); const auto &defaults = FullPrintConfig::defaults(); for (const std::string &key : Preset::filament_options()) { - if (key == "compatible_prints" || key == "compatible_printers") - continue; + if (key == "compatible_prints" || key == "compatible_printers") + continue; auto *opt = config.option(key, false); /*assert(opt != nullptr); assert(opt->is_vector());*/ @@ -307,7 +307,7 @@ bool Preset::is_compatible_with_print(const Preset &active_print) const } } return this->is_default || active_print.name.empty() || ! has_compatible_prints || - std::find(compatible_prints->values.begin(), compatible_prints->values.end(), active_print.name) != + std::find(compatible_prints->values.begin(), compatible_prints->values.end(), active_print.name) != compatible_prints->values.end(); } @@ -326,7 +326,7 @@ bool Preset::is_compatible_with_printer(const Preset &active_printer, const Dyna } } return this->is_default || active_printer.name.empty() || ! has_compatible_printers || - std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != + std::find(compatible_printers->values.begin(), compatible_printers->values.end(), active_printer.name) != compatible_printers->values.end(); } @@ -334,9 +334,9 @@ bool Preset::is_compatible_with_printer(const Preset &active_printer) const { DynamicPrintConfig config; config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); - const ConfigOption *opt = active_printer.config.option("nozzle_diameter"); - if (opt) - config.set_key_value("num_extruders", new ConfigOptionInt((int)static_cast(opt)->values.size())); + const ConfigOption *opt = active_printer.config.option("nozzle_diameter"); + if (opt) + config.set_key_value("num_extruders", new ConfigOptionInt((int)static_cast(opt)->values.size())); return this->is_compatible_with_printer(active_printer, &config); } @@ -358,40 +358,40 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config) } const std::vector& Preset::print_options() -{ +{ static std::vector s_opts { - "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "top_solid_layers", "bottom_solid_layers", - "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", + "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "top_solid_layers", "bottom_solid_layers", + "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", - "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", - "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", - "max_volumetric_speed", + "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", + "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", + "max_volumetric_speed", #ifdef HAS_PRESSURE_EQUALIZER - "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", + "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", #endif /* HAS_PRESSURE_EQUALIZER */ - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", - "bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", + "bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", - "min_skirt_length", "brim_width", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", - "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", - "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", - "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", - "support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius", - "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", - "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", - "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", - "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", - "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", + "min_skirt_length", "brim_width", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", + "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", + "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", + "support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius", + "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", + "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", + "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", + "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", + "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", - "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "single_extruder_multi_material_priming", + "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "single_extruder_multi_material_priming", "compatible_printers", "compatible_printers_condition", "inherits" }; return s_opts; } const std::vector& Preset::filament_options() -{ +{ static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time", @@ -401,16 +401,16 @@ const std::vector& Preset::filament_options() "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode", // Retract overrides - "filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel", - "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", - // Profile compatibility + "filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel", + "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", + // Profile compatibility "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" }; return s_opts; } const std::vector& Preset::printer_options() -{ +{ static std::vector s_opts; if (s_opts.empty()) { s_opts = { @@ -420,20 +420,20 @@ const std::vector& Preset::printer_options() "host_type", "print_host", "printhost_apikey", "printhost_cafile", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", "between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction", - "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "max_print_height", + "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits", "remaining_times", "silent_mode", "machine_max_acceleration_extruding", "machine_max_acceleration_retracting", - "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e", - "machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e", - "machine_min_extruding_rate", "machine_min_travel_rate", - "machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e" + "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e", + "machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e", + "machine_min_extruding_rate", "machine_min_travel_rate", + "machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e" }; s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end()); } return s_opts; } -// The following nozzle options of a printer profile will be adjusted to match the size +// The following nozzle options of a printer profile will be adjusted to match the size // of the nozzle_diameter vector. const std::vector& Preset::nozzle_options() { @@ -442,14 +442,14 @@ const std::vector& Preset::nozzle_options() "nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset", "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe", - "retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour", + "retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour", "default_filament_profile" }; return s_opts; } const std::vector& Preset::sla_print_options() -{ +{ static std::vector s_opts; if (s_opts.empty()) { s_opts = { @@ -477,16 +477,17 @@ const std::vector& Preset::sla_print_options() "pad_wall_thickness", "pad_wall_height", "pad_max_merge_distance", - "pad_edge_radius", + // "pad_edge_radius", "pad_wall_slope", "pad_object_gap", + "pad_zero_elevation", "pad_object_connector_stride", "pad_object_connector_width", "pad_object_connector_penetration", - "output_filename_format", + "output_filename_format", "default_sla_print_profile", "compatible_printers", - "compatible_printers_condition", + "compatible_printers_condition", "inherits" }; } @@ -494,7 +495,7 @@ const std::vector& Preset::sla_print_options() } const std::vector& Preset::sla_material_options() -{ +{ static std::vector s_opts; if (s_opts.empty()) { s_opts = { @@ -503,7 +504,7 @@ const std::vector& Preset::sla_material_options() "material_correction", "material_notes", "default_sla_material_profile", - "compatible_prints", "compatible_prints_condition", + "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" }; } @@ -511,7 +512,7 @@ const std::vector& Preset::sla_material_options() } const std::vector& Preset::sla_printer_options() -{ +{ static std::vector s_opts; if (s_opts.empty()) { s_opts = { @@ -539,7 +540,7 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vectoradd_default_preset(keys, defaults, default_name); @@ -552,8 +553,8 @@ PresetCollection::~PresetCollection() m_bitmap_main_frame = nullptr; delete m_bitmap_add; m_bitmap_add = nullptr; - delete m_bitmap_cache; - m_bitmap_cache = nullptr; + delete m_bitmap_cache; + m_bitmap_cache = nullptr; } void PresetCollection::reset(bool delete_files) @@ -575,8 +576,8 @@ void PresetCollection::add_default_preset(const std::vector &keys, { // Insert just the default preset. m_presets.emplace_back(Preset(this->type(), preset_name, true)); - m_presets.back().config.apply_only(defaults, keys.empty() ? defaults.keys() : keys); - m_presets.back().loaded = true; + m_presets.back().config.apply_only(defaults, keys.empty() ? defaults.keys() : keys); + m_presets.back().loaded = true; ++ m_num_default_presets; } @@ -584,13 +585,13 @@ void PresetCollection::add_default_preset(const std::vector &keys, // Throws an exception on error. void PresetCollection::load_presets(const std::string &dir_path, const std::string &subdir) { - boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred(); - m_dir_path = dir.string(); + boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred(); + m_dir_path = dir.string(); 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; - for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) + // 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; + for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) if (Slic3r::is_ini_file(dir_entry)) { std::string name = dir_entry.path().filename().string(); // Remove the .ini suffix. @@ -609,28 +610,28 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri DynamicPrintConfig config; config.load_from_ini(preset.file); // Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field. - const Preset &default_preset = this->default_preset_for(config); + const Preset &default_preset = this->default_preset_for(config); preset.config = default_preset.config; preset.config.apply(std::move(config)); Preset::normalize(preset.config); // Report configuration fields, which are misplaced into a wrong group. - std::string incorrect_keys = Preset::remove_invalid_keys(config, default_preset.config); + std::string incorrect_keys = Preset::remove_invalid_keys(config, default_preset.config); if (! incorrect_keys.empty()) BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; preset.loaded = true; } catch (const std::ifstream::failure &err) { - throw std::runtime_error(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what()); + throw std::runtime_error(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what()); } catch (const std::runtime_error &err) { - throw std::runtime_error(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what()); + throw std::runtime_error(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what()); } - presets_loaded.emplace_back(preset); + presets_loaded.emplace_back(preset); } catch (const std::runtime_error &err) { errors_cummulative += err.what(); errors_cummulative += "\n"; - } + } } - m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end())); + m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end())); std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); this->select_preset(first_visible_idx()); if (! errors_cummulative.empty()) @@ -651,8 +652,8 @@ static bool profile_print_params_same(const DynamicPrintConfig &cfg1, const Dyna t_config_option_keys diff = cfg1.diff(cfg2); // Following keys are used by the UI, not by the slicing core, therefore they are not important // when comparing profiles for equality. Ignore them. - for (const char *key : { "compatible_prints", "compatible_prints_condition", - "compatible_printers", "compatible_printers_condition", "inherits", + for (const char *key : { "compatible_prints", "compatible_prints_condition", + "compatible_printers", "compatible_printers_condition", "inherits", "print_settings_id", "filament_settings_id", "sla_print_settings_id", "sla_material_settings_id", "printer_settings_id", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile", "default_sla_print_profile", "default_sla_material_profile", "printhost_apikey", "printhost_cafile" }) @@ -663,7 +664,7 @@ static bool profile_print_params_same(const DynamicPrintConfig &cfg1, const Dyna // Load a preset from an already parsed config file, insert it into the sorted sequence of presets // and select it, losing previous modifications. -// In case +// In case Preset& PresetCollection::load_external_preset( // Path to the profile source file (a G-code, an AMF or 3MF file, a config file) const std::string &path, @@ -681,7 +682,7 @@ Preset& PresetCollection::load_external_preset( cfg.apply_only(config, cfg.keys(), true); // Is there a preset already loaded with the name stored inside the config? std::deque::iterator it = this->find_preset_internal(original_name); - bool found = it != m_presets.end() && it->name == original_name; + bool found = it != m_presets.end() && it->name == original_name; if (found && profile_print_params_same(it->config, cfg)) { // The preset exists and it matches the values stored inside config. if (select) @@ -706,7 +707,7 @@ Preset& PresetCollection::load_external_preset( suffix = " (" + std::to_string(idx) + ")"; } else { if (idx == 0) - suffix = " (" + original_name + ")"; + suffix = " (" + original_name + ")"; else suffix = " (" + original_name + "-" + std::to_string(idx) + ")"; } @@ -751,8 +752,8 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string void PresetCollection::save_current_preset(const std::string &new_name) { - // 1) Find the preset with a new_name or create a new one, - // initialize it with the edited config. + // 1) Find the preset with a new_name or create a new one, + // initialize it with the edited config. auto it = this->find_preset_internal(new_name); if (it != m_presets.end() && it->name == new_name) { // Preset with the same name found. @@ -762,15 +763,15 @@ void PresetCollection::save_current_preset(const std::string &new_name) return; // Overwriting an existing preset. preset.config = std::move(m_edited_preset.config); - // The newly saved preset will be activated -> make it visible. - preset.is_visible = true; + // The newly saved preset will be activated -> make it visible. + preset.is_visible = true; } else { // Creating a new preset. - Preset &preset = *m_presets.insert(it, m_edited_preset); + Preset &preset = *m_presets.insert(it, m_edited_preset); std::string &inherits = preset.inherits(); std::string old_name = preset.name; preset.name = new_name; - preset.file = this->path_from_name(new_name); + preset.file = this->path_from_name(new_name); preset.vendor = nullptr; if (preset.is_system) { // Inheriting from a system preset. @@ -779,30 +780,30 @@ void PresetCollection::save_current_preset(const std::string &new_name) // Inheriting from a user preset. Link the new preset to the old preset. // inherits = old_name; } else { - // Inherited from a user preset. Just maintain the "inherited" flag, + // Inherited from a user preset. Just maintain the "inherited" flag, // meaning it will inherit from either the system preset, or the inherited user preset. } preset.is_default = false; preset.is_system = false; preset.is_external = false; - // The newly saved preset will be activated -> make it visible. - preset.is_visible = true; - } - // 2) Activate the saved preset. - this->select_preset_by_name(new_name, true); - // 2) Store the active preset to disk. - this->get_selected_preset().save(); + // The newly saved preset will be activated -> make it visible. + preset.is_visible = true; + } + // 2) Activate the saved preset. + this->select_preset_by_name(new_name, true); + // 2) Store the active preset to disk. + this->get_selected_preset().save(); } bool PresetCollection::delete_current_preset() { const Preset &selected = this->get_selected_preset(); - if (selected.is_default) - return false; - if (! selected.is_external && ! selected.is_system) { - // Erase the preset file. - boost::nowide::remove(selected.file.c_str()); - } + if (selected.is_default) + return false; + if (! selected.is_external && ! selected.is_system) { + // Erase the preset file. + boost::nowide::remove(selected.file.c_str()); + } // Remove the preset from the list. m_presets.erase(m_presets.begin() + m_idx_selected); // Find the next visible preset. @@ -810,9 +811,9 @@ bool PresetCollection::delete_current_preset() if (new_selected_idx < m_presets.size()) for (; new_selected_idx < m_presets.size() && ! m_presets[new_selected_idx].is_visible; ++ new_selected_idx) ; if (new_selected_idx == m_presets.size()) - for (--new_selected_idx; new_selected_idx > 0 && !m_presets[new_selected_idx].is_visible; --new_selected_idx); + for (--new_selected_idx; new_selected_idx > 0 && !m_presets[new_selected_idx].is_visible; --new_selected_idx); this->select_preset(new_selected_idx); - return true; + return true; } void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name) @@ -836,18 +837,18 @@ const Preset* PresetCollection::get_selected_preset_parent() const return nullptr; // const std::string &inherits = this->get_edited_preset().inherits(); // if (inherits.empty()) -// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; +// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; std::string inherits = this->get_edited_preset().inherits(); if (inherits.empty()) { - if (this->get_selected_preset().is_system || this->get_selected_preset().is_default) + if (this->get_selected_preset().is_system || this->get_selected_preset().is_default) return &this->get_selected_preset(); if (this->get_selected_preset().is_external) return nullptr; - + inherits = m_type != Preset::Type::TYPE_PRINTER ? "- default -" : - this->get_edited_preset().printer_technology() == ptFFF ? + this->get_edited_preset().printer_technology() == ptFFF ? "- default FFF -" : "- default SLA -" ; } @@ -859,14 +860,14 @@ const Preset* PresetCollection::get_preset_parent(const Preset& child) const { const std::string &inherits = child.inherits(); if (inherits.empty()) -// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; - return nullptr; +// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; + return nullptr; const Preset* preset = this->find_preset(inherits, false); return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; } const std::string& PresetCollection::get_suffix_modified() { - return g_suffix_modified; + return g_suffix_modified; } // Return a preset by its name. If the preset is active, a temporary copy is returned. @@ -876,7 +877,7 @@ Preset* PresetCollection::find_preset(const std::string &name, bool first_visibl Preset key(m_type, name, false); auto it = this->find_preset_internal(name); // 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()) : + return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin()) : first_visible_if_not_found ? &this->first_visible() : nullptr; } @@ -896,9 +897,9 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) { if (m_default_suppressed != default_suppressed) { m_default_suppressed = default_suppressed; - bool default_visible = ! default_suppressed || m_idx_selected < m_num_default_presets; - for (size_t i = 0; i < m_num_default_presets; ++ i) - m_presets[i].is_visible = default_visible; + bool default_visible = ! default_suppressed || m_idx_selected < m_num_default_presets; + for (size_t i = 0; i < m_num_default_presets; ++ i) + m_presets[i].is_visible = default_visible; } } @@ -931,7 +932,7 @@ size_t PresetCollection::update_compatible_internal(const Preset &active_printer //void PresetCollection::delete_current_preset(); // Update the wxChoice UI component from this list of presets. -// Hide the +// Hide the void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) { if (ui == nullptr) @@ -940,12 +941,12 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) // Otherwise fill in the list from scratch. ui->Freeze(); ui->Clear(); - size_t selected_preset_item = 0; + size_t selected_preset_item = 0; - const Preset &selected_preset = this->get_selected_preset(); - // Show wide icons if the currently selected preset is not compatible with the current printer, - // and draw a red flag in front of the selected preset. - bool wide_icons = ! selected_preset.is_compatible && m_bitmap_incompatible != nullptr; + const Preset &selected_preset = this->get_selected_preset(); + // Show wide icons if the currently selected preset is not compatible with the current printer, + // and draw a red flag in front of the selected preset. + bool wide_icons = ! selected_preset.is_compatible && m_bitmap_incompatible != nullptr; /* It's supposed that standard size of an icon is 16px*16px for 100% scaled display. * So set sizes for solid_colored icons used for filament preset @@ -957,87 +958,87 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) const int thin_space_icon_width = 4 * scale_f + 0.5f; const int wide_space_icon_width = 6 * scale_f + 0.5f; - std::map nonsys_presets; - wxString selected = ""; - if (!this->m_presets.front().is_visible) + std::map nonsys_presets; + wxString selected = ""; + if (!this->m_presets.front().is_visible) ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); - for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { + for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) continue; - std::string bitmap_key = ""; - // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left - // to the filament color image. - if (wide_icons) - bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; - bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; - wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); - if (bmp == nullptr) { - // Create the bitmap with color bars. - std::vector bmps; - if (wide_icons) - // Paint a red flag for incompatible presets. - bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(icon_width, icon_height) : *m_bitmap_incompatible); - // Paint the color bars. - bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); - bmps.emplace_back(*m_bitmap_main_frame); - // Paint a lock at the system presets. - bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); - bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); - bmp = m_bitmap_cache->insert(bitmap_key, bmps); - } + std::string bitmap_key = ""; + // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left + // to the filament color image. + if (wide_icons) + bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; + bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + if (wide_icons) + // Paint a red flag for incompatible presets. + bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(icon_width, icon_height) : *m_bitmap_incompatible); + // Paint the color bars. + bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); + bmps.emplace_back(*m_bitmap_main_frame); + // Paint a lock at the system presets. + bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } - if (preset.is_default || preset.is_system) { - ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), - (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); - if (i == m_idx_selected) - selected_preset_item = ui->GetCount() - 1; - } - else - { - nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); - if (i == m_idx_selected) - selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); - } - if (i + 1 == m_num_default_presets) + if (preset.is_default || preset.is_system) { + ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), + (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); + if (i == m_idx_selected) + selected_preset_item = ui->GetCount() - 1; + } + else + { + nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); + if (i == m_idx_selected) + selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); + } + if (i + 1 == m_num_default_presets) ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap)); - } - if (!nonsys_presets.empty()) - { + } + if (!nonsys_presets.empty()) + { ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap)); - for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { - ui->Append(it->first, *it->second); - if (it->first == selected) - selected_preset_item = ui->GetCount() - 1; - } - } - if (m_type == Preset::TYPE_PRINTER) { - std::string bitmap_key = ""; - // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left - // to the filament color image. - if (wide_icons) - bitmap_key += "wide,"; - bitmap_key += "add_printer"; - wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); - if (bmp == nullptr) { - // Create the bitmap with color bars. - std::vector bmps; - if (wide_icons) - // Paint a red flag for incompatible presets. - bmps.emplace_back(m_bitmap_cache->mkclear(icon_width, icon_height)); - // Paint the color bars. - bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); - bmps.emplace_back(*m_bitmap_main_frame); - // Paint a lock at the system presets. - bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); - bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); - bmp = m_bitmap_cache->insert(bitmap_key, bmps); - } - ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); - } + for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { + ui->Append(it->first, *it->second); + if (it->first == selected) + selected_preset_item = ui->GetCount() - 1; + } + } + if (m_type == Preset::TYPE_PRINTER) { + std::string bitmap_key = ""; + // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left + // to the filament color image. + if (wide_icons) + bitmap_key += "wide,"; + bitmap_key += "add_printer"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + if (wide_icons) + // Paint a red flag for incompatible presets. + bmps.emplace_back(m_bitmap_cache->mkclear(icon_width, icon_height)); + // Paint the color bars. + bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height)); + bmps.emplace_back(*m_bitmap_main_frame); + // Paint a lock at the system presets. + bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height)); + bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } + ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD); + } - ui->SetSelection(selected_preset_item); - ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->SetSelection(selected_preset_item); + ui->SetToolTip(ui->GetString(selected_preset_item)); ui->check_selection(); ui->Thaw(); @@ -1052,7 +1053,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati return 0; ui->Freeze(); ui->Clear(); - size_t selected_preset_item = 0; + size_t selected_preset_item = 0; /* It's supposed that standard size of an icon is 16px*16px for 100% scaled display. * So set sizes for solid_colored(empty) icons used for preset @@ -1062,52 +1063,52 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati const int icon_height = 16 * scale_f + 0.5f; const int icon_width = 16 * scale_f + 0.5f; - std::map nonsys_presets; - wxString selected = ""; - if (!this->m_presets.front().is_visible) - ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); - for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { + std::map nonsys_presets; + wxString selected = ""; + if (!this->m_presets.front().is_visible) + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); + for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) continue; - std::string bitmap_key = "tab"; - bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; - bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; - wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); - if (bmp == nullptr) { - // Create the bitmap with color bars. - std::vector bmps; - const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; - bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp); - // Paint a lock at the system presets. - bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); - bmp = m_bitmap_cache->insert(bitmap_key, bmps); - } + std::string bitmap_key = "tab"; + bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; + bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; + bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp); + // Paint a lock at the system presets. + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height)); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } - if (preset.is_default || preset.is_system) { - ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), - (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); - if (i == m_idx_selected) - selected_preset_item = ui->GetCount() - 1; - } - else - { - nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); - if (i == m_idx_selected) - selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); - } - if (i + 1 == m_num_default_presets) - ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); + if (preset.is_default || preset.is_system) { + ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), + (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); + if (i == m_idx_selected) + selected_preset_item = ui->GetCount() - 1; + } + else + { + nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); + if (i == m_idx_selected) + selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); + } + if (i + 1 == m_num_default_presets) + ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap); + } + if (!nonsys_presets.empty()) + { + ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap); + for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { + ui->Append(it->first, *it->second); + if (it->first == selected) + selected_preset_item = ui->GetCount() - 1; + } } - if (!nonsys_presets.empty()) - { - ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap); - for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { - ui->Append(it->first, *it->second); - if (it->first == selected) - selected_preset_item = ui->GetCount() - 1; - } - } if (m_type == Preset::TYPE_PRINTER) { wxBitmap *bmp = m_bitmap_cache->find("add_printer_tab"); if (bmp == nullptr) { @@ -1119,10 +1120,10 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati } ui->Append(PresetCollection::separator("Add a new printer"), *bmp); } - ui->SetSelection(selected_preset_item); - ui->SetToolTip(ui->GetString(selected_preset_item)); + ui->SetSelection(selected_preset_item); + ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); - return selected_preset_item; + return selected_preset_item; } // Update a dirty floag of the current preset, update the labels of the UI component accordingly. @@ -1142,11 +1143,11 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) const Preset *preset = this->find_preset(preset_name, false); // The old_label could be the "----- system presets ------" or the "------- user presets --------" separator. // assert(preset != nullptr); - if (preset != nullptr) { - std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name; - if (old_label != new_label) - ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str())); - } + if (preset != nullptr) { + std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name; + if (old_label != new_label) + ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str())); + } } #ifdef __APPLE__ // wxWidgets on OSX do not upload the text of the combo box line automatically. @@ -1159,15 +1160,15 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) template void add_correct_opts_to_diff(const std::string &opt_key, t_config_option_keys& vec, const ConfigBase &other, const ConfigBase &this_c) { - const T* opt_init = static_cast(other.option(opt_key)); - const T* opt_cur = static_cast(this_c.option(opt_key)); - int opt_init_max_id = opt_init->values.size() - 1; - for (int i = 0; i < opt_cur->values.size(); i++) - { - int init_id = i <= opt_init_max_id ? i : 0; - if (opt_cur->values[i] != opt_init->values[init_id]) - vec.emplace_back(opt_key + "#" + std::to_string(i)); - } + const T* opt_init = static_cast(other.option(opt_key)); + const T* opt_cur = static_cast(this_c.option(opt_key)); + int opt_init_max_id = opt_init->values.size() - 1; + for (int i = 0; i < opt_cur->values.size(); i++) + { + int init_id = i <= opt_init_max_id ? i : 0; + if (opt_cur->values[i] != opt_init->values[init_id]) + vec.emplace_back(opt_key + "#" + std::to_string(i)); + } } // Use deep_diff to correct return of changed options, considering individual options for each extruder. @@ -1201,10 +1202,10 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi std::vector PresetCollection::dirty_options(const Preset *edited, const Preset *reference, const bool deep_compare /*= false*/) { std::vector changed; - if (edited != nullptr && reference != nullptr) { + if (edited != nullptr && reference != nullptr) { changed = deep_compare ? - deep_diff(edited->config, reference->config) : - reference->config.diff(edited->config); + deep_diff(edited->config, reference->config) : + reference->config.diff(edited->config); // The "compatible_printers" option key is handled differently from the others: // It is not mandatory. If the key is missing, it means it is compatible with any printer. // If the key exists and it is empty, it means it is compatible with no printer. @@ -1227,19 +1228,19 @@ Preset& PresetCollection::select_preset(size_t idx) idx = first_visible_idx(); m_idx_selected = idx; m_edited_preset = m_presets[idx]; - bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets; - for (size_t i = 0; i < m_num_default_presets; ++i) - m_presets[i].is_visible = default_visible; + bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets; + for (size_t i = 0; i < m_num_default_presets; ++i) + m_presets[i].is_visible = default_visible; return m_presets[idx]; } bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, bool force) -{ +{ std::string name = Preset::remove_suffix_modified(name_w_suffix); // 1) Try to find the preset by its name. auto it = this->find_preset_internal(name); size_t idx = 0; - if (it != m_presets.end() && it->name == 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 { @@ -1262,11 +1263,11 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b } bool PresetCollection::select_preset_by_name_strict(const std::string &name) -{ +{ // 1) Try to find the preset by its name. auto it = this->find_preset_internal(name); size_t idx = (size_t)-1; - if (it != m_presets.end() && it->name == 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. @@ -1333,9 +1334,9 @@ std::vector PresetCollection::system_preset_names() const ++ num; std::vector out; out.reserve(num); - for (const Preset &preset : m_presets) - if (preset.is_system) - out.emplace_back(preset.name); + for (const Preset &preset : m_presets) + if (preset.is_system) + out.emplace_back(preset.name); std::sort(out.begin(), out.end()); return out; } @@ -1343,7 +1344,7 @@ std::vector PresetCollection::system_preset_names() const // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. std::string PresetCollection::path_from_name(const std::string &new_name) const { - std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini"); + std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini"); return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); } @@ -1354,13 +1355,13 @@ void PresetCollection::clear_bitmap_cache() wxString PresetCollection::separator(const std::string &label) { - return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail()); + return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail()); } -const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const -{ +const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const +{ const ConfigOptionEnumGeneric *opt_printer_technology = config.opt("printer_technology"); - return this->default_preset((opt_printer_technology == nullptr || opt_printer_technology->value == ptFFF) ? 0 : 1); + return this->default_preset((opt_printer_technology == nullptr || opt_printer_technology->value == ptFFF) ? 0 : 1); } const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model_id) const diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 2488947bc3..937619a460 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -100,6 +100,7 @@ void Selection::set_volumes(GLVolumePtrs* volumes) update_valid(); } +// Init shall be called from the OpenGL render function, so that the OpenGL context is initialized! bool Selection::init() { if (!m_arrow.init()) @@ -1461,6 +1462,39 @@ std::vector Selection::get_unselected_volume_idxs_from(const std:: return idxs; } +void Selection::toggle_instance_printable_state() +{ + int instance_idx = get_instance_idx(); + if (instance_idx == -1) + return; + + int obj_idx = get_object_idx(); + if ((0 <= obj_idx) && (obj_idx < (int)m_model->objects.size())) + { + ModelObject* model_object = m_model->objects[obj_idx]; + if ((0 <= instance_idx) && (instance_idx < (int)model_object->instances.size())) + { + ModelInstance* instance = model_object->instances[instance_idx]; + const bool printable = !instance->printable; + + wxString snapshot_text = model_object->instances.size() == 1 ? wxString::Format("%s %s", + printable ? _(L("Set Printable")) : _(L("Set Unprintable")), model_object->name) : + printable ? _(L("Set Printable Instance")) : _(L("Set Unprintable Instance")); + wxGetApp().plater()->take_snapshot(snapshot_text); + + instance->printable = printable; + + for (GLVolume* volume : *m_volumes) + { + if ((volume->object_idx() == obj_idx) && (volume->instance_idx() == instance_idx)) + volume->printable = instance->printable; + } + + wxGetApp().obj_list()->update_printable_state(obj_idx, instance_idx); + } + } +} + void Selection::update_valid() { m_valid = (m_volumes != nullptr) && (m_model != nullptr); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 0f71cefc44..c27b4cc29d 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -336,6 +336,8 @@ public: // returns the list of idxs of the volumes contained in the given list but not in the selection std::vector get_unselected_volume_idxs_from(const std::vector& volume_idxs) const; + void toggle_instance_printable_state(); + private: void update_valid(); void update_type(); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index e9487ee155..a1bae8742e 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -58,21 +58,19 @@ std::string get_mem_info(bool format_as_html) std::string b_end = format_as_html ? "" : ""; std::string line_end = format_as_html ? "
" : "\n"; - const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack_main(); - out << b_start << "RAM size reserved for the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; - out << b_start << "RAM size occupied by the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; - -#ifdef _WIN32 - HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); - if (hProcess != nullptr) { - PROCESS_MEMORY_COUNTERS_EX pmc; - if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out << b_start << "WorkingSet [MB]: " << b_end << format_memsize_MB(pmc.WorkingSetSize) << line_end - << b_start << "PrivateBytes [MB]: " << b_end << format_memsize_MB(pmc.PrivateUsage) << line_end - << b_start << "Pagefile(peak) [MB]: " << b_end << format_memsize_MB(pmc.PagefileUsage) << "(" << format_memsize_MB(pmc.PeakPagefileUsage) << ")" << line_end; - CloseHandle(hProcess); + std::string mem_info_str = log_memory_info(true); + std::istringstream mem_info(mem_info_str); + std::string value; + while (std::getline(mem_info, value, ':')) { + out << b_start << (value+": ") << b_end; + std::getline(mem_info, value, ';'); + out << value << line_end; } -#endif + + const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack_main(); + out << b_start << "RAM size reserved for the Undo / Redo stack: " << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; + out << b_start << "RAM size occupied by the Undo / Redo stack: " << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; + return out.str(); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9d7fc20a3e..d643aa4a86 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -38,36 +38,36 @@ namespace GUI { wxDEFINE_EVENT(EVT_TAB_VALUE_CHANGED, wxCommandEvent); wxDEFINE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent); -// Tab::Tab(wxNotebook* parent, const wxString& title, const char* name) : +// Tab::Tab(wxNotebook* parent, const wxString& title, const char* name) : // m_parent(parent), m_title(title), m_name(name) Tab::Tab(wxNotebook* parent, const wxString& title, Preset::Type type) : - m_parent(parent), m_title(title), m_type(type) + m_parent(parent), m_title(title), m_type(type) { - Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/); - this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/); + this->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - m_compatible_printers.type = Preset::TYPE_PRINTER; - m_compatible_printers.key_list = "compatible_printers"; - m_compatible_printers.key_condition = "compatible_printers_condition"; - m_compatible_printers.dialog_title = _(L("Compatible printers")); - m_compatible_printers.dialog_label = _(L("Select the printers this profile is compatible with.")); + m_compatible_printers.type = Preset::TYPE_PRINTER; + m_compatible_printers.key_list = "compatible_printers"; + m_compatible_printers.key_condition = "compatible_printers_condition"; + m_compatible_printers.dialog_title = _(L("Compatible printers")); + m_compatible_printers.dialog_label = _(L("Select the printers this profile is compatible with.")); - m_compatible_prints.type = Preset::TYPE_PRINT; - m_compatible_prints.key_list = "compatible_prints"; - m_compatible_prints.key_condition = "compatible_prints_condition"; - m_compatible_prints.dialog_title = _(L("Compatible print profiles")); - m_compatible_prints.dialog_label = _(L("Select the print profiles this profile is compatible with.")); + m_compatible_prints.type = Preset::TYPE_PRINT; + m_compatible_prints.key_list = "compatible_prints"; + m_compatible_prints.key_condition = "compatible_prints_condition"; + m_compatible_prints.dialog_title = _(L("Compatible print profiles")); + m_compatible_prints.dialog_label = _(L("Select the print profiles this profile is compatible with.")); - wxGetApp().tabs_list.push_back(this); + wxGetApp().tabs_list.push_back(this); m_em_unit = wxGetApp().em_unit(); - Bind(wxEVT_SIZE, ([this](wxSizeEvent &evt) { - for (auto page : m_pages) - if (! page.get()->IsShown()) - page->layout_valid = false; - evt.Skip(); - })); + Bind(wxEVT_SIZE, ([this](wxSizeEvent &evt) { + for (auto page : m_pages) + if (! page.get()->IsShown()) + page->layout_valid = false; + evt.Skip(); + })); } void Tab::set_type() @@ -89,169 +89,169 @@ void Tab::create_preset_tab() m_preset_bundle = wxGetApp().preset_bundle; - // Vertical sizer to hold the choice menu and the rest of the page. + // Vertical sizer to hold the choice menu and the rest of the page. #ifdef __WXOSX__ - auto *main_sizer = new wxBoxSizer(wxVERTICAL); - main_sizer->SetSizeHints(this); - this->SetSizer(main_sizer); + auto *main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->SetSizeHints(this); + this->SetSizer(main_sizer); - // Create additional panel to Fit() it from OnActivate() - // It's needed for tooltip showing on OSX - m_tmp_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); - auto panel = m_tmp_panel; - auto sizer = new wxBoxSizer(wxVERTICAL); - m_tmp_panel->SetSizer(sizer); - m_tmp_panel->Layout(); + // Create additional panel to Fit() it from OnActivate() + // It's needed for tooltip showing on OSX + m_tmp_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); + auto panel = m_tmp_panel; + auto sizer = new wxBoxSizer(wxVERTICAL); + m_tmp_panel->SetSizer(sizer); + m_tmp_panel->Layout(); - main_sizer->Add(m_tmp_panel, 1, wxEXPAND | wxALL, 0); + main_sizer->Add(m_tmp_panel, 1, wxEXPAND | wxALL, 0); #else - Tab *panel = this; - auto *sizer = new wxBoxSizer(wxVERTICAL); - sizer->SetSizeHints(panel); - panel->SetSizer(sizer); + Tab *panel = this; + auto *sizer = new wxBoxSizer(wxVERTICAL); + sizer->SetSizeHints(panel); + panel->SetSizer(sizer); #endif //__WXOSX__ - // preset chooser + // preset chooser m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(35 * m_em_unit, -1), 0, 0, wxCB_READONLY); - auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - //buttons + //buttons m_scaled_buttons.reserve(6); m_scaled_buttons.reserve(2); add_scaled_button(panel, &m_btn_save_preset, "save"); add_scaled_button(panel, &m_btn_delete_preset, "cross"); - m_show_incompatible_presets = false; - add_scaled_bitmap(this, m_bmp_show_incompatible_presets, "flag_red"); - add_scaled_bitmap(this, m_bmp_hide_incompatible_presets, "flag_green"); + m_show_incompatible_presets = false; + add_scaled_bitmap(this, m_bmp_show_incompatible_presets, "flag_red"); + add_scaled_bitmap(this, m_bmp_hide_incompatible_presets, "flag_green"); add_scaled_button(panel, &m_btn_hide_incompatible_presets, m_bmp_hide_incompatible_presets.name()); // TRN "Save current Settings" - m_btn_save_preset->SetToolTip(wxString::Format(_(L("Save current %s")),m_title)); - m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); - m_btn_delete_preset->Disable(); + m_btn_save_preset->SetToolTip(wxString::Format(_(L("Save current %s")),m_title)); + m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); + m_btn_delete_preset->Disable(); add_scaled_button(panel, &m_question_btn, "question"); - m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n" - "or click this button."))); + m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n" + "or click this button."))); - // Determine the theme color of OS (dark or light) + // Determine the theme color of OS (dark or light) auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - add_scaled_bitmap(this, m_bmp_value_lock , luma >= 128 ? "lock_closed" : "lock_closed_white"); - add_scaled_bitmap(this, m_bmp_value_unlock, "lock_open"); - m_bmp_non_system = &m_bmp_white_bullet; - // Bitmaps to be shown on the "Undo user changes" button next to each input field. - add_scaled_bitmap(this, m_bmp_value_revert, "undo"); - add_scaled_bitmap(this, m_bmp_white_bullet, luma >= 128 ? "dot" : "dot_white"); + // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + add_scaled_bitmap(this, m_bmp_value_lock , luma >= 128 ? "lock_closed" : "lock_closed_white"); + add_scaled_bitmap(this, m_bmp_value_unlock, "lock_open"); + m_bmp_non_system = &m_bmp_white_bullet; + // Bitmaps to be shown on the "Undo user changes" button next to each input field. + add_scaled_bitmap(this, m_bmp_value_revert, "undo"); + add_scaled_bitmap(this, m_bmp_white_bullet, luma >= 128 ? "dot" : "dot_white"); - fill_icon_descriptions(); - set_tooltips_text(); + fill_icon_descriptions(); + set_tooltips_text(); add_scaled_button(panel, &m_undo_btn, m_bmp_white_bullet.name()); add_scaled_button(panel, &m_undo_to_sys_btn, m_bmp_white_bullet.name()); - m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(); })); - m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(true); })); - m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) - { - auto dlg = new ButtonsDescription(this, m_icon_descriptions); - if (dlg->ShowModal() == wxID_OK) { - // Colors for ui "decoration" + m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(); })); + m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_roll_back_value(true); })); + m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) + { + auto dlg = new ButtonsDescription(this, m_icon_descriptions); + if (dlg->ShowModal() == wxID_OK) { + // Colors for ui "decoration" for (Tab *tab : wxGetApp().tabs_list) { tab->m_sys_label_clr = wxGetApp().get_label_clr_sys(); tab->m_modified_label_clr = wxGetApp().get_label_clr_modified(); - tab->update_labels_colour(); - } - } - })); + tab->update_labels_colour(); + } + } + })); - // Colors for ui "decoration" - m_sys_label_clr = wxGetApp().get_label_clr_sys(); - m_modified_label_clr = wxGetApp().get_label_clr_modified(); - m_default_text_clr = wxGetApp().get_label_clr_default(); + // Colors for ui "decoration" + m_sys_label_clr = wxGetApp().get_label_clr_sys(); + m_modified_label_clr = wxGetApp().get_label_clr_modified(); + m_default_text_clr = wxGetApp().get_label_clr_default(); // Sizer with buttons for mode changing m_mode_sizer = new ModeSizer(panel); const float scale_factor = /*wxGetApp().*/em_unit(this)*0.1;// GetContentScaleFactor(); - m_hsizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(m_hsizer, 0, wxEXPAND | wxBOTTOM, 3); - m_hsizer->Add(m_presets_choice, 0, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3); - m_hsizer->AddSpacer(int(4*scale_factor)); - m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_hsizer, 0, wxEXPAND | wxBOTTOM, 3); + m_hsizer->Add(m_presets_choice, 0, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3); + m_hsizer->AddSpacer(int(4*scale_factor)); + m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(4 * scale_factor)); - m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(16 * scale_factor)); - m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(64 * scale_factor)); - m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); - m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(32 * scale_factor)); - m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL); // m_hsizer->AddStretchSpacer(32); - // StretchSpacer has a strange behavior under OSX, so + // StretchSpacer has a strange behavior under OSX, so // There is used just additional sizer for m_mode_sizer with right alignment auto mode_sizer = new wxBoxSizer(wxVERTICAL); mode_sizer->Add(m_mode_sizer, 1, wxALIGN_RIGHT); m_hsizer->Add(mode_sizer, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, wxOSX ? 15 : 10); - //Horizontal sizer to hold the tree and the selected page. - m_hsizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(m_hsizer, 1, wxEXPAND, 0); + //Horizontal sizer to hold the tree and the selected page. + m_hsizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_hsizer, 1, wxEXPAND, 0); - //left vertical sizer - m_left_sizer = new wxBoxSizer(wxVERTICAL); - m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); + //left vertical sizer + m_left_sizer = new wxBoxSizer(wxVERTICAL); + m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); - // tree + // tree m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1), - wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS); - m_left_sizer->Add(m_treectrl, 1, wxEXPAND); + wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS); + m_left_sizer->Add(m_treectrl, 1, wxEXPAND); const int img_sz = int(16 * scale_factor + 0.5f); m_icons = new wxImageList(img_sz, img_sz, true, 1); - // Index of the last icon inserted into $self->{icons}. - m_icon_count = -1; - m_treectrl->AssignImageList(m_icons); - m_treectrl->AddRoot("root"); - m_treectrl->SetIndent(0); - m_disable_tree_sel_changed_event = 0; + // Index of the last icon inserted into $self->{icons}. + m_icon_count = -1; + m_treectrl->AssignImageList(m_icons); + m_treectrl->AddRoot("root"); + m_treectrl->SetIndent(0); + m_disable_tree_sel_changed_event = 0; - m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); - m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); + m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); + m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); - m_presets_choice->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { - //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, - //! but the OSX version derived from wxOwnerDrawnCombo, instead of: - //! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data()); - //! we doing next: - int selected_item = m_presets_choice->GetSelection(); - if (m_selected_preset_item == selected_item && !m_presets->current_is_dirty()) - return; - if (selected_item >= 0) { - std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); - if (selected_string.find(PresetCollection::separator_head()) == 0 - /*selected_string == "------- System presets -------" || - selected_string == "------- User presets -------"*/) { - m_presets_choice->SetSelection(m_selected_preset_item); - if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer"))) - wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); - return; - } - m_selected_preset_item = selected_item; - select_preset(selected_string); - } - })); + m_presets_choice->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { + //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, + //! but the OSX version derived from wxOwnerDrawnCombo, instead of: + //! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data()); + //! we doing next: + int selected_item = m_presets_choice->GetSelection(); + if (m_selected_preset_item == selected_item && !m_presets->current_is_dirty()) + return; + if (selected_item >= 0) { + std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); + if (selected_string.find(PresetCollection::separator_head()) == 0 + /*selected_string == "------- System presets -------" || + selected_string == "------- User presets -------"*/) { + m_presets_choice->SetSelection(m_selected_preset_item); + if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer"))) + wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); }); + return; + } + m_selected_preset_item = selected_item; + select_preset(selected_string); + } + })); - m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); })); - m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); })); - m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { - toggle_show_hide_incompatible(); - })); + m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); })); + m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); })); + m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { + toggle_show_hide_incompatible(); + })); // Fill cache for mode bitmaps m_mode_bitmap_cache.reserve(3); @@ -259,24 +259,24 @@ void Tab::create_preset_tab() m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_advanced_.png")); m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_expert_.png")); - // Initialize the DynamicPrintConfig by default keys/values. - build(); - rebuild_page_tree(); + // Initialize the DynamicPrintConfig by default keys/values. + build(); + rebuild_page_tree(); m_complited = true; } -void Tab::add_scaled_button(wxWindow* parent, - ScalableButton** btn, - const std::string& icon_name, - const wxString& label/* = wxEmptyString*/, +void Tab::add_scaled_button(wxWindow* parent, + ScalableButton** btn, + const std::string& icon_name, + const wxString& label/* = wxEmptyString*/, long style /*= wxBU_EXACTFIT | wxNO_BORDER*/) { *btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, style); m_scaled_buttons.push_back(*btn); } -void Tab::add_scaled_bitmap(wxWindow* parent, - ScalableBitmap& bmp, +void Tab::add_scaled_bitmap(wxWindow* parent, + ScalableBitmap& bmp, const std::string& icon_name) { bmp = ScalableBitmap(parent, icon_name); @@ -285,233 +285,235 @@ void Tab::add_scaled_bitmap(wxWindow* parent, void Tab::load_initial_data() { - m_config = &m_presets->get_edited_preset().config; - bool has_parent = m_presets->get_selected_preset_parent() != nullptr; - m_bmp_non_system = has_parent ? &m_bmp_value_unlock : &m_bmp_white_bullet; - m_ttg_non_system = has_parent ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; - m_tt_non_system = has_parent ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; + m_config = &m_presets->get_edited_preset().config; + bool has_parent = m_presets->get_selected_preset_parent() != nullptr; + m_bmp_non_system = has_parent ? &m_bmp_value_unlock : &m_bmp_white_bullet; + m_ttg_non_system = has_parent ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; + m_tt_non_system = has_parent ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; } Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages /*= false*/) { - // Index of icon in an icon list $self->{icons}. - auto icon_idx = 0; - if (!icon.empty()) { - icon_idx = (m_icon_index.find(icon) == m_icon_index.end()) ? -1 : m_icon_index.at(icon); - if (icon_idx == -1) { - // Add a new icon to the icon list. + // Index of icon in an icon list $self->{icons}. + auto icon_idx = 0; + if (!icon.empty()) { + icon_idx = (m_icon_index.find(icon) == m_icon_index.end()) ? -1 : m_icon_index.at(icon); + if (icon_idx == -1) { + // Add a new icon to the icon list. m_scaled_icons_list.push_back(ScalableBitmap(this, icon)); m_icons->Add(m_scaled_icons_list.back().bmp()); icon_idx = ++m_icon_count; - m_icon_index[icon] = icon_idx; - } - } - // Initialize the page. + m_icon_index[icon] = icon_idx; + } + } + // Initialize the page. #ifdef __WXOSX__ - auto panel = m_tmp_panel; + auto panel = m_tmp_panel; #else - auto panel = this; + auto panel = this; #endif - PageShp page(new Page(panel, title, icon_idx, m_mode_bitmap_cache)); + PageShp page(new Page(panel, title, icon_idx, m_mode_bitmap_cache)); // page->SetBackgroundStyle(wxBG_STYLE_SYSTEM); #ifdef __WINDOWS__ // page->SetDoubleBuffered(true); #endif //__WINDOWS__ - page->SetScrollbars(1, 20, 1, 2); - page->Hide(); - m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); + page->SetScrollbars(1, 20, 1, 2); + page->Hide(); + m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); - if (!is_extruder_pages) - m_pages.push_back(page); + if (!is_extruder_pages) + m_pages.push_back(page); - page->set_config(m_config); - return page; + page->set_config(m_config); + return page; } void Tab::OnActivate() { -#ifdef __WXOSX__ - wxWindowUpdateLocker noUpdates(this); +#ifdef __WXOSX__ + wxWindowUpdateLocker noUpdates(this); - auto size = GetSizer()->GetSize(); - m_tmp_panel->GetSizer()->SetMinSize(size.x + m_size_move, size.y); - Fit(); - m_size_move *= -1; + auto size = GetSizer()->GetSize(); + m_tmp_panel->GetSizer()->SetMinSize(size.x + m_size_move, size.y); + Fit(); + m_size_move *= -1; #endif // __WXOSX__ } void Tab::update_labels_colour() { // Freeze(); - //update options "decoration" - for (const auto opt : m_options_list) - { - const wxColour *color = &m_sys_label_clr; + //update options "decoration" + for (const auto opt : m_options_list) + { + const wxColour *color = &m_sys_label_clr; - // value isn't equal to system value - if ((opt.second & osSystemValue) == 0) { - // value is equal to last saved - if ((opt.second & osInitValue) != 0) - color = &m_default_text_clr; - // value is modified - else - color = &m_modified_label_clr; - } - if (opt.first == "bed_shape" || opt.first == "compatible_prints" || opt.first == "compatible_printers") { - if (m_colored_Label != nullptr) { - m_colored_Label->SetForegroundColour(*color); - m_colored_Label->Refresh(true); - } - continue; - } + // value isn't equal to system value + if ((opt.second & osSystemValue) == 0) { + // value is equal to last saved + if ((opt.second & osInitValue) != 0) + color = &m_default_text_clr; + // value is modified + else + color = &m_modified_label_clr; + } + if (opt.first == "bed_shape" || opt.first == "compatible_prints" || opt.first == "compatible_printers") { + if (m_colored_Label != nullptr) { + m_colored_Label->SetForegroundColour(*color); + m_colored_Label->Refresh(true); + } + continue; + } - Field* field = get_field(opt.first); - if (field == nullptr) continue; - field->set_label_colour_force(color); - } + Field* field = get_field(opt.first); + if (field == nullptr) continue; + field->set_label_colour_force(color); + } // Thaw(); - auto cur_item = m_treectrl->GetFirstVisibleItem(); - while (cur_item) { - auto title = m_treectrl->GetItemText(cur_item); - for (auto page : m_pages) - { - if (page->title() != title) - continue; - - const wxColor *clr = !page->m_is_nonsys_values ? &m_sys_label_clr : - page->m_is_modified_values ? &m_modified_label_clr : - &m_default_text_clr; + auto cur_item = m_treectrl->GetFirstVisibleItem(); + if (!cur_item || !m_treectrl->IsVisible(cur_item)) + return; + while (cur_item) { + auto title = m_treectrl->GetItemText(cur_item); + for (auto page : m_pages) + { + if (page->title() != title) + continue; - m_treectrl->SetItemTextColour(cur_item, *clr); - break; - } - cur_item = m_treectrl->GetNextVisible(cur_item); - } + const wxColor *clr = !page->m_is_nonsys_values ? &m_sys_label_clr : + page->m_is_modified_values ? &m_modified_label_clr : + &m_default_text_clr; + + m_treectrl->SetItemTextColour(cur_item, *clr); + break; + } + cur_item = m_treectrl->GetNextVisible(cur_item); + } } // Update UI according to changes void Tab::update_changed_ui() { - if (m_postpone_update_ui) - return; + if (m_postpone_update_ui) + return; - const bool deep_compare = (m_type == Slic3r::Preset::TYPE_PRINTER || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL); - auto dirty_options = m_presets->current_dirty_options(deep_compare); - auto nonsys_options = m_presets->current_different_from_parent_options(deep_compare); + const bool deep_compare = (m_type == Slic3r::Preset::TYPE_PRINTER || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL); + auto dirty_options = m_presets->current_dirty_options(deep_compare); + auto nonsys_options = m_presets->current_different_from_parent_options(deep_compare); if (m_type == Slic3r::Preset::TYPE_PRINTER) { - TabPrinter* tab = static_cast(this); - if (tab->m_initial_extruders_count != tab->m_extruders_count) - dirty_options.emplace_back("extruders_count"); - if (tab->m_sys_extruders_count != tab->m_extruders_count) - nonsys_options.emplace_back("extruders_count"); - } + TabPrinter* tab = static_cast(this); + if (tab->m_initial_extruders_count != tab->m_extruders_count) + dirty_options.emplace_back("extruders_count"); + if (tab->m_sys_extruders_count != tab->m_extruders_count) + nonsys_options.emplace_back("extruders_count"); + } - for (auto& it : m_options_list) - it.second = m_opt_status_value; + for (auto& it : m_options_list) + it.second = m_opt_status_value; - for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue; - for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue; + for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue; + for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue; // Freeze(); - //update options "decoration" - for (const auto opt : m_options_list) - { - bool is_nonsys_value = false; - bool is_modified_value = true; - const ScalableBitmap *sys_icon = &m_bmp_value_lock; - const ScalableBitmap *icon = &m_bmp_value_revert; + //update options "decoration" + for (const auto opt : m_options_list) + { + bool is_nonsys_value = false; + bool is_modified_value = true; + const ScalableBitmap *sys_icon = &m_bmp_value_lock; + const ScalableBitmap *icon = &m_bmp_value_revert; - const wxColour *color = m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr; + const wxColour *color = m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr; - const wxString *sys_tt = &m_tt_value_lock; - const wxString *tt = &m_tt_value_revert; + const wxString *sys_tt = &m_tt_value_lock; + const wxString *tt = &m_tt_value_revert; - // value isn't equal to system value - if ((opt.second & osSystemValue) == 0) { - is_nonsys_value = true; - sys_icon = m_bmp_non_system; - sys_tt = m_tt_non_system; - // value is equal to last saved - if ((opt.second & osInitValue) != 0) - color = &m_default_text_clr; - // value is modified - else - color = &m_modified_label_clr; - } - if ((opt.second & osInitValue) != 0) - { - is_modified_value = false; - icon = &m_bmp_white_bullet; - tt = &m_tt_white_bullet; - } - if (opt.first == "bed_shape" || opt.first == "compatible_prints" || opt.first == "compatible_printers") { - if (m_colored_Label != nullptr) { - m_colored_Label->SetForegroundColour(*color); - m_colored_Label->Refresh(true); - } - continue; - } + // value isn't equal to system value + if ((opt.second & osSystemValue) == 0) { + is_nonsys_value = true; + sys_icon = m_bmp_non_system; + sys_tt = m_tt_non_system; + // value is equal to last saved + if ((opt.second & osInitValue) != 0) + color = &m_default_text_clr; + // value is modified + else + color = &m_modified_label_clr; + } + if ((opt.second & osInitValue) != 0) + { + is_modified_value = false; + icon = &m_bmp_white_bullet; + tt = &m_tt_white_bullet; + } + if (opt.first == "bed_shape" || opt.first == "compatible_prints" || opt.first == "compatible_printers") { + if (m_colored_Label != nullptr) { + m_colored_Label->SetForegroundColour(*color); + m_colored_Label->Refresh(true); + } + continue; + } - Field* field = get_field(opt.first); - if (field == nullptr) continue; - field->m_is_nonsys_value = is_nonsys_value; - field->m_is_modified_value = is_modified_value; - field->set_undo_bitmap(icon); - field->set_undo_to_sys_bitmap(sys_icon); - field->set_undo_tooltip(tt); - field->set_undo_to_sys_tooltip(sys_tt); - field->set_label_colour(color); - } + Field* field = get_field(opt.first); + if (field == nullptr) continue; + field->m_is_nonsys_value = is_nonsys_value; + field->m_is_modified_value = is_modified_value; + field->set_undo_bitmap(icon); + field->set_undo_to_sys_bitmap(sys_icon); + field->set_undo_tooltip(tt); + field->set_undo_to_sys_tooltip(sys_tt); + field->set_label_colour(color); + } // Thaw(); - wxTheApp->CallAfter([this]() { + wxTheApp->CallAfter([this]() { if (parent()) //To avoid a crash, parent should be exist for a moment of a tree updating - update_changed_tree_ui(); - }); + update_changed_tree_ui(); + }); } void Tab::init_options_list() { - if (!m_options_list.empty()) - m_options_list.clear(); + if (!m_options_list.empty()) + m_options_list.clear(); - for (const auto opt_key : m_config->keys()) - m_options_list.emplace(opt_key, m_opt_status_value); + for (const auto opt_key : m_config->keys()) + m_options_list.emplace(opt_key, m_opt_status_value); } template void add_correct_opts_to_options_list(const std::string &opt_key, std::map& map, Tab *tab, const int& value) { - T *opt_cur = static_cast(tab->m_config->option(opt_key)); - for (int i = 0; i < opt_cur->values.size(); i++) - map.emplace(opt_key + "#" + std::to_string(i), value); + T *opt_cur = static_cast(tab->m_config->option(opt_key)); + for (int i = 0; i < opt_cur->values.size(); i++) + map.emplace(opt_key + "#" + std::to_string(i), value); } void TabPrinter::init_options_list() { - if (!m_options_list.empty()) - m_options_list.clear(); + if (!m_options_list.empty()) + m_options_list.clear(); - for (const auto opt_key : m_config->keys()) - { - if (opt_key == "bed_shape") { - m_options_list.emplace(opt_key, m_opt_status_value); - continue; - } - switch (m_config->option(opt_key)->type()) - { - case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - default: m_options_list.emplace(opt_key, m_opt_status_value); break; - } - } - m_options_list.emplace("extruders_count", m_opt_status_value); + for (const auto opt_key : m_config->keys()) + { + if (opt_key == "bed_shape") { + m_options_list.emplace(opt_key, m_opt_status_value); + continue; + } + switch (m_config->option(opt_key)->type()) + { + case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + default: m_options_list.emplace(opt_key, m_opt_status_value); break; + } + } + m_options_list.emplace("extruders_count", m_opt_status_value); } void TabSLAMaterial::init_options_list() @@ -540,184 +542,184 @@ void TabSLAMaterial::init_options_list() void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page) { - auto opt = m_options_list.find(opt_key); - if (sys_page) sys_page = (opt->second & osSystemValue) != 0; - modified_page |= (opt->second & osInitValue) == 0; + auto opt = m_options_list.find(opt_key); + if (sys_page) sys_page = (opt->second & osSystemValue) != 0; + modified_page |= (opt->second & osInitValue) == 0; } void Tab::update_changed_tree_ui() { - if (m_options_list.empty()) + if (m_options_list.empty()) return; - auto cur_item = m_treectrl->GetFirstVisibleItem(); + auto cur_item = m_treectrl->GetFirstVisibleItem(); if (!cur_item || !m_treectrl->IsVisible(cur_item)) return; - auto selected_item = m_treectrl->GetSelection(); - auto selection = selected_item ? m_treectrl->GetItemText(selected_item) : ""; + auto selected_item = m_treectrl->GetSelection(); + auto selection = selected_item ? m_treectrl->GetItemText(selected_item) : ""; - while (cur_item) { - auto title = m_treectrl->GetItemText(cur_item); - for (auto page : m_pages) - { - if (page->title() != title) - continue; - bool sys_page = true; - bool modified_page = false; - if (title == _("General")) { - std::initializer_list optional_keys{ "extruders_count", "bed_shape" }; - for (auto &opt_key : optional_keys) { - get_sys_and_mod_flags(opt_key, sys_page, modified_page); - } - } - if (title == _("Dependencies")) { - if (m_type == Slic3r::Preset::TYPE_PRINTER) { - sys_page = m_presets->get_selected_preset_parent() != nullptr; - modified_page = false; - } else { - if (m_type == Slic3r::Preset::TYPE_FILAMENT || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL) - get_sys_and_mod_flags("compatible_prints", sys_page, modified_page); - get_sys_and_mod_flags("compatible_printers", sys_page, modified_page); - } - } - for (auto group : page->m_optgroups) - { - if (!sys_page && modified_page) - break; - for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { - const std::string& opt_key = it->first; - get_sys_and_mod_flags(opt_key, sys_page, modified_page); - } - } + while (cur_item) { + auto title = m_treectrl->GetItemText(cur_item); + for (auto page : m_pages) + { + if (page->title() != title) + continue; + bool sys_page = true; + bool modified_page = false; + if (title == _("General")) { + std::initializer_list optional_keys{ "extruders_count", "bed_shape" }; + for (auto &opt_key : optional_keys) { + get_sys_and_mod_flags(opt_key, sys_page, modified_page); + } + } + if (title == _("Dependencies")) { + if (m_type == Slic3r::Preset::TYPE_PRINTER) { + sys_page = m_presets->get_selected_preset_parent() != nullptr; + modified_page = false; + } else { + if (m_type == Slic3r::Preset::TYPE_FILAMENT || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL) + get_sys_and_mod_flags("compatible_prints", sys_page, modified_page); + get_sys_and_mod_flags("compatible_printers", sys_page, modified_page); + } + } + for (auto group : page->m_optgroups) + { + if (!sys_page && modified_page) + break; + for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { + const std::string& opt_key = it->first; + get_sys_and_mod_flags(opt_key, sys_page, modified_page); + } + } - const wxColor *clr = sys_page ? (m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr) : - modified_page ? &m_modified_label_clr : - &m_default_text_clr; + const wxColor *clr = sys_page ? (m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr) : + modified_page ? &m_modified_label_clr : + &m_default_text_clr; - if (page->set_item_colour(clr)) - m_treectrl->SetItemTextColour(cur_item, *clr); + if (page->set_item_colour(clr)) + m_treectrl->SetItemTextColour(cur_item, *clr); - page->m_is_nonsys_values = !sys_page; - page->m_is_modified_values = modified_page; + page->m_is_nonsys_values = !sys_page; + page->m_is_modified_values = modified_page; - if (selection == title) { - m_is_nonsys_values = page->m_is_nonsys_values; - m_is_modified_values = page->m_is_modified_values; - } - break; - } + if (selection == title) { + m_is_nonsys_values = page->m_is_nonsys_values; + m_is_modified_values = page->m_is_modified_values; + } + break; + } auto next_item = m_treectrl->GetNextVisible(cur_item); cur_item = next_item; - } - update_undo_buttons(); + } + update_undo_buttons(); } void Tab::update_undo_buttons() { - m_undo_btn-> SetBitmap_(m_is_modified_values ? m_bmp_value_revert: m_bmp_white_bullet); - m_undo_to_sys_btn-> SetBitmap_(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock); + m_undo_btn-> SetBitmap_(m_is_modified_values ? m_bmp_value_revert: m_bmp_white_bullet); + m_undo_to_sys_btn-> SetBitmap_(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock); - m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet); - m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock); + m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet); + m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock); } void Tab::on_roll_back_value(const bool to_sys /*= true*/) { - int os; - if (to_sys) { - if (!m_is_nonsys_values) return; - os = osSystemValue; - } - else { - if (!m_is_modified_values) return; - os = osInitValue; - } + int os; + if (to_sys) { + if (!m_is_nonsys_values) return; + os = osSystemValue; + } + else { + if (!m_is_modified_values) return; + os = osInitValue; + } - m_postpone_update_ui = true; + m_postpone_update_ui = true; - auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); - for (auto page : m_pages) - if (page->title() == selection) { - for (auto group : page->m_optgroups) { - if (group->title == _("Capabilities")) { - if ((m_options_list["extruders_count"] & os) == 0) - to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count"); - } - if (group->title == _("Size and coordinates")) { - if ((m_options_list["bed_shape"] & os) == 0) { - to_sys ? group->back_to_sys_value("bed_shape") : group->back_to_initial_value("bed_shape"); - load_key_value("bed_shape", true/*some value*/, true); - } + auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); + for (auto page : m_pages) + if (page->title() == selection) { + for (auto group : page->m_optgroups) { + if (group->title == _("Capabilities")) { + if ((m_options_list["extruders_count"] & os) == 0) + to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count"); + } + if (group->title == _("Size and coordinates")) { + if ((m_options_list["bed_shape"] & os) == 0) { + to_sys ? group->back_to_sys_value("bed_shape") : group->back_to_initial_value("bed_shape"); + load_key_value("bed_shape", true/*some value*/, true); + } - } - if (group->title == _("Profile dependencies")) { - if (m_type != Slic3r::Preset::TYPE_PRINTER && (m_options_list["compatible_printers"] & os) == 0) { - to_sys ? group->back_to_sys_value("compatible_printers") : group->back_to_initial_value("compatible_printers"); - load_key_value("compatible_printers", true/*some value*/, true); + } + if (group->title == _("Profile dependencies")) { + if (m_type != Slic3r::Preset::TYPE_PRINTER && (m_options_list["compatible_printers"] & os) == 0) { + to_sys ? group->back_to_sys_value("compatible_printers") : group->back_to_initial_value("compatible_printers"); + load_key_value("compatible_printers", true/*some value*/, true); - bool is_empty = m_config->option("compatible_printers")->values.empty(); - m_compatible_printers.checkbox->SetValue(is_empty); - is_empty ? m_compatible_printers.btn->Disable() : m_compatible_printers.btn->Enable(); - } - if ((m_type == Slic3r::Preset::TYPE_PRINT || m_type == Slic3r::Preset::TYPE_SLA_PRINT) && (m_options_list["compatible_prints"] & os) == 0) { - to_sys ? group->back_to_sys_value("compatible_prints") : group->back_to_initial_value("compatible_prints"); - load_key_value("compatible_prints", true/*some value*/, true); + bool is_empty = m_config->option("compatible_printers")->values.empty(); + m_compatible_printers.checkbox->SetValue(is_empty); + is_empty ? m_compatible_printers.btn->Disable() : m_compatible_printers.btn->Enable(); + } + if ((m_type == Slic3r::Preset::TYPE_PRINT || m_type == Slic3r::Preset::TYPE_SLA_PRINT) && (m_options_list["compatible_prints"] & os) == 0) { + to_sys ? group->back_to_sys_value("compatible_prints") : group->back_to_initial_value("compatible_prints"); + load_key_value("compatible_prints", true/*some value*/, true); - bool is_empty = m_config->option("compatible_prints")->values.empty(); - m_compatible_prints.checkbox->SetValue(is_empty); - is_empty ? m_compatible_prints.btn->Disable() : m_compatible_prints.btn->Enable(); - } - } - for (auto kvp : group->m_opt_map) { - const std::string& opt_key = kvp.first; - if ((m_options_list[opt_key] & os) == 0) - to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key); - } - } - break; - } + bool is_empty = m_config->option("compatible_prints")->values.empty(); + m_compatible_prints.checkbox->SetValue(is_empty); + is_empty ? m_compatible_prints.btn->Disable() : m_compatible_prints.btn->Enable(); + } + } + for (auto kvp : group->m_opt_map) { + const std::string& opt_key = kvp.first; + if ((m_options_list[opt_key] & os) == 0) + to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key); + } + } + break; + } - m_postpone_update_ui = false; - update_changed_ui(); + m_postpone_update_ui = false; + update_changed_ui(); } // Update the combo box label of the selected preset based on its "dirty" state, // comparing the selected preset config with $self->{config}. void Tab::update_dirty() { - m_presets->update_dirty_ui(m_presets_choice); - on_presets_changed(); - update_changed_ui(); + m_presets->update_dirty_ui(m_presets_choice); + on_presets_changed(); + update_changed_ui(); } void Tab::update_tab_ui() { - m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets, m_em_unit); + m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets, m_em_unit); } // Load a provied DynamicConfig into the tab, modifying the active preset. // This could be used for example by setting a Wipe Tower position by interactive manipulation in the 3D view. void Tab::load_config(const DynamicPrintConfig& config) { - bool modified = 0; - for(auto opt_key : m_config->diff(config)) { - m_config->set_key_value(opt_key, config.option(opt_key)->clone()); - modified = 1; - } - if (modified) { - update_dirty(); - //# Initialize UI components with the config values. - reload_config(); - update(); - } + bool modified = 0; + for(auto opt_key : m_config->diff(config)) { + m_config->set_key_value(opt_key, config.option(opt_key)->clone()); + modified = 1; + } + if (modified) { + update_dirty(); + //# Initialize UI components with the config values. + reload_config(); + update(); + } } // Reload current $self->{config} (aka $self->{presets}->edited_preset->config) into the UI fields. void Tab::reload_config() { // Freeze(); - for (auto page : m_pages) - page->reload_config(); + for (auto page : m_pages) + page->reload_config(); // Thaw(); } @@ -729,20 +731,20 @@ void Tab::update_mode() m_mode_sizer->SetMode(m_mode); update_visibility(); + + update_changed_tree_ui(); } void Tab::update_visibility() { Freeze(); // There is needed Freeze/Thaw to avoid a flashing after Show/Layout - for (auto page : m_pages) + for (auto page : m_pages) page->update_visibility(m_mode); update_page_tree_visibility(); Layout(); - Thaw(); - - update_changed_tree_ui(); + Thaw(); } void Tab::msw_rescale() @@ -783,25 +785,25 @@ void Tab::msw_rescale() Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const { - Field* field = nullptr; - for (auto page : m_pages) { - field = page->get_field(opt_key, opt_index); - if (field != nullptr) - return field; - } - return field; + Field* field = nullptr; + for (auto page : m_pages) { + field = page->get_field(opt_key, opt_index); + if (field != nullptr) + return field; + } + return field; } // Set a key/value pair on this page. Return true if the value has been modified. // Currently used for distributing extruders_count over preset pages of Slic3r::GUI::Tab::Printer // after a preset is loaded. bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value) { - bool changed = false; - for(auto page: m_pages) { - if (page->set_value(opt_key, value)) - changed = true; - } - return changed; + bool changed = false; + for(auto page: m_pages) { + if (page->set_value(opt_key, value)) + changed = true; + } + return changed; } // To be called by custom widgets, load a value into a config, @@ -810,54 +812,62 @@ bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value) // and value can be some random value because in this case it will not been used void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value /*= false*/) { - if (!saved_value) change_opt_value(*m_config, opt_key, value); - // Mark the print & filament enabled if they are compatible with the currently selected preset. - if (opt_key == "compatible_printers" || opt_key == "compatible_prints") { - // Don't select another profile if this profile happens to become incompatible. - m_preset_bundle->update_compatible(false); - } - m_presets->update_dirty_ui(m_presets_choice); - on_presets_changed(); - update(); + if (!saved_value) change_opt_value(*m_config, opt_key, value); + // Mark the print & filament enabled if they are compatible with the currently selected preset. + if (opt_key == "compatible_printers" || opt_key == "compatible_prints") { + // Don't select another profile if this profile happens to become incompatible. + m_preset_bundle->update_compatible(false); + } + m_presets->update_dirty_ui(m_presets_choice); + on_presets_changed(); + update(); } static wxString support_combo_value_for_config(const DynamicPrintConfig &config, bool is_fff) { const std::string support = is_fff ? "support_material" : "supports_enable"; const std::string buildplate_only = is_fff ? "support_material_buildplate_only" : "support_buildplate_only"; - return - ! config.opt_bool(support) ? - _("None") : - (is_fff && !config.opt_bool("support_material_auto")) ? - _("For support enforcers only") : + return + ! config.opt_bool(support) ? + _("None") : + (is_fff && !config.opt_bool("support_material_auto")) ? + _("For support enforcers only") : (config.opt_bool(buildplate_only) ? _("Support on build plate only") : - _("Everywhere")); + _("Everywhere")); +} + +static wxString pad_combo_value_for_config(const DynamicPrintConfig &config) +{ + return config.opt_bool("pad_enable") ? (config.opt_bool("pad_zero_elevation") ? _("Around object") : _("Below object")) : _("None"); } void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { - if (wxGetApp().plater() == nullptr) { - return; - } + if (wxGetApp().plater() == nullptr) { + return; + } const bool is_fff = supports_printer_technology(ptFFF); - ConfigOptionsGroup* og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); + ConfigOptionsGroup* og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); if (opt_key == "fill_density" || opt_key == "pad_enable") - { + { boost::any val = og_freq_chng_params->get_config_value(*m_config, opt_key); og_freq_chng_params->set_value(opt_key, val); - } + } - if (is_fff ? - (opt_key == "support_material" || opt_key == "support_material_auto" || opt_key == "support_material_buildplate_only") : - (opt_key == "supports_enable" || opt_key == "support_buildplate_only")) - og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); + if (is_fff ? + (opt_key == "support_material" || opt_key == "support_material_auto" || opt_key == "support_material_buildplate_only") : + (opt_key == "supports_enable" || opt_key == "support_buildplate_only")) + og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); - if (opt_key == "brim_width") - { - bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; + if (! is_fff && (opt_key == "pad_enable" || opt_key == "pad_zero_elevation")) + og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config)); + + if (opt_key == "brim_width") + { + bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; og_freq_chng_params->set_value("brim", val); - } + } if (opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" ) update_wiping_button_visibility(); @@ -865,7 +875,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) if (opt_key == "extruders_count") wxGetApp().plater()->on_extruders_change(boost::any_cast(value)); - update(); + update(); } // Show/hide the 'purging volumes' button @@ -890,13 +900,13 @@ void Tab::update_wiping_button_visibility() { // to update number of "filament" selection boxes when the number of extruders change. void Tab::on_presets_changed() { - if (wxGetApp().plater() == nullptr) { - return; - } + if (wxGetApp().plater() == nullptr) { + return; + } // Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets wxGetApp().plater()->sidebar().update_presets(m_type); - update_preset_description_line(); + update_preset_description_line(); // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. for (auto t: m_dependent_tabs) @@ -912,81 +922,83 @@ void Tab::on_presets_changed() void Tab::update_preset_description_line() { - const Preset* parent = m_presets->get_selected_preset_parent(); - const Preset& preset = m_presets->get_edited_preset(); + const Preset* parent = m_presets->get_selected_preset_parent(); + const Preset& preset = m_presets->get_edited_preset(); - wxString description_line; + wxString description_line; - if (preset.is_default) { - description_line = _(L("This is a default preset.")); - } else if (preset.is_system) { - description_line = _(L("This is a system preset.")); - } else if (parent == nullptr) { - description_line = _(L("Current preset is inherited from the default preset.")); - } else { - description_line = wxString::Format( - _(L("Current preset is inherited from:\n\t%s")), GUI::from_u8(parent->name)); - } + if (preset.is_default) { + description_line = _(L("This is a default preset.")); + } else if (preset.is_system) { + description_line = _(L("This is a system preset.")); + } else if (parent == nullptr) { + description_line = _(L("Current preset is inherited from the default preset.")); + } else { + description_line = wxString::Format( + _(L("Current preset is inherited from:\n\t%s")), GUI::from_u8(parent->name)); + } - if (preset.is_default || preset.is_system) - description_line += "\n\t" + _(L("It can't be deleted or modified.")) + - "\n\t" + _(L("Any modifications should be saved as a new preset inherited from this one.")) + - "\n\t" + _(L("To do that please specify a new name for the preset.")); - - if (parent && parent->vendor) - { - description_line += "\n\n" + _(L("Additional information:")) + "\n"; - description_line += "\t" + _(L("vendor")) + ": " + (m_type == Slic3r::Preset::TYPE_PRINTER ? "\n\t\t" : "") + parent->vendor->name + - ", ver: " + parent->vendor->config_version.to_string(); - if (m_type == Slic3r::Preset::TYPE_PRINTER) { - const std::string &printer_model = preset.config.opt_string("printer_model"); - if (! printer_model.empty()) - description_line += "\n\n\t" + _(L("printer model")) + ": \n\t\t" + printer_model; - switch (preset.printer_technology()) { - case ptFFF: - { - //FIXME add prefered_sla_material_profile for SLA - const std::string &default_print_profile = preset.config.opt_string("default_print_profile"); - const std::vector &default_filament_profiles = preset.config.option("default_filament_profile")->values; - if (!default_print_profile.empty()) - description_line += "\n\n\t" + _(L("default print profile")) + ": \n\t\t" + default_print_profile; - if (!default_filament_profiles.empty()) - { - description_line += "\n\n\t" + _(L("default filament profile")) + ": \n\t\t"; - for (auto& profile : default_filament_profiles) { - if (&profile != &*default_filament_profiles.begin()) - description_line += ", "; - description_line += profile; - } - } - break; - } - case ptSLA: - { - //FIXME add prefered_sla_material_profile for SLA - const std::string &default_sla_material_profile = preset.config.opt_string("default_sla_material_profile"); - if (!default_sla_material_profile.empty()) - description_line += "\n\n\t" + _(L("default SLA material profile")) + ": \n\t\t" + default_sla_material_profile; + if (preset.is_default || preset.is_system) + description_line += "\n\t" + _(L("It can't be deleted or modified.")) + + "\n\t" + _(L("Any modifications should be saved as a new preset inherited from this one.")) + + "\n\t" + _(L("To do that please specify a new name for the preset.")); - const std::string &default_sla_print_profile = preset.config.opt_string("default_sla_print_profile"); - if (!default_sla_print_profile.empty()) - description_line += "\n\n\t" + _(L("default SLA print profile")) + ": \n\t\t" + default_sla_print_profile; - break; - } - } - } - } + if (parent && parent->vendor) + { + description_line += "\n\n" + _(L("Additional information:")) + "\n"; + description_line += "\t" + _(L("vendor")) + ": " + (m_type == Slic3r::Preset::TYPE_PRINTER ? "\n\t\t" : "") + parent->vendor->name + + ", ver: " + parent->vendor->config_version.to_string(); + if (m_type == Slic3r::Preset::TYPE_PRINTER) { + const std::string &printer_model = preset.config.opt_string("printer_model"); + if (! printer_model.empty()) + description_line += "\n\n\t" + _(L("printer model")) + ": \n\t\t" + printer_model; + switch (preset.printer_technology()) { + case ptFFF: + { + //FIXME add prefered_sla_material_profile for SLA + const std::string &default_print_profile = preset.config.opt_string("default_print_profile"); + const std::vector &default_filament_profiles = preset.config.option("default_filament_profile")->values; + if (!default_print_profile.empty()) + description_line += "\n\n\t" + _(L("default print profile")) + ": \n\t\t" + default_print_profile; + if (!default_filament_profiles.empty()) + { + description_line += "\n\n\t" + _(L("default filament profile")) + ": \n\t\t"; + for (auto& profile : default_filament_profiles) { + if (&profile != &*default_filament_profiles.begin()) + description_line += ", "; + description_line += profile; + } + } + break; + } + case ptSLA: + { + //FIXME add prefered_sla_material_profile for SLA + const std::string &default_sla_material_profile = preset.config.opt_string("default_sla_material_profile"); + if (!default_sla_material_profile.empty()) + description_line += "\n\n\t" + _(L("default SLA material profile")) + ": \n\t\t" + default_sla_material_profile; - m_parent_preset_description_line->SetText(description_line, false); + const std::string &default_sla_print_profile = preset.config.opt_string("default_sla_print_profile"); + if (!default_sla_print_profile.empty()) + description_line += "\n\n\t" + _(L("default SLA print profile")) + ": \n\t\t" + default_sla_print_profile; + break; + } + } + } + } + + m_parent_preset_description_line->SetText(description_line, false); } void Tab::update_frequently_changed_parameters() { - const bool is_fff = supports_printer_technology(ptFFF); - auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); + const bool is_fff = supports_printer_technology(ptFFF); + auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(is_fff); if (!og_freq_chng_params) return; - og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); + og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff)); + if (! is_fff) + og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config)); const std::string updated_value_key = is_fff ? "fill_density" : "pad_enable"; @@ -1002,236 +1014,236 @@ void Tab::update_frequently_changed_parameters() void TabPrint::build() { - m_presets = &m_preset_bundle->prints; - load_initial_data(); + m_presets = &m_preset_bundle->prints; + load_initial_data(); - auto page = add_options_page(_(L("Layers and perimeters")), "layers"); - auto optgroup = page->new_optgroup(_(L("Layer height"))); - optgroup->append_single_option_line("layer_height"); - optgroup->append_single_option_line("first_layer_height"); + auto page = add_options_page(_(L("Layers and perimeters")), "layers"); + auto optgroup = page->new_optgroup(_(L("Layer height"))); + optgroup->append_single_option_line("layer_height"); + optgroup->append_single_option_line("first_layer_height"); - optgroup = page->new_optgroup(_(L("Vertical shells"))); - optgroup->append_single_option_line("perimeters"); - optgroup->append_single_option_line("spiral_vase"); + optgroup = page->new_optgroup(_(L("Vertical shells"))); + optgroup->append_single_option_line("perimeters"); + optgroup->append_single_option_line("spiral_vase"); - Line line { "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_recommended_thin_wall_thickness_description_line); - }; - optgroup->append_line(line); + Line line { "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_recommended_thin_wall_thickness_description_line); + }; + optgroup->append_line(line); - optgroup = page->new_optgroup(_(L("Horizontal shells"))); - line = { _(L("Solid layers")), "" }; - line.append_option(optgroup->get_option("top_solid_layers")); - line.append_option(optgroup->get_option("bottom_solid_layers")); - optgroup->append_line(line); + optgroup = page->new_optgroup(_(L("Horizontal shells"))); + line = { _(L("Solid layers")), "" }; + line.append_option(optgroup->get_option("top_solid_layers")); + line.append_option(optgroup->get_option("bottom_solid_layers")); + optgroup->append_line(line); - optgroup = page->new_optgroup(_(L("Quality (slower slicing)"))); - optgroup->append_single_option_line("extra_perimeters"); - optgroup->append_single_option_line("ensure_vertical_shell_thickness"); - optgroup->append_single_option_line("avoid_crossing_perimeters"); - optgroup->append_single_option_line("thin_walls"); - optgroup->append_single_option_line("overhangs"); + optgroup = page->new_optgroup(_(L("Quality (slower slicing)"))); + optgroup->append_single_option_line("extra_perimeters"); + optgroup->append_single_option_line("ensure_vertical_shell_thickness"); + optgroup->append_single_option_line("avoid_crossing_perimeters"); + optgroup->append_single_option_line("thin_walls"); + optgroup->append_single_option_line("overhangs"); - optgroup = page->new_optgroup(_(L("Advanced"))); - optgroup->append_single_option_line("seam_position"); - optgroup->append_single_option_line("external_perimeters_first"); + optgroup = page->new_optgroup(_(L("Advanced"))); + optgroup->append_single_option_line("seam_position"); + optgroup->append_single_option_line("external_perimeters_first"); - page = add_options_page(_(L("Infill")), "infill"); - optgroup = page->new_optgroup(_(L("Infill"))); - optgroup->append_single_option_line("fill_density"); - optgroup->append_single_option_line("fill_pattern"); - optgroup->append_single_option_line("top_fill_pattern"); - optgroup->append_single_option_line("bottom_fill_pattern"); + page = add_options_page(_(L("Infill")), "infill"); + optgroup = page->new_optgroup(_(L("Infill"))); + optgroup->append_single_option_line("fill_density"); + optgroup->append_single_option_line("fill_pattern"); + optgroup->append_single_option_line("top_fill_pattern"); + optgroup->append_single_option_line("bottom_fill_pattern"); - optgroup = page->new_optgroup(_(L("Reducing printing time"))); - optgroup->append_single_option_line("infill_every_layers"); - optgroup->append_single_option_line("infill_only_where_needed"); + optgroup = page->new_optgroup(_(L("Reducing printing time"))); + optgroup->append_single_option_line("infill_every_layers"); + optgroup->append_single_option_line("infill_only_where_needed"); - optgroup = page->new_optgroup(_(L("Advanced"))); - optgroup->append_single_option_line("solid_infill_every_layers"); - optgroup->append_single_option_line("fill_angle"); - optgroup->append_single_option_line("solid_infill_below_area"); - optgroup->append_single_option_line("bridge_angle"); - optgroup->append_single_option_line("only_retract_when_crossing_perimeters"); - optgroup->append_single_option_line("infill_first"); + optgroup = page->new_optgroup(_(L("Advanced"))); + optgroup->append_single_option_line("solid_infill_every_layers"); + optgroup->append_single_option_line("fill_angle"); + optgroup->append_single_option_line("solid_infill_below_area"); + optgroup->append_single_option_line("bridge_angle"); + optgroup->append_single_option_line("only_retract_when_crossing_perimeters"); + optgroup->append_single_option_line("infill_first"); - page = add_options_page(_(L("Skirt and brim")), "skirt+brim"); - optgroup = page->new_optgroup(_(L("Skirt"))); - optgroup->append_single_option_line("skirts"); - optgroup->append_single_option_line("skirt_distance"); - optgroup->append_single_option_line("skirt_height"); - optgroup->append_single_option_line("min_skirt_length"); + page = add_options_page(_(L("Skirt and brim")), "skirt+brim"); + optgroup = page->new_optgroup(_(L("Skirt"))); + optgroup->append_single_option_line("skirts"); + optgroup->append_single_option_line("skirt_distance"); + optgroup->append_single_option_line("skirt_height"); + optgroup->append_single_option_line("min_skirt_length"); - optgroup = page->new_optgroup(_(L("Brim"))); - optgroup->append_single_option_line("brim_width"); + optgroup = page->new_optgroup(_(L("Brim"))); + optgroup->append_single_option_line("brim_width"); - page = add_options_page(_(L("Support material")), "support"); - optgroup = page->new_optgroup(_(L("Support material"))); - optgroup->append_single_option_line("support_material"); - optgroup->append_single_option_line("support_material_auto"); - optgroup->append_single_option_line("support_material_threshold"); - optgroup->append_single_option_line("support_material_enforce_layers"); + page = add_options_page(_(L("Support material")), "support"); + optgroup = page->new_optgroup(_(L("Support material"))); + optgroup->append_single_option_line("support_material"); + optgroup->append_single_option_line("support_material_auto"); + optgroup->append_single_option_line("support_material_threshold"); + optgroup->append_single_option_line("support_material_enforce_layers"); - optgroup = page->new_optgroup(_(L("Raft"))); - optgroup->append_single_option_line("raft_layers"); + optgroup = page->new_optgroup(_(L("Raft"))); + optgroup->append_single_option_line("raft_layers"); // # optgroup->append_single_option_line(get_option_("raft_contact_distance"); - optgroup = page->new_optgroup(_(L("Options for support material and raft"))); - optgroup->append_single_option_line("support_material_contact_distance"); - optgroup->append_single_option_line("support_material_pattern"); - optgroup->append_single_option_line("support_material_with_sheath"); - optgroup->append_single_option_line("support_material_spacing"); - optgroup->append_single_option_line("support_material_angle"); - optgroup->append_single_option_line("support_material_interface_layers"); - optgroup->append_single_option_line("support_material_interface_spacing"); - optgroup->append_single_option_line("support_material_interface_contact_loops"); - optgroup->append_single_option_line("support_material_buildplate_only"); - optgroup->append_single_option_line("support_material_xy_spacing"); - optgroup->append_single_option_line("dont_support_bridges"); - optgroup->append_single_option_line("support_material_synchronize_layers"); + optgroup = page->new_optgroup(_(L("Options for support material and raft"))); + optgroup->append_single_option_line("support_material_contact_distance"); + optgroup->append_single_option_line("support_material_pattern"); + optgroup->append_single_option_line("support_material_with_sheath"); + optgroup->append_single_option_line("support_material_spacing"); + optgroup->append_single_option_line("support_material_angle"); + optgroup->append_single_option_line("support_material_interface_layers"); + optgroup->append_single_option_line("support_material_interface_spacing"); + optgroup->append_single_option_line("support_material_interface_contact_loops"); + optgroup->append_single_option_line("support_material_buildplate_only"); + optgroup->append_single_option_line("support_material_xy_spacing"); + optgroup->append_single_option_line("dont_support_bridges"); + optgroup->append_single_option_line("support_material_synchronize_layers"); - page = add_options_page(_(L("Speed")), "time"); - optgroup = page->new_optgroup(_(L("Speed for print moves"))); - optgroup->append_single_option_line("perimeter_speed"); - optgroup->append_single_option_line("small_perimeter_speed"); - optgroup->append_single_option_line("external_perimeter_speed"); - optgroup->append_single_option_line("infill_speed"); - optgroup->append_single_option_line("solid_infill_speed"); - optgroup->append_single_option_line("top_solid_infill_speed"); - optgroup->append_single_option_line("support_material_speed"); - optgroup->append_single_option_line("support_material_interface_speed"); - optgroup->append_single_option_line("bridge_speed"); - optgroup->append_single_option_line("gap_fill_speed"); + page = add_options_page(_(L("Speed")), "time"); + optgroup = page->new_optgroup(_(L("Speed for print moves"))); + optgroup->append_single_option_line("perimeter_speed"); + optgroup->append_single_option_line("small_perimeter_speed"); + optgroup->append_single_option_line("external_perimeter_speed"); + optgroup->append_single_option_line("infill_speed"); + optgroup->append_single_option_line("solid_infill_speed"); + optgroup->append_single_option_line("top_solid_infill_speed"); + optgroup->append_single_option_line("support_material_speed"); + optgroup->append_single_option_line("support_material_interface_speed"); + optgroup->append_single_option_line("bridge_speed"); + optgroup->append_single_option_line("gap_fill_speed"); - optgroup = page->new_optgroup(_(L("Speed for non-print moves"))); - optgroup->append_single_option_line("travel_speed"); + optgroup = page->new_optgroup(_(L("Speed for non-print moves"))); + optgroup->append_single_option_line("travel_speed"); - optgroup = page->new_optgroup(_(L("Modifiers"))); - optgroup->append_single_option_line("first_layer_speed"); + optgroup = page->new_optgroup(_(L("Modifiers"))); + optgroup->append_single_option_line("first_layer_speed"); - optgroup = page->new_optgroup(_(L("Acceleration control (advanced)"))); - optgroup->append_single_option_line("perimeter_acceleration"); - optgroup->append_single_option_line("infill_acceleration"); - optgroup->append_single_option_line("bridge_acceleration"); - optgroup->append_single_option_line("first_layer_acceleration"); - optgroup->append_single_option_line("default_acceleration"); + optgroup = page->new_optgroup(_(L("Acceleration control (advanced)"))); + optgroup->append_single_option_line("perimeter_acceleration"); + optgroup->append_single_option_line("infill_acceleration"); + optgroup->append_single_option_line("bridge_acceleration"); + optgroup->append_single_option_line("first_layer_acceleration"); + optgroup->append_single_option_line("default_acceleration"); - optgroup = page->new_optgroup(_(L("Autospeed (advanced)"))); - optgroup->append_single_option_line("max_print_speed"); - optgroup->append_single_option_line("max_volumetric_speed"); + optgroup = page->new_optgroup(_(L("Autospeed (advanced)"))); + optgroup->append_single_option_line("max_print_speed"); + optgroup->append_single_option_line("max_volumetric_speed"); #ifdef HAS_PRESSURE_EQUALIZER - optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive"); - optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative"); + optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive"); + optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative"); #endif /* HAS_PRESSURE_EQUALIZER */ - page = add_options_page(_(L("Multiple Extruders")), "funnel"); - optgroup = page->new_optgroup(_(L("Extruders"))); - optgroup->append_single_option_line("perimeter_extruder"); - optgroup->append_single_option_line("infill_extruder"); - optgroup->append_single_option_line("solid_infill_extruder"); - optgroup->append_single_option_line("support_material_extruder"); - optgroup->append_single_option_line("support_material_interface_extruder"); + page = add_options_page(_(L("Multiple Extruders")), "funnel"); + optgroup = page->new_optgroup(_(L("Extruders"))); + optgroup->append_single_option_line("perimeter_extruder"); + optgroup->append_single_option_line("infill_extruder"); + optgroup->append_single_option_line("solid_infill_extruder"); + optgroup->append_single_option_line("support_material_extruder"); + optgroup->append_single_option_line("support_material_interface_extruder"); - optgroup = page->new_optgroup(_(L("Ooze prevention"))); - optgroup->append_single_option_line("ooze_prevention"); - optgroup->append_single_option_line("standby_temperature_delta"); + optgroup = page->new_optgroup(_(L("Ooze prevention"))); + optgroup->append_single_option_line("ooze_prevention"); + optgroup->append_single_option_line("standby_temperature_delta"); - optgroup = page->new_optgroup(_(L("Wipe tower"))); - optgroup->append_single_option_line("wipe_tower"); - optgroup->append_single_option_line("wipe_tower_x"); - optgroup->append_single_option_line("wipe_tower_y"); - optgroup->append_single_option_line("wipe_tower_width"); - optgroup->append_single_option_line("wipe_tower_rotation_angle"); + optgroup = page->new_optgroup(_(L("Wipe tower"))); + optgroup->append_single_option_line("wipe_tower"); + optgroup->append_single_option_line("wipe_tower_x"); + optgroup->append_single_option_line("wipe_tower_y"); + optgroup->append_single_option_line("wipe_tower_width"); + optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup->append_single_option_line("wipe_tower_bridging"); optgroup->append_single_option_line("single_extruder_multi_material_priming"); - optgroup = page->new_optgroup(_(L("Advanced"))); - optgroup->append_single_option_line("interface_shells"); + optgroup = page->new_optgroup(_(L("Advanced"))); + optgroup->append_single_option_line("interface_shells"); - page = add_options_page(_(L("Advanced")), "wrench"); - optgroup = page->new_optgroup(_(L("Extrusion width"))); - optgroup->append_single_option_line("extrusion_width"); - optgroup->append_single_option_line("first_layer_extrusion_width"); - optgroup->append_single_option_line("perimeter_extrusion_width"); - optgroup->append_single_option_line("external_perimeter_extrusion_width"); - optgroup->append_single_option_line("infill_extrusion_width"); - optgroup->append_single_option_line("solid_infill_extrusion_width"); - optgroup->append_single_option_line("top_infill_extrusion_width"); - optgroup->append_single_option_line("support_material_extrusion_width"); + page = add_options_page(_(L("Advanced")), "wrench"); + optgroup = page->new_optgroup(_(L("Extrusion width"))); + optgroup->append_single_option_line("extrusion_width"); + optgroup->append_single_option_line("first_layer_extrusion_width"); + optgroup->append_single_option_line("perimeter_extrusion_width"); + optgroup->append_single_option_line("external_perimeter_extrusion_width"); + optgroup->append_single_option_line("infill_extrusion_width"); + optgroup->append_single_option_line("solid_infill_extrusion_width"); + optgroup->append_single_option_line("top_infill_extrusion_width"); + optgroup->append_single_option_line("support_material_extrusion_width"); - optgroup = page->new_optgroup(_(L("Overlap"))); - optgroup->append_single_option_line("infill_overlap"); + optgroup = page->new_optgroup(_(L("Overlap"))); + optgroup->append_single_option_line("infill_overlap"); - optgroup = page->new_optgroup(_(L("Flow"))); - optgroup->append_single_option_line("bridge_flow_ratio"); + optgroup = page->new_optgroup(_(L("Flow"))); + optgroup->append_single_option_line("bridge_flow_ratio"); - optgroup = page->new_optgroup(_(L("Slicing"))); - optgroup->append_single_option_line("slice_closing_radius"); - optgroup->append_single_option_line("resolution"); - optgroup->append_single_option_line("xy_size_compensation"); - optgroup->append_single_option_line("elefant_foot_compensation"); + optgroup = page->new_optgroup(_(L("Slicing"))); + optgroup->append_single_option_line("slice_closing_radius"); + optgroup->append_single_option_line("resolution"); + optgroup->append_single_option_line("xy_size_compensation"); + optgroup->append_single_option_line("elefant_foot_compensation"); - optgroup = page->new_optgroup(_(L("Other"))); - optgroup->append_single_option_line("clip_multipart_objects"); + optgroup = page->new_optgroup(_(L("Other"))); + optgroup->append_single_option_line("clip_multipart_objects"); - page = add_options_page(_(L("Output options")), "output+page_white"); - optgroup = page->new_optgroup(_(L("Sequential printing"))); - optgroup->append_single_option_line("complete_objects"); - line = { _(L("Extruder clearance (mm)")), "" }; - Option option = optgroup->get_option("extruder_clearance_radius"); - option.opt.width = 6; - line.append_option(option); - option = optgroup->get_option("extruder_clearance_height"); - option.opt.width = 6; - line.append_option(option); - optgroup->append_line(line); + page = add_options_page(_(L("Output options")), "output+page_white"); + optgroup = page->new_optgroup(_(L("Sequential printing"))); + optgroup->append_single_option_line("complete_objects"); + line = { _(L("Extruder clearance (mm)")), "" }; + Option option = optgroup->get_option("extruder_clearance_radius"); + option.opt.width = 6; + line.append_option(option); + option = optgroup->get_option("extruder_clearance_height"); + option.opt.width = 6; + line.append_option(option); + optgroup->append_line(line); - optgroup = page->new_optgroup(_(L("Output file"))); - optgroup->append_single_option_line("gcode_comments"); - optgroup->append_single_option_line("gcode_label_objects"); - option = optgroup->get_option("output_filename_format"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + optgroup = page->new_optgroup(_(L("Output file"))); + optgroup->append_single_option_line("gcode_comments"); + optgroup->append_single_option_line("gcode_label_objects"); + option = optgroup->get_option("output_filename_format"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("Post-processing scripts")), 0); - option = optgroup->get_option("post_process"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("Post-processing scripts")), 0); + option = optgroup->get_option("post_process"); + option.opt.full_width = true; option.opt.height = 5;//50; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - page = add_options_page(_(L("Notes")), "note.png"); - optgroup = page->new_optgroup(_(L("Notes")), 0); - option = optgroup->get_option("notes"); - option.opt.full_width = true; + page = add_options_page(_(L("Notes")), "note.png"); + optgroup = page->new_optgroup(_(L("Notes")), 0); + option = optgroup->get_option("notes"); + option.opt.full_width = true; option.opt.height = 25;//250; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - page = add_options_page(_(L("Dependencies")), "wrench.png"); - optgroup = page->new_optgroup(_(L("Profile dependencies"))); + page = add_options_page(_(L("Dependencies")), "wrench.png"); + optgroup = page->new_optgroup(_(L("Profile dependencies"))); line = optgroup->create_single_option_line("compatible_printers"); line.widget = [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_printers); - }; - optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + return compatible_widget_create(parent, m_compatible_printers); + }; + optgroup->append_line(line, &m_colored_Label); + option = optgroup->get_option("compatible_printers_condition"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); - line = Line{ "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_parent_preset_description_line); - }; - optgroup->append_line(line); + line = Line{ "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_parent_preset_description_line); + }; + optgroup->append_line(line); } // Reload current config (aka presets->edited_preset->config) into the UI fields. void TabPrint::reload_config() { - this->compatible_widget_reload(m_compatible_printers); - Tab::reload_config(); + this->compatible_widget_reload(m_compatible_printers); + Tab::reload_config(); } void TabPrint::update() @@ -1275,212 +1287,212 @@ void TabPrint::update() is_msg_dlg_already_exist = false; } - double fill_density = m_config->option("fill_density")->value; + double fill_density = m_config->option("fill_density")->value; - if (m_config->opt_bool("spiral_vase") && - !(m_config->opt_int("perimeters") == 1 && m_config->opt_int("top_solid_layers") == 0 && - fill_density == 0)) { - wxString msg_text = _(L("The Spiral Vase mode requires:\n" - "- one perimeter\n" - "- no top solid layers\n" - "- 0% fill density\n" - "- no support material\n" - "- no ensure_vertical_shell_thickness\n" - "\nShall I adjust those settings in order to enable Spiral Vase?")); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); - new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0)); - new_conf.set_key_value("fill_density", new ConfigOptionPercent(0)); - new_conf.set_key_value("support_material", new ConfigOptionBool(false)); - new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0)); - new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false)); - fill_density = 0; - } - else { - new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false)); - } - load_config(new_conf); - on_value_change("fill_density", fill_density); - } + if (m_config->opt_bool("spiral_vase") && + !(m_config->opt_int("perimeters") == 1 && m_config->opt_int("top_solid_layers") == 0 && + fill_density == 0)) { + wxString msg_text = _(L("The Spiral Vase mode requires:\n" + "- one perimeter\n" + "- no top solid layers\n" + "- 0% fill density\n" + "- no support material\n" + "- no ensure_vertical_shell_thickness\n" + "\nShall I adjust those settings in order to enable Spiral Vase?")); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO); + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); + new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0)); + new_conf.set_key_value("fill_density", new ConfigOptionPercent(0)); + new_conf.set_key_value("support_material", new ConfigOptionBool(false)); + new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0)); + new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false)); + fill_density = 0; + } + else { + new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false)); + } + load_config(new_conf); + on_value_change("fill_density", fill_density); + } - if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && - m_config->opt_float("support_material_contact_distance") > 0. && - (m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) { - wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n" - "if they are printed with the current extruder without triggering a tool change.\n" - "(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n" - "\nShall I adjust those settings in order to enable the Wipe Tower?")); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0)); - new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0)); - } - else - new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); - load_config(new_conf); - } + if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && + m_config->opt_float("support_material_contact_distance") > 0. && + (m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) { + wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n" + "if they are printed with the current extruder without triggering a tool change.\n" + "(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n" + "\nShall I adjust those settings in order to enable the Wipe Tower?")); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO); + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0)); + new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0)); + } + else + new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); + load_config(new_conf); + } - if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && - m_config->opt_float("support_material_contact_distance") == 0 && - !m_config->opt_bool("support_material_synchronize_layers")) { - wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n" - "need to be synchronized with the object layers.\n" - "\nShall I synchronize support layers in order to enable the Wipe Tower?")); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true)); - } - else - new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); - load_config(new_conf); - } + if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && + m_config->opt_float("support_material_contact_distance") == 0 && + !m_config->opt_bool("support_material_synchronize_layers")) { + wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n" + "need to be synchronized with the object layers.\n" + "\nShall I synchronize support layers in order to enable the Wipe Tower?")); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO); + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true)); + } + else + new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); + load_config(new_conf); + } - if (m_config->opt_bool("support_material")) { - // Ask only once. - if (!m_support_material_overhangs_queried) { - m_support_material_overhangs_queried = true; - if (!m_config->opt_bool("overhangs")/* != 1*/) { - wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n" - "- Detect bridging perimeters\n" - "\nShall I adjust those settings for supports?")); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Support Generator")), wxICON_WARNING | wxYES | wxNO | wxCANCEL); - DynamicPrintConfig new_conf = *m_config; - auto answer = dialog->ShowModal(); - if (answer == wxID_YES) { - // Enable "detect bridging perimeters". - new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); - } else if (answer == wxID_NO) { - // Do nothing, leave supports on and "detect bridging perimeters" off. - } else if (answer == wxID_CANCEL) { - // Disable supports. - new_conf.set_key_value("support_material", new ConfigOptionBool(false)); - m_support_material_overhangs_queried = false; - } - load_config(new_conf); - } - } - } - else { - m_support_material_overhangs_queried = false; - } + if (m_config->opt_bool("support_material")) { + // Ask only once. + if (!m_support_material_overhangs_queried) { + m_support_material_overhangs_queried = true; + if (!m_config->opt_bool("overhangs")/* != 1*/) { + wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n" + "- Detect bridging perimeters\n" + "\nShall I adjust those settings for supports?")); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Support Generator")), wxICON_WARNING | wxYES | wxNO | wxCANCEL); + DynamicPrintConfig new_conf = *m_config; + auto answer = dialog->ShowModal(); + if (answer == wxID_YES) { + // Enable "detect bridging perimeters". + new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); + } else if (answer == wxID_NO) { + // Do nothing, leave supports on and "detect bridging perimeters" off. + } else if (answer == wxID_CANCEL) { + // Disable supports. + new_conf.set_key_value("support_material", new ConfigOptionBool(false)); + m_support_material_overhangs_queried = false; + } + load_config(new_conf); + } + } + } + else { + m_support_material_overhangs_queried = false; + } - if (m_config->option("fill_density")->value == 100) { - auto fill_pattern = m_config->option>("fill_pattern")->value; - std::string str_fill_pattern = ""; - t_config_enum_values map_names = m_config->option>("fill_pattern")->get_enum_values(); - for (auto it : map_names) { - if (fill_pattern == it.second) { - str_fill_pattern = it.first; - break; - } - } - if (!str_fill_pattern.empty()) { - const std::vector &external_fill_pattern = m_config->def()->get("top_fill_pattern")->enum_values; - bool correct_100p_fill = false; - for (const std::string &fill : external_fill_pattern) - { - if (str_fill_pattern == fill) - correct_100p_fill = true; - } - // get fill_pattern name from enum_labels for using this one at dialog_msg - str_fill_pattern = _utf8(m_config->def()->get("fill_pattern")->enum_labels[fill_pattern]); - if (!correct_100p_fill) { - wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density.\n\n" - "Shall I switch to rectilinear fill pattern?"))) % str_fill_pattern).str()); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Infill")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - new_conf.set_key_value("fill_pattern", new ConfigOptionEnum(ipRectilinear)); - fill_density = 100; - } - else - fill_density = m_presets->get_selected_preset().config.option("fill_density")->value; - new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density)); - load_config(new_conf); - on_value_change("fill_density", fill_density); - } - } - } + if (m_config->option("fill_density")->value == 100) { + auto fill_pattern = m_config->option>("fill_pattern")->value; + std::string str_fill_pattern = ""; + t_config_enum_values map_names = m_config->option>("fill_pattern")->get_enum_values(); + for (auto it : map_names) { + if (fill_pattern == it.second) { + str_fill_pattern = it.first; + break; + } + } + if (!str_fill_pattern.empty()) { + const std::vector &external_fill_pattern = m_config->def()->get("top_fill_pattern")->enum_values; + bool correct_100p_fill = false; + for (const std::string &fill : external_fill_pattern) + { + if (str_fill_pattern == fill) + correct_100p_fill = true; + } + // get fill_pattern name from enum_labels for using this one at dialog_msg + str_fill_pattern = _utf8(m_config->def()->get("fill_pattern")->enum_labels[fill_pattern]); + if (!correct_100p_fill) { + wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density.\n\n" + "Shall I switch to rectilinear fill pattern?"))) % str_fill_pattern).str()); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Infill")), wxICON_WARNING | wxYES | wxNO); + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + new_conf.set_key_value("fill_pattern", new ConfigOptionEnum(ipRectilinear)); + fill_density = 100; + } + else + fill_density = m_presets->get_selected_preset().config.option("fill_density")->value; + new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density)); + load_config(new_conf); + on_value_change("fill_density", fill_density); + } + } + } - bool have_perimeters = m_config->opt_int("perimeters") > 0; - for (auto el : {"extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }) - get_field(el)->toggle(have_perimeters); + bool have_perimeters = m_config->opt_int("perimeters") > 0; + for (auto el : {"extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", + "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }) + get_field(el)->toggle(have_perimeters); - bool have_infill = m_config->option("fill_density")->value > 0; - // infill_extruder uses the same logic as in Print::extruders() - for (auto el : {"fill_pattern", "infill_every_layers", "infill_only_where_needed", - "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" }) - get_field(el)->toggle(have_infill); + bool have_infill = m_config->option("fill_density")->value > 0; + // infill_extruder uses the same logic as in Print::extruders() + for (auto el : {"fill_pattern", "infill_every_layers", "infill_only_where_needed", + "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" }) + get_field(el)->toggle(have_infill); - bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; - // solid_infill_extruder uses the same logic as in Print::extruders() - for (auto el : {"top_fill_pattern", "bottom_fill_pattern", "infill_first", "solid_infill_extruder", - "solid_infill_extrusion_width", "solid_infill_speed" }) - get_field(el)->toggle(have_solid_infill); + bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; + // solid_infill_extruder uses the same logic as in Print::extruders() + for (auto el : {"top_fill_pattern", "bottom_fill_pattern", "infill_first", "solid_infill_extruder", + "solid_infill_extrusion_width", "solid_infill_speed" }) + get_field(el)->toggle(have_solid_infill); - for (auto el : {"fill_angle", "bridge_angle", "infill_extrusion_width", - "infill_speed", "bridge_speed" }) - get_field(el)->toggle(have_infill || have_solid_infill); + for (auto el : {"fill_angle", "bridge_angle", "infill_extrusion_width", + "infill_speed", "bridge_speed" }) + get_field(el)->toggle(have_infill || have_solid_infill); - get_field("gap_fill_speed")->toggle(have_perimeters && have_infill); + get_field("gap_fill_speed")->toggle(have_perimeters && have_infill); - bool have_top_solid_infill = m_config->opt_int("top_solid_layers") > 0; - for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" }) - get_field(el)->toggle(have_top_solid_infill); + bool have_top_solid_infill = m_config->opt_int("top_solid_layers") > 0; + for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" }) + get_field(el)->toggle(have_top_solid_infill); - bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0; - for (auto el : {"perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration" }) - get_field(el)->toggle(have_default_acceleration); + bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0; + for (auto el : {"perimeter_acceleration", "infill_acceleration", + "bridge_acceleration", "first_layer_acceleration" }) + get_field(el)->toggle(have_default_acceleration); - bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0; - for (auto el : { "skirt_distance", "skirt_height" }) - get_field(el)->toggle(have_skirt); + bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0; + for (auto el : { "skirt_distance", "skirt_height" }) + get_field(el)->toggle(have_skirt); - bool have_brim = m_config->opt_float("brim_width") > 0; - // perimeter_extruder uses the same logic as in Print::extruders() - get_field("perimeter_extruder")->toggle(have_perimeters || have_brim); + bool have_brim = m_config->opt_float("brim_width") > 0; + // perimeter_extruder uses the same logic as in Print::extruders() + get_field("perimeter_extruder")->toggle(have_perimeters || have_brim); - bool have_raft = m_config->opt_int("raft_layers") > 0; - bool have_support_material = m_config->opt_bool("support_material") || have_raft; - bool have_support_material_auto = have_support_material && m_config->opt_bool("support_material_auto"); - bool have_support_interface = m_config->opt_int("support_material_interface_layers") > 0; - bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0; - for (auto el : {"support_material_pattern", "support_material_with_sheath", - "support_material_spacing", "support_material_angle", "support_material_interface_layers", - "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", - "support_material_xy_spacing" }) - get_field(el)->toggle(have_support_material); - get_field("support_material_threshold")->toggle(have_support_material_auto); + bool have_raft = m_config->opt_int("raft_layers") > 0; + bool have_support_material = m_config->opt_bool("support_material") || have_raft; + bool have_support_material_auto = have_support_material && m_config->opt_bool("support_material_auto"); + bool have_support_interface = m_config->opt_int("support_material_interface_layers") > 0; + bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0; + for (auto el : {"support_material_pattern", "support_material_with_sheath", + "support_material_spacing", "support_material_angle", "support_material_interface_layers", + "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance", + "support_material_xy_spacing" }) + get_field(el)->toggle(have_support_material); + get_field("support_material_threshold")->toggle(have_support_material_auto); - for (auto el : {"support_material_interface_spacing", "support_material_interface_extruder", - "support_material_interface_speed", "support_material_interface_contact_loops" }) - get_field(el)->toggle(have_support_material && have_support_interface); - get_field("support_material_synchronize_layers")->toggle(have_support_soluble); + for (auto el : {"support_material_interface_spacing", "support_material_interface_extruder", + "support_material_interface_speed", "support_material_interface_contact_loops" }) + get_field(el)->toggle(have_support_material && have_support_interface); + get_field("support_material_synchronize_layers")->toggle(have_support_soluble); - get_field("perimeter_extrusion_width")->toggle(have_perimeters || have_skirt || have_brim); - get_field("support_material_extruder")->toggle(have_support_material || have_skirt); - get_field("support_material_speed")->toggle(have_support_material || have_brim || have_skirt); + get_field("perimeter_extrusion_width")->toggle(have_perimeters || have_skirt || have_brim); + get_field("support_material_extruder")->toggle(have_support_material || have_skirt); + get_field("support_material_speed")->toggle(have_support_material || have_brim || have_skirt); - bool have_sequential_printing = m_config->opt_bool("complete_objects"); - for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" }) - get_field(el)->toggle(have_sequential_printing); + bool have_sequential_printing = m_config->opt_bool("complete_objects"); + for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" }) + get_field(el)->toggle(have_sequential_printing); - bool have_ooze_prevention = m_config->opt_bool("ooze_prevention"); - get_field("standby_temperature_delta")->toggle(have_ooze_prevention); + bool have_ooze_prevention = m_config->opt_bool("ooze_prevention"); + get_field("standby_temperature_delta")->toggle(have_ooze_prevention); - bool have_wipe_tower = m_config->opt_bool("wipe_tower"); - for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"}) - get_field(el)->toggle(have_wipe_tower); + bool have_wipe_tower = m_config->opt_bool("wipe_tower"); + for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"}) + get_field(el)->toggle(have_wipe_tower); - m_recommended_thin_wall_thickness_description_line->SetText( - from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); + m_recommended_thin_wall_thickness_description_line->SetText( + from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); Layout(); // Thaw(); @@ -1492,9 +1504,9 @@ void TabPrint::update() void TabPrint::OnActivate() { - m_recommended_thin_wall_thickness_description_line->SetText( - from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); - Tab::OnActivate(); + m_recommended_thin_wall_thickness_description_line->SetText( + from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); + Tab::OnActivate(); } void TabFilament::add_filament_overrides_page() @@ -1564,9 +1576,9 @@ void TabFilament::update_filament_overrides_page() return; ConfigOptionsGroupShp optgroup = *og_it; - std::vector opt_keys = { "filament_retract_length", - "filament_retract_lift", - "filament_retract_lift_above", + std::vector opt_keys = { "filament_retract_length", + "filament_retract_lift", + "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", @@ -1598,79 +1610,79 @@ void TabFilament::update_filament_overrides_page() void TabFilament::build() { - m_presets = &m_preset_bundle->filaments; - load_initial_data(); + m_presets = &m_preset_bundle->filaments; + load_initial_data(); - auto page = add_options_page(_(L("Filament")), "spool.png"); - auto optgroup = page->new_optgroup(_(L("Filament"))); - optgroup->append_single_option_line("filament_colour"); - optgroup->append_single_option_line("filament_diameter"); - optgroup->append_single_option_line("extrusion_multiplier"); - optgroup->append_single_option_line("filament_density"); - optgroup->append_single_option_line("filament_cost"); + auto page = add_options_page(_(L("Filament")), "spool.png"); + auto optgroup = page->new_optgroup(_(L("Filament"))); + optgroup->append_single_option_line("filament_colour"); + optgroup->append_single_option_line("filament_diameter"); + optgroup->append_single_option_line("extrusion_multiplier"); + optgroup->append_single_option_line("filament_density"); + optgroup->append_single_option_line("filament_cost"); - optgroup = page->new_optgroup(_(L("Temperature")) + wxString(" °C", wxConvUTF8)); - Line line = { _(L("Extruder")), "" }; - line.append_option(optgroup->get_option("first_layer_temperature")); - line.append_option(optgroup->get_option("temperature")); - optgroup->append_line(line); + optgroup = page->new_optgroup(_(L("Temperature")) + wxString(" °C", wxConvUTF8)); + Line line = { _(L("Extruder")), "" }; + line.append_option(optgroup->get_option("first_layer_temperature")); + line.append_option(optgroup->get_option("temperature")); + optgroup->append_line(line); - line = { _(L("Bed")), "" }; - line.append_option(optgroup->get_option("first_layer_bed_temperature")); - line.append_option(optgroup->get_option("bed_temperature")); - optgroup->append_line(line); + line = { _(L("Bed")), "" }; + line.append_option(optgroup->get_option("first_layer_bed_temperature")); + line.append_option(optgroup->get_option("bed_temperature")); + optgroup->append_line(line); - page = add_options_page(_(L("Cooling")), "cooling"); - optgroup = page->new_optgroup(_(L("Enable"))); - optgroup->append_single_option_line("fan_always_on"); - optgroup->append_single_option_line("cooling"); + page = add_options_page(_(L("Cooling")), "cooling"); + optgroup = page->new_optgroup(_(L("Enable"))); + optgroup->append_single_option_line("fan_always_on"); + optgroup->append_single_option_line("cooling"); - line = { "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_cooling_description_line); - }; - optgroup->append_line(line); + line = { "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_cooling_description_line); + }; + optgroup->append_line(line); - optgroup = page->new_optgroup(_(L("Fan settings"))); - line = { _(L("Fan speed")), "" }; - line.append_option(optgroup->get_option("min_fan_speed")); - line.append_option(optgroup->get_option("max_fan_speed")); - optgroup->append_line(line); + optgroup = page->new_optgroup(_(L("Fan settings"))); + line = { _(L("Fan speed")), "" }; + line.append_option(optgroup->get_option("min_fan_speed")); + line.append_option(optgroup->get_option("max_fan_speed")); + optgroup->append_line(line); - optgroup->append_single_option_line("bridge_fan_speed"); - optgroup->append_single_option_line("disable_fan_first_layers"); + optgroup->append_single_option_line("bridge_fan_speed"); + optgroup->append_single_option_line("disable_fan_first_layers"); - optgroup = page->new_optgroup(_(L("Cooling thresholds")), 25); - optgroup->append_single_option_line("fan_below_layer_time"); - optgroup->append_single_option_line("slowdown_below_layer_time"); - optgroup->append_single_option_line("min_print_speed"); + optgroup = page->new_optgroup(_(L("Cooling thresholds")), 25); + optgroup->append_single_option_line("fan_below_layer_time"); + optgroup->append_single_option_line("slowdown_below_layer_time"); + optgroup->append_single_option_line("min_print_speed"); - page = add_options_page(_(L("Advanced")), "wrench"); - optgroup = page->new_optgroup(_(L("Filament properties"))); - optgroup->append_single_option_line("filament_type"); - optgroup->append_single_option_line("filament_soluble"); + page = add_options_page(_(L("Advanced")), "wrench"); + optgroup = page->new_optgroup(_(L("Filament properties"))); + optgroup->append_single_option_line("filament_type"); + optgroup->append_single_option_line("filament_soluble"); - optgroup = page->new_optgroup(_(L("Print speed override"))); - optgroup->append_single_option_line("filament_max_volumetric_speed"); + optgroup = page->new_optgroup(_(L("Print speed override"))); + optgroup->append_single_option_line("filament_max_volumetric_speed"); - line = { "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_volumetric_speed_description_line); - }; - optgroup->append_line(line); + line = { "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_volumetric_speed_description_line); + }; + optgroup->append_line(line); optgroup = page->new_optgroup(_(L("Wipe tower parameters"))); optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower"); optgroup = page->new_optgroup(_(L("Toolchange parameters with single extruder MM printers"))); - optgroup->append_single_option_line("filament_loading_speed_start"); + optgroup->append_single_option_line("filament_loading_speed_start"); optgroup->append_single_option_line("filament_loading_speed"); optgroup->append_single_option_line("filament_unloading_speed_start"); optgroup->append_single_option_line("filament_unloading_speed"); - optgroup->append_single_option_line("filament_load_time"); - optgroup->append_single_option_line("filament_unload_time"); + optgroup->append_single_option_line("filament_load_time"); + optgroup->append_single_option_line("filament_unload_time"); optgroup->append_single_option_line("filament_toolchange_delay"); optgroup->append_single_option_line("filament_cooling_moves"); optgroup->append_single_option_line("filament_cooling_initial_speed"); @@ -1678,20 +1690,20 @@ void TabFilament::build() line = optgroup->create_single_option_line("filament_ramming_parameters");// { _(L("Ramming")), "" }; line.widget = [this](wxWindow* parent) { - auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); - ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); + ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(ramming_dialog_btn); - + sizer->Add(ramming_dialog_btn); + ramming_dialog_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) - { + { RammingDialog dlg(this,(m_config->option("filament_ramming_parameters"))->get_at(0)); if (dlg.ShowModal() == wxID_OK) (m_config->option("filament_ramming_parameters"))->get_at(0) = dlg.get_parameters(); - })); - return sizer; - }; - optgroup->append_line(line); + })); + return sizer; + }; + optgroup->append_line(line); add_filament_overrides_page(); @@ -1701,61 +1713,72 @@ void TabFilament::build() const int notes_field_height = 25; // 250 page = add_options_page(_(L("Custom G-code")), "cog"); - optgroup = page->new_optgroup(_(L("Start G-code")), 0); - Option option = optgroup->get_option("start_filament_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("Start G-code")), 0); + Option option = optgroup->get_option("start_filament_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;// 150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("End G-code")), 0); - option = optgroup->get_option("end_filament_gcode"); - option.opt.full_width = true; - option.opt.height = gcode_field_height;// 150; - optgroup->append_single_option_line(option); + optgroup = page->new_optgroup(_(L("End G-code")), 0); + option = optgroup->get_option("end_filament_gcode"); + option.opt.full_width = true; + option.opt.height = gcode_field_height;// 150; + optgroup->append_single_option_line(option); - page = add_options_page(_(L("Notes")), "note.png"); - optgroup = page->new_optgroup(_(L("Notes")), 0); - optgroup->label_width = 0; - option = optgroup->get_option("filament_notes"); - option.opt.full_width = true; - option.opt.height = notes_field_height;// 250; - optgroup->append_single_option_line(option); + page = add_options_page(_(L("Notes")), "note.png"); + optgroup = page->new_optgroup(_(L("Notes")), 0); + optgroup->label_width = 0; + option = optgroup->get_option("filament_notes"); + option.opt.full_width = true; + option.opt.height = notes_field_height;// 250; + optgroup->append_single_option_line(option); + + page = add_options_page(_(L("Dependencies")), "wrench.png"); + optgroup = page->new_optgroup(_(L("Profile dependencies"))); - page = add_options_page(_(L("Dependencies")), "wrench.png"); - optgroup = page->new_optgroup(_(L("Profile dependencies"))); - line = optgroup->create_single_option_line("compatible_printers"); line.widget = [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_printers); - }; - optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_printers_condition"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + return compatible_widget_create(parent, m_compatible_printers); + }; + optgroup->append_line(line, &m_colored_Label); + option = optgroup->get_option("compatible_printers_condition"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); line = optgroup->create_single_option_line("compatible_prints"); line.widget = [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_prints); - }; - optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_prints_condition"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + return compatible_widget_create(parent, m_compatible_prints); + }; + optgroup->append_line(line, &m_colored_Label); + option = optgroup->get_option("compatible_prints_condition"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); - line = Line{ "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_parent_preset_description_line); - }; - optgroup->append_line(line); + line = Line{ "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_parent_preset_description_line); + }; + optgroup->append_line(line); } // Reload current config (aka presets->edited_preset->config) into the UI fields. void TabFilament::reload_config() { - this->compatible_widget_reload(m_compatible_printers); - this->compatible_widget_reload(m_compatible_prints); - Tab::reload_config(); + this->compatible_widget_reload(m_compatible_printers); + this->compatible_widget_reload(m_compatible_prints); + Tab::reload_config(); +} + +void TabFilament::update_volumetric_flow_preset_hints() +{ + wxString text; + try { + text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); + } catch (std::exception &ex) { + text = _(L("Volumetric flow hints not available\n\n")) + from_u8(ex.what()); + } + m_volumetric_speed_description_line->SetText(text); } void TabFilament::update() @@ -1767,18 +1790,17 @@ void TabFilament::update() wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); m_cooling_description_line->SetText(text); - text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); - m_volumetric_speed_description_line->SetText(text); + this->update_volumetric_flow_preset_hints(); Layout(); - bool cooling = m_config->opt_bool("cooling", 0); - bool fan_always_on = cooling || m_config->opt_bool("fan_always_on", 0); + bool cooling = m_config->opt_bool("cooling", 0); + bool fan_always_on = cooling || m_config->opt_bool("fan_always_on", 0); - for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }) - get_field(el)->toggle(cooling); + for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }) + get_field(el)->toggle(cooling); - for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) - get_field(el)->toggle(fan_always_on); + for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) + get_field(el)->toggle(fan_always_on); update_filament_overrides_page(); @@ -1790,147 +1812,147 @@ void TabFilament::update() void TabFilament::OnActivate() { - m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle))); + this->update_volumetric_flow_preset_hints(); Tab::OnActivate(); } wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText) { - *StaticText = new ogStaticText(parent, ""); + *StaticText = new ogStaticText(parent, ""); // auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT); - (*StaticText)->SetFont(wxGetApp().normal_font()); + (*StaticText)->SetFont(wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(*StaticText, 1, wxEXPAND|wxALL, 0); - return sizer; + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(*StaticText, 1, wxEXPAND|wxALL, 0); + return sizer; } bool Tab::current_preset_is_dirty() { - return m_presets->current_is_dirty(); + return m_presets->current_is_dirty(); } void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) { - const PrinterTechnology tech = m_presets->get_selected_preset().printer_technology(); + const PrinterTechnology tech = m_presets->get_selected_preset().printer_technology(); - // Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment) - if (tech == ptFFF) { - optgroup->append_single_option_line("host_type"); - } + // Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment) + if (tech == ptFFF) { + optgroup->append_single_option_line("host_type"); + } - auto printhost_browse = [=](wxWindow* parent) { + auto printhost_browse = [=](wxWindow* parent) { add_scaled_button(parent, &m_printhost_browse_btn, "browse", _(L("Browse")) + " "+ dots, wxBU_LEFT | wxBU_EXACTFIT); ScalableButton* btn = m_printhost_browse_btn; - btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { - BonjourDialog dialog(parent, tech); - if (dialog.show_and_lookup()) { - optgroup->set_value("print_host", std::move(dialog.get_selected()), true); - optgroup->get_field("print_host")->field_changed(); - } - }); + btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { + BonjourDialog dialog(parent, tech); + if (dialog.show_and_lookup()) { + optgroup->set_value("print_host", std::move(dialog.get_selected()), true); + optgroup->get_field("print_host")->field_changed(); + } + }); - return sizer; - }; + return sizer; + }; - auto print_host_test = [this](wxWindow* parent) { + auto print_host_test = [this](wxWindow* parent) { add_scaled_button(parent, &m_print_host_test_btn, "test", _(L("Test")), wxBU_LEFT | wxBU_EXACTFIT); ScalableButton* btn = m_print_host_test_btn; btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - if (! host) { - const auto text = wxString::Format("%s", - _(L("Could not get a valid Printer Host reference"))); - show_error(this, text); - return; - } - wxString msg; - if (host->test(msg)) { - show_info(this, host->get_test_ok_msg(), _(L("Success!"))); - } else { - show_error(this, host->get_test_failed_msg(msg)); - } - }); + btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { + std::unique_ptr host(PrintHost::get_print_host(m_config)); + if (! host) { + const auto text = wxString::Format("%s", + _(L("Could not get a valid Printer Host reference"))); + show_error(this, text); + return; + } + wxString msg; + if (host->test(msg)) { + show_info(this, host->get_test_ok_msg(), _(L("Success!"))); + } else { + show_error(this, host->get_test_failed_msg(msg)); + } + }); - return sizer; - }; + return sizer; + }; - Line host_line = optgroup->create_single_option_line("print_host"); - host_line.append_widget(printhost_browse); - host_line.append_widget(print_host_test); - optgroup->append_line(host_line); - optgroup->append_single_option_line("printhost_apikey"); + Line host_line = optgroup->create_single_option_line("print_host"); + host_line.append_widget(printhost_browse); + host_line.append_widget(print_host_test); + optgroup->append_line(host_line); + optgroup->append_single_option_line("printhost_apikey"); - const auto ca_file_hint = _(L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate.")); + const auto ca_file_hint = _(L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate.")); - if (Http::ca_file_supported()) { - Line cafile_line = optgroup->create_single_option_line("printhost_cafile"); + if (Http::ca_file_supported()) { + Line cafile_line = optgroup->create_single_option_line("printhost_cafile"); - auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) { - auto btn = new wxButton(parent, wxID_ANY, " " + _(L("Browse"))+" " +dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); - btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - btn->SetBitmap(create_scaled_bitmap(this, "browse")); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) { + auto btn = new wxButton(parent, wxID_ANY, " " + _(L("Browse"))+" " +dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + btn->SetBitmap(create_scaled_bitmap(this, "browse")); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this, optgroup] (wxCommandEvent e) { - static const auto filemasks = _(L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*")); - wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (openFileDialog.ShowModal() != wxID_CANCEL) { - optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true); - optgroup->get_field("printhost_cafile")->field_changed(); - } - }); + btn->Bind(wxEVT_BUTTON, [this, optgroup] (wxCommandEvent e) { + static const auto filemasks = _(L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*")); + wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (openFileDialog.ShowModal() != wxID_CANCEL) { + optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true); + optgroup->get_field("printhost_cafile")->field_changed(); + } + }); - return sizer; - }; + return sizer; + }; - cafile_line.append_widget(printhost_cafile_browse); - optgroup->append_line(cafile_line); + cafile_line.append_widget(printhost_cafile_browse); + optgroup->append_line(cafile_line); - Line cafile_hint { "", "" }; - cafile_hint.full_width = 1; - cafile_hint.widget = [this, ca_file_hint](wxWindow* parent) { - auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt); - return sizer; - }; - optgroup->append_line(cafile_hint); - } else { - Line line { "", "" }; - line.full_width = 1; + Line cafile_hint { "", "" }; + cafile_hint.full_width = 1; + cafile_hint.widget = [this, ca_file_hint](wxWindow* parent) { + auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(txt); + return sizer; + }; + optgroup->append_line(cafile_hint); + } else { + Line line { "", "" }; + line.full_width = 1; - line.widget = [this, ca_file_hint] (wxWindow* parent) { - auto txt = new wxStaticText(parent, wxID_ANY, wxString::Format("%s\n\n\t%s", - wxString::Format(_(L("HTTPS CA File:\n\ + line.widget = [this, ca_file_hint] (wxWindow* parent) { + auto txt = new wxStaticText(parent, wxID_ANY, wxString::Format("%s\n\n\t%s", + wxString::Format(_(L("HTTPS CA File:\n\ \tOn this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.\n\ \tTo use a custom CA file, please import your CA file into Certificate Store / Keychain.")), SLIC3R_APP_NAME), - ca_file_hint)); - txt->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt); - return sizer; - }; + ca_file_hint)); + txt->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(txt); + return sizer; + }; - optgroup->append_line(line); - } + optgroup->append_line(line); + } } void TabPrinter::build() { - m_presets = &m_preset_bundle->printers; - load_initial_data(); + m_presets = &m_preset_bundle->printers; + load_initial_data(); m_printer_technology = m_presets->get_selected_preset().printer_technology(); @@ -1941,31 +1963,31 @@ void TabPrinter::build_fff() { if (!m_pages.empty()) m_pages.resize(0); - // to avoid redundant memory allocation / deallocation during extruders count changing - m_pages.reserve(30); + // to avoid redundant memory allocation / deallocation during extruders count changing + m_pages.reserve(30); - auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); - m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); + auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); + m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); wxGetApp().sidebar().update_objects_list_extruder_column(m_initial_extruders_count); - const Preset* parent_preset = m_presets->get_selected_preset_parent(); - m_sys_extruders_count = parent_preset == nullptr ? 0 : - static_cast(parent_preset->config.option("nozzle_diameter"))->values.size(); + const Preset* parent_preset = m_presets->get_selected_preset_parent(); + m_sys_extruders_count = parent_preset == nullptr ? 0 : + static_cast(parent_preset->config.option("nozzle_diameter"))->values.size(); - auto page = add_options_page(_(L("General")), "printer"); - auto optgroup = page->new_optgroup(_(L("Size and coordinates"))); + auto page = add_options_page(_(L("General")), "printer"); + auto optgroup = page->new_optgroup(_(L("Size and coordinates"))); Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" }; - line.widget = [this](wxWindow* parent) { + line.widget = [this](wxWindow* parent) { ScalableButton* btn; add_scaled_button(parent, &btn, "printer_white", " " + _(L("Set")) + " " + dots, wxBU_LEFT | wxBU_EXACTFIT); btn->SetFont(wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) - { + btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) + { BedShapeDialog dlg(this); dlg.build_dialog(*m_config->option("bed_shape"), *m_config->option("bed_custom_texture"), @@ -1984,31 +2006,31 @@ void TabPrinter::build_fff() } })); - return sizer; - }; - optgroup->append_line(line, &m_colored_Label); + return sizer; + }; + optgroup->append_line(line, &m_colored_Label); optgroup->append_single_option_line("max_print_height"); optgroup->append_single_option_line("z_offset"); - optgroup = page->new_optgroup(_(L("Capabilities"))); - ConfigOptionDef def; - def.type = coInt, - def.set_default_value(new ConfigOptionInt(1)); - def.label = L("Extruders"); - def.tooltip = L("Number of extruders of the printer."); - def.min = 1; + optgroup = page->new_optgroup(_(L("Capabilities"))); + ConfigOptionDef def; + def.type = coInt, + def.set_default_value(new ConfigOptionInt(1)); + def.label = L("Extruders"); + def.tooltip = L("Number of extruders of the printer."); + def.min = 1; def.mode = comExpert; - Option option(def, "extruders_count"); - optgroup->append_single_option_line(option); - optgroup->append_single_option_line("single_extruder_multi_material"); + Option option(def, "extruders_count"); + optgroup->append_single_option_line(option); + optgroup->append_single_option_line("single_extruder_multi_material"); - optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) { - size_t extruders_count = boost::any_cast(optgroup->get_value("extruders_count")); - wxTheApp->CallAfter([this, opt_key, value, extruders_count]() { - if (opt_key == "extruders_count" || opt_key == "single_extruder_multi_material") { - extruders_count_changed(extruders_count); + optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) { + size_t extruders_count = boost::any_cast(optgroup->get_value("extruders_count")); + wxTheApp->CallAfter([this, opt_key, value, extruders_count]() { + if (opt_key == "extruders_count" || opt_key == "single_extruder_multi_material") { + extruders_count_changed(extruders_count); init_options_list(); // m_options_list should be updated before UI updating - update_dirty(); + update_dirty(); if (opt_key == "single_extruder_multi_material") { // the single_extruder_multimaterial was added to force pages on_value_change(opt_key, value); // rebuild - let's make sure the on_value_change is not skipped @@ -2024,165 +2046,168 @@ void TabPrinter::build_fff() "and all extruders must have the same diameter.\n" "Do you want to change the diameter for all extruders to first extruder nozzle diameter value?")); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); - + + DynamicPrintConfig new_conf = *m_config; if (dialog->ShowModal() == wxID_YES) { - DynamicPrintConfig new_conf = *m_config; for (size_t i = 1; i < nozzle_diameters.size(); i++) nozzle_diameters[i] = frst_diam; new_conf.set_key_value("nozzle_diameter", new ConfigOptionFloats(nozzle_diameters)); - load_config(new_conf); } + else + new_conf.set_key_value("single_extruder_multi_material", new ConfigOptionBool(false)); + + load_config(new_conf); break; } - } + } } } - } - else { - update_dirty(); - on_value_change(opt_key, value); - } - }); - }; + } + else { + update_dirty(); + on_value_change(opt_key, value); + } + }); + }; #if 0 - if (!m_no_controller) - { - optgroup = page->new_optgroup(_(L("USB/Serial connection"))); - line = {_(L("Serial port")), ""}; - Option serial_port = optgroup->get_option("serial_port"); - serial_port.side_widget = ([this](wxWindow* parent) { - auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(Slic3r::var("arrow_rotate_clockwise.png")), wxBITMAP_TYPE_PNG), - wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); - btn->SetToolTip(_(L("Rescan serial ports"))); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + if (!m_no_controller) + { + optgroup = page->new_optgroup(_(L("USB/Serial connection"))); + line = {_(L("Serial port")), ""}; + Option serial_port = optgroup->get_option("serial_port"); + serial_port.side_widget = ([this](wxWindow* parent) { + auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(Slic3r::var("arrow_rotate_clockwise.png")), wxBITMAP_TYPE_PNG), + wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); + btn->SetToolTip(_(L("Rescan serial ports"))); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) {update_serial_ports(); }); - return sizer; - }); - auto serial_test = [this](wxWindow* parent) { - auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY, - _(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetFont(Slic3r::GUI::small_font()); - btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG)); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) {update_serial_ports(); }); + return sizer; + }); + auto serial_test = [this](wxWindow* parent) { + auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY, + _(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + btn->SetFont(Slic3r::GUI::small_font()); + btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); - btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) { - auto sender = Slic3r::make_unique(); - auto res = sender->connect( - m_config->opt_string("serial_port"), - m_config->opt_int("serial_speed") - ); - if (res && sender->wait_connected()) { - show_info(parent, _(L("Connection to printer works correctly.")), _(L("Success!"))); - } - else { - show_error(parent, _(L("Connection failed."))); - } - }); - return sizer; - }; + btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) { + auto sender = Slic3r::make_unique(); + auto res = sender->connect( + m_config->opt_string("serial_port"), + m_config->opt_int("serial_speed") + ); + if (res && sender->wait_connected()) { + show_info(parent, _(L("Connection to printer works correctly.")), _(L("Success!"))); + } + else { + show_error(parent, _(L("Connection failed."))); + } + }); + return sizer; + }; - line.append_option(serial_port); - line.append_option(optgroup->get_option("serial_speed")); - line.append_widget(serial_test); - optgroup->append_line(line); - } + line.append_option(serial_port); + line.append_option(optgroup->get_option("serial_speed")); + line.append_widget(serial_test); + optgroup->append_line(line); + } #endif - optgroup = page->new_optgroup(_(L("Print Host upload"))); - build_printhost(optgroup.get()); + optgroup = page->new_optgroup(_(L("Print Host upload"))); + build_printhost(optgroup.get()); - optgroup = page->new_optgroup(_(L("Firmware"))); - optgroup->append_single_option_line("gcode_flavor"); - optgroup->append_single_option_line("silent_mode"); - optgroup->append_single_option_line("remaining_times"); + optgroup = page->new_optgroup(_(L("Firmware"))); + optgroup->append_single_option_line("gcode_flavor"); + optgroup->append_single_option_line("silent_mode"); + optgroup->append_single_option_line("remaining_times"); - optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) { - wxTheApp->CallAfter([this, opt_key, value]() { - if (opt_key == "silent_mode") { - bool val = boost::any_cast(value); - if (m_use_silent_mode != val) { - m_rebuild_kinematics_page = true; - m_use_silent_mode = val; - } - } - build_unregular_pages(); - update_dirty(); - on_value_change(opt_key, value); - }); - }; + optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) { + wxTheApp->CallAfter([this, opt_key, value]() { + if (opt_key == "silent_mode") { + bool val = boost::any_cast(value); + if (m_use_silent_mode != val) { + m_rebuild_kinematics_page = true; + m_use_silent_mode = val; + } + } + build_unregular_pages(); + update_dirty(); + on_value_change(opt_key, value); + }); + }; - optgroup = page->new_optgroup(_(L("Advanced"))); - optgroup->append_single_option_line("use_relative_e_distances"); - optgroup->append_single_option_line("use_firmware_retraction"); - optgroup->append_single_option_line("use_volumetric_e"); - optgroup->append_single_option_line("variable_layer_height"); + optgroup = page->new_optgroup(_(L("Advanced"))); + optgroup->append_single_option_line("use_relative_e_distances"); + optgroup->append_single_option_line("use_firmware_retraction"); + optgroup->append_single_option_line("use_volumetric_e"); + optgroup->append_single_option_line("variable_layer_height"); const int gcode_field_height = 15; // 150 const int notes_field_height = 25; // 250 - page = add_options_page(_(L("Custom G-code")), "cog"); - optgroup = page->new_optgroup(_(L("Start G-code")), 0); - option = optgroup->get_option("start_gcode"); - option.opt.full_width = true; + page = add_options_page(_(L("Custom G-code")), "cog"); + optgroup = page->new_optgroup(_(L("Start G-code")), 0); + option = optgroup->get_option("start_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("End G-code")), 0); - option = optgroup->get_option("end_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("End G-code")), 0); + option = optgroup->get_option("end_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("Before layer change G-code")), 0); - option = optgroup->get_option("before_layer_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("Before layer change G-code")), 0); + option = optgroup->get_option("before_layer_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("After layer change G-code")), 0); - option = optgroup->get_option("layer_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("After layer change G-code")), 0); + option = optgroup->get_option("layer_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("Tool change G-code")), 0); - option = optgroup->get_option("toolchange_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("Tool change G-code")), 0); + option = optgroup->get_option("toolchange_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(_(L("Between objects G-code (for sequential printing)")), 0); - option = optgroup->get_option("between_objects_gcode"); - option.opt.full_width = true; + optgroup = page->new_optgroup(_(L("Between objects G-code (for sequential printing)")), 0); + option = optgroup->get_option("between_objects_gcode"); + option.opt.full_width = true; option.opt.height = gcode_field_height;//150; - optgroup->append_single_option_line(option); - - page = add_options_page(_(L("Notes")), "note.png"); - optgroup = page->new_optgroup(_(L("Notes")), 0); - option = optgroup->get_option("printer_notes"); - option.opt.full_width = true; + optgroup->append_single_option_line(option); + + page = add_options_page(_(L("Notes")), "note.png"); + optgroup = page->new_optgroup(_(L("Notes")), 0); + option = optgroup->get_option("printer_notes"); + option.opt.full_width = true; option.opt.height = notes_field_height;//250; - optgroup->append_single_option_line(option); + optgroup->append_single_option_line(option); - page = add_options_page(_(L("Dependencies")), "wrench.png"); - optgroup = page->new_optgroup(_(L("Profile dependencies"))); - line = Line{ "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_parent_preset_description_line); - }; - optgroup->append_line(line); + page = add_options_page(_(L("Dependencies")), "wrench.png"); + optgroup = page->new_optgroup(_(L("Profile dependencies"))); + line = Line{ "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_parent_preset_description_line); + }; + optgroup->append_line(line); - build_unregular_pages(); + build_unregular_pages(); #if 0 - if (!m_no_controller) - update_serial_ports(); + if (!m_no_controller) + update_serial_ports(); #endif } @@ -2238,7 +2263,7 @@ void TabPrinter::build_sla() line.append_option(optgroup->get_option("display_pixels_y")); optgroup->append_line(line); optgroup->append_single_option_line("display_orientation"); - + // FIXME: This should be on one line in the UI optgroup->append_single_option_line("display_mirror_x"); optgroup->append_single_option_line("display_mirror_y"); @@ -2289,28 +2314,28 @@ void TabPrinter::build_sla() void TabPrinter::update_serial_ports() { - Field *field = get_field("serial_port"); - Choice *choice = static_cast(field); - choice->set_values(Utils::scan_serial_ports()); + Field *field = get_field("serial_port"); + Choice *choice = static_cast(field); + choice->set_values(Utils::scan_serial_ports()); } void TabPrinter::extruders_count_changed(size_t extruders_count) { bool is_count_changed = false; if (m_extruders_count != extruders_count) { - m_extruders_count = extruders_count; - m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); - m_preset_bundle->update_multi_material_filament_presets(); + m_extruders_count = extruders_count; + m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); + m_preset_bundle->update_multi_material_filament_presets(); is_count_changed = true; } - else if (m_extruders_count == 1 && + else if (m_extruders_count == 1 && m_preset_bundle->project_config.option("wiping_volumes_matrix")->values.size()>1) m_preset_bundle->update_multi_material_filament_presets(); - /* This function should be call in any case because of correct updating/rebuilding + /* This function should be call in any case because of correct updating/rebuilding * of unregular pages of a Printer Settings */ - build_unregular_pages(); + build_unregular_pages(); if (is_count_changed) { on_value_change("extruders_count", extruders_count); @@ -2320,81 +2345,81 @@ void TabPrinter::extruders_count_changed(size_t extruders_count) void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) { - auto option = optgroup->get_option(opt_key, 0); - auto line = Line{ _(option.opt.full_label), "" }; - line.append_option(option); - if (m_use_silent_mode) - line.append_option(optgroup->get_option(opt_key, 1)); - optgroup->append_line(line); + auto option = optgroup->get_option(opt_key, 0); + auto line = Line{ _(option.opt.full_label), "" }; + line.append_option(option); + if (m_use_silent_mode) + line.append_option(optgroup->get_option(opt_key, 1)); + optgroup->append_line(line); } PageShp TabPrinter::build_kinematics_page() { - auto page = add_options_page(_(L("Machine limits")), "cog", true); + auto page = add_options_page(_(L("Machine limits")), "cog", true); - if (m_use_silent_mode) { - // Legend for OptionsGroups - auto optgroup = page->new_optgroup(""); - optgroup->set_show_modified_btns_val(false); + if (m_use_silent_mode) { + // Legend for OptionsGroups + auto optgroup = page->new_optgroup(""); + optgroup->set_show_modified_btns_val(false); optgroup->label_width = 23;// 230; - auto line = Line{ "", "" }; + auto line = Line{ "", "" }; - ConfigOptionDef def; - def.type = coString; - def.width = 15; - def.gui_type = "legend"; + ConfigOptionDef def; + def.type = coString; + def.width = 15; + def.gui_type = "legend"; def.mode = comAdvanced; - def.tooltip = L("Values in this column are for Normal mode"); - def.set_default_value(new ConfigOptionString{ _(L("Normal")).ToUTF8().data() }); + def.tooltip = L("Values in this column are for Normal mode"); + def.set_default_value(new ConfigOptionString{ _(L("Normal")).ToUTF8().data() }); - auto option = Option(def, "full_power_legend"); - line.append_option(option); + auto option = Option(def, "full_power_legend"); + line.append_option(option); - def.tooltip = L("Values in this column are for Stealth mode"); - def.set_default_value(new ConfigOptionString{ _(L("Stealth")).ToUTF8().data() }); - option = Option(def, "silent_legend"); - line.append_option(option); + def.tooltip = L("Values in this column are for Stealth mode"); + def.set_default_value(new ConfigOptionString{ _(L("Stealth")).ToUTF8().data() }); + option = Option(def, "silent_legend"); + line.append_option(option); - optgroup->append_line(line); - } + optgroup->append_line(line); + } - std::vector axes{ "x", "y", "z", "e" }; - auto optgroup = page->new_optgroup(_(L("Maximum feedrates"))); - for (const std::string &axis : axes) { - append_option_line(optgroup, "machine_max_feedrate_" + axis); - } + std::vector axes{ "x", "y", "z", "e" }; + auto optgroup = page->new_optgroup(_(L("Maximum feedrates"))); + for (const std::string &axis : axes) { + append_option_line(optgroup, "machine_max_feedrate_" + axis); + } - optgroup = page->new_optgroup(_(L("Maximum accelerations"))); - for (const std::string &axis : axes) { - append_option_line(optgroup, "machine_max_acceleration_" + axis); - } - append_option_line(optgroup, "machine_max_acceleration_extruding"); - append_option_line(optgroup, "machine_max_acceleration_retracting"); + optgroup = page->new_optgroup(_(L("Maximum accelerations"))); + for (const std::string &axis : axes) { + append_option_line(optgroup, "machine_max_acceleration_" + axis); + } + append_option_line(optgroup, "machine_max_acceleration_extruding"); + append_option_line(optgroup, "machine_max_acceleration_retracting"); - optgroup = page->new_optgroup(_(L("Jerk limits"))); - for (const std::string &axis : axes) { - append_option_line(optgroup, "machine_max_jerk_" + axis); - } + optgroup = page->new_optgroup(_(L("Jerk limits"))); + for (const std::string &axis : axes) { + append_option_line(optgroup, "machine_max_jerk_" + axis); + } - optgroup = page->new_optgroup(_(L("Minimum feedrates"))); - append_option_line(optgroup, "machine_min_extruding_rate"); - append_option_line(optgroup, "machine_min_travel_rate"); + optgroup = page->new_optgroup(_(L("Minimum feedrates"))); + append_option_line(optgroup, "machine_min_extruding_rate"); + append_option_line(optgroup, "machine_min_travel_rate"); - return page; + return page; } /* Previous name build_extruder_pages(). - * - * This function was renamed because of now it implements not just an extruder pages building, - * but "Machine limits" and "Single extruder MM setup" too + * + * This function was renamed because of now it implements not just an extruder pages building, + * but "Machine limits" and "Single extruder MM setup" too * (These pages can changes according to the another values of a current preset) * */ void TabPrinter::build_unregular_pages() { - size_t n_before_extruders = 2; // Count of pages before Extruder pages - bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; + size_t n_before_extruders = 2; // Count of pages before Extruder pages + bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; - /* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages + /* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages * and be cause of application crash, when try to change Preset in moment, * when one of unregular pages is selected. * */ @@ -2412,62 +2437,62 @@ void TabPrinter::build_unregular_pages() }; #endif //__WXMSW__ - // Add/delete Kinematics page according to is_marlin_flavor - size_t existed_page = 0; - for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already - if (m_pages[i]->title().find(_(L("Machine limits"))) != std::string::npos) { - if (!is_marlin_flavor || m_rebuild_kinematics_page) - m_pages.erase(m_pages.begin() + i); - else - existed_page = i; - break; - } + // Add/delete Kinematics page according to is_marlin_flavor + size_t existed_page = 0; + for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already + if (m_pages[i]->title().find(_(L("Machine limits"))) != std::string::npos) { + if (!is_marlin_flavor || m_rebuild_kinematics_page) + m_pages.erase(m_pages.begin() + i); + else + existed_page = i; + break; + } - if (existed_page < n_before_extruders && is_marlin_flavor) { - auto page = build_kinematics_page(); + if (existed_page < n_before_extruders && is_marlin_flavor) { + auto page = build_kinematics_page(); #ifdef __WXMSW__ - layout_page(page); + layout_page(page); #endif - m_pages.insert(m_pages.begin() + n_before_extruders, page); - } + m_pages.insert(m_pages.begin() + n_before_extruders, page); + } - if (is_marlin_flavor) - n_before_extruders++; - size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page + if (is_marlin_flavor) + n_before_extruders++; + size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page - if (m_extruders_count_old == m_extruders_count || - (m_has_single_extruder_MM_page && m_extruders_count == 1)) - { - // if we have a single extruder MM setup, add a page with configuration options: - for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already - if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) { - m_pages.erase(m_pages.begin() + i); - break; - } - m_has_single_extruder_MM_page = false; - } - if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page) { - // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves - auto page = add_options_page(_(L("Single extruder MM setup")), "printer", true); - auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters"))); - optgroup->append_single_option_line("cooling_tube_retraction"); - optgroup->append_single_option_line("cooling_tube_length"); - optgroup->append_single_option_line("parking_pos_retraction"); + if (m_extruders_count_old == m_extruders_count || + (m_has_single_extruder_MM_page && m_extruders_count == 1)) + { + // if we have a single extruder MM setup, add a page with configuration options: + for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already + if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) { + m_pages.erase(m_pages.begin() + i); + break; + } + m_has_single_extruder_MM_page = false; + } + if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page) { + // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves + auto page = add_options_page(_(L("Single extruder MM setup")), "printer", true); + auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters"))); + optgroup->append_single_option_line("cooling_tube_retraction"); + optgroup->append_single_option_line("cooling_tube_length"); + optgroup->append_single_option_line("parking_pos_retraction"); optgroup->append_single_option_line("extra_loading_move"); optgroup->append_single_option_line("high_current_on_filament_swap"); - m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); - m_has_single_extruder_MM_page = true; - } - + m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); + m_has_single_extruder_MM_page = true; + } + // Build missed extruder pages - for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx) { - //# build page + for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx) { + //# build page const wxString& page_name = wxString::Format(_(L("Extruder %d")), int(extruder_idx + 1)); auto page = add_options_page(page_name, "funnel", true); - m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page); - - auto optgroup = page->new_optgroup(_(L("Size"))); - optgroup->append_single_option_line("nozzle_diameter", extruder_idx); + m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page); + + auto optgroup = page->new_optgroup(_(L("Size"))); + optgroup->append_single_option_line("nozzle_diameter", extruder_idx); optgroup->m_on_change = [this, extruder_idx](const t_config_option_key& opt_key, boost::any value) { @@ -2478,9 +2503,10 @@ void TabPrinter::build_unregular_pages() std::vector nozzle_diameters = static_cast(m_config->option("nozzle_diameter"))->values; // if value was changed - if (fabs(nozzle_diameters[extruder_idx == 0 ? 1 : 0] - new_nd) > EPSILON) + if (fabs(nozzle_diameters[extruder_idx == 0 ? 1 : 0] - new_nd) > EPSILON) { - const wxString msg_text = _(L("Do you want to change the diameter for all extruders?")); + const wxString msg_text = _(L("This is a single extruder multimaterial printer, diameters of all extruders " + "will be set to the new value. Do you want to proceed?")); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); DynamicPrintConfig new_conf = *m_config; @@ -2491,7 +2517,7 @@ void TabPrinter::build_unregular_pages() nozzle_diameters[i] = new_nd; } } - else + else nozzle_diameters[extruder_idx] = nozzle_diameters[extruder_idx == 0 ? 1 : 0]; new_conf.set_key_value("nozzle_diameter", new ConfigOptionFloats(nozzle_diameters)); @@ -2502,52 +2528,52 @@ void TabPrinter::build_unregular_pages() update_dirty(); update(); }; - - optgroup = page->new_optgroup(_(L("Layer height limits"))); - optgroup->append_single_option_line("min_layer_height", extruder_idx); - optgroup->append_single_option_line("max_layer_height", extruder_idx); - - - optgroup = page->new_optgroup(_(L("Position (for multi-extruder printers)"))); - optgroup->append_single_option_line("extruder_offset", extruder_idx); - - optgroup = page->new_optgroup(_(L("Retraction"))); - optgroup->append_single_option_line("retract_length", extruder_idx); - optgroup->append_single_option_line("retract_lift", extruder_idx); - Line line = { _(L("Only lift Z")), "" }; - line.append_option(optgroup->get_option("retract_lift_above", extruder_idx)); - line.append_option(optgroup->get_option("retract_lift_below", extruder_idx)); - optgroup->append_line(line); - - optgroup->append_single_option_line("retract_speed", extruder_idx); - optgroup->append_single_option_line("deretract_speed", extruder_idx); - optgroup->append_single_option_line("retract_restart_extra", extruder_idx); - optgroup->append_single_option_line("retract_before_travel", extruder_idx); - optgroup->append_single_option_line("retract_layer_change", extruder_idx); - optgroup->append_single_option_line("wipe", extruder_idx); - optgroup->append_single_option_line("retract_before_wipe", extruder_idx); - - optgroup = page->new_optgroup(_(L("Retraction when tool is disabled (advanced settings for multi-extruder setups)"))); - optgroup->append_single_option_line("retract_length_toolchange", extruder_idx); - optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx); - optgroup = page->new_optgroup(_(L("Preview"))); - optgroup->append_single_option_line("extruder_colour", extruder_idx); + optgroup = page->new_optgroup(_(L("Layer height limits"))); + optgroup->append_single_option_line("min_layer_height", extruder_idx); + optgroup->append_single_option_line("max_layer_height", extruder_idx); + + + optgroup = page->new_optgroup(_(L("Position (for multi-extruder printers)"))); + optgroup->append_single_option_line("extruder_offset", extruder_idx); + + optgroup = page->new_optgroup(_(L("Retraction"))); + optgroup->append_single_option_line("retract_length", extruder_idx); + optgroup->append_single_option_line("retract_lift", extruder_idx); + Line line = { _(L("Only lift Z")), "" }; + line.append_option(optgroup->get_option("retract_lift_above", extruder_idx)); + line.append_option(optgroup->get_option("retract_lift_below", extruder_idx)); + optgroup->append_line(line); + + optgroup->append_single_option_line("retract_speed", extruder_idx); + optgroup->append_single_option_line("deretract_speed", extruder_idx); + optgroup->append_single_option_line("retract_restart_extra", extruder_idx); + optgroup->append_single_option_line("retract_before_travel", extruder_idx); + optgroup->append_single_option_line("retract_layer_change", extruder_idx); + optgroup->append_single_option_line("wipe", extruder_idx); + optgroup->append_single_option_line("retract_before_wipe", extruder_idx); + + optgroup = page->new_optgroup(_(L("Retraction when tool is disabled (advanced settings for multi-extruder setups)"))); + optgroup->append_single_option_line("retract_length_toolchange", extruder_idx); + optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx); + + optgroup = page->new_optgroup(_(L("Preview"))); + optgroup->append_single_option_line("extruder_colour", extruder_idx); #ifdef __WXMSW__ - layout_page(page); + layout_page(page); #endif - } - - // # remove extra pages - if (m_extruders_count < m_extruders_count_old) - m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count, - m_pages.begin() + n_before_extruders + m_extruders_count_old); + } + + // # remove extra pages + if (m_extruders_count < m_extruders_count_old) + m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count, + m_pages.begin() + n_before_extruders + m_extruders_count_old); Thaw(); - m_extruders_count_old = m_extruders_count; - rebuild_page_tree(); + m_extruders_count_old = m_extruders_count; + rebuild_page_tree(); // Reload preset pages with current configuration values reload_config(); @@ -2556,12 +2582,12 @@ void TabPrinter::build_unregular_pages() // this gets executed after preset is loaded and before GUI fields are updated void TabPrinter::on_preset_loaded() { - // update the extruders count field - auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); - int extruders_count = nozzle_diameter->values.size(); - set_value("extruders_count", extruders_count); - // update the GUI field according to the number of nozzle diameters supplied - extruders_count_changed(extruders_count); + // update the extruders count field + auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); + int extruders_count = nozzle_diameter->values.size(); + set_value("extruders_count", extruders_count); + // update the GUI field according to the number of nozzle diameters supplied + extruders_count_changed(extruders_count); } void TabPrinter::update_pages() @@ -2597,7 +2623,7 @@ void TabPrinter::update_pages() wxGetApp().sidebar().update_objects_list_extruder_column(m_extruders_count); } - else + else m_pages_sla.empty() ? build_sla() : m_pages.swap(m_pages_sla); rebuild_page_tree(); @@ -2617,102 +2643,102 @@ void TabPrinter::update_fff() { // Freeze(); - bool en; - auto serial_speed = get_field("serial_speed"); - if (serial_speed != nullptr) { - en = !m_config->opt_string("serial_port").empty(); - get_field("serial_speed")->toggle(en); - if (m_config->opt_int("serial_speed") != 0 && en) - m_serial_test_btn->Enable(); - else - m_serial_test_btn->Disable(); - } + bool en; + auto serial_speed = get_field("serial_speed"); + if (serial_speed != nullptr) { + en = !m_config->opt_string("serial_port").empty(); + get_field("serial_speed")->toggle(en); + if (m_config->opt_int("serial_speed") != 0 && en) + m_serial_test_btn->Enable(); + else + m_serial_test_btn->Disable(); + } - { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - m_print_host_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test()); - m_printhost_browse_btn->Enable(host->has_auto_discovery()); - } + { + std::unique_ptr host(PrintHost::get_print_host(m_config)); + m_print_host_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test()); + m_printhost_browse_btn->Enable(host->has_auto_discovery()); + } - bool have_multiple_extruders = m_extruders_count > 1; - get_field("toolchange_gcode")->toggle(have_multiple_extruders); - get_field("single_extruder_multi_material")->toggle(have_multiple_extruders); + bool have_multiple_extruders = m_extruders_count > 1; + get_field("toolchange_gcode")->toggle(have_multiple_extruders); + get_field("single_extruder_multi_material")->toggle(have_multiple_extruders); - bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; + bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; - { - Field *sm = get_field("silent_mode"); - if (! is_marlin_flavor) - // Disable silent mode for non-marlin firmwares. - get_field("silent_mode")->toggle(false); - if (is_marlin_flavor) - sm->enable(); - else - sm->disable(); - } + { + Field *sm = get_field("silent_mode"); + if (! is_marlin_flavor) + // Disable silent mode for non-marlin firmwares. + get_field("silent_mode")->toggle(false); + if (is_marlin_flavor) + sm->enable(); + else + sm->disable(); + } - if (m_use_silent_mode != m_config->opt_bool("silent_mode")) { - m_rebuild_kinematics_page = true; - m_use_silent_mode = m_config->opt_bool("silent_mode"); - } + if (m_use_silent_mode != m_config->opt_bool("silent_mode")) { + m_rebuild_kinematics_page = true; + m_use_silent_mode = m_config->opt_bool("silent_mode"); + } - for (size_t i = 0; i < m_extruders_count; ++i) { - bool have_retract_length = m_config->opt_float("retract_length", i) > 0; + for (size_t i = 0; i < m_extruders_count; ++i) { + bool have_retract_length = m_config->opt_float("retract_length", i) > 0; - // when using firmware retraction, firmware decides retraction length - bool use_firmware_retraction = m_config->opt_bool("use_firmware_retraction"); - get_field("retract_length", i)->toggle(!use_firmware_retraction); + // when using firmware retraction, firmware decides retraction length + bool use_firmware_retraction = m_config->opt_bool("use_firmware_retraction"); + get_field("retract_length", i)->toggle(!use_firmware_retraction); - // user can customize travel length if we have retraction length or we"re using - // firmware retraction - get_field("retract_before_travel", i)->toggle(have_retract_length || use_firmware_retraction); + // user can customize travel length if we have retraction length or we"re using + // firmware retraction + get_field("retract_before_travel", i)->toggle(have_retract_length || use_firmware_retraction); - // user can customize other retraction options if retraction is enabled - bool retraction = (have_retract_length || use_firmware_retraction); - std::vector vec = { "retract_lift", "retract_layer_change" }; - for (auto el : vec) - get_field(el, i)->toggle(retraction); + // user can customize other retraction options if retraction is enabled + bool retraction = (have_retract_length || use_firmware_retraction); + std::vector vec = { "retract_lift", "retract_layer_change" }; + for (auto el : vec) + get_field(el, i)->toggle(retraction); - // retract lift above / below only applies if using retract lift - vec.resize(0); - vec = { "retract_lift_above", "retract_lift_below" }; - for (auto el : vec) - get_field(el, i)->toggle(retraction && m_config->opt_float("retract_lift", i) > 0); + // retract lift above / below only applies if using retract lift + vec.resize(0); + vec = { "retract_lift_above", "retract_lift_below" }; + for (auto el : vec) + get_field(el, i)->toggle(retraction && m_config->opt_float("retract_lift", i) > 0); - // some options only apply when not using firmware retraction - vec.resize(0); - vec = { "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "wipe" }; - for (auto el : vec) - get_field(el, i)->toggle(retraction && !use_firmware_retraction); + // some options only apply when not using firmware retraction + vec.resize(0); + vec = { "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "wipe" }; + for (auto el : vec) + get_field(el, i)->toggle(retraction && !use_firmware_retraction); - bool wipe = m_config->opt_bool("wipe", i); - get_field("retract_before_wipe", i)->toggle(wipe); + bool wipe = m_config->opt_bool("wipe", i); + get_field("retract_before_wipe", i)->toggle(wipe); - if (use_firmware_retraction && wipe) { - auto dialog = new wxMessageDialog(parent(), - _(L("The Wipe option is not available when using the Firmware Retraction mode.\n" - "\nShall I disable it in order to enable Firmware Retraction?")), - _(L("Firmware Retraction")), wxICON_WARNING | wxYES | wxNO); + if (use_firmware_retraction && wipe) { + auto dialog = new wxMessageDialog(parent(), + _(L("The Wipe option is not available when using the Firmware Retraction mode.\n" + "\nShall I disable it in order to enable Firmware Retraction?")), + _(L("Firmware Retraction")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - auto wipe = static_cast(m_config->option("wipe")->clone()); - for (int w = 0; w < wipe->values.size(); w++) - wipe->values[w] = false; - new_conf.set_key_value("wipe", wipe); - } - else { - new_conf.set_key_value("use_firmware_retraction", new ConfigOptionBool(false)); - } - load_config(new_conf); - } + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + auto wipe = static_cast(m_config->option("wipe")->clone()); + for (int w = 0; w < wipe->values.size(); w++) + wipe->values[w] = false; + new_conf.set_key_value("wipe", wipe); + } + else { + new_conf.set_key_value("use_firmware_retraction", new ConfigOptionBool(false)); + } + load_config(new_conf); + } - get_field("retract_length_toolchange", i)->toggle(have_multiple_extruders); + get_field("retract_length_toolchange", i)->toggle(have_multiple_extruders); - bool toolchange_retraction = m_config->opt_float("retract_length_toolchange", i) > 0; - get_field("retract_restart_extra_toolchange", i)->toggle - (have_multiple_extruders && toolchange_retraction); - } + bool toolchange_retraction = m_config->opt_float("retract_length_toolchange", i) > 0; + get_field("retract_restart_extra_toolchange", i)->toggle + (have_multiple_extruders && toolchange_retraction); + } // Thaw(); } @@ -2723,45 +2749,45 @@ void TabPrinter::update_sla() // Initialize the UI from the current preset void Tab::load_current_preset() { - const Preset& preset = m_presets->get_edited_preset(); + const Preset& preset = m_presets->get_edited_preset(); - (preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); + (preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); update(); - if (m_type == Slic3r::Preset::TYPE_PRINTER) { - // For the printer profile, generate the extruder pages. - if (preset.printer_technology() == ptFFF) - on_preset_loaded(); - else - wxGetApp().sidebar().update_objects_list_extruder_column(1); - } + if (m_type == Slic3r::Preset::TYPE_PRINTER) { + // For the printer profile, generate the extruder pages. + if (preset.printer_technology() == ptFFF) + on_preset_loaded(); + else + wxGetApp().sidebar().update_objects_list_extruder_column(1); + } // Reload preset pages with the new configuration values. reload_config(); const Preset* selected_preset_parent = m_presets->get_selected_preset_parent(); m_is_default_preset = selected_preset_parent != nullptr && selected_preset_parent->is_default; - m_bmp_non_system = selected_preset_parent ? &m_bmp_value_unlock : &m_bmp_white_bullet; - m_ttg_non_system = selected_preset_parent ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; - m_tt_non_system = selected_preset_parent ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; + m_bmp_non_system = selected_preset_parent ? &m_bmp_value_unlock : &m_bmp_white_bullet; + m_ttg_non_system = selected_preset_parent ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; + m_tt_non_system = selected_preset_parent ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; // m_undo_to_sys_btn->Enable(!preset.is_default); #if 0 - // use CallAfter because some field triggers schedule on_change calls using CallAfter, - // and we don't want them to be called after this update_dirty() as they would mark the - // preset dirty again - // (not sure this is true anymore now that update_dirty is idempotent) - wxTheApp->CallAfter([this] + // use CallAfter because some field triggers schedule on_change calls using CallAfter, + // and we don't want them to be called after this update_dirty() as they would mark the + // preset dirty again + // (not sure this is true anymore now that update_dirty is idempotent) + wxTheApp->CallAfter([this] #endif - { - // checking out if this Tab exists till this moment - if (!wxGetApp().checked_tab(this)) - return; - update_tab_ui(); + { + // checking out if this Tab exists till this moment + if (!wxGetApp().checked_tab(this)) + return; + update_tab_ui(); // update show/hide tabs - if (m_type == Slic3r::Preset::TYPE_PRINTER) { + if (m_type == Slic3r::Preset::TYPE_PRINTER) { const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); if (printer_technology != static_cast(this)->m_printer_technology) { @@ -2780,61 +2806,61 @@ void Tab::load_current_preset() int page_id = wxGetApp().tab_panel()->FindPage(tab); wxGetApp().tab_panel()->GetPage(page_id)->Show(false); wxGetApp().tab_panel()->RemovePage(page_id); - } + } } static_cast(this)->m_printer_technology = printer_technology; } - on_presets_changed(); - if (printer_technology == ptFFF) { - static_cast(this)->m_initial_extruders_count = static_cast(this)->m_extruders_count; - const Preset* parent_preset = m_presets->get_selected_preset_parent(); - static_cast(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 : - static_cast(parent_preset->config.option("nozzle_diameter"))->values.size(); - } - } - else { - on_presets_changed(); + on_presets_changed(); + if (printer_technology == ptFFF) { + static_cast(this)->m_initial_extruders_count = static_cast(this)->m_extruders_count; + const Preset* parent_preset = m_presets->get_selected_preset_parent(); + static_cast(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 : + static_cast(parent_preset->config.option("nozzle_diameter"))->values.size(); + } + } + else { + on_presets_changed(); if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT) - update_frequently_changed_parameters(); - } + update_frequently_changed_parameters(); + } - m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue; - init_options_list(); + m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue; + init_options_list(); update_visibility(); - update_changed_ui(); - } + update_changed_ui(); + } #if 0 - ); + ); #endif } //Regerenerate content of the page tree. void Tab::rebuild_page_tree() { - // get label of the currently selected item + // get label of the currently selected item const auto sel_item = m_treectrl->GetSelection(); - const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; - const auto rootItem = m_treectrl->GetRootItem(); + const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; + const auto rootItem = m_treectrl->GetRootItem(); - auto have_selection = 0; - m_treectrl->DeleteChildren(rootItem); - for (auto p : m_pages) - { - auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); - m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); - if (p->title() == selected) { - m_treectrl->SelectItem(itemId); - have_selection = 1; - } - } + auto have_selection = 0; + m_treectrl->DeleteChildren(rootItem); + for (auto p : m_pages) + { + auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); + m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); + if (p->title() == selected) { + m_treectrl->SelectItem(itemId); + have_selection = 1; + } + } - if (!have_selection) { - // this is triggered on first load, so we don't disable the sel change event - auto item = m_treectrl->GetFirstVisibleItem(); - if (item) { - m_treectrl->SelectItem(item); - } - } + if (!have_selection) { + // this is triggered on first load, so we don't disable the sel change event + auto item = m_treectrl->GetFirstVisibleItem(); + if (item) { + m_treectrl->SelectItem(item); + } + } } void Tab::update_page_tree_visibility() @@ -2872,38 +2898,38 @@ void Tab::update_page_tree_visibility() // If the current profile is modified, user is asked to save the changes. void Tab::select_preset(std::string preset_name, bool delete_current) { - if (preset_name.empty()) { - if (delete_current) { - // Find an alternate preset to be selected after the current preset is deleted. - const std::deque &presets = this->m_presets->get_presets(); - size_t idx_current = this->m_presets->get_idx_selected(); - // Find the next visible preset. - size_t idx_new = idx_current + 1; - if (idx_new < presets.size()) - for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ; - if (idx_new == presets.size()) - for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new); - preset_name = presets[idx_new].name; - } else { - // If no name is provided, select the "-- default --" preset. - preset_name = m_presets->default_preset().name; - } - } - assert(! delete_current || (m_presets->get_edited_preset().name != preset_name && m_presets->get_edited_preset().is_user())); - bool current_dirty = ! delete_current && m_presets->current_is_dirty(); - bool print_tab = m_presets->type() == Preset::TYPE_PRINT || m_presets->type() == Preset::TYPE_SLA_PRINT; - bool printer_tab = m_presets->type() == Preset::TYPE_PRINTER; - bool canceled = false; - m_dependent_tabs = {}; - if (current_dirty && ! may_discard_current_dirty_preset()) { - canceled = true; - } else if (print_tab) { - // Before switching the print profile to a new one, verify, whether the currently active filament or SLA material - // are compatible with the new print. - // If it is not compatible and the current filament or SLA material are dirty, let user decide - // whether to discard the changes or keep the current print selection. - PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); - PresetCollection &dependent = (printer_technology == ptFFF) ? m_preset_bundle->filaments : m_preset_bundle->sla_materials; + if (preset_name.empty()) { + if (delete_current) { + // Find an alternate preset to be selected after the current preset is deleted. + const std::deque &presets = this->m_presets->get_presets(); + size_t idx_current = this->m_presets->get_idx_selected(); + // Find the next visible preset. + size_t idx_new = idx_current + 1; + if (idx_new < presets.size()) + for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ; + if (idx_new == presets.size()) + for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new); + preset_name = presets[idx_new].name; + } else { + // If no name is provided, select the "-- default --" preset. + preset_name = m_presets->default_preset().name; + } + } + assert(! delete_current || (m_presets->get_edited_preset().name != preset_name && m_presets->get_edited_preset().is_user())); + bool current_dirty = ! delete_current && m_presets->current_is_dirty(); + bool print_tab = m_presets->type() == Preset::TYPE_PRINT || m_presets->type() == Preset::TYPE_SLA_PRINT; + bool printer_tab = m_presets->type() == Preset::TYPE_PRINTER; + bool canceled = false; + m_dependent_tabs = {}; + if (current_dirty && ! may_discard_current_dirty_preset()) { + canceled = true; + } else if (print_tab) { + // Before switching the print profile to a new one, verify, whether the currently active filament or SLA material + // are compatible with the new print. + // If it is not compatible and the current filament or SLA material are dirty, let user decide + // whether to discard the changes or keep the current print selection. + PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); + PresetCollection &dependent = (printer_technology == ptFFF) ? m_preset_bundle->filaments : m_preset_bundle->sla_materials; bool old_preset_dirty = dependent.current_is_dirty(); bool new_preset_compatible = dependent.get_edited_preset().is_compatible_with_print(*m_presets->find_preset(preset_name, true)); if (! canceled) @@ -2914,17 +2940,17 @@ void Tab::select_preset(std::string preset_name, bool delete_current) if (old_preset_dirty) dependent.discard_current_changes(); } - } else if (printer_tab) { - // Before switching the printer to a new one, verify, whether the currently active print and filament - // are compatible with the new printer. - // If they are not compatible and the current print or filament are dirty, let user decide - // whether to discard the changes or keep the current printer selection. - // - // With the introduction of the SLA printer types, we need to support switching between - // the FFF and SLA printers. - const Preset &new_printer_preset = *m_presets->find_preset(preset_name, true); - PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology(); - PrinterTechnology new_printer_technology = new_printer_preset.printer_technology(); + } else if (printer_tab) { + // Before switching the printer to a new one, verify, whether the currently active print and filament + // are compatible with the new printer. + // If they are not compatible and the current print or filament are dirty, let user decide + // whether to discard the changes or keep the current printer selection. + // + // With the introduction of the SLA printer types, we need to support switching between + // the FFF and SLA printers. + const Preset &new_printer_preset = *m_presets->find_preset(preset_name, true); + PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology(); + PrinterTechnology new_printer_technology = new_printer_preset.printer_technology(); if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !may_switch_to_SLA_preset()) canceled = true; else { @@ -2957,100 +2983,100 @@ void Tab::select_preset(std::string preset_name, bool delete_current) } } } - } + } - if (! canceled && delete_current) { - // Delete the file and select some other reasonable preset. - // It does not matter which preset will be made active as the preset will be re-selected from the preset_name variable. - // The 'external' presets will only be removed from the preset list, their files will not be deleted. - try { - m_presets->delete_current_preset(); - } catch (const std::exception & /* e */) { - //FIXME add some error reporting! - canceled = true; - } - } + if (! canceled && delete_current) { + // Delete the file and select some other reasonable preset. + // It does not matter which preset will be made active as the preset will be re-selected from the preset_name variable. + // The 'external' presets will only be removed from the preset list, their files will not be deleted. + try { + m_presets->delete_current_preset(); + } catch (const std::exception & /* e */) { + //FIXME add some error reporting! + canceled = true; + } + } - if (canceled) { - update_tab_ui(); - // Trigger the on_presets_changed event so that we also restore the previous value in the plater selector, - // if this action was initiated from the platter. - on_presets_changed(); - } else { - if (current_dirty) - m_presets->discard_current_changes(); + if (canceled) { + update_tab_ui(); + // Trigger the on_presets_changed event so that we also restore the previous value in the plater selector, + // if this action was initiated from the platter. + on_presets_changed(); + } else { + if (current_dirty) + m_presets->discard_current_changes(); - const bool is_selected = m_presets->select_preset_by_name(preset_name, false) || delete_current; - assert(m_presets->get_edited_preset().name == preset_name || ! is_selected); - // Mark the print & filament enabled if they are compatible with the currently selected preset. - // The following method should not discard changes of current print or filament presets on change of a printer profile, - // if they are compatible with the current printer. - if (current_dirty || delete_current || print_tab || printer_tab) - m_preset_bundle->update_compatible(true); - // Initialize the UI from the current preset. + const bool is_selected = m_presets->select_preset_by_name(preset_name, false) || delete_current; + assert(m_presets->get_edited_preset().name == preset_name || ! is_selected); + // Mark the print & filament enabled if they are compatible with the currently selected preset. + // The following method should not discard changes of current print or filament presets on change of a printer profile, + // if they are compatible with the current printer. + if (current_dirty || delete_current || print_tab || printer_tab) + m_preset_bundle->update_compatible(true); + // Initialize the UI from the current preset. if (printer_tab) static_cast(this)->update_pages(); if (! is_selected && printer_tab) { /* There is a case, when : - * after Config Wizard applying we try to select previously selected preset, but + * after Config Wizard applying we try to select previously selected preset, but * in a current configuration this one: * 1. doesn't exist now, * 2. have another printer_technology - * So, it is necessary to update list of dependent tabs + * So, it is necessary to update list of dependent tabs * to the corresponding printer_technology */ const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT) - m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT }; + m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT }; else if (printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT) m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL }; } - load_current_preset(); - } + load_current_preset(); + } } // If the current preset is dirty, the user is asked whether the changes may be discarded. // if the current preset was not dirty, or the user agreed to discard the changes, 1 is returned. bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr*/, const std::string& new_printer_name /*= ""*/) { - if (presets == nullptr) presets = m_presets; - // Display a dialog showing the dirty options in a human readable form. - const Preset& old_preset = presets->get_edited_preset(); - std::string type_name = presets->name(); - wxString tab = " "; - wxString name = old_preset.is_default ? - wxString::Format(_(L("Default preset (%s)")), _(type_name)) : - wxString::Format(_(L("Preset (%s)")), _(type_name)) + "\n" + tab + old_preset.name; + if (presets == nullptr) presets = m_presets; + // Display a dialog showing the dirty options in a human readable form. + const Preset& old_preset = presets->get_edited_preset(); + std::string type_name = presets->name(); + wxString tab = " "; + wxString name = old_preset.is_default ? + wxString::Format(_(L("Default preset (%s)")), _(type_name)) : + wxString::Format(_(L("Preset (%s)")), _(type_name)) + "\n" + tab + old_preset.name; - // Collect descriptions of the dirty options. - wxString changes; - for (const std::string &opt_key : presets->current_dirty_options()) { - const ConfigOptionDef &opt = m_config->def()->options.at(opt_key); - /*std::string*/wxString name = ""; - if (! opt.category.empty()) - name += _(opt.category) + " > "; - name += !opt.full_label.empty() ? - _(opt.full_label) : - _(opt.label); - changes += tab + /*from_u8*/(name) + "\n"; - } - // Show a confirmation dialog with the list of dirty options. - wxString message = name + "\n\n"; - if (new_printer_name.empty()) - message += _(L("has the following unsaved changes:")); - else { - message += (m_type == Slic3r::Preset::TYPE_PRINTER) ? - _(L("is not compatible with printer")) : - _(L("is not compatible with print profile")); - message += wxString("\n") + tab + from_u8(new_printer_name) + "\n\n"; - message += _(L("and it has the following unsaved changes:")); - } - auto confirm = new wxMessageDialog(parent(), - message + "\n" + changes + "\n\n" + _(L("Discard changes and continue anyway?")), - _(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); - return confirm->ShowModal() == wxID_YES; + // Collect descriptions of the dirty options. + wxString changes; + for (const std::string &opt_key : presets->current_dirty_options()) { + const ConfigOptionDef &opt = m_config->def()->options.at(opt_key); + /*std::string*/wxString name = ""; + if (! opt.category.empty()) + name += _(opt.category) + " > "; + name += !opt.full_label.empty() ? + _(opt.full_label) : + _(opt.label); + changes += tab + /*from_u8*/(name) + "\n"; + } + // Show a confirmation dialog with the list of dirty options. + wxString message = name + "\n\n"; + if (new_printer_name.empty()) + message += _(L("has the following unsaved changes:")); + else { + message += (m_type == Slic3r::Preset::TYPE_PRINTER) ? + _(L("is not compatible with printer")) : + _(L("is not compatible with print profile")); + message += wxString("\n") + tab + from_u8(new_printer_name) + "\n\n"; + message += _(L("and it has the following unsaved changes:")); + } + auto confirm = new wxMessageDialog(parent(), + message + "\n" + changes + "\n\n" + _(L("Discard changes and continue anyway?")), + _(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); + return confirm->ShowModal() == wxID_YES; } // If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s). @@ -3059,7 +3085,7 @@ bool Tab::may_switch_to_SLA_preset() { if (model_has_multi_part_objects(wxGetApp().model())) { - show_info( parent(), + show_info( parent(), _(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" + _(L("Please check your object list before preset changing.")), _(L("Attention!")) ); @@ -3070,14 +3096,14 @@ bool Tab::may_switch_to_SLA_preset() void Tab::OnTreeSelChange(wxTreeEvent& event) { - if (m_disable_tree_sel_changed_event) + if (m_disable_tree_sel_changed_event) return; // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, // we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. -#ifdef __linux__ - std::unique_ptr no_updates(new wxWindowUpdateLocker(this)); +#ifdef __linux__ + std::unique_ptr no_updates(new wxWindowUpdateLocker(this)); #else // wxWindowUpdateLocker noUpdates(this); #endif @@ -3085,44 +3111,44 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) if (m_pages.empty()) return; - Page* page = nullptr; + Page* page = nullptr; const auto sel_item = m_treectrl->GetSelection(); const auto selection = sel_item ? m_treectrl->GetItemText(sel_item) : ""; for (auto p : m_pages) - if (p->title() == selection) - { - page = p.get(); - m_is_nonsys_values = page->m_is_nonsys_values; - m_is_modified_values = page->m_is_modified_values; - break; - } - if (page == nullptr) return; + if (p->title() == selection) + { + page = p.get(); + m_is_nonsys_values = page->m_is_nonsys_values; + m_is_modified_values = page->m_is_modified_values; + break; + } + if (page == nullptr) return; - for (auto& el : m_pages) + for (auto& el : m_pages) // if (el.get()->IsShown()) { - el.get()->Hide(); + el.get()->Hide(); // break; // } - #ifdef __linux__ - no_updates.reset(nullptr); - #endif + #ifdef __linux__ + no_updates.reset(nullptr); + #endif - update_undo_buttons(); - page->Show(); + update_undo_buttons(); + page->Show(); // if (! page->layout_valid) { - page->layout_valid = true; - m_hsizer->Layout(); - Refresh(); + page->layout_valid = true; + m_hsizer->Layout(); + Refresh(); // } } void Tab::OnKeyDown(wxKeyEvent& event) { - if (event.GetKeyCode() == WXK_TAB) - m_treectrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); - else - event.Skip(); + if (event.GetKeyCode() == WXK_TAB) + m_treectrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); + else + event.Skip(); } // Save the current preset into file. @@ -3132,263 +3158,263 @@ void Tab::OnKeyDown(wxKeyEvent& event) // opens a Slic3r::GUI::SavePresetWindow dialog. void Tab::save_preset(std::string name /*= ""*/) { - // since buttons(and choices too) don't get focus on Mac, we set focus manually - // to the treectrl so that the EVT_* events are fired for the input field having - // focus currently.is there anything better than this ? + // since buttons(and choices too) don't get focus on Mac, we set focus manually + // to the treectrl so that the EVT_* events are fired for the input field having + // focus currently.is there anything better than this ? //! m_treectrl->OnSetFocus(); - if (name.empty()) { - const Preset &preset = m_presets->get_selected_preset(); + if (name.empty()) { + const Preset &preset = m_presets->get_selected_preset(); auto default_name = preset.is_default ? "Untitled" : - preset.is_system ? (boost::format(_utf8(L("%1% - Copy"))) % preset.name).str() : - preset.name; + preset.is_system ? (boost::format(_utf8(L("%1% - Copy"))) % preset.name).str() : + preset.name; - bool have_extention = boost::iends_with(default_name, ".ini"); - if (have_extention) { - size_t len = default_name.length()-4; - default_name.resize(len); - } - //[map $_->name, grep !$_->default && !$_->external, @{$self->{presets}}], - std::vector values; - for (size_t i = 0; i < m_presets->size(); ++i) { - const Preset &preset = m_presets->preset(i); - if (preset.is_default || preset.is_system || preset.is_external) - continue; - values.push_back(preset.name); - } + bool have_extention = boost::iends_with(default_name, ".ini"); + if (have_extention) { + size_t len = default_name.length()-4; + default_name.resize(len); + } + //[map $_->name, grep !$_->default && !$_->external, @{$self->{presets}}], + std::vector values; + for (size_t i = 0; i < m_presets->size(); ++i) { + const Preset &preset = m_presets->preset(i); + if (preset.is_default || preset.is_system || preset.is_external) + continue; + values.push_back(preset.name); + } - auto dlg = new SavePresetWindow(parent()); - dlg->build(title(), default_name, values); - if (dlg->ShowModal() != wxID_OK) - return; - name = dlg->get_name(); - if (name == "") { - show_error(this, _(L("The supplied name is empty. It can't be saved."))); - return; - } - const Preset *existing = m_presets->find_preset(name, false); - if (existing && (existing->is_default || existing->is_system)) { - show_error(this, _(L("Cannot overwrite a system profile."))); - return; - } - if (existing && (existing->is_external)) { - show_error(this, _(L("Cannot overwrite an external profile."))); - return; - } - } + auto dlg = new SavePresetWindow(parent()); + dlg->build(title(), default_name, values); + if (dlg->ShowModal() != wxID_OK) + return; + name = dlg->get_name(); + if (name == "") { + show_error(this, _(L("The supplied name is empty. It can't be saved."))); + return; + } + const Preset *existing = m_presets->find_preset(name, false); + if (existing && (existing->is_default || existing->is_system)) { + show_error(this, _(L("Cannot overwrite a system profile."))); + return; + } + if (existing && (existing->is_external)) { + show_error(this, _(L("Cannot overwrite an external profile."))); + return; + } + } - // Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini - m_presets->save_current_preset(name); - // Mark the print & filament enabled if they are compatible with the currently selected preset. - m_preset_bundle->update_compatible(false); - // Add the new item into the UI component, remove dirty flags and activate the saved item. - update_tab_ui(); - // Update the selection boxes at the platter. - on_presets_changed(); - // If current profile is saved, "delete preset" button have to be enabled - m_btn_delete_preset->Enable(true); + // Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini + m_presets->save_current_preset(name); + // Mark the print & filament enabled if they are compatible with the currently selected preset. + m_preset_bundle->update_compatible(false); + // Add the new item into the UI component, remove dirty flags and activate the saved item. + update_tab_ui(); + // Update the selection boxes at the platter. + on_presets_changed(); + // If current profile is saved, "delete preset" button have to be enabled + m_btn_delete_preset->Enable(true); - if (m_type == Preset::TYPE_PRINTER) - static_cast(this)->m_initial_extruders_count = static_cast(this)->m_extruders_count; - update_changed_ui(); + if (m_type == Preset::TYPE_PRINTER) + static_cast(this)->m_initial_extruders_count = static_cast(this)->m_extruders_count; + update_changed_ui(); } // Called for a currently selected preset. void Tab::delete_preset() { - auto current_preset = m_presets->get_selected_preset(); - // Don't let the user delete the ' - default - ' configuration. + auto current_preset = m_presets->get_selected_preset(); + // Don't let the user delete the ' - default - ' configuration. std::string action = current_preset.is_external ? _utf8(L("remove")) : _utf8(L("delete")); // TRN remove/delete const wxString msg = from_u8((boost::format(_utf8(L("Are you sure you want to %1% the selected preset?"))) % action).str()); - action = current_preset.is_external ? _utf8(L("Remove")) : _utf8(L("Delete")); - // TRN Remove/Delete + action = current_preset.is_external ? _utf8(L("Remove")) : _utf8(L("Delete")); + // TRN Remove/Delete wxString title = from_u8((boost::format(_utf8(L("%1% Preset"))) % action).str()); //action + _(L(" Preset")); - if (current_preset.is_default || - wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) - return; - // Select will handle of the preset dependencies, of saving & closing the depending profiles, and - // finally of deleting the preset. - this->select_preset("", true); + if (current_preset.is_default || + wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) + return; + // Select will handle of the preset dependencies, of saving & closing the depending profiles, and + // finally of deleting the preset. + this->select_preset("", true); } void Tab::toggle_show_hide_incompatible() { - m_show_incompatible_presets = !m_show_incompatible_presets; - update_show_hide_incompatible_button(); - update_tab_ui(); + m_show_incompatible_presets = !m_show_incompatible_presets; + update_show_hide_incompatible_button(); + update_tab_ui(); } void Tab::update_show_hide_incompatible_button() { - m_btn_hide_incompatible_presets->SetBitmap_(m_show_incompatible_presets ? - m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets); - m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ? - "Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." : - "Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer."); + m_btn_hide_incompatible_presets->SetBitmap_(m_show_incompatible_presets ? + m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets); + m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ? + "Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." : + "Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer."); } void Tab::update_ui_from_settings() { - // Show the 'show / hide presets' button only for the print and filament tabs, and only if enabled - // in application preferences. - m_show_btn_incompatible_presets = wxGetApp().app_config->get("show_incompatible_presets")[0] == '1' ? true : false; - bool show = m_show_btn_incompatible_presets && m_type != Slic3r::Preset::TYPE_PRINTER; - Layout(); - show ? m_btn_hide_incompatible_presets->Show() : m_btn_hide_incompatible_presets->Hide(); - // If the 'show / hide presets' button is hidden, hide the incompatible presets. - if (show) { - update_show_hide_incompatible_button(); - } - else { - if (m_show_incompatible_presets) { - m_show_incompatible_presets = false; - update_tab_ui(); - } - } + // Show the 'show / hide presets' button only for the print and filament tabs, and only if enabled + // in application preferences. + m_show_btn_incompatible_presets = wxGetApp().app_config->get("show_incompatible_presets")[0] == '1' ? true : false; + bool show = m_show_btn_incompatible_presets && m_type != Slic3r::Preset::TYPE_PRINTER; + Layout(); + show ? m_btn_hide_incompatible_presets->Show() : m_btn_hide_incompatible_presets->Hide(); + // If the 'show / hide presets' button is hidden, hide the incompatible presets. + if (show) { + update_show_hide_incompatible_button(); + } + else { + if (m_show_incompatible_presets) { + m_show_incompatible_presets = false; + update_tab_ui(); + } + } } // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &deps) { - deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); - deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); + deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); add_scaled_button(parent, &deps.btn, "printer_white", wxString::Format(" %s %s", _(L("Set")), dots), wxBU_LEFT | wxBU_EXACTFIT); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); - sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); + sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL); - deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps](wxCommandEvent e) - { - deps.btn->Enable(! deps.checkbox->GetValue()); - // All printers have been made compatible with this preset. - if (deps.checkbox->GetValue()) - this->load_key_value(deps.key_list, std::vector {}); - this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); - this->update_changed_ui(); - }) ); + deps.checkbox->Bind(wxEVT_CHECKBOX, ([this, &deps](wxCommandEvent e) + { + deps.btn->Enable(! deps.checkbox->GetValue()); + // All printers have been made compatible with this preset. + if (deps.checkbox->GetValue()) + this->load_key_value(deps.key_list, std::vector {}); + this->get_field(deps.key_condition)->toggle(deps.checkbox->GetValue()); + this->update_changed_ui(); + }) ); - deps.btn->Bind(wxEVT_BUTTON, ([this, parent, &deps](wxCommandEvent e) - { - // Collect names of non-default non-external profiles. - PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); - PresetCollection &depending_presets = (deps.type == Preset::TYPE_PRINTER) ? m_preset_bundle->printers : - (printer_technology == ptFFF) ? m_preset_bundle->prints : m_preset_bundle->sla_prints; - wxArrayString presets; - for (size_t idx = 0; idx < depending_presets.size(); ++ idx) - { - Preset& preset = depending_presets.preset(idx); - bool add = ! preset.is_default && ! preset.is_external; - if (add && deps.type == Preset::TYPE_PRINTER) - // Only add printers with the same technology as the active printer. - add &= preset.printer_technology() == printer_technology; - if (add) - presets.Add(from_u8(preset.name)); - } + deps.btn->Bind(wxEVT_BUTTON, ([this, parent, &deps](wxCommandEvent e) + { + // Collect names of non-default non-external profiles. + PrinterTechnology printer_technology = m_preset_bundle->printers.get_edited_preset().printer_technology(); + PresetCollection &depending_presets = (deps.type == Preset::TYPE_PRINTER) ? m_preset_bundle->printers : + (printer_technology == ptFFF) ? m_preset_bundle->prints : m_preset_bundle->sla_prints; + wxArrayString presets; + for (size_t idx = 0; idx < depending_presets.size(); ++ idx) + { + Preset& preset = depending_presets.preset(idx); + bool add = ! preset.is_default && ! preset.is_external; + if (add && deps.type == Preset::TYPE_PRINTER) + // Only add printers with the same technology as the active printer. + add &= preset.printer_technology() == printer_technology; + if (add) + presets.Add(from_u8(preset.name)); + } - wxMultiChoiceDialog dlg(parent, deps.dialog_title, deps.dialog_label, presets); - // Collect and set indices of depending_presets marked as compatible. - wxArrayInt selections; - auto *compatible_printers = dynamic_cast(m_config->option(deps.key_list)); - if (compatible_printers != nullptr || !compatible_printers->values.empty()) - for (auto preset_name : compatible_printers->values) - for (size_t idx = 0; idx < presets.GetCount(); ++idx) - if (presets[idx] == preset_name) { - selections.Add(idx); - break; - } - dlg.SetSelections(selections); - std::vector value; - // Show the dialog. - if (dlg.ShowModal() == wxID_OK) { - selections.Clear(); - selections = dlg.GetSelections(); - for (auto idx : selections) - value.push_back(presets[idx].ToUTF8().data()); - if (value.empty()) { - deps.checkbox->SetValue(1); - deps.btn->Disable(); - } - // All depending_presets have been made compatible with this preset. - this->load_key_value(deps.key_list, value); - this->update_changed_ui(); - } - })); - return sizer; + wxMultiChoiceDialog dlg(parent, deps.dialog_title, deps.dialog_label, presets); + // Collect and set indices of depending_presets marked as compatible. + wxArrayInt selections; + auto *compatible_printers = dynamic_cast(m_config->option(deps.key_list)); + if (compatible_printers != nullptr || !compatible_printers->values.empty()) + for (auto preset_name : compatible_printers->values) + for (size_t idx = 0; idx < presets.GetCount(); ++idx) + if (presets[idx] == preset_name) { + selections.Add(idx); + break; + } + dlg.SetSelections(selections); + std::vector value; + // Show the dialog. + if (dlg.ShowModal() == wxID_OK) { + selections.Clear(); + selections = dlg.GetSelections(); + for (auto idx : selections) + value.push_back(presets[idx].ToUTF8().data()); + if (value.empty()) { + deps.checkbox->SetValue(1); + deps.btn->Disable(); + } + // All depending_presets have been made compatible with this preset. + this->load_key_value(deps.key_list, value); + this->update_changed_ui(); + } + })); + return sizer; } void Tab::compatible_widget_reload(PresetDependencies &deps) { - bool has_any = ! m_config->option(deps.key_list)->values.empty(); - has_any ? deps.btn->Enable() : deps.btn->Disable(); - deps.checkbox->SetValue(! has_any); - this->get_field(deps.key_condition)->toggle(! has_any); + bool has_any = ! m_config->option(deps.key_list)->values.empty(); + has_any ? deps.btn->Enable() : deps.btn->Disable(); + deps.checkbox->SetValue(! has_any); + this->get_field(deps.key_condition)->toggle(! has_any); } void Tab::fill_icon_descriptions() { - m_icon_descriptions.emplace_back(&m_bmp_value_lock, L("LOCKED LOCK"), + m_icon_descriptions.emplace_back(&m_bmp_value_lock, L("LOCKED LOCK"), // TRN Description for "LOCKED LOCK" - L("indicates that the settings are the same as the system (or default) values for the current option group")); + L("indicates that the settings are the same as the system (or default) values for the current option group")); m_icon_descriptions.emplace_back(&m_bmp_value_unlock, L("UNLOCKED LOCK"), // TRN Description for "UNLOCKED LOCK" - L("indicates that some settings were changed and are not equal to the system (or default) values for " - "the current option group.\n" - "Click the UNLOCKED LOCK icon to reset all settings for current option group to " - "the system (or default) values.")); + L("indicates that some settings were changed and are not equal to the system (or default) values for " + "the current option group.\n" + "Click the UNLOCKED LOCK icon to reset all settings for current option group to " + "the system (or default) values.")); m_icon_descriptions.emplace_back(&m_bmp_white_bullet, L("WHITE BULLET"), // TRN Description for "WHITE BULLET" L("for the left button: \tindicates a non-system (or non-default) preset,\n" - "for the right button: \tindicates that the settings hasn't been modified.")); + "for the right button: \tindicates that the settings hasn't been modified.")); m_icon_descriptions.emplace_back(&m_bmp_value_revert, L("BACK ARROW"), // TRN Description for "BACK ARROW" L("indicates that the settings were changed and are not equal to the last saved preset for " - "the current option group.\n" - "Click the BACK ARROW icon to reset all settings for the current option group to " - "the last saved preset.")); + "the current option group.\n" + "Click the BACK ARROW icon to reset all settings for the current option group to " + "the last saved preset.")); } void Tab::set_tooltips_text() { - // --- Tooltip text for reset buttons (for whole options group) - // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system (or default) values " - "for the current option group")); - m_ttg_value_unlock = _(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal " - "to the system (or default) values for the current option group.\n" - "Click to reset all settings for current option group to the system (or default) values.")); - m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system (or non default) preset.")); - m_ttg_non_system = &m_ttg_white_bullet_ns; - // Text to be shown on the "Undo user changes" button next to each input field. - m_ttg_white_bullet = _(L("WHITE BULLET icon indicates that the settings are the same as in the last saved " - "preset for the current option group.")); - m_ttg_value_revert = _(L("BACK ARROW icon indicates that the settings were changed and are not equal to " - "the last saved preset for the current option group.\n" - "Click to reset all settings for the current option group to the last saved preset.")); + // --- Tooltip text for reset buttons (for whole options group) + // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system (or default) values " + "for the current option group")); + m_ttg_value_unlock = _(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal " + "to the system (or default) values for the current option group.\n" + "Click to reset all settings for current option group to the system (or default) values.")); + m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system (or non default) preset.")); + m_ttg_non_system = &m_ttg_white_bullet_ns; + // Text to be shown on the "Undo user changes" button next to each input field. + m_ttg_white_bullet = _(L("WHITE BULLET icon indicates that the settings are the same as in the last saved " + "preset for the current option group.")); + m_ttg_value_revert = _(L("BACK ARROW icon indicates that the settings were changed and are not equal to " + "the last saved preset for the current option group.\n" + "Click to reset all settings for the current option group to the last saved preset.")); - // --- Tooltip text for reset buttons (for each option in group) - // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system (or default) value.")); - m_tt_value_unlock = _(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal " - "to the system (or default) value.\n" - "Click to reset current value to the system (or default) value.")); - // m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset.")); - m_tt_non_system = &m_ttg_white_bullet_ns; - // Text to be shown on the "Undo user changes" button next to each input field. - m_tt_white_bullet = _(L("WHITE BULLET icon indicates that the value is the same as in the last saved preset.")); - m_tt_value_revert = _(L("BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset.\n" - "Click to reset current value to the last saved preset.")); + // --- Tooltip text for reset buttons (for each option in group) + // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system (or default) value.")); + m_tt_value_unlock = _(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal " + "to the system (or default) value.\n" + "Click to reset current value to the system (or default) value.")); + // m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset.")); + m_tt_non_system = &m_ttg_white_bullet_ns; + // Text to be shown on the "Undo user changes" button next to each input field. + m_tt_white_bullet = _(L("WHITE BULLET icon indicates that the value is the same as in the last saved preset.")); + m_tt_value_revert = _(L("BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset.\n" + "Click to reset current value to the last saved preset.")); } void Page::reload_config() { - for (auto group : m_optgroups) - group->reload_config(); + for (auto group : m_optgroups) + group->reload_config(); } void Page::update_visibility(ConfigOptionMode mode) @@ -3408,22 +3434,22 @@ void Page::msw_rescale() Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const { - Field* field = nullptr; - for (auto opt : m_optgroups) { - field = opt->get_fieldc(opt_key, opt_index); - if (field != nullptr) - return field; - } - return field; + Field* field = nullptr; + for (auto opt : m_optgroups) { + field = opt->get_fieldc(opt_key, opt_index); + if (field != nullptr) + return field; + } + return field; } bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value) { - bool changed = false; - for(auto optgroup: m_optgroups) { - if (optgroup->set_value(opt_key, value)) - changed = 1 ; - } - return changed; + bool changed = false; + for(auto optgroup: m_optgroups) { + if (optgroup->set_value(opt_key, value)) + changed = 1 ; + } + return changed; } // package Slic3r::GUI::Tab::Page; @@ -3443,39 +3469,39 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la return bmp; }; - //! config_ have to be "right" - ConfigOptionsGroupShp optgroup = std::make_shared(this, title, m_config, true, extra_column); - if (noncommon_label_width >= 0) - optgroup->label_width = noncommon_label_width; + //! config_ have to be "right" + ConfigOptionsGroupShp optgroup = std::make_shared(this, title, m_config, true, extra_column); + if (noncommon_label_width >= 0) + optgroup->label_width = noncommon_label_width; #ifdef __WXOSX__ - auto tab = GetParent()->GetParent(); + auto tab = GetParent()->GetParent(); #else - auto tab = GetParent(); + auto tab = GetParent(); #endif - optgroup->m_on_change = [this, tab](t_config_option_key opt_key, boost::any value) { - //! This function will be called from OptionGroup. - //! Using of CallAfter is redundant. - //! And in some cases it causes update() function to be recalled again + optgroup->m_on_change = [this, tab](t_config_option_key opt_key, boost::any value) { + //! This function will be called from OptionGroup. + //! Using of CallAfter is redundant. + //! And in some cases it causes update() function to be recalled again //! wxTheApp->CallAfter([this, opt_key, value]() { - static_cast(tab)->update_dirty(); - static_cast(tab)->on_value_change(opt_key, value); + static_cast(tab)->update_dirty(); + static_cast(tab)->on_value_change(opt_key, value); //! }); - }; + }; - optgroup->m_get_initial_config = [this, tab]() { - DynamicPrintConfig config = static_cast(tab)->m_presets->get_selected_preset().config; - return config; - }; + optgroup->m_get_initial_config = [this, tab]() { + DynamicPrintConfig config = static_cast(tab)->m_presets->get_selected_preset().config; + return config; + }; - optgroup->m_get_sys_config = [this, tab]() { - DynamicPrintConfig config = static_cast(tab)->m_presets->get_selected_preset_parent()->config; - return config; - }; + optgroup->m_get_sys_config = [this, tab]() { + DynamicPrintConfig config = static_cast(tab)->m_presets->get_selected_preset_parent()->config; + return config; + }; - optgroup->have_sys_config = [this, tab]() { - return static_cast(tab)->m_presets->get_selected_preset_parent() != nullptr; - }; + optgroup->have_sys_config = [this, tab]() { + return static_cast(tab)->m_presets->get_selected_preset_parent() != nullptr; + }; optgroup->rescale_extra_column_item = [this](wxWindow* win) { auto *ctrl = dynamic_cast(win); @@ -3485,69 +3511,69 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la ctrl->SetBitmap(reinterpret_cast(ctrl->GetClientData())->bmp()); }; - vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); - m_optgroups.push_back(optgroup); + vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); + m_optgroups.push_back(optgroup); - return optgroup; + return optgroup; } void SavePresetWindow::build(const wxString& title, const std::string& default_name, std::vector &values) { // TRN Preset - auto text = new wxStaticText(this, wxID_ANY, wxString::Format(_(L("Save %s as:")), title), - wxDefaultPosition, wxDefaultSize); - m_combo = new wxComboBox(this, wxID_ANY, from_u8(default_name), - wxDefaultPosition, wxDefaultSize, 0, 0, wxTE_PROCESS_ENTER); - for (auto value : values) - m_combo->Append(from_u8(value)); - auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); + auto text = new wxStaticText(this, wxID_ANY, wxString::Format(_(L("Save %s as:")), title), + wxDefaultPosition, wxDefaultSize); + m_combo = new wxComboBox(this, wxID_ANY, from_u8(default_name), + wxDefaultPosition, wxDefaultSize, 0, 0, wxTE_PROCESS_ENTER); + for (auto value : values) + m_combo->Append(from_u8(value)); + auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); - auto sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(text, 0, wxEXPAND | wxALL, 10); - sizer->Add(m_combo, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); - sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 10); + auto sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(text, 0, wxEXPAND | wxALL, 10); + sizer->Add(m_combo, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); + sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 10); - wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); }); - m_combo->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent&) { accept(); }); + wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); + btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); }); + m_combo->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent&) { accept(); }); - SetSizer(sizer); - sizer->SetSizeHints(this); + SetSizer(sizer); + sizer->SetSizeHints(this); } void SavePresetWindow::accept() { - m_chosen_name = normalize_utf8_nfc(m_combo->GetValue().ToUTF8()); - if (!m_chosen_name.empty()) { - const char* unusable_symbols = "<>[]:/\\|?*\""; - bool is_unusable_symbol = false; - bool is_unusable_suffix = false; - const std::string unusable_suffix = PresetCollection::get_suffix_modified();//"(modified)"; - for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { - if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { - is_unusable_symbol = true; - break; - } - } - if (m_chosen_name.find(unusable_suffix) != std::string::npos) - is_unusable_suffix = true; + m_chosen_name = normalize_utf8_nfc(m_combo->GetValue().ToUTF8()); + if (!m_chosen_name.empty()) { + const char* unusable_symbols = "<>[]:/\\|?*\""; + bool is_unusable_symbol = false; + bool is_unusable_suffix = false; + const std::string unusable_suffix = PresetCollection::get_suffix_modified();//"(modified)"; + for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { + if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { + is_unusable_symbol = true; + break; + } + } + if (m_chosen_name.find(unusable_suffix) != std::string::npos) + is_unusable_suffix = true; - if (is_unusable_symbol) { - show_error(this,_(L("The supplied name is not valid;")) + "\n" + - _(L("the following characters are not allowed:")) + " " + unusable_symbols); - } - else if (is_unusable_suffix) { - show_error(this,_(L("The supplied name is not valid;")) + "\n" + - _(L("the following suffix is not allowed:")) + "\n\t" + - wxString::FromUTF8(unusable_suffix.c_str())); - } - else if (m_chosen_name == "- default -") { - show_error(this, _(L("The supplied name is not available."))); - } - else { - EndModal(wxID_OK); - } - } + if (is_unusable_symbol) { + show_error(this,_(L("The supplied name is not valid;")) + "\n" + + _(L("the following characters are not allowed:")) + " " + unusable_symbols); + } + else if (is_unusable_suffix) { + show_error(this,_(L("The supplied name is not valid;")) + "\n" + + _(L("the following suffix is not allowed:")) + "\n\t" + + wxString::FromUTF8(unusable_suffix.c_str())); + } + else if (m_chosen_name == "- default -") { + show_error(this, _(L("The supplied name is not available."))); + } + else { + EndModal(wxID_OK); + } + } } void TabSLAMaterial::build() @@ -3604,12 +3630,12 @@ void TabSLAMaterial::build() line = optgroup->create_single_option_line("compatible_prints"); line.widget = [this](wxWindow* parent) { - return compatible_widget_create(parent, m_compatible_prints); - }; - optgroup->append_line(line, &m_colored_Label); - option = optgroup->get_option("compatible_prints_condition"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + return compatible_widget_create(parent, m_compatible_prints); + }; + optgroup->append_line(line, &m_colored_Label); + option = optgroup->get_option("compatible_prints_condition"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); line = Line{ "", "" }; line.full_width = 1; @@ -3622,21 +3648,21 @@ void TabSLAMaterial::build() // Reload current config (aka presets->edited_preset->config) into the UI fields. void TabSLAMaterial::reload_config() { - this->compatible_widget_reload(m_compatible_printers); - this->compatible_widget_reload(m_compatible_prints); - Tab::reload_config(); + this->compatible_widget_reload(m_compatible_printers); + this->compatible_widget_reload(m_compatible_prints); + Tab::reload_config(); } void TabSLAMaterial::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) return; - + // #ys_FIXME. Just a template for this function // m_update_cnt++; // ! something to update // m_update_cnt--; -// +// // if (m_update_cnt == 0) wxGetApp().mainframe->on_config_changed(m_config); } @@ -3690,21 +3716,22 @@ void TabSLAPrint::build() // TODO: Disabling this parameter for the beta release // optgroup->append_single_option_line("pad_edge_radius"); optgroup->append_single_option_line("pad_wall_slope"); - + + optgroup->append_single_option_line("pad_zero_elevation"); optgroup->append_single_option_line("pad_object_gap"); optgroup->append_single_option_line("pad_object_connector_stride"); optgroup->append_single_option_line("pad_object_connector_width"); optgroup->append_single_option_line("pad_object_connector_penetration"); - - page = add_options_page(_(L("Advanced")), "wrench"); - optgroup = page->new_optgroup(_(L("Slicing"))); - optgroup->append_single_option_line("slice_closing_radius"); - page = add_options_page(_(L("Output options")), "output+page_white"); - optgroup = page->new_optgroup(_(L("Output file"))); - Option option = optgroup->get_option("output_filename_format"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); + page = add_options_page(_(L("Advanced")), "wrench"); + optgroup = page->new_optgroup(_(L("Slicing"))); + optgroup->append_single_option_line("slice_closing_radius"); + + page = add_options_page(_(L("Output options")), "output+page_white"); + optgroup = page->new_optgroup(_(L("Output file"))); + Option option = optgroup->get_option("output_filename_format"); + option.opt.full_width = true; + optgroup->append_single_option_line(option); page = add_options_page(_(L("Dependencies")), "wrench"); optgroup = page->new_optgroup(_(L("Profile dependencies"))); @@ -3729,8 +3756,8 @@ void TabSLAPrint::build() // Reload current config (aka presets->edited_preset->config) into the UI fields. void TabSLAPrint::reload_config() { - this->compatible_widget_reload(m_compatible_printers); - Tab::reload_config(); + this->compatible_widget_reload(m_compatible_printers); + Tab::reload_config(); } void TabSLAPrint::update() @@ -3738,7 +3765,33 @@ void TabSLAPrint::update() if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) return; - m_update_cnt++; + m_update_cnt++; + + bool supports_en = m_config->opt_bool("supports_enable"); + + get_field("support_head_front_diameter")->toggle(supports_en); + get_field("support_head_penetration")->toggle(supports_en); + get_field("support_head_width")->toggle(supports_en); + get_field("support_pillar_diameter")->toggle(supports_en); + get_field("support_pillar_connection_mode")->toggle(supports_en); + get_field("support_buildplate_only")->toggle(supports_en); + get_field("support_base_diameter")->toggle(supports_en); + get_field("support_base_height")->toggle(supports_en); + get_field("support_base_safety_distance")->toggle(supports_en); + get_field("support_critical_angle")->toggle(supports_en); + get_field("support_max_bridge_length")->toggle(supports_en); + get_field("support_max_pillar_link_distance")->toggle(supports_en); + get_field("support_points_density_relative")->toggle(supports_en); + get_field("support_points_minimal_distance")->toggle(supports_en); + + bool pad_en = m_config->opt_bool("pad_enable"); + + get_field("pad_wall_thickness")->toggle(pad_en); + get_field("pad_wall_height")->toggle(pad_en); + get_field("pad_max_merge_distance")->toggle(pad_en); + // get_field("pad_edge_radius")->toggle(supports_en); + get_field("pad_wall_slope")->toggle(pad_en); + get_field("pad_zero_elevation")->toggle(pad_en); double head_penetration = m_config->opt_float("support_head_penetration"); double head_width = m_config->opt_float("support_head_width"); @@ -3779,14 +3832,15 @@ void TabSLAPrint::update() load_config(new_conf); } - - // if(m_config->opt_float("support_object_elevation") < EPSILON && - // m_config->opt_bool("pad_enable")) { - // // TODO: disable editding of: - // // pad_object_connector_stride - // // pad_object_connector_width - // // pad_object_connector_penetration - // } + + bool has_suppad = pad_en && supports_en; + bool zero_elev = m_config->opt_bool("pad_zero_elevation") && has_suppad; + + get_field("support_object_elevation")->toggle(supports_en && !zero_elev); + get_field("pad_object_gap")->toggle(zero_elev); + get_field("pad_object_connector_stride")->toggle(zero_elev); + get_field("pad_object_connector_width")->toggle(zero_elev); + get_field("pad_object_connector_penetration")->toggle(zero_elev); m_update_cnt--; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 6ff76f5c4a..efefc47c56 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -218,7 +218,7 @@ protected: int m_em_unit; // To avoid actions with no-completed Tab bool m_complited { false }; - ConfigOptionMode m_mode = comSimple; + ConfigOptionMode m_mode = comExpert; // to correct first Tab update_visibility() set mode to Expert public: PresetBundle* m_preset_bundle; @@ -340,6 +340,7 @@ class TabFilament : public Tab void add_filament_overrides_page(); void update_filament_overrides_page(); + void update_volumetric_flow_preset_hints(); std::map m_overrides_options; public: diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index a33b7248c3..a4cccfb86f 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -157,6 +157,24 @@ wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, return item; } +wxMenuItem* append_menu_check_item(wxMenu* menu, int id, const wxString& string, const wxString& description, + std::function cb, wxEvtHandler* event_handler) +{ + if (id == wxID_ANY) + id = wxNewId(); + + wxMenuItem* item = menu->AppendCheckItem(id, string, description); + +#ifdef __WXMSW__ + if (event_handler != nullptr && event_handler != menu) + event_handler->Bind(wxEVT_MENU, cb, id); + else +#endif // __WXMSW__ + menu->Bind(wxEVT_MENU, cb, id); + + return item; +} + const unsigned int wxCheckListBoxComboPopup::DefaultWidth = 200; const unsigned int wxCheckListBoxComboPopup::DefaultHeight = 200; const unsigned int wxCheckListBoxComboPopup::DefaultItemHeight = 18; @@ -432,6 +450,16 @@ wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, // ObjectDataViewModelNode // ---------------------------------------------------------------------------- +void ObjectDataViewModelNode::init_container() +{ +#ifdef __WXGTK__ + // it's necessary on GTK because of control have to know if this item will be container + // in another case you couldn't to add subitem for this item + // it will be produce "segmentation fault" + m_container = true; +#endif //__WXGTK__ +} + ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type) : m_parent(parent), m_type(type), @@ -454,13 +482,8 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_name = _(L("Layers")); } -#ifdef __WXGTK__ - // it's necessary on GTK because of control have to know if this item will be container - // in another case you couldn't to add subitem for this item - // it will be produce "segmentation fault" if (type & (itInstanceRoot | itLayerRoot)) - m_container = true; -#endif //__WXGTK__ + init_container(); } ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, @@ -486,14 +509,8 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_name = _(L("Range")) + label_range + "(" + _(L("mm")) + ")"; m_bmp = create_scaled_bitmap(nullptr, "edit_layers_some"); // FIXME: pass window ptr -#ifdef __WXGTK__ - // it's necessary on GTK because of control have to know if this item will be container - // in another case you couldn't to add subitem for this item - // it will be produce "segmentation fault" - m_container = true; -#endif //__WXGTK__ - set_action_icon(); + init_container(); } #ifndef NDEBUG @@ -512,6 +529,13 @@ void ObjectDataViewModelNode::set_action_icon() m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); // FIXME: pass window ptr } +void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable) +{ + m_printable = printable; + m_printable_icon = m_printable == piUndef ? m_empty_bmp : + create_scaled_bitmap(nullptr, m_printable == piPrintable ? "eye_open.png" : "eye_closed.png"); +} + Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr; void ObjectDataViewModelNode::update_settings_digest_bitmaps() { @@ -565,17 +589,20 @@ bool ObjectDataViewModelNode::SetValue(const wxVariant& variant, unsigned col) { switch (col) { - case 0: { + case colPrint: + m_printable_icon << variant; + return true; + case colName: { DataViewBitmapText data; data << variant; m_bmp = data.GetBitmap(); m_name = data.GetText(); return true; } - case 1: { + case colExtruder: { const wxString & val = variant.GetString(); m_extruder = val == "0" ? _(L("default")) : val; return true; } - case 2: + case colEditing: m_action_icon << variant; return true; default: @@ -735,26 +762,60 @@ static bool append_root_node(ObjectDataViewModelNode *parent_node, return false; } -wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) +wxDataViewItem ObjectDataViewModel::AddRoot(const wxDataViewItem &parent_item, ItemType root_type) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); // get InstanceRoot node - ObjectDataViewModelNode *inst_root_node { nullptr }; + ObjectDataViewModelNode *root_node { nullptr }; + const bool appended = append_root_node(parent_node, &root_node, root_type); + if (!root_node) return wxDataViewItem(0); - const bool appended = append_root_node(parent_node, &inst_root_node, itInstanceRoot); - const wxDataViewItem inst_root_item((void*)inst_root_node); - if (!inst_root_node) return wxDataViewItem(0); + const wxDataViewItem root_item((void*)root_node); if (appended) - ItemAdded(parent_item, inst_root_item);// notify control + ItemAdded(parent_item, root_item);// notify control + return root_item; +} + +wxDataViewItem ObjectDataViewModel::AddInstanceRoot(const wxDataViewItem &parent_item) +{ + return AddRoot(parent_item, itInstanceRoot); +} + +wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) +{ + const std::vector print_indicator(num, true); + + return wxDataViewItem((void*)AddInstanceChild(parent_item, print_indicator)); +} + +wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem& parent_item, + const std::vector& print_indicator) +{ + const wxDataViewItem inst_root_item = AddInstanceRoot(parent_item); + if (!inst_root_item) return wxDataViewItem(0); + + ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID(); + + const bool just_created = inst_root_node->GetChildren().Count() == 0; // Add instance nodes ObjectDataViewModelNode *instance_node = nullptr; size_t counter = 0; - while (counter < num) { + while (counter < print_indicator.size()) { instance_node = new ObjectDataViewModelNode(inst_root_node, itInstance); + + // if InstanceRoot item is just created and start to adding Instances + if (just_created && counter == 0) { + ObjectDataViewModelNode* obj_node = (ObjectDataViewModelNode*)parent_item.GetID(); + // use object's printable state to first instance + instance_node->set_printable_icon(obj_node->IsPrintable()); + } + else + instance_node->set_printable_icon(print_indicator[counter] ? piPrintable : piUnprintable); + inst_root_node->Append(instance_node); // notify control const wxDataViewItem instance_item((void*)instance_node); @@ -762,25 +823,67 @@ wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &paren ++counter; } + // update object_node printable property + UpdateObjectPrintable(parent_item); + return wxDataViewItem((void*)instance_node); } +void ObjectDataViewModel::UpdateObjectPrintable(wxDataViewItem parent_item) +{ + const wxDataViewItem inst_root_item = GetInstanceRootItem(parent_item); + if (!inst_root_item) + return; + + ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID(); + + const size_t child_cnt = inst_root_node->GetChildren().Count(); + PrintIndicator obj_pi = piUnprintable; + for (size_t i=0; i < child_cnt; i++) + if (inst_root_node->GetNthChild(i)->IsPrintable() & piPrintable) { + obj_pi = piPrintable; + break; + } + // and set printable state for object_node to piUndef + ObjectDataViewModelNode* obj_node = (ObjectDataViewModelNode*)parent_item.GetID(); + obj_node->set_printable_icon(obj_pi); + ItemChanged(parent_item); +} + +// update printable property for all instances from object +void ObjectDataViewModel::UpdateInstancesPrintable(wxDataViewItem parent_item) +{ + const wxDataViewItem inst_root_item = GetInstanceRootItem(parent_item); + if (!inst_root_item) + return; + + ObjectDataViewModelNode* obj_node = (ObjectDataViewModelNode*)parent_item.GetID(); + const PrintIndicator obj_pi = obj_node->IsPrintable(); + + ObjectDataViewModelNode* inst_root_node = (ObjectDataViewModelNode*)inst_root_item.GetID(); + const size_t child_cnt = inst_root_node->GetChildren().Count(); + + for (size_t i=0; i < child_cnt; i++) + { + ObjectDataViewModelNode* inst_node = inst_root_node->GetNthChild(i); + // and set printable state for object_node to piUndef + inst_node->set_printable_icon(obj_pi); + ItemChanged(wxDataViewItem((void*)inst_node)); + } +} + +bool ObjectDataViewModel::IsPrintable(const wxDataViewItem& item) const +{ + ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); + if (!node) + return false; + + return node->IsPrintable() == piPrintable; +} + wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_item) { - ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); - if (!parent_node) return wxDataViewItem(0); - - // get LayerRoot node - ObjectDataViewModelNode *layer_root_node{ nullptr }; - const bool appended = append_root_node(parent_node, &layer_root_node, itLayerRoot); - if (!layer_root_node) return wxDataViewItem(0); - - const wxDataViewItem layer_root_item((void*)layer_root_node); - - if (appended) - ItemAdded(parent_item, layer_root_item);// notify control - - return layer_root_item; + return AddRoot(parent_item, itLayerRoot); } wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, @@ -878,11 +981,13 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) ItemDeleted(parent, item); ObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0); + PrintIndicator last_instance_printable = last_instance_node->IsPrintable(); node_parent->GetChildren().Remove(last_instance_node); delete last_instance_node; ItemDeleted(parent, wxDataViewItem(last_instance_node)); ObjectDataViewModelNode *obj_node = node_parent->GetParent(); + obj_node->set_printable_icon(last_instance_printable); obj_node->GetChildren().Remove(node_parent); delete node_parent; ret_item = wxDataViewItem(obj_node); @@ -895,6 +1000,9 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) return ret_item; } + if (node->m_type & itInstance) + UpdateObjectPrintable(wxDataViewItem(node_parent->GetParent())); + // if there was last layer item, delete this one and layers root item if (node_parent->GetChildCount() == 0 && node_parent->m_type == itLayerRoot) { @@ -1004,9 +1112,12 @@ wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &par const int inst_cnt = inst_root_node->GetChildCount(); const bool delete_inst_root_item = inst_cnt - num < 2 ? true : false; + PrintIndicator last_inst_printable = piUndef; + int stop = delete_inst_root_item ? 0 : inst_cnt - num; for (int i = inst_cnt - 1; i >= stop;--i) { ObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i); + if (i==0) last_inst_printable = last_instance_node->IsPrintable(); inst_root_node->GetChildren().Remove(last_instance_node); delete last_instance_node; ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node)); @@ -1015,13 +1126,18 @@ wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &par if (delete_inst_root_item) { ret_item = parent_item; parent_node->GetChildren().Remove(inst_root_node); + parent_node->set_printable_icon(last_inst_printable); ItemDeleted(parent_item, inst_root_item); + ItemChanged(parent_item); #ifndef __WXGTK__ if (parent_node->GetChildCount() == 0) parent_node->m_container = false; #endif //__WXGTK__ } + // update object_node printable property + UpdateObjectPrintable(parent_item); + return ret_item; } @@ -1325,6 +1441,18 @@ int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const return -1; } +bool ObjectDataViewModel::InvalidItem(const wxDataViewItem& item) +{ + if (!item) + return true; + + ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); + if (!node || node->invalid()) + return true; + + return false; +} + wxString ObjectDataViewModel::GetName(const wxDataViewItem &item) const { ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); @@ -1347,13 +1475,16 @@ void ObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &ite ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); switch (col) { - case 0: + case colPrint: + variant << node->m_printable_icon; + break; + case colName: variant << DataViewBitmapText(node->m_name, node->m_bmp); break; - case 1: + case colExtruder: variant = node->m_extruder; break; - case 2: + case colEditing: variant << node->m_action_icon; break; default: @@ -1416,7 +1547,7 @@ bool ObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); // disable extruder selection for the non "itObject|itVolume" item - return !(col == 1 && node->m_extruder.IsEmpty()); + return !(col == colExtruder && node->m_extruder.IsEmpty()); } wxDataViewItem ObjectDataViewModel::GetParent(const wxDataViewItem &item) const @@ -1581,6 +1712,46 @@ void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r ItemChanged(item); } +wxDataViewItem ObjectDataViewModel::SetPrintableState( + PrintIndicator printable, + int obj_idx, + int subobj_idx /* = -1*/, + ItemType subobj_type/* = itInstance*/) +{ + wxDataViewItem item = wxDataViewItem(0); + if (subobj_idx < 0) + item = GetItemById(obj_idx); + else + item = subobj_type&itInstance ? GetItemByInstanceId(obj_idx, subobj_idx) : + GetItemByVolumeId(obj_idx, subobj_idx); + + ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); + if (!node) + return wxDataViewItem(0); + node->set_printable_icon(printable); + ItemChanged(item); + + if (subobj_idx >= 0) + UpdateObjectPrintable(GetItemById(obj_idx)); + + return item; +} + +wxDataViewItem ObjectDataViewModel::SetObjectPrintableState( + PrintIndicator printable, + wxDataViewItem obj_item) +{ + ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)obj_item.GetID(); + if (!node) + return wxDataViewItem(0); + node->set_printable_icon(printable); + ItemChanged(obj_item); + + UpdateInstancesPrintable(obj_item); + + return obj_item; +} + void ObjectDataViewModel::Rescale() { wxDataViewItemArray all_items; @@ -1765,7 +1936,7 @@ bool BitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value // The icon can't be edited so get its old value and reuse it. wxVariant valueOld; - GetView()->GetModel()->GetValue(valueOld, m_item, 0); + GetView()->GetModel()->GetValue(valueOld, m_item, colName); DataViewBitmapText bmpText; bmpText << valueOld; diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index aef0896346..14ceab8ff3 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -44,6 +44,9 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, wxEvtHandler* event_handler); +wxMenuItem* append_menu_check_item(wxMenu* menu, int id, const wxString& string, const wxString& description, + std::function cb, wxEvtHandler* event_handler); + class wxDialog; void edit_tooltip(wxString& tooltip); void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector& btn_ids); @@ -173,6 +176,21 @@ enum ItemType { itLayer = 64, }; +enum ColumnNumber +{ + colName = 0, // item name + colPrint , // printable property + colExtruder , // extruder selection + colEditing , // item editing +}; + +enum PrintIndicator +{ + piUndef = 0, // no print indicator + piPrintable , // printable + piUnprintable , // unprintable +}; + class ObjectDataViewModelNode; WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); @@ -192,6 +210,8 @@ class ObjectDataViewModelNode bool m_container = false; wxString m_extruder = "default"; wxBitmap m_action_icon; + PrintIndicator m_printable {piUndef}; + wxBitmap m_printable_icon; std::string m_action_icon_name = ""; Slic3r::ModelVolumeType m_volume_type; @@ -204,15 +224,9 @@ public: m_type(itObject), m_extruder(extruder) { -#ifdef __WXGTK__ - // it's necessary on GTK because of control have to know if this item will be container - // in another case you couldn't to add subitem for this item - // it will be produce "segmentation fault" - m_container = true; -#endif //__WXGTK__ - set_action_icon(); - } + init_container(); + } ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const wxString& sub_obj_name, @@ -226,14 +240,8 @@ public: m_extruder (extruder) { m_bmp = bmp; -#ifdef __WXGTK__ - // it's necessary on GTK because of control have to know if this item will be container - // in another case you couldn't to add subitem for this item - // it will be produce "segmentation fault" - m_container = true; -#endif //__WXGTK__ - set_action_icon(); + init_container(); } ObjectDataViewModelNode(ObjectDataViewModelNode* parent, @@ -258,10 +266,11 @@ public: #endif /* NDEBUG */ } - bool IsContainer() const - { - return m_container; - } + void init_container(); + bool IsContainer() const + { + return m_container; + } ObjectDataViewModelNode* GetParent() { @@ -313,9 +322,10 @@ public: const wxBitmap& GetBitmap() const { return m_bmp; } const wxString& GetName() const { return m_name; } ItemType GetType() const { return m_type; } - void SetIdx(const int& idx); - int GetIdx() const { return m_idx; } - t_layer_height_range GetLayerRange() const { return m_layer_range; } + void SetIdx(const int& idx); + int GetIdx() const { return m_idx; } + t_layer_height_range GetLayerRange() const { return m_layer_range; } + PrintIndicator IsPrintable() const { return m_printable; } // use this function only for childrens void AssignAllVal(ObjectDataViewModelNode& from_node) @@ -347,6 +357,8 @@ public: // Set action icons for node void set_action_icon(); + // Set printable icon for node + void set_printable_icon(PrintIndicator printable); void update_settings_digest_bitmaps(); bool update_settings_digest(const std::vector& categories); @@ -356,6 +368,7 @@ public: #ifndef NDEBUG bool valid(); #endif /* NDEBUG */ + bool invalid() const { return m_idx < -1; } private: friend class ObjectDataViewModel; @@ -391,6 +404,7 @@ public: const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); + wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, const std::vector& print_indicator); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, const t_layer_height_range& layer_range, @@ -418,6 +432,7 @@ public: void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); int GetRowByItem(const wxDataViewItem& item) const; bool IsEmpty() { return m_objects.empty(); } + bool InvalidItem(const wxDataViewItem& item); // helper method for wxLog @@ -468,9 +483,17 @@ public: void UpdateSettingsDigest( const wxDataViewItem &item, const std::vector& categories); + bool IsPrintable(const wxDataViewItem &item) const; + void UpdateObjectPrintable(wxDataViewItem parent_item); + void UpdateInstancesPrintable(wxDataViewItem parent_item); + void SetVolumeBitmaps(const std::vector& volume_bmps) { m_volume_bmps = volume_bmps; } void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; } void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type); + wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx, + int subobj_idx = -1, + ItemType subobj_type = itInstance); + wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item); void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; } // Rescale bitmaps for existing Items @@ -480,6 +503,10 @@ public: const bool is_marked = false); void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false); t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const; + +private: + wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type); + wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item); }; // ---------------------------------------------------------------------------- diff --git a/src/slic3r/Utils/Serial.cpp b/src/slic3r/Utils/Serial.cpp index cd2a01cbfd..acfd5fafd0 100644 --- a/src/slic3r/Utils/Serial.cpp +++ b/src/slic3r/Utils/Serial.cpp @@ -353,6 +353,8 @@ void Serial::set_baud_rate(unsigned baud_rate) } } + +/* void Serial::set_DTR(bool on) { auto handle = native_handle(); @@ -495,6 +497,7 @@ std::string Serial::printer_format_line(const std::string &line, unsigned line_n return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str(); } +*/ } // namespace Utils diff --git a/src/slic3r/Utils/Serial.hpp b/src/slic3r/Utils/Serial.hpp index 67d64b4ec1..8bad75b315 100644 --- a/src/slic3r/Utils/Serial.hpp +++ b/src/slic3r/Utils/Serial.hpp @@ -46,6 +46,17 @@ public: ~Serial(); void set_baud_rate(unsigned baud_rate); + + // The Serial implementation is currently in disarray and therefore commented out. + // The boost implementation seems to have several problems, such as lack of support + // for custom baud rates, few weird implementation bugs and a history of API breakages. + // It's questionable whether it solves more problems than causes. Probably not. + // TODO: Custom implementation not based on asio. + // + // As of now, this class is only kept for the purpose of rebooting AVR109, + // see FirmwareDialog::priv::avr109_reboot() + +/* void set_DTR(bool on); // Resets the line number both internally as well as with the firmware using M110 @@ -68,7 +79,7 @@ public: // Same as above, but with internally-managed line number size_t printer_write_line(const std::string &line); - + // Toggles DTR to reset the printer void printer_reset(); @@ -76,6 +87,7 @@ public: static std::string printer_format_line(const std::string &line, unsigned line_num); private: unsigned m_line_num = 0; +*/ }; diff --git a/version.inc b/version.inc index 4e1607bda1..f84354ab81 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.1.0-alpha0") +set(SLIC3R_VERSION "2.1.0-alpha1") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_RC_VERSION "2,1,0,0") set(SLIC3R_RC_VERSION_DOTS "2.1.0.0") diff --git a/xs/t/03_point.t b/xs/t/03_point.t index cb71f68f5f..c950998fbb 100644 --- a/xs/t/03_point.t +++ b/xs/t/03_point.t @@ -44,7 +44,7 @@ ok !$point->coincides_with($point2), 'coincides_with'; { my $line = Slic3r::Line->new([50,50], [125,-25]); - is +Slic3r::Point->new(100,0)->distance_to_line($line), 0, 'distance_to_line()'; + cmp_ok(abs(Slic3r::Point->new(100,0)->distance_to_line($line)), '<=', 4e-15, 'distance_to_line()'); } {