diff --git a/deps/wxWidgets/wxWidgets.cmake b/deps/wxWidgets/wxWidgets.cmake
index 661ea766c7..8174be589d 100644
--- a/deps/wxWidgets/wxWidgets.cmake
+++ b/deps/wxWidgets/wxWidgets.cmake
@@ -13,8 +13,8 @@ if (UNIX AND NOT APPLE) # wxWidgets will not use char as the underlying type for
endif()
prusaslicer_add_cmake_project(wxWidgets
- URL https://github.com/prusa3d/wxWidgets/archive/0b49beaacce17d90f0c370ecd73221abd089667a.zip
- URL_HASH SHA256=8fa978a76d6bd811b30eecc5124186b9ad54290b820f3a354e85bfa9dae6a5ce
+ URL https://github.com/prusa3d/wxWidgets/archive/78aa2dc0ea7ce99dc19adc1140f74c3e2e3f3a26.zip
+ URL_HASH SHA256=94b7d972373503e380e5a8b0ca63b1ccb956da4006402298dd89a0c5c7041b1e
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} dep_TIFF dep_JPEG dep_NanoSVG
CMAKE_ARGS
-DwxBUILD_PRECOMP=ON
diff --git a/resources/localization/be/PrusaSlicer.mo b/resources/localization/be/PrusaSlicer.mo
index 1c45b44e3e..ca0eb52fab 100644
Binary files a/resources/localization/be/PrusaSlicer.mo and b/resources/localization/be/PrusaSlicer.mo differ
diff --git a/resources/localization/be/PrusaSlicer_be.po b/resources/localization/be/PrusaSlicer_be.po
index 7a039e35b0..f44477aa1d 100644
--- a/resources/localization/be/PrusaSlicer_be.po
+++ b/resources/localization/be/PrusaSlicer_be.po
@@ -1512,7 +1512,7 @@ msgstr ""
#: src/slic3r/GUI/DoubleSlider.cpp:1465
msgid "Edit current color - Right click the colored slider segment"
msgstr ""
-"Змяніць бягучы колер - Правая кнопка мышы по каляроваму адрэзку "
+"Змяніць бягучы колер - Правая кнопка мышы по каляроваму адрэзку "
"паўзунка"
#: src/slic3r/GUI/DoubleSlider.cpp:1467
@@ -1533,32 +1533,32 @@ msgstr "Рэжым друку"
#: src/slic3r/GUI/DoubleSlider.cpp:1495
msgid "Add extruder change - Left click"
-msgstr "Дадаць змену экструдара - Левая кнопка мышы"
+msgstr "Дадаць змену экструдара - Левая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1497
msgid ""
"Add color change - Left click for predefined color or Shift + Left click for "
"custom color selection"
msgstr ""
-"Дадаць змену колера - Левая кнопка мышы для колера з спіску "
-"першапачатковых колераў ці Shift + Левая кнопка мышы для выбору "
+"Дадаць змену колера - Левая кнопка мышы для колера з спіску "
+"першапачатковых колераў ці Shift + Левая кнопка мышы для выбору "
"свайго колеру"
#: src/slic3r/GUI/DoubleSlider.cpp:1499
msgid "Add color change - Left click"
-msgstr "Дадаць змену колера - Левая кнопка мышы"
+msgstr "Дадаць змену колера - Левая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1500
msgid "or press \"+\" key"
-msgstr "альбо клавіша +"
+msgstr "альбо клавіша \"+\""
#: src/slic3r/GUI/DoubleSlider.cpp:1502
msgid "Add another code - Ctrl + Left click"
-msgstr "Дадаць іншы кода - Ctrl + левая кнопка мышы"
+msgstr "Дадаць іншы кода - Ctrl + левая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1503
msgid "Add another code - Right click"
-msgstr "Дадаць іншы код - Правая кнопка мышы"
+msgstr "Дадаць іншы код - Правая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1509
msgid ""
@@ -1639,15 +1639,15 @@ msgstr ""
#: src/slic3r/GUI/DoubleSlider.cpp:1565
msgid "Delete tick mark - Left click or press \"-\" key"
-msgstr "Выдаліц птушку - Левая кнопка мышы альбо клавіша -"
+msgstr "Выдаліц птушку - Левая кнопка мышы альбо клавіша \"-\""
#: src/slic3r/GUI/DoubleSlider.cpp:1567
msgid "Edit tick mark - Ctrl + Left click"
-msgstr "Змяніць птушку - Ctrl + левая кнопка мышы"
+msgstr "Змяніць птушку - Ctrl + левая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1568
msgid "Edit tick mark - Right click"
-msgstr "Змяніць птушку - Правая кнопка мышы"
+msgstr "Змяніць птушку - Правая кнопка мышы"
#: src/slic3r/GUI/DoubleSlider.cpp:1671 src/slic3r/GUI/DoubleSlider.cpp:1702
#: src/slic3r/GUI/GUI_Factories.cpp:870
@@ -2495,7 +2495,7 @@ msgstr "Пераменная вышыня пластоў"
#: src/slic3r/GUI/GLCanvas3D.cpp:191
msgid "Left mouse button:"
-msgstr "Левая кнопка мышы:"
+msgstr "Левая кнопка мышы:"
#: src/slic3r/GUI/GLCanvas3D.cpp:193
msgid "Add detail"
@@ -2503,7 +2503,7 @@ msgstr "Павялічыць дэтальнасць"
#: src/slic3r/GUI/GLCanvas3D.cpp:195
msgid "Right mouse button:"
-msgstr "Правая кнопка мышы:"
+msgstr "Правая кнопка мышы:"
#: src/slic3r/GUI/GLCanvas3D.cpp:197
msgid "Remove detail"
@@ -2511,7 +2511,7 @@ msgstr "Паменьшыць дэтальнасць"
#: src/slic3r/GUI/GLCanvas3D.cpp:199
msgid "Shift + Left mouse button:"
-msgstr "Shift + Левая кнопка мышы:"
+msgstr "Shift + Левая кнопка мышы:"
#: src/slic3r/GUI/GLCanvas3D.cpp:201
msgid "Reset to base"
@@ -2519,7 +2519,7 @@ msgstr "Скід да звычайнай вышыні пласта"
#: src/slic3r/GUI/GLCanvas3D.cpp:203
msgid "Shift + Right mouse button:"
-msgstr "Shift + Правая кнопка мышы:"
+msgstr "Shift + Правая кнопка мышы:"
#: src/slic3r/GUI/GLCanvas3D.cpp:205
msgid "Smoothing"
@@ -2527,7 +2527,7 @@ msgstr "Згладжванне"
#: src/slic3r/GUI/GLCanvas3D.cpp:207
msgid "Mouse wheel:"
-msgstr "Кола мышы:"
+msgstr "Кола мышы:"
#: src/slic3r/GUI/GLCanvas3D.cpp:209
msgid "Increase/decrease edit area"
@@ -2676,7 +2676,7 @@ msgstr "Налады ўпарадкавання"
#: src/slic3r/GUI/GLCanvas3D.cpp:4845
#, boost-format
msgid "Press %1%left mouse button to enter the exact value"
-msgstr "Націсніце %1% левую кнопку мышы для ўводу дакладнага значэння"
+msgstr "Націсніце %1% левую кнопку мышы для ўводу дакладнага значэння"
#: src/slic3r/GUI/GLCanvas3D.cpp:4847
msgid "Spacing"
@@ -2739,7 +2739,7 @@ msgstr "Упарадкаваць абраныя"
#: src/slic3r/GUI/GLCanvas3D.cpp:5325
msgid "Click right mouse button to show arrangement options"
msgstr ""
-"Пстрыкніце правую кнопку мышы, каб адлюстраваць налады ўпарадкавання"
+"Пстрыкніце правую кнопку мышы, каб адлюстраваць налады ўпарадкавання"
#: src/slic3r/GUI/GLCanvas3D.cpp:5345
msgid "Copy"
@@ -2769,7 +2769,7 @@ msgstr "Падзяліць на часткі"
#: src/slic3r/GUI/GLCanvas3D.cpp:5506 src/slic3r/GUI/GLCanvas3D.cpp:5543
msgid "Click right mouse button to open/close History"
msgstr ""
-"Псктрыкнуць правую кнопку мышы, каб адлюстраваць/схаваць Гісторы дзей"
+"Псктрыкнуць правую кнопку мышы, каб адлюстраваць/схаваць Гісторы дзей"
#: src/slic3r/GUI/GLCanvas3D.cpp:5528
#, boost-format
@@ -2942,7 +2942,7 @@ msgstr ""
#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1268
#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1269
msgid "Left click"
-msgstr "Левая кнопка мышы"
+msgstr "Левая кнопка мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:823
#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:2821
@@ -2952,7 +2952,7 @@ msgstr ""
#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:824
#: src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp:1266
msgid "Right click"
-msgstr "Правая кнопка мышы"
+msgstr "Правая кнопка мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoCut.cpp:824
msgid "Remove connector"
@@ -3612,7 +3612,7 @@ msgstr "Форма пэндзаля"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:110
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:35
msgid "Left mouse button"
-msgstr "Левая кнопка мышы"
+msgstr "Левая кнопка мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:55
msgid "Enforce supports"
@@ -3622,7 +3622,7 @@ msgstr "Прымусовая падтрымка"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:112
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:37
msgid "Right mouse button"
-msgstr "Правая кнопка мышы"
+msgstr "Правая кнопка мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:57
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:575
@@ -3633,7 +3633,7 @@ msgstr "Блакаваць падтрымкі"
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:114
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:39
msgid "Shift + Left mouse button"
-msgstr "Shift + Левая кнопка мышы"
+msgstr "Shift + Левая кнопка мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:59
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:570
@@ -3747,7 +3747,7 @@ msgstr "Фарбуе толькі адну мяжу."
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:462
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:129
msgid "Alt + Mouse wheel"
-msgstr "Alt + Кола мышы"
+msgstr "Alt + Кола мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:290
msgid "Splits bigger facets into smaller ones while the object is painted."
@@ -3757,7 +3757,7 @@ msgstr "Падчас фарбоўкі мадэлі разбівае вялікі
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:483
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:167
msgid "Ctrl + Mouse wheel"
-msgstr "Ctrl + Кола мышы"
+msgstr "Ctrl + Кола мышы"
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:328
#: src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp:488
@@ -5566,28 +5566,28 @@ msgstr "Засталося памылак"
#: src/slic3r/GUI/GUI_ObjectList.cpp:480
msgid "Right button click the icon to fix STL through Netfabb"
msgstr ""
-"Пстрыкніце правай кнопкай мышы на гузік, каб выправіць STL з "
+"Пстрыкніце правай кнопкай мышы на гузік, каб выправіць STL з "
"дапамогай сервіса Netfabb"
#: src/slic3r/GUI/GUI_ObjectList.cpp:526
msgid "Right button click the icon to change the object settings"
msgstr ""
-"Пстрыкніце правай кнопкай мышы на гузік, каб змяніць налады мадэлі"
+"Пстрыкніце правай кнопкай мышы на гузік, каб змяніць налады мадэлі"
#: src/slic3r/GUI/GUI_ObjectList.cpp:528
msgid "Click the icon to change the object settings"
-msgstr "Пстрыкніце кнопкай мышы на гузік, каб змяніць налады мадэлі"
+msgstr "Пстрыкніце кнопкай мышы на гузік, каб змяніць налады мадэлі"
#: src/slic3r/GUI/GUI_ObjectList.cpp:532
msgid "Right button click the icon to change the object printable property"
msgstr ""
-"Пстрыкніце правай кнопкай мышы на гузік, каб змяніць уласцівасці "
+"Пстрыкніце правай кнопкай мышы на гузік, каб змяніць уласцівасці "
"друку мадэлі"
#: src/slic3r/GUI/GUI_ObjectList.cpp:534
msgid "Click the icon to change the object printable property"
msgstr ""
-"Пстрыкніце кнопкай мышы на гузік, каб змяніць уласцівасці друку мадэлі"
+"Пстрыкніце кнопкай мышы на гузік, каб змяніць уласцівасці друку мадэлі"
#: src/slic3r/GUI/GUI_ObjectList.cpp:660
msgid "Change Extruder"
@@ -6515,7 +6515,7 @@ msgstr "Націсніце, каб актываваць прастакутнік
#: src/slic3r/GUI/KBShortcutsDialog.cpp:239
#: src/slic3r/GUI/KBShortcutsDialog.cpp:254
msgid "Arrow Up"
-msgstr "Стрэлка ўверх"
+msgstr "Стрэлка ўверх"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:148
msgid "Move selection 10 mm in positive Y direction"
@@ -6526,7 +6526,7 @@ msgstr "Рушыць абранае на 10 мм у станоўчым кіру
#: src/slic3r/GUI/KBShortcutsDialog.cpp:240
#: src/slic3r/GUI/KBShortcutsDialog.cpp:255
msgid "Arrow Down"
-msgstr "Стрэлка ўніз"
+msgstr "Стрэлка ўніз"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:149
msgid "Move selection 10 mm in negative Y direction"
@@ -6537,7 +6537,7 @@ msgstr "Рушыць абранае на 10 мм у адмоўным кірун
#: src/slic3r/GUI/KBShortcutsDialog.cpp:241
#: src/slic3r/GUI/KBShortcutsDialog.cpp:252
msgid "Arrow Left"
-msgstr "Стрэлка налева"
+msgstr "Стрэлка налева"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:150
msgid "Move selection 10 mm in negative X direction"
@@ -6548,7 +6548,7 @@ msgstr "Рушыць абранае на 10 мм у адмоўным кірун
#: src/slic3r/GUI/KBShortcutsDialog.cpp:242
#: src/slic3r/GUI/KBShortcutsDialog.cpp:253
msgid "Arrow Right"
-msgstr "Стрэлка направа"
+msgstr "Стрэлка направа"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:151
msgid "Move selection 10 mm in positive X direction"
@@ -6569,7 +6569,7 @@ msgstr "Рух абранага ў прасторы камеры"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:154
msgid "Page Up"
-msgstr "Page Up"
+msgstr "Page Up"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:154
msgid "Rotate selection 45 degrees CCW"
@@ -6577,7 +6577,7 @@ msgstr "Вярчэнне абранага на 45° супраць гадзін
#: src/slic3r/GUI/KBShortcutsDialog.cpp:155
msgid "Page Down"
-msgstr "Page Down"
+msgstr "Page Down"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:155
msgid "Rotate selection 45 degrees CW"
@@ -6688,8 +6688,8 @@ msgstr "Стол"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:190
msgid "All gizmos: Rotate - left mouse button; Pan - right mouse button"
msgstr ""
-"Усе штуковіны: Вярчэнне камеры - Левая кнопка мышы; Рух камеры - "
-"Правая кнопка мышы"
+"Усе штуковіны: Вярчэнне камеры - Левая кнопка мышы; Рух камеры - "
+"Правая кнопка мышы"
#: src/slic3r/GUI/KBShortcutsDialog.cpp:191
msgid "Gizmo move: Press to snap by 1mm"
@@ -8216,7 +8216,7 @@ msgstr "Нарэзаць зараз"
#: src/slic3r/GUI/Plater.cpp:1124
msgid "Hold Shift to Slice & Export G-code"
-msgstr "Утрымлівайце Shift, каб нарэзаць і экспартаваць у G-код"
+msgstr "Утрымлівайце Shift, каб нарэзаць і экспартаваць у G-код"
#: src/slic3r/GUI/Plater.cpp:1321
#, boost-format
@@ -11163,7 +11163,7 @@ msgstr ""
msgid ""
"Some fields are too long to fit. Right mouse click reveals the full text."
msgstr ""
-"Некаторыя палі занадта доўгія. Пстрыкніце правай кнопкай мышы, каб "
+"Некаторыя палі занадта доўгія. Пстрыкніце правай кнопкай мышы, каб "
"адлюстраваць поўны тэкст."
#: src/slic3r/GUI/UnsavedChangesDialog.cpp:969
@@ -17761,7 +17761,7 @@ msgid ""
"size of the gap between objects and to allow automatic rotations?"
msgstr ""
"Налады ўпарадкавання\n"
-"Ці ведаеце вы, што вы можаце пстрыкнуць правай кнопкай мышы на гузік "
+"Ці ведаеце вы, што вы можаце пстрыкнуць правай кнопкай мышы на гузік "
"Упарадкаваць гузікі, каб наладзіць прагал паміж мадэлямя і дазволіць "
"аўтаматычнае вярчэнне?"
@@ -17788,8 +17788,8 @@ msgid ""
msgstr ""
"Спрасціць сетку\n"
"Ці ведаеце вы, што вы можаце паменьшыць колкасць трыкутнікаў у паліганальнай "
-"сетцы, калі ўжыць функцыю спрашчэння сеткі? Пстрыкніце правай кнопкай "
-"мышы на мадэлі і абярыце Спрасціць мадэль. Больш падрабязна "
+"сетцы, калі ўжыць функцыю спрашчэння сеткі? Пстрыкніце правай кнопкай "
+"мышы на мадэлі і абярыце Спрасціць мадэль. Больш падрабязна "
"чытайце ў дакументацыі."
#: resources/data/hints.ini: [hint:Reload from disk]
@@ -17801,9 +17801,9 @@ msgid ""
msgstr ""
"Перазагрузіць з дыску\n"
"Ці ведаеце вы, што калі вы стварылі больш новую версію сваёй мадэлі, вы "
-"можаце проста перазагрузіць яе ў PrusaSlicer? Пстрыкніце правай кнопкай "
-"мышы на мадэлі ў акне 3D-прагляду і абярыце Перазагрузіць з дыска"
-"a>. Больш падрабязна чытайце ў дакументацыі."
+"можаце проста перазагрузіць яе ў PrusaSlicer? Пстрыкніце правай кнопкай "
+"мышы на мадэлі ў акне 3D-прагляду і абярыце Перазагрузіць з дыска"
+". Больш падрабязна чытайце ў дакументацыі."
#: resources/data/hints.ini: [hint:Hiding sidebar]
msgid ""
@@ -17833,7 +17833,7 @@ msgid ""
"between predefined camera angles?"
msgstr ""
"Выгляд з камеры\n"
-"Ці ведаеце вы, што вы можаце ўжываць лічбавыя клавішы 0-6, каб "
+"Ці ведаеце вы, што вы можаце ўжываць лічбавыя клавішы 0-6, каб "
"хутка пераключацца паміж папярэдне зададзенымі ракурсамі камеры?"
#: resources/data/hints.ini: [hint:Place on face]
@@ -17855,7 +17855,7 @@ msgid ""
"instances instead of copy-pasting it several times?"
msgstr ""
"Ужыць колькасць асобнікаў\n"
-"Ці ведаеце вы, што вы можаце пстрыкнуць правай кнопкай мышы на мадэлі "
+"Ці ведаеце вы, што вы можаце пстрыкнуць правай кнопкай мышы на мадэлі "
"і задаць дакладную колькасць копіяў мадэлі замест таго, каб капіяваць і "
"ўстаўляць её некалькі разоў?"
@@ -17890,7 +17890,7 @@ msgid ""
"history of changes and to undo or redo several actions at once?"
msgstr ""
"Гісторыя адкаціць/зрабіць нанова\n"
-"Ці ведаеце вы, вы можаце пстрыкнуць правай кнопкай мышы на стрэлкі "
+"Ці ведаеце вы, вы можаце пстрыкнуць правай кнопкай мышы на стрэлкі "
"адмены/паўтору, каб праглядзець гісторыю змяненняў і адмяніць ці "
"паўтарыць некалькі дзеянняў адначасова?"
@@ -17904,8 +17904,8 @@ msgid ""
msgstr ""
"Розная вышыня пластаў для кожнай мадэлі\n"
"Ці ведаеце вы, што вы можаце надрукаваць кожную мадэль на стале з рознай "
-"вышынёй пластоў? Пстрыкніце правай кнопкай мышы на мадэлі ў акне 3D-"
-"прагляду, абярыце Пласты і перыметры, наладзьце значэнні на правай "
+"вышынёй пластоў? Пстрыкніце правай кнопкай мышы на мадэлі ў акне 3D-"
+"прагляду, абярыце Пласты і перыметры, наладзьце значэнні на правай "
"панэлі. Больш падрабязна чытайце ў дакументацыі."
#: resources/data/hints.ini: [hint:Solid infill threshold area]
@@ -17938,8 +17938,8 @@ msgid ""
"also box-deselect objects with Alt+Mouse drag."
msgstr ""
"Выдзяленне прастакутнікам\n"
-"Ці ведаеце вы, што вы можаце вылучыць поле з дапамогай Shift + "
-"перацягванне мышшу? Вы так сама можаце адмяніць вылучэнне мадэляў з "
+"Ці ведаеце вы, што вы можаце вылучыць поле з дапамогай Shift + "
+"перацягванне мышшу? Вы так сама можаце адмяніць вылучэнне мадэляў з "
"дапамогай спалучэння клавішаў Alt + перацягванне мышшу."
#: resources/data/hints.ini: [hint:Zoom on selected objects or all if none
@@ -17965,8 +17965,8 @@ msgstr ""
"Перамыкач для друку\n"
"Ці ведаеце вы, што вы можаце адключыць стварэнне G-кода для абранай мадэлі, "
"без неабходнасці рухаць ці выдаляць яе? Пераключыце ўласцівасць мадэлі "
-"Для друку з кантэкстнага меню, калі пстрыкнуць правай кнопкай "
-"мышы."
+"Для друку з кантэкстнага меню, калі пстрыкнуць правай кнопкай "
+"мышы."
#: resources/data/hints.ini: [hint:Mirror]
msgid ""
@@ -17976,8 +17976,8 @@ msgid ""
msgstr ""
"Люстраваць\n"
"Ці ведаеце вы, што вы можаце люстраваць абраную мадэль, каб стварыць яе "
-"зваротную версію? Пстрыкніце правай кнопкай мышы на мадэль, абярыце "
-"Люстраваць і абярыце вось."
+"зваротную версію? Пстрыкніце правай кнопкай мышы на мадэль, абярыце "
+"Люстраваць і абярыце вось."
#: resources/data/hints.ini: [hint:PageUp / PageDown quick rotation by 45
#: degrees]
@@ -18056,7 +18056,7 @@ msgid ""
msgstr ""
"Уставіць прыпынак\n"
"Ці ведаеце вы, што вы можаце запланаваць прыпынак друку на поэным пласту? "
-"Пстрыкніце правай кнопкай мышы на паўзунке пласта ў акне папярэдняга "
+"Пстрыкніце правай кнопкай мышы на паўзунке пласта ў акне папярэдняга "
"прагляду і абярыце \"Дадаць прыпынак друку\" (M601). Можна ўжываць для "
"ўстаўкі ў ўстаўкі магнітаў, грузікаў ці гаек увашыя мадэлі. Больш падрабязна "
"чытайце ў дакументацыі."
@@ -18071,9 +18071,9 @@ msgid ""
msgstr ""
"Карыстальніцкі G-код\n"
"Ці ведаеце вы, што вы можаце ўставіць карыстальніцкі G-код на пэўным пласту? "
-"Пстрыкніце левай кнопкай мышы на пласт у акне папярэдняга прагляду, "
-"пстрыкніце правай кнопкай мышы гузік плюсу і абярыце Дадаць "
-"карыстальніцкі G-код. З дапамогай гэтай функцыі можна, напрыклад, "
+"Пстрыкніце левай кнопкай мышы на пласт у акне папярэдняга прагляду, "
+"пстрыкніце правай кнопкай мышы гузік плюсу і абярыце Дадаць "
+"карыстальніцкі G-код. З дапамогай гэтай функцыі можна, напрыклад, "
"стварыць тэмпературную вежу. Больш падрабязна чытайце ў дакументацыі."
#: resources/data/hints.ini: [hint:Configuration snapshots]
@@ -18111,8 +18111,8 @@ msgstr ""
"Налады ў асобным акне\n"
"Ці ведаеце вы, што вы можаце адчыніць налады ў новым немадальным акне? Гэта "
"значыць, што налады можна адчыніць на адным экране, а папярэдні прагляд G-"
-"кода на іншчым. Перайдзіце ў Перавагі і абярыце Налады будуць "
-"адлюстроўвацца ў асобным акне."
+"кода на іншчым. Перайдзіце ў Перавагі і абярыце Налады будуць "
+"адлюстроўвацца ў асобным акне."
#: resources/data/hints.ini: [hint:Adaptive infills]
msgid ""
@@ -19531,7 +19531,7 @@ msgstr "Колер фону"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:52
msgid "Backspace"
-msgstr "Backspace"
+msgstr "Backspace"
#: ../src/common/fmapbase.cpp:160
msgid "Baltic (ISO-8859-13)"
@@ -20904,7 +20904,7 @@ msgstr "Канец"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:55
msgid "Enter"
-msgstr "Enter"
+msgstr "Enter"
#: ../src/richtext/richtextstyledlg.cpp:934
msgid "Enter a box style name"
@@ -20991,7 +20991,7 @@ msgstr "Памылка: "
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:69
msgid "Esc"
-msgstr "Esc"
+msgstr "Esc"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:70
@@ -22180,7 +22180,7 @@ msgstr "Ініцыялізацыя не атрымалася ў post init, пе
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:54
msgid "Ins"
-msgstr "Ins"
+msgstr "Ins"
#. TRANSLATORS: Name of keyboard key
#: ../src/richtext/richtextsymboldlg.cpp:472 ../src/common/accelcmn.cpp:53
@@ -22879,7 +22879,7 @@ msgstr "&Згарнуць"
#. TRANSLATORS: System cursor name
#: ../src/propgrid/advprops.cpp:1763
msgid "Middle Button"
-msgstr "Сярэдняя кнопка"
+msgstr "Сярэдняя кнопка"
#: ../src/richtext/richtextsizepage.cpp:409
msgid "Min height:"
@@ -23111,117 +23111,117 @@ msgstr "Заўвага, 8 1/2 x 11 цалі"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:105
msgid "Num *"
-msgstr "Num *"
+msgstr "Num *"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:106
msgid "Num +"
-msgstr "Num +"
+msgstr "Num +"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:107
msgid "Num ,"
-msgstr "Num ,"
+msgstr "Num ,"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:108
msgid "Num -"
-msgstr "Num -"
+msgstr "Num -"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:109
msgid "Num ."
-msgstr "Num ."
+msgstr "Num ."
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:110
msgid "Num /"
-msgstr "Num /"
+msgstr "Num /"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:104
msgid "Num ="
-msgstr "Num ="
+msgstr "Num ="
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:101
msgid "Num Begin"
-msgstr "Num Begin"
+msgstr "Num Begin"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:103
msgid "Num Delete"
-msgstr "Num Delete"
+msgstr "Num Delete"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:95
msgid "Num Down"
-msgstr "Num Down"
+msgstr "Num Down"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:100
msgid "Num End"
-msgstr "Num End"
+msgstr "Num End"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:90
msgid "Num Enter"
-msgstr "Num Enter"
+msgstr "Num Enter"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:91
msgid "Num Home"
-msgstr "Num Home"
+msgstr "Num Home"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:102
msgid "Num Insert"
-msgstr "Num Insert"
+msgstr "Num Insert"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:86
msgid "Num Lock"
-msgstr "Num Lock"
+msgstr "Num Lock"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:97
msgid "Num Page Down"
-msgstr "Num Page Down"
+msgstr "Num Page Down"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:96
msgid "Num Page Up"
-msgstr "Num Page Up"
+msgstr "Num Page Up"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:94
msgid "Num Right"
-msgstr "Num Right"
+msgstr "Num Right"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:88
msgid "Num Space"
-msgstr "Num Space"
+msgstr "Num Space"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:89
msgid "Num Tab"
-msgstr "Num Tab"
+msgstr "Num Tab"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:93
msgid "Num Up"
-msgstr "Num Up"
+msgstr "Num Up"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:92
msgid "Num left"
-msgstr "Num left"
+msgstr "Num left"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:86
msgid "Num_lock"
-msgstr "Num_lock"
+msgstr "Num_lock"
#: ../src/richtext/richtextliststylepage.cpp:487
#: ../src/richtext/richtextbulletspage.cpp:279
@@ -23490,12 +23490,12 @@ msgstr "Налады старонкі"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:58
msgid "PageDown"
-msgstr "PageDown"
+msgstr "PageDown"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:57
msgid "PageUp"
-msgstr "PageUp"
+msgstr "PageUp"
#: ../src/generic/prntdlgg.cpp:216
msgid "Pages"
@@ -23545,12 +23545,12 @@ msgstr "Дазволы"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:60
msgid "PgDn"
-msgstr "PgDn"
+msgstr "PgDn"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:59
msgid "PgUp"
-msgstr "PgUp"
+msgstr "PgUp"
#: ../src/richtext/richtextbuffer.cpp:12868
msgid "Picture Properties"
@@ -25636,17 +25636,17 @@ msgstr "Кірыліца Windows/DOS OEM (CP 866)"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:111
msgid "Windows_Left"
-msgstr "Windows_Left"
+msgstr "Windows_Left"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:113
msgid "Windows_Menu"
-msgstr "Windows_Menu"
+msgstr "Windows_Menu"
#. TRANSLATORS: Name of keyboard key
#: ../src/common/accelcmn.cpp:112
msgid "Windows_Right"
-msgstr "Windows_Right"
+msgstr "Windows_Right"
#: ../src/common/ffile.cpp:150
#, c-format
@@ -25709,7 +25709,7 @@ msgstr "Вы не можаце дадаць новы каталог у гэту
#: ../src/propgrid/propgrid.cpp:3299
msgid "You have entered invalid value. Press ESC to cancel editing."
msgstr ""
-"Вы ўвялі недапушчальнае значэнне. Націсніце Esc, каб адмяніць змены."
+"Вы ўвялі недапушчальнае значэнне. Націсніце ESC, каб адмяніць змены."
#: ../src/common/stockitem.cpp:209
msgid "Zoom &In"
diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx
index 9f9ecebadc..54d2615903 100644
--- a/resources/profiles/PrusaResearch.idx
+++ b/resources/profiles/PrusaResearch.idx
@@ -1,4 +1,5 @@
min_slic3r_version = 2.6.0-beta2
+1.9.0 Bumped up configuration version.
1.9.0-beta3 Updated start g-code for MK4 (modified purge line and nozzle cleaning).
1.9.0-beta2 Added profiles for Original Prusa MK4 Input Shaper (Alpha).
min_slic3r_version = 2.6.0-beta0
diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini
index 3150d0032e..5d4f33e979 100644
--- a/resources/profiles/PrusaResearch.ini
+++ b/resources/profiles/PrusaResearch.ini
@@ -5,7 +5,7 @@
name = Prusa Research
# 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.9.0-beta3
+config_version = 1.9.0
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
diff --git a/resources/profiles/PrusaResearch/MK2.5MMU2_thumbnail.png b/resources/profiles/PrusaResearch/MK2.5MMU2_thumbnail.png
index 7d6e9feded..4affdf8abc 100644
Binary files a/resources/profiles/PrusaResearch/MK2.5MMU2_thumbnail.png and b/resources/profiles/PrusaResearch/MK2.5MMU2_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK2.5SMMU2S_thumbnail.png b/resources/profiles/PrusaResearch/MK2.5SMMU2S_thumbnail.png
index 7d6e9feded..058a5d07da 100644
Binary files a/resources/profiles/PrusaResearch/MK2.5SMMU2S_thumbnail.png and b/resources/profiles/PrusaResearch/MK2.5SMMU2S_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK2.5S_thumbnail.png b/resources/profiles/PrusaResearch/MK2.5S_thumbnail.png
index d9bf3260d4..ef62a4512b 100644
Binary files a/resources/profiles/PrusaResearch/MK2.5S_thumbnail.png and b/resources/profiles/PrusaResearch/MK2.5S_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK2.5_thumbnail.png b/resources/profiles/PrusaResearch/MK2.5_thumbnail.png
index d9bf3260d4..9465e5e0ac 100644
Binary files a/resources/profiles/PrusaResearch/MK2.5_thumbnail.png and b/resources/profiles/PrusaResearch/MK2.5_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK3MMU2_thumbnail.png b/resources/profiles/PrusaResearch/MK3MMU2_thumbnail.png
index eb5dccf08c..ad913624a6 100644
Binary files a/resources/profiles/PrusaResearch/MK3MMU2_thumbnail.png and b/resources/profiles/PrusaResearch/MK3MMU2_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK3SMMU2S_thumbnail.png b/resources/profiles/PrusaResearch/MK3SMMU2S_thumbnail.png
index eb5dccf08c..ad41b7bd6d 100644
Binary files a/resources/profiles/PrusaResearch/MK3SMMU2S_thumbnail.png and b/resources/profiles/PrusaResearch/MK3SMMU2S_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK3S_thumbnail.png b/resources/profiles/PrusaResearch/MK3S_thumbnail.png
index 8a859b82e7..559888aa06 100644
Binary files a/resources/profiles/PrusaResearch/MK3S_thumbnail.png and b/resources/profiles/PrusaResearch/MK3S_thumbnail.png differ
diff --git a/resources/profiles/PrusaResearch/MK4_thumbnail.png b/resources/profiles/PrusaResearch/MK4_thumbnail.png
index 2b729f930c..7602b0c3a2 100644
Binary files a/resources/profiles/PrusaResearch/MK4_thumbnail.png and b/resources/profiles/PrusaResearch/MK4_thumbnail.png differ
diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp
index 6042c6ded4..ea71a1a55f 100644
--- a/src/libslic3r/Arrange.cpp
+++ b/src/libslic3r/Arrange.cpp
@@ -755,5 +755,21 @@ void arrange(ArrangePolygons &items,
}
}
+BoundingBox bounding_box(const InfiniteBed &bed)
+{
+ BoundingBox ret;
+ using C = coord_t;
+
+ // It is important for Mx and My to be strictly less than half of the
+ // range of type C. width(), height() and area() will not overflow this way.
+ C Mx = C((std::numeric_limits::lowest() + 2 * bed.center.x()) / 4.01);
+ C My = C((std::numeric_limits::lowest() + 2 * bed.center.y()) / 4.01);
+
+ ret.max = bed.center - Point{Mx, My};
+ ret.min = bed.center + Point{Mx, My};
+
+ return ret;
+}
+
} // namespace arr
} // namespace Slic3r
diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp
index 874742ecb5..f705a1ad85 100644
--- a/src/libslic3r/Arrange.hpp
+++ b/src/libslic3r/Arrange.hpp
@@ -55,6 +55,25 @@ struct IrregularBed {
using ArrangeBed = boost::variant;
+BoundingBox bounding_box(const InfiniteBed &bed);
+inline BoundingBox bounding_box(const RectangleBed &b) { return b.bb; }
+inline BoundingBox bounding_box(const SegmentedRectangleBed &b) { return b.bb; }
+inline BoundingBox bounding_box(const CircleBed &b)
+{
+ auto r = static_cast(std::round(b.radius()));
+ Point R{r, r};
+
+ return {b.center() - R, b.center() + R};
+}
+inline BoundingBox bounding_box(const ArrangeBed &b)
+{
+ BoundingBox ret;
+ auto visitor = [&ret](const auto &b) { ret = bounding_box(b); };
+ boost::apply_visitor(visitor, b);
+
+ return ret;
+}
+
ArrangeBed to_arrange_bed(const Points &bedpts);
/// A logical bed representing an object not being arranged. Either the arrange
diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index 5a6c2d5bec..64a49cc7e8 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -1065,6 +1065,9 @@ void GCodeProcessor::process_file(const std::string& filename, std::function, 4> g1_axes = { std::nullopt, std::nullopt, std::nullopt, std::nullopt };
+ if (line.has_x()) g1_axes[X] = (double)line.x();
+ if (line.has_y()) g1_axes[Y] = (double)line.y();
+ if (line.has_z()) g1_axes[Z] = (double)line.z();
+ if (line.has_e()) g1_axes[E] = (double)line.e();
+ std::optional g1_feedrate = std::nullopt;
+ if (line.has_f()) g1_feedrate = (double)line.f();
+ std::optional g1_cmt = std::nullopt;
+ if (!line.comment().empty()) g1_cmt = line.comment();
+
+ process_G1(g1_axes, g1_feedrate, g1_cmt);
+}
+
+void GCodeProcessor::process_G1(const std::array, 4>& axes, std::optional feedrate, std::optional cmt)
{
const float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
const float filament_radius = 0.5f * filament_diameter;
const float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius);
auto move_type = [this](const AxisCoords& delta_pos) {
- EMoveType type = EMoveType::Noop;
-
if (m_wiping)
- type = EMoveType::Wipe;
+ return EMoveType::Wipe;
else if (delta_pos[E] < 0.0f)
- type = (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f) ? EMoveType::Travel : EMoveType::Retract;
+ return (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f) ? EMoveType::Travel : EMoveType::Retract;
else if (delta_pos[E] > 0.0f) {
if (delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f)
- type = (delta_pos[Z] == 0.0f) ? EMoveType::Unretract : EMoveType::Travel;
+ return (delta_pos[Z] == 0.0f) ? EMoveType::Unretract : EMoveType::Travel;
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f)
- type = EMoveType::Extrude;
- }
+ return EMoveType::Extrude;
+ }
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f)
- type = EMoveType::Travel;
+ return EMoveType::Travel;
- return type;
+ return EMoveType::Noop;
+ };
+
+ auto extract_absolute_position_on_axis = [&](Axis axis, std::optional value, double area_filament_cross_section)
+ {
+ if (value.has_value()) {
+ bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
+ if (axis == E)
+ is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
+
+ const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
+ double ret = *value * lengthsScaleFactor;
+ if (axis == E && m_use_volumetric_e)
+ ret /= area_filament_cross_section;
+ return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
+ }
+ else
+ return m_start_position[axis];
};
++m_g1_line_id;
@@ -2383,27 +2416,26 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// updates axes positions from line
for (unsigned char a = X; a <= E; ++a) {
- m_end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
+ m_end_position[a] = extract_absolute_position_on_axis((Axis)a, axes[a], double(area_filament_cross_section));
}
// updates feedrate from line, if present
- if (line.has_f())
- m_feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
+ if (feedrate.has_value())
+ m_feedrate = m_feed_multiply.current * (*feedrate) * MMMIN_TO_MMSEC;
- // calculates movement deltas
- AxisCoords delta_pos;
+ // calculates movement deltas
+ AxisCoords delta_pos;
for (unsigned char a = X; a <= E; ++a)
- delta_pos[a] = m_end_position[a] - m_start_position[a];
-
+ delta_pos[a] = m_end_position[a] - m_start_position[a];
+
if (std::all_of(delta_pos.begin(), delta_pos.end(), [](double d) { return d == 0.; }))
- return;
-
+ return;
+
const float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
if (volume_extruded_filament != 0.)
- m_used_filaments.increase_caches(volume_extruded_filament,
- m_extruder_id, area_filament_cross_section * m_parking_position,
- area_filament_cross_section * m_extra_loading_move);
+ m_used_filaments.increase_caches(volume_extruded_filament, m_extruder_id, area_filament_cross_section * m_parking_position,
+ area_filament_cross_section * m_extra_loading_move);
const EMoveType type = move_type(delta_pos);
if (type == EMoveType::Extrude) {
@@ -2420,7 +2452,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_height = m_forced_height;
else if (m_layer_id == 0)
m_height = m_first_layer_height + m_z_offset;
- else if (line.comment() != INTERNAL_G2G3_TAG){
+ else if (!cmt.has_value() || *cmt != INTERNAL_G2G3_TAG) {
if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0)
m_height = m_end_position[Z] - m_extruded_last_z;
}
@@ -2431,7 +2463,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (m_end_position[Z] == 0.0f || (m_extrusion_role == GCodeExtrusionRole::Custom && m_layer_id == 0))
m_end_position[Z] = m_height;
- if (line.comment() != INTERNAL_G2G3_TAG)
+ if (!cmt.has_value() || *cmt != INTERNAL_G2G3_TAG)
m_extruded_last_z = m_end_position[Z];
m_options_z_corrector.update(m_height);
@@ -2464,7 +2496,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// time estimate section
auto move_length = [](const AxisCoords& delta_pos) {
- float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]);
+ const float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]);
return (sq_xyz_length > 0.0f) ? std::sqrt(sq_xyz_length) : std::abs(delta_pos[E]);
};
@@ -2485,8 +2517,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
TimeMachine::State& prev = machine.prev;
std::vector& blocks = machine.blocks;
- curr.feedrate = (delta_pos[E] == 0.0f) ?
- minimum_travel_feedrate(static_cast(i), m_feedrate) :
+ curr.feedrate = (delta_pos[E] == 0.0f) ? minimum_travel_feedrate(static_cast(i), m_feedrate) :
minimum_feedrate(static_cast(i), m_feedrate);
TimeBlock block;
@@ -2521,11 +2552,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// calculates block acceleration
- float acceleration =
- (type == EMoveType::Travel) ? get_travel_acceleration(static_cast(i)) :
- (is_extrusion_only_move(delta_pos) ?
- get_retract_acceleration(static_cast(i)) :
- get_acceleration(static_cast(i)));
+ float acceleration = (type == EMoveType::Travel) ? get_travel_acceleration(static_cast(i)) :
+ (is_extrusion_only_move(delta_pos) ? get_retract_acceleration(static_cast(i)) :
+ get_acceleration(static_cast(i)));
for (unsigned char a = X; a <= E; ++a) {
const float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a));
@@ -2551,8 +2580,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// calculates block entry feedrate
float vmax_junction = curr.safe_feedrate;
if (!blocks.empty() && prev.feedrate > PREVIOUS_FEEDRATE_THRESHOLD) {
- bool prev_speed_larger = prev.feedrate > block.feedrate_profile.cruise;
- float smaller_speed_factor = prev_speed_larger ? (block.feedrate_profile.cruise / prev.feedrate) : (prev.feedrate / block.feedrate_profile.cruise);
+ const bool prev_speed_larger = prev.feedrate > block.feedrate_profile.cruise;
+ const float smaller_speed_factor = prev_speed_larger ? (block.feedrate_profile.cruise / prev.feedrate) : (prev.feedrate / block.feedrate_profile.cruise);
// Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
vmax_junction = prev_speed_larger ? block.feedrate_profile.cruise : prev.feedrate;
@@ -2574,18 +2603,18 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
const float jerk =
- (v_exit > v_entry) ?
- ((v_entry > 0.0f || v_exit < 0.0f) ?
- // coasting
- (v_exit - v_entry) :
- // axis reversal
- std::max(v_exit, -v_entry)) :
- // v_exit <= v_entry
- ((v_entry < 0.0f || v_exit > 0.0f) ?
- // coasting
- (v_entry - v_exit) :
- // axis reversal
- std::max(-v_exit, v_entry));
+ (v_exit > v_entry) ?
+ ((v_entry > 0.0f || v_exit < 0.0f) ?
+ // coasting
+ (v_exit - v_entry) :
+ // axis reversal
+ std::max(v_exit, -v_entry)) :
+ // v_exit <= v_entry
+ ((v_entry < 0.0f || v_exit > 0.0f) ?
+ // coasting
+ (v_entry - v_exit) :
+ // axis reversal
+ std::max(-v_exit, v_entry));
const float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a));
if (jerk > axis_max_jerk) {
@@ -2664,7 +2693,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// store move
- store_move_vertex(type, line.comment() == INTERNAL_G2G3_TAG);
+ store_move_vertex(type, cmt.has_value() && *cmt == INTERNAL_G2G3_TAG);
}
void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise)
@@ -2693,7 +2722,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
double delta_z() const { return end.z() - start.z(); }
double length() const { return angle * start_radius(); }
- double travel_length() const { return std::sqrt(sqr(length() + sqr(delta_z()))); }
+ double travel_length() const { return std::sqrt(sqr(length()) + sqr(delta_z())); }
double start_radius() const { return (start - center).norm(); }
double end_radius() const { return (end - center).norm(); }
@@ -2778,18 +2807,18 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
return ret;
};
- auto internal_only_g1_line = [](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) {
- std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
+ auto internal_only_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) {
+ std::array, 4> g1_axes = { target[X], target[Y], std::nullopt, std::nullopt };
+ std::optional g1_feedrate = std::nullopt;
if (has_z)
- ret += (boost::format(" Z%1%") % target[Z]).str();
+ g1_axes[Z] = target[Z];
if (feedrate.has_value())
- ret += (boost::format(" F%1%") % *feedrate).str();
+ g1_feedrate = (double)*feedrate;
if (extrusion.has_value())
- ret += (boost::format(" E%1%") % target[E]).str();
+ g1_axes[E] = target[E];
+ std::optional g1_cmt = INTERNAL_G2G3_TAG;
- ret += (boost::format(" ;%1%\n") % INTERNAL_G2G3_TAG).str();
-
- return ret;
+ process_G1(g1_axes, g1_feedrate, g1_cmt);
};
// calculate arc segments
@@ -2798,17 +2827,16 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
// https://github.com/prusa3d/Prusa-Firmware/blob/MK3/Firmware/motion_control.cpp
// segments count
- static const double MM_PER_ARC_SEGMENT = 0.5;
- const size_t segments = std::ceil(travel_length / MM_PER_ARC_SEGMENT);
- assert(segments >= 1);
+ static const double MM_PER_ARC_SEGMENT = 1.0;
+ const size_t segments = std::max(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1);
- const double theta_per_segment = arc.angle / double(segments);
- const double z_per_segment = arc.delta_z() / double(segments);
- const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0;
+ const double inv_segment = 1.0 / double(segments);
+ const double theta_per_segment = arc.angle * inv_segment;
+ const double z_per_segment = arc.delta_z() * inv_segment;
+ const double extruder_per_segment = (extrusion.has_value()) ? *extrusion * inv_segment : 0.0;
- const double sq_theta_per_segment = sqr(theta_per_segment);
- const double cos_T = 1.0 - 0.5 * sq_theta_per_segment; // Small angle approximation
- const double sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6.0; // Small angle approximation
+ const double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
+ const double sin_T = theta_per_segment;
AxisCoords prev_target = m_start_position;
AxisCoords arc_target;
@@ -2820,28 +2848,25 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
arc_target[E] = m_start_position[E];
static const size_t N_ARC_CORRECTION = 25;
-
Vec3d curr_rel_arc_start = arc.relative_start();
-
- std::string gcode;
-
- size_t n_arc_correction = N_ARC_CORRECTION;
+ size_t count = 0;
for (size_t i = 1; i < segments; ++i) {
- if (n_arc_correction-- == 0) {
- // Calculate the actual position for r_axis_x and r_axis_y
- const double cos_Ti = ::cos((double)i * theta_per_segment);
- const double sin_Ti = ::sin((double)i * theta_per_segment);
- curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
- curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
- // reset n_arc_correction
- n_arc_correction = N_ARC_CORRECTION;
- }
- else {
- // Calculate X and Y using the small angle approximation
+ if (count < N_ARC_CORRECTION) {
+ // Apply vector rotation matrix
const float r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T;
curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T;
curr_rel_arc_start.y() = r_axisi;
+ ++count;
+ }
+ else {
+ // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+ // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+ const double cos_Ti = ::cos(i * theta_per_segment);
+ const double sin_Ti = ::sin(i * theta_per_segment);
+ curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
+ curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
+ count = 0;
}
// Update arc_target location
@@ -2850,23 +2875,14 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
arc_target[Z] += z_per_segment;
arc_target[E] += extruder_per_segment;
- gcode += internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
+ m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
+ internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, (i == 1) ? feedrate : std::nullopt, extrusion);
prev_target = arc_target;
-
- // feedrate is constant, we do not need to repeat it
- feedrate.reset();
}
// Ensure last segment arrives at target location.
- gcode += internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
-
- // process fake gcode lines
- GCodeReader parser;
- parser.parse_buffer(gcode, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
- // force all lines to share the same id
- --m_line_id;
- process_gcode_line(line, false);
- });
+ m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
+ internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, (segments == 1) ? feedrate : std::nullopt, extrusion);
}
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp
index 90d52c231a..fcba4321ae 100644
--- a/src/libslic3r/GCode/GCodeProcessor.hpp
+++ b/src/libslic3r/GCode/GCodeProcessor.hpp
@@ -680,6 +680,8 @@ namespace Slic3r {
// Move
void process_G0(const GCodeReader::GCodeLine& line);
void process_G1(const GCodeReader::GCodeLine& line);
+ void process_G1(const std::array, 4>& axes = { std::nullopt, std::nullopt, std::nullopt, std::nullopt },
+ std::optional feedrate = std::nullopt, std::optional cmt = std::nullopt);
// Arc Move
void process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise);
diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp
index 6df0155cf3..73f225c577 100644
--- a/src/libslic3r/LayerRegion.cpp
+++ b/src/libslic3r/LayerRegion.cpp
@@ -276,7 +276,7 @@ Surfaces expand_bridges_detect_orientations(
for (; it_bridge_anchor != bridge_anchors.end() && it_bridge_anchor->src == bridge_id; ++ it_bridge_anchor) {
if (last_anchor_id != int(it_bridge_anchor->boundary)) {
last_anchor_id = int(it_bridge_anchor->boundary);
- append(anchor_areas, to_polygons(last_anchor_id < int32_t(shells.size()) ? shells[last_anchor_id] : sparse[last_anchor_id]));
+ append(anchor_areas, to_polygons(last_anchor_id < int32_t(shells.size()) ? shells[last_anchor_id] : sparse[last_anchor_id - int32_t(shells.size())]));
}
// if (Points &polyline = it_bridge_anchor->path; polyline.size() >= 2) {
// reserve_more_power_of_2(lines, polyline.size() - 1);
diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp
index 21e7d4c682..bedd26436f 100644
--- a/src/libslic3r/Model.hpp
+++ b/src/libslic3r/Model.hpp
@@ -509,6 +509,8 @@ public:
bool has_solid_mesh() const;
// Detect if object has at least one negative volume mash
bool has_negative_volume_mesh() const;
+ // Detect if object has at least one sla drain hole
+ bool has_sla_drain_holes() const { return !sla_drain_holes.empty(); }
bool is_cut() const { return cut_id.id().valid(); }
bool has_connectors() const;
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index 13625748a1..f42b3f7708 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -2240,7 +2240,7 @@ namespace PresetUtils {
{
const VendorProfile::PrinterModel *out = nullptr;
if (preset.vendor != nullptr) {
- auto *printer_model = preset.config.opt("printer_model");
+ const auto *printer_model = preset.config.opt("printer_model");
if (printer_model != nullptr && ! printer_model->value.empty()) {
auto it = std::find_if(preset.vendor->models.begin(), preset.vendor->models.end(), [printer_model](const VendorProfile::PrinterModel &pm) { return pm.id == printer_model->value; });
if (it != preset.vendor->models.end())
diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp
index 924fbe9223..f040750274 100644
--- a/src/libslic3r/Thread.cpp
+++ b/src/libslic3r/Thread.cpp
@@ -211,6 +211,12 @@ bool is_main_thread_active()
return get_main_thread_id() == boost::this_thread::get_id();
}
+static thread_local ThreadData s_thread_data;
+ThreadData& thread_data()
+{
+ return s_thread_data;
+}
+
// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
// Also it sets locale of the worker threads to "C" for the G-code generator to produce "." as a decimal separator.
void name_tbb_thread_pool_threads_set_locale()
@@ -274,16 +280,16 @@ void set_current_thread_qos()
#endif // __APPLE__
}
-void TBBLocalesSetter::on_scheduler_entry(bool is_worker)
+void ThreadData::tbb_worker_thread_set_c_locales()
{
// static std::atomic cnt = 0;
// std::cout << "TBBLocalesSetter Entering " << cnt ++ << " ID " << std::this_thread::get_id() << "\n";
- if (bool& is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) {
+ if (! m_tbb_worker_thread_c_locales_set) {
// Set locales of the worker thread to "C".
set_c_locales();
// OSX specific: Elevate QOS on Apple Silicon.
set_current_thread_qos();
- is_locales_sets = true;
+ m_tbb_worker_thread_c_locales_set = true;
}
}
diff --git a/src/libslic3r/Thread.hpp b/src/libslic3r/Thread.hpp
index 19ad29801c..61629addfb 100644
--- a/src/libslic3r/Thread.hpp
+++ b/src/libslic3r/Thread.hpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#include
#include
@@ -67,6 +68,27 @@ template inline boost::thread create_thread(Fn &&fn)
return create_thread(attrs, std::forward(fn));
}
+class ThreadData {
+public:
+ std::mt19937& random_generator() {
+ if (! m_random_generator_initialized) {
+ std::random_device rd;
+ m_random_generator.seed(rd());
+ m_random_generator_initialized = true;
+ }
+ return m_random_generator;
+ }
+
+ void tbb_worker_thread_set_c_locales();
+
+private:
+ std::mt19937 m_random_generator;
+ bool m_random_generator_initialized { false };
+ bool m_tbb_worker_thread_c_locales_set { false };
+};
+
+ThreadData& thread_data();
+
// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread
// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned.
// So in this class method on_scheduler_entry is called for every thread before it starts participating
@@ -79,11 +101,7 @@ class TBBLocalesSetter : public tbb::task_scheduler_observer
public:
TBBLocalesSetter() { this->observe(true); }
~TBBLocalesSetter() override { this->observe(false); };
-
- void on_scheduler_entry(bool is_worker) override;
-
-private:
- tbb::enumerable_thread_specific, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{ false };
+ void on_scheduler_entry(bool /* is_worker */) override { thread_data().tbb_worker_thread_set_c_locales(); }
};
}
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 7696cbac1e..571b7f480d 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1162,6 +1162,10 @@ static bool object_contains_negative_volumes(const Model& model, int obj_id) {
return (0 <= obj_id && obj_id < (int)model.objects.size()) ? model.objects[obj_id]->has_negative_volume_mesh() : false;
}
+static bool object_has_sla_drain_holes(const Model& model, int obj_id) {
+ return (0 <= obj_id && obj_id < (int)model.objects.size()) ? model.objects[obj_id]->has_sla_drain_holes() : false;
+}
+
void GLCanvas3D::SLAView::detect_type_from_volumes(const GLVolumePtrs& volumes)
{
for (auto& [id, type] : m_instances_cache) {
@@ -1170,7 +1174,8 @@ void GLCanvas3D::SLAView::detect_type_from_volumes(const GLVolumePtrs& volumes)
for (const GLVolume* v : volumes) {
if (v->volume_idx() == -(int)slaposDrillHoles) {
- if (object_contains_negative_volumes(*m_parent.get_model(), v->composite_id.object_id)) {
+ if (object_contains_negative_volumes(*m_parent.get_model(), v->composite_id.object_id) ||
+ object_has_sla_drain_holes(*m_parent.get_model(), v->composite_id.object_id)) {
const InstancesCacheItem* instance = find_instance_item(v->composite_id);
assert(instance != nullptr);
set_type(instance->first, ESLAViewType::Processed);
@@ -4687,6 +4692,13 @@ std::pair> GLCanvas3D::get_layers_h
return ret;
}
+void GLCanvas3D::detect_sla_view_type()
+{
+ m_sla_view.detect_type_from_volumes(m_volumes.volumes);
+ m_sla_view.update_volumes_visibility(m_volumes.volumes);
+ m_dirty = true;
+}
+
void GLCanvas3D::set_sla_view_type(ESLAViewType type)
{
m_sla_view.set_type(type);
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index eb674dffe3..4d7368ed26 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -1005,6 +1005,7 @@ public:
std::pair> get_layers_height_data(int object_id);
+ void detect_sla_view_type();
void set_sla_view_type(ESLAViewType type);
void set_sla_view_type(const GLVolume::CompositeID& id, ESLAViewType type);
void enable_sla_view_type_detection() { m_sla_view_type_detection_active = true; }
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index a380692370..ec7f43ae11 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -2281,14 +2281,7 @@ bool GUI_App::load_language(wxString language, bool initial)
}
#endif
-#ifdef __APPLE__
- // ysFIXME after fix for wxWidgets issue (https://github.com/wxWidgets/wxWidgets/issues/23209)
- // Workaround for wxLANGUAGE_CHINESE(...) languages => Allow to continue even if wxLocale is not available.
- // Because of translation will works fine, just locales will set to EN
- if (! wxLocale::IsAvailable(language_info->Language) && language_info->CanonicalName.BeforeFirst('_') != "zh" ) {
-#else
if (! wxLocale::IsAvailable(language_info->Language)) {
-#endif
// Loading the language dictionary failed.
wxString message = "Switching PrusaSlicer to language " + language_info->CanonicalName + " failed.";
#if !defined(_WIN32) && !defined(__APPLE__)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index e7cd63fece..ec6f66577e 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -855,6 +855,7 @@ void GLGizmoSlaSupports::on_set_state()
m_old_mo_id = -1;
}
+ m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE));
m_c->instances_hider()->set_hide_full_scene(false);
m_c->selection_info()->set_use_shift(false); // see top of on_render for details
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index ad67b99bb9..578a5ded98 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -960,6 +960,8 @@ bool GLGizmosManager::activate_gizmo(EType type)
if (type == Undefined) {
// it is deactivation of gizmo
m_current = Undefined;
+ if (m_parent.current_printer_technology() == ptSLA)
+ m_parent.detect_sla_view_type();
return true;
}
diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp
index 47cd01fdbe..b5c328ae8e 100644
--- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp
+++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp
@@ -99,7 +99,6 @@ void ArrangeJob::prepare_selected() {
clear_input();
Model &model = m_plater->model();
- double stride = bed_stride(m_plater);
std::vector
obj_sel(model.objects.size(), nullptr);
@@ -143,12 +142,6 @@ void ArrangeJob::prepare_selected() {
// If the selection was empty arrange everything
if (m_selected.empty())
m_selected.swap(m_unselected);
-
- // The strides have to be removed from the fixed items. For the
- // arrangeable (selected) items bed_idx is ignored and the
- // translation is irrelevant.
- for (auto &p : m_unselected)
- p.translation(X) -= p.bed_idx * stride;
}
static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret,
@@ -261,6 +254,10 @@ void ArrangeJob::prepare()
}
m_min_bed_inset = min_offset;
}
+
+ double stride = bed_stride(m_plater);
+ get_bed_shape(*m_plater->config(), m_bed);
+ assign_logical_beds(m_unselected, m_bed, stride);
}
void ArrangeJob::process(Ctl &ctl)
@@ -268,11 +265,9 @@ void ArrangeJob::process(Ctl &ctl)
static const auto arrangestr = _u8L("Arranging");
arrangement::ArrangeParams params;
- arrangement::ArrangeBed bed;
- ctl.call_on_main_thread([this, ¶ms, &bed]{
+ ctl.call_on_main_thread([this, ¶ms]{
prepare();
params = get_arrange_params(m_plater);
- get_bed_shape(*m_plater->config(), bed);
coord_t min_inset = get_skirt_offset(m_plater) + m_min_bed_inset;
params.min_bed_distance = std::max(params.min_bed_distance, min_inset);
}).wait();
@@ -293,13 +288,13 @@ void ArrangeJob::process(Ctl &ctl)
ctl.update_status(0, arrangestr);
- arrangement::arrange(m_selected, m_unselected, bed, params);
+ arrangement::arrange(m_selected, m_unselected, m_bed, params);
params.progressind = [this, count, &ctl](unsigned st) {
if (st > 0) ctl.update_status(int(count - st) * 100 / status_range(), arrangestr);
};
- arrangement::arrange(m_unprintable, {}, bed, params);
+ arrangement::arrange(m_unprintable, {}, m_bed, params);
// finalize just here.
ctl.update_status(int(count) * 100 / status_range(), ctl.was_canceled() ?
@@ -358,7 +353,9 @@ void ArrangeJob::finalize(bool canceled, std::exception_ptr &eptr) {
ap.apply();
}
- m_plater->update((unsigned int)Plater::UpdateParams::FORCE_FULL_SCREEN_REFRESH);
+ m_plater->update(static_cast(
+ Plater::UpdateParams::FORCE_FULL_SCREEN_REFRESH));
+
wxGetApp().obj_manipul()->set_dirty();
if (!m_unarranged.empty()) {
@@ -442,4 +439,26 @@ arrangement::ArrangeParams get_arrange_params(Plater *p)
return params;
}
+void assign_logical_beds(std::vector &items,
+ const arrangement::ArrangeBed &bed,
+ double stride)
+{
+
+ // The strides have to be removed from the fixed items. For the
+ // arrangeable (selected) items bed_idx is ignored and the
+ // translation is irrelevant.
+ coord_t bedx = bounding_box(bed).min.x();
+ for (auto &itm : items) {
+ auto bedidx = std::max(arrangement::UNARRANGED,
+ static_cast(std::floor(
+ (get_extents(itm.transformed_poly()).min.x() - bedx) /
+ stride)));
+
+ itm.bed_idx = bedidx;
+
+ if (bedidx >= 0)
+ itm.translation.x() -= bedidx * stride;
+ }
+}
+
}} // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp
index 4defc07e8b..c7070f213d 100644
--- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp
+++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp
@@ -21,6 +21,7 @@ class ArrangeJob : public Job
ArrangePolygons m_selected, m_unselected, m_unprintable;
std::vector m_unarranged;
+ arrangement::ArrangeBed m_bed;
coord_t m_min_bed_inset = 0.;
Plater *m_plater;
@@ -89,7 +90,6 @@ arrangement::ArrangePolygon get_arrange_poly(T obj, const Plater *plater)
using ArrangePolygon = arrangement::ArrangePolygon;
ArrangePolygon ap = obj.get_arrange_polygon();
- ap.bed_idx = get_extents(ap.transformed_poly()).min.x() / bed_stride(plater);
ap.setter = [obj, plater](const ArrangePolygon &p) {
if (p.is_arranged()) {
Vec2d t = p.translation.cast();
@@ -109,6 +109,10 @@ arrangement::ArrangeParams get_arrange_params(Plater *p);
coord_t get_skirt_offset(const Plater* plater);
+void assign_logical_beds(std::vector &items,
+ const arrangement::ArrangeBed &bed,
+ double stride);
+
}} // namespace Slic3r::GUI
#endif // ARRANGEJOB_HPP
diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp
index 11d9450c2e..7594d32109 100644
--- a/src/slic3r/GUI/Jobs/FillBedJob.cpp
+++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp
@@ -17,7 +17,6 @@ void FillBedJob::prepare()
{
m_selected.clear();
m_unselected.clear();
- m_bedpts.clear();
m_min_bed_inset = 0.;
m_object_idx = m_plater->get_selected_object_idx();
@@ -41,10 +40,10 @@ void FillBedJob::prepare()
if (m_selected.empty())
return;
- m_bedpts = get_bed_shape(*m_plater->config());
+ Points bedpts = get_bed_shape(*m_plater->config());
auto &objects = m_plater->model().objects;
- BoundingBox bedbb = get_extents(m_bedpts);
+ BoundingBox bedbb = get_extents(bedpts);
for (size_t idx = 0; idx < objects.size(); ++idx)
if (int(idx) != m_object_idx)
@@ -72,7 +71,7 @@ void FillBedJob::prepare()
}) / sc;
double fixed_area = unsel_area + m_selected.size() * poly_area;
- double bed_area = Polygon{m_bedpts}.area() / sc;
+ double bed_area = Polygon{bedpts}.area() / sc;
// This is the maximum number of items, the real number will always be close but less.
int needed_items = (bed_area - fixed_area) / poly_area;
@@ -85,13 +84,11 @@ void FillBedJob::prepare()
for (int i = 0; i < needed_items; ++i) {
ArrangePolygon ap = template_ap;
- ap.poly = m_selected.front().poly;
ap.bed_idx = arrangement::UNARRANGED;
auto m = mi->get_transformation();
- ap.setter = [this, mi, m](const ArrangePolygon &p) {
+ ap.setter = [this, m](const ArrangePolygon &p) {
ModelObject *mo = m_plater->model().objects[m_object_idx];
- ModelInstance *inst = mo->add_instance(*mi);
- inst->set_transformation(m);
+ ModelInstance *inst = mo->add_instance(m);
inst->apply_arrange_result(p.translation.cast(), p.rotation);
};
m_selected.emplace_back(ap);
@@ -99,14 +96,6 @@ void FillBedJob::prepare()
m_status_range = m_selected.size();
- // The strides have to be removed from the fixed items. For the
- // arrangeable (selected) items bed_idx is ignored and the
- // translation is irrelevant.
- double stride = bed_stride(m_plater);
- for (auto &p : m_unselected)
- if (p.bed_idx > 0)
- p.translation(X) -= p.bed_idx * stride;
-
coord_t min_offset = 0;
for (auto &ap : m_selected) {
min_offset = std::max(ap.inflation, min_offset);
@@ -123,6 +112,14 @@ void FillBedJob::prepare()
}
m_min_bed_inset = min_offset;
}
+
+ // The strides have to be removed from the fixed items. For the
+ // arrangeable (selected) items bed_idx is ignored and the
+ // translation is irrelevant.
+ double stride = bed_stride(m_plater);
+
+ m_bed = arrangement::to_arrange_bed(bedpts);
+ assign_logical_beds(m_unselected, m_bed, stride);
}
void FillBedJob::process(Ctl &ctl)
@@ -154,7 +151,7 @@ void FillBedJob::process(Ctl &ctl)
do_stop = ap.bed_idx > 0 && ap.priority == 0;
};
- arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
+ arrangement::arrange(m_selected, m_unselected, m_bed, params);
// finalize just here.
ctl.update_status(100, ctl.was_canceled() ?
@@ -191,7 +188,8 @@ void FillBedJob::finalize(bool canceled, std::exception_ptr &eptr)
model_object->ensure_on_bed();
- m_plater->update();
+ m_plater->update(static_cast(
+ Plater::UpdateParams::FORCE_FULL_SCREEN_REFRESH));
// FIXME: somebody explain why this is needed for increase_object_instances
if (inst_cnt == 1)
diff --git a/src/slic3r/GUI/Jobs/FillBedJob.hpp b/src/slic3r/GUI/Jobs/FillBedJob.hpp
index b953e0e981..ae8680de16 100644
--- a/src/slic3r/GUI/Jobs/FillBedJob.hpp
+++ b/src/slic3r/GUI/Jobs/FillBedJob.hpp
@@ -18,7 +18,7 @@ class FillBedJob : public Job
ArrangePolygons m_unselected;
coord_t m_min_bed_inset = 0.;
- Points m_bedpts;
+ arrangement::ArrangeBed m_bed;
int m_status_range = 0;
Plater *m_plater;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 5e987d6669..187e2737d4 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -6477,7 +6477,7 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
const SLAPrintObject *object = this->p->sla_print.get_print_object_by_model_object_id(mo.id());
- if (auto m = object->get_mesh_to_print(); !m || m->empty())
+ if (!object || !object->get_mesh_to_print() || object->get_mesh_to_print()->empty())
mesh = mesh_to_export_fff(mo, instance_id);
else {
const Transform3d mesh_trafo_inv = object->trafo().inverse();
@@ -7696,7 +7696,7 @@ PlaterAfterLoadAutoArrange::PlaterAfterLoadAutoArrange()
Plater* plater = wxGetApp().plater();
m_enabled = plater->model().objects.empty() &&
plater->printer_technology() == ptFFF &&
- plater->fff_print().config().printer_model.value == "XL";
+ is_XL_printer(plater->fff_print().config());
}
PlaterAfterLoadAutoArrange::~PlaterAfterLoadAutoArrange()
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 93017714e7..184b8af707 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -216,10 +216,10 @@ void Tab::create_preset_tab()
m_mode_sizer = new ModeSizer(panel, int (0.5*em_unit(this)));
const float scale_factor = em_unit(this)*0.1;// GetContentScaleFactor();
- m_hsizer = new wxBoxSizer(wxHORIZONTAL);
- sizer->Add(m_hsizer, 0, wxEXPAND | wxBOTTOM, 3);
- m_hsizer->Add(m_presets_choice, 0, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
- m_hsizer->AddSpacer(int(4*scale_factor));
+ m_top_hsizer = new wxBoxSizer(wxHORIZONTAL);
+ sizer->Add(m_top_hsizer, 0, wxEXPAND | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 3);
+ m_top_hsizer->Add(m_presets_choice, 0, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
+ m_top_hsizer->AddSpacer(int(4*scale_factor));
m_h_buttons_sizer = new wxBoxSizer(wxHORIZONTAL);
m_h_buttons_sizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
@@ -243,9 +243,8 @@ void Tab::create_preset_tab()
m_h_buttons_sizer->AddSpacer(int(8*scale_factor));
m_h_buttons_sizer->Add(m_btn_compare_preset, 0, wxALIGN_CENTER_VERTICAL);
- m_hsizer->Add(m_h_buttons_sizer, 1, wxEXPAND);
- m_hsizer->AddSpacer(int(16*scale_factor));
- // m_hsizer->AddStretchSpacer(32);
+ m_top_hsizer->Add(m_h_buttons_sizer, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
+ m_top_hsizer->AddSpacer(int(16*scale_factor));
// StretchSpacer has a strange behavior under OSX, so
// There is used just additional sizer for m_mode_sizer with right alignment
if (m_mode_sizer) {
@@ -253,8 +252,10 @@ void Tab::create_preset_tab()
// Don't set the 2nd parameter to 1, making the sizer rubbery scalable in Y axis may lead
// to wrong vertical size assigned to wxBitmapComboBoxes, see GH issue #7176.
mode_sizer->Add(m_mode_sizer, 0, wxALIGN_RIGHT);
- m_hsizer->Add(mode_sizer, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, wxOSX ? 15 : 10);
+ m_top_hsizer->Add(mode_sizer, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, wxOSX ? 15 : 10);
}
+ // hide whole top sizer to correct layout later
+ m_top_hsizer->ShowItems(false);
//Horizontal sizer to hold the tree and the selected page.
m_hsizer = new wxBoxSizer(wxHORIZONTAL);
@@ -461,20 +462,15 @@ void Tab::OnActivate()
activate_selected_page([](){});
m_hsizer->Layout();
-#ifdef _MSW_DARK_MODE
- // Because of DarkMode we use our own Notebook (inherited from wxSiplebook) instead of wxNotebook
- // And it looks like first Layout of the page doesn't update a size of the m_presets_choice
- // So we have to set correct size explicitely
- if (wxSize ok_sz = wxSize(35 * m_em_unit, m_presets_choice->GetBestSize().y);
- ok_sz != m_presets_choice->GetSize()) {
- m_presets_choice->SetMinSize(ok_sz);
- m_presets_choice->SetSize(ok_sz);
- GetSizer()->GetItem(size_t(0))->GetSizer()->Layout();
- if (wxGetApp().tabs_as_menu())
- m_presets_choice->update();
+ if (m_presets_choice->IsShown())
+ Refresh(); // Just refresh page, if m_presets_choice is already shown
+ else {
+ // on first OnActivate call show top sizer
+ m_top_hsizer->ShowItems(true);
+ if (TabFilament* tab = dynamic_cast(this))
+ tab->update_extruder_combobox();
+ Layout();
}
-#endif // _MSW_DARK_MODE
- Refresh();
}
void Tab::update_label_colours()
@@ -1950,6 +1946,9 @@ void TabFilament::create_extruder_combobox()
void TabFilament::update_extruder_combobox()
{
+ if (!m_presets_choice->IsShown())
+ return; // it will be updated later, on OnActive()
+
const size_t extruder_cnt = static_cast(m_preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter"))->values.size();
m_extruders_cb->Show(extruder_cnt > 1);
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index bbe1d1b17b..81344c6151 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -172,6 +172,7 @@ protected:
ScalableButton* m_btn_delete_preset;
ScalableButton* m_btn_edit_ph_printer {nullptr};
ScalableButton* m_btn_hide_incompatible_presets;
+ wxBoxSizer* m_top_hsizer;
wxBoxSizer* m_hsizer;
wxBoxSizer* m_h_buttons_sizer;
wxBoxSizer* m_left_sizer;