Merge branch 'master' into fs_emboss
# Conflicts: # src/slic3r/GUI/GLCanvas3D.cpp # src/slic3r/GUI/Selection.cpp
|
@ -46,7 +46,7 @@ BreakConstructorInitializersBeforeComma: false
|
|||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 78
|
||||
ColumnLimit: 140
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
|
|
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 Width: | Height: | Size: 1.5 KiB |
|
@ -2135,8 +2135,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Vyberte jeden nebo více souborů (STL, OBJ):"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Vyberte jeden nebo více souborů (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/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
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)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Importovat STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Importovat STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "Importovat STL/OBJ/AMF/3MF bez konfigurace, zachová stávající podložku"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr ""
|
||||
"Importovat STL/3MF/STEP/OBJ/AMF bez konfigurace, zachová stávající podložku"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8227,9 +8228,8 @@ msgid "Open new instance"
|
|||
msgstr "Otevřít novou instanci"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr ""
|
||||
"Otevřít projekt STL/OBJ/AMF/3MF s konfigurací, odstranit modely na podložce"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Otevřít projekt AMF/3MF s konfigurací, odstranit modely na podložce"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2130,8 +2130,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Wählen Sie eine oder mehrere Dateien (STL, OBJ):"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Wählen Sie eine oder mehrere Dateien (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/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
msgid "Choose the type of firmware used by your printer."
|
||||
|
@ -6141,13 +6141,13 @@ msgid "Import STL (Imperial Units)"
|
|||
msgstr "STL importieren (imperiale Einheiten)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Importiere STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Importiere STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: 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 ""
|
||||
"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
|
||||
msgid "Import config only"
|
||||
|
@ -8357,8 +8357,8 @@ msgid "Open new instance"
|
|||
msgstr "Neue Instanz öffnen"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr "Öffne Projekt STL/OBJ/AMF/3MF mit Konfiguration, Druckplatte leeren"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Öffne Projekt AMF/3MF mit Konfiguration, Druckplatte leeren"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2115,8 +2115,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Elije uno o varios archivos (STL, OBJ):"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Escoje uno o más archivos (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/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
msgid "Choose the type of firmware used by your printer."
|
||||
|
@ -6096,12 +6096,12 @@ msgid "Import STL (Imperial Units)"
|
|||
msgstr "Importar STL (Unidades Imperiales)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Importar STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Importar STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "Importar STL/OBJ/AMF/3MF sin configuración, mantener la base"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr "Importar STL/3MF/STEP/OBJ/AMF sin configuración, mantener la base"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8302,8 +8302,8 @@ msgid "Open new instance"
|
|||
msgstr "Abrir instancia nueva"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr "Abrir proyecto STL/OBJ/AMF/3MF con configuración, limpiar plataforma"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Abrir proyecto AMF/3MF con configuración, limpiar plataforma"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2139,8 +2139,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Choisissez un ou plusieurs fichiers (STL, OBJ) :"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Choisir un ou plusieurs fichiers (STL/OBJ/AMF/3MF/PRUSA) :"
|
||||
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
msgstr "Choisir un ou plusieurs fichiers (STL/3MF/STEP/OBJ/AMF/PRUSA) :"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
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)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Importer STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Importer STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "Importer un STL/OBJ/AMF/3MF sans configuration, conserver le plateau"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr "Importer un STL/3MF/STEP/OBJ/AMF sans configuration, conserver le plateau"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8375,9 +8375,8 @@ msgid "Open new instance"
|
|||
msgstr "Ouvrir une nouvelle instance"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr ""
|
||||
"Ouvrir un projet STL/OBJ/AMF/3MF avec configuration, libérer le plateau"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Ouvrir un projet AMF/3MF avec configuration, libérer le plateau"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2119,8 +2119,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Scegli uno o più file (STL, OBJ):"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Seleziona uno o più file (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
msgstr "Seleziona uno o più file (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
msgid "Choose the type of firmware used by your printer."
|
||||
|
@ -6091,12 +6091,12 @@ msgid "Import STL (Imperial Units)"
|
|||
msgstr "Importa STL (unità imperiali)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Importa STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Importa STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "Importa STL/OBJ/AMF/3MF senza configurazione, mantieni piano"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr "Importa STL/3MF/STEP/OBJ/AMF senza configurazione, mantieni piano"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8294,8 +8294,8 @@ msgid "Open new instance"
|
|||
msgstr "Apri una nuova istanza"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr "Apri progetto STL/OBJ/AMF/3MF con configurazione, pulisci piano"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Apri progetto AMF/3MF con configurazione, pulisci piano"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2081,8 +2081,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "1つ以上のファイル(STL, OBJ)を選択します:"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "1つ以上のファイルの選択(STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgid "Choose one or more files (STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
msgstr "1つ以上のファイルの選択(STL/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
msgid "Choose the type of firmware used by your printer."
|
||||
|
@ -5963,12 +5963,12 @@ msgid "Import STL (Imperial Units)"
|
|||
msgstr "STLのインポート(インチ)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "STL/OBJ/AMF/3MFのインポート(&F)"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "STL/3MF/STEP/OBJ/AMFのインポート(&F)"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "既存のプレートを保持しながらSTL/OBJ/AMF/3MFを設定なしでインポート"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr "既存のプレートを保持しながらSTL/3MF/STEP/OBJ/AMFを設定なしでインポート"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8124,8 +8124,8 @@ msgid "Open new instance"
|
|||
msgstr "新しいインスタンスを開く"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr "プロジェクトSTL/OBJ/AMF/3MFを設定を含めて開き、プレートをクリアします"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "プロジェクトAMF/3MFを設定を含めて開き、プレートをクリアします"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
|
@ -2145,8 +2145,8 @@ msgid "Choose one or more files (STL, OBJ):"
|
|||
msgstr "Wybierz jeden lub więcej plików (STL, OBJ):"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1870
|
||||
msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
msgstr "Wybierz jeden lub więcej plików (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/3MF/STEP/OBJ/AMF/PRUSA):"
|
||||
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:1361
|
||||
msgid "Choose the type of firmware used by your printer."
|
||||
|
@ -6080,12 +6080,12 @@ msgid "Import STL (Imperial Units)"
|
|||
msgstr "Import STL (jednostki imperialne)"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1208
|
||||
msgid "Import STL/OBJ/AM&F/3MF"
|
||||
msgstr "Import STL/OBJ/AM&F/3MF"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
msgstr "Import STL/3MF/STEP/OBJ/AM&F"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:83
|
||||
msgid "Import STL/OBJ/AMF/3MF without config, keep plater"
|
||||
msgstr "Otwórz STL/OBJ/AMF/3MF bez konfiguracji, zachowaj zawartość stołu"
|
||||
msgid "Import STL/3MF/STEP/OBJ/AMF without config, keep plater"
|
||||
msgstr "Otwórz STL/3MF/STEP/OBJ/AMF bez konfiguracji, zachowaj zawartość stołu"
|
||||
|
||||
#: src/slic3r/GUI/Plater.cpp:5293
|
||||
msgid "Import config only"
|
||||
|
@ -8279,8 +8279,8 @@ msgid "Open new instance"
|
|||
msgstr "Otwórz nową instancję"
|
||||
|
||||
#: src/slic3r/GUI/KBShortcutsDialog.cpp:78
|
||||
msgid "Open project STL/OBJ/AMF/3MF with config, clear plater"
|
||||
msgstr "Otwórz projekt STL/OBJ/AMF/3MF z konfiguracją, wyczyść stół"
|
||||
msgid "Open project AMF/3MF with config, clear plater"
|
||||
msgstr "Otwórz projekt AMF/3MF z konfiguracją, wyczyść stół"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:1082
|
||||
#, c-format, boost-format
|
||||
|
|
BIN
resources/profiles/Creality/ENDER5PRO_thumbnail.png
Normal file
After Width: | Height: | Size: 28 KiB |
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
|
@ -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
After Width: | Height: | Size: 53 KiB |
BIN
resources/profiles/Rigid3D/Mucit_thumbnail.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
resources/profiles/Rigid3D/Zero2_thumbnail.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
resources/profiles/Rigid3D/Zero3_thumbnail.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/mucit_bed.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
resources/profiles/Rigid3D/mucit_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/zero2_bed.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero3_bed.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero_bed.stl
Normal file
|
@ -1,8 +1,6 @@
|
|||
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/EdgeGrid.hpp"
|
||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||
#include "libslic3r/Line.hpp"
|
||||
|
||||
|
|
|
@ -250,6 +250,8 @@ set(SLIC3R_SOURCES
|
|||
SlicingAdaptive.hpp
|
||||
Subdivide.cpp
|
||||
Subdivide.hpp
|
||||
SupportSpotsGenerator.cpp
|
||||
SupportSpotsGenerator.hpp
|
||||
SupportMaterial.cpp
|
||||
SupportMaterial.hpp
|
||||
Surface.cpp
|
||||
|
@ -283,6 +285,8 @@ set(SLIC3R_SOURCES
|
|||
TriangleSelector.hpp
|
||||
TriangleSetSampling.cpp
|
||||
TriangleSetSampling.hpp
|
||||
TriangleSelectorWrapper.cpp
|
||||
TriangleSelectorWrapper.hpp
|
||||
MTUtils.hpp
|
||||
Zipper.hpp
|
||||
Zipper.cpp
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "libslic3r/format.hpp"
|
||||
#include "GCodeProcessor.hpp"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
@ -777,8 +778,7 @@ void GCodeProcessorResult::reset() {
|
|||
max_print_height = 0.0f;
|
||||
settings_ids.reset();
|
||||
extruders_count = 0;
|
||||
extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
||||
assert(extruder_colors.size() == MIN_EXTRUDERS_COUNT);
|
||||
extruder_colors = std::vector<std::string>();
|
||||
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||
#if ENABLE_USED_FILAMENT_POST_PROCESS
|
||||
|
@ -870,6 +870,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
{
|
||||
m_parser.apply_config(config);
|
||||
|
||||
m_producer = EProducer::PrusaSlicer;
|
||||
m_flavor = config.gcode_flavor;
|
||||
|
||||
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;
|
||||
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
|
||||
if (machine_limits_usage != nullptr)
|
||||
|
@ -1289,6 +1304,7 @@ void GCodeProcessor::reset()
|
|||
m_options_z_corrector.reset();
|
||||
|
||||
m_spiral_vase_active = false;
|
||||
m_kissslicer_toolchange_time_correction = 0.0f;
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
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);
|
||||
apply_config(config);
|
||||
}
|
||||
else if (m_producer == EProducer::Simplify3D)
|
||||
apply_config_simplify3d(filename);
|
||||
else if (m_producer == EProducer::SuperSlicer)
|
||||
apply_config_superslicer(filename);
|
||||
else {
|
||||
m_result.extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
||||
|
||||
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
|
||||
|
@ -1529,6 +1551,82 @@ void GCodeProcessor::apply_config_superslicer(const std::string& filename)
|
|||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
m_producer = id;
|
||||
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
|
||||
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
unsigned char id = static_cast<unsigned char>(eid);
|
||||
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.";
|
||||
else {
|
||||
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));
|
||||
m_time_processor.extruder_unloaded = false;
|
||||
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);
|
||||
|
||||
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;
|
||||
size_t m_last_default_color_id;
|
||||
bool m_spiral_vase_active;
|
||||
float m_kissslicer_toolchange_time_correction;
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
@ -648,6 +649,7 @@ namespace Slic3r {
|
|||
void apply_config(const DynamicPrintConfig& config);
|
||||
void apply_config_simplify3d(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);
|
||||
|
||||
// Process tags embedded into comments
|
||||
|
|
|
@ -395,8 +395,7 @@ struct GlobalModelInfo {
|
|||
;
|
||||
|
||||
//Extract perimeter polygons of the given layer
|
||||
Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition configured_seam_preference,
|
||||
std::vector<const LayerRegion*> &corresponding_regions_out) {
|
||||
Polygons extract_perimeter_polygons(const Layer *layer, std::vector<const LayerRegion*> &corresponding_regions_out) {
|
||||
Polygons polygons;
|
||||
for (const LayerRegion *layer_region : layer->regions()) {
|
||||
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
|
||||
|| (is_perimeter(role)
|
||||
&& configured_seam_preference == spRandom)) { //for random seam alignment, extract all perimeters
|
||||
if (role == ExtrusionRole::erExternalPerimeter) {
|
||||
Points p;
|
||||
perimeter->collect_points(p);
|
||||
polygons.emplace_back(std::move(p));
|
||||
|
@ -1044,14 +1041,13 @@ public:
|
|||
// Parallel process and extract each perimeter polygon of the given print object.
|
||||
// Gather SeamCandidates of each layer into vector and build KDtree over them
|
||||
// Store results in the SeamPlacer variables m_seam_per_object
|
||||
void SeamPlacer::gather_seam_candidates(const PrintObject *po,
|
||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference) {
|
||||
void SeamPlacer::gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info) {
|
||||
using namespace SeamPlacerImpl;
|
||||
PrintObjectSeamData &seam_data = m_seam_per_object.emplace(po, PrintObjectSeamData { }).first->second;
|
||||
seam_data.layers.resize(po->layer_count());
|
||||
|
||||
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) {
|
||||
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++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;
|
||||
std::vector<const LayerRegion*> regions;
|
||||
//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) {
|
||||
process_perimeter_polygon(polygons[poly_index], unscaled_z,
|
||||
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();
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "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)
|
||||
<< "SeamPlacer: gather_seam_candidates: end";
|
||||
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 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;
|
||||
if (current.segment_idx >= loop.paths[current.path_idx].polyline.points.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) {
|
||||
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);
|
||||
closest_perimeter_point_index = find_closest_point(*layer_perimeters.points_tree.get(),
|
||||
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());
|
||||
|
||||
if (const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
||||
(po->config().seam_position == spNearest || po->config().seam_position == spAligned) &&
|
||||
loop.role() == ExtrusionRole::erPerimeter && //Hopefully internal perimeter
|
||||
(seam_position - perimeter_point.position).squaredNorm() < 4.0f && // seam is on perimeter point
|
||||
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
|
||||
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
|
||||
// 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)
|
||||
if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter
|
||||
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
||||
ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false);
|
||||
// determine depth of the seam point.
|
||||
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
|
||||
float beta_angle = cos(perimeter_point.local_ccw_angle / 2.0f);
|
||||
size_t index_of_prev =
|
||||
seam_index == perimeter_point.perimeter.start_index ?
|
||||
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 :
|
||||
seam_index + 1;
|
||||
|
||||
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;
|
||||
if ((seam_position - perimeter_point.position).squaredNorm() < depth && // seam is on perimeter point
|
||||
perimeter_point.local_ccw_angle < -EPSILON // In concave angles
|
||||
) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align
|
||||
// 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);
|
||||
//get closest projected point, determine depth of the seam point.
|
||||
float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm();
|
||||
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.
|
||||
//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>() + (1.4142 * depth / angle_factor) * dir_to_middle;
|
||||
seam_point = Point::new_scale(final_pos.x(), final_pos.y());
|
||||
seam_point = projected_point.foot_pt;
|
||||
|
||||
//lastly, for internal perimeters, do the staggering if requested
|
||||
if (po->config().staggered_inner_seams && loop.length() > 0.0) {
|
||||
//fix depth, it is sometimes strongly underestimated
|
||||
depth = std::max(loop.paths[projected_point.path_idx].width, depth);
|
||||
|
||||
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,
|
||||
|
|
|
@ -143,8 +143,7 @@ public:
|
|||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
|
||||
private:
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info,
|
||||
const SeamPosition configured_seam_preference);
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_candidates_visibility(const PrintObject *po,
|
||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
|
@ -577,6 +581,8 @@ void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
|||
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
||||
{
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
assert(scaling_factor > 0.0);
|
||||
|
||||
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||
scale(axis, axis) = scaling_factor;
|
||||
|
||||
|
@ -600,8 +606,11 @@ Vec3d Transformation::get_mirror() const
|
|||
|
||||
Transform3d Transformation::get_mirror_matrix() const
|
||||
{
|
||||
const Vec3d scale = get_scaling_factor();
|
||||
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
|
||||
Transform3d scale = extract_scale(m_matrix);
|
||||
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
|
||||
|
||||
|
@ -617,13 +626,17 @@ void Transformation::set_mirror(const Vec3d& mirror)
|
|||
copy(i) /= abs_mirror(i);
|
||||
}
|
||||
|
||||
const Vec3d curr_scale = get_scaling_factor();
|
||||
const Vec3d signs = curr_scale.cwiseProduct(copy);
|
||||
set_scaling_factor({
|
||||
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(),
|
||||
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
|
||||
});
|
||||
auto [rotation, scale] = extract_rotation_scale(m_matrix);
|
||||
const Vec3d curr_scales = { scale(0, 0), scale(1, 1), scale(2, 2) };
|
||||
const Vec3d signs = curr_scales.cwiseProduct(copy);
|
||||
|
||||
if (signs[0] < 0.0) scale(0, 0) = -scale(0, 0);
|
||||
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
|
||||
set_mirror(X, mirror.x());
|
||||
set_mirror(Y, mirror.y());
|
||||
|
@ -640,9 +653,15 @@ void Transformation::set_mirror(Axis axis, double mirror)
|
|||
mirror /= abs_mirror;
|
||||
|
||||
#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;
|
||||
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
|
||||
if (m_mirror(axis) != mirror) {
|
||||
m_mirror(axis) = mirror;
|
||||
|
@ -746,7 +765,6 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const
|
|||
{
|
||||
Transformation copy(*this);
|
||||
copy.reset_scaling_factor();
|
||||
copy.reset_mirror();
|
||||
return copy.get_matrix();
|
||||
}
|
||||
#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.
|
||||
out.back().p = out.front().p;
|
||||
out.front().p = out.back().p;
|
||||
|
||||
if (out.size() >= 3)
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
// 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",
|
||||
"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",
|
||||
"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",
|
||||
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
|
||||
"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.
|
||||
// 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);
|
||||
auto it = this->find_preset_internal(name);
|
||||
// Ensure that a temporary copy is returned if the preset found is currently selected.
|
||||
return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin()) :
|
||||
return (it != m_presets.end() && it->name == key.name) ? &this->preset(it - m_presets.begin(), respect_active_preset) :
|
||||
first_visible_if_not_found ? &this->first_visible() : nullptr;
|
||||
}
|
||||
|
||||
|
@ -1876,13 +1876,23 @@ bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string&
|
|||
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
|
||||
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;
|
||||
|
||||
for (auto printer : m_printers) {
|
||||
if (printer.preset_names.size() == 1)
|
||||
if (!respect_only_preset && printer.preset_names.size() == 1)
|
||||
continue;
|
||||
if (printer.preset_names.find(preset_name) != printer.preset_names.end())
|
||||
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]; }
|
||||
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.
|
||||
Preset& preset(size_t idx) { return (idx == m_idx_selected) ? m_edited_preset : m_presets[idx]; }
|
||||
const Preset& preset(size_t idx) const { return const_cast<PresetCollection*>(this)->preset(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, bool respect_active_preset = true) const { return const_cast<PresetCollection*>(this)->preset(idx); }
|
||||
void discard_current_changes() {
|
||||
m_presets[m_idx_selected].reset_dirty();
|
||||
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.
|
||||
// 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);
|
||||
const Preset* find_preset(const std::string &name, bool first_visible_if_not_found = false) const
|
||||
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found); }
|
||||
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, bool respect_active_preset = true) const
|
||||
{ return const_cast<PresetCollection*>(this)->find_preset(name, first_visible_if_not_found, respect_active_preset); }
|
||||
|
||||
size_t first_visible_idx() const;
|
||||
// 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
|
||||
// returns true if all presets were deleted successfully.
|
||||
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
|
||||
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
|
||||
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);
|
||||
|
||||
|
|
|
@ -825,6 +825,8 @@ void Print::process()
|
|||
obj->infill();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->ironing();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_spots();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_material();
|
||||
if (this->set_started(psWipeTower)) {
|
||||
|
|
|
@ -61,7 +61,7 @@ enum PrintStep : unsigned int {
|
|||
|
||||
enum PrintObjectStep : unsigned int {
|
||||
posSlice, posPerimeters, posPrepareInfill,
|
||||
posInfill, posIroning, posSupportMaterial, posCount,
|
||||
posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount,
|
||||
};
|
||||
|
||||
// A PrintRegion object represents a group of volumes to print
|
||||
|
@ -381,6 +381,7 @@ private:
|
|||
void prepare_infill();
|
||||
void infill();
|
||||
void ironing();
|
||||
void generate_support_spots();
|
||||
void generate_support_material();
|
||||
|
||||
void slice_volumes();
|
||||
|
|
|
@ -1195,8 +1195,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
update_apply_status(false);
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
if (supports_differ) {
|
||||
// Copy just the support volumes.
|
||||
model_volume_list_update_supports(model_object, model_object_new);
|
||||
|
|
|
@ -2253,6 +2253,12 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comSimple;
|
||||
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
|
||||
def = this->add("seam_preferred_direction", coFloat);
|
||||
// def->gui_type = ConfigOptionDef::GUIType::slider;
|
||||
|
|
|
@ -503,6 +503,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, raft_first_layer_expansion))
|
||||
((ConfigOptionInt, raft_layers))
|
||||
((ConfigOptionEnum<SeamPosition>, seam_position))
|
||||
((ConfigOptionBool, staggered_inner_seams))
|
||||
// ((ConfigOptionFloat, seam_preferred_direction))
|
||||
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
|
||||
((ConfigOptionFloat, slice_closing_radius))
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include "Fill/FillAdaptive.hpp"
|
||||
#include "Fill/FillLightning.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
#include "SupportSpotsGenerator.hpp"
|
||||
#include "TriangleSelectorWrapper.hpp"
|
||||
#include "format.hpp"
|
||||
|
||||
#include <float.h>
|
||||
#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()
|
||||
{
|
||||
if (this->set_started(posSupportMaterial)) {
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include "SVG.hpp"
|
||||
#endif
|
||||
|
||||
#pragma message ("TODO: Wrap svg usages in DEBUG ifdef and remove the following include")
|
||||
#include "SVG.hpp"
|
||||
|
||||
// #undef NDEBUG
|
||||
#include <cassert>
|
||||
|
||||
|
|
1257
src/libslic3r/SupportSpotsGenerator.cpp
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 :
|
||||
0;
|
||||
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));
|
||||
// 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));
|
||||
|
@ -163,15 +162,9 @@ TreeModelVolumes::TreeModelVolumes(
|
|||
}
|
||||
|
||||
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;
|
||||
if (TreeSupport::TreeSupportSettings::has_to_rely_on_min_xy_dist_only)
|
||||
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_current_min_xy_dist = config.xy_min_distance;
|
||||
m_current_min_xy_dist_delta = config.xy_distance - m_current_min_xy_dist;
|
||||
assert(m_current_min_xy_dist_delta >= 0);
|
||||
m_increase_until_radius = config.increase_radius_until_radius;
|
||||
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 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));
|
||||
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
||||
// not currently processing meshes as this delta will be added at request time.
|
||||
// avoiding this would require saving each collision for each outline_idx separately.
|
||||
// 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.
|
||||
// so avoiding this inaccuracy seems infeasible as it would require 2x the avoidance calculations => 0.5x the performance.
|
||||
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist : settings.support_xy_distance;
|
||||
const coord_t xy_distance = outline_idx == m_current_outline_idx ? m_current_min_xy_dist :
|
||||
// technically this causes collision for the normal xy_distance to be larger by m_current_min_xy_dist_delta for all
|
||||
// not currently processing meshes as this delta will be added at request time.
|
||||
// avoiding this would require saving each collision for each outline_idx separately.
|
||||
// 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.
|
||||
// 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.
|
||||
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.
|
||||
coord_t support_bottom_height { scaled<coord_t>(1.) };
|
||||
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
|
||||
// Distance of the support structure from the print in the X/Y directions.
|
||||
// minimum: 0, maximum warning: 1.5 * machine_nozzle_tip_outer_diameter
|
||||
|
@ -75,7 +71,6 @@ struct TreeSupportMeshGroupSettings {
|
|||
// Minimum Support X/Y Distance
|
||||
// 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
|
||||
// Used if ! support_xy_overrides_z.
|
||||
coord_t support_xy_distance_overhang { scaled<coord_t>(0.2) };
|
||||
// Support Top Distance
|
||||
// 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
|
||||
// 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.
|
||||
std::vector<double> support_infill_angles {};
|
||||
// std::vector<double> support_infill_angles {};
|
||||
// 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.
|
||||
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) {
|
||||
const PrintObject &print_object = *print.get_object(object_id);
|
||||
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)
|
||||
// || 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;
|
||||
|
@ -307,7 +305,7 @@ void TreeSupport::showError(std::string message, bool critical)
|
|||
raw_overhangs_calculated = true;
|
||||
}
|
||||
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())
|
||||
// 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.
|
||||
* \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(
|
||||
const TreeModelVolumes &volumes, const TreeSupport::TreeSupportSettings &config,
|
||||
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;
|
||||
// Also checks if the position is valid, if it is NOT, it deletes that point
|
||||
for (const Polyline &line : polylines) {
|
||||
LineInformation res_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
else if (!res_line.empty()) {
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (config.support_rests_on_model && (p.second != LineStatus::TO_BP && p.second != LineStatus::TO_BP_SAFE))
|
||||
return ! contains(
|
||||
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.getCollision(config.getRadius(0), current_layer - 1, !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, min_xy_dist),
|
||||
p.first);
|
||||
return false;
|
||||
}
|
||||
|
@ -1066,12 +1066,8 @@ void TreeSupport::generateInitialAreas(
|
|||
SupportGeneratorLayersPtr &top_interface_layers,
|
||||
SupportGeneratorLayerStorage &layer_storage)
|
||||
{
|
||||
Polygon base_circle;
|
||||
const auto base_radius = scaled<int>(0.01);
|
||||
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));
|
||||
}
|
||||
static constexpr const auto base_radius = scaled<int>(0.01);
|
||||
const Polygon base_circle = make_circle(base_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
|
||||
TreeSupportMeshGroupSettings mesh_group_settings(print_object);
|
||||
TreeSupportSettings mesh_config{ mesh_group_settings };
|
||||
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 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 (mesh.overhang_areas.size() <= z_distance_delta)
|
||||
return;
|
||||
|
@ -1096,7 +1093,7 @@ void TreeSupport::generateInitialAreas(
|
|||
//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 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.
|
||||
// + 10 * mesh_config.support_line_width;
|
||||
;
|
||||
|
@ -1114,9 +1111,9 @@ void TreeSupport::generateInitialAreas(
|
|||
std::mutex mutex_layer_storage, mutex_movebounds;
|
||||
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,
|
||||
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,
|
||||
&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) {
|
||||
if (overhangs[layer_idx + z_distance_delta].empty())
|
||||
continue;
|
||||
|
@ -1124,9 +1121,9 @@ void TreeSupport::generateInitialAreas(
|
|||
Polygons relevant_forbidden;
|
||||
{
|
||||
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) :
|
||||
m_volumes.getCollision(mesh_config.getRadius(0), layer_idx, !xy_overrides_z)) :
|
||||
m_volumes.getAvoidance(mesh_config.getRadius(0), layer_idx, AvoidanceType::Fast, false, !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, min_xy_dist)) :
|
||||
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.
|
||||
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))) {
|
||||
// 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));
|
||||
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();
|
||||
validate_range(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.
|
||||
//=> 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;
|
||||
{
|
||||
//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);
|
||||
}
|
||||
|
||||
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
|
||||
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.
|
||||
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);
|
||||
if (mesh_group_settings.minimum_support_area > 0)
|
||||
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))
|
||||
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 ?
|
||||
(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.getCollision(mesh_config.getRadius(0), layer_idx - (dtt_roof + 1), !xy_overrides_z)) :
|
||||
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, true, min_xy_dist) :
|
||||
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, min_xy_dist);
|
||||
// prevent rounding errors down the line
|
||||
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;
|
||||
#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.
|
||||
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);
|
||||
branch_circle.points.emplace_back(coord_t(cos(angle) * m_config.branch_radius), coord_t(sin(angle) * m_config.branch_radius));
|
||||
}
|
||||
|
||||
// Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
|
||||
const Polygon branch_circle = make_circle(m_config.branch_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
|
||||
std::vector<Polygons> linear_inserts(linear_data.size());
|
||||
|
||||
#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(PrintObject &print_object);
|
||||
|
||||
|
||||
//todo Remove! Only relevant for public BETA!
|
||||
static bool inline showed_critical=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)),
|
||||
support_rests_on_model(! mesh_group_settings.support_material_buildplate_only),
|
||||
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),
|
||||
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_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)),
|
||||
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),
|
||||
roof_pattern(mesh_group_settings.support_roof_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);
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// This is not the best solution, but the only one to ensure areas can not lag though walls at high maximum_move_distance.
|
||||
if (has_to_rely_on_min_xy_dist_only)
|
||||
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.
|
||||
if (TreeSupport::TreeSupportSettings::soluble) {
|
||||
// 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
|
||||
// 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
|
||||
// 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(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 } };
|
||||
// interface_preference = interface_map.at(mesh_group_settings.get<std::string>("support_interface_priority"));
|
||||
//FIXME this was the default
|
||||
|
@ -448,8 +421,7 @@ public:
|
|||
public:
|
||||
// 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.
|
||||
inline static bool some_model_contains_thick_roof = false;
|
||||
inline static bool has_to_rely_on_min_xy_dist_only = false;
|
||||
inline static bool soluble = false;
|
||||
/*!
|
||||
* \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.
|
||||
*/
|
||||
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-
|
||||
*/
|
||||
|
@ -545,7 +513,7 @@ public:
|
|||
/*!
|
||||
* \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.
|
||||
*/
|
||||
|
@ -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.
|
||||
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_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_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
|
||||
&& 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
|
||||
|
|
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
|
@ -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(
|
||||
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());
|
||||
|
|
|
@ -219,7 +219,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||
{
|
||||
bool have_perimeters = config->opt_int("perimeters") > 0;
|
||||
for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||
"seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||
"seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width",
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
|
||||
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();
|
||||
if (check_unsaved_preset_changes)
|
||||
header = _L("All user presets will be deleted.");
|
||||
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP;
|
||||
int act_btns = ActionButtons::KEEP;
|
||||
if (!check_unsaved_preset_changes)
|
||||
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
|
||||
act_btns |= ActionButtons::SAVE;
|
||||
|
||||
// Install bundles from resources if needed:
|
||||
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.
|
||||
// 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)
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
shader->set_uniform("emission_factor", 0.15f);
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const int position_id = shader->get_attrib_location("v_position");
|
||||
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) {
|
||||
// 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) {
|
||||
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
||||
continue;
|
||||
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);
|
||||
used_filaments_m.push_back(used_filament_m);
|
||||
used_filaments_g.push_back(used_filament_g);
|
||||
used_filaments_m[extruder_id] = used_filament_m;
|
||||
used_filaments_g[extruder_id] = used_filament_g;
|
||||
}
|
||||
|
||||
std::string longest_used_filament_string;
|
||||
|
@ -3999,11 +4002,10 @@ void GCodeViewer::render_legend(float& legend_height)
|
|||
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||
case EViewType::Tool: {
|
||||
// shows only extruders actually used
|
||||
size_t i = 0;
|
||||
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),
|
||||
true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]);
|
||||
++i;
|
||||
if (used_filaments_m[extruder_id] > 0.0 && used_filaments_g[extruder_id] > 0.0)
|
||||
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
|
||||
true, "", 0.0f, 0.0f, offsets, used_filaments_m[extruder_id], used_filaments_g[extruder_id]);
|
||||
}
|
||||
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::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||
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::AlignTextToFramePadding();
|
||||
imgui.text(owner.label);
|
||||
|
||||
if (!owner.print_order.empty()) {
|
||||
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::AlignTextToFramePadding();
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -5504,28 +5504,41 @@ void GLCanvas3D::_picking_pass()
|
|||
}
|
||||
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];
|
||||
if (hit.type != SceneRaycaster::EType::None) {
|
||||
sprintf(buf, "Object ID: %d", hit.raycaster_id);
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Type: %s", object_type.c_str());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Position: %.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Normal: %.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
|
||||
imgui.text(std::string(buf));
|
||||
if (ImGui::BeginTable("Hit", 2)) {
|
||||
add_strings_row_to_table("Object ID", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(hit.raycaster_id), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
add_strings_row_to_table("Type", ImGuiWrapper::COL_ORANGE_LIGHT, object_type, ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
sprintf(buf, "%.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));
|
||||
sprintf(buf, "%.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::EndTable();
|
||||
}
|
||||
}
|
||||
else
|
||||
imgui.text("NO HIT");
|
||||
|
||||
ImGui::Separator();
|
||||
imgui.text("Registered for picking:");
|
||||
sprintf(buf, "Beds: %d", (int)m_scene_raycaster.beds_count());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Volumes: %d", (int)m_scene_raycaster.volumes_count());
|
||||
imgui.text(std::string(buf));
|
||||
sprintf(buf, "Gizmo elements: %d", (int)m_scene_raycaster.gizmos_count());
|
||||
imgui.text(std::string(buf));
|
||||
if (ImGui::BeginTable("Raycasters", 2)) {
|
||||
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.beds_count(), (int)m_scene_raycaster.active_beds_count());
|
||||
add_strings_row_to_table("Beds", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
sprintf(buf, "%d (%d)", (int)m_scene_raycaster.volumes_count(), (int)m_scene_raycaster.active_volumes_count());
|
||||
add_strings_row_to_table("Volumes", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
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();
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace GUI {
|
|||
GLModel::Geometry init_data;
|
||||
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
|
||||
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);
|
||||
#else
|
||||
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));
|
||||
perimeter += width;
|
||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
||||
|
||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
||||
perimeter += height;
|
||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
||||
|
||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
||||
perimeter += width;
|
||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
||||
|
||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
||||
perimeter += height;
|
||||
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
||||
|
||||
// indices
|
||||
init_data.add_line(0, 1);
|
||||
init_data.add_line(1, 2);
|
||||
init_data.add_line(2, 3);
|
||||
init_data.add_line(4, 5);
|
||||
init_data.add_line(6, 7);
|
||||
init_data.add_line(3, 4);
|
||||
#else
|
||||
init_data.add_vertex(Vec2f(left, 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();
|
||||
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()), "",
|
||||
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()) {
|
||||
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)
|
||||
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
|
||||
act_buttons |= ActionButtons::DONT_SAVE;
|
||||
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
||||
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
||||
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()
|
||||
{
|
||||
wxDataViewItem item = GetSelection();
|
||||
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
|
||||
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject | itLayer)))
|
||||
return;
|
||||
|
||||
wxRect rect = this->GetItemRect(item, GetColumn(colExtruder));
|
||||
|
@ -1016,6 +1016,7 @@ void ObjectList::extruder_editing()
|
|||
|
||||
m_extruder_editor->Hide();
|
||||
update_extruder_in_config(item);
|
||||
Refresh();
|
||||
};
|
||||
|
||||
// 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) {
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
new_text.ToDouble(&new_rounded);
|
||||
if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) {
|
||||
cached_rounded(i) = new_rounded;
|
||||
const int id = key_id*3+i;
|
||||
if (m_imperial_units && (key_id == mePosition || key_id == meSize))
|
||||
new_text = double_to_string(new_value(i)*mm_to_in, 2);
|
||||
if (m_imperial_units) {
|
||||
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);
|
||||
}
|
||||
cached(i) = new_value(i);
|
||||
|
@ -1137,6 +1148,13 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
|||
if (value <= 0.0)
|
||||
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)
|
||||
return;
|
||||
|
||||
|
@ -1237,11 +1255,11 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
|||
if (!m_cache.is_valid())
|
||||
return;
|
||||
|
||||
if (m_imperial_units && (opt_key == "position" || opt_key == "size"))
|
||||
new_value *= in_to_mm;
|
||||
|
||||
if (opt_key == "position")
|
||||
if (opt_key == "position") {
|
||||
if (m_imperial_units)
|
||||
new_value *= in_to_mm;
|
||||
change_position_value(axis, new_value);
|
||||
}
|
||||
else if (opt_key == "rotation")
|
||||
change_rotation_value(axis, new_value);
|
||||
else if (opt_key == "scale") {
|
||||
|
|
|
@ -85,6 +85,7 @@ private:
|
|||
Vec3d scale;
|
||||
Vec3d scale_rounded;
|
||||
Vec3d size;
|
||||
Vec3d size_inches;
|
||||
Vec3d size_rounded;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
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())
|
||||
{
|
||||
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)
|
||||
if (range.second.has("extruder") &&
|
||||
range.second.option("extruder")->getInt() != 0 && // extruder isn't default
|
||||
range.second.option("extruder")->getInt() != extruder)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
@ -39,6 +41,8 @@ bool GLGizmoFdmSupports::on_init()
|
|||
{
|
||||
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["reset_direction"] = _L("Reset direction");
|
||||
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())
|
||||
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);
|
||||
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();
|
||||
|
||||
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;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
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();
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
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")
|
||||
: _L("Add supports by angle"));
|
||||
update_model_object();
|
||||
this->waiting_for_autogenerated_supports = false;
|
||||
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
|
||||
|
@ -391,8 +450,6 @@ void GLGizmoFdmSupports::update_model_object() const
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoFdmSupports::update_from_model_object()
|
||||
{
|
||||
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
|
||||
|
|
|
@ -26,6 +26,7 @@ protected:
|
|||
|
||||
private:
|
||||
bool on_init() override;
|
||||
void data_changed() override;
|
||||
|
||||
void update_model_object() const 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
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
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::SliderFloatEditBtnIcon, "edit_button" },
|
||||
{ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" },
|
||||
};
|
||||
|
||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
{ImGui::LegendTravel , "legend_travel" },
|
||||
{ImGui::LegendWipe , "legend_wipe" },
|
||||
|
@ -73,9 +76,6 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
|||
{ImGui::LegendShells , "legend_shells" },
|
||||
{ImGui::LegendToolMarker , "legend_toolmarker" },
|
||||
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||
};
|
||||
|
||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||
{ImGui::CloseNotifButton , "notification_close" },
|
||||
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
|
||||
{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 = {
|
||||
{ImGui::ClippyMarker , "notification_clippy" },
|
||||
|
||||
};
|
||||
|
||||
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 = {
|
||||
// File
|
||||
{ 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 + alt + "S", L("Save project as (3mf)") },
|
||||
{ ctrl + "R", L("(Re)slice") },
|
||||
// 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 + alt + "L", L("Load Config from ini/amf/3mf/gcode and merge") },
|
||||
// File>Export
|
||||
|
|
|
@ -277,8 +277,52 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
|
||||
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
|
||||
static wxString pref() { return " [ "; }
|
||||
static wxString suff() { return " ] "; }
|
||||
|
@ -1219,7 +1263,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
fileMenu->AppendSeparator();
|
||||
|
||||
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](){return m_plater != nullptr; }, this);
|
||||
|
||||
|
@ -2130,9 +2174,6 @@ void MainFrame::add_to_recent_projects(const wxString& filename)
|
|||
|
||||
void MainFrame::technology_changed()
|
||||
{
|
||||
// upadte DiffDlg
|
||||
diff_dialog.update_presets();
|
||||
|
||||
// update menu titles
|
||||
PrinterTechnology pt = plater()->printer_technology();
|
||||
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_all() const;
|
||||
bool can_reslice() const;
|
||||
void bind_diff_dialog();
|
||||
|
||||
// MenuBar items changeable in respect to printer technology
|
||||
enum MenuItems
|
||||
|
|