Merge branch 'master' into fs_emboss
# Conflicts: # src/slic3r/GUI/GLCanvas3D.cpp # src/slic3r/GUI/Selection.cpp
This commit is contained in:
commit
ed6a1b18f3
115 changed files with 19036 additions and 16206 deletions
.clang-format
resources
src
libslic3r
AABBTreeLines.hppCMakeLists.txt
GCode
Geometry.cppPerimeterGenerator.cppPolygon.cppPolygon.hppPreset.cppPreset.hppPrint.cppPrint.hppPrintApply.cppPrintConfig.cppPrintConfig.hppPrintObject.cppSupportMaterial.cppSupportSpotsGenerator.cppSupportSpotsGenerator.hppTreeModelVolumes.cppTreeModelVolumes.hppTreeSupport.cppTreeSupport.hppTriangleSelectorWrapper.cppTriangleSelectorWrapper.hppslic3r/GUI
|
@ -46,7 +46,7 @@ BreakConstructorInitializersBeforeComma: false
|
||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 78
|
ColumnLimit: 140
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
CompactNamespaces: true
|
CompactNamespaces: true
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
|
4
resources/icons/edit.svg
Normal file
4
resources/icons/edit.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M38.2923 1.34808L38.2441 1.30417C37.3235 0.463194 36.1301 0 34.8837 0C33.4864 0 32.1449 0.591489 31.2029 1.62267L13.3916 21.1224C13.2293 21.3002 13.1061 21.5099 13.03 21.7381L10.9357 28.0167C10.6935 28.7426 10.815 29.5453 11.2607 30.164C11.7099 30.7875 12.4336 31.1598 13.1967 31.1598H13.1968C13.5269 31.1598 13.8495 31.0919 14.1555 30.958L20.2195 28.3052C20.44 28.2087 20.6377 28.0671 20.8 27.8894L38.6114 8.38977C40.4648 6.36078 40.3219 3.20211 38.2923 1.34808ZM14.9484 26.8569L16.1773 23.1726L16.281 23.0591L18.6102 25.1866L18.5066 25.3001L14.9484 26.8569ZM36.0718 6.07002L20.93 22.6472L18.6007 20.5197L33.7426 3.94242C34.0387 3.61819 34.444 3.43956 34.8838 3.43956C35.2696 3.43956 35.6391 3.5831 35.9251 3.84428L35.9731 3.88819C36.6019 4.46248 36.6461 5.44127 36.0718 6.07002V6.07002Z" fill="#ED6B21"/>
|
||||||
|
<path d="M34.8369 15.8664C33.8871 15.8664 33.1171 16.6364 33.1171 17.5862V32.1868C33.1171 34.5984 31.155 36.5604 28.7435 36.5604H7.89985C5.48815 36.5604 3.52623 34.5984 3.52623 32.1868V11.5125C3.52623 9.10094 5.48826 7.1389 7.89985 7.1389H22.9865C23.9363 7.1389 24.7063 6.3689 24.7063 5.41912C24.7063 4.46934 23.9363 3.69934 22.9865 3.69934H7.89985C3.59158 3.69934 0.0866699 7.20437 0.0866699 11.5125V32.1867C0.0866699 36.4949 3.59169 39.9999 7.89985 39.9999H28.7433C33.0515 39.9999 36.5565 36.4949 36.5565 32.1867V17.5862C36.5566 16.6364 35.7866 15.8664 34.8369 15.8664V15.8664Z" fill="#808080"/>
|
||||||
|
</svg>
|
After (image error) Size: 1.5 KiB |
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -2135,8 +2135,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Vyberte jeden nebo více souborů (STL, OBJ):"
|
msgstr "Vyberte jeden nebo více souborů (STL, OBJ):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Vyberte jeden nebo více souborů (STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "Vyberte jeden nebo více souborů (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6044,12 +6044,13 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "Importovat STL (imperiální jednotky)"
|
msgstr "Importovat STL (imperiální jednotky)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Importovat STL/OBJ/AM&F/3MF"
|
msgstr "Importovat STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "Importovat STL/OBJ/AMF/3MF bez konfigurace, zachová stávající podložku"
|
msgstr ""
|
||||||
|
"Importovat STL/3MF/STEP/OBJ/AMF bez konfigurace, zachová stávající podložku"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8227,9 +8228,8 @@ msgid "Open new instance"
|
||||||
msgstr "Otevřít novou instanci"
|
msgstr "Otevřít novou instanci"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr ""
|
msgstr "Otevřít projekt AMF/3MF s konfigurací, odstranit modely na podložce"
|
||||||
"Otevřít projekt STL/OBJ/AMF/3MF s konfigurací, odstranit modely na podložce"
|
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
|
@ -2130,8 +2130,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Wählen Sie eine oder mehrere Dateien (STL, OBJ):"
|
msgstr "Wählen Sie eine oder mehrere Dateien (STL, OBJ):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Wählen Sie eine oder mehrere Dateien (STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "Wählen Sie eine oder mehrere Dateien (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6141,13 +6141,13 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "STL importieren (imperiale Einheiten)"
|
msgstr "STL importieren (imperiale Einheiten)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Importiere STL/OBJ/AM&F/3MF"
|
msgstr "Importiere STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Importiere STL/OBJ/AMF/3MF mit Konfigurationsdaten, Druckplatte beibehalten"
|
"Importiere STL/3MF/STEP/OBJ/AMF mit Konfigurationsdaten, Druckplatte beibehalten"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8357,8 +8357,8 @@ msgid "Open new instance"
|
||||||
msgstr "Neue Instanz öffnen"
|
msgstr "Neue Instanz öffnen"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr "Öffne Projekt STL/OBJ/AMF/3MF mit Konfiguration, Druckplatte leeren"
|
msgstr "Öffne Projekt AMF/3MF mit Konfiguration, Druckplatte leeren"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -2115,8 +2115,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Elije uno o varios archivos (STL, OBJ):"
|
msgstr "Elije uno o varios archivos (STL, OBJ):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Escoje uno o más archivos (STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "Escoje uno o más archivos (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6096,12 +6096,12 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "Importar STL (Unidades Imperiales)"
|
msgstr "Importar STL (Unidades Imperiales)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Importar STL/OBJ/AM&F/3MF"
|
msgstr "Importar STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "Importar STL/OBJ/AMF/3MF sin configuración, mantener la base"
|
msgstr "Importar STL/3MF/STEP/OBJ/AMF sin configuración, mantener la base"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8302,8 +8302,8 @@ msgid "Open new instance"
|
||||||
msgstr "Abrir instancia nueva"
|
msgstr "Abrir instancia nueva"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr "Abrir proyecto STL/OBJ/AMF/3MF con configuración, limpiar plataforma"
|
msgstr "Abrir proyecto AMF/3MF con configuración, limpiar plataforma"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
|
@ -2139,8 +2139,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Choisissez un ou plusieurs fichiers (STL, OBJ) :"
|
msgstr "Choisissez un ou plusieurs fichiers (STL, OBJ) :"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Choisir un ou plusieurs fichiers (STL/OBJ/AMF/3MF/PRUSA) :"
|
msgstr "Choisir un ou plusieurs fichiers (STL/3MF/STEP/OBJ/AMF/PRUSA) :"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6155,12 +6155,12 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "Importer le STL (unités impériales)"
|
msgstr "Importer le STL (unités impériales)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Importer STL/OBJ/AM&F/3MF"
|
msgstr "Importer STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "Importer un STL/OBJ/AMF/3MF sans configuration, conserver le plateau"
|
msgstr "Importer un STL/3MF/STEP/OBJ/AMF sans configuration, conserver le plateau"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8375,9 +8375,8 @@ msgid "Open new instance"
|
||||||
msgstr "Ouvrir une nouvelle instance"
|
msgstr "Ouvrir une nouvelle instance"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr ""
|
msgstr "Ouvrir un projet AMF/3MF avec configuration, libérer le plateau"
|
||||||
"Ouvrir un projet STL/OBJ/AMF/3MF avec configuration, libérer le plateau"
|
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -2119,8 +2119,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Scegli uno o più file (STL, OBJ):"
|
msgstr "Scegli uno o più file (STL, OBJ):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Seleziona uno o più file (STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "Seleziona uno o più file (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6091,12 +6091,12 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "Importa STL (unità imperiali)"
|
msgstr "Importa STL (unità imperiali)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Importa STL/OBJ/AM&F/3MF"
|
msgstr "Importa STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "Importa STL/OBJ/AMF/3MF senza configurazione, mantieni piano"
|
msgstr "Importa STL/3MF/STEP/OBJ/AMF senza configurazione, mantieni piano"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8294,8 +8294,8 @@ msgid "Open new instance"
|
||||||
msgstr "Apri una nuova istanza"
|
msgstr "Apri una nuova istanza"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr "Apri progetto STL/OBJ/AMF/3MF con configurazione, pulisci piano"
|
msgstr "Apri progetto AMF/3MF con configurazione, pulisci piano"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
|
@ -2081,8 +2081,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "1つ以上のファイル(STL, OBJ)を選択します:"
|
msgstr "1つ以上のファイル(STL, OBJ)を選択します:"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "1つ以上のファイルの選択(STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "1つ以上のファイルの選択(STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -5963,12 +5963,12 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "STLのインポート(インチ)"
|
msgstr "STLのインポート(インチ)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "STL/OBJ/AMF/3MFのインポート(&F)"
|
msgstr "STL/3MF/STEP/OBJ/AMFのインポート(&F)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "既存のプレートを保持しながらSTL/OBJ/AMF/3MFを設定なしでインポート"
|
msgstr "既存のプレートを保持しながらSTL/3MF/STEP/OBJ/AMFを設定なしでインポート"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8124,8 +8124,8 @@ msgid "Open new instance"
|
||||||
msgstr "新しいインスタンスを開く"
|
msgstr "新しいインスタンスを開く"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr "プロジェクトSTL/OBJ/AMF/3MFを設定を含めて開き、プレートをクリアします"
|
msgstr "プロジェクトAMF/3MFを設定を含めて開き、プレートをクリアします"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -2145,8 +2145,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
||||||
msgstr "Wybierz jeden lub więcej plików (STL, OBJ):"
|
msgstr "Wybierz jeden lub więcej plików (STL, OBJ):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
msgstr "Wybierz jeden lub więcej plików (STL/OBJ/AMF/3MF/PRUSA):"
|
msgstr "Wybierz jeden lub więcej plików (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||||
|
|
||||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||||
msgid "Choose the type of firmware used by your printer."
|
msgid "Choose the type of firmware used by your printer."
|
||||||
|
@ -6080,12 +6080,12 @@ msgid "Import STL (Imperial Units)"
|
||||||
msgstr "Import STL (jednostki imperialne)"
|
msgstr "Import STL (jednostki imperialne)"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||||
msgid "Import STL/OBJ/AM&F/3MF"
|
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
msgstr "Import STL/OBJ/AM&F/3MF"
|
msgstr "Import STL/3MF/STEP/OBJ/AM&F"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||||
msgstr "Otwórz STL/OBJ/AMF/3MF bez konfiguracji, zachowaj zawartość stołu"
|
msgstr "Otwórz STL/3MF/STEP/OBJ/AMF bez konfiguracji, zachowaj zawartość stołu"
|
||||||
|
|
||||||
#: src/slic3r/GUI/Plater.cpp:5293
|
#: src/slic3r/GUI/Plater.cpp:5293
|
||||||
msgid "Import config only"
|
msgid "Import config only"
|
||||||
|
@ -8279,8 +8279,8 @@ msgid "Open new instance"
|
||||||
msgstr "Otwórz nową instancję"
|
msgstr "Otwórz nową instancję"
|
||||||
|
|
||||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
msgid "Open project AMF/3MF with config, clear plater"
|
||||||
msgstr "Otwórz projekt STL/OBJ/AMF/3MF z konfiguracją, wyczyść stół"
|
msgstr "Otwórz projekt AMF/3MF z konfiguracją, wyczyść stół"
|
||||||
|
|
||||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||||
#, c-format, boost-format
|
#, c-format, boost-format
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
BIN
resources/profiles/Creality/ENDER5PRO_thumbnail.png
Normal file
BIN
resources/profiles/Creality/ENDER5PRO_thumbnail.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 28 KiB |
3
resources/profiles/Rigid3D.idx
Normal file
3
resources/profiles/Rigid3D.idx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
min_slic3r_version = 2.6.0-alpha0
|
||||||
|
1.0.0 Initial Rigid3D bundle
|
||||||
|
|
469
resources/profiles/Rigid3D.ini
Normal file
469
resources/profiles/Rigid3D.ini
Normal file
|
@ -0,0 +1,469 @@
|
||||||
|
# Print profiles for the Rigid3D printers.
|
||||||
|
|
||||||
|
[vendor]
|
||||||
|
# Vendor name will be shown by the Config Wizard.
|
||||||
|
name = Rigid3D
|
||||||
|
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||||
|
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||||
|
config_version = 1.0.0
|
||||||
|
# Where to get the updates from?
|
||||||
|
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Rigid3D/
|
||||||
|
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||||
|
|
||||||
|
# The printer models will be shown by the Configuration Wizard in this order,
|
||||||
|
# also the first model installed & the first nozzle installed will be activated after install.
|
||||||
|
# Printer model name will be shown by the installation wizard.
|
||||||
|
|
||||||
|
[printer_model:Zero2]
|
||||||
|
name = Rigid3D Zero2
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Zero
|
||||||
|
bed_model = zero_bed.stl
|
||||||
|
bed_texture = zero2_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Zero3]
|
||||||
|
name = Rigid3D Zero3
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Zero
|
||||||
|
bed_model = zero_bed.stl
|
||||||
|
bed_texture = zero3_bed.png
|
||||||
|
default_materials =Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Mucit]
|
||||||
|
name = Rigid3D Mucit
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Mucit
|
||||||
|
bed_model = mucit_bed.stl
|
||||||
|
bed_texture = mucit_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Rigid3D PLA @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Mucit2]
|
||||||
|
name = Rigid3D Mucit2
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Mucit
|
||||||
|
bed_model = mucit2_bed.stl
|
||||||
|
bed_texture = mucit2_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||||
|
# not make it into the user interface.
|
||||||
|
|
||||||
|
# Common print preset
|
||||||
|
[print:*common*]
|
||||||
|
avoid_crossing_perimeters = 0
|
||||||
|
avoid_crossing_perimeters_max_detour = 0
|
||||||
|
bottom_fill_pattern = monotonic
|
||||||
|
bottom_solid_min_thickness = 0.8
|
||||||
|
bridge_acceleration = 0
|
||||||
|
bridge_angle = 0
|
||||||
|
bridge_flow_ratio = 1
|
||||||
|
bridge_speed = 60
|
||||||
|
brim_separation = 0
|
||||||
|
brim_type = no_brim
|
||||||
|
brim_width = 0
|
||||||
|
clip_multipart_objects = 1
|
||||||
|
compatible_printers =
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
|
||||||
|
complete_objects = 0
|
||||||
|
default_acceleration = 0
|
||||||
|
dont_support_bridges = 1
|
||||||
|
draft_shield = disabled
|
||||||
|
elefant_foot_compensation = 0
|
||||||
|
ensure_vertical_shell_thickness = 0
|
||||||
|
external_perimeter_extrusion_width = 0.45
|
||||||
|
external_perimeter_speed = 50%
|
||||||
|
external_perimeters_first = 1
|
||||||
|
extra_perimeters = 1
|
||||||
|
extruder_clearance_height = 20
|
||||||
|
extruder_clearance_radius = 20
|
||||||
|
extrusion_width = 0.45
|
||||||
|
fill_angle = 45
|
||||||
|
fill_density = 10%
|
||||||
|
fill_pattern = line
|
||||||
|
first_layer_acceleration = 0
|
||||||
|
first_layer_acceleration_over_raft = 0
|
||||||
|
first_layer_extrusion_width = 0.42
|
||||||
|
first_layer_height = 0.2
|
||||||
|
first_layer_speed = 50%
|
||||||
|
first_layer_speed_over_raft = 30
|
||||||
|
fuzzy_skin = none
|
||||||
|
fuzzy_skin_point_dist = 0.8
|
||||||
|
fuzzy_skin_thickness = 0.3
|
||||||
|
gap_fill_enabled = 1
|
||||||
|
gap_fill_speed = 20
|
||||||
|
gcode_comments = 0
|
||||||
|
gcode_label_objects = 0
|
||||||
|
gcode_resolution = 0.0125
|
||||||
|
gcode_substitutions =
|
||||||
|
infill_acceleration = 0
|
||||||
|
infill_anchor = 2.5
|
||||||
|
infill_anchor_max = 12
|
||||||
|
infill_every_layers = 1
|
||||||
|
infill_extruder = 1
|
||||||
|
infill_extrusion_width = 0.45
|
||||||
|
infill_first = 1
|
||||||
|
infill_only_where_needed = 0
|
||||||
|
infill_overlap = 25%
|
||||||
|
infill_speed = 60
|
||||||
|
inherits =
|
||||||
|
interface_shells = 0
|
||||||
|
ironing = 0
|
||||||
|
ironing_flowrate = 15%
|
||||||
|
ironing_spacing = 0.1
|
||||||
|
ironing_speed = 15
|
||||||
|
ironing_type = top
|
||||||
|
max_print_speed = 80
|
||||||
|
max_volumetric_speed = 0
|
||||||
|
min_skirt_length = 0
|
||||||
|
mmu_segmented_region_max_width = 0
|
||||||
|
notes =
|
||||||
|
only_retract_when_crossing_perimeters = 0
|
||||||
|
ooze_prevention = 0
|
||||||
|
output_filename_format = {input_filename_base}_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode
|
||||||
|
overhangs = 1
|
||||||
|
perimeter_acceleration = 0
|
||||||
|
perimeter_extruder = 1
|
||||||
|
perimeter_extrusion_width = 0.45
|
||||||
|
perimeter_speed = 60
|
||||||
|
perimeters = 2
|
||||||
|
post_process =
|
||||||
|
print_settings_id =
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
raft_expansion = 1.5
|
||||||
|
raft_first_layer_density = 90%
|
||||||
|
raft_first_layer_expansion = 3
|
||||||
|
raft_layers = 0
|
||||||
|
resolution = 0
|
||||||
|
seam_position = rear
|
||||||
|
single_extruder_multi_material_priming = 1
|
||||||
|
skirt_distance = 6
|
||||||
|
skirt_height = 1
|
||||||
|
skirts = 0
|
||||||
|
slice_closing_radius = 0.049
|
||||||
|
slicing_mode = regular
|
||||||
|
small_perimeter_speed = 15
|
||||||
|
solid_infill_below_area = 70
|
||||||
|
solid_infill_every_layers = 0
|
||||||
|
solid_infill_extruder = 1
|
||||||
|
solid_infill_extrusion_width = 0.45
|
||||||
|
solid_infill_speed = 100%
|
||||||
|
spiral_vase = 0
|
||||||
|
standby_temperature_delta = -5
|
||||||
|
support_material = 0
|
||||||
|
support_material_angle = 0
|
||||||
|
support_material_auto = 1
|
||||||
|
support_material_bottom_contact_distance = 0
|
||||||
|
support_material_bottom_interface_layers = -1
|
||||||
|
support_material_buildplate_only = 0
|
||||||
|
support_material_closing_radius = 2
|
||||||
|
support_material_contact_distance = 0.2
|
||||||
|
support_material_enforce_layers = 0
|
||||||
|
support_material_extruder = 1
|
||||||
|
support_material_extrusion_width = 0.35
|
||||||
|
support_material_interface_contact_loops = 0
|
||||||
|
support_material_interface_extruder = 1
|
||||||
|
support_material_interface_layers = 3
|
||||||
|
support_material_interface_pattern = rectilinear
|
||||||
|
support_material_interface_spacing = 0
|
||||||
|
support_material_interface_speed = 100%
|
||||||
|
support_material_pattern = rectilinear
|
||||||
|
support_material_spacing = 2.5
|
||||||
|
support_material_speed = 60
|
||||||
|
support_material_style = grid
|
||||||
|
support_material_synchronize_layers = 0
|
||||||
|
support_material_threshold = 0
|
||||||
|
support_material_with_sheath = 1
|
||||||
|
support_material_xy_spacing = 50%
|
||||||
|
thick_bridges = 0
|
||||||
|
thin_walls = 1
|
||||||
|
top_fill_pattern = monotonic
|
||||||
|
top_infill_extrusion_width = 0.4
|
||||||
|
top_solid_infill_speed = 100%
|
||||||
|
top_solid_min_thickness = 0.8
|
||||||
|
travel_speed = 80
|
||||||
|
travel_speed_z = 0
|
||||||
|
wipe_tower = 0
|
||||||
|
wipe_tower_bridging = 10
|
||||||
|
wipe_tower_brim_width = 2
|
||||||
|
wipe_tower_no_sparse_layers = 0
|
||||||
|
wipe_tower_rotation_angle = 0
|
||||||
|
wipe_tower_width = 60
|
||||||
|
wipe_tower_x = 180
|
||||||
|
wipe_tower_y = 140
|
||||||
|
xy_size_compensation = 0
|
||||||
|
|
||||||
|
[print:0.06mm - Ultra @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.06
|
||||||
|
bottom_solid_layers = 10
|
||||||
|
top_solid_layers = 14
|
||||||
|
|
||||||
|
[print:0.12mm - Super @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.12
|
||||||
|
bottom_solid_layers = 7
|
||||||
|
top_solid_layers = 7
|
||||||
|
|
||||||
|
[print:0.16mm - Good @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.16
|
||||||
|
bottom_solid_layers = 5
|
||||||
|
top_solid_layers = 5
|
||||||
|
|
||||||
|
[print:0.20mm - Standard @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.20
|
||||||
|
bottom_solid_layers = 4
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[print:0.24mm - Draft @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.24
|
||||||
|
bottom_solid_layers = 3
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[print:0.28mm - Low @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.28
|
||||||
|
bottom_solid_layers = 3
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[filament:*common*]
|
||||||
|
disable_fan_first_layers = 3
|
||||||
|
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
|
||||||
|
extrusion_multiplier = 1
|
||||||
|
fan_below_layer_time = 60
|
||||||
|
filament_cooling_final_speed = 3.4
|
||||||
|
filament_cooling_initial_speed = 2.2
|
||||||
|
filament_cooling_moves = 4
|
||||||
|
filament_cost = 0
|
||||||
|
filament_deretract_speed = nil
|
||||||
|
filament_diameter = 1.75
|
||||||
|
filament_minimal_purge_on_wipe_tower = 15
|
||||||
|
filament_notes = ""
|
||||||
|
filament_retract_before_travel = nil
|
||||||
|
filament_retract_before_wipe = nil
|
||||||
|
filament_retract_layer_change = nil
|
||||||
|
filament_retract_length = nil
|
||||||
|
filament_retract_lift = nil
|
||||||
|
filament_retract_lift_above = nil
|
||||||
|
filament_retract_lift_below = nil
|
||||||
|
filament_retract_restart_extra = nil
|
||||||
|
filament_retract_speed = nil
|
||||||
|
filament_settings_id = ""
|
||||||
|
filament_soluble = 0
|
||||||
|
filament_spool_weight = 0
|
||||||
|
filament_wipe = nil
|
||||||
|
min_print_speed = 10
|
||||||
|
slowdown_below_layer_time = 10
|
||||||
|
start_filament_gcode = "; Filament gcode\n"
|
||||||
|
|
||||||
|
[filament:*PLA*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
|
||||||
|
bridge_fan_speed = 100
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 1
|
||||||
|
filament_type = PLA
|
||||||
|
full_fan_speed_layer = 4
|
||||||
|
max_fan_speed = 100
|
||||||
|
min_fan_speed = 100
|
||||||
|
|
||||||
|
[filament:*ABS*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = ABS
|
||||||
|
max_fan_speed = 0
|
||||||
|
min_fan_speed = 0
|
||||||
|
|
||||||
|
[filament:*PETG*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = PETG
|
||||||
|
max_fan_speed = 50
|
||||||
|
min_fan_speed = 30
|
||||||
|
|
||||||
|
[filament:*FLEX*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
bridge_fan_speed = 100
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 1
|
||||||
|
filament_type = FLEX
|
||||||
|
full_fan_speed_layer = 4
|
||||||
|
max_fan_speed = 100
|
||||||
|
min_fan_speed = 100
|
||||||
|
|
||||||
|
[filament:*NYLON*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = NYLON
|
||||||
|
max_fan_speed = 0
|
||||||
|
min_fan_speed = 0
|
||||||
|
|
||||||
|
[filament:Generic PLA @Rigid3D]
|
||||||
|
inherits = *PLA*
|
||||||
|
bed_temperature = 55
|
||||||
|
filament_colour = #FFFF00
|
||||||
|
filament_density = 1.24
|
||||||
|
filament_max_volumetric_speed = 12
|
||||||
|
first_layer_temperature = 215
|
||||||
|
temperature = 215
|
||||||
|
first_layer_bed_temperature = 60
|
||||||
|
|
||||||
|
[filament:Rigid3D PLA @Rigid3D]
|
||||||
|
inherits = *PLA*
|
||||||
|
filament_colour = #FFFF00
|
||||||
|
filament_density = 1.24
|
||||||
|
first_layer_temperature = 210
|
||||||
|
temperature = 205
|
||||||
|
first_layer_bed_temperature = 60
|
||||||
|
bed_temperature = 55
|
||||||
|
filament_max_volumetric_speed = 12
|
||||||
|
|
||||||
|
[filament:Generic ABS @Rigid3D]
|
||||||
|
inherits = *ABS*
|
||||||
|
filament_colour = #49B928
|
||||||
|
filament_density = 1.04
|
||||||
|
first_layer_temperature = 235
|
||||||
|
temperature = 235
|
||||||
|
first_layer_bed_temperature = 100
|
||||||
|
bed_temperature = 100
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
[filament:Generic PETG @Rigid3D]
|
||||||
|
inherits = *PETG*
|
||||||
|
filament_colour = #FF8000
|
||||||
|
filament_density = 1.27
|
||||||
|
first_layer_temperature = 240
|
||||||
|
temperature = 240
|
||||||
|
first_layer_bed_temperature = 70
|
||||||
|
bed_temperature = 70
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
[filament:Generic FLEX @Rigid3D]
|
||||||
|
inherits = *FLEX*
|
||||||
|
filament_colour = #C80000
|
||||||
|
filament_density = 1.21
|
||||||
|
first_layer_temperature = 225
|
||||||
|
temperature = 225
|
||||||
|
first_layer_bed_temperature = 70
|
||||||
|
bed_temperature = 70
|
||||||
|
filament_max_volumetric_speed = 2.5
|
||||||
|
|
||||||
|
[filament:Generic Nylon @Rigid3D]
|
||||||
|
inherits = *NYLON*
|
||||||
|
filament_colour = #0AF1CE
|
||||||
|
filament_density = 1.12
|
||||||
|
first_layer_temperature = 250
|
||||||
|
temperature = 250
|
||||||
|
first_layer_bed_temperature = 100
|
||||||
|
bed_temperature = 100
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
# Common printer preset
|
||||||
|
[printer:*common*]
|
||||||
|
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
|
||||||
|
between_objects_gcode =
|
||||||
|
color_change_gcode = M600
|
||||||
|
default_filament_profile = "Rigid3D PLA @Rigid3D"
|
||||||
|
default_print_profile = "0.20mm - Standard @Rigid3D"
|
||||||
|
deretract_speed = 0
|
||||||
|
extruder_offset = 0x0
|
||||||
|
gcode_flavor = marlin2
|
||||||
|
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]\n\n
|
||||||
|
machine_limits_usage = time_estimate_only
|
||||||
|
machine_max_acceleration_e = 1000
|
||||||
|
machine_max_acceleration_extruding = 500
|
||||||
|
machine_max_acceleration_retracting = 1000
|
||||||
|
machine_max_acceleration_travel = 1000
|
||||||
|
machine_max_acceleration_x = 500
|
||||||
|
machine_max_acceleration_y = 500
|
||||||
|
machine_max_acceleration_z = 100
|
||||||
|
machine_max_feedrate_e = 25
|
||||||
|
machine_max_feedrate_x = 120
|
||||||
|
machine_max_feedrate_y = 120
|
||||||
|
machine_max_feedrate_z = 20
|
||||||
|
machine_max_jerk_e = 5
|
||||||
|
machine_max_jerk_x = 10
|
||||||
|
machine_max_jerk_y = 10
|
||||||
|
machine_max_jerk_z = 0.3
|
||||||
|
machine_min_extruding_rate = 0
|
||||||
|
machine_min_travel_rate = 0
|
||||||
|
max_layer_height = 0.32
|
||||||
|
min_layer_height = 0.05
|
||||||
|
nozzle_diameter = 0.4
|
||||||
|
pause_print_gcode = M0
|
||||||
|
printer_settings_id =
|
||||||
|
printer_technology = FFF
|
||||||
|
printer_variant = 0.4
|
||||||
|
remaining_times = 1
|
||||||
|
retract_before_travel = 2
|
||||||
|
retract_before_wipe = 0%
|
||||||
|
retract_layer_change = 0
|
||||||
|
retract_length = 1
|
||||||
|
retract_length_toolchange = 10
|
||||||
|
retract_lift = 0
|
||||||
|
retract_lift_above = 0
|
||||||
|
retract_lift_below = 0
|
||||||
|
retract_restart_extra = 0
|
||||||
|
retract_restart_extra_toolchange = 0
|
||||||
|
retract_speed = 25
|
||||||
|
silent_mode = 0
|
||||||
|
single_extruder_multi_material = 0
|
||||||
|
template_custom_gcode =
|
||||||
|
thumbnails =
|
||||||
|
toolchange_gcode =
|
||||||
|
use_firmware_retraction = 0
|
||||||
|
use_relative_e_distances = 0
|
||||||
|
use_volumetric_e = 0
|
||||||
|
variable_layer_height = 1
|
||||||
|
wipe = 0
|
||||||
|
z_offset = 0
|
||||||
|
|
||||||
|
[printer:Rigid3D Zero2]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,200x0,200x200,0x200
|
||||||
|
max_print_height = 190
|
||||||
|
printer_model = Zero2
|
||||||
|
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_RIGID3D\nPRINTER_MODEL_ZERO2\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G1 X0 Y180\nM107\nG91\nG0 Z20\nT0\nG1 E-1\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Zero3]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,200x0,200x200,0x200
|
||||||
|
max_print_height = 200
|
||||||
|
printer_model = Zero3
|
||||||
|
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_RIGID3D\nPRINTER_MODEL_ZERO3\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Mucit]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,150x0,150x150,0x150
|
||||||
|
max_print_height = 150
|
||||||
|
printer_model = Mucit
|
||||||
|
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_RIGID3D\nPRINTER_MODEL_MUCIT\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G1 X0 Y140\nM107\nG91\nG0 Z20\nT0\nG1 E-2\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Mucit2]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,150x0,150x150,0x150
|
||||||
|
max_print_height = 150
|
||||||
|
printer_model = Mucit2
|
||||||
|
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_RIGID3D\nPRINTER_MODEL_MUCIT2\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n
|
BIN
resources/profiles/Rigid3D/Mucit2_thumbnail.png
Normal file
BIN
resources/profiles/Rigid3D/Mucit2_thumbnail.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 53 KiB |
BIN
resources/profiles/Rigid3D/Mucit_thumbnail.png
Normal file
BIN
resources/profiles/Rigid3D/Mucit_thumbnail.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 54 KiB |
BIN
resources/profiles/Rigid3D/Zero2_thumbnail.png
Normal file
BIN
resources/profiles/Rigid3D/Zero2_thumbnail.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 59 KiB |
BIN
resources/profiles/Rigid3D/Zero3_thumbnail.png
Normal file
BIN
resources/profiles/Rigid3D/Zero3_thumbnail.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 46 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.png
Normal file
BIN
resources/profiles/Rigid3D/mucit2_bed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 10 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/mucit2_bed.stl
Normal file
Binary file not shown.
BIN
resources/profiles/Rigid3D/mucit_bed.png
Normal file
BIN
resources/profiles/Rigid3D/mucit_bed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 9.1 KiB |
BIN
resources/profiles/Rigid3D/mucit_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/mucit_bed.stl
Normal file
Binary file not shown.
BIN
resources/profiles/Rigid3D/zero2_bed.png
Normal file
BIN
resources/profiles/Rigid3D/zero2_bed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero3_bed.png
Normal file
BIN
resources/profiles/Rigid3D/zero3_bed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/zero_bed.stl
Normal file
Binary file not shown.
|
@ -1,8 +1,6 @@
|
||||||
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
|
||||||
#include "libslic3r/EdgeGrid.hpp"
|
|
||||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||||
#include "libslic3r/Line.hpp"
|
#include "libslic3r/Line.hpp"
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,8 @@ set(SLIC3R_SOURCES
|
||||||
SlicingAdaptive.hpp
|
SlicingAdaptive.hpp
|
||||||
Subdivide.cpp
|
Subdivide.cpp
|
||||||
Subdivide.hpp
|
Subdivide.hpp
|
||||||
|
SupportSpotsGenerator.cpp
|
||||||
|
SupportSpotsGenerator.hpp
|
||||||
SupportMaterial.cpp
|
SupportMaterial.cpp
|
||||||
SupportMaterial.hpp
|
SupportMaterial.hpp
|
||||||
Surface.cpp
|
Surface.cpp
|
||||||
|
@ -283,6 +285,8 @@ set(SLIC3R_SOURCES
|
||||||
TriangleSelector.hpp
|
TriangleSelector.hpp
|
||||||
TriangleSetSampling.cpp
|
TriangleSetSampling.cpp
|
||||||
TriangleSetSampling.hpp
|
TriangleSetSampling.hpp
|
||||||
|
TriangleSelectorWrapper.cpp
|
||||||
|
TriangleSelectorWrapper.hpp
|
||||||
MTUtils.hpp
|
MTUtils.hpp
|
||||||
Zipper.hpp
|
Zipper.hpp
|
||||||
Zipper.cpp
|
Zipper.cpp
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "libslic3r/format.hpp"
|
#include "libslic3r/format.hpp"
|
||||||
#include "GCodeProcessor.hpp"
|
#include "GCodeProcessor.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string/split.hpp>
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
@ -777,8 +778,7 @@ void GCodeProcessorResult::reset() {
|
||||||
max_print_height = 0.0f;
|
max_print_height = 0.0f;
|
||||||
settings_ids.reset();
|
settings_ids.reset();
|
||||||
extruders_count = 0;
|
extruders_count = 0;
|
||||||
extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
extruder_colors = std::vector<std::string>();
|
||||||
assert(extruder_colors.size() == MIN_EXTRUDERS_COUNT);
|
|
||||||
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
||||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||||
#if ENABLE_USED_FILAMENT_POST_PROCESS
|
#if ENABLE_USED_FILAMENT_POST_PROCESS
|
||||||
|
@ -870,6 +870,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
||||||
{
|
{
|
||||||
m_parser.apply_config(config);
|
m_parser.apply_config(config);
|
||||||
|
|
||||||
|
m_producer = EProducer::PrusaSlicer;
|
||||||
m_flavor = config.gcode_flavor;
|
m_flavor = config.gcode_flavor;
|
||||||
|
|
||||||
size_t extruders_count = config.nozzle_diameter.values.size();
|
size_t extruders_count = config.nozzle_diameter.values.size();
|
||||||
|
@ -1093,6 +1094,20 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning.
|
||||||
|
// Remember the parking position so the initial load is not included in filament estimate.
|
||||||
|
const ConfigOptionBool* single_extruder_multi_material = config.option<ConfigOptionBool>("single_extruder_multi_material");
|
||||||
|
const ConfigOptionBool* wipe_tower = config.option<ConfigOptionBool>("wipe_tower");
|
||||||
|
const ConfigOptionFloat* parking_pos_retraction = config.option<ConfigOptionFloat>("parking_pos_retraction");
|
||||||
|
const ConfigOptionFloat* extra_loading_move = config.option<ConfigOptionFloat>("extra_loading_move");
|
||||||
|
|
||||||
|
if (single_extruder_multi_material != nullptr && wipe_tower != nullptr && parking_pos_retraction != nullptr && extra_loading_move != nullptr) {
|
||||||
|
if (single_extruder_multi_material->value && m_result.extruders_count > 1 && wipe_tower->value) {
|
||||||
|
m_parking_position = float(parking_pos_retraction->value);
|
||||||
|
m_extra_loading_move = float(extra_loading_move->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool use_machine_limits = false;
|
bool use_machine_limits = false;
|
||||||
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
|
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
|
||||||
if (machine_limits_usage != nullptr)
|
if (machine_limits_usage != nullptr)
|
||||||
|
@ -1289,6 +1304,7 @@ void GCodeProcessor::reset()
|
||||||
m_options_z_corrector.reset();
|
m_options_z_corrector.reset();
|
||||||
|
|
||||||
m_spiral_vase_active = false;
|
m_spiral_vase_active = false;
|
||||||
|
m_kissslicer_toolchange_time_correction = 0.0f;
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
m_mm3_per_mm_compare.reset();
|
m_mm3_per_mm_compare.reset();
|
||||||
|
@ -1343,10 +1359,16 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
|
||||||
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||||
apply_config(config);
|
apply_config(config);
|
||||||
}
|
}
|
||||||
else if (m_producer == EProducer::Simplify3D)
|
else {
|
||||||
apply_config_simplify3d(filename);
|
m_result.extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
||||||
else if (m_producer == EProducer::SuperSlicer)
|
|
||||||
apply_config_superslicer(filename);
|
if (m_producer == EProducer::Simplify3D)
|
||||||
|
apply_config_simplify3d(filename);
|
||||||
|
else if (m_producer == EProducer::SuperSlicer)
|
||||||
|
apply_config_superslicer(filename);
|
||||||
|
else if (m_producer == EProducer::KissSlicer)
|
||||||
|
apply_config_kissslicer(filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process gcode
|
// process gcode
|
||||||
|
@ -1529,6 +1551,82 @@ void GCodeProcessor::apply_config_superslicer(const std::string& filename)
|
||||||
apply_config(config);
|
apply_config(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCodeProcessor::apply_config_kissslicer(const std::string& filename)
|
||||||
|
{
|
||||||
|
size_t found_counter = 0;
|
||||||
|
m_parser.parse_file_raw(filename, [this, &found_counter](GCodeReader& reader, const char* begin, const char* end) {
|
||||||
|
auto detect_flavor = [this](const std::string_view comment) {
|
||||||
|
static const std::string search_str = "firmware_type";
|
||||||
|
const size_t pos = comment.find(search_str);
|
||||||
|
if (pos != comment.npos) {
|
||||||
|
std::vector<std::string> elements;
|
||||||
|
boost::split(elements, comment, boost::is_any_of("="));
|
||||||
|
if (elements.size() == 2) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (std::stoi(elements[1]))
|
||||||
|
{
|
||||||
|
default: { break; }
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3: { m_flavor = gcfMarlinLegacy; break; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// invalid data, do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto detect_printer = [this](const std::string_view comment) {
|
||||||
|
static const std::string search_str = "printer_name";
|
||||||
|
const size_t pos = comment.find(search_str);
|
||||||
|
if (pos != comment.npos) {
|
||||||
|
std::vector<std::string> elements;
|
||||||
|
boost::split(elements, comment, boost::is_any_of("="));
|
||||||
|
if (elements.size() == 2) {
|
||||||
|
elements[1] = boost::to_upper_copy(elements[1]);
|
||||||
|
if (boost::contains(elements[1], "MK2.5") || boost::contains(elements[1], "MK3"))
|
||||||
|
m_kissslicer_toolchange_time_correction = 18.0f; // MMU2
|
||||||
|
else if (boost::contains(elements[1], "MK2"))
|
||||||
|
m_kissslicer_toolchange_time_correction = 5.0f; // MMU
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
begin = skip_whitespaces(begin, end);
|
||||||
|
if (begin != end) {
|
||||||
|
if (*begin == ';') {
|
||||||
|
// Comment.
|
||||||
|
begin = skip_whitespaces(++begin, end);
|
||||||
|
end = remove_eols(begin, end);
|
||||||
|
if (begin != end) {
|
||||||
|
const std::string_view comment(begin, end - begin);
|
||||||
|
if (detect_flavor(comment) || detect_printer(comment))
|
||||||
|
++found_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we got the data,
|
||||||
|
// force early exit to avoid parsing the entire file
|
||||||
|
if (found_counter == 2)
|
||||||
|
m_parser.quit_parsing();
|
||||||
|
}
|
||||||
|
else if (*begin == 'M' || *begin == 'G')
|
||||||
|
// the header has been fully parsed, quit search
|
||||||
|
m_parser.quit_parsing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m_parser.reset();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
|
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
|
||||||
{
|
{
|
||||||
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
|
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
|
||||||
|
@ -2559,7 +2657,7 @@ bool GCodeProcessor::process_bambustudio_tags(const std::string_view comment)
|
||||||
bool GCodeProcessor::detect_producer(const std::string_view comment)
|
bool GCodeProcessor::detect_producer(const std::string_view comment)
|
||||||
{
|
{
|
||||||
for (const auto& [id, search_string] : Producers) {
|
for (const auto& [id, search_string] : Producers) {
|
||||||
size_t pos = comment.find(search_string);
|
const size_t pos = comment.find(search_string);
|
||||||
if (pos != comment.npos) {
|
if (pos != comment.npos) {
|
||||||
m_producer = id;
|
m_producer = id;
|
||||||
BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
|
BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
|
||||||
|
@ -3615,10 +3713,12 @@ void GCodeProcessor::process_T(const std::string_view command)
|
||||||
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
||||||
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
||||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
unsigned char id = static_cast<unsigned char>(eid);
|
unsigned char id = static_cast<unsigned char>(eid);
|
||||||
if (m_extruder_id != id) {
|
if (m_extruder_id != id) {
|
||||||
if (id >= m_result.extruder_colors.size())
|
if (((m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) && id >= m_result.extruders_count) ||
|
||||||
|
((m_producer != EProducer::PrusaSlicer && m_producer != EProducer::Slic3rPE && m_producer != EProducer::Slic3r) && id >= m_result.extruder_colors.size()))
|
||||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
|
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
|
||||||
else {
|
else {
|
||||||
unsigned char old_extruder_id = m_extruder_id;
|
unsigned char old_extruder_id = m_extruder_id;
|
||||||
|
@ -3631,6 +3731,8 @@ void GCodeProcessor::process_T(const std::string_view command)
|
||||||
float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
|
float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
|
||||||
m_time_processor.extruder_unloaded = false;
|
m_time_processor.extruder_unloaded = false;
|
||||||
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
|
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
|
||||||
|
if (m_producer == EProducer::KissSlicer && m_flavor == gcfMarlinLegacy)
|
||||||
|
extra_time += m_kissslicer_toolchange_time_correction;
|
||||||
simulate_st_synchronize(extra_time);
|
simulate_st_synchronize(extra_time);
|
||||||
|
|
||||||
m_result.extruders_count = std::max<size_t>(m_result.extruders_count, m_extruder_id + 1);
|
m_result.extruders_count = std::max<size_t>(m_result.extruders_count, m_extruder_id + 1);
|
||||||
|
|
|
@ -575,6 +575,7 @@ namespace Slic3r {
|
||||||
OptionsZCorrector m_options_z_corrector;
|
OptionsZCorrector m_options_z_corrector;
|
||||||
size_t m_last_default_color_id;
|
size_t m_last_default_color_id;
|
||||||
bool m_spiral_vase_active;
|
bool m_spiral_vase_active;
|
||||||
|
float m_kissslicer_toolchange_time_correction;
|
||||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
|
@ -648,6 +649,7 @@ namespace Slic3r {
|
||||||
void apply_config(const DynamicPrintConfig& config);
|
void apply_config(const DynamicPrintConfig& config);
|
||||||
void apply_config_simplify3d(const std::string& filename);
|
void apply_config_simplify3d(const std::string& filename);
|
||||||
void apply_config_superslicer(const std::string& filename);
|
void apply_config_superslicer(const std::string& filename);
|
||||||
|
void apply_config_kissslicer(const std::string& filename);
|
||||||
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
|
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
|
||||||
|
|
||||||
// Process tags embedded into comments
|
// Process tags embedded into comments
|
||||||
|
|
|
@ -395,8 +395,7 @@ struct GlobalModelInfo {
|
||||||
;
|
;
|
||||||
|
|
||||||
//Extract perimeter polygons of the given layer
|
//Extract perimeter polygons of the given layer
|
||||||
Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition configured_seam_preference,
|
Polygons extract_perimeter_polygons(const Layer *layer, std::vector<const LayerRegion*> &corresponding_regions_out) {
|
||||||
std::vector<const LayerRegion*> &corresponding_regions_out) {
|
|
||||||
Polygons polygons;
|
Polygons polygons;
|
||||||
for (const LayerRegion *layer_region : layer->regions()) {
|
for (const LayerRegion *layer_region : layer->regions()) {
|
||||||
for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) {
|
for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) {
|
||||||
|
@ -411,9 +410,7 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == ExtrusionRole::erExternalPerimeter
|
if (role == ExtrusionRole::erExternalPerimeter) {
|
||||||
|| (is_perimeter(role)
|
|
||||||
&& configured_seam_preference == spRandom)) { //for random seam alignment, extract all perimeters
|
|
||||||
Points p;
|
Points p;
|
||||||
perimeter->collect_points(p);
|
perimeter->collect_points(p);
|
||||||
polygons.emplace_back(std::move(p));
|
polygons.emplace_back(std::move(p));
|
||||||
|
@ -1044,14 +1041,13 @@ public:
|
||||||
// Parallel process and extract each perimeter polygon of the given print object.
|
// Parallel process and extract each perimeter polygon of the given print object.
|
||||||
// Gather SeamCandidates of each layer into vector and build KDtree over them
|
// Gather SeamCandidates of each layer into vector and build KDtree over them
|
||||||
// Store results in the SeamPlacer variables m_seam_per_object
|
// Store results in the SeamPlacer variables m_seam_per_object
|
||||||
void SeamPlacer::gather_seam_candidates(const PrintObject *po,
|
void SeamPlacer::gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info) {
|
||||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference) {
|
|
||||||
using namespace SeamPlacerImpl;
|
using namespace SeamPlacerImpl;
|
||||||
PrintObjectSeamData &seam_data = m_seam_per_object.emplace(po, PrintObjectSeamData { }).first->second;
|
PrintObjectSeamData &seam_data = m_seam_per_object.emplace(po, PrintObjectSeamData { }).first->second;
|
||||||
seam_data.layers.resize(po->layer_count());
|
seam_data.layers.resize(po->layer_count());
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, po->layers().size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, po->layers().size()),
|
||||||
[po, configured_seam_preference, &global_model_info, &seam_data]
|
[po, &global_model_info, &seam_data]
|
||||||
(tbb::blocked_range<size_t> r) {
|
(tbb::blocked_range<size_t> r) {
|
||||||
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
|
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
|
||||||
PrintObjectSeamData::LayerSeams &layer_seams = seam_data.layers[layer_idx];
|
PrintObjectSeamData::LayerSeams &layer_seams = seam_data.layers[layer_idx];
|
||||||
|
@ -1059,7 +1055,7 @@ void SeamPlacer::gather_seam_candidates(const PrintObject *po,
|
||||||
auto unscaled_z = layer->slice_z;
|
auto unscaled_z = layer->slice_z;
|
||||||
std::vector<const LayerRegion*> regions;
|
std::vector<const LayerRegion*> regions;
|
||||||
//NOTE corresponding region ptr may be null, if the layer has zero perimeters
|
//NOTE corresponding region ptr may be null, if the layer has zero perimeters
|
||||||
Polygons polygons = extract_perimeter_polygons(layer, configured_seam_preference, regions);
|
Polygons polygons = extract_perimeter_polygons(layer, regions);
|
||||||
for (size_t poly_index = 0; poly_index < polygons.size(); ++poly_index) {
|
for (size_t poly_index = 0; poly_index < polygons.size(); ++poly_index) {
|
||||||
process_perimeter_polygon(polygons[poly_index], unscaled_z,
|
process_perimeter_polygon(polygons[poly_index], unscaled_z,
|
||||||
regions[poly_index], global_model_info, layer_seams);
|
regions[poly_index], global_model_info, layer_seams);
|
||||||
|
@ -1468,7 +1464,7 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
|
||||||
throw_if_canceled_func();
|
throw_if_canceled_func();
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
<< "SeamPlacer: gather_seam_candidates: start";
|
<< "SeamPlacer: gather_seam_candidates: start";
|
||||||
gather_seam_candidates(po, global_model_info, configured_seam_preference);
|
gather_seam_candidates(po, global_model_info);
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
<< "SeamPlacer: gather_seam_candidates: end";
|
<< "SeamPlacer: gather_seam_candidates: end";
|
||||||
throw_if_canceled_func();
|
throw_if_canceled_func();
|
||||||
|
@ -1533,7 +1529,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
|
||||||
const size_t layer_index = layer->id() - po->slicing_parameters().raft_layers();
|
const size_t layer_index = layer->id() - po->slicing_parameters().raft_layers();
|
||||||
const double unscaled_z = layer->slice_z;
|
const double unscaled_z = layer->slice_z;
|
||||||
|
|
||||||
auto get_next_loop_point = [&loop](ExtrusionLoop::ClosestPathPoint current) {
|
auto get_next_loop_point = [loop](ExtrusionLoop::ClosestPathPoint current) {
|
||||||
current.segment_idx += 1;
|
current.segment_idx += 1;
|
||||||
if (current.segment_idx >= loop.paths[current.path_idx].polyline.points.size()) {
|
if (current.segment_idx >= loop.paths[current.path_idx].polyline.points.size()) {
|
||||||
current.path_idx = next_idx_modulo(current.path_idx, loop.paths.size());
|
current.path_idx = next_idx_modulo(current.path_idx, loop.paths.size());
|
||||||
|
@ -1556,7 +1552,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
|
||||||
size_t points_count = std::accumulate(loop.paths.begin(), loop.paths.end(), 0, [](size_t acc,const ExtrusionPath& p) {
|
size_t points_count = std::accumulate(loop.paths.begin(), loop.paths.end(), 0, [](size_t acc,const ExtrusionPath& p) {
|
||||||
return acc + p.polyline.points.size();
|
return acc + p.polyline.points.size();
|
||||||
});
|
});
|
||||||
for (size_t _ = 0; _ < points_count; ++_) {
|
for (size_t i = 0; i < points_count; ++i) {
|
||||||
Vec2f unscaled_p = unscaled<float>(closest_point.foot_pt);
|
Vec2f unscaled_p = unscaled<float>(closest_point.foot_pt);
|
||||||
closest_perimeter_point_index = find_closest_point(*layer_perimeters.points_tree.get(),
|
closest_perimeter_point_index = find_closest_point(*layer_perimeters.points_tree.get(),
|
||||||
to_3d(unscaled_p, float(unscaled_z)));
|
to_3d(unscaled_p, float(unscaled_z)));
|
||||||
|
@ -1586,13 +1582,12 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
|
||||||
|
|
||||||
Point seam_point = Point::new_scale(seam_position.x(), seam_position.y());
|
Point seam_point = Point::new_scale(seam_position.x(), seam_position.y());
|
||||||
|
|
||||||
if (const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter
|
||||||
(po->config().seam_position == spNearest || po->config().seam_position == spAligned) &&
|
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
||||||
loop.role() == ExtrusionRole::erPerimeter && //Hopefully internal perimeter
|
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false);
|
||||||
(seam_position - perimeter_point.position).squaredNorm() < 4.0f && // seam is on perimeter point
|
// determine depth of the seam point.
|
||||||
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
|
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
|
||||||
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
|
float beta_angle = cos(perimeter_point.local_ccw_angle / 2.0f);
|
||||||
// the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does)
|
|
||||||
size_t index_of_prev =
|
size_t index_of_prev =
|
||||||
seam_index == perimeter_point.perimeter.start_index ?
|
seam_index == perimeter_point.perimeter.start_index ?
|
||||||
perimeter_point.perimeter.end_index - 1 :
|
perimeter_point.perimeter.end_index - 1 :
|
||||||
|
@ -1602,18 +1597,46 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern
|
||||||
perimeter_point.perimeter.start_index :
|
perimeter_point.perimeter.start_index :
|
||||||
seam_index + 1;
|
seam_index + 1;
|
||||||
|
|
||||||
Vec2f dir_to_middle =
|
if ((seam_position - perimeter_point.position).squaredNorm() < depth && // seam is on perimeter point
|
||||||
((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized()
|
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
|
||||||
+ (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized())
|
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
|
||||||
* 0.5;
|
// the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does)
|
||||||
|
Vec2f dir_to_middle =
|
||||||
|
((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized()
|
||||||
|
+ (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized())
|
||||||
|
* 0.5;
|
||||||
|
depth = 1.4142 * depth / beta_angle;
|
||||||
|
// There are some nice geometric identities in determination of the correct depth of new seam point.
|
||||||
|
//overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed.
|
||||||
|
Vec2f final_pos = perimeter_point.position.head<2>() + depth * dir_to_middle;
|
||||||
|
projected_point = loop.get_closest_path_and_point(Point::new_scale(final_pos.x(), final_pos.y()), false);
|
||||||
|
} else { // not concave angle, in that case the nearest point is the good candidate
|
||||||
|
// but for staggering, we also need to recompute depth of the inner perimter, because in convex corners, the distance is larger than layer width
|
||||||
|
// we want the perpendicular depth, not distance to nearest point
|
||||||
|
depth = depth * beta_angle / 1.4142;
|
||||||
|
}
|
||||||
|
|
||||||
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, true);
|
seam_point = projected_point.foot_pt;
|
||||||
//get closest projected point, determine depth of the seam point.
|
|
||||||
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
|
//lastly, for internal perimeters, do the staggering if requested
|
||||||
float angle_factor = cos(-perimeter_point.local_ccw_angle / 2.0f); // There are some nice geometric identities in determination of the correct depth of new seam point.
|
if (po->config().staggered_inner_seams && loop.length() > 0.0) {
|
||||||
//overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed.
|
//fix depth, it is sometimes strongly underestimated
|
||||||
Vec2f final_pos = perimeter_point.position.head<2>() + (1.4142 * depth / angle_factor) * dir_to_middle;
|
depth = std::max(loop.paths[projected_point.path_idx].width, depth);
|
||||||
seam_point = Point::new_scale(final_pos.x(), final_pos.y());
|
|
||||||
|
while (depth > 0.0f) {
|
||||||
|
auto next_point = get_next_loop_point(projected_point);
|
||||||
|
Vec2f a = unscale(projected_point.foot_pt).cast<float>();
|
||||||
|
Vec2f b = unscale(next_point.foot_pt).cast<float>();
|
||||||
|
float dist = (a - b).norm();
|
||||||
|
if (dist > depth) {
|
||||||
|
Vec2f final_pos = a + (b - a) * depth / dist;
|
||||||
|
next_point.foot_pt = Point::new_scale(final_pos.x(), final_pos.y());
|
||||||
|
}
|
||||||
|
depth -= dist;
|
||||||
|
projected_point = next_point;
|
||||||
|
}
|
||||||
|
seam_point = projected_point.foot_pt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
|
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
|
||||||
|
|
|
@ -143,8 +143,7 @@ public:
|
||||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info,
|
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||||
const SeamPosition configured_seam_preference);
|
|
||||||
void calculate_candidates_visibility(const PrintObject *po,
|
void calculate_candidates_visibility(const PrintObject *po,
|
||||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||||
|
|
|
@ -550,12 +550,16 @@ void Transformation::set_rotation(Axis axis, double rotation)
|
||||||
Vec3d Transformation::get_scaling_factor() const
|
Vec3d Transformation::get_scaling_factor() const
|
||||||
{
|
{
|
||||||
const Transform3d scale = extract_scale(m_matrix);
|
const Transform3d scale = extract_scale(m_matrix);
|
||||||
return { scale(0, 0), scale(1, 1), scale(2, 2) };
|
return { std::abs(scale(0, 0)), std::abs(scale(1, 1)), std::abs(scale(2, 2)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform3d Transformation::get_scaling_factor_matrix() const
|
Transform3d Transformation::get_scaling_factor_matrix() const
|
||||||
{
|
{
|
||||||
return extract_scale(m_matrix);
|
Transform3d scale = extract_scale(m_matrix);
|
||||||
|
scale(0, 0) = std::abs(scale(0, 0));
|
||||||
|
scale(1, 1) = std::abs(scale(1, 1));
|
||||||
|
scale(2, 2) = std::abs(scale(2, 2));
|
||||||
|
return scale;
|
||||||
}
|
}
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
@ -577,6 +581,8 @@ void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
||||||
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
||||||
{
|
{
|
||||||
#if ENABLE_WORLD_COORDINATE
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
assert(scaling_factor > 0.0);
|
||||||
|
|
||||||
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||||
scale(axis, axis) = scaling_factor;
|
scale(axis, axis) = scaling_factor;
|
||||||
|
|
||||||
|
@ -600,8 +606,11 @@ Vec3d Transformation::get_mirror() const
|
||||||
|
|
||||||
Transform3d Transformation::get_mirror_matrix() const
|
Transform3d Transformation::get_mirror_matrix() const
|
||||||
{
|
{
|
||||||
const Vec3d scale = get_scaling_factor();
|
Transform3d scale = extract_scale(m_matrix);
|
||||||
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
|
scale(0, 0) = scale(0, 0) / std::abs(scale(0, 0));
|
||||||
|
scale(1, 1) = scale(1, 1) / std::abs(scale(1, 1));
|
||||||
|
scale(2, 2) = scale(2, 2) / std::abs(scale(2, 2));
|
||||||
|
return scale;
|
||||||
}
|
}
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
|
@ -617,13 +626,17 @@ void Transformation::set_mirror(const Vec3d& mirror)
|
||||||
copy(i) /= abs_mirror(i);
|
copy(i) /= abs_mirror(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3d curr_scale = get_scaling_factor();
|
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||||
const Vec3d signs = curr_scale.cwiseProduct(copy);
|
const Vec3d curr_scales = { scale(0, 0), scale(1, 1), scale(2, 2) };
|
||||||
set_scaling_factor({
|
const Vec3d signs = curr_scales.cwiseProduct(copy);
|
||||||
signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(),
|
|
||||||
signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(),
|
if (signs[0] < 0.0) scale(0, 0) = -scale(0, 0);
|
||||||
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
|
if (signs[1] < 0.0) scale(1, 1) = -scale(1, 1);
|
||||||
});
|
if (signs[2] < 0.0) scale(2, 2) = -scale(2, 2);
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation * scale;
|
||||||
|
m_matrix.translation() = offset;
|
||||||
#else
|
#else
|
||||||
set_mirror(X, mirror.x());
|
set_mirror(X, mirror.x());
|
||||||
set_mirror(Y, mirror.y());
|
set_mirror(Y, mirror.y());
|
||||||
|
@ -640,9 +653,15 @@ void Transformation::set_mirror(Axis axis, double mirror)
|
||||||
mirror /= abs_mirror;
|
mirror /= abs_mirror;
|
||||||
|
|
||||||
#if ENABLE_WORLD_COORDINATE
|
#if ENABLE_WORLD_COORDINATE
|
||||||
const double curr_scale = get_scaling_factor(axis);
|
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||||
|
const double curr_scale = scale(axis, axis);
|
||||||
const double sign = curr_scale * mirror;
|
const double sign = curr_scale * mirror;
|
||||||
set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale);
|
|
||||||
|
if (sign < 0.0) scale(axis, axis) = -scale(axis, axis);
|
||||||
|
|
||||||
|
const Vec3d offset = get_offset();
|
||||||
|
m_matrix = rotation * scale;
|
||||||
|
m_matrix.translation() = offset;
|
||||||
#else
|
#else
|
||||||
if (m_mirror(axis) != mirror) {
|
if (m_mirror(axis) != mirror) {
|
||||||
m_mirror(axis) = mirror;
|
m_mirror(axis) = mirror;
|
||||||
|
@ -746,7 +765,6 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const
|
||||||
{
|
{
|
||||||
Transformation copy(*this);
|
Transformation copy(*this);
|
||||||
copy.reset_scaling_factor();
|
copy.reset_scaling_factor();
|
||||||
copy.reset_mirror();
|
|
||||||
return copy.get_matrix();
|
return copy.get_matrix();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -235,7 +235,7 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext_lines.back().p == ext_lines.front().p) // Connect endpoints.
|
if (ext_lines.back().p == ext_lines.front().p) // Connect endpoints.
|
||||||
out.back().p = out.front().p;
|
out.front().p = out.back().p;
|
||||||
|
|
||||||
if (out.size() >= 3)
|
if (out.size() >= 3)
|
||||||
ext_lines.junctions = std::move(out);
|
ext_lines.junctions = std::move(out);
|
||||||
|
|
|
@ -528,4 +528,23 @@ bool contains(const Polygons &polygons, const Point &p, bool border_result)
|
||||||
return (poly_count_inside % 2) == 1;
|
return (poly_count_inside % 2) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Polygon make_circle(double radius, double error)
|
||||||
|
{
|
||||||
|
double angle = 2. * acos(1. - error / radius);
|
||||||
|
size_t num_segments = size_t(ceil(2. * M_PI / angle));
|
||||||
|
return make_circle_num_segments(radius, num_segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygon make_circle_num_segments(double radius, size_t num_segments)
|
||||||
|
{
|
||||||
|
Polygon out;
|
||||||
|
out.points.reserve(num_segments);
|
||||||
|
double angle_inc = 2.0 * M_PI / num_segments;
|
||||||
|
for (size_t i = 0; i < num_segments; ++ i) {
|
||||||
|
const double angle = angle_inc * i;
|
||||||
|
out.points.emplace_back(coord_t(cos(angle) * radius), coord_t(sin(angle) * radius));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,9 @@ inline Polygons to_polygons(std::vector<Points> &&paths)
|
||||||
// Returns true if inside. Returns border_result if on boundary.
|
// Returns true if inside. Returns border_result if on boundary.
|
||||||
bool contains(const Polygons& polygons, const Point& p, bool border_result = true);
|
bool contains(const Polygons& polygons, const Point& p, bool border_result = true);
|
||||||
|
|
||||||
|
Polygon make_circle(double radius, double error);
|
||||||
|
Polygon make_circle_num_segments(double radius, size_t num_segments);
|
||||||
|
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
|
|
|
@ -421,7 +421,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
|
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
|
||||||
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
|
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
|
||||||
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
"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",
|
"seam_position","staggered_inner_seams", "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",
|
"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",
|
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
|
||||||
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
|
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
|
||||||
|
@ -1055,12 +1055,12 @@ const std::string& PresetCollection::get_suffix_modified() {
|
||||||
|
|
||||||
// Return a preset by its name. If the preset is active, a temporary copy is returned.
|
// Return a preset by its name. If the preset is active, a temporary copy is returned.
|
||||||
// If a preset is not found by its name, null is returned.
|
// If a preset is not found by its name, null is returned.
|
||||||
Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found)
|
Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found, bool respect_active_preset /*= true*/)
|
||||||
{
|
{
|
||||||
Preset key(m_type, name, false);
|
Preset key(m_type, name, false);
|
||||||
auto it = this->find_preset_internal(name);
|
auto it = this->find_preset_internal(name);
|
||||||
// Ensure that a temporary copy is returned if the preset found is currently selected.
|
// 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(), respect_active_preset) :
|
||||||
first_visible_if_not_found ? &this->first_visible() : nullptr;
|
first_visible_if_not_found ? &this->first_visible() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1876,13 +1876,23 @@ bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicalPrinterCollection::rename_preset_in_printers(const std::string& old_preset_name, const std::string& new_preset_name)
|
||||||
|
{
|
||||||
|
for (PhysicalPrinter& printer : m_printers)
|
||||||
|
if (printer.delete_preset(old_preset_name)) {
|
||||||
|
printer.add_preset(new_preset_name);
|
||||||
|
printer.update_preset_names_in_config();
|
||||||
|
printer.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get list of printers which have more than one preset and "preset_names" preset is one of them
|
// Get list of printers which have more than one preset and "preset_names" preset is one of them
|
||||||
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name)
|
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name, bool respect_only_preset /*= true*/)
|
||||||
{
|
{
|
||||||
std::vector<std::string> printers;
|
std::vector<std::string> printers;
|
||||||
|
|
||||||
for (auto printer : m_printers) {
|
for (auto printer : m_printers) {
|
||||||
if (printer.preset_names.size() == 1)
|
if (!respect_only_preset && printer.preset_names.size() == 1)
|
||||||
continue;
|
continue;
|
||||||
if (printer.preset_names.find(preset_name) != printer.preset_names.end())
|
if (printer.preset_names.find(preset_name) != printer.preset_names.end())
|
||||||
printers.emplace_back(printer.name);
|
printers.emplace_back(printer.name);
|
||||||
|
|
|
@ -392,8 +392,8 @@ public:
|
||||||
const Preset& default_preset(size_t idx = 0) const { assert(idx < m_num_default_presets); return m_presets[idx]; }
|
const Preset& default_preset(size_t idx = 0) const { assert(idx < m_num_default_presets); return m_presets[idx]; }
|
||||||
virtual const Preset& default_preset_for(const DynamicPrintConfig & /* config */) const { return this->default_preset(); }
|
virtual const Preset& default_preset_for(const DynamicPrintConfig & /* config */) const { return this->default_preset(); }
|
||||||
// Return a preset by an index. If the preset is active, a temporary copy is returned.
|
// Return a preset by an index. If the preset is active, a temporary copy is returned.
|
||||||
Preset& preset(size_t idx) { return (idx == m_idx_selected) ? m_edited_preset : m_presets[idx]; }
|
Preset& preset(size_t idx, bool respect_active_preset = true) { return (idx == m_idx_selected && respect_active_preset) ? m_edited_preset : m_presets[idx]; }
|
||||||
const Preset& preset(size_t idx) const { return const_cast<PresetCollection*>(this)->preset(idx); }
|
const Preset& preset(size_t idx, bool respect_active_preset = true) const { return const_cast<PresetCollection*>(this)->preset(idx); }
|
||||||
void discard_current_changes() {
|
void discard_current_changes() {
|
||||||
m_presets[m_idx_selected].reset_dirty();
|
m_presets[m_idx_selected].reset_dirty();
|
||||||
m_edited_preset = m_presets[m_idx_selected];
|
m_edited_preset = m_presets[m_idx_selected];
|
||||||
|
@ -403,9 +403,9 @@ public:
|
||||||
|
|
||||||
// Return a preset by its name. If the preset is active, a temporary copy is returned.
|
// Return a preset by its name. If the preset is active, a temporary copy is returned.
|
||||||
// If a preset is not found by its name, null is returned.
|
// If a preset is not found by its name, null is returned.
|
||||||
Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false);
|
Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false, bool respect_active_preset = true);
|
||||||
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false) const
|
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false, bool respect_active_preset = true) const
|
||||||
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found); }
|
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found, respect_active_preset); }
|
||||||
|
|
||||||
size_t first_visible_idx() const;
|
size_t first_visible_idx() const;
|
||||||
// Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible.
|
// Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible.
|
||||||
|
@ -734,9 +734,9 @@ public:
|
||||||
// If there is last preset for the printer and first_check== false, then delete this printer
|
// If there is last preset for the printer and first_check== false, then delete this printer
|
||||||
// returns true if all presets were deleted successfully.
|
// returns true if all presets were deleted successfully.
|
||||||
bool delete_preset_from_printers(const std::string& preset_name);
|
bool delete_preset_from_printers(const std::string& preset_name);
|
||||||
|
void rename_preset_in_printers(const std::string& old_name, const std::string& new_name);
|
||||||
// Get list of printers which have more than one preset and "preset_names" preset is one of them
|
// Get list of printers which have more than one preset and "preset_names" preset is one of them
|
||||||
std::vector<std::string> get_printers_with_preset( const std::string &preset_name);
|
std::vector<std::string> get_printers_with_preset( const std::string &preset_name, bool respect_only_preset = true);
|
||||||
// Get list of printers which has only "preset_names" preset
|
// Get list of printers which has only "preset_names" preset
|
||||||
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);
|
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);
|
||||||
|
|
||||||
|
|
|
@ -825,6 +825,8 @@ void Print::process()
|
||||||
obj->infill();
|
obj->infill();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->ironing();
|
obj->ironing();
|
||||||
|
for (PrintObject *obj : m_objects)
|
||||||
|
obj->generate_support_spots();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
if (this->set_started(psWipeTower)) {
|
if (this->set_started(psWipeTower)) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ enum PrintStep : unsigned int {
|
||||||
|
|
||||||
enum PrintObjectStep : unsigned int {
|
enum PrintObjectStep : unsigned int {
|
||||||
posSlice, posPerimeters, posPrepareInfill,
|
posSlice, posPerimeters, posPrepareInfill,
|
||||||
posInfill, posIroning, posSupportMaterial, posCount,
|
posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A PrintRegion object represents a group of volumes to print
|
// A PrintRegion object represents a group of volumes to print
|
||||||
|
@ -381,6 +381,7 @@ private:
|
||||||
void prepare_infill();
|
void prepare_infill();
|
||||||
void infill();
|
void infill();
|
||||||
void ironing();
|
void ironing();
|
||||||
|
void generate_support_spots();
|
||||||
void generate_support_material();
|
void generate_support_material();
|
||||||
|
|
||||||
void slice_volumes();
|
void slice_volumes();
|
||||||
|
|
|
@ -1195,8 +1195,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
update_apply_status(false);
|
update_apply_status(false);
|
||||||
}
|
}
|
||||||
// Invalidate just the supports step.
|
// Invalidate just the supports step.
|
||||||
for (const PrintObjectStatus &print_object_status : print_objects_range)
|
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
||||||
|
update_apply_status(print_object_status.print_object->invalidate_step(posSupportSpotsSearch));
|
||||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
||||||
|
}
|
||||||
if (supports_differ) {
|
if (supports_differ) {
|
||||||
// Copy just the support volumes.
|
// Copy just the support volumes.
|
||||||
model_volume_list_update_supports(model_object, model_object_new);
|
model_volume_list_update_supports(model_object, model_object_new);
|
||||||
|
|
|
@ -2253,6 +2253,12 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->mode = comSimple;
|
def->mode = comSimple;
|
||||||
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned));
|
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned));
|
||||||
|
|
||||||
|
def = this->add("staggered_inner_seams", coBool);
|
||||||
|
def->label = L("Staggered inner seams");
|
||||||
|
def->tooltip = L("This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern.");
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
def = this->add("seam_preferred_direction", coFloat);
|
def = this->add("seam_preferred_direction", coFloat);
|
||||||
// def->gui_type = ConfigOptionDef::GUIType::slider;
|
// def->gui_type = ConfigOptionDef::GUIType::slider;
|
||||||
|
|
|
@ -503,6 +503,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionFloat, raft_first_layer_expansion))
|
((ConfigOptionFloat, raft_first_layer_expansion))
|
||||||
((ConfigOptionInt, raft_layers))
|
((ConfigOptionInt, raft_layers))
|
||||||
((ConfigOptionEnum<SeamPosition>, seam_position))
|
((ConfigOptionEnum<SeamPosition>, seam_position))
|
||||||
|
((ConfigOptionBool, staggered_inner_seams))
|
||||||
// ((ConfigOptionFloat, seam_preferred_direction))
|
// ((ConfigOptionFloat, seam_preferred_direction))
|
||||||
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
|
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
|
||||||
((ConfigOptionFloat, slice_closing_radius))
|
((ConfigOptionFloat, slice_closing_radius))
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "Fill/FillAdaptive.hpp"
|
#include "Fill/FillAdaptive.hpp"
|
||||||
#include "Fill/FillLightning.hpp"
|
#include "Fill/FillLightning.hpp"
|
||||||
#include "Format/STL.hpp"
|
#include "Format/STL.hpp"
|
||||||
|
#include "SupportSpotsGenerator.hpp"
|
||||||
|
#include "TriangleSelectorWrapper.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -394,6 +397,65 @@ void PrintObject::ironing()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::vector<size_t> problematic_layers = SupportSpotsGenerator::quick_search(this);
|
||||||
|
if (!problematic_layers.empty()) {
|
||||||
|
std::cout << "Object needs supports" << std::endl;
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
L("Supportable issues found. Consider enabling supports for this object"));
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
L("Supportable issues found. Consider enabling supports for this object"));
|
||||||
|
for (size_t index = 0; index < std::min(problematic_layers.size(), size_t(4)); ++index) {
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
format(L("Layer with issues: %1%"), problematic_layers[index] + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void PrintObject::generate_support_spots()
|
||||||
|
{
|
||||||
|
if (this->set_started(posSupportSpotsSearch)) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< "Searching support spots - start";
|
||||||
|
m_print->set_status(75, L("Searching support spots"));
|
||||||
|
if (this->m_config.support_material && !this->m_config.support_material_auto &&
|
||||||
|
std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(),
|
||||||
|
[](const ModelVolume* mv){return mv->supported_facets.empty();})
|
||||||
|
) {
|
||||||
|
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
|
||||||
|
SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this, params);
|
||||||
|
auto obj_transform = this->trafo_centered();
|
||||||
|
for (ModelVolume *model_volume : this->model_object()->volumes) {
|
||||||
|
if (model_volume->is_model_part()) {
|
||||||
|
Transform3d mesh_transformation = obj_transform * model_volume->get_matrix();
|
||||||
|
Transform3d inv_transform = mesh_transformation.inverse();
|
||||||
|
TriangleSelectorWrapper selector { model_volume->mesh(), mesh_transformation};
|
||||||
|
|
||||||
|
for (const SupportSpotsGenerator::SupportPoint &support_point : issues.support_points) {
|
||||||
|
Vec3f point = Vec3f(inv_transform.cast<float>() * support_point.position);
|
||||||
|
Vec3f origin = Vec3f(
|
||||||
|
inv_transform.cast<float>() * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f));
|
||||||
|
selector.enforce_spot(point, origin, support_point.spot_radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
model_volume->supported_facets.set(selector.selector);
|
||||||
|
#if 0 //DEBUG export
|
||||||
|
indexed_triangle_set copy = model_volume->mesh().its;
|
||||||
|
its_transform(copy, obj_transform * model_transformation);
|
||||||
|
its_write_obj(copy,
|
||||||
|
debug_out_path(("model"+std::to_string(model_volume->id().id)+".obj").c_str()).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< "Searching support spots - end";
|
||||||
|
this->set_done(posSupportSpotsSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PrintObject::generate_support_material()
|
void PrintObject::generate_support_material()
|
||||||
{
|
{
|
||||||
if (this->set_started(posSupportMaterial)) {
|
if (this->set_started(posSupportMaterial)) {
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
#include "SVG.hpp"
|
#include "SVG.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#pragma message ("TODO: Wrap svg usages in DEBUG ifdef and remove the following include")
|
||||||
|
#include "SVG.hpp"
|
||||||
|
|
||||||
// #undef NDEBUG
|
// #undef NDEBUG
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
1257
src/libslic3r/SupportSpotsGenerator.cpp
Normal file
1257
src/libslic3r/SupportSpotsGenerator.cpp
Normal file
File diff suppressed because it is too large
Load diff
82
src/libslic3r/SupportSpotsGenerator.hpp
Normal file
82
src/libslic3r/SupportSpotsGenerator.hpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
|
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
|
|
||||||
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
namespace SupportSpotsGenerator {
|
||||||
|
|
||||||
|
struct Params {
|
||||||
|
Params(const std::vector<std::string> &filament_types) {
|
||||||
|
if (filament_types.size() > 1) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
||||||
|
}
|
||||||
|
if (filament_types.empty() || filament_types[0].empty()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< "SupportSpotsGenerator error: empty filament_type";
|
||||||
|
filament_type = std::string("PLA");
|
||||||
|
} else {
|
||||||
|
filament_type = filament_types[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
||||||
|
const float bridge_distance = 12.0f; //mm
|
||||||
|
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
||||||
|
const float overhang_angle_deg = 80.0f;
|
||||||
|
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
|
||||||
|
|
||||||
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
|
const float support_points_interface_radius = 1.5f; // mm
|
||||||
|
const float connections_min_considerable_area = 1.5f; //mm^2
|
||||||
|
const float small_parts_threshold = 5.0f; //mm^3
|
||||||
|
const float small_parts_support_points_interface_radius = 3.0f; // mm
|
||||||
|
|
||||||
|
std::string filament_type;
|
||||||
|
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
||||||
|
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
||||||
|
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
|
||||||
|
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
|
||||||
|
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
|
||||||
|
const float malformations_additive_conflict_extruder_force = 300.0f * gravity_constant; // for areas with possible high layered curled filaments
|
||||||
|
|
||||||
|
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
|
||||||
|
double get_bed_adhesion_yield_strength() const {
|
||||||
|
if (filament_type == "PLA") {
|
||||||
|
return 0.018 * 1e6;
|
||||||
|
} else if (filament_type == "PET" || filament_type == "PETG") {
|
||||||
|
return 0.3 * 1e6;
|
||||||
|
} else { //PLA default value - defensive approach, PLA has quite low adhesion
|
||||||
|
return 0.018 * 1e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//just return PLA adhesion value as value for supports
|
||||||
|
double get_support_spots_adhesion_strength() const {
|
||||||
|
return 0.018f * 1e6;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SupportPoint {
|
||||||
|
SupportPoint(const Vec3f &position, float force, float spot_radius, const Vec3f &direction);
|
||||||
|
Vec3f position;
|
||||||
|
float force;
|
||||||
|
float spot_radius;
|
||||||
|
Vec3f direction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Issues {
|
||||||
|
std::vector<SupportPoint> support_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::vector<size_t> quick_search(const PrintObject *po, const Params ¶ms);
|
||||||
|
Issues full_search(const PrintObject *po, const Params ¶ms);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */
|
|
@ -63,7 +63,6 @@ TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &pr
|
||||||
config.support_material_interface_layers.value) * this->layer_height :
|
config.support_material_interface_layers.value) * this->layer_height :
|
||||||
0;
|
0;
|
||||||
this->support_material_buildplate_only = config.support_material_buildplate_only;
|
this->support_material_buildplate_only = config.support_material_buildplate_only;
|
||||||
// this->support_xy_overrides_z =
|
|
||||||
this->support_xy_distance = scaled<coord_t>(config.support_material_xy_spacing.get_abs_value(external_perimeter_width));
|
this->support_xy_distance = scaled<coord_t>(config.support_material_xy_spacing.get_abs_value(external_perimeter_width));
|
||||||
// Separation of interfaces, it is likely smaller than support_xy_distance.
|
// Separation of interfaces, it is likely smaller than support_xy_distance.
|
||||||
this->support_xy_distance_overhang = std::min(this->support_xy_distance, scaled<coord_t>(0.5 * external_perimeter_width));
|
this->support_xy_distance_overhang = std::min(this->support_xy_distance, scaled<coord_t>(0.5 * external_perimeter_width));
|
||||||
|
@ -163,15 +162,9 @@ TreeModelVolumes::TreeModelVolumes(
|
||||||
}
|
}
|
||||||
|
|
||||||
const TreeSupport::TreeSupportSettings config{ m_layer_outlines[m_current_outline_idx].first };
|
const TreeSupport::TreeSupportSettings config{ m_layer_outlines[m_current_outline_idx].first };
|
||||||
if (! config.support_xy_overrides_z) {
|
m_current_min_xy_dist = config.xy_min_distance;
|
||||||
m_current_min_xy_dist = config.xy_min_distance;
|
m_current_min_xy_dist_delta = config.xy_distance - m_current_min_xy_dist;
|
||||||
if (TreeSupport::TreeSupportSettings::has_to_rely_on_min_xy_dist_only)
|
assert(m_current_min_xy_dist_delta >= 0);
|
||||||
m_current_min_xy_dist = std::max(m_current_min_xy_dist, coord_t(100));
|
|
||||||
m_current_min_xy_dist_delta = std::max(config.xy_distance - m_current_min_xy_dist, coord_t(0));
|
|
||||||
} else {
|
|
||||||
m_current_min_xy_dist = config.xy_distance;
|
|
||||||
m_current_min_xy_dist_delta = 0;
|
|
||||||
}
|
|
||||||
m_increase_until_radius = config.increase_radius_until_radius;
|
m_increase_until_radius = config.increase_radius_until_radius;
|
||||||
m_radius_0 = config.getRadius(0);
|
m_radius_0 = config.getRadius(0);
|
||||||
|
|
||||||
|
@ -436,12 +429,14 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
||||||
const int z_distance_top_layers = round_up_divide<int>(settings.support_top_distance, layer_height);
|
const int z_distance_top_layers = round_up_divide<int>(settings.support_top_distance, layer_height);
|
||||||
const LayerIndex max_required_layer = std::min<LayerIndex>(outlines.size(), max_layer_idx + std::max(coord_t(1), z_distance_top_layers));
|
const LayerIndex max_required_layer = std::min<LayerIndex>(outlines.size(), max_layer_idx + std::max(coord_t(1), z_distance_top_layers));
|
||||||
const LayerIndex min_layer_bottom = std::max<LayerIndex>(0, min_layer_last - int(z_distance_bottom_layers));
|
const LayerIndex min_layer_bottom = std::max<LayerIndex>(0, min_layer_last - int(z_distance_bottom_layers));
|
||||||
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist :
|
||||||
// not currently processing meshes as this delta will be added at request time.
|
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
||||||
// avoiding this would require saving each collision for each outline_idx separately.
|
// not currently processing meshes as this delta will be added at request time.
|
||||||
// and later for each avoidance... But avoidance calculation has to be for the whole scene and can NOT be done for each outline_idx separately and combined later.
|
// avoiding this would require saving each collision for each outline_idx separately.
|
||||||
// so avoiding this inaccuracy seems infeasible as it would require 2x the avoidance calculations => 0.5x the performance.
|
// and later for each avoidance... But avoidance calculation has to be for the whole scene and can NOT be done for each outline_idx separately and combined later.
|
||||||
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist : settings.support_xy_distance;
|
// so avoiding this inaccuracy seems infeasible as it would require 2x the avoidance calculations => 0.5x the performance.
|
||||||
|
//FIXME support_xy_distance is not corrected for "soluble" flag, see TreeSupportSettings constructor.
|
||||||
|
settings.support_xy_distance;
|
||||||
|
|
||||||
// 1) Calculate offsets of collision areas in parallel.
|
// 1) Calculate offsets of collision areas in parallel.
|
||||||
std::vector<Polygons> collision_areas_offsetted(max_required_layer + 1 - min_layer_bottom);
|
std::vector<Polygons> collision_areas_offsetted(max_required_layer + 1 - min_layer_bottom);
|
||||||
|
|
|
@ -64,10 +64,6 @@ struct TreeSupportMeshGroupSettings {
|
||||||
// The thickness of the support floors. This controls the number of dense layers that are printed on top of places of a model on which support rests.
|
// The thickness of the support floors. This controls the number of dense layers that are printed on top of places of a model on which support rests.
|
||||||
coord_t support_bottom_height { scaled<coord_t>(1.) };
|
coord_t support_bottom_height { scaled<coord_t>(1.) };
|
||||||
bool support_material_buildplate_only { false };
|
bool support_material_buildplate_only { false };
|
||||||
// Support Distance Priority
|
|
||||||
// Whether the Support X/Y Distance overrides the Support Z Distance or vice versa. When X/Y overrides Z the X/Y distance can push away
|
|
||||||
// the support from the model, influencing the actual Z distance to the overhang. We can disable this by not applying the X/Y distance around overhangs.
|
|
||||||
bool support_xy_overrides_z { false };
|
|
||||||
// Support X/Y Distance
|
// Support X/Y Distance
|
||||||
// Distance of the support structure from the print in the X/Y directions.
|
// Distance of the support structure from the print in the X/Y directions.
|
||||||
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
|
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
|
||||||
|
@ -75,7 +71,6 @@ struct TreeSupportMeshGroupSettings {
|
||||||
// Minimum Support X/Y Distance
|
// Minimum Support X/Y Distance
|
||||||
// Distance of the support structure from the overhang in the X/Y directions.
|
// Distance of the support structure from the overhang in the X/Y directions.
|
||||||
// minimum_value: 0, minimum warning": support_xy_distance - support_line_width * 2, maximum warning: support_xy_distance
|
// minimum_value: 0, minimum warning": support_xy_distance - support_line_width * 2, maximum warning: support_xy_distance
|
||||||
// Used if ! support_xy_overrides_z.
|
|
||||||
coord_t support_xy_distance_overhang { scaled<coord_t>(0.2) };
|
coord_t support_xy_distance_overhang { scaled<coord_t>(0.2) };
|
||||||
// Support Top Distance
|
// Support Top Distance
|
||||||
// Distance from the top of the support to the print.
|
// Distance from the top of the support to the print.
|
||||||
|
@ -91,7 +86,7 @@ struct TreeSupportMeshGroupSettings {
|
||||||
// A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end
|
// A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end
|
||||||
// of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained
|
// of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained
|
||||||
// in square brackets. Default is an empty list which means use the default angle 0 degrees.
|
// in square brackets. Default is an empty list which means use the default angle 0 degrees.
|
||||||
std::vector<double> support_infill_angles {};
|
// std::vector<double> support_infill_angles {};
|
||||||
// Enable Support Roof
|
// Enable Support Roof
|
||||||
// Generate a dense slab of material between the top of support and the model. This will create a skin between the model and support.
|
// Generate a dense slab of material between the top of support and the model. This will create a skin between the model and support.
|
||||||
bool support_roof_enable { false };
|
bool support_roof_enable { false };
|
||||||
|
|
|
@ -173,11 +173,9 @@ static std::vector<std::pair<TreeSupport::TreeSupportSettings, std::vector<size_
|
||||||
for (size_t object_id = 0; object_id < print_object_ids.size(); ++ object_id) {
|
for (size_t object_id = 0; object_id < print_object_ids.size(); ++ object_id) {
|
||||||
const PrintObject &print_object = *print.get_object(object_id);
|
const PrintObject &print_object = *print.get_object(object_id);
|
||||||
const PrintObjectConfig &object_config = print_object.config();
|
const PrintObjectConfig &object_config = print_object.config();
|
||||||
if (object_config.support_material_interface_layers >= 2)
|
|
||||||
TreeSupport::TreeSupportSettings::some_model_contains_thick_roof = true;
|
|
||||||
if (object_config.support_material_contact_distance < EPSILON)
|
if (object_config.support_material_contact_distance < EPSILON)
|
||||||
// || min_feature_size < scaled<coord_t>(0.1) that is the minimum line width
|
// || min_feature_size < scaled<coord_t>(0.1) that is the minimum line width
|
||||||
TreeSupport::TreeSupportSettings::has_to_rely_on_min_xy_dist_only = true;
|
TreeSupport::TreeSupportSettings::soluble = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t largest_printed_mesh_idx = 0;
|
size_t largest_printed_mesh_idx = 0;
|
||||||
|
@ -307,7 +305,7 @@ void TreeSupport::showError(std::string message, bool critical)
|
||||||
raw_overhangs_calculated = true;
|
raw_overhangs_calculated = true;
|
||||||
}
|
}
|
||||||
if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty()))
|
if (! (enforced_layer || blockers_layers.empty() || blockers_layers[layer_id].empty()))
|
||||||
overhangs = diff(overhangs, blockers_layers[layer_id]);
|
overhangs = diff(overhangs, blockers_layers[layer_id], ApplySafetyOffset::Yes);
|
||||||
}
|
}
|
||||||
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty())
|
if (! enforcers_layers.empty() && ! enforcers_layers[layer_id].empty())
|
||||||
// Has some support enforcers at this layer, apply them to the overhangs, don't apply the support threshold angle.
|
// Has some support enforcers at this layer, apply them to the overhangs, don't apply the support threshold angle.
|
||||||
|
@ -531,26 +529,27 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
|
||||||
* \param layer_idx[in] The current layer.
|
* \param layer_idx[in] The current layer.
|
||||||
* \return All lines of the \p polylines object, with information for each point regarding in which avoidance it is currently valid in.
|
* \return All lines of the \p polylines object, with information for each point regarding in which avoidance it is currently valid in.
|
||||||
*/
|
*/
|
||||||
|
// Called by TreeSupport::generateInitialAreas()
|
||||||
[[nodiscard]] static LineInformations convertLinesToInternal(
|
[[nodiscard]] static LineInformations convertLinesToInternal(
|
||||||
const TreeModelVolumes &volumes, const TreeSupport::TreeSupportSettings &config,
|
const TreeModelVolumes &volumes, const TreeSupport::TreeSupportSettings &config,
|
||||||
const Polylines &polylines, LayerIndex layer_idx)
|
const Polylines &polylines, LayerIndex layer_idx)
|
||||||
{
|
{
|
||||||
const bool xy_overrides_z = config.support_xy_overrides_z;
|
const bool min_xy_dist = config.xy_distance > config.xy_min_distance;
|
||||||
|
|
||||||
LineInformations result;
|
LineInformations result;
|
||||||
// Also checks if the position is valid, if it is NOT, it deletes that point
|
// Also checks if the position is valid, if it is NOT, it deletes that point
|
||||||
for (const Polyline &line : polylines) {
|
for (const Polyline &line : polylines) {
|
||||||
LineInformation res_line;
|
LineInformation res_line;
|
||||||
for (Point p : line) {
|
for (Point p : line) {
|
||||||
if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, false, !xy_overrides_z), p))
|
if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, false, min_xy_dist), p))
|
||||||
res_line.emplace_back(p, LineStatus::TO_BP_SAFE);
|
res_line.emplace_back(p, LineStatus::TO_BP_SAFE);
|
||||||
else if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, false, !xy_overrides_z), p))
|
else if (! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, false, min_xy_dist), p))
|
||||||
res_line.emplace_back(p, LineStatus::TO_BP);
|
res_line.emplace_back(p, LineStatus::TO_BP);
|
||||||
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, true, !xy_overrides_z), p))
|
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::FastSafe, true, min_xy_dist), p))
|
||||||
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS_SAFE);
|
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS_SAFE);
|
||||||
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, true, !xy_overrides_z), p))
|
else if (config.support_rests_on_model && ! contains(volumes.getAvoidance(config.getRadius(0), layer_idx, TreeModelVolumes::AvoidanceType::Fast, true, min_xy_dist), p))
|
||||||
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS);
|
res_line.emplace_back(p, LineStatus::TO_MODEL_GRACIOUS);
|
||||||
else if (config.support_rests_on_model && ! contains(volumes.getCollision(config.getRadius(0), layer_idx, !xy_overrides_z), p))
|
else if (config.support_rests_on_model && ! contains(volumes.getCollision(config.getRadius(0), layer_idx, min_xy_dist), p))
|
||||||
res_line.emplace_back(p, LineStatus::TO_MODEL);
|
res_line.emplace_back(p, LineStatus::TO_MODEL);
|
||||||
else if (!res_line.empty()) {
|
else if (!res_line.empty()) {
|
||||||
result.emplace_back(res_line);
|
result.emplace_back(res_line);
|
||||||
|
@ -597,13 +596,14 @@ void TreeSupport::generateSupportAreas(Print &print, const BuildVolume &build_vo
|
||||||
size_t current_layer, std::pair<Point, LineStatus> &p)
|
size_t current_layer, std::pair<Point, LineStatus> &p)
|
||||||
{
|
{
|
||||||
using AvoidanceType = TreeSupport::AvoidanceType;
|
using AvoidanceType = TreeSupport::AvoidanceType;
|
||||||
if (! contains(volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_BP_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, false, !config.support_xy_overrides_z), p.first))
|
const bool min_xy_dist = config.xy_distance > config.xy_min_distance;
|
||||||
|
if (! contains(volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_BP_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, false, min_xy_dist), p.first))
|
||||||
return true;
|
return true;
|
||||||
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
|
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
|
||||||
return ! contains(
|
return ! contains(
|
||||||
p.second == LineStatus::TO_MODEL_GRACIOUS || p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ?
|
p.second == LineStatus::TO_MODEL_GRACIOUS || p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ?
|
||||||
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, !config.support_xy_overrides_z) :
|
volumes.getAvoidance(config.getRadius(0), current_layer - 1, p.second == LineStatus::TO_MODEL_GRACIOUS_SAFE ? AvoidanceType::FastSafe : AvoidanceType::Fast, true, min_xy_dist) :
|
||||||
volumes.getCollision(config.getRadius(0), current_layer - 1, !config.support_xy_overrides_z),
|
volumes.getCollision(config.getRadius(0), current_layer - 1, min_xy_dist),
|
||||||
p.first);
|
p.first);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1066,12 +1066,8 @@ void TreeSupport::generateInitialAreas(
|
||||||
SupportGeneratorLayersPtr &top_interface_layers,
|
SupportGeneratorLayersPtr &top_interface_layers,
|
||||||
SupportGeneratorLayerStorage &layer_storage)
|
SupportGeneratorLayerStorage &layer_storage)
|
||||||
{
|
{
|
||||||
Polygon base_circle;
|
static constexpr const auto base_radius = scaled<int>(0.01);
|
||||||
const auto base_radius = scaled<int>(0.01);
|
const Polygon base_circle = make_circle(base_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
|
||||||
for (unsigned int i = 0; i < SUPPORT_TREE_CIRCLE_RESOLUTION; ++ i) {
|
|
||||||
const double angle = static_cast<double>(i) / SUPPORT_TREE_CIRCLE_RESOLUTION * (2.0 * M_PI);
|
|
||||||
base_circle.points.emplace_back(coord_t(cos(angle) * base_radius), coord_t(sin(angle) * base_radius));
|
|
||||||
}
|
|
||||||
TreeSupportMeshGroupSettings mesh_group_settings(print_object);
|
TreeSupportMeshGroupSettings mesh_group_settings(print_object);
|
||||||
TreeSupportSettings mesh_config{ mesh_group_settings };
|
TreeSupportSettings mesh_config{ mesh_group_settings };
|
||||||
SupportParameters support_params(print_object);
|
SupportParameters support_params(print_object);
|
||||||
|
@ -1080,7 +1076,8 @@ void TreeSupport::generateInitialAreas(
|
||||||
|
|
||||||
const size_t z_distance_delta = mesh_config.z_distance_top_layers + 1; // To ensure z_distance_top_layers are left empty between the overhang (zeroth empty layer), the support has to be added z_distance_top_layers+1 layers below
|
const size_t z_distance_delta = mesh_config.z_distance_top_layers + 1; // To ensure z_distance_top_layers are left empty between the overhang (zeroth empty layer), the support has to be added z_distance_top_layers+1 layers below
|
||||||
|
|
||||||
const bool xy_overrides_z = mesh_config.support_xy_overrides_z;
|
const bool min_xy_dist = mesh_config.xy_distance > mesh_config.xy_min_distance;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (mesh.overhang_areas.size() <= z_distance_delta)
|
if (mesh.overhang_areas.size() <= z_distance_delta)
|
||||||
return;
|
return;
|
||||||
|
@ -1096,7 +1093,7 @@ void TreeSupport::generateInitialAreas(
|
||||||
//FIXME Vojtech: This is not sufficient for support enforcers to work.
|
//FIXME Vojtech: This is not sufficient for support enforcers to work.
|
||||||
//FIXME There is no account for the support overhang angle.
|
//FIXME There is no account for the support overhang angle.
|
||||||
//FIXME There is no account for the width of the collision regions.
|
//FIXME There is no account for the width of the collision regions.
|
||||||
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (xy_overrides_z ? 0 : mesh_config.support_line_width / 2)
|
const coord_t extra_outset = std::max(coord_t(0), mesh_config.min_radius - mesh_config.support_line_width) + (min_xy_dist ? mesh_config.support_line_width / 2 : 0)
|
||||||
//FIXME this is a heuristic value for support enforcers to work.
|
//FIXME this is a heuristic value for support enforcers to work.
|
||||||
// + 10 * mesh_config.support_line_width;
|
// + 10 * mesh_config.support_line_width;
|
||||||
;
|
;
|
||||||
|
@ -1114,9 +1111,9 @@ void TreeSupport::generateInitialAreas(
|
||||||
std::mutex mutex_layer_storage, mutex_movebounds;
|
std::mutex mutex_layer_storage, mutex_movebounds;
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta),
|
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_support_layers - z_distance_delta),
|
||||||
[this, &print_object, &overhangs, &mesh_config, &mesh_group_settings, &support_params,
|
[this, &print_object, &overhangs, &mesh_config, &mesh_group_settings, &support_params,
|
||||||
z_distance_delta, xy_overrides_z, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
|
z_distance_delta, min_xy_dist, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
|
||||||
&base_circle, &mutex_layer_storage, &mutex_movebounds, &top_contacts, &layer_storage, &already_inserted,
|
&base_circle, &mutex_layer_storage, &mutex_movebounds, &top_contacts, &layer_storage, &already_inserted,
|
||||||
&move_bounds, &base_radius](const tbb::blocked_range<size_t> &range) {
|
&move_bounds](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||||
if (overhangs[layer_idx + z_distance_delta].empty())
|
if (overhangs[layer_idx + z_distance_delta].empty())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1124,9 +1121,9 @@ void TreeSupport::generateInitialAreas(
|
||||||
Polygons relevant_forbidden;
|
Polygons relevant_forbidden;
|
||||||
{
|
{
|
||||||
const Polygons &relevant_forbidden_raw = (mesh_config.support_rests_on_model ?
|
const Polygons &relevant_forbidden_raw = (mesh_config.support_rests_on_model ?
|
||||||
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, true, !xy_overrides_z) :
|
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, true, min_xy_dist) :
|
||||||
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx, !xy_overrides_z)) :
|
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx, min_xy_dist)) :
|
||||||
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, false, !xy_overrides_z));
|
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, false, min_xy_dist));
|
||||||
// prevent rounding errors down the line, points placed directly on the line of the forbidden area may not be added otherwise.
|
// prevent rounding errors down the line, points placed directly on the line of the forbidden area may not be added otherwise.
|
||||||
relevant_forbidden = offset(union_ex(relevant_forbidden_raw), scaled<float>(0.005), jtMiter, 1.2);
|
relevant_forbidden = offset(union_ex(relevant_forbidden_raw), scaled<float>(0.005), jtMiter, 1.2);
|
||||||
}
|
}
|
||||||
|
@ -1154,7 +1151,7 @@ void TreeSupport::generateInitialAreas(
|
||||||
if (! already_inserted[insert_layer].count(p.first / ((mesh_config.min_radius + 1) / 10))) {
|
if (! already_inserted[insert_layer].count(p.first / ((mesh_config.min_radius + 1) / 10))) {
|
||||||
// normalize the point a bit to also catch points which are so close that inserting it would achieve nothing
|
// normalize the point a bit to also catch points which are so close that inserting it would achieve nothing
|
||||||
already_inserted[insert_layer].emplace(p.first / ((mesh_config.min_radius + 1) / 10));
|
already_inserted[insert_layer].emplace(p.first / ((mesh_config.min_radius + 1) / 10));
|
||||||
SupportElement* elem = new SupportElement(dtt, insert_layer, p.first, to_bp, gracious, !xy_overrides_z, dont_move_until, roof, safe_radius, force_tip_to_roof, skip_ovalisation);
|
SupportElement* elem = new SupportElement(dtt, insert_layer, p.first, to_bp, gracious, min_xy_dist, dont_move_until, roof, safe_radius, force_tip_to_roof, skip_ovalisation);
|
||||||
elem->area = new Polygons();
|
elem->area = new Polygons();
|
||||||
validate_range(circle);
|
validate_range(circle);
|
||||||
elem->area->emplace_back(std::move(circle));
|
elem->area->emplace_back(std::move(circle));
|
||||||
|
@ -1264,8 +1261,7 @@ void TreeSupport::generateInitialAreas(
|
||||||
}
|
}
|
||||||
// If the xy distance overrides the z distance, some support needs to be inserted further down.
|
// If the xy distance overrides the z distance, some support needs to be inserted further down.
|
||||||
//=> Analyze which support points do not fit on this layer and check if they will fit a few layers down (while adding them an infinite amount of layers down would technically be closer the the setting description, it would not produce reasonable results. )
|
//=> Analyze which support points do not fit on this layer and check if they will fit a few layers down (while adding them an infinite amount of layers down would technically be closer the the setting description, it would not produce reasonable results. )
|
||||||
if (xy_overrides_z)
|
if (! min_xy_dist) {
|
||||||
{
|
|
||||||
LineInformations overhang_lines;
|
LineInformations overhang_lines;
|
||||||
{
|
{
|
||||||
//Vojtech: Generate support heads at support_tree_branch_distance spacing by producing a zig-zag infill at support_tree_branch_distance spacing,
|
//Vojtech: Generate support heads at support_tree_branch_distance spacing by producing a zig-zag infill at support_tree_branch_distance spacing,
|
||||||
|
@ -1286,10 +1282,9 @@ void TreeSupport::generateInitialAreas(
|
||||||
}
|
}
|
||||||
validate_range(overhang_lines);
|
validate_range(overhang_lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t lag_ctr = 1; lag_ctr <= max_overhang_insert_lag && !overhang_lines.empty() && layer_idx - coord_t(lag_ctr) >= 1; lag_ctr++) {
|
for (size_t lag_ctr = 1; lag_ctr <= max_overhang_insert_lag && !overhang_lines.empty() && layer_idx - coord_t(lag_ctr) >= 1; lag_ctr++) {
|
||||||
// get least restricted avoidance for layer_idx-lag_ctr
|
// get least restricted avoidance for layer_idx-lag_ctr
|
||||||
const Polygons &relevant_forbidden_below = (mesh_config.support_rests_on_model ? (SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, true, !xy_overrides_z) : m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - lag_ctr, !xy_overrides_z)) : m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, !xy_overrides_z));
|
const Polygons &relevant_forbidden_below = (mesh_config.support_rests_on_model ? (SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ? m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, true, min_xy_dist) : m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - lag_ctr, min_xy_dist)) : m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - lag_ctr, AvoidanceType::Fast, false, min_xy_dist));
|
||||||
// it is not required to offset the forbidden area here as the points wont change: If points here are not inside the forbidden area neither will they be later when placing these points, as these are the same points.
|
// it is not required to offset the forbidden area here as the points wont change: If points here are not inside the forbidden area neither will they be later when placing these points, as these are the same points.
|
||||||
auto evaluatePoint = [&](std::pair<Point, LineStatus> p) { return contains(relevant_forbidden_below, p.first); };
|
auto evaluatePoint = [&](std::pair<Point, LineStatus> p) { return contains(relevant_forbidden_below, p.first); };
|
||||||
|
|
||||||
|
@ -1310,7 +1305,7 @@ void TreeSupport::generateInitialAreas(
|
||||||
overhang_roofs = safeOffsetInc(overhangs[layer_idx + z_distance_delta], support_roof_offset, relevant_forbidden, mesh_config.min_radius * 2 + mesh_config.xy_min_distance, 0, 1);
|
overhang_roofs = safeOffsetInc(overhangs[layer_idx + z_distance_delta], support_roof_offset, relevant_forbidden, mesh_config.min_radius * 2 + mesh_config.xy_min_distance, 0, 1);
|
||||||
if (mesh_group_settings.minimum_support_area > 0)
|
if (mesh_group_settings.minimum_support_area > 0)
|
||||||
remove_small(overhang_roofs, mesh_group_settings.minimum_roof_area);
|
remove_small(overhang_roofs, mesh_group_settings.minimum_roof_area);
|
||||||
overhang_regular = diff(overhang_regular, overhang_roofs);
|
overhang_regular = diff(overhang_regular, overhang_roofs, ApplySafetyOffset::Yes);
|
||||||
for (ExPolygon &roof_part : union_ex(overhang_roofs))
|
for (ExPolygon &roof_part : union_ex(overhang_roofs))
|
||||||
overhang_processing.emplace_back(std::move(roof_part), true);
|
overhang_processing.emplace_back(std::move(roof_part), true);
|
||||||
}
|
}
|
||||||
|
@ -1345,9 +1340,9 @@ void TreeSupport::generateInitialAreas(
|
||||||
{
|
{
|
||||||
const Polygons &forbidden_next_raw = mesh_config.support_rests_on_model ?
|
const Polygons &forbidden_next_raw = mesh_config.support_rests_on_model ?
|
||||||
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ?
|
(SUPPORT_TREE_ONLY_GRACIOUS_TO_MODEL ?
|
||||||
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, true, !xy_overrides_z) :
|
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, true, min_xy_dist) :
|
||||||
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), !xy_overrides_z)) :
|
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), min_xy_dist)) :
|
||||||
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, false, !xy_overrides_z);
|
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), AvoidanceType::Fast, false, min_xy_dist);
|
||||||
// prevent rounding errors down the line
|
// prevent rounding errors down the line
|
||||||
forbidden_next = offset(union_ex(forbidden_next_raw), scaled<float>(0.005), jtMiter, 1.2);
|
forbidden_next = offset(union_ex(forbidden_next_raw), scaled<float>(0.005), jtMiter, 1.2);
|
||||||
}
|
}
|
||||||
|
@ -2406,12 +2401,8 @@ void TreeSupport::generateBranchAreas(
|
||||||
constexpr int progress_report_steps = 10;
|
constexpr int progress_report_steps = 10;
|
||||||
#endif // SLIC3R_TREESUPPORTS_PROGRESS
|
#endif // SLIC3R_TREESUPPORTS_PROGRESS
|
||||||
|
|
||||||
Polygon branch_circle; // Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
|
// Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
|
||||||
for (unsigned int i = 0; i < SUPPORT_TREE_CIRCLE_RESOLUTION; ++ i) {
|
const Polygon branch_circle = make_circle(m_config.branch_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
|
||||||
const double angle = static_cast<double>(i) / SUPPORT_TREE_CIRCLE_RESOLUTION * (2.0 * M_PI);
|
|
||||||
branch_circle.points.emplace_back(coord_t(cos(angle) * m_config.branch_radius), coord_t(sin(angle) * m_config.branch_radius));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Polygons> linear_inserts(linear_data.size());
|
std::vector<Polygons> linear_inserts(linear_data.size());
|
||||||
|
|
||||||
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
|
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
|
||||||
|
|
|
@ -85,7 +85,6 @@ public:
|
||||||
void generateSupportAreas(Print &print, const BuildVolume &build_volume, const std::vector<size_t>& print_object_ids);
|
void generateSupportAreas(Print &print, const BuildVolume &build_volume, const std::vector<size_t>& print_object_ids);
|
||||||
void generateSupportAreas(PrintObject &print_object);
|
void generateSupportAreas(PrintObject &print_object);
|
||||||
|
|
||||||
|
|
||||||
//todo Remove! Only relevant for public BETA!
|
//todo Remove! Only relevant for public BETA!
|
||||||
static bool inline showed_critical=false;
|
static bool inline showed_critical=false;
|
||||||
static bool inline showed_performance=false;
|
static bool inline showed_performance=false;
|
||||||
|
@ -375,14 +374,13 @@ public:
|
||||||
increase_radius_until_layer(increase_radius_until_radius <= branch_radius ? tip_layers * (increase_radius_until_radius / branch_radius) : (increase_radius_until_radius - branch_radius) / (branch_radius * diameter_angle_scale_factor)),
|
increase_radius_until_layer(increase_radius_until_radius <= branch_radius ? tip_layers * (increase_radius_until_radius / branch_radius) : (increase_radius_until_radius - branch_radius) / (branch_radius * diameter_angle_scale_factor)),
|
||||||
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
|
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
|
||||||
xy_distance(mesh_group_settings.support_xy_distance),
|
xy_distance(mesh_group_settings.support_xy_distance),
|
||||||
|
xy_min_distance(std::min(mesh_group_settings.support_xy_distance, mesh_group_settings.support_xy_distance_overhang)),
|
||||||
bp_radius(mesh_group_settings.support_tree_bp_diameter / 2),
|
bp_radius(mesh_group_settings.support_tree_bp_diameter / 2),
|
||||||
diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller.
|
diameter_scale_bp_radius(std::min(sin(0.7) * layer_height / branch_radius, 1.0 / (branch_radius / (support_line_width / 2.0)))), // Either 40? or as much as possible so that 2 lines will overlap by at least 50%, whichever is smaller.
|
||||||
support_xy_overrides_z(mesh_group_settings.support_xy_overrides_z),
|
|
||||||
xy_min_distance(support_xy_overrides_z ? xy_distance : mesh_group_settings.support_xy_distance_overhang),
|
|
||||||
z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)),
|
z_distance_top_layers(round_up_divide(mesh_group_settings.support_top_distance, layer_height)),
|
||||||
z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)),
|
z_distance_bottom_layers(round_up_divide(mesh_group_settings.support_bottom_distance, layer_height)),
|
||||||
performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)),
|
performance_interface_skip_layers(round_up_divide(mesh_group_settings.support_interface_skip_height, layer_height)),
|
||||||
support_infill_angles(mesh_group_settings.support_infill_angles),
|
// support_infill_angles(mesh_group_settings.support_infill_angles),
|
||||||
support_roof_angles(mesh_group_settings.support_roof_angles),
|
support_roof_angles(mesh_group_settings.support_roof_angles),
|
||||||
roof_pattern(mesh_group_settings.support_roof_pattern),
|
roof_pattern(mesh_group_settings.support_roof_pattern),
|
||||||
support_pattern(mesh_group_settings.support_pattern),
|
support_pattern(mesh_group_settings.support_pattern),
|
||||||
|
@ -399,40 +397,15 @@ public:
|
||||||
{
|
{
|
||||||
layer_start_bp_radius = (bp_radius - branch_radius) / (branch_radius * diameter_scale_bp_radius);
|
layer_start_bp_radius = (bp_radius - branch_radius) / (branch_radius * diameter_scale_bp_radius);
|
||||||
|
|
||||||
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
|
if (TreeSupport::TreeSupportSettings::soluble) {
|
||||||
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
|
// safeOffsetInc can only work in steps of the size xy_min_distance in the worst case => xy_min_distance has to be a bit larger than 0 in this worst case and should be large enough for performance to not suffer extremely
|
||||||
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
|
// When for all meshes the z bottom and top distance is more than one layer though the worst case is xy_min_distance + min_feature_size
|
||||||
if (has_to_rely_on_min_xy_dist_only)
|
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
|
||||||
xy_min_distance = std::max(coord_t(100), xy_min_distance); // If set to low rounding errors WILL cause errors. Best to keep it above 25.
|
xy_min_distance = std::max(xy_min_distance, scaled<coord_t>(0.1));
|
||||||
|
xy_distance = std::max(xy_distance, xy_min_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
xy_distance = std::max(xy_distance, xy_min_distance);
|
|
||||||
|
|
||||||
// (logic) from getInterfaceAngles in FFFGcodeWriter.
|
|
||||||
auto getInterfaceAngles = [&](std::vector<double>& angles, SupportMaterialInterfacePattern pattern) {
|
|
||||||
if (angles.empty())
|
|
||||||
{
|
|
||||||
if (pattern == SupportMaterialInterfacePattern::smipConcentric)
|
|
||||||
angles.push_back(0); // Concentric has no rotation.
|
|
||||||
/*
|
|
||||||
else if (pattern == SupportMaterialInterfacePattern::TRIANGLES)
|
|
||||||
angles.push_back(90); // Triangular support interface shouldn't alternate every layer.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
if (TreeSupportSettings::some_model_contains_thick_roof) {
|
|
||||||
// Some roofs are quite thick.
|
|
||||||
// Alternate between the two kinds of diagonal: / and \ .
|
|
||||||
angles.push_back(M_PI / 4.);
|
|
||||||
angles.push_back(3. * M_PI / 4.);
|
|
||||||
}
|
|
||||||
if (angles.empty())
|
|
||||||
angles.push_back(M_PI / 2.); // Perpendicular to support lines.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//getInterfaceAngles(support_infill_angles, support_pattern);
|
|
||||||
support_infill_angles = { M_PI / 2. };
|
|
||||||
getInterfaceAngles(support_roof_angles, roof_pattern);
|
|
||||||
// const std::unordered_map<std::string, InterfacePreference> interface_map = { { "support_area_overwrite_interface_area", InterfacePreference::SUPPORT_AREA_OVERWRITES_INTERFACE }, { "interface_area_overwrite_support_area", InterfacePreference::INTERFACE_AREA_OVERWRITES_SUPPORT }, { "support_lines_overwrite_interface_area", InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE }, { "interface_lines_overwrite_support_area", InterfacePreference::INTERFACE_LINES_OVERWRITE_SUPPORT }, { "nothing", InterfacePreference::NOTHING } };
|
// const std::unordered_map<std::string, InterfacePreference> interface_map = { { "support_area_overwrite_interface_area", InterfacePreference::SUPPORT_AREA_OVERWRITES_INTERFACE }, { "interface_area_overwrite_support_area", InterfacePreference::INTERFACE_AREA_OVERWRITES_SUPPORT }, { "support_lines_overwrite_interface_area", InterfacePreference::SUPPORT_LINES_OVERWRITE_INTERFACE }, { "interface_lines_overwrite_support_area", InterfacePreference::INTERFACE_LINES_OVERWRITE_SUPPORT }, { "nothing", InterfacePreference::NOTHING } };
|
||||||
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
|
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
|
||||||
//FIXME this was the default
|
//FIXME this was the default
|
||||||
|
@ -448,8 +421,7 @@ public:
|
||||||
public:
|
public:
|
||||||
// some static variables dependent on other meshes that are not currently processed.
|
// some static variables dependent on other meshes that are not currently processed.
|
||||||
// Has to be static because TreeSupportConfig will be used in TreeModelVolumes as this reduces redundancy.
|
// Has to be static because TreeSupportConfig will be used in TreeModelVolumes as this reduces redundancy.
|
||||||
inline static bool some_model_contains_thick_roof = false;
|
inline static bool soluble = false;
|
||||||
inline static bool has_to_rely_on_min_xy_dist_only = false;
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Width of a single line of support.
|
* \brief Width of a single line of support.
|
||||||
*/
|
*/
|
||||||
|
@ -522,10 +494,6 @@ public:
|
||||||
* \brief Factor by which to increase the branch radius to reach the required bp_radius at layer 0. Note that this radius increase will not happen in the tip, to ensure the tip is structurally sound.
|
* \brief Factor by which to increase the branch radius to reach the required bp_radius at layer 0. Note that this radius increase will not happen in the tip, to ensure the tip is structurally sound.
|
||||||
*/
|
*/
|
||||||
double diameter_scale_bp_radius;
|
double diameter_scale_bp_radius;
|
||||||
/*!
|
|
||||||
* \brief Should Z distance override X/Y distance, or the other way around.
|
|
||||||
*/
|
|
||||||
bool support_xy_overrides_z;
|
|
||||||
/*!
|
/*!
|
||||||
* \brief minimum xy_distance. Only relevant when Z overrides XY, otherwise equal to xy_distance-
|
* \brief minimum xy_distance. Only relevant when Z overrides XY, otherwise equal to xy_distance-
|
||||||
*/
|
*/
|
||||||
|
@ -545,7 +513,7 @@ public:
|
||||||
/*!
|
/*!
|
||||||
* \brief User specified angles for the support infill.
|
* \brief User specified angles for the support infill.
|
||||||
*/
|
*/
|
||||||
std::vector<double> support_infill_angles;
|
// std::vector<double> support_infill_angles;
|
||||||
/*!
|
/*!
|
||||||
* \brief User specified angles for the support roof infill.
|
* \brief User specified angles for the support roof infill.
|
||||||
*/
|
*/
|
||||||
|
@ -603,9 +571,11 @@ public:
|
||||||
return branch_radius == other.branch_radius && tip_layers == other.tip_layers && diameter_angle_scale_factor == other.diameter_angle_scale_factor && layer_start_bp_radius == other.layer_start_bp_radius && bp_radius == other.bp_radius && diameter_scale_bp_radius == other.diameter_scale_bp_radius && min_radius == other.min_radius && xy_min_distance == other.xy_min_distance && // as a recalculation of the collision areas is required to set a new min_radius.
|
return branch_radius == other.branch_radius && tip_layers == other.tip_layers && diameter_angle_scale_factor == other.diameter_angle_scale_factor && layer_start_bp_radius == other.layer_start_bp_radius && bp_radius == other.bp_radius && diameter_scale_bp_radius == other.diameter_scale_bp_radius && min_radius == other.min_radius && xy_min_distance == other.xy_min_distance && // as a recalculation of the collision areas is required to set a new min_radius.
|
||||||
xy_distance - xy_min_distance == other.xy_distance - other.xy_min_distance && // if the delta of xy_min_distance and xy_distance is different the collision areas have to be recalculated.
|
xy_distance - xy_min_distance == other.xy_distance - other.xy_min_distance && // if the delta of xy_min_distance and xy_distance is different the collision areas have to be recalculated.
|
||||||
support_rests_on_model == other.support_rests_on_model && increase_radius_until_layer == other.increase_radius_until_layer && min_dtt_to_model == other.min_dtt_to_model && max_to_model_radius_increase == other.max_to_model_radius_increase && maximum_move_distance == other.maximum_move_distance && maximum_move_distance_slow == other.maximum_move_distance_slow && z_distance_bottom_layers == other.z_distance_bottom_layers && support_line_width == other.support_line_width &&
|
support_rests_on_model == other.support_rests_on_model && increase_radius_until_layer == other.increase_radius_until_layer && min_dtt_to_model == other.min_dtt_to_model && max_to_model_radius_increase == other.max_to_model_radius_increase && maximum_move_distance == other.maximum_move_distance && maximum_move_distance_slow == other.maximum_move_distance_slow && z_distance_bottom_layers == other.z_distance_bottom_layers && support_line_width == other.support_line_width &&
|
||||||
support_xy_overrides_z == other.support_xy_overrides_z && support_line_spacing == other.support_line_spacing && support_roof_line_width == other.support_roof_line_width && // can not be set on a per-mesh basis currently, so code to enable processing different roof line width in the same iteration seems useless.
|
support_line_spacing == other.support_line_spacing && support_roof_line_width == other.support_roof_line_width && // can not be set on a per-mesh basis currently, so code to enable processing different roof line width in the same iteration seems useless.
|
||||||
support_bottom_offset == other.support_bottom_offset && support_wall_count == other.support_wall_count && support_pattern == other.support_pattern && roof_pattern == other.roof_pattern && // can not be set on a per-mesh basis currently, so code to enable processing different roof patterns in the same iteration seems useless.
|
support_bottom_offset == other.support_bottom_offset && support_wall_count == other.support_wall_count && support_pattern == other.support_pattern && roof_pattern == other.roof_pattern && // can not be set on a per-mesh basis currently, so code to enable processing different roof patterns in the same iteration seems useless.
|
||||||
support_roof_angles == other.support_roof_angles && support_infill_angles == other.support_infill_angles && increase_radius_until_radius == other.increase_radius_until_radius && support_bottom_layers == other.support_bottom_layers && layer_height == other.layer_height && z_distance_top_layers == other.z_distance_top_layers && resolution == other.resolution && // Infill generation depends on deviation and resolution.
|
support_roof_angles == other.support_roof_angles &&
|
||||||
|
//support_infill_angles == other.support_infill_angles &&
|
||||||
|
increase_radius_until_radius == other.increase_radius_until_radius && support_bottom_layers == other.support_bottom_layers && layer_height == other.layer_height && z_distance_top_layers == other.z_distance_top_layers && resolution == other.resolution && // Infill generation depends on deviation and resolution.
|
||||||
support_roof_line_distance == other.support_roof_line_distance && interface_preference == other.interface_preference
|
support_roof_line_distance == other.support_roof_line_distance && interface_preference == other.interface_preference
|
||||||
&& min_feature_size == other.min_feature_size // interface_preference should be identical to ensure the tree will correctly interact with the roof.
|
&& min_feature_size == other.min_feature_size // interface_preference should be identical to ensure the tree will correctly interact with the roof.
|
||||||
// The infill class now wants the settings object and reads a lot of settings, and as the infill class is used to calculate support roof lines for interface-preference. Not all of these may be required to be identical, but as I am not sure, better safe than sorry
|
// The infill class now wants the settings object and reads a lot of settings, and as the infill class is used to calculate support roof lines for interface-preference. Not all of these may be required to be identical, but as I am not sure, better safe than sorry
|
||||||
|
|
46
src/libslic3r/TriangleSelectorWrapper.cpp
Normal file
46
src/libslic3r/TriangleSelectorWrapper.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "TriangleSelectorWrapper.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
TriangleSelectorWrapper::TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform) :
|
||||||
|
mesh(mesh), mesh_transform(mesh_transform), selector(mesh), triangles_tree(
|
||||||
|
AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(mesh.its.vertices, mesh.its.indices)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &origin, float radius) {
|
||||||
|
std::vector<igl::Hit> hits;
|
||||||
|
Vec3f dir = (point - origin).normalized();
|
||||||
|
if (AABBTreeIndirect::intersect_ray_all_hits(mesh.its.vertices, mesh.its.indices, triangles_tree,
|
||||||
|
Vec3d(origin.cast<double>()),
|
||||||
|
Vec3d(dir.cast<double>()),
|
||||||
|
hits)) {
|
||||||
|
for (int hit_idx = hits.size() - 1; hit_idx >= 0; --hit_idx) {
|
||||||
|
const igl::Hit &hit = hits[hit_idx];
|
||||||
|
Vec3f pos = origin + dir * hit.t;
|
||||||
|
Vec3f face_normal = its_face_normal(mesh.its, hit.id);
|
||||||
|
if ((point - pos).norm() < radius && face_normal.dot(dir) < 0) {
|
||||||
|
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||||
|
pos, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||||
|
selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(),
|
||||||
|
true, 0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t hit_idx_out;
|
||||||
|
Vec3f hit_point_out;
|
||||||
|
float dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(mesh.its.vertices, mesh.its.indices,
|
||||||
|
triangles_tree, point, hit_idx_out, hit_point_out);
|
||||||
|
if (dist < radius) {
|
||||||
|
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||||
|
point, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||||
|
selector.select_patch(hit_idx_out, std::move(cursor), EnforcerBlockerType::ENFORCER,
|
||||||
|
Transform3d::Identity(),
|
||||||
|
true, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/libslic3r/TriangleSelectorWrapper.hpp
Normal file
31
src/libslic3r/TriangleSelectorWrapper.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||||
|
#define SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||||
|
|
||||||
|
#include "TriangleSelector.hpp"
|
||||||
|
#include "Model.hpp"
|
||||||
|
#include "AABBTreeIndirect.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
//NOTE: We need to replace the FacetsAnnotation struct for support storage (or extend/add another)
|
||||||
|
// Problems: Does not support negative volumes, strange usage for supports computed from extrusion -
|
||||||
|
// expensively converted back to triangles and then sliced again.
|
||||||
|
// Another problem is weird and very limited interface when painting supports via algorithms
|
||||||
|
|
||||||
|
|
||||||
|
class TriangleSelectorWrapper {
|
||||||
|
public:
|
||||||
|
const TriangleMesh &mesh;
|
||||||
|
const Transform3d& mesh_transform;
|
||||||
|
TriangleSelector selector;
|
||||||
|
AABBTreeIndirect::Tree<3, float> triangles_tree;
|
||||||
|
|
||||||
|
TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform);
|
||||||
|
|
||||||
|
void enforce_spot(const Vec3f &point, const Vec3f& origin, float radius);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_ */
|
|
@ -738,7 +738,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
||||||
|
|
||||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||||
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.string());
|
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.filename().string());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
||||||
|
|
|
@ -219,7 +219,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||||
{
|
{
|
||||||
bool have_perimeters = config->opt_int("perimeters") > 0;
|
bool have_perimeters = config->opt_int("perimeters") > 0;
|
||||||
for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
|
"seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
|
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
|
||||||
toggle_field(el, have_perimeters);
|
toggle_field(el, have_perimeters);
|
||||||
|
|
||||||
|
|
|
@ -2564,9 +2564,9 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||||
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
||||||
if (check_unsaved_preset_changes)
|
if (check_unsaved_preset_changes)
|
||||||
header = _L("All user presets will be deleted.");
|
header = _L("All user presets will be deleted.");
|
||||||
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP;
|
int act_btns = ActionButtons::KEEP;
|
||||||
if (!check_unsaved_preset_changes)
|
if (!check_unsaved_preset_changes)
|
||||||
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
|
act_btns |= ActionButtons::SAVE;
|
||||||
|
|
||||||
// Install bundles from resources if needed:
|
// Install bundles from resources if needed:
|
||||||
std::vector<std::string> install_bundles;
|
std::vector<std::string> install_bundles;
|
||||||
|
|
|
@ -33,7 +33,7 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/)
|
||||||
// Style_NoTrailingZeroes does not work on OSX. It also does not work correctly with some locales on Windows.
|
// Style_NoTrailingZeroes does not work on OSX. It also does not work correctly with some locales on Windows.
|
||||||
// return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
|
// return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
|
||||||
|
|
||||||
wxString s = wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_None);
|
wxString s = wxNumberFormatter::ToString(value, value < 0.0001 ? 10 : max_precision, wxNumberFormatter::Style_None);
|
||||||
|
|
||||||
// The following code comes from wxNumberFormatter::RemoveTrailingZeroes(wxString& s)
|
// The following code comes from wxNumberFormatter::RemoveTrailingZeroes(wxString& s)
|
||||||
// with the exception that here one sets the decimal separator explicitely to dot.
|
// with the exception that here one sets the decimal separator explicitely to dot.
|
||||||
|
|
|
@ -3288,6 +3288,7 @@ void GCodeViewer::render_toolpaths()
|
||||||
shader->set_uniform("emission_factor", 0.0f);
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
shader->set_uniform("emission_factor", 0.15f);
|
||||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||||
const int position_id = shader->get_attrib_location("v_position");
|
const int position_id = shader->get_attrib_location("v_position");
|
||||||
const int normal_id = shader->get_attrib_location("v_normal");
|
const int normal_id = shader->get_attrib_location("v_normal");
|
||||||
|
@ -3859,14 +3860,16 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||||
|
|
||||||
if (m_view_type == EViewType::Tool) {
|
if (m_view_type == EViewType::Tool) {
|
||||||
// calculate used filaments data
|
// calculate used filaments data
|
||||||
|
used_filaments_m = std::vector<double>(m_extruders_count, 0.0);
|
||||||
|
used_filaments_g = std::vector<double>(m_extruders_count, 0.0);
|
||||||
for (size_t extruder_id : m_extruder_ids) {
|
for (size_t extruder_id : m_extruder_ids) {
|
||||||
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
||||||
continue;
|
continue;
|
||||||
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
||||||
|
|
||||||
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
||||||
used_filaments_m.push_back(used_filament_m);
|
used_filaments_m[extruder_id] = used_filament_m;
|
||||||
used_filaments_g.push_back(used_filament_g);
|
used_filaments_g[extruder_id] = used_filament_g;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string longest_used_filament_string;
|
std::string longest_used_filament_string;
|
||||||
|
@ -3999,11 +4002,10 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||||
#endif // ENABLE_PREVIEW_LAYER_TIME
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
case EViewType::Tool: {
|
case EViewType::Tool: {
|
||||||
// shows only extruders actually used
|
// shows only extruders actually used
|
||||||
size_t i = 0;
|
|
||||||
for (unsigned char extruder_id : m_extruder_ids) {
|
for (unsigned char extruder_id : m_extruder_ids) {
|
||||||
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
|
if (used_filaments_m[extruder_id] > 0.0 && used_filaments_g[extruder_id] > 0.0)
|
||||||
true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]);
|
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
|
||||||
++i;
|
true, "", 0.0f, 0.0f, offsets, used_filaments_m[extruder_id], used_filaments_g[extruder_id]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -834,14 +834,14 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
|
||||||
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||||
float win_w = ImGui::GetWindowWidth();
|
float win_w = ImGui::GetWindowWidth();
|
||||||
float label_len = imgui.calc_text_size(owner.label).x;
|
float label_len = ImGui::CalcTextSize(owner.label.c_str()).x;
|
||||||
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
|
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
imgui.text(owner.label);
|
imgui.text(owner.label);
|
||||||
|
|
||||||
if (!owner.print_order.empty()) {
|
if (!owner.print_order.empty()) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
float po_len = imgui.calc_text_size(owner.print_order).x;
|
float po_len = ImGui::CalcTextSize(owner.print_order.c_str()).x;
|
||||||
ImGui::SetCursorPosX(0.5f * (win_w - po_len));
|
ImGui::SetCursorPosX(0.5f * (win_w - po_len));
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
imgui.text(owner.print_order);
|
imgui.text(owner.print_order);
|
||||||
|
@ -4173,7 +4173,7 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc
|
||||||
|
|
||||||
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
|
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
|
||||||
{
|
{
|
||||||
std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second);
|
std::string field = "layer_" + std::to_string(type) + "_" + float_to_string_decimal_point(range.first) + "_" + float_to_string_decimal_point(range.second);
|
||||||
handle_sidebar_focus_event(field, true);
|
handle_sidebar_focus_event(field, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5504,28 +5504,41 @@ void GLCanvas3D::_picking_pass()
|
||||||
}
|
}
|
||||||
default: { break; }
|
default: { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
imgui.text_colored(col_1_color, col_1.c_str());
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
imgui.text_colored(col_2_color, col_2.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
if (hit.type != SceneRaycaster::EType::None) {
|
if (hit.type != SceneRaycaster::EType::None) {
|
||||||
sprintf(buf, "Object ID: %d", hit.raycaster_id);
|
if (ImGui::BeginTable("Hit", 2)) {
|
||||||
imgui.text(std::string(buf));
|
add_strings_row_to_table("Object ID", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(hit.raycaster_id), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
sprintf(buf, "Type: %s", object_type.c_str());
|
add_strings_row_to_table("Type", ImGuiWrapper::COL_ORANGE_LIGHT, object_type, ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
imgui.text(std::string(buf));
|
sprintf(buf, "%.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
|
||||||
sprintf(buf, "Position: %.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
|
add_strings_row_to_table("Position", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
imgui.text(std::string(buf));
|
sprintf(buf, "%.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
|
||||||
sprintf(buf, "Normal: %.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
|
add_strings_row_to_table("Normal", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
imgui.text(std::string(buf));
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
imgui.text("NO HIT");
|
imgui.text("NO HIT");
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
imgui.text("Registered for picking:");
|
imgui.text("Registered for picking:");
|
||||||
sprintf(buf, "Beds: %d", (int)m_scene_raycaster.beds_count());
|
if (ImGui::BeginTable("Raycasters", 2)) {
|
||||||
imgui.text(std::string(buf));
|
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.beds_count(), (int)m_scene_raycaster.active_beds_count());
|
||||||
sprintf(buf, "Volumes: %d", (int)m_scene_raycaster.volumes_count());
|
add_strings_row_to_table("Beds", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
imgui.text(std::string(buf));
|
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.volumes_count(), (int)m_scene_raycaster.active_volumes_count());
|
||||||
sprintf(buf, "Gizmo elements: %d", (int)m_scene_raycaster.gizmos_count());
|
add_strings_row_to_table("Volumes", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
imgui.text(std::string(buf));
|
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.gizmos_count(), (int)m_scene_raycaster.active_gizmos_count());
|
||||||
|
add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
imgui.end();
|
imgui.end();
|
||||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace GUI {
|
||||||
GLModel::Geometry init_data;
|
GLModel::Geometry init_data;
|
||||||
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
|
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
|
||||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 };
|
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 };
|
||||||
init_data.reserve_vertices(8);
|
init_data.reserve_vertices(5);
|
||||||
init_data.reserve_indices(8);
|
init_data.reserve_indices(8);
|
||||||
#else
|
#else
|
||||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
|
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
|
||||||
|
@ -173,25 +173,19 @@ namespace GUI {
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
||||||
perimeter += width;
|
perimeter += width;
|
||||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
||||||
perimeter += height;
|
perimeter += height;
|
||||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
||||||
perimeter += width;
|
perimeter += width;
|
||||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
||||||
perimeter += height;
|
perimeter += height;
|
||||||
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
||||||
|
|
||||||
// indices
|
// indices
|
||||||
init_data.add_line(0, 1);
|
init_data.add_line(0, 1);
|
||||||
|
init_data.add_line(1, 2);
|
||||||
init_data.add_line(2, 3);
|
init_data.add_line(2, 3);
|
||||||
init_data.add_line(4, 5);
|
init_data.add_line(3, 4);
|
||||||
init_data.add_line(6, 7);
|
|
||||||
#else
|
#else
|
||||||
init_data.add_vertex(Vec2f(left, bottom));
|
init_data.add_vertex(Vec2f(left, bottom));
|
||||||
init_data.add_vertex(Vec2f(right, bottom));
|
init_data.add_vertex(Vec2f(right, bottom));
|
||||||
|
|
|
@ -1898,7 +1898,7 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
|
||||||
{
|
{
|
||||||
input_files.Clear();
|
input_files.Clear();
|
||||||
wxFileDialog dialog(parent ? parent : GetTopWindow(),
|
wxFileDialog dialog(parent ? parent : GetTopWindow(),
|
||||||
_L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA/STEP):"),
|
_L("Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"),
|
||||||
from_u8(app_config->get_last_dir()), "",
|
from_u8(app_config->get_last_dir()), "",
|
||||||
file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||||
|
|
||||||
|
@ -2522,9 +2522,9 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con
|
||||||
{
|
{
|
||||||
if (has_current_preset_changes()) {
|
if (has_current_preset_changes()) {
|
||||||
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
|
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
|
||||||
int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE;
|
int act_buttons = ActionButtons::SAVE;
|
||||||
if (dont_save_insted_of_discard)
|
if (dont_save_insted_of_discard)
|
||||||
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
|
act_buttons |= ActionButtons::DONT_SAVE;
|
||||||
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
||||||
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
||||||
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
||||||
|
|
|
@ -991,7 +991,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
|
||||||
void ObjectList::extruder_editing()
|
void ObjectList::extruder_editing()
|
||||||
{
|
{
|
||||||
wxDataViewItem item = GetSelection();
|
wxDataViewItem item = GetSelection();
|
||||||
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
|
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject | itLayer)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wxRect rect = this->GetItemRect(item, GetColumn(colExtruder));
|
wxRect rect = this->GetItemRect(item, GetColumn(colExtruder));
|
||||||
|
@ -1016,6 +1016,7 @@ void ObjectList::extruder_editing()
|
||||||
|
|
||||||
m_extruder_editor->Hide();
|
m_extruder_editor->Hide();
|
||||||
update_extruder_in_config(item);
|
update_extruder_in_config(item);
|
||||||
|
Refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
// to avoid event propagation to other sidebar items
|
// to avoid event propagation to other sidebar items
|
||||||
|
|
|
@ -590,7 +590,10 @@ void ObjectManipulation::update_ui_from_settings()
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
auto update = [this, i](/*ManipulationEditorKey*/int key_id, const Vec3d& new_value) {
|
auto update = [this, i](/*ManipulationEditorKey*/int key_id, const Vec3d& new_value) {
|
||||||
wxString new_text = double_to_string(m_imperial_units ? new_value(i) * mm_to_in : new_value(i), 2);
|
double value = new_value(i);
|
||||||
|
if (m_imperial_units)
|
||||||
|
value *= mm_to_in;
|
||||||
|
wxString new_text = double_to_string(value, m_imperial_units && key_id == 3/*meSize*/ ? 4 : 2);
|
||||||
const int id = key_id * 3 + i;
|
const int id = key_id * 3 + i;
|
||||||
if (id >= 0) m_editors[id]->set_value(new_text);
|
if (id >= 0) m_editors[id]->set_value(new_text);
|
||||||
};
|
};
|
||||||
|
@ -776,14 +779,22 @@ void ObjectManipulation::update_if_dirty()
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++ i) {
|
for (int i = 0; i < 3; ++ i) {
|
||||||
auto update = [this, i](Vec3d &cached, Vec3d &cached_rounded, ManipulationEditorKey key_id, const Vec3d &new_value) {
|
auto update = [this, i](Vec3d &cached, Vec3d &cached_rounded, ManipulationEditorKey key_id, const Vec3d &new_value) {
|
||||||
wxString new_text = double_to_string(new_value(i), 2);
|
wxString new_text = double_to_string(new_value(i), m_imperial_units && key_id == meSize ? 4 : 2);
|
||||||
double new_rounded;
|
double new_rounded;
|
||||||
new_text.ToDouble(&new_rounded);
|
new_text.ToDouble(&new_rounded);
|
||||||
if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) {
|
if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) {
|
||||||
cached_rounded(i) = new_rounded;
|
cached_rounded(i) = new_rounded;
|
||||||
const int id = key_id*3+i;
|
const int id = key_id*3+i;
|
||||||
if (m_imperial_units && (key_id == mePosition || key_id == meSize))
|
if (m_imperial_units) {
|
||||||
new_text = double_to_string(new_value(i)*mm_to_in, 2);
|
double inch_value = new_value(i) * mm_to_in;
|
||||||
|
if (key_id == mePosition)
|
||||||
|
new_text = double_to_string(inch_value, 2);
|
||||||
|
if (key_id == meSize) {
|
||||||
|
if(std::abs(m_cache.size_inches(i) - inch_value) > EPSILON)
|
||||||
|
m_cache.size_inches(i) = inch_value;
|
||||||
|
new_text = double_to_string(inch_value, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (id >= 0) m_editors[id]->set_value(new_text);
|
if (id >= 0) m_editors[id]->set_value(new_text);
|
||||||
}
|
}
|
||||||
cached(i) = new_value(i);
|
cached(i) = new_value(i);
|
||||||
|
@ -1137,6 +1148,13 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
||||||
if (value <= 0.0)
|
if (value <= 0.0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_imperial_units) {
|
||||||
|
if (std::abs(m_cache.size_inches(axis) - value) < EPSILON)
|
||||||
|
return;
|
||||||
|
m_cache.size_inches(axis) = value;
|
||||||
|
value *= in_to_mm;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::abs(m_cache.size_rounded(axis) - value) < EPSILON)
|
if (std::abs(m_cache.size_rounded(axis) - value) < EPSILON)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1237,11 +1255,11 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
||||||
if (!m_cache.is_valid())
|
if (!m_cache.is_valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_imperial_units && (opt_key == "position" || opt_key == "size"))
|
if (opt_key == "position") {
|
||||||
new_value *= in_to_mm;
|
if (m_imperial_units)
|
||||||
|
new_value *= in_to_mm;
|
||||||
if (opt_key == "position")
|
|
||||||
change_position_value(axis, new_value);
|
change_position_value(axis, new_value);
|
||||||
|
}
|
||||||
else if (opt_key == "rotation")
|
else if (opt_key == "rotation")
|
||||||
change_rotation_value(axis, new_value);
|
change_rotation_value(axis, new_value);
|
||||||
else if (opt_key == "scale") {
|
else if (opt_key == "scale") {
|
||||||
|
|
|
@ -85,6 +85,7 @@ private:
|
||||||
Vec3d scale;
|
Vec3d scale;
|
||||||
Vec3d scale_rounded;
|
Vec3d scale_rounded;
|
||||||
Vec3d size;
|
Vec3d size;
|
||||||
|
Vec3d size_inches;
|
||||||
Vec3d size_rounded;
|
Vec3d size_rounded;
|
||||||
|
|
||||||
wxString move_label_string;
|
wxString move_label_string;
|
||||||
|
|
|
@ -705,8 +705,17 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
|
||||||
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
|
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if ticks_info_from_model contains ColorChange g-code
|
||||||
|
bool color_change_already_exists = false;
|
||||||
|
for (const CustomGCode::Item& gcode: ticks_info_from_model.gcodes)
|
||||||
|
if (gcode.type == CustomGCode::Type::ColorChange) {
|
||||||
|
color_change_already_exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Suggest the auto color change, if model looks like sign
|
// Suggest the auto color change, if model looks like sign
|
||||||
if (wxGetApp().app_config->get("allow_auto_color_change") == "1" &&
|
if (!color_change_already_exists &&
|
||||||
|
wxGetApp().app_config->get("allow_auto_color_change") == "1" &&
|
||||||
m_layers_slider->IsNewPrint())
|
m_layers_slider->IsNewPrint())
|
||||||
{
|
{
|
||||||
const Print& print = wxGetApp().plater()->fff_print();
|
const Print& print = wxGetApp().plater()->fff_print();
|
||||||
|
@ -804,6 +813,7 @@ void Preview::update_layers_slider_mode()
|
||||||
|
|
||||||
for (const auto& range : object->layer_config_ranges)
|
for (const auto& range : object->layer_config_ranges)
|
||||||
if (range.second.has("extruder") &&
|
if (range.second.has("extruder") &&
|
||||||
|
range.second.option("extruder")->getInt() != 0 && // extruder isn't default
|
||||||
range.second.option("extruder")->getInt() != extruder)
|
range.second.option("extruder")->getInt() != extruder)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
#include "slic3r/GUI/format.hpp"
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "slic3r/Utils/UndoRedo.hpp"
|
#include "slic3r/Utils/UndoRedo.hpp"
|
||||||
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
@ -39,6 +41,8 @@ bool GLGizmoFdmSupports::on_init()
|
||||||
{
|
{
|
||||||
m_shortcut_key = WXK_CONTROL_L;
|
m_shortcut_key = WXK_CONTROL_L;
|
||||||
|
|
||||||
|
m_desc["auto_generate"] = _L("Auto-generate supports");
|
||||||
|
m_desc["generating"] = _L("Generating supports...");
|
||||||
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
||||||
m_desc["reset_direction"] = _L("Reset direction");
|
m_desc["reset_direction"] = _L("Reset direction");
|
||||||
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
||||||
|
@ -91,7 +95,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
if (! m_c->selection_info()->model_object())
|
if (! m_c->selection_info()->model_object())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float approx_height = m_imgui->scaled(23.f);
|
const float approx_height = m_imgui->scaled(25.f);
|
||||||
y = std::min(y, bottom_limit - approx_height);
|
y = std::min(y, bottom_limit - approx_height);
|
||||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||||
|
|
||||||
|
@ -153,6 +157,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (waiting_for_autogenerated_supports) {
|
||||||
|
m_imgui->text(m_desc.at("generating"));
|
||||||
|
} else {
|
||||||
|
bool generate = m_imgui->button(m_desc.at("auto_generate"));
|
||||||
|
if (generate)
|
||||||
|
auto_generate();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
float position_before_text_y = ImGui::GetCursorPos().y;
|
float position_before_text_y = ImGui::GetCursorPos().y;
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
|
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
|
||||||
|
@ -319,6 +332,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
}
|
}
|
||||||
|
|
||||||
update_model_object();
|
update_model_object();
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,9 +380,54 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||||
: _L("Add supports by angle"));
|
: _L("Add supports by angle"));
|
||||||
update_model_object();
|
update_model_object();
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::data_changed()
|
||||||
|
{
|
||||||
|
GLGizmoPainterBase::data_changed();
|
||||||
|
if (! m_c->selection_info())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
if (mo && this->waiting_for_autogenerated_supports) {
|
||||||
|
get_data_from_backend();
|
||||||
|
} else {
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::get_data_from_backend()
|
||||||
|
{
|
||||||
|
if (! has_backend_supports())
|
||||||
|
return;
|
||||||
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
|
||||||
|
// find the respective PrintObject, we need a pointer to it
|
||||||
|
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||||
|
if (po->model_object()->id() == mo->id()) {
|
||||||
|
std::unordered_map<size_t, const ModelVolume*> mvs;
|
||||||
|
for (const ModelVolume* mv : po->model_object()->volumes) {
|
||||||
|
if (mv->is_model_part()) {
|
||||||
|
mvs.emplace(mv->id().id, mv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int mesh_id = -1.0f;
|
||||||
|
for (ModelVolume* mv : mo->volumes){
|
||||||
|
if (mv->is_model_part()){
|
||||||
|
mesh_id++;
|
||||||
|
mv->supported_facets.assign(mvs[mv->id().id]->supported_facets);
|
||||||
|
m_triangle_selectors[mesh_id]->deserialize(mv->supported_facets.get_data(), true);
|
||||||
|
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||||
|
m_parent.set_as_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_model_object() const
|
void GLGizmoFdmSupports::update_model_object() const
|
||||||
|
@ -391,8 +450,6 @@ void GLGizmoFdmSupports::update_model_object() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_from_model_object()
|
void GLGizmoFdmSupports::update_from_model_object()
|
||||||
{
|
{
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
|
@ -417,6 +474,58 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLGizmoFdmSupports::has_backend_supports() const
|
||||||
|
{
|
||||||
|
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
if (! mo)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// find PrintObject with this ID
|
||||||
|
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||||
|
if (po->model_object()->id() == mo->id())
|
||||||
|
return po->is_step_done(posSupportSpotsSearch);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const {
|
||||||
|
wxGetApp().CallAfter(
|
||||||
|
[this, postpone_error_messages]() {
|
||||||
|
wxGetApp().plater()->reslice_FFF_until_step(posSupportSpotsSearch,
|
||||||
|
*m_c->selection_info()->model_object(), postpone_error_messages);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::auto_generate()
|
||||||
|
{
|
||||||
|
ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
|
bool not_painted = std::all_of(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume* vol){
|
||||||
|
return vol->type() != ModelVolumeType::MODEL_PART || vol->supported_facets.empty();
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageDialog dlg(GUI::wxGetApp().plater(),
|
||||||
|
_L("Autogeneration will erase all currently painted areas.") + "\n\n" +
|
||||||
|
_L("Are you sure you want to do it?") + "\n",
|
||||||
|
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||||
|
|
||||||
|
if (not_painted || dlg.ShowModal() == wxID_YES) {
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
|
||||||
|
int mesh_id = -1.0f;
|
||||||
|
for (ModelVolume *mv : mo->volumes) {
|
||||||
|
if (mv->is_model_part()) {
|
||||||
|
mesh_id++;
|
||||||
|
mv->supported_facets.reset();
|
||||||
|
m_triangle_selectors[mesh_id]->reset();
|
||||||
|
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mo->config.set("support_material", true);
|
||||||
|
mo->config.set("support_material_auto", false);
|
||||||
|
this->waiting_for_autogenerated_supports = true;
|
||||||
|
wxGetApp().CallAfter([this]() { reslice_FDM_supports(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const
|
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const
|
||||||
|
|
|
@ -26,6 +26,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool on_init() override;
|
bool on_init() override;
|
||||||
|
void data_changed() override;
|
||||||
|
|
||||||
void update_model_object() const override;
|
void update_model_object() const override;
|
||||||
void update_from_model_object() override;
|
void update_from_model_object() override;
|
||||||
|
@ -39,6 +40,13 @@ private:
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
std::map<std::string, wxString> m_desc;
|
std::map<std::string, wxString> m_desc;
|
||||||
|
|
||||||
|
|
||||||
|
bool waiting_for_autogenerated_supports = false;
|
||||||
|
bool has_backend_supports() const;
|
||||||
|
void reslice_FDM_supports(bool postpone_error_messages = false) const;
|
||||||
|
void auto_generate();
|
||||||
|
void get_data_from_backend();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,9 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
||||||
{ImGui::PreferencesHoverButton, "notification_preferences_hover"},
|
{ImGui::PreferencesHoverButton, "notification_preferences_hover"},
|
||||||
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
|
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
|
||||||
{ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" },
|
{ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
{ImGui::LegendTravel , "legend_travel" },
|
{ImGui::LegendTravel , "legend_travel" },
|
||||||
{ImGui::LegendWipe , "legend_wipe" },
|
{ImGui::LegendWipe , "legend_wipe" },
|
||||||
|
@ -73,9 +76,6 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
||||||
{ImGui::LegendShells , "legend_shells" },
|
{ImGui::LegendShells , "legend_shells" },
|
||||||
{ImGui::LegendToolMarker , "legend_toolmarker" },
|
{ImGui::LegendToolMarker , "legend_toolmarker" },
|
||||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
};
|
|
||||||
|
|
||||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
|
||||||
{ImGui::CloseNotifButton , "notification_close" },
|
{ImGui::CloseNotifButton , "notification_close" },
|
||||||
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
|
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
|
||||||
{ImGui::EjectButton , "notification_eject_sd" },
|
{ImGui::EjectButton , "notification_eject_sd" },
|
||||||
|
@ -97,7 +97,6 @@ static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||||
|
|
||||||
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
|
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
|
||||||
{ImGui::ClippyMarker , "notification_clippy" },
|
{ImGui::ClippyMarker , "notification_clippy" },
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f };
|
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f };
|
||||||
|
|
|
@ -75,12 +75,12 @@ void KBShortcutsDialog::fill_shortcuts()
|
||||||
Shortcuts commands_shortcuts = {
|
Shortcuts commands_shortcuts = {
|
||||||
// File
|
// File
|
||||||
{ ctrl + "N", L("New project, clear plater") },
|
{ ctrl + "N", L("New project, clear plater") },
|
||||||
{ ctrl + "O", L("Open project STL/OBJ/AMF/3MF with config, clear plater") },
|
{ ctrl + "O", L("Open project AMF/3MF with config, clear plater") },
|
||||||
{ ctrl + "S", L("Save project (3mf)") },
|
{ ctrl + "S", L("Save project (3mf)") },
|
||||||
{ ctrl + alt + "S", L("Save project as (3mf)") },
|
{ ctrl + alt + "S", L("Save project as (3mf)") },
|
||||||
{ ctrl + "R", L("(Re)slice") },
|
{ ctrl + "R", L("(Re)slice") },
|
||||||
// File>Import
|
// File>Import
|
||||||
{ ctrl + "I", L("Import STL/OBJ/AMF/3MF/STEP without config, keep plater") },
|
{ ctrl + "I", L("Import STL/3MF/STEP/OBJ/AMF without config, keep plater") },
|
||||||
{ ctrl + "L", L("Import Config from ini/amf/3mf/gcode") },
|
{ ctrl + "L", L("Import Config from ini/amf/3mf/gcode") },
|
||||||
{ ctrl + alt + "L", L("Load Config from ini/amf/3mf/gcode and merge") },
|
{ ctrl + alt + "L", L("Load Config from ini/amf/3mf/gcode and merge") },
|
||||||
// File>Export
|
// File>Export
|
||||||
|
|
|
@ -277,8 +277,52 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||||
|
|
||||||
preferences_dialog = new PreferencesDialog(this);
|
preferences_dialog = new PreferencesDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind events from DiffDlg
|
||||||
|
|
||||||
|
bind_diff_dialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainFrame::bind_diff_dialog()
|
||||||
|
{
|
||||||
|
auto get_tab = [](Preset::Type type) {
|
||||||
|
Tab* null_tab = nullptr;
|
||||||
|
for (Tab* tab : wxGetApp().tabs_list)
|
||||||
|
if (tab->type() == type)
|
||||||
|
return tab;
|
||||||
|
return null_tab;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto transfer = [this, get_tab](Preset::Type type) {
|
||||||
|
get_tab(type)->transfer_options(diff_dialog.get_left_preset_name(type),
|
||||||
|
diff_dialog.get_right_preset_name(type),
|
||||||
|
std::move(diff_dialog.get_selected_options(type)));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto save = [this, get_tab](Preset::Type type) {
|
||||||
|
get_tab(type)->save_options(diff_dialog.get_left_preset_name(type),
|
||||||
|
diff_dialog.get_right_preset_name(type),
|
||||||
|
std::move(diff_dialog.get_selected_options(type)));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto process_options = [this](std::function<void(Preset::Type)> process) {
|
||||||
|
const Preset::Type diff_dlg_type = diff_dialog.view_type();
|
||||||
|
if (diff_dlg_type == Preset::TYPE_INVALID) {
|
||||||
|
for (const Preset::Type& type : diff_dialog.printer_technology() == ptFFF ?
|
||||||
|
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT} :
|
||||||
|
std::initializer_list<Preset::Type>{ Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL } )
|
||||||
|
process(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
process(diff_dlg_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
diff_dialog.Bind(EVT_DIFF_DIALOG_TRANSFER, [this, process_options, transfer](SimpleEvent&) { process_options(transfer); });
|
||||||
|
|
||||||
|
diff_dialog.Bind(EVT_DIFF_DIALOG_SAVE, [this, process_options, save](SimpleEvent&) { process_options(save); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSW_DARK_MODE
|
#ifdef _MSW_DARK_MODE
|
||||||
static wxString pref() { return " [ "; }
|
static wxString pref() { return " [ "; }
|
||||||
static wxString suff() { return " ] "; }
|
static wxString suff() { return " ] "; }
|
||||||
|
@ -1219,7 +1263,7 @@ void MainFrame::init_menubar_as_editor()
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
|
|
||||||
wxMenu* import_menu = new wxMenu();
|
wxMenu* import_menu = new wxMenu();
|
||||||
append_menu_item(import_menu, wxID_ANY, _L("Import STL/OBJ/AM&F/3MF/STEP") + dots + "\tCtrl+I", _L("Load a model"),
|
append_menu_item(import_menu, wxID_ANY, _L("Import STL/3MF/STEP/OBJ/AM&F") + dots + "\tCtrl+I", _L("Load a model"),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr,
|
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr,
|
||||||
[this](){return m_plater != nullptr; }, this);
|
[this](){return m_plater != nullptr; }, this);
|
||||||
|
|
||||||
|
@ -2130,9 +2174,6 @@ void MainFrame::add_to_recent_projects(const wxString& filename)
|
||||||
|
|
||||||
void MainFrame::technology_changed()
|
void MainFrame::technology_changed()
|
||||||
{
|
{
|
||||||
// upadte DiffDlg
|
|
||||||
diff_dialog.update_presets();
|
|
||||||
|
|
||||||
// update menu titles
|
// update menu titles
|
||||||
PrinterTechnology pt = plater()->printer_technology();
|
PrinterTechnology pt = plater()->printer_technology();
|
||||||
if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND)
|
if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND)
|
||||||
|
|
|
@ -107,6 +107,7 @@ class MainFrame : public DPIFrame
|
||||||
bool can_delete() const;
|
bool can_delete() const;
|
||||||
bool can_delete_all() const;
|
bool can_delete_all() const;
|
||||||
bool can_reslice() const;
|
bool can_reslice() const;
|
||||||
|
void bind_diff_dialog();
|
||||||
|
|
||||||
// MenuBar items changeable in respect to printer technology
|
// MenuBar items changeable in respect to printer technology
|
||||||
enum MenuItems
|
enum MenuItems
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue