From b0abb4c5a697ac1933597d1695e3c64773b6ea73 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Sun, 14 Apr 2024 10:21:03 +0200 Subject: [PATCH 01/21] Rename tab_auxiliary_avtice.svg to tab_auxiliary_active.svg (#4390) * Rename tab_auxiliary_avtice.svg to tab_auxiliary_active.svg * Update MainFrame.cpp --- .../{tab_auxiliary_avtice.svg => tab_auxiliary_active.svg} | 0 src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename resources/images/{tab_auxiliary_avtice.svg => tab_auxiliary_active.svg} (100%) diff --git a/resources/images/tab_auxiliary_avtice.svg b/resources/images/tab_auxiliary_active.svg similarity index 100% rename from resources/images/tab_auxiliary_avtice.svg rename to resources/images/tab_auxiliary_active.svg diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c25b14d7e1..9befbb77b3 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1081,7 +1081,7 @@ void MainFrame::init_tabpanel() { m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); m_project->SetBackgroundColour(*wxWHITE); - m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"), false); + m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_active"), std::string("tab_auxiliary_active"), false); m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize); m_calibration->SetBackgroundColour(*wxWHITE); From 5d45770745fe5a85dfb40484fc9c87253f559156 Mon Sep 17 00:00:00 2001 From: Dima Buzdyk <46728448+buzzhuzz@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:49:44 +0500 Subject: [PATCH 02/21] gui: fix zoom-to-mouse (#4844) gui: fix zoom-to-mouse Plater disappeared when zoom-to-mouse enabled and user tries to zoom with a side view enabled (Ctrl+<3..6>). Mouse/screen center position estimation in 3D is made by calculating intersection of a mouse vector which comes 'through' the screen with an XY plane. However, when screen is parallel to Z axis, intersection point located at infinite which results in infinite camera translation vector. This change switches mouse position estimation to use of projection matrix like its done for camera panning. --- src/slic3r/GUI/GLCanvas3D.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d346cec8d0..26486c6259 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3693,9 +3693,11 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) } else { auto cnv_size = get_canvas_size(); - auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }); - auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()}); + float z{0.f}; + auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }, &z); + auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()}, &z); Vec3d displacement = mouse_3d_pos - screen_center_3d_pos; + wxGetApp().plater()->get_camera().translate(displacement); auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom(); _update_camera_zoom(delta); From 50d9d889ffecec7fa012ef7ecfae93ee788130fe Mon Sep 17 00:00:00 2001 From: Lee Jong Mun <43285072+crwusiz@users.noreply.github.com> Date: Sun, 14 Apr 2024 18:56:42 +0900 Subject: [PATCH 03/21] kor translation update (#4970) --- localization/i18n/ko/OrcaSlicer_ko.po | 86 ++++++++++++++++----------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/localization/i18n/ko/OrcaSlicer_ko.po b/localization/i18n/ko/OrcaSlicer_ko.po index 65475066f0..38d91b110c 100644 --- a/localization/i18n/ko/OrcaSlicer_ko.po +++ b/localization/i18n/ko/OrcaSlicer_ko.po @@ -8,9 +8,9 @@ msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-29 21:10+0800\n" -"PO-Revision-Date: 2024-03-15 23:12+0900\n" +"PO-Revision-Date: 2024-04-11 18:46+0900\n" "Last-Translator: Hotsolidinfill <138652683+Hotsolidinfill@users.noreply." -"github.com>, crwusiz \n" +"github.com>, crwusiz \n" "Language-Team: \n" "Language: ko_KR\n" "MIME-Version: 1.0\n" @@ -1170,7 +1170,7 @@ msgid "" "Do NOT save local path to 3MF file.\n" "Also disables 'reload from disk' option." msgstr "" -"3MF 파일에 로컬 경로를 저장하지 마십시오.\n" +"3mf 파일에 로컬 경로를 저장하지 마십시오.\n" "또한 '디스크에서 다시 로드' 옵션을 비활성화합니다." #. TRN: An menu option to convert the SVG into an unmodifiable model part. @@ -3386,6 +3386,8 @@ msgid "" "seam_slope_start_height need to be smaller than layer_height.\n" "Reset to 0." msgstr "" +"심_경사_시작_높이는 레이어_높이보다 작아야 합니다.\n" +"0으로 재설정합니다." msgid "Auto bed leveling" msgstr "자동 베드 레벨링" @@ -4714,7 +4716,7 @@ msgid "Switch to video files." msgstr "비디오 파일로 전환합니다." msgid "Switch to 3mf model files." -msgstr "3MF 모델 파일로 전환." +msgstr "3mf 모델 파일로 전환." msgid "Delete selected files from printer." msgstr "선택된 파일을 프린터에서 삭제합니다." @@ -6022,7 +6024,7 @@ msgid "Stealth Mode" msgstr "스텔스 모드" msgid "Enable network plugin" -msgstr "" +msgstr "네트워크 플러그인 사용" msgid "Check for stable updates only" msgstr "안정적인 업데이트만 확인" @@ -6080,7 +6082,7 @@ msgid "If enabled, auto-calculate everytime the color changed." msgstr "활성화하면 색상이 변경될 때마다 자동 계산됩니다." msgid "Network" -msgstr "" +msgstr "네트워크" msgid "Auto sync user presets(Printer/Filament/Process)" msgstr "사용자 사전 설정 자동 동기화(프린터/필라멘트/프로세스)" @@ -6928,8 +6930,8 @@ msgstr "무시" msgid "" "When recording timelapse without toolhead, it is recommended to add a " "\"Timelapse Wipe Tower\" \n" -"by right-click the empty position of build plate and choose \"Add Primitive" -"\"->\"Timelapse Wipe Tower\"." +"by right-click the empty position of build plate and choose \"Add " +"Primitive\"->\"Timelapse Wipe Tower\"." msgstr "" "툴헤드 없이 시간 경과를 기록할 경우 \"타임랩스 닦기 타워\"를 추가하는 것이 좋" "습니다\n" @@ -8510,6 +8512,12 @@ msgid "" "You can adjust the machine_max_acceleration_travel value in your printer's " "configuration to get higher speeds." msgstr "" +"이동 가속도 설정이 프린터의 최대 이동 가속도(machine_max_acceleration_travel)" +"를 초과합니다.\n" +"Orca는 이동 가속 속도를 자동으로 제한하여 프린터의 성능을 초과하지 않도록 합" +"니다.\n" +"더 빠른 속도를 얻으려면 프린터 구성에서 machine_max_acceleration_travel 값을 " +"조정할 수 있습니다." msgid "Generating skirt & brim" msgstr "스커트 & 브림 생성 중" @@ -8592,10 +8600,10 @@ msgid "Printer preset names" msgstr "프린터 사전 설정 이름" msgid "Use 3rd-party print host" -msgstr "" +msgstr "타사 인쇄 호스트 사용" msgid "Allow controlling BambuLab's printer through 3rd party print hosts" -msgstr "" +msgstr "타사 프린트 호스트를 통해 밤부랩의 프린터 제어 허용" msgid "Hostname, IP or URL" msgstr "호스트 이름, IP 또는 URL" @@ -10263,10 +10271,10 @@ msgstr "팬 최대 속도 레이어" msgid "" "Fan speed will be ramped up linearly from zero at layer " -"\"close_fan_the_first_x_layers\" to maximum at layer \"full_fan_speed_layer" -"\". \"full_fan_speed_layer\" will be ignored if lower than " -"\"close_fan_the_first_x_layers\", in which case the fan will be running at " -"maximum allowed speed at layer \"close_fan_the_first_x_layers\" + 1." +"\"close_fan_the_first_x_layers\" to maximum at layer " +"\"full_fan_speed_layer\". \"full_fan_speed_layer\" will be ignored if lower " +"than \"close_fan_the_first_x_layers\", in which case the fan will be running " +"at maximum allowed speed at layer \"close_fan_the_first_x_layers\" + 1." msgstr "" "팬 속도는 \"close_fan_the_first_x_layers\" 의 0에서 \"full_fan_speed_layer\" " "의 최고 속도까지 선형적으로 증가합니다. \"full_fan_speed_layer\"가 " @@ -11360,7 +11368,7 @@ msgstr "설정된 남은 출력 시간 비활성화" msgid "" "Disable generating of the M73: Set remaining print time in the final gcode" -msgstr "" +msgstr "M73 생성 비활성화: 최종 G코드에 남은 인쇄 시간 설정" msgid "Seam position" msgstr "솔기 위치" @@ -11436,7 +11444,7 @@ msgstr "" "냄) 스카프 조인트 솔기가 사용됩니다. 기본값은 155°입니다." msgid "Conditional overhang threshold" -msgstr "" +msgstr "조건부 오버행 임계값" #, no-c-format, no-boost-format msgid "" @@ -11446,6 +11454,10 @@ msgid "" "at 40% of the external wall's width. Due to performance considerations, the " "degree of overhang is estimated." msgstr "" +"이 옵션은 스카프 조인트 이음새 적용을 위한 돌출 임계값을 결정합니다. 둘레의 " +"지지되지 않은 부분이 이 임계값보다 작으면 스카프 조인트 심이 적용됩니다. 기" +"본 임계값은 외벽 너비의 40% of로 설정됩니다. 성능 고려 사항으로 인해 돌출 정" +"도가 추정됩니다." msgid "Scarf joint speed" msgstr "스카프 조인트 속도" @@ -13824,7 +13836,7 @@ msgid "Export Log" msgstr "로그 내보내기" msgid "OrcaSlicer Version:" -msgstr "" +msgstr "OrcaSlicer 버전:" msgid "System Version:" msgstr "시스템 버전:" @@ -13833,10 +13845,10 @@ msgid "DNS Server:" msgstr "DNS 서버:" msgid "Test OrcaSlicer(GitHub)" -msgstr "" +msgstr "OrcaSlicer 테스트(깃허브)" msgid "Test OrcaSlicer(GitHub):" -msgstr "" +msgstr "OrcaSlicer 테스트(깃허브):" msgid "Test Bing.com" msgstr "테스트 Bing.com" @@ -13944,8 +13956,8 @@ msgstr "" "다시 작성하시겠습니까?" msgid "" -"We would rename the presets as \"Vendor Type Serial @printer you selected" -"\". \n" +"We would rename the presets as \"Vendor Type Serial @printer you " +"selected\". \n" "To add preset for more printers, Please go to printer selection" msgstr "" "사전 설정의 이름을 \"선택한 공급업체 유형 직렬 @프린터\"로 변경합니다.\n" @@ -14355,7 +14367,7 @@ msgid "Success!" msgstr "성공!" msgid "Are you sure to log out?" -msgstr "" +msgstr "정말 로그아웃하시겠습니까?" msgid "Refresh Printers" msgstr "프린터 새로 고침" @@ -14388,7 +14400,7 @@ msgstr "" "시오." msgid "Login/Test" -msgstr "" +msgstr "로그인/테스트" msgid "Connection to printers connected via the print host failed." msgstr "출력 호스트를 통해 연결된 프린터에 연결하지 못했습니다." @@ -14525,45 +14537,49 @@ msgstr "" "오류: \"%2%\"" msgid "Connected to Obico successfully!" -msgstr "" +msgstr "Obico에 성공적으로 연결되었습니다!" msgid "Could not connect to Obico" -msgstr "" +msgstr "Obico에 연결할 수 없습니다" msgid "Connected to SimplyPrint successfully!" -msgstr "" +msgstr "SimplyPrint에 성공적으로 연결되었습니다!" msgid "Could not connect to SimplyPrint" -msgstr "" +msgstr "SimplyPrint에 연결할 수 없습니다" msgid "SimplyPrint account not linked. Go to Connect options to set it up." msgstr "" +"SimplyPrint 계정이 연결되지 않았습니다. 연결 옵션으로 이동하여 설정합니다." msgid "" "File size exceeds the 100MB upload limit. Please upload your file through " "the panel." msgstr "" +"파일 크기가 업로드 제한인 100MB를 초과했습니다. 패널을 통해 파일을 업로드하세" +"요." msgid "Unknown error" -msgstr "" +msgstr "알 수 없는 오류" msgid "Connection to Flashforge works correctly." -msgstr "" +msgstr "플래시포지 연결이 정상적으로 작동합니다." msgid "Could not connect to Flashforge" -msgstr "" +msgstr "플래시포지 연결할 수 없음" msgid "The provided state is not correct." -msgstr "" +msgstr "제공된 상태가 올바르지 않습니다." msgid "Please give the required permissions when authorizing this application." -msgstr "" +msgstr "이 애플리케이션을 승인할 때 필요한 권한을 부여하세요." msgid "Something unexpected happened when trying to log in, please try again." msgstr "" +"로그인을 시도하는 동안 예기치 않은 문제가 발생했습니다. 다시 시도해 주세요." msgid "User cancelled." -msgstr "" +msgstr "사용자가 취소했습니다." #: resources/data/hints.ini: [hint:Precise wall] msgid "" @@ -15056,8 +15072,8 @@ msgstr "" #~ msgstr "드문 레이어 없음(실험적)" #~ msgid "" -#~ "We would rename the presets as \"Vendor Type Serial @printer you selected" -#~ "\". \n" +#~ "We would rename the presets as \"Vendor Type Serial @printer you " +#~ "selected\". \n" #~ "To add preset for more prinetrs, Please go to printer selection" #~ msgstr "" #~ "사전 설정의 이름을 \"선택한 공급업체 유형 직렬 @프린터\"로 변경합니다.\n" From c6094d48aa36cf9fc2f33b12e584e2f0d7c5fa8a Mon Sep 17 00:00:00 2001 From: Andy Date: Sun, 14 Apr 2024 16:57:10 +0700 Subject: [PATCH 04/21] Russian translation update (#4981) * Russian translation update Russian translation update OrcaSlicer V2.0.0 RC + two lines in intext.js * Russian translation update Russian translation update OrcaSlicer V2.0.0 Official Release. Thx. --- localization/i18n/ru/OrcaSlicer_ru.po | 5670 ++++++++----------------- 1 file changed, 1719 insertions(+), 3951 deletions(-) diff --git a/localization/i18n/ru/OrcaSlicer_ru.po b/localization/i18n/ru/OrcaSlicer_ru.po index 82ceeb5cfb..b4c02ec83d 100644 --- a/localization/i18n/ru/OrcaSlicer_ru.po +++ b/localization/i18n/ru/OrcaSlicer_ru.po @@ -5,18 +5,17 @@ # msgid "" msgstr "" -"Project-Id-Version: OrcaSlicer V2.0.0 RC\n" +"Project-Id-Version: OrcaSlicer V2.0.0 Official Release\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-29 21:10+0800\n" -"PO-Revision-Date: 2024-03-30 17:42+0700\n" +"PO-Revision-Date: 2024-04-12 13:49+0700\n" "Last-Translator: \n" "Language-Team: andylg@yandex.ru\n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" "X-Generator: Poedit 3.4.2\n" msgid "Supports Painting" @@ -114,13 +113,10 @@ msgid "Lay on face" msgstr "Поверхностью на стол" #, boost-format -msgid "" -"Filament count exceeds the maximum number that painting tool supports. only " -"the first %1% filaments will be available in painting tool." +msgid "Filament count exceeds the maximum number that painting tool supports. only the first %1% filaments will be available in painting tool." msgstr "" -"Количество пластиковых нитей превышает максимальное количество " -"поддерживаемое инструментом рисования. Только первые %1% материала будут " -"доступны в инструменте для рисования." +"Количество пластиковых нитей превышает максимальное количество поддерживаемое инструментом рисования. Только первые %1% материала будут доступны в инструменте " +"для рисования." msgid "Color Painting" msgstr "Покраска" @@ -533,9 +529,7 @@ msgid "Cut by Plane" msgstr "Разрез по плоскости" msgid "non-manifold edges be caused by cut tool, do you want to fix it now?" -msgstr "" -"При работе режущего инструмента образовались открытые рёбра. Хотите починить " -"это сейчас?" +msgstr "При работе режущего инструмента образовались открытые рёбра. Хотите починить это сейчас?" msgid "Repairing model object" msgstr "Починка модели" @@ -556,12 +550,8 @@ msgid "Decimate ratio" msgstr "Коэффициент упрощения" #, boost-format -msgid "" -"Processing model '%1%' with more than 1M triangles could be slow. It is " -"highly recommended to simplify the model." -msgstr "" -"Обработка модели '%1%' с более чем 1 млн. треугольников может быть " -"медленной. Настоятельно рекомендуется упростить модель." +msgid "Processing model '%1%' with more than 1M triangles could be slow. It is highly recommended to simplify the model." +msgstr "Обработка модели '%1%' с более чем 1 млн. треугольников может быть медленной. Настоятельно рекомендуется упростить модель." msgid "Simplify model" msgstr "Упростить полигональную сетку" @@ -731,12 +721,8 @@ msgstr "Шрифт по умолчанию" msgid "Advanced" msgstr "Дополнительно" -msgid "" -"The text cannot be written using the selected font. Please try choosing a " -"different font." -msgstr "" -"Текст не может быть написан выбранным шрифтом. Пожалуйста, выберите другой " -"шрифт." +msgid "The text cannot be written using the selected font. Please try choosing a different font." +msgstr "Текст не может быть написан выбранным шрифтом. Пожалуйста, выберите другой шрифт." msgid "Embossed text cannot contain only white spaces." msgstr "Рельефный текст не может содержать одни пробелы." @@ -751,8 +737,7 @@ msgid "Text input doesn't show font boldness." msgstr "Визуализация толщины шрифта в окне ввода текста не поддерживается." msgid "Text input doesn't show gap between lines." -msgstr "" -"Визуализация межстрочного интервала в окне ввода текста не поддерживается." +msgstr "Визуализация межстрочного интервала в окне ввода текста не поддерживается." msgid "Too tall, diminished font height inside text input." msgstr "Слишком высокий. Уменьшите высоту шрифта в окне ввода текста." @@ -997,12 +982,10 @@ msgid "Rotate text Clock-wise." msgstr "Поворот текста по часовой стрелке." msgid "Unlock the text's rotation when moving text along the object's surface." -msgstr "" -"Разблокировать вращение текста при перемещении текста по поверхности модели." +msgstr "Разблокировать вращение текста при перемещении текста по поверхности модели." msgid "Lock the text's rotation when moving text along the object's surface." -msgstr "" -"Заблокировать вращение текста при перемещении текста по поверхности модели." +msgstr "Заблокировать вращение текста при перемещении текста по поверхности модели." msgid "Select from True Type Collection." msgstr "Выберите True Type шрифт." @@ -1014,12 +997,8 @@ msgid "Orient the text towards the camera." msgstr "Сориентировать текст по направлению к камере." #, boost-format -msgid "" -"Can't load exactly same font(\"%1%\"). Aplication selected a similar " -"one(\"%2%\"). You have to specify font for enable edit text." -msgstr "" -"Т.к. не удалось загрузить тот же шрифт (\"%1%\"), приложение выбрало похожий " -"шрифт (\"%2%\"). Выберите шрифт для включения редактирования текста." +msgid "Can't load exactly same font(\"%1%\"). Aplication selected a similar one(\"%2%\"). You have to specify font for enable edit text." +msgstr "Т.к. не удалось загрузить тот же шрифт (\"%1%\"), приложение выбрало похожий шрифт (\"%2%\"). Выберите шрифт для включения редактирования текста." msgid "No symbol" msgstr "Нет символов" @@ -1132,16 +1111,10 @@ msgid "Undefined stroke type" msgstr "Неопределенный тип обводки" msgid "Path can't be healed from selfintersection and multiple points." -msgstr "" -"Контур не может быть исправлен от проблемы самопересечения и дублирующихся " -"точек." +msgstr "Контур не может быть исправлен от проблемы самопересечения и дублирующихся точек." -msgid "" -"Final shape constains selfintersection or multiple points with same " -"coordinate." -msgstr "" -"У конечной фигуры имеется самопересечение или несколько точек с одинаковыми " -"координатами." +msgid "Final shape constains selfintersection or multiple points with same coordinate." +msgstr "У конечной фигуры имеется самопересечение или несколько точек с одинаковыми координатами." #, boost-format msgid "Shape is marked as invisible (%1%)." @@ -1237,8 +1210,7 @@ msgid "Reset rotation" msgstr "Сброс вращения" msgid "Lock/unlock rotation angle when dragging above the surface." -msgstr "" -"Блокировка/разблокировка угла поворота при перетаскивании над поверхностью." +msgstr "Блокировка/разблокировка угла поворота при перетаскивании над поверхностью." msgid "Mirror vertically" msgstr "Зеркалировать по вертикали" @@ -1384,35 +1356,23 @@ msgid "Machine" msgstr "Принтер" msgid "Configuration package was loaded, but some values were not recognized." -msgstr "" -"Пакет конфигурации был загружен, но некоторые значения не были распознаны." +msgstr "Пакет конфигурации был загружен, но некоторые значения не были распознаны." #, boost-format -msgid "" -"Configuration file \"%1%\" was loaded, but some values were not recognized." -msgstr "" -"Файл конфигурации \"%1%\" был загружен, но некоторые значения не были " -"распознаны." +msgid "Configuration file \"%1%\" was loaded, but some values were not recognized." +msgstr "Файл конфигурации \"%1%\" был загружен, но некоторые значения не были распознаны." msgid "V" msgstr "V" -msgid "" -"OrcaSlicer will terminate because of running out of memory.It may be a bug. " -"It will be appreciated if you report the issue to our team." -msgstr "" -"OrcaSlicer завершает работу из-за нехватки памяти. Возможно, это баг " -"программы. Будем признательны, если вы сообщите о проблеме нашей команде." +msgid "OrcaSlicer will terminate because of running out of memory.It may be a bug. It will be appreciated if you report the issue to our team." +msgstr "OrcaSlicer завершает работу из-за нехватки памяти. Возможно, это баг программы. Будем признательны, если вы сообщите о проблеме нашей команде." msgid "Fatal error" msgstr "Критическая ошибка" -msgid "" -"OrcaSlicer will terminate because of a localization error. It will be " -"appreciated if you report the specific scenario this issue happened." -msgstr "" -"OrcaSlicer завершит работу из-за ошибки локализации. Будем признательны, " -"если вы сообщите о конкретном сценарии возникновения этой проблемы." +msgid "OrcaSlicer will terminate because of a localization error. It will be appreciated if you report the specific scenario this issue happened." +msgstr "OrcaSlicer завершит работу из-за ошибки локализации. Будем признательны, если вы сообщите о конкретном сценарии возникновения этой проблемы." msgid "Critical error" msgstr "Критическая ошибка" @@ -1438,12 +1398,10 @@ msgid "Connect %s failed! [SN:%s, code=%s]" msgstr "Сбой подключения к %s! [Серийный №:%s, код=%s]" msgid "" -"Orca Slicer requires the Microsoft WebView2 Runtime to operate certain " -"features.\n" +"Orca Slicer requires the Microsoft WebView2 Runtime to operate certain features.\n" "Click Yes to install it now." msgstr "" -"Для работы некоторых функций Orca Slicer требуется Microsoft WebView2 " -"Runtime.\n" +"Для работы некоторых функций Orca Slicer требуется Microsoft WebView2 Runtime.\n" "Нажмите Да, чтобы установить." msgid "WebView2 Runtime" @@ -1465,8 +1423,7 @@ msgstr "Загрузка настроек" #, c-format, boost-format msgid "Click to download new version in default browser: %s" -msgstr "" -"Нажмите OK, чтобы загрузить последнюю версию в браузере по умолчанию: %s" +msgstr "Нажмите OK, чтобы загрузить последнюю версию в браузере по умолчанию: %s" msgid "The Orca Slicer needs an upgrade" msgstr "Orca Slice нуждается в обновлении." @@ -1480,13 +1437,11 @@ msgstr "Информация" msgid "" "The OrcaSlicer configuration file may be corrupted and cannot be parsed.\n" "OrcaSlicer has attempted to recreate the configuration file.\n" -"Please note, application settings will be lost, but printer profiles will " -"not be affected." +"Please note, application settings will be lost, but printer profiles will not be affected." msgstr "" "Возможно, файл конфигурации OrcaSlicer повреждён и не может быть обработан.\n" "OrcaSlicer попытался воссоздать файл конфигурации.\n" -"Обратите внимание, что настройки приложения будут потеряны, но профили " -"принтера не будут затронуты." +"Обратите внимание, что настройки приложения будут потеряны, но профили принтера не будут затронуты." msgid "Rebuild" msgstr "Пересоздание" @@ -1501,8 +1456,7 @@ msgid "Choose one file (3mf):" msgstr "Выберите один файл (3mf):" msgid "Choose one or more files (3mf/step/stl/svg/obj/amf/usd*/abc/ply):" -msgstr "" -"Выберите один или несколько файлов (3mf/step/stl/svg/obj/amf/usd*/abc/ply):" +msgstr "Выберите один или несколько файлов (3mf/step/stl/svg/obj/amf/usd*/abc/ply):" msgid "Choose one or more files (3mf/step/stl/svg/obj/amf):" msgstr "Выберите один или несколько файлов (3mf/step/stl/svg/obj/amf):" @@ -1513,12 +1467,8 @@ msgstr "Выберите один файл (gcode/3mf):" msgid "Some presets are modified." msgstr "В некоторых профилях имеются изменения." -msgid "" -"You can keep the modifield presets to the new project, discard or save " -"changes as new presets." -msgstr "" -"Вы можете сохранить изменённые профили в новом проекте, отменить или " -"сохранить изменения в новые профили." +msgid "You can keep the modifield presets to the new project, discard or save changes as new presets." +msgstr "Вы можете сохранить изменённые профили в новом проекте, отменить или сохранить изменения в новые профили." msgid "User logged out" msgstr "Пользователь вышел из системы" @@ -1529,23 +1479,16 @@ msgstr "Создание или открытие файла проекта во msgid "Open Project" msgstr "Открыть проект" -msgid "" -"The version of Orca Slicer is too low and needs to be updated to the latest " -"version before it can be used normally" -msgstr "" -"Слишком старая версия Orca Slicer. Для корректной работы обновите программу " -"до последней версии." +msgid "The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally" +msgstr "Слишком старая версия Orca Slicer. Для корректной работы обновите программу до последней версии." msgid "Privacy Policy Update" msgstr "Обновление политики конфиденциальности" -msgid "" -"The number of user presets cached in the cloud has exceeded the upper limit, " -"newly created user presets can only be used locally." +msgid "The number of user presets cached in the cloud has exceeded the upper limit, newly created user presets can only be used locally." msgstr "" -"Количество пользовательских профилей, кэшированных в облаке, превысило " -"установленный лимит. Новые создаваемые пользовательские профили можно будет " -"использовать только локально." +"Количество пользовательских профилей, кэшированных в облаке, превысило установленный лимит. Новые создаваемые пользовательские профили можно будет использовать " +"только локально." msgid "Sync user presets" msgstr "\"Синхронизация пользовательских профилей" @@ -1735,16 +1678,13 @@ msgid "Orca String Hell" msgstr "«Струнный ад» Orca" msgid "" -"This model features text embossment on the top surface. For optimal results, " -"it is advisable to set the 'One Wall Threshold(min_width_top_surface)' to 0 " -"for the 'Only One Wall on Top Surfaces' to work best.\n" +"This model features text embossment on the top surface. For optimal results, it is advisable to set the 'One Wall Threshold(min_width_top_surface)' to 0 for the " +"'Only One Wall on Top Surfaces' to work best.\n" "Yes - Change these settings automatically\n" "No - Do not change these settings for me" msgstr "" -"На верхней поверхности модели присутствует рельефный текст. Для достижения " -"оптимального результата рекомендуется установить значение «Порог одного " -"периметра» (min_width_top_surface)\" равным 0, чтобы хорошо работал параметр " -"«Только один периметр на верхней поверхности».\n" +"На верхней поверхности модели присутствует рельефный текст. Для достижения оптимального результата рекомендуется установить значение «Порог одного " +"периметра» (min_width_top_surface)\" равным 0, чтобы хорошо работал параметр «Только один периметр на верхней поверхности».\n" "Да - Изменить эти настройки автоматически\n" "Нет - Не изменять эти настройки" @@ -1849,8 +1789,7 @@ msgid "Assemble" msgstr "Объединить в сборку" msgid "Assemble the selected objects to an object with multiple parts" -msgstr "" -"Объединение выбранных объектов в модель, состоящую из несколько частей." +msgstr "Объединение выбранных объектов в модель, состоящую из несколько частей." msgid "Assemble the selected objects to an object with single part" msgstr "Объединение выбранных моделей в единую." @@ -2039,9 +1978,7 @@ msgid "Click the icon to reset all settings of the object" msgstr "Нажмите на значок, чтобы сбросить все настройки модели" msgid "Right button click the icon to drop the object printable property" -msgstr "" -"Нажмите правой кнопкой мыши на значок, чтобы разрешить/запретить печать " -"модели" +msgstr "Нажмите правой кнопкой мыши на значок, чтобы разрешить/запретить печать модели" msgid "Click the icon to toggle printable property of the object" msgstr "Нажмите на значок, чтобы разрешить/запретить печать модели" @@ -2071,47 +2008,33 @@ msgid "Add Modifier" msgstr "Добавление модификатора" msgid "Switch to per-object setting mode to edit modifier settings." -msgstr "" -"Переключение в режим работы с моделями для редактирования параметров " -"модификатора." +msgstr "Переключение в режим работы с моделями для редактирования параметров модификатора." -msgid "" -"Switch to per-object setting mode to edit process settings of selected " -"objects." -msgstr "" -"Переключение в режим работы с моделями для редактирования настроек печати " -"выбранных моделей." +msgid "Switch to per-object setting mode to edit process settings of selected objects." +msgstr "Переключение в режим работы с моделями для редактирования настроек печати выбранных моделей." msgid "Delete connector from object which is a part of cut" msgstr "Удаление соединения из модели, которое является частью разреза" msgid "Delete solid part from object which is a part of cut" -msgstr "" -"Удаление твердотельной части из модели, которая является частью разреза" +msgstr "Удаление твердотельной части из модели, которая является частью разреза" msgid "Delete negative volume from object which is a part of cut" -msgstr "" -"Удаление объёма для вычитания из модели, которая является частью разреза" +msgstr "Удаление объёма для вычитания из модели, которая является частью разреза" -msgid "" -"To save cut correspondence you can delete all connectors from all related " -"objects." -msgstr "" -"Для сохранения информации о разрезе, вы можете удалить все соединения из " -"всех связанных объектов." +msgid "To save cut correspondence you can delete all connectors from all related objects." +msgstr "Для сохранения информации о разрезе, вы можете удалить все соединения из всех связанных объектов." msgid "" "This action will break a cut correspondence.\n" "After that model consistency can't be guaranteed .\n" "\n" -"To manipulate with solid parts or negative volumes you have to invalidate " -"cut infornation first." +"To manipulate with solid parts or negative volumes you have to invalidate cut infornation first." msgstr "" "Это действие приведёт к удалению информации о разрезе.\n" "После этого согласованность модели не может быть гарантирована.\n" "\n" -"Чтобы манипулировать с твердотельными частями или объёмами для вычитания, " -"необходимо сначала удалить информацию о сделанном разрезе." +"Чтобы манипулировать с твердотельными частями или объёмами для вычитания, необходимо сначала удалить информацию о сделанном разрезе." msgid "Delete all connectors" msgstr "Удалить все соединения" @@ -2161,18 +2084,11 @@ msgstr "Слой" msgid "Selection conflicts" msgstr "Конфликты при выборе" -msgid "" -"If first selected item is an object, the second one should also be object." -msgstr "" -"Если первый выбранный элемент является моделью, то второй также должен быть " -"моделью." +msgid "If first selected item is an object, the second one should also be object." +msgstr "Если первый выбранный элемент является моделью, то второй также должен быть моделью." -msgid "" -"If first selected item is a part, the second one should be part in the same " -"object." -msgstr "" -"Если первый выбранный элемент является частью, то второй должен быть частью " -"той же модели." +msgid "If first selected item is a part, the second one should be part in the same object." +msgstr "Если первый выбранный элемент является частью, то второй должен быть частью той же модели." msgid "The type of the last solid object part is not to be changed." msgstr "Вы не можете изменить тип последнего твердотельного элемента модели." @@ -2232,9 +2148,7 @@ msgid "Invalid numeric." msgstr "Неправильное числовое значение." msgid "one cell can only be copied to one or multiple cells in the same column" -msgstr "" -"Одна ячейка может быть скопирована только в одну или несколько ячеек одного " -"и того же столбца." +msgstr "Одна ячейка может быть скопирована только в одну или несколько ячеек одного и того же столбца." msgid "multiple cells copy is not supported" msgstr "копирование нескольких ячеек не поддерживается" @@ -2396,8 +2310,7 @@ msgid "Failed to connect to cloud service" msgstr "Не удалось подключиться к облачному сервису" msgid "Please click on the hyperlink above to view the cloud service status" -msgstr "" -"Для просмотра состояния статуса сервиса нажмите на вышерасположенную ссылку" +msgstr "Для просмотра состояния статуса сервиса нажмите на вышерасположенную ссылку" msgid "Failed to connect to the printer" msgstr "Не удалось подключиться к принтеру." @@ -2451,8 +2364,7 @@ msgid "Calibrating AMS..." msgstr "Калибровка АСПП..." msgid "A problem occured during calibration. Click to view the solution." -msgstr "" -"Во время калибровки возникла проблема. Нажмите, чтобы просмотреть решение." +msgstr "Во время калибровки возникла проблема. Нажмите, чтобы просмотреть решение." msgid "Calibrate again" msgstr "Повторить калибровку" @@ -2490,12 +2402,8 @@ msgstr "Проверка расположения прутка" msgid "Grab new filament" msgstr "Загрузка нового прутка" -msgid "" -"Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically " -"load or unload filiament." -msgstr "" -"Выберите слот АСПП, затем нажмите кнопку «Загрузить» или «Выгрузить» для " -"автоматической загрузки или выгрузки прутка." +msgid "Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filiament." +msgstr "Выберите слот АСПП, затем нажмите кнопку «Загрузить» или «Выгрузить» для автоматической загрузки или выгрузки прутка." msgid "Edit" msgstr "Правка" @@ -2526,29 +2434,21 @@ msgstr "Расстановка" msgid "Arranging canceled." msgstr "Расстановка отменена." -msgid "" -"Arranging is done but there are unpacked items. Reduce spacing and try again." -msgstr "" -"Расстановка завершена, но не всё уместилось на столе. Уменьшите интервал " -"расстановки и повторите попытку." +msgid "Arranging is done but there are unpacked items. Reduce spacing and try again." +msgstr "Расстановка завершена, но не всё уместилось на столе. Уменьшите интервал расстановки и повторите попытку." msgid "Arranging done." msgstr "Расстановка выполнена." -msgid "" -"Arrange failed. Found some exceptions when processing object geometries." -msgstr "" -"Ошибка расстановки. Обнаружены некоторые исключения при обработке геометрии " -"моделей." +msgid "Arrange failed. Found some exceptions when processing object geometries." +msgstr "Ошибка расстановки. Обнаружены некоторые исключения при обработке геометрии моделей." #, c-format, boost-format msgid "" -"Arrangement ignored the following objects which can't fit into a single " -"bed:\n" +"Arrangement ignored the following objects which can't fit into a single bed:\n" "%s" msgstr "" -"При расстановке были проигнорированы следующие модели, которые не помещаются " -"на одном столе:\n" +"При расстановке были проигнорированы следующие модели, которые не помещаются на одном столе:\n" "%s" msgid "" @@ -2608,55 +2508,34 @@ msgid "Task canceled." msgstr "Задание отменено." msgid "Upload task timed out. Please check the network status and try again." -msgstr "" -"Истекло время ожидания отправки задания. Проверьте сетевое подключение и " -"повторите попытку." +msgstr "Истекло время ожидания отправки задания. Проверьте сетевое подключение и повторите попытку." msgid "Cloud service connection failed. Please try again." -msgstr "" -"Не удалось подключиться к облачному сервису. Пожалуйста, попробуйте ещё раз." +msgstr "Не удалось подключиться к облачному сервису. Пожалуйста, попробуйте ещё раз." msgid "Print file not found. please slice again." msgstr "Файл для печати не найден, нарежьте ещё раз." -msgid "" -"The print file exceeds the maximum allowable size (1GB). Please simplify the " -"model and slice again." -msgstr "" -"Файл для печати превышает максимально допустимый размер (1 ГБ). Пожалуйста, " -"упростите модель и нарежьте ещё раз." +msgid "The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again." +msgstr "Файл для печати превышает максимально допустимый размер (1 ГБ). Пожалуйста, упростите модель и нарежьте ещё раз." msgid "Failed to send the print job. Please try again." -msgstr "" -"Не удалось отправить задание на печать. Пожалуйста, попробуйте ещё раз." +msgstr "Не удалось отправить задание на печать. Пожалуйста, попробуйте ещё раз." msgid "Failed to upload file to ftp. Please try again." msgstr "Не удалось загрузить файл на FTP. Пожалуйста, попробуйте ещё раз." -msgid "" -"Check the current status of the bambu server by clicking on the link above." -msgstr "" -"Проверить текущий статус сервера Bambu можно перейдя по указанной выше " -"ссылке." +msgid "Check the current status of the bambu server by clicking on the link above." +msgstr "Проверить текущий статус сервера Bambu можно перейдя по указанной выше ссылке." -msgid "" -"The size of the print file is too large. Please adjust the file size and try " -"again." -msgstr "" -"Размер файла для печати слишком велик. Пожалуйста, уменьшите размер файла и " -"повторите попытку." +msgid "The size of the print file is too large. Please adjust the file size and try again." +msgstr "Размер файла для печати слишком велик. Пожалуйста, уменьшите размер файла и повторите попытку." msgid "Print file not found, Please slice it again and send it for printing." -msgstr "" -"Файл печати не найден. Пожалуйста, нарежьте его ещё раз и отправьте на " -"печать." +msgstr "Файл печати не найден. Пожалуйста, нарежьте его ещё раз и отправьте на печать." -msgid "" -"Failed to upload print file to FTP. Please check the network status and try " -"again." -msgstr "" -"Не удалось загрузить файл печати на FTP. Проверьте состояние сети и " -"повторите попытку." +msgid "Failed to upload print file to FTP. Please check the network status and try again." +msgstr "Не удалось загрузить файл печати на FTP. Проверьте состояние сети и повторите попытку." msgid "Sending print job over LAN" msgstr "Отправка задания на печать по локальной сети" @@ -2678,13 +2557,11 @@ msgstr "Отправка конфигурации печати" #, c-format, boost-format msgid "Successfully sent. Will automatically jump to the device page in %ss" -msgstr "" -"Успешно отправлено. Автоматический переход на страницу устройства через %s с." +msgstr "Успешно отправлено. Автоматический переход на страницу устройства через %s с." #, c-format, boost-format msgid "Successfully sent. Will automatically jump to the next page in %ss" -msgstr "" -"Успешно отправлено. Автоматический переход на следующую страницу через %s с." +msgstr "Успешно отправлено. Автоматический переход на следующую страницу через %s с." msgid "An SD card needs to be inserted before printing via LAN." msgstr "Перед печатью через локальную сеть необходимо вставить SD-карту." @@ -2705,12 +2582,8 @@ msgstr "Перед отправкой на принтер необходимо msgid "Importing SLA archive" msgstr "Импорт SLA архива" -msgid "" -"The SLA archive doesn't contain any presets. Please activate some SLA " -"printer preset first before importing that SLA archive." -msgstr "" -"Архив SLA не содержит никаких профилей. Пожалуйста, сначала активируйте " -"какой-нибудь профиль SLA принтера, прежде чем импортировать этот SLA архив." +msgid "The SLA archive doesn't contain any presets. Please activate some SLA printer preset first before importing that SLA archive." +msgstr "Архив SLA не содержит никаких профилей. Пожалуйста, сначала активируйте какой-нибудь профиль SLA принтера, прежде чем импортировать этот SLA архив." msgid "Importing canceled." msgstr "Импорт отменен." @@ -2718,12 +2591,8 @@ msgstr "Импорт отменен." msgid "Importing done." msgstr "Импорт завершён." -msgid "" -"The imported SLA archive did not contain any presets. The current SLA " -"presets were used as fallback." -msgstr "" -"Импортированный SLA архив не содержит никаких профилей. Текущие SLA профили " -"использовались в качестве резервных." +msgid "The imported SLA archive did not contain any presets. The current SLA presets were used as fallback." +msgstr "Импортированный SLA архив не содержит никаких профилей. Текущие SLA профили использовались в качестве резервных." msgid "You cannot load SLA project with a multi-part object on the bed" msgstr "Вы не можете загрузить SLA проект с составной моделью на столе" @@ -2768,24 +2637,18 @@ msgid "GNU Affero General Public License, version 3" msgstr "GNU Affero General Public третьей версии" msgid "" -"Orca Slicer is based on BambuStudio by Bambulab, which is from PrusaSlicer " -"by Prusa Research. PrusaSlicer is from Slic3r by Alessandro Ranellucci and " -"the RepRap community" +"Orca Slicer is based on BambuStudio by Bambulab, which is from PrusaSlicer by Prusa Research. PrusaSlicer is from Slic3r by Alessandro Ranellucci and the RepRap " +"community" msgstr "" -"Orca Slicer основан на BambuStudio от компании Bambulab, которая взяла за " -"основу PrusaSlicer от компании Prusa Research. PrusaSlicer же основан на " -"Slic3r от Alessandro Ranellucci и разработках сообщества RepRap." +"Orca Slicer основан на BambuStudio от компании Bambulab, которая взяла за основу PrusaSlicer от компании Prusa Research. PrusaSlicer же основан на Slic3r от " +"Alessandro Ranellucci и разработках сообщества RepRap." msgid "Libraries" msgstr "Библиотеки" -msgid "" -"This software uses open source components whose copyright and other " -"proprietary rights belong to their respective owners" +msgid "This software uses open source components whose copyright and other proprietary rights belong to their respective owners" msgstr "" -"В данном программном обеспечении используются компоненты с открытым исходным " -"кодом, авторские и иные права на которые принадлежат их соответствующим " -"владельцам." +"В данном программном обеспечении используются компоненты с открытым исходным кодом, авторские и иные права на которые принадлежат их соответствующим владельцам." #, c-format, boost-format msgid "About %s" @@ -2798,18 +2661,13 @@ msgid "OrcaSlicer is based on BambuStudio, PrusaSlicer, and SuperSlicer." msgstr "OrcaSlicer основан на проектах BambuStudio, PrusaSlicer и SuperSlicer." msgid "BambuStudio is originally based on PrusaSlicer by PrusaResearch." -msgstr "" -"BambuStudio изначально основан на PrusaSlicer от компании PrusaResearch." +msgstr "BambuStudio изначально основан на PrusaSlicer от компании PrusaResearch." msgid "PrusaSlicer is originally based on Slic3r by Alessandro Ranellucci." msgstr "PrusaSlicer основан на проекте Slic3r от Alessandro Ranellucci." -msgid "" -"Slic3r was created by Alessandro Ranellucci with the help of many other " -"contributors." -msgstr "" -"Slic3r был создан Alessandro Ranellucci совместно с многими другими " -"участниками сообщества." +msgid "Slic3r was created by Alessandro Ranellucci with the help of many other contributors." +msgstr "Slic3r был создан Alessandro Ranellucci совместно с многими другими участниками сообщества." msgid "Version" msgstr "Версия" @@ -2862,8 +2720,7 @@ msgid "Factor N" msgstr "Коэф. N" msgid "Setting Virtual slot information while printing is not supported" -msgstr "" -"Настройка информации виртуального слота во время печати не поддерживается" +msgstr "Настройка информации виртуального слота во время печати не поддерживается" msgid "Are you sure you want to clear the filament information?" msgstr "Вы уверены, что хотите удалить информацию о пластиковой нити?" @@ -2875,9 +2732,7 @@ msgid "Please input a valid value (K in 0~0.3)" msgstr "Пожалуйста, введите допустимое значение (K в диапазоне 0~0.3)" msgid "Please input a valid value (K in 0~0.3, N in 0.6~2.0)" -msgstr "" -"Пожалуйста, введите допустимое значение (K в диапазоне 0~0.3, N в диапазоне " -"0.6~2.0)" +msgstr "Пожалуйста, введите допустимое значение (K в диапазоне 0~0.3, N в диапазоне 0.6~2.0)" msgid "Other Color" msgstr "Другой цвет" @@ -2889,14 +2744,11 @@ msgid "Dynamic flow calibration" msgstr "Калибровка динамики потока" msgid "" -"The nozzle temp and max volumetric speed will affect the calibration " -"results. Please fill in the same values as the actual printing. They can be " -"auto-filled by selecting a filament preset." +"The nozzle temp and max volumetric speed will affect the calibration results. Please fill in the same values as the actual printing. They can be auto-filled by " +"selecting a filament preset." msgstr "" -"Температура сопла и максимальная объёмная скорость влияют на результаты " -"калибровки. Введите те же значения, которые вы используете при фактической " -"печати. Их можно заполнить автоматически, выбрав существующий профиль " -"пластиковой нити." +"Температура сопла и максимальная объёмная скорость влияют на результаты калибровки. Введите те же значения, которые вы используете при фактической печати. Их " +"можно заполнить автоматически, выбрав существующий профиль пластиковой нити." msgid "Nozzle Diameter" msgstr "Диаметр сопла" @@ -2929,13 +2781,11 @@ msgid "Next" msgstr "Далее" msgid "" -"Calibration completed. Please find the most uniform extrusion line on your " -"hot bed like the picture below, and fill the value on its left side into the " -"factor K input box." +"Calibration completed. Please find the most uniform extrusion line on your hot bed like the picture below, and fill the value on its left side into the factor K " +"input box." msgstr "" -"Калибровка завершена. Теперь найдите на столе наиболее равномерно " -"экструдированную линию, как показано на рисунке ниже, и введите это значение " -"в поле ввода коэффициента K." +"Калибровка завершена. Теперь найдите на столе наиболее равномерно экструдированную линию, как показано на рисунке ниже, и введите это значение в поле ввода " +"коэффициента K." msgid "Save" msgstr "Сохранить" @@ -2966,8 +2816,7 @@ msgstr "Шаг" msgid "AMS Slots" msgstr "Слоты АСПП" -msgid "" -"Note: Only the AMS slots loaded with the same material type can be selected." +msgid "Note: Only the AMS slots loaded with the same material type can be selected." msgstr "Примечание: выбор слотов АСПП ограничен одинаковым типом материала." msgid "Enable AMS" @@ -2985,40 +2834,26 @@ msgstr "Печать материалом, установленным на за msgid "Cabin humidity" msgstr "Влажность внутри" -msgid "" -"Green means that AMS humidity is normal, orange represent humidity is high, " -"red represent humidity is too high.(Hygrometer: lower the better.)" -msgstr "" -"Зелёный цвет означает, что влажность в системе АСПП нормальная, оранжевый - " -"высокая, красный - слишком высокая. Чем ниже значение гигрометра, тем лучше." +msgid "Green means that AMS humidity is normal, orange represent humidity is high, red represent humidity is too high.(Hygrometer: lower the better.)" +msgstr "Зелёный цвет означает, что влажность в системе АСПП нормальная, оранжевый - высокая, красный - слишком высокая. Чем ниже значение гигрометра, тем лучше." msgid "Desiccant status" msgstr "Состояние влагопоглотителя" -msgid "" -"A desiccant status lower than two bars indicates that desiccant may be " -"inactive. Please change the desiccant.(The bars: higher the better.)" +msgid "A desiccant status lower than two bars indicates that desiccant may be inactive. Please change the desiccant.(The bars: higher the better.)" msgstr "" -"Состояние влагопоглотителя (силикагеля) ниже двух делений указывает на то, " -"что он может уже не выполнять свою функцию. Пожалуйста, замените его. Чем " -"больше делений на индикаторе, тем лучше." +"Состояние влагопоглотителя (силикагеля) ниже двух делений указывает на то, что он может уже не выполнять свою функцию. Пожалуйста, замените его. Чем больше " +"делений на индикаторе, тем лучше." msgid "" -"Note: When the lid is open or the desiccant pack is changed, it can take " -"hours or a night to absorb the moisture. Low temperatures also slow down the " -"process. During this time, the indicator may not represent the chamber " -"accurately." +"Note: When the lid is open or the desiccant pack is changed, it can take hours or a night to absorb the moisture. Low temperatures also slow down the process. " +"During this time, the indicator may not represent the chamber accurately." msgstr "" -"Примечание: при открытой крышке или заменённом влагопоглотителе, может " -"потребоваться несколько часов или ночь для поглощения влаги. Кроме того, " -"процесс может замедлиться из-за низкой температуры окружающей среды. В " -"течение этого времени значения индикатора могут быть неточными." +"Примечание: при открытой крышке или заменённом влагопоглотителе, может потребоваться несколько часов или ночь для поглощения влаги. Кроме того, процесс может " +"замедлиться из-за низкой температуры окружающей среды. В течение этого времени значения индикатора могут быть неточными." -msgid "" -"Config which AMS slot should be used for a filament used in the print job" -msgstr "" -"Задайте слот АСПП, который должен использоваться для прутка, используемого в " -"текущем задании." +msgid "Config which AMS slot should be used for a filament used in the print job" +msgstr "Задайте слот АСПП, который должен использоваться для прутка, используемого в текущем задании." msgid "Filament used in this print job" msgstr "Пруток используемый в этом задании" @@ -3033,8 +2868,7 @@ msgid "Do not Enable AMS" msgstr "Не включать АСПП" msgid "Print using materials mounted on the back of the case" -msgstr "" -"Печать с использованием материала, установленного на задней части корпуса" +msgstr "Печать с использованием материала, установленного на задней части корпуса" msgid "Print with filaments in ams" msgstr "" @@ -3044,12 +2878,8 @@ msgstr "" msgid "Print with filaments mounted on the back of the chassis" msgstr "Печать материалами, установленными на задней части корпуса." -msgid "" -"When the current material run out, the printer will continue to print in the " -"following order." -msgstr "" -"Когда текущий материал закончится, принтер продолжит печать в указанном " -"порядке." +msgid "When the current material run out, the printer will continue to print in the following order." +msgstr "Когда текущий материал закончится, принтер продолжит печать в указанном порядке." msgid "Group" msgstr "Группа" @@ -3057,22 +2887,15 @@ msgstr "Группа" msgid "The printer does not currently support auto refill." msgstr "В настоящее время принтер не поддерживает функцию автодозаправки." -msgid "" -"AMS filament backup is not enabled, please enable it in the AMS settings." -msgstr "" -"Резервирование материала АСПП не включено, пожалуйста, включите его в " -"настройках АСПП." +msgid "AMS filament backup is not enabled, please enable it in the AMS settings." +msgstr "Резервирование материала АСПП не включено, пожалуйста, включите его в настройках АСПП." msgid "" -"If there are two identical filaments in AMS, AMS filament backup will be " -"enabled. \n" -"(Currently supporting automatic supply of consumables with the same brand, " -"material type, and color)" +"If there are two identical filaments in AMS, AMS filament backup will be enabled. \n" +"(Currently supporting automatic supply of consumables with the same brand, material type, and color)" msgstr "" -"При наличии в АСПП двух одинаковых материалов включается функция " -"резервирования материала (автодозаправка). \n" -"(В настоящее время поддерживается автоматическая дозаправка материала только " -"одного производителя, типа и цвета)" +"При наличии в АСПП двух одинаковых материалов включается функция резервирования материала (автодозаправка). \n" +"(В настоящее время поддерживается автоматическая дозаправка материала только одного производителя, типа и цвета)" msgid "AMS Settings" msgstr "Настройки АСПП" @@ -3080,70 +2903,45 @@ msgstr "Настройки АСПП" msgid "Insertion update" msgstr "Обновлять данные при вставке материала" -msgid "" -"The AMS will automatically read the filament information when inserting a " -"new Bambu Lab filament. This takes about 20 seconds." -msgstr "" -"АСПП автоматически считывает информацию о материале при установке новой " -"катушки Bambu. Это занимает около 20 секунд." +msgid "The AMS will automatically read the filament information when inserting a new Bambu Lab filament. This takes about 20 seconds." +msgstr "АСПП автоматически считывает информацию о материале при установке новой катушки Bambu. Это занимает около 20 секунд." -msgid "" -"Note: if new filament is inserted during printing, the AMS will not " -"automatically read any information until printing is completed." -msgstr "" -"Примечание: если во время печати вставляется новая пластиковая нить, АСПП " -"автоматически считает информацию о ней только по завершению печати." +msgid "Note: if new filament is inserted during printing, the AMS will not automatically read any information until printing is completed." +msgstr "Примечание: если во время печати вставляется новая пластиковая нить, АСПП автоматически считает информацию о ней только по завершению печати." -msgid "" -"When inserting a new filament, the AMS will not automatically read its " -"information, leaving it blank for you to enter manually." +msgid "When inserting a new filament, the AMS will not automatically read its information, leaving it blank for you to enter manually." msgstr "" -"При вставке новой пластиковой нити, АСПП не будет автоматически считывать " -"информацию о ней, оставляя поле пустым, чтобы пользователь мог ввести данные " -"о ней вручную." +"При вставке новой пластиковой нити, АСПП не будет автоматически считывать информацию о ней, оставляя поле пустым, чтобы пользователь мог ввести данные о ней " +"вручную." msgid "Power on update" msgstr "Обновлять данные при включении принтера" -msgid "" -"The AMS will automatically read the information of inserted filament on " -"start-up. It will take about 1 minute.The reading process will roll filament " -"spools." +msgid "The AMS will automatically read the information of inserted filament on start-up. It will take about 1 minute.The reading process will roll filament spools." msgstr "" -"При каждом включении принтера АСПП будет автоматически считывать информация " -"о вставленных материалах. Это занимает приблизительно одну минуту. В " -"процессе считывания информации о материале катушка вращается." +"При каждом включении принтера АСПП будет автоматически считывать информация о вставленных материалах. Это занимает приблизительно одну минуту. В процессе " +"считывания информации о материале катушка вращается." msgid "" -"The AMS will not automatically read information from inserted filament " -"during startup and will continue to use the information recorded before the " -"last shutdown." +"The AMS will not automatically read information from inserted filament during startup and will continue to use the information recorded before the last shutdown." msgstr "" -"При каждом включении принтера, считывание информации о вставленных " -"материалах АСПП будет отключено. Будет использоваться информация, полученная " -"перед последним выключением." +"При каждом включении принтера, считывание информации о вставленных материалах АСПП будет отключено. Будет использоваться информация, полученная перед последним " +"выключением." msgid "Update remaining capacity" msgstr "Обновлять оставшуюся ёмкость катушки" msgid "" -"The AMS will estimate Bambu filament's remaining capacity after the filament " -"info is updated. During printing, remaining capacity will be updated " -"automatically." +"The AMS will estimate Bambu filament's remaining capacity after the filament info is updated. During printing, remaining capacity will be updated automatically." msgstr "" -"АСПП считывает информацию о расходном материале Bambu и рассчитывает его " -"остаточную ёмкость на катушке. Остаточная ёмкость обновляется автоматически " -"в процессе печати." +"АСПП считывает информацию о расходном материале Bambu и рассчитывает его остаточную ёмкость на катушке. Остаточная ёмкость обновляется автоматически в процессе " +"печати." msgid "AMS filament backup" msgstr "Резервирование материала АСПП" -msgid "" -"AMS will continue to another spool with the same properties of filament " -"automatically when current filament runs out" -msgstr "" -"АСПП автоматически переключится на другую катушку с тем же типом материала, " -"когда текущий закончится." +msgid "AMS will continue to another spool with the same properties of filament automatically when current filament runs out" +msgstr "АСПП автоматически переключится на другую катушку с тем же типом материала, когда текущий закончится." msgid "File" msgstr "Файл" @@ -3151,19 +2949,11 @@ msgstr "Файл" msgid "Calibration" msgstr "Калибровка" -msgid "" -"Failed to download the plug-in. Please check your firewall settings and vpn " -"software, check and retry." -msgstr "" -"Не удалось загрузить плагин. Пожалуйста, проверьте настройки брандмауэра и " -"vpn, и повторите попытку." +msgid "Failed to download the plug-in. Please check your firewall settings and vpn software, check and retry." +msgstr "Не удалось загрузить плагин. Пожалуйста, проверьте настройки брандмауэра и vpn, и повторите попытку." -msgid "" -"Failed to install the plug-in. Please check whether it is blocked or deleted " -"by anti-virus software." -msgstr "" -"Не удалось установить плагин. Пожалуйста, проверьте, не заблокирован ли он " -"или не удалён антивирусом." +msgid "Failed to install the plug-in. Please check whether it is blocked or deleted by anti-virus software." +msgstr "Не удалось установить плагин. Пожалуйста, проверьте, не заблокирован ли он или не удалён антивирусом." msgid "click here to see more info" msgstr "нажмите здесь, чтобы увидеть больше информации" @@ -3171,22 +2961,14 @@ msgstr "нажмите здесь, чтобы увидеть больше инф msgid "Please home all axes (click " msgstr "Пожалуйста, припаркуйте все оси в начало координат (нажав " -msgid "" -") to locate the toolhead's position. This prevents device moving beyond the " -"printable boundary and causing equipment wear." -msgstr "" -") для определения положения печатной головы. Это предотвращает перемещение " -"за пределы области печати и износ оборудования." +msgid ") to locate the toolhead's position. This prevents device moving beyond the printable boundary and causing equipment wear." +msgstr ") для определения положения печатной головы. Это предотвращает перемещение за пределы области печати и износ оборудования." msgid "Go Home" msgstr "На главную" -msgid "" -"A error occurred. Maybe memory of system is not enough or it's a bug of the " -"program" -msgstr "" -"Произошла ошибка. Возможно, недостаточно системной памяти или это баг " -"программы." +msgid "A error occurred. Maybe memory of system is not enough or it's a bug of the program" +msgstr "Произошла ошибка. Возможно, недостаточно системной памяти или это баг программы." msgid "Please save project and restart the program. " msgstr "Пожалуйста, сохраните проект и перезапустите программу. " @@ -3239,15 +3021,11 @@ msgid "Running post-processing scripts" msgstr "Запуск скриптов постобработки" msgid "Copying of the temporary G-code to the output G-code failed" -msgstr "" -"Не удалось скопировать временный G-код в местонахождение выходного файла G-" -"кода" +msgstr "Не удалось скопировать временный G-код в местонахождение выходного файла G-кода" #, boost-format msgid "Scheduling upload to `%1%`. See Window -> Print Host Upload Queue" -msgstr "" -"Планирование загрузки на `%1%`. Смотрите Окна -> Очередь загрузки на хост " -"печати" +msgstr "Планирование загрузки на `%1%`. Смотрите Окна -> Очередь загрузки на хост печати" msgid "Origin" msgstr "Начало координат" @@ -3255,18 +3033,11 @@ msgstr "Начало координат" msgid "Size in X and Y of the rectangular plate." msgstr "Размеры прямоугольного стола в XY координатах." -msgid "" -"Distance of the 0,0 G-code coordinate from the front left corner of the " -"rectangle." -msgstr "" -"Расстояние до точки начало координат. Отсчёт от левого переднего угла " -"прямоугольного стола." +msgid "Distance of the 0,0 G-code coordinate from the front left corner of the rectangle." +msgstr "Расстояние до точки начало координат. Отсчёт от левого переднего угла прямоугольного стола." -msgid "" -"Diameter of the print bed. It is assumed that origin (0,0) is located in the " -"center." -msgstr "" -"Диаметр стола. Предполагается, что начало координат (0,0) находится в центре." +msgid "Diameter of the print bed. It is assumed that origin (0,0) is located in the center." +msgstr "Диаметр стола. Предполагается, что начало координат (0,0) находится в центре." msgid "Rectangular" msgstr "Прямоугольная" @@ -3304,11 +3075,8 @@ msgstr "Ошибка! Недопустимая модель" msgid "The selected file contains no geometry." msgstr "Выбранный файл не содержит геометрии." -msgid "" -"The selected file contains several disjoint areas. This is not supported." -msgstr "" -"Выбранный файл содержит несколько не пересекающихся областей. Такие файлы не " -"поддерживаются." +msgid "The selected file contains several disjoint areas. This is not supported." +msgstr "Выбранный файл содержит несколько не пересекающихся областей. Такие файлы не поддерживаются." msgid "Choose a file to import bed texture from (PNG/SVG):" msgstr "Выберите файл для импорта текстуры стола из PNG/SVG:" @@ -3329,12 +3097,8 @@ msgstr "" "\n" #, c-format, boost-format -msgid "" -"Recommended nozzle temperature of this filament type is [%d, %d] degree " -"centigrade" -msgstr "" -"Рекомендуемая температура сопла для данного типа пластиковой нити составляет " -"[%d, %d] градусов Цельсия." +msgid "Recommended nozzle temperature of this filament type is [%d, %d] degree centigrade" +msgstr "Рекомендуемая температура сопла для данного типа пластиковой нити составляет [%d, %d] градусов Цельсия." msgid "" "Too small max volumetric speed.\n" @@ -3345,13 +3109,11 @@ msgstr "" #, c-format, boost-format msgid "" -"Current chamber temperature is higher than the material's safe temperature," -"it may result in material softening and clogging.The maximum safe " -"temperature for the material is %d" +"Current chamber temperature is higher than the material's safe temperature,it may result in material softening and clogging.The maximum safe temperature for the " +"material is %d" msgstr "" -"Текущая температура в камере превышает безопасную температуру для этого " -"материала, что может привести к размягчению материала или засорению " -"экструдера. Безопасная температура текущего материала составляет %d." +"Текущая температура в камере превышает безопасную температуру для этого материала, что может привести к размягчению материала или засорению экструдера. " +"Безопасная температура текущего материала составляет %d." msgid "" "Too small layer height.\n" @@ -3377,19 +3139,15 @@ msgstr "" "Высота первого слоя будет сброшена до 0,2." msgid "" -"This setting is only used for model size tunning with small value in some " -"cases.\n" +"This setting is only used for model size tunning with small value in some cases.\n" "For example, when model size has small error and hard to be assembled.\n" "For large size tuning, please use model scale function.\n" "\n" "The value will be reset to 0." msgstr "" -"Этот параметр используется только для точной корректировки размера модели в " -"определенных случаях.\n" -"Например, когда есть небольшая погрешность в размерах модели и её трудно " -"собрать.\n" -"Для более значительной корректировки размеров используйте функцию " -"масштабирования модели.\n" +"Этот параметр используется только для точной корректировки размера модели в определенных случаях.\n" +"Например, когда есть небольшая погрешность в размерах модели и её трудно собрать.\n" +"Для более значительной корректировки размеров используйте функцию масштабирования модели.\n" "\n" "Это значение будет сброшено на 0." @@ -3401,18 +3159,14 @@ msgid "" "The value will be reset to 0." msgstr "" "Слишком большая компенсация слоновьей ноги нецелесообразна.\n" -"Если имеется серьёзный эффект слоновьей ноги, проверьте другие настройки " -"печати.\n" +"Если имеется серьёзный эффект слоновьей ноги, проверьте другие настройки печати.\n" "Например, не слишком ли высокая температура стола.\n" "\n" "Значение будет сброшено на 0." -msgid "" -"Spiral mode only works when wall loops is 1, support is disabled, top shell " -"layers is 0, sparse infill density is 0 and timelapse type is traditional." +msgid "Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional." msgstr "" -"Для режима печати «Спиральная ваза» необходимо чтобы соблюдались следующие " -"условия:\n" +"Для режима печати «Спиральная ваза» необходимо чтобы соблюдались следующие условия:\n" "- одностеночный периметр\n" "- отсутствие поддержки\n" "- отсутствие верхних сплошных слоёв\n" @@ -3432,33 +3186,25 @@ msgstr "" "Да - Изменить эти настройки и включить режим «Спиральная ваза»\n" "Нет - Отказаться от использования режима «Спиральная ваза»" -msgid "" -"Alternate extra wall does't work well when ensure vertical shell thickness " -"is set to All. " -msgstr "" -"Чередующаяся дополнительная стенка не работает, если для \"Обеспечивать " -"верт. толщину оболочки\" установлено значение «Везде»." +msgid "Alternate extra wall does't work well when ensure vertical shell thickness is set to All. " +msgstr "Чередующаяся дополнительная стенка не работает, если для \"Обеспечивать верт. толщину оболочки\" установлено значение «Везде»." msgid "" "Change these settings automatically? \n" -"Yes - Change ensure vertical shell thickness to Moderate and enable " -"alternate extra wall\n" +"Yes - Change ensure vertical shell thickness to Moderate and enable alternate extra wall\n" "No - Dont use alternate extra wall" msgstr "" "Изменить эти настройки автоматически?\n" -"Да - Изменить в «Обеспечивать верт. толщину оболочки» на значение " -"«Умеренное» и включить чередующуюся дополнительную стенку\n" +"Да - Изменить в «Обеспечивать верт. толщину оболочки» на значение «Умеренное» и включить чередующуюся дополнительную стенку\n" "Нет - Отказаться от использования чередующейся дополнительной стенки" msgid "" -"Prime tower does not work when Adaptive Layer Height or Independent Support " -"Layer Height is on.\n" +"Prime tower does not work when Adaptive Layer Height or Independent Support Layer Height is on.\n" "Which do you want to keep?\n" "YES - Keep Prime Tower\n" "NO - Keep Adaptive Layer Height and Independent Support Layer Height" msgstr "" -"Черновая башня не работает, когда включена функция «Переменная высота слоёв» " -"или «Независимая высота слоя поддержки»\n" +"Черновая башня не работает, когда включена функция «Переменная высота слоёв» или «Независимая высота слоя поддержки»\n" "Что вы хотите сохранить?\n" "ДА - Сохранить черновую башню\n" "НЕТ - Сохранить переменную высоту слоя и независимую высоту слоя поддержки" @@ -3469,8 +3215,7 @@ msgid "" "YES - Keep Prime Tower\n" "NO - Keep Adaptive Layer Height" msgstr "" -"Черновая башня не работает, когда включена функция «Переменная высота " -"слоёв».\n" +"Черновая башня не работает, когда включена функция «Переменная высота слоёв».\n" "Что вы хотите сохранить?\n" "Да - Сохранить черновую башню\n" "Нет - Сохранить переменную высоту слоёв" @@ -3481,8 +3226,7 @@ msgid "" "YES - Keep Prime Tower\n" "NO - Keep Independent Support Layer Height" msgstr "" -"Черновая башня не работает, если включена функция «Независимая высота слоя " -"поддержки»\n" +"Черновая башня не работает, если включена функция «Независимая высота слоя поддержки»\n" "Что вы хотите сохранить?\n" "ДА - Сохранить черновую башню\n" "НЕТ - Сохранить независимую высоту слоя поддержки" @@ -3581,8 +3325,7 @@ msgid "Paused due to AMS lost" msgstr "Печать приостановлена из-за потери связи с АСПП" msgid "Paused due to low speed of the heat break fan" -msgstr "" -"Печать приостановлена из-за низкой скорости вращения вентилятора головы" +msgstr "Печать приостановлена из-за низкой скорости вращения вентилятора головы" msgid "Paused due to chamber temperature control error" msgstr "Печать приостановлена из-за ошибки контроля температуры в камере" @@ -3645,37 +3388,29 @@ msgid "Update failed." msgstr "Сбой обновления." msgid "" -"The current chamber temperature or the target chamber temperature exceeds " -"45℃.In order to avoid extruder clogging,low temperature filament(PLA/PETG/" -"TPU) is not allowed to be loaded." +"The current chamber temperature or the target chamber temperature exceeds 45℃.In order to avoid extruder clogging,low temperature filament(PLA/PETG/TPU) is not " +"allowed to be loaded." msgstr "" -"Текущая температура в камере или целевая температура в камере превышает 45℃. " -"Чтобы избежать засорения экструдера, запрещается загрузка низкотемпературной " +"Текущая температура в камере или целевая температура в камере превышает 45℃. Чтобы избежать засорения экструдера, запрещается загрузка низкотемпературной " "печатной нити (PLA/PETG/TPU)." msgid "" -"Low temperature filament(PLA/PETG/TPU) is loaded in the extruder.In order to " -"avoid extruder clogging,it is not allowed to set the chamber temperature " -"above 45℃." +"Low temperature filament(PLA/PETG/TPU) is loaded in the extruder.In order to avoid extruder clogging,it is not allowed to set the chamber temperature above 45℃." msgstr "" -"В экструдер загружается низкотемпературная пластиковая нить (PLA/PETG/TPU). " -"Чтобы избежать засорения экструдера, запрещается устанавливать температуру в " -"камере выше 45℃." +"В экструдер загружается низкотемпературная пластиковая нить (PLA/PETG/TPU). Чтобы избежать засорения экструдера, запрещается устанавливать температуру в камере " +"выше 45℃." msgid "" -"When you set the chamber temperature below 40℃, the chamber temperature " -"control will not be activated. And the target chamber temperature will " -"automatically be set to 0℃." +"When you set the chamber temperature below 40℃, the chamber temperature control will not be activated. And the target chamber temperature will automatically be " +"set to 0℃." msgstr "" -"Если вы установили температура в камере ниже 40℃, то контроль температуры в " -"камере не запустится, а целевая температура в ней будет автоматически " -"установлена на 0℃." +"Если вы установили температура в камере ниже 40℃, то контроль температуры в камере не запустится, а целевая температура в ней будет автоматически установлена на " +"0℃." msgid "Failed to start printing job" msgstr "Не удалось запустить задание на печать." -msgid "" -"This calibration does not support the currently selected nozzle diameter" +msgid "This calibration does not support the currently selected nozzle diameter" msgstr "Данная калибровка не поддерживает выбранный диаметр сопла" msgid "Current flowrate cali param is invalid" @@ -3696,19 +3431,11 @@ msgstr "Печать TPU с помощью АСПП не поддерживае msgid "Bambu PET-CF/PA6-CF is not supported by AMS." msgstr "Печать Bambu PET-CF/PA6-CF с помощью АСПП не поддерживается." -msgid "" -"Damp PVA will become flexible and get stuck inside AMS,please take care to " -"dry it before use." -msgstr "" -"Влажный PVA становится гибким и застревает внутри АСПП, поэтому перед " -"использованием его необходимо просушить." +msgid "Damp PVA will become flexible and get stuck inside AMS,please take care to dry it before use." +msgstr "Влажный PVA становится гибким и застревает внутри АСПП, поэтому перед использованием его необходимо просушить." -msgid "" -"CF/GF filaments are hard and brittle, It's easy to break or get stuck in " -"AMS, please use with caution." -msgstr "" -"CF/GF пластиковые нити твердые и хрупкие, легко ломаются или застревают в " -"АСПП, поэтому используйте их с осторожностью." +msgid "CF/GF filaments are hard and brittle, It's easy to break or get stuck in AMS, please use with caution." +msgstr "CF/GF пластиковые нити твердые и хрупкие, легко ломаются или застревают в АСПП, поэтому используйте их с осторожностью." msgid "default" msgstr "По ум." @@ -3718,9 +3445,7 @@ msgid "Edit Custom G-code (%1%)" msgstr "Изменение пользовательского G-кода (%1%)" msgid "Built-in placeholders (Double click item to add to G-code)" -msgstr "" -"Встроенные заполнители. Для добавить его в G-код, дважды щелкните на " -"выбранное." +msgstr "Встроенные заполнители. Для добавить его в G-код, дважды щелкните на выбранное." msgid "Search gcode placeholders" msgstr "Поиск G-кода в заполнителях" @@ -4145,12 +3870,8 @@ msgid "Size:" msgstr "Размер:" #, c-format, boost-format -msgid "" -"Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please " -"separate the conflicted objects farther (%s <-> %s)." -msgstr "" -"В G-коде на %d слое (z = %.2lf мм) обнаружен конфликт путей. Пожалуйста, " -"разместите конфликтующие модели дальше друг от друга (%s <-> %s)." +msgid "Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s)." +msgstr "В G-коде на %d слое (z = %.2lf мм) обнаружен конфликт путей. Пожалуйста, разместите конфликтующие модели дальше друг от друга (%s <-> %s)." msgid "An object is layed over the boundary of plate." msgstr "Модель выходить за границы печатного стола." @@ -4166,13 +3887,10 @@ msgstr "При редактировании, те модели с которым msgid "" "An object is laid over the boundary of plate or exceeds the height limit.\n" -"Please solve the problem by moving it totally on or off the plate, and " -"confirming that the height is within the build volume." +"Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume." msgstr "" "Модель выходит за границы стола или превышает высоту печати.\n" -"Пожалуйста, устраните проблему, уместив всю модель в границы стола (или за " -"пределы стола) и убедитесь, что высота модели находится в пределах область " -"построения." +"Пожалуйста, устраните проблему, уместив всю модель в границы стола (или за пределы стола) и убедитесь, что высота модели находится в пределах область построения." msgid "Calibration step selection" msgstr "Выбор шагов калибровки" @@ -4193,12 +3911,10 @@ msgid "Calibration program" msgstr "О программе калибровке" msgid "" -"The calibration program detects the status of your device automatically to " -"minimize deviation.\n" +"The calibration program detects the status of your device automatically to minimize deviation.\n" "It keeps the device performing optimally." msgstr "" -"Программа калибровки автоматически определяет состояние вашего принтера, " -"чтобы свести к минимуму ошибки оборудования.\n" +"Программа калибровки автоматически определяет состояние вашего принтера, чтобы свести к минимуму ошибки оборудования.\n" "Это обеспечивает оптимальную работу устройства." msgid "Calibration Flow" @@ -4253,9 +3969,7 @@ msgstr "Пожалуйста, введите код доступа к принт msgid "" "You can find it in \"Settings > Network > Connection code\"\n" "on the printer, as shown in the figure:" -msgstr "" -"Вы можете найти его на принтере в разделе Настройки > Сеть > Код " -"подключения, как показано на рисунке:" +msgstr "Вы можете найти его на принтере в разделе Настройки > Сеть > Код подключения, как показано на рисунке:" msgid "Invalid input." msgstr "Неверный ввод." @@ -4543,8 +4257,7 @@ msgid "Show 3D Navigator" msgstr "Показать навигационный куб" msgid "Show 3D navigator in Prepare and Preview scene" -msgstr "" -"Показать навигационный куб в режиме подготовки и предварительного просмотра." +msgstr "Показать навигационный куб в режиме подготовки и предварительного просмотра." msgid "Reset Window Layout" msgstr "Сбросить настройки окон" @@ -4694,20 +4407,17 @@ msgstr "Выберите профиль для загрузки:" #, c-format, boost-format msgid "There is %d config imported. (Only non-system and compatible configs)" -msgid_plural "" -"There are %d configs imported. (Only non-system and compatible configs)" +msgid_plural "There are %d configs imported. (Only non-system and compatible configs)" msgstr[0] "Импортирована %d конфигурация (только не системная и совместимая)." msgstr[1] "Импортировано %d конфигурации (только не системные и совместимые)." msgstr[2] "Импортировано %d конфигураций (только не системные и совместимые)." msgid "" "\n" -"Hint: Make sure you have added the corresponding printer before importing " -"the configs." +"Hint: Make sure you have added the corresponding printer before importing the configs." msgstr "" "\n" -"Подсказка: перед импортом конфигураций убедитесь, что вы добавили " -"соответствующий принтер." +"Подсказка: перед импортом конфигураций убедитесь, что вы добавили соответствующий принтер." msgid "Import result" msgstr "Импортировать результат" @@ -4776,9 +4486,7 @@ msgid "Stopped." msgstr "Остановлено." msgid "LAN Connection Failed (Failed to start liveview)" -msgstr "" -"Сбой подключения к локальной сети (не удалось запустить просмотр в реальном " -"времени)" +msgstr "Сбой подключения к локальной сети (не удалось запустить просмотр в реальном времени)" msgid "" "Virtual Camera Tools is required for this task!\n" @@ -4884,17 +4592,10 @@ msgstr "Ошибка загрузки [%d]" #, c-format, boost-format msgid "You are going to delete %u file from printer. Are you sure to continue?" -msgid_plural "" -"You are going to delete %u files from printer. Are you sure to continue?" -msgstr[0] "" -"Вы собираетесь удалить %u файл с принтера. Вы уверены, что хотите это " -"сделать?" -msgstr[1] "" -"Вы собираетесь удалить %u файла с принтера. Вы уверены, что хотите это " -"сделать?" -msgstr[2] "" -"Вы собираетесь удалить %u файлов с принтера. Вы уверены, что хотите это " -"сделать?" +msgid_plural "You are going to delete %u files from printer. Are you sure to continue?" +msgstr[0] "Вы собираетесь удалить %u файл с принтера. Вы уверены, что хотите это сделать?" +msgstr[1] "Вы собираетесь удалить %u файла с принтера. Вы уверены, что хотите это сделать?" +msgstr[2] "Вы собираетесь удалить %u файлов с принтера. Вы уверены, что хотите это сделать?" msgid "Delete files" msgstr "Удалить файлы" @@ -4915,12 +4616,8 @@ msgstr "Не удалось получить информацию о модел msgid "Failed to parse model infomations." msgstr "Не удалось проанализировать информацию о модели." -msgid "" -"The .gcode.3mf file contains no G-code data.Please slice it with Orca Slicer " -"and export a new .gcode.3mf file." -msgstr "" -"Файл .gcode.3mf не содержит G-кода. Пожалуйста, нарежьте его в программе " -"Orca Slicer и экспортируйте новый файл .gcode.3mf." +msgid "The .gcode.3mf file contains no G-code data.Please slice it with Orca Slicer and export a new .gcode.3mf file." +msgstr "Файл .gcode.3mf не содержит G-кода. Пожалуйста, нарежьте его в программе Orca Slicer и экспортируйте новый файл .gcode.3mf." #, c-format, boost-format msgid "File '%s' was lost! Please download it again." @@ -4946,9 +4643,7 @@ msgid "Connection lost. Please retry." msgstr "Соединение потеряно. Пожалуйста, повторите попытку." msgid "The device cannot handle more conversations. Please retry later." -msgstr "" -"Устройство не может обработать больше сообщений. Пожалуйста, повторите " -"попытку позже." +msgstr "Устройство не может обработать больше сообщений. Пожалуйста, повторите попытку позже." msgid "File not exists." msgstr "Файл не существует." @@ -5033,9 +4728,7 @@ msgstr "" msgid "How do you like this printing file?" msgstr "На сколько вы оцениваете этот напечатанный файл?" -msgid "" -"(The model has already been rated. Your rating will overwrite the previous " -"rating.)" +msgid "(The model has already been rated. Your rating will overwrite the previous rating.)" msgstr "(Модели уже присвоен рейтинг. Ваш рейтинг перезапишет предыдущий.)" msgid "Rate" @@ -5110,12 +4803,8 @@ msgstr "Слой: %s" msgid "Layer: %d/%d" msgstr "Слой: %d/%d" -msgid "" -"Please heat the nozzle to above 170 degree before loading or unloading " -"filament." -msgstr "" -"Пожалуйста, перед загрузкой или выгрузкой прутка, нагрейте сопло до " -"температуры выше 170°C." +msgid "Please heat the nozzle to above 170 degree before loading or unloading filament." +msgstr "Пожалуйста, перед загрузкой или выгрузкой прутка, нагрейте сопло до температуры выше 170°C." msgid "Still unload" msgstr "Ещё выгружается" @@ -5126,12 +4815,8 @@ msgstr "Ещё загружается" msgid "Please select an AMS slot before calibration" msgstr "Пожалуйста, выберите слот АСПП перед калибровкой" -msgid "" -"Cannot read filament info: the filament is loaded to the tool head,please " -"unload the filament and try again." -msgstr "" -"Не удаётся считать информацию о пластиковой нити. Пластиковая нить загружена " -"в голову, пожалуйста, выгрузите её и повторите попытку." +msgid "Cannot read filament info: the filament is loaded to the tool head,please unload the filament and try again." +msgstr "Не удаётся считать информацию о пластиковой нити. Пластиковая нить загружена в голову, пожалуйста, выгрузите её и повторите попытку." msgid "This only takes effect during printing" msgstr "Применимо только во время печати" @@ -5200,20 +4885,17 @@ msgid " can not be opened\n" msgstr " не удаётся открыть\n" msgid "" -"The following issues occurred during the process of uploading images. Do you " -"want to ignore them?\n" +"The following issues occurred during the process of uploading images. Do you want to ignore them?\n" "\n" msgstr "" -"В процессе загрузки изображений возникли следующие проблемы. Игнорировать " -"их?\n" +"В процессе загрузки изображений возникли следующие проблемы. Игнорировать их?\n" "\n" msgid "info" msgstr "Информация" msgid "Synchronizing the printing results. Please retry a few seconds later." -msgstr "" -"Синхронизация результатов печати. Повторите попытку через несколько секунд." +msgstr "Синхронизация результатов печати. Повторите попытку через несколько секунд." msgid "Upload failed\n" msgstr "Ошибка отправки\n" @@ -5242,12 +4924,8 @@ msgstr "" "\n" "Хотите перейти на страницу для выставления оценки?" -msgid "" -"Some of your images failed to upload. Would you like to redirect to the " -"webpage for rating?" -msgstr "" -"Некоторые из ваших изображений не удалось загрузить. Хотите перейти на " -"страницу для выставления оценки?" +msgid "Some of your images failed to upload. Would you like to redirect to the webpage for rating?" +msgstr "Некоторые из ваших изображений не удалось загрузить. Хотите перейти на страницу для выставления оценки?" msgid "You can select up to 16 images." msgstr "Допускается выбор до 16 изображений." @@ -5255,9 +4933,7 @@ msgstr "Допускается выбор до 16 изображений." msgid "" "At least one successful print record of this print profile is required \n" "to give a positive rating(4 or 5stars)." -msgstr "" -"Для выставления положительной оценки (4 или 5 звезд) требуется хотя бы одна " -"успешная запись о печати данным профилем печати." +msgstr "Для выставления положительной оценки (4 или 5 звезд) требуется хотя бы одна успешная запись о печати данным профилем печати." msgid "Status" msgstr "Статус" @@ -5427,11 +5103,8 @@ msgstr "Слои" msgid "Range" msgstr "Диапазон" -msgid "" -"The application cannot run normally because OpenGL version is lower than " -"2.0.\n" -msgstr "" -"Приложение не может работать нормально, так как версия OpenGL ниже 2.0.\n" +msgid "The application cannot run normally because OpenGL version is lower than 2.0.\n" +msgstr "Приложение не может работать нормально, так как версия OpenGL ниже 2.0.\n" msgid "Please upgrade your graphics card driver." msgstr "Пожалуйста, обновите драйвер вашей видеокарты." @@ -5467,12 +5140,8 @@ msgstr "Чувствительность" msgid "Enable detection of build plate position" msgstr "Определение положения печатной пластины" -msgid "" -"The localization tag of build plate is detected, and printing is paused if " -"the tag is not in predefined range." -msgstr "" -"Функция обнаружения метки (QR-кода) печатной пластины. Печать " -"приостанавливается, если метка находится не в том месте." +msgid "The localization tag of build plate is detected, and printing is paused if the tag is not in predefined range." +msgstr "Функция обнаружения метки (QR-кода) печатной пластины. Печать приостанавливается, если метка находится не в том месте." msgid "First Layer Inspection" msgstr "Проверка первого слоя" @@ -5577,8 +5246,7 @@ msgstr "Выбор пластиковой нити" msgid "Search plate, object and part." msgstr "Поиск печатной пластины, модели или части модели." -msgid "" -"No AMS filaments. Please select a printer in 'Device' page to load AMS info." +msgid "No AMS filaments. Please select a printer in 'Device' page to load AMS info." msgstr "" "АСПП недоступна. Пожалуйста, выберите принтер \n" "на странице «Принтер», чтобы загрузить информацию о АСПП." @@ -5586,19 +5254,11 @@ msgstr "" msgid "Sync filaments with AMS" msgstr "Синхронизация прутка с АСПП" -msgid "" -"Sync filaments with AMS will drop all current selected filament presets and " -"colors. Do you want to continue?" -msgstr "" -"При синхронизации пластиковых нитей с АСПП все текущие выбранные профили " -"прутков и цвета будут сброшены. Продолжить?" +msgid "Sync filaments with AMS will drop all current selected filament presets and colors. Do you want to continue?" +msgstr "При синхронизации пластиковых нитей с АСПП все текущие выбранные профили прутков и цвета будут сброшены. Продолжить?" -msgid "" -"Already did a synchronization, do you want to sync only changes or resync " -"all?" -msgstr "" -"Синхронизация уже выполнена. Хотите синхронизировать только изменения или " -"заново синхронизировать всё?" +msgid "Already did a synchronization, do you want to sync only changes or resync all?" +msgstr "Синхронизация уже выполнена. Хотите синхронизировать только изменения или заново синхронизировать всё?" msgid "Sync" msgstr "Только изменения" @@ -5607,29 +5267,21 @@ msgid "Resync" msgstr "Всё" msgid "There are no compatible filaments, and sync is not performed." -msgstr "" -"Синхронизация не выполнена, ввиду отсутствия совместимых пластиковых нитей." +msgstr "Синхронизация не выполнена, ввиду отсутствия совместимых пластиковых нитей." msgid "" -"There are some unknown filaments mapped to generic preset. Please update " -"Orca Slicer or restart Orca Slicer to check if there is an update to system " -"presets." +"There are some unknown filaments mapped to generic preset. Please update Orca Slicer or restart Orca Slicer to check if there is an update to system presets." msgstr "" -"Имеются несколько неизвестных материалов, сопоставленных с общим профилем. " -"Обновите или перезапустите Orca Slicer, чтобы проверить наличие обновлений " -"системных профилей." +"Имеются несколько неизвестных материалов, сопоставленных с общим профилем. Обновите или перезапустите Orca Slicer, чтобы проверить наличие обновлений системных " +"профилей." #, boost-format msgid "Do you want to save changes to \"%1%\"?" msgstr "Вы хотите сохранить изменения в \"%1%\"?" #, c-format, boost-format -msgid "" -"Successfully unmounted. The device %s(%s) can now be safely removed from the " -"computer." -msgstr "" -"Размонтирование прошло успешно. Теперь устройство %s(%s) может быть " -"безопасно извлечено из компьютера." +msgid "Successfully unmounted. The device %s(%s) can now be safely removed from the computer." +msgstr "Размонтирование прошло успешно. Теперь устройство %s(%s) может быть безопасно извлечено из компьютера." #, c-format, boost-format msgid "Ejecting of device %s(%s) has failed." @@ -5642,29 +5294,21 @@ msgid "Restore" msgstr "Восстановить" msgid "" -"The current hot bed temperature is relatively high. The nozzle may be " -"clogged when printing this filament in a closed enclosure. Please open the " -"front door and/or remove the upper glass." +"The current hot bed temperature is relatively high. The nozzle may be clogged when printing this filament in a closed enclosure. Please open the front door and/" +"or remove the upper glass." msgstr "" -"Текущая температура стола довольно высока. При печати этим материалом в " -"закрытом корпусе возможно засорение сопла. Откройте переднюю дверцу и/или " -"верхнюю крышку принтера." +"Текущая температура стола довольно высока. При печати этим материалом в закрытом корпусе возможно засорение сопла. Откройте переднюю дверцу и/или верхнюю крышку " +"принтера." msgid "" -"The nozzle hardness required by the filament is higher than the default " -"nozzle hardness of the printer. Please replace the hardened nozzle or " -"filament, otherwise, the nozzle will be attrited or damaged." +"The nozzle hardness required by the filament is higher than the default nozzle hardness of the printer. Please replace the hardened nozzle or filament, " +"otherwise, the nozzle will be attrited or damaged." msgstr "" -"Твердость сопла, установленного по умолчанию, не достаточна для печати " -"данной пластиковой нитью. Замените сопло на закаленное или смените " -"пластиковую нить. В противном случае сопло будет изношено или повреждено." +"Твердость сопла, установленного по умолчанию, не достаточна для печати данной пластиковой нитью. Замените сопло на закаленное или смените пластиковую нить. В " +"противном случае сопло будет изношено или повреждено." -msgid "" -"Enabling traditional timelapse photography may cause surface imperfections. " -"It is recommended to change to smooth mode." -msgstr "" -"Включение обычного режима таймлапса может привести к появлению дефектов " -"поверхности, поэтому рекомендуется изменить режим на плавный." +msgid "Enabling traditional timelapse photography may cause surface imperfections. It is recommended to change to smooth mode." +msgstr "Включение обычного режима таймлапса может привести к появлению дефектов поверхности, поэтому рекомендуется изменить режим на плавный." msgid "Expand sidebar" msgstr "Развернуть боковую панель" @@ -5677,16 +5321,13 @@ msgid "Loading file: %s" msgstr "Загрузка файла: %s" msgid "The 3mf is not supported by OrcaSlicer, load geometry data only." -msgstr "" -"Этот 3mf создан не в OrcaSlicer, поэтому загрузятся только данные геометрии." +msgstr "Этот 3mf создан не в OrcaSlicer, поэтому загрузятся только данные геометрии." msgid "Load 3mf" msgstr "Загрузка 3mf" #, c-format, boost-format -msgid "" -"The 3mf's version %s is newer than %s's version %s, Found following keys " -"unrecognized:" +msgid "The 3mf's version %s is newer than %s's version %s, Found following keys unrecognized:" msgstr "" "Версия этого формата 3mf (%s) новее текущей версии %s (%s).\n" "Обнаружены следующие нераспознанные ключи:" @@ -5698,9 +5339,7 @@ msgid "Newer 3mf version" msgstr "Новая версия 3mf" #, c-format, boost-format -msgid "" -"The 3mf's version %s is newer than %s's version %s, Suggest to upgrade your " -"software." +msgid "The 3mf's version %s is newer than %s's version %s, Suggest to upgrade your software." msgstr "" "Версия этого формата 3mf (%s) новее текущей версии %s (%s).\n" "Рекомендуется обновить программу." @@ -5712,31 +5351,19 @@ msgid "Please correct them in the param tabs" msgstr "Пожалуйста, исправьте их на вкладках параметров" msgid "The 3mf has following modified G-codes in filament or printer presets:" -msgstr "" -"В профиле прутка или принтера этого 3mf файла содержится следующий " -"модифицированный G-код:" +msgstr "В профиле прутка или принтера этого 3mf файла содержится следующий модифицированный G-код:" -msgid "" -"Please confirm that these modified G-codes are safe to prevent any damage to " -"the machine!" -msgstr "" -"Пожалуйста, подтвердите, что этот модифицированный G-код безопасен во " -"избежание повреждения принтера!" +msgid "Please confirm that these modified G-codes are safe to prevent any damage to the machine!" +msgstr "Пожалуйста, подтвердите, что этот модифицированный G-код безопасен во избежание повреждения принтера!" msgid "Modified G-codes" msgstr "Модифицированный G-код" msgid "The 3mf has following customized filament or printer presets:" -msgstr "" -"В этом 3mf файле содержаться следующие пользовательские профили прутка или " -"принтера:" +msgstr "В этом 3mf файле содержаться следующие пользовательские профили прутка или принтера:" -msgid "" -"Please confirm that the G-codes within these presets are safe to prevent any " -"damage to the machine!" -msgstr "" -"Во избежании повреждения принтера убедитесь, что G-код в этих профилях " -"безопасен!" +msgid "Please confirm that the G-codes within these presets are safe to prevent any damage to the machine!" +msgstr "Во избежании повреждения принтера убедитесь, что G-код в этих профилях безопасен!" msgid "Customized Preset" msgstr "Пользовательский профиль" @@ -5749,8 +5376,7 @@ msgstr "В названии могут присутствовать ненужн #, boost-format msgid "Failed loading file \"%1%\". An invalid configuration was found." -msgstr "" -"Не удалось загрузить файл \"%1%\". Обнаружена недопустимая конфигурация." +msgstr "Не удалось загрузить файл \"%1%\". Обнаружена недопустимая конфигурация." msgid "Objects with zero volume removed" msgstr "Модели с нулевым объёмом удалены" @@ -5783,8 +5409,7 @@ msgid "Multi-part object detected" msgstr "Обнаружена модель, состоящая из нескольких частей" msgid "Load these files as a single object with multiple parts?\n" -msgstr "" -"Загрузить эти файлы как единую модель состоящую из нескольких частей?\n" +msgstr "Загрузить эти файлы как единую модель состоящую из нескольких частей?\n" msgid "Object with multiple parts was detected" msgstr "Обнаружена модель, состоящая из нескольких частей" @@ -5792,9 +5417,7 @@ msgstr "Обнаружена модель, состоящая из нескол msgid "The file does not contain any geometry data." msgstr "Файл не содержит никаких геометрических данных." -msgid "" -"Your object appears to be too large, Do you want to scale it down to fit the " -"heat bed automatically?" +msgid "Your object appears to be too large, Do you want to scale it down to fit the heat bed automatically?" msgstr "" "Похоже, ваша модель слишком большая. \n" "Хотите автоматически уменьшить её масштаб, \n" @@ -5899,8 +5522,7 @@ msgstr "Нарезка стола %d" msgid "Please resolve the slicing errors and publish again." msgstr "Пожалуйста, устраните ошибки нарезки и попробуйте опубликовать снова." -msgid "" -"Network Plug-in is not detected. Network related features are unavailable." +msgid "Network Plug-in is not detected. Network related features are unavailable." msgstr "Сетевой плагин не обнаружен. Функции, связанные с сетью, недоступны." msgid "" @@ -5908,8 +5530,7 @@ msgid "" "The loaded file contains gcode only, Can not enter the Prepare page" msgstr "" "Режим только предпросмотра:\n" -"Загруженный файл содержит только G-код, поэтому переход на страницу " -"«Подготовка» невозможен." +"Загруженный файл содержит только G-код, поэтому переход на страницу «Подготовка» невозможен." msgid "You can keep the modified presets to the new project or discard them" msgstr "Изменённые профили можно сохранить в новом проекте или отказаться." @@ -5922,12 +5543,10 @@ msgstr "Загрузить проект" msgid "" "Failed to save the project.\n" -"Please check whether the folder exists online or if other programs open the " -"project file." +"Please check whether the folder exists online or if other programs open the project file." msgstr "" "Не удалось сохранить проект.\n" -"Убедитесь, что папка существует и что файл проекта не открыт в другой " -"программе." +"Убедитесь, что папка существует и что файл проекта не открыт в другой программе." msgid "Save project" msgstr "Сохранение проекта" @@ -5945,12 +5564,8 @@ msgstr "скачивание проекта..." msgid "Project downloaded %d%%" msgstr "Проект загружен %d%%" -msgid "" -"Importing to Orca Slicer failed. Please download the file and manually " -"import it." -msgstr "" -"Не удалось импортировать в Orca Slicer. Загрузите файл и импортируйте его " -"вручную." +msgid "Importing to Orca Slicer failed. Please download the file and manually import it." +msgstr "Не удалось импортировать в Orca Slicer. Загрузите файл и импортируйте его вручную." msgid "Import SLA archive" msgstr "Импорт SLA архива" @@ -6024,27 +5639,18 @@ msgid "Save Sliced file as:" msgstr "Сохранить нарезанный файл как:" #, c-format, boost-format -msgid "" -"The file %s has been sent to the printer's storage space and can be viewed " -"on the printer." +msgid "The file %s has been sent to the printer's storage space and can be viewed on the printer." msgstr "Файл %s отправлен в память принтера и может быть просмотрен на нём." -msgid "" -"Unable to perform boolean operation on model meshes. Only positive parts " -"will be exported." -msgstr "" -"Невозможно выполнить булевы операции над сетками модели. Будут " -"экспортированы только положительные части." +msgid "Unable to perform boolean operation on model meshes. Only positive parts will be exported." +msgstr "Невозможно выполнить булевы операции над сетками модели. Будут экспортированы только положительные части." msgid "" -"Are you sure you want to store original SVGs with their local paths into the " -"3MF file?\n" +"Are you sure you want to store original SVGs with their local paths into the 3MF file?\n" "If you hit 'NO', all SVGs in the project will not be editable any more." msgstr "" -"Вы уверены, что хотите сохранить исходные SVG файлы с их локальными путями в " -"3MF файле?\n" -"Если нажмете «НЕТ», все SVG файлы в проекте больше не будут доступны для " -"редактирования." +"Вы уверены, что хотите сохранить исходные SVG файлы с их локальными путями в 3MF файле?\n" +"Если нажмете «НЕТ», все SVG файлы в проекте больше не будут доступны для редактирования." msgid "Private protection" msgstr "Частная охрана" @@ -6060,8 +5666,7 @@ msgid "" "Suggest to use auto-arrange to avoid collisions when printing." msgstr "" "Печать по очереди: \n" -"Рекомендуется использовать автоматическую расстановку, чтобы избежать " -"столкновений при печати." +"Рекомендуется использовать автоматическую расстановку, чтобы избежать столкновений при печати." msgid "Send G-code" msgstr "Отправить G-код" @@ -6122,23 +5727,16 @@ msgstr "Треугольников: %1%\n" msgid "Tips:" msgstr "Подсказки:" -msgid "" -"\"Fix Model\" feature is currently only on Windows. Please repair the model " -"on Orca Slicer(windows) or CAD softwares." +msgid "\"Fix Model\" feature is currently only on Windows. Please repair the model on Orca Slicer(windows) or CAD softwares." msgstr "" -"Функция «Починить модель» в настоящее время доступна только в Windows. " -"Пожалуйста, почините модель с помощью Bambu Studio (Windows) или в другой " -"CAD программе." +"Функция «Починить модель» в настоящее время доступна только в Windows. Пожалуйста, почините модель с помощью Bambu Studio (Windows) или в другой CAD программе." #, c-format, boost-format msgid "" -"Plate% d: %s is not suggested to be used to print filament %s(%s). If you " -"still want to do this printing, please set this filament's bed temperature " -"to non zero." +"Plate% d: %s is not suggested to be used to print filament %s(%s). If you still want to do this printing, please set this filament's bed temperature to non zero." msgstr "" -"Не рекомендуется использовать печатную пластину% d (%s) для печати прутком " -"%s (%s). Если вы всё же хотите сделать это, то установите температуру стола " -"для этого прутка на ненулевое значение." +"Не рекомендуется использовать печатную пластину% d (%s) для печати прутком %s (%s). Если вы всё же хотите сделать это, то установите температуру стола для этого " +"прутка на ненулевое значение." msgid "Switching the language requires application restart.\n" msgstr "Для смены языка требуется перезапуск приложения.\n" @@ -6225,20 +5823,14 @@ msgstr "Задание страницы, открываемой при запу msgid "Zoom to mouse position" msgstr "Приближать к положению курсор" -msgid "" -"Zoom in towards the mouse pointer's position in the 3D view, rather than the " -"2D window center." -msgstr "" -"Увеличивать масштаб по направлению к курсору в 3D-виде, а не к центру 2D-" -"окна." +msgid "Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center." +msgstr "Увеличивать масштаб по направлению к курсору в 3D-виде, а не к центру 2D-окна." msgid "Use free camera" msgstr "Использовать свободную камеру" msgid "If enabled, use free camera. If not enabled, use constrained camera." -msgstr "" -"Если включено, используется свободное вращение камеры. Если выключено, " -"используется вращение камера с ограничениями." +msgstr "Если включено, используется свободное вращение камеры. Если выключено, используется вращение камера с ограничениями." msgid "Show splash screen" msgstr "Показывать заставку при запуске программы" @@ -6250,17 +5842,13 @@ msgid "Show \"Tip of the day\" notification after start" msgstr "Показывать уведомление с полезным советом при запуске приложения" msgid "If enabled, useful hints are displayed at startup." -msgstr "" -"Если включено, будут показываться уведомления с полезном советом при запуске " -"приложения." +msgstr "Если включено, будут показываться уведомления с полезном советом при запуске приложения." msgid "Flushing volumes: Auto-calculate everytime the color changed." msgstr "Объём очистки: автопересчёт при каждом изменении цвета." msgid "If enabled, auto-calculate everytime the color changed." -msgstr "" -"Если включено, выполняется автоматический перерасчет объёма очистки при " -"каждом изменении цвета." +msgstr "Если включено, выполняется автоматический перерасчет объёма очистки при каждом изменении цвета." msgid "Network" msgstr "Сеть" @@ -6287,32 +5875,25 @@ msgid "Associate .3mf files to OrcaSlicer" msgstr "Ассоциировать файлы .3mf с OrcaSlicer" msgid "If enabled, sets OrcaSlicer as default application to open .3mf files" -msgstr "" -"Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для " -"открытия .3mf файлов." +msgstr "Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для открытия .3mf файлов." msgid "Associate .stl files to OrcaSlicer" msgstr "Ассоциировать файлы .stl с OrcaSlicer" msgid "If enabled, sets OrcaSlicer as default application to open .stl files" -msgstr "" -"Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для " -"открытия .stl файлов." +msgstr "Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для открытия .stl файлов." msgid "Associate .step/.stp files to OrcaSlicer" msgstr "Ассоциировать файлы .step/.stp с OrcaSlicer" msgid "If enabled, sets OrcaSlicer as default application to open .step files" -msgstr "" -"Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для " -"открытия .step файлов." +msgstr "Если включено, назначает OrcaSlicer в качестве приложения по умолчанию для открытия .step файлов." msgid "Maximum recent projects" msgstr "Максимальное количество недавних проектов" msgid "Maximum count of recent projects" -msgstr "" -"Максимальное количество проектов, отображаемое в списке недавних проектов." +msgstr "Максимальное количество проектов, отображаемое в списке недавних проектов." msgid "Clear my choice on the unsaved projects." msgstr "Очистить мой выбор от несохранённых проектов." @@ -6323,11 +5904,8 @@ msgstr "Отключить предупреждения при загрузке msgid "Auto-Backup" msgstr "Автосоздание резервной копии" -msgid "" -"Backup your project periodically for restoring from the occasional crash." -msgstr "" -"Периодическое создание резервной копии проекта для восстановления после " -"непредвиденного сбоя программы." +msgid "Backup your project periodically for restoring from the occasional crash." +msgstr "Периодическое создание резервной копии проекта для восстановления после непредвиденного сбоя программы." msgid "every" msgstr "каждые" @@ -6519,9 +6097,7 @@ msgid "Log Out" msgstr "Выход" msgid "Slice all plate to obtain time and filament estimation" -msgstr "" -"Нарезка всех столов для получения примерного времени печати и расчёта " -"необходимого количества материала." +msgstr "Нарезка всех столов для получения примерного времени печати и расчёта необходимого количества материала." msgid "Packing project data into 3mf file" msgstr "Упаковка данных проекта в файл формата 3mf" @@ -6533,9 +6109,7 @@ msgid "Jump to model publish web page" msgstr "Перейти на веб-страницу публикации модели" msgid "Note: The preparation may takes several minutes. Please be patiant." -msgstr "" -"Примечание: подготовка может занять несколько минут. Пожалуйста, наберитесь " -"терпения." +msgstr "Примечание: подготовка может занять несколько минут. Пожалуйста, наберитесь терпения." msgid "Publish" msgstr "Опубликовать" @@ -6586,8 +6160,7 @@ msgid "Preset \"%1%\" already exists and is incompatible with current printer." msgstr "Профиль \"%1%\" уже существует и несовместим с текущим принтером." msgid "Please note that saving action will replace this preset" -msgstr "" -"Обратите внимание, что при сохранении произойдёт замена текущего профиля." +msgstr "Обратите внимание, что при сохранении произойдёт замена текущего профиля." msgid "The name is not allowed to be empty." msgstr "Имя не может быть пустым." @@ -6705,8 +6278,7 @@ msgid "Error code" msgstr "Код ошибки" msgid "Printer local connection failed, please try again." -msgstr "" -"Не удалось установить локальное соединение с принтером, попробуйте ещё раз." +msgstr "Не удалось установить локальное соединение с принтером, попробуйте ещё раз." msgid "No login account, only printers in LAN mode are displayed" msgstr "" @@ -6723,70 +6295,37 @@ msgid "Synchronizing device information time out" msgstr "Время синхронизации информации об устройстве истекло" msgid "Cannot send the print job when the printer is updating firmware" -msgstr "" -"Невозможно отправить задание на печать, при обновлении прошивки принтера." +msgstr "Невозможно отправить задание на печать, при обновлении прошивки принтера." -msgid "" -"The printer is executing instructions. Please restart printing after it ends" -msgstr "" -"Принтер выполняет инструкции. Пожалуйста, перезапустите печать после их " -"завершения." +msgid "The printer is executing instructions. Please restart printing after it ends" +msgstr "Принтер выполняет инструкции. Пожалуйста, перезапустите печать после их завершения." msgid "The printer is busy on other print job" msgstr "Принтер занят другим заданием" #, c-format, boost-format -msgid "" -"Filament %s exceeds the number of AMS slots. Please update the printer " -"firmware to support AMS slot assignment." +msgid "Filament %s exceeds the number of AMS slots. Please update the printer firmware to support AMS slot assignment." msgstr "" -"Количество пластиковых нитей - %s, что превышает количество слотов АСПП. " -"Обновите прошивку принтера, чтобы получить поддержку функции назначения " -"слотов АСПП." +"Количество пластиковых нитей - %s, что превышает количество слотов АСПП. Обновите прошивку принтера, чтобы получить поддержку функции назначения слотов АСПП." -msgid "" -"Filament exceeds the number of AMS slots. Please update the printer firmware " -"to support AMS slot assignment." -msgstr "" -"Количество пластиковых нитей превышает количество слотов АСПП. Обновите " -"прошивку принтера, чтобы получить поддержку функции назначения слотов АСПП." +msgid "Filament exceeds the number of AMS slots. Please update the printer firmware to support AMS slot assignment." +msgstr "Количество пластиковых нитей превышает количество слотов АСПП. Обновите прошивку принтера, чтобы получить поддержку функции назначения слотов АСПП." -msgid "" -"Filaments to AMS slots mappings have been established. You can click a " -"filament above to change its mapping AMS slot" -msgstr "" -"Соответствия между материалами и слотами АСПП были установлены. Вы можете " -"нажать на пластиковую нить выше, чтобы вручную задать для неё нужный слот " -"АСПП." +msgid "Filaments to AMS slots mappings have been established. You can click a filament above to change its mapping AMS slot" +msgstr "Соответствия между материалами и слотами АСПП были установлены. Вы можете нажать на пластиковую нить выше, чтобы вручную задать для неё нужный слот АСПП." -msgid "" -"Please click each filament above to specify its mapping AMS slot before " -"sending the print job" -msgstr "" -"Перед отправкой задания на печать, нажмите на каждую пластиковую нить, чтобы " -"вручную задать для неё нужный слот АСПП." +msgid "Please click each filament above to specify its mapping AMS slot before sending the print job" +msgstr "Перед отправкой задания на печать, нажмите на каждую пластиковую нить, чтобы вручную задать для неё нужный слот АСПП." #, c-format, boost-format -msgid "" -"Filament %s does not match the filament in AMS slot %s. Please update the " -"printer firmware to support AMS slot assignment." -msgstr "" -"Материал %s не соответствует материалу в слоте %s АСПП. Обновите прошивку " -"принтера, чтобы получить поддержку функции назначения слотов АСПП." +msgid "Filament %s does not match the filament in AMS slot %s. Please update the printer firmware to support AMS slot assignment." +msgstr "Материал %s не соответствует материалу в слоте %s АСПП. Обновите прошивку принтера, чтобы получить поддержку функции назначения слотов АСПП." -msgid "" -"Filament does not match the filament in AMS slot. Please update the printer " -"firmware to support AMS slot assignment." -msgstr "" -"Материал не соответствует материалу в слоте АСПП. Обновите прошивку " -"принтера, чтобы получить поддержку функции назначения слотов АСПП." +msgid "Filament does not match the filament in AMS slot. Please update the printer firmware to support AMS slot assignment." +msgstr "Материал не соответствует материалу в слоте АСПП. Обновите прошивку принтера, чтобы получить поддержку функции назначения слотов АСПП." -msgid "" -"The printer firmware only supports sequential mapping of filament => AMS " -"slot." -msgstr "" -"Текущая прошивка принтера поддерживает только последовательное сопоставление " -"пластиковых нитей => слот АСПП." +msgid "The printer firmware only supports sequential mapping of filament => AMS slot." +msgstr "Текущая прошивка принтера поддерживает только последовательное сопоставление пластиковых нитей => слот АСПП." msgid "An SD card needs to be inserted before printing." msgstr "Перед печатью необходимо вставить SD-карту." @@ -6797,12 +6336,8 @@ msgstr "Выбранный принтер несовместим с выбран msgid "An SD card needs to be inserted to record timelapse." msgstr "Для записи таймлапсов необходимо вставить SD-карту." -msgid "" -"Cannot send the print job to a printer whose firmware is required to get " -"updated." -msgstr "" -"Невозможно отправить задание печати на принтер, прошивка которого нуждается " -"в обновлении." +msgid "Cannot send the print job to a printer whose firmware is required to get updated." +msgstr "Невозможно отправить задание печати на принтер, прошивка которого нуждается в обновлении." msgid "Cannot send the print job for empty plate" msgstr "Невозможно отправить задание на печать, так как стол пуст." @@ -6810,18 +6345,11 @@ msgstr "Невозможно отправить задание на печать msgid "This printer does not support printing all plates" msgstr "Данный принтер не поддерживает печать на всех типах печатных пластин." -msgid "" -"When enable spiral vase mode, machines with I3 structure will not generate " -"timelapse videos." -msgstr "" -"При включении режима «Спиральная ваза» принтеры с кинематикой I3 не будут " -"писать таймлапс." +msgid "When enable spiral vase mode, machines with I3 structure will not generate timelapse videos." +msgstr "При включении режима «Спиральная ваза» принтеры с кинематикой I3 не будут писать таймлапс." -msgid "" -"Timelapse is not supported because Print sequence is set to \"By object\"." -msgstr "" -"Таймлапс не поддерживается, поскольку для последовательности печати " -"установлено значение «Печать по очереди»." +msgid "Timelapse is not supported because Print sequence is set to \"By object\"." +msgstr "Таймлапс не поддерживается, поскольку для последовательности печати установлено значение «Печать по очереди»." msgid "Errors" msgstr "Ошибок" @@ -6830,21 +6358,14 @@ msgid "Please check the following:" msgstr "Пожалуйста, проверьте следующую информацию:" msgid "" -"The printer type selected when generating G-Code is not consistent with the " -"currently selected printer. It is recommended that you use the same printer " -"type for slicing." -msgstr "" -"Выбранный профиль принтера в настройках слайсера не совпадает с фактическим " -"принтером. Для нарезки рекомендуется использовать тот же профиль принтера." +"The printer type selected when generating G-Code is not consistent with the currently selected printer. It is recommended that you use the same printer type for " +"slicing." +msgstr "Выбранный профиль принтера в настройках слайсера не совпадает с фактическим принтером. Для нарезки рекомендуется использовать тот же профиль принтера." msgid "" -"There are some unknown filaments in the AMS mappings. Please check whether " -"they are the required filaments. If they are okay, press \"Confirm\" to " -"start printing." +"There are some unknown filaments in the AMS mappings. Please check whether they are the required filaments. If they are okay, press \"Confirm\" to start printing." msgstr "" -"В АСПП установлены неизвестные пластиковые нити. Убедитесь, что стоят именно " -"те, что вам нужны. Если всё в порядке, нажмите «Подтвердить», чтобы начать " -"печать." +"В АСПП установлены неизвестные пластиковые нити. Убедитесь, что стоят именно те, что вам нужны. Если всё в порядке, нажмите «Подтвердить», чтобы начать печать." #, c-format, boost-format msgid "nozzle in preset: %s %s" @@ -6854,19 +6375,14 @@ msgstr "сопло в профиле: %s %s" msgid "nozzle memorized: %.1f %s" msgstr "сопло сохранённое: %.1f %s" -msgid "" -"Your nozzle diameter in preset is not consistent with memorized nozzle " -"diameter. Did you change your nozzle lately?" -msgstr "" -"Диаметр сопла в профиле не соответствует сохранённому диаметру сопла. Вы " -"недавно сменили сопло?" +msgid "Your nozzle diameter in preset is not consistent with memorized nozzle diameter. Did you change your nozzle lately?" +msgstr "Диаметр сопла в профиле не соответствует сохранённому диаметру сопла. Вы недавно сменили сопло?" #, c-format, boost-format msgid "*Printing %s material with %s may cause nozzle damage" msgstr "*Печать %s материалом %s может привести к повреждению сопла." -msgid "" -"Please click the confirm button if you still want to proceed with printing." +msgid "Please click the confirm button if you still want to proceed with printing." msgstr "Нажмите кнопку подтверждения, если всё ещё хотите продолжить печать." msgid "Hardened Steel" @@ -6875,10 +6391,8 @@ msgstr "Закаленная сталь" msgid "Stainless Steel" msgstr "Нержавеющая сталь" -msgid "" -"Connecting to the printer. Unable to cancel during the connection process." -msgstr "" -"Подключение к принтеру. Невозможно отменить во время процесса подключения." +msgid "Connecting to the printer. Unable to cancel during the connection process." +msgstr "Подключение к принтеру. Невозможно отменить во время процесса подключения." msgid "Preparing print job" msgstr "Подготовка задания на печать" @@ -6889,12 +6403,8 @@ msgstr "Неправильные данные файла печати. Пожа msgid "The name length exceeds the limit." msgstr "Длина имени превышает установленное ограничение." -msgid "" -"Caution to use! Flow calibration on Textured PEI Plate may fail due to the " -"scattered surface." -msgstr "" -"Внимание! Калибровка потока на текстурированной пластине с PEI покрытием " -"может быть неудачной из-за шероховатой поверхности." +msgid "Caution to use! Flow calibration on Textured PEI Plate may fail due to the scattered surface." +msgstr "Внимание! Калибровка потока на текстурированной пластине с PEI покрытием может быть неудачной из-за шероховатой поверхности." msgid "Automatic flow calibration using Micro Lidar" msgstr "Автокалибровка потока с помощью микролидара" @@ -6966,18 +6476,13 @@ msgid "Terms and Conditions" msgstr "Условия использования" msgid "" -"Thank you for purchasing a Bambu Lab device.Before using your Bambu Lab " -"device, please read the termsand conditions.By clicking to agree to use your " -"Bambu Lab device, you agree to abide by the Privacy Policyand Terms of " -"Use(collectively, the \"Terms\"). If you do not comply with or agree to the " -"Bambu Lab Privacy Policy, please do not use Bambu Lab equipment and services." +"Thank you for purchasing a Bambu Lab device.Before using your Bambu Lab device, please read the termsand conditions.By clicking to agree to use your Bambu Lab " +"device, you agree to abide by the Privacy Policyand Terms of Use(collectively, the \"Terms\"). If you do not comply with or agree to the Bambu Lab Privacy " +"Policy, please do not use Bambu Lab equipment and services." msgstr "" -"Перед использованием устройства Bambu Lab ознакомьтесь с правилами и " -"условиями. Нажимая на кнопку \"Согласие на использование устройства Bambu " -"Lab\", вы соглашаетесь соблюдать Политику конфиденциальности и Условия " -"использования (далее - \"Условия\"). Если вы не соблюдаете или не согласны с " -"Политикой конфиденциальности Bambu Lab, пожалуйста, не пользуйтесь " -"оборудованием и услугами Bambu Lab." +"Перед использованием устройства Bambu Lab ознакомьтесь с правилами и условиями. Нажимая на кнопку \"Согласие на использование устройства Bambu Lab\", вы " +"соглашаетесь соблюдать Политику конфиденциальности и Условия использования (далее - \"Условия\"). Если вы не соблюдаете или не согласны с Политикой " +"конфиденциальности Bambu Lab, пожалуйста, не пользуйтесь оборудованием и услугами Bambu Lab." msgid "and" msgstr "и" @@ -6993,30 +6498,18 @@ msgstr "Заявление о программе улучшения пользо #, c-format, boost-format msgid "" -"In the 3D Printing community, we learn from each other's successes and " -"failures to adjust our own slicing parameters and settings. %s follows the " -"same principle and uses machine learning to improve its performance from the " -"successes and failures of the vast number of prints by our users. We are " -"training %s to be smarter by feeding them the real-world data. If you are " -"willing, this service will access information from your error logs and usage " -"logs, which may include information described in Privacy Policy. We will " -"not collect any Personal Data by which an individual can be identified " -"directly or indirectly, including without limitation names, addresses, " -"payment information, or phone numbers. By enabling this service, you agree " -"to these terms and the statement about Privacy Policy." +"In the 3D Printing community, we learn from each other's successes and failures to adjust our own slicing parameters and settings. %s follows the same principle " +"and uses machine learning to improve its performance from the successes and failures of the vast number of prints by our users. We are training %s to be smarter " +"by feeding them the real-world data. If you are willing, this service will access information from your error logs and usage logs, which may include information " +"described in Privacy Policy. We will not collect any Personal Data by which an individual can be identified directly or indirectly, including without limitation " +"names, addresses, payment information, or phone numbers. By enabling this service, you agree to these terms and the statement about Privacy Policy." msgstr "" -"В сообществе 3D-печатников мы учимся на успехах и неудачах друг друга, чтобы " -"корректировать свои собственные параметры и настройки нарезки. Система %s " -"работает по тому же принципу и использует машинное обучение для улучшения " -"своей работы на основе успехов и неудач огромного количества отпечатков " -"наших пользователей. Мы обучаем %s быть умнее, предоставляя ему данные из " -"реального мира. По вашему желанию эта служба получит доступ к информации из " -"журналу ошибок и журналу использования, которая может включать информацию, " -"описанную в Политике конфиденциальности. Мы не будем собирать никаких " -"персональных данных, по которым можно прямо или косвенно идентифицировать " -"физическое лицо, включая, помимо прочего, имена, адреса, платежную " -"информацию или номера телефонов. Включая данную услугу, вы соглашаетесь с " -"данными условиями и заявлением о Политике конфиденциальности." +"В сообществе 3D-печатников мы учимся на успехах и неудачах друг друга, чтобы корректировать свои собственные параметры и настройки нарезки. Система %s работает " +"по тому же принципу и использует машинное обучение для улучшения своей работы на основе успехов и неудач огромного количества отпечатков наших пользователей. Мы " +"обучаем %s быть умнее, предоставляя ему данные из реального мира. По вашему желанию эта служба получит доступ к информации из журналу ошибок и журналу " +"использования, которая может включать информацию, описанную в Политике конфиденциальности. Мы не будем собирать никаких персональных данных, по которым можно " +"прямо или косвенно идентифицировать физическое лицо, включая, помимо прочего, имена, адреса, платежную информацию или номера телефонов. Включая данную услугу, вы " +"соглашаетесь с данными условиями и заявлением о Политике конфиденциальности." msgid "Statement on User Experience Improvement Plan" msgstr "Заявление о плане улучшения взаимодействия с пользователем" @@ -7034,8 +6527,7 @@ msgid "Please log in first." msgstr "Пожалуйста, сначала авторизуйтесь." msgid "There was a problem connecting to the printer. Please try again." -msgstr "" -"Возникла проблема с подключением к принтеру. Пожалуйста, попробуйте ещё раз." +msgstr "Возникла проблема с подключением к принтеру. Пожалуйста, попробуйте ещё раз." msgid "Failed to log out." msgstr "Не удалось выйти." @@ -7052,36 +6544,24 @@ msgid "Search in preset" msgstr "Поиск в профиле" msgid "Click to reset all settings to the last saved preset." -msgstr "" -"Нажмите, чтобы сбросить все настройки до последнего сохраненного профиля." +msgstr "Нажмите, чтобы сбросить все настройки до последнего сохраненного профиля." -msgid "" -"Prime tower is required for smooth timeplase. There may be flaws on the " -"model without prime tower. Are you sure you want to disable prime tower?" +msgid "Prime tower is required for smooth timeplase. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?" msgstr "" -"Для плавного таймлапса требуется черновая башня. На модели без использования " -"черновой башни могут быть дефекты. Вы уверены, что хотите отключить черновую " -"башню?" +"Для плавного таймлапса требуется черновая башня. На модели без использования черновой башни могут быть дефекты. Вы уверены, что хотите отключить черновую башню?" -msgid "" -"Prime tower is required for smooth timelapse. There may be flaws on the " -"model without prime tower. Do you want to enable prime tower?" -msgstr "" -"Для плавного таймлапса требуется черновая башня. На модели без использования " -"черновой башни могут быть дефекты. Вы хотите включить черновую башню?" +msgid "Prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Do you want to enable prime tower?" +msgstr "Для плавного таймлапса требуется черновая башня. На модели без использования черновой башни могут быть дефекты. Вы хотите включить черновую башню?" msgid "Still print by object?" msgstr "Продолжить печать по очереди?" msgid "" -"We have added an experimental style \"Tree Slim\" that features smaller " -"support volume but weaker strength.\n" +"We have added an experimental style \"Tree Slim\" that features smaller support volume but weaker strength.\n" "We recommend using it with: 0 interface layers, 0 top distance, 2 walls." msgstr "" -"Мы добавили экспериментальный стиль «Стройный (древ. поддержка)», который " -"отличается меньшим объёмом поддержки, а следовательно, и меньшей прочностью. " -"Мы рекомендуем использовать его со следующими параметрами: количество " -"связующих слоёв - 0, зазор поддержки сверху - 0, периметров - 2." +"Мы добавили экспериментальный стиль «Стройный (древ. поддержка)», который отличается меньшим объёмом поддержки, а следовательно, и меньшей прочностью. Мы " +"рекомендуем использовать его со следующими параметрами: количество связующих слоёв - 0, зазор поддержки сверху - 0, периметров - 2." msgid "" "Change these settings automatically? \n" @@ -7093,9 +6573,8 @@ msgstr "" "Нет - Не изменять эти настройки" msgid "" -"For \"Tree Strong\" and \"Tree Hybrid\" styles, we recommend the following " -"settings: at least 2 interface layers, at least 0.1mm top z distance or " -"using support materials on interface." +"For \"Tree Strong\" and \"Tree Hybrid\" styles, we recommend the following settings: at least 2 interface layers, at least 0.1mm top z distance or using support " +"materials on interface." msgstr "" "Для стилей «Крепкий (древ. поддержка)» и «Гибридный (древ. поддержка)» \n" "мы рекомендуем следующие параметры: \n" @@ -7104,10 +6583,8 @@ msgstr "" "или использование «материалов для поддержек» в качестве связующего слоя." msgid "" -"When using support material for the support interface, We recommend the " -"following settings:\n" -"0 top z distance, 0 interface spacing, concentric pattern and disable " -"independent support layer height" +"When using support material for the support interface, We recommend the following settings:\n" +"0 top z distance, 0 interface spacing, concentric pattern and disable independent support layer height" msgstr "" "При использовании «материалов для поддержек» в качестве связующего \n" "слоя поддержки, мы рекомендуем следующие параметры:\n" @@ -7117,13 +6594,11 @@ msgstr "" "отключение независимой высоты слоя поддержки." msgid "" -"Enabling this option will modify the model's shape. If your print requires " -"precise dimensions or is part of an assembly, it's important to double-check " -"whether this change in geometry impacts the functionality of your print." +"Enabling this option will modify the model's shape. If your print requires precise dimensions or is part of an assembly, it's important to double-check whether " +"this change in geometry impacts the functionality of your print." msgstr "" -"Включение этой опции приведёт к изменению формы модели. Если ваша печать " -"требует точных размеров или является частью сборки, важно перепроверить, не " -"повлияет ли изменение геометрии на функциональность напечатанного." +"Включение этой опции приведёт к изменению формы модели. Если ваша печать требует точных размеров или является частью сборки, важно перепроверить, не повлияет ли " +"изменение геометрии на функциональность напечатанного." msgid "Are you sure you want to enable this option?" msgstr "Вы уверены, что хотите включить эту опцию?" @@ -7135,13 +6610,10 @@ msgstr "" "Высота слоя слишком мала.\n" "Будет установлено значение min_layer_height\n" -msgid "" -"Layer height exceeds the limit in Printer Settings -> Extruder -> Layer " -"height limits ,this may cause printing quality issues." +msgid "Layer height exceeds the limit in Printer Settings -> Extruder -> Layer height limits ,this may cause printing quality issues." msgstr "" -"Высота слоя не может превышать ограничения установленные в настройках " -"принтера -> Экструдер -> Ограничение высоты слоя. Это может вызвать проблемы " -"с качеством печати." +"Высота слоя не может превышать ограничения установленные в настройках принтера -> Экструдер -> Ограничение высоты слоя. Это может вызвать проблемы с качеством " +"печати." msgid "Adjust to the set range automatically? \n" msgstr "Автоматически подстроиться под заданный в настройках диапазон?\n" @@ -7153,15 +6625,11 @@ msgid "Ignore" msgstr "Игнорировать" msgid "" -"When recording timelapse without toolhead, it is recommended to add a " -"\"Timelapse Wipe Tower\" \n" -"by right-click the empty position of build plate and choose \"Add " -"Primitive\"->\"Timelapse Wipe Tower\"." +"When recording timelapse without toolhead, it is recommended to add a \"Timelapse Wipe Tower\" \n" +"by right-click the empty position of build plate and choose \"Add Primitive\"->\"Timelapse Wipe Tower\"." msgstr "" -"При записи таймлапса без видимости головы рекомендуется добавить «Черновая " -"башня таймлапса». \n" -"Щёлкните правой кнопкой мыши на пустом месте стола и выберите «Добавить " -"примитив» -> «Черновая башня таймлапса»." +"При записи таймлапса без видимости головы рекомендуется добавить «Черновая башня таймлапса». \n" +"Щёлкните правой кнопкой мыши на пустом месте стола и выберите «Добавить примитив» -> «Черновая башня таймлапса»." msgid "Line width" msgstr "Ширина экструзии" @@ -7200,15 +6668,11 @@ msgid "Overhang speed" msgstr "Скорость печати нависаний" msgid "" -"This is the speed for various overhang degrees. Overhang degrees are " -"expressed as a percentage of line width. 0 speed means no slowing down for " -"the overhang degree range and wall speed is used" +"This is the speed for various overhang degrees. Overhang degrees are expressed as a percentage of line width. 0 speed means no slowing down for the overhang " +"degree range and wall speed is used" msgstr "" -"Скорость печати нависаний разной степени свеса. Размер этого свеса " -"выражается в процентах от ширины линии. Скорость 0 означает, что для данного " -"диапазона нависаний замедление отсутствует и используется скорость " -"периметра. Скорость для промежуточных значений рассчитывается с помощью " -"линейной интерполяции." +"Скорость печати нависаний разной степени свеса. Размер этого свеса выражается в процентах от ширины линии. Скорость 0 означает, что для данного диапазона " +"нависаний замедление отсутствует и используется скорость периметра. Скорость для промежуточных значений рассчитывается с помощью линейной интерполяции." msgid "Bridge" msgstr "Мосты" @@ -7255,24 +6719,19 @@ msgstr "Частые" #, c-format, boost-format msgid "" "Following line %s contains reserved keywords.\n" -"Please remove it, or will beat G-code visualization and printing time " -"estimation." +"Please remove it, or will beat G-code visualization and printing time estimation." msgid_plural "" "Following lines %s contain reserved keywords.\n" -"Please remove them, or will beat G-code visualization and printing time " -"estimation." +"Please remove them, or will beat G-code visualization and printing time estimation." msgstr[0] "" "Следующая строка %s содержит зарезервированные ключевые слова.\n" -"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка " -"времени печати." +"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка времени печати." msgstr[1] "" "Следующие строки %s содержат зарезервированные ключевые слова.\n" -"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка " -"времени печати." +"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка времени печати." msgstr[2] "" "Следующие строки %s содержат зарезервированные ключевые слова.\n" -"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка " -"времени печати." +"Пожалуйста, удалите их, иначе будет нарушена визуализация G-кода и оценка времени печати." msgid "Reserved keywords found" msgstr "Найдены зарезервированные ключевые слова" @@ -7290,9 +6749,7 @@ msgid "Recommended nozzle temperature" msgstr "Рекомендуемая температура сопла" msgid "Recommended nozzle temperature range of this filament. 0 means no set" -msgstr "" -"Рекомендуемый диапазон температуры сопла для данной пластиковой нити. 0 " -"значит не задано." +msgstr "Рекомендуемый диапазон температуры сопла для данной пластиковой нити. 0 значит не задано." msgid "Print chamber temperature" msgstr "Температура в камере" @@ -7309,46 +6766,31 @@ msgstr "Температура сопла при печати" msgid "Cool plate" msgstr "Не нагреваемая пластина" -msgid "" -"Bed temperature when cool plate is installed. Value 0 means the filament " -"does not support to print on the Cool Plate" -msgstr "" -"Температура не подогреваемого стола. 0 означает, что пластиковая нить не " -"поддерживает печать на этой печатной пластине." +msgid "Bed temperature when cool plate is installed. Value 0 means the filament does not support to print on the Cool Plate" +msgstr "Температура не подогреваемого стола. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "Engineering plate" msgstr "Инженерная пластина" -msgid "" -"Bed temperature when engineering plate is installed. Value 0 means the " -"filament does not support to print on the Engineering Plate" -msgstr "" -"Температура стола при установленной инженерной печатной пластине. 0 " -"означает, что пластиковая нить не поддерживает печать на этой печатной " -"пластине." +msgid "Bed temperature when engineering plate is installed. Value 0 means the filament does not support to print on the Engineering Plate" +msgstr "Температура стола при установленной инженерной печатной пластине. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "Smooth PEI Plate / High Temp Plate" msgstr "Гладкая PEI/высокотемпер. пластина" msgid "" -"Bed temperature when Smooth PEI Plate/High temperature plate is installed. " -"Value 0 means the filament does not support to print on the Smooth PEI Plate/" -"High Temp Plate" +"Bed temperature when Smooth PEI Plate/High temperature plate is installed. Value 0 means the filament does not support to print on the Smooth PEI Plate/High Temp " +"Plate" msgstr "" -"Температура стола при установленной гладкой PEI/высокотемпературный печатной " -"пластине. 0 означает, что пластиковая нить не поддерживает печать на этой " -"печатной пластине." +"Температура стола при установленной гладкой PEI/высокотемпературный печатной пластине. 0 означает, что пластиковая нить не поддерживает печать на этой печатной " +"пластине." msgid "Textured PEI Plate" msgstr "Текстурированная PEI пластина" -msgid "" -"Bed temperature when Textured PEI Plate is installed. Value 0 means the " -"filament does not support to print on the Textured PEI Plate" +msgid "Bed temperature when Textured PEI Plate is installed. Value 0 means the filament does not support to print on the Textured PEI Plate" msgstr "" -"Температура стола при установленной текстурированной пластите с PEI " -"покрытием. 0 означает, что пластиковая нить не поддерживает печать на этой " -"печатной пластине." +"Температура стола при установленной текстурированной пластите с PEI покрытием. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "Volumetric speed limitation" msgstr "Ограничение объёмной скорости" @@ -7366,26 +6808,18 @@ msgid "Min fan speed threshold" msgstr "Порог мин. скорости вентилятора" msgid "" -"Part cooling fan speed will start to run at min speed when the estimated " -"layer time is no longer than the layer time in setting. When layer time is " -"shorter than threshold, fan speed is interpolated between the minimum and " -"maximum fan speed according to layer printing time" +"Part cooling fan speed will start to run at min speed when the estimated layer time is no longer than the layer time in setting. When layer time is shorter than " +"threshold, fan speed is interpolated between the minimum and maximum fan speed according to layer printing time" msgstr "" -"Вентилятор для охлаждения моделей начнет работать с минимальной скоростью, " -"когда расчётное время печати слоя не превышает заданное время печати слоя. " -"Если время печати слоя меньше порогового значения, скорость вентилятора " -"интерполируется между минимальной и максимальной скоростью вентилятора в " -"зависимости от времени печати слоя." +"Вентилятор для охлаждения моделей начнет работать с минимальной скоростью, когда расчётное время печати слоя не превышает заданное время печати слоя. Если время " +"печати слоя меньше порогового значения, скорость вентилятора интерполируется между минимальной и максимальной скоростью вентилятора в зависимости от времени " +"печати слоя." msgid "Max fan speed threshold" msgstr "Порог макс. скорости вентилятора" -msgid "" -"Part cooling fan speed will be max when the estimated layer time is shorter " -"than the setting value" -msgstr "" -"Скорость вентилятора для охлаждения детали будет максимальной, если " -"расчётное время печати слоя меньше установленного значения." +msgid "Part cooling fan speed will be max when the estimated layer time is shorter than the setting value" +msgstr "Скорость вентилятора для охлаждения детали будет максимальной, если расчётное время печати слоя меньше установленного значения." msgid "Auxiliary part cooling fan" msgstr "Вспомогательный вентилятор для охлаждения моделей" @@ -7412,15 +6846,13 @@ msgid "Wipe tower parameters" msgstr "Параметры черновой башни" msgid "Toolchange parameters with single extruder MM printers" -msgstr "" -"Параметры смены инструмента в одноэкструдерных мультиматериальных принтерах" +msgstr "Параметры смены инструмента в одноэкструдерных мультиматериальных принтерах" msgid "Ramming settings" msgstr "Настройки рэмминга" msgid "Toolchange parameters with multi extruder MM printers" -msgstr "" -"Параметры смены инструмента в мультиэкструдерных мультиматериальных принтерах" +msgstr "Параметры смены инструмента в мультиэкструдерных мультиматериальных принтерах" msgid "Printable space" msgstr "Область печати" @@ -7522,9 +6954,7 @@ msgid "Detached" msgstr "Отсоединён" #, c-format, boost-format -msgid "" -"%d Filament Preset and %d Process Preset is attached to this printer. Those " -"presets would be deleted if the printer is deleted." +msgid "%d Filament Preset and %d Process Preset is attached to this printer. Those presets would be deleted if the printer is deleted." msgstr "" "К этому принтеру прикреплено: \n" "профилей прутка -%dшт. и профилей процесса печати - %dшт.\n" @@ -7553,12 +6983,10 @@ msgstr[2] "Следующие профили также будут удален msgid "" "Are you sure to delete the selected preset? \n" -"If the preset corresponds to a filament currently in use on your printer, " -"please reset the filament information for that slot." +"If the preset corresponds to a filament currently in use on your printer, please reset the filament information for that slot." msgstr "" "Вы уверены, что хотите удалить выбранный профиль? \n" -"Если этот профиль используется в данный момент в вашем принтере, пожалуйста, " -"сбросьте информацию о прутке для этого слота." +"Если этот профиль используется в данный момент в вашем принтере, пожалуйста, сбросьте информацию о прутке для этого слота." #, boost-format msgid "Are you sure to %1% the selected preset?" @@ -7643,34 +7071,24 @@ msgid "Preset \"%1%\" contains the following unsaved changes:" msgstr "Профиль \"%1%\" имеет следующие несохранённые изменения:" #, boost-format -msgid "" -"Preset \"%1%\" is not compatible with the new printer profile and it " -"contains the following unsaved changes:" -msgstr "" -"Профиль \"%1%\" несовместим с новым профилем принтера, и имеет следующие " -"несохранённые изменения:" +msgid "Preset \"%1%\" is not compatible with the new printer profile and it contains the following unsaved changes:" +msgstr "Профиль \"%1%\" несовместим с новым профилем принтера, и имеет следующие несохранённые изменения:" #, boost-format -msgid "" -"Preset \"%1%\" is not compatible with the new process profile and it " -"contains the following unsaved changes:" -msgstr "" -"Профиль \"%1%\" несовместим с новым профилем процесса, и имеет следующие " -"несохранённые изменения:" +msgid "Preset \"%1%\" is not compatible with the new process profile and it contains the following unsaved changes:" +msgstr "Профиль \"%1%\" несовместим с новым профилем процесса, и имеет следующие несохранённые изменения:" #, boost-format msgid "" "You have changed some settings of preset \"%1%\". \n" -"Would you like to keep these changed settings (new value) after switching " -"preset?" +"Would you like to keep these changed settings (new value) after switching preset?" msgstr "" "Вы изменили некоторые параметры профиля \"%1%\". \n" "Хотите сохранить эти изменения (новые значения)?" msgid "" "You have changed some preset settings. \n" -"Would you like to keep these changed settings (new value) after switching " -"preset?" +"Would you like to keep these changed settings (new value) after switching preset?" msgstr "" "Вы изменили некоторые параметры профиля.\n" "Хотите сохранить эти изменения (новые значения)?" @@ -7690,29 +7108,21 @@ msgstr "Показать все профили (включая несовмес msgid "Select presets to compare" msgstr "Выберите профили для сравнения" -msgid "" -"You can only transfer to current active profile because it has been modified." -msgstr "" -"Перенос в текущий активный профиль невозможен потому, что он был изменён." +msgid "You can only transfer to current active profile because it has been modified." +msgstr "Перенос в текущий активный профиль невозможен потому, что он был изменён." msgid "" "Transfer the selected options from left preset to the right.\n" -"Note: New modified presets will be selected in settings tabs after close " -"this dialog." +"Note: New modified presets will be selected in settings tabs after close this dialog." msgstr "" "Перенос выбранных параметров из левого профиля в правый.\n" -"Примечание: новые изменённые профили будут выбраны после закрытия этого " -"диалогового окна." +"Примечание: новые изменённые профили будут выбраны после закрытия этого диалогового окна." msgid "Transfer values from left to right" msgstr "Перенос значений слева направо" -msgid "" -"If enabled, this dialog can be used for transver selected values from left " -"to right preset." -msgstr "" -"Если включено, это диалоговое окно можно использовать для переноса выбранных " -"значений из левого профиля в правый." +msgid "If enabled, this dialog can be used for transver selected values from left to right preset." +msgstr "Если включено, это диалоговое окно можно использовать для переноса выбранных значений из левого профиля в правый." msgid "Add File" msgstr "Добавить файл" @@ -7795,27 +7205,18 @@ msgid "Ramming customization" msgstr "Настройки рэмминга" msgid "" -"Ramming denotes the rapid extrusion just before a tool change in a single-" -"extruder MM printer. Its purpose is to properly shape the end of the " -"unloaded filament so it does not prevent insertion of the new filament and " -"can itself be reinserted later. This phase is important and different " -"materials can require different extrusion speeds to get the good shape. For " -"this reason, the extrusion rates during ramming are adjustable.\n" +"Ramming denotes the rapid extrusion just before a tool change in a single-extruder MM printer. Its purpose is to properly shape the end of the unloaded filament " +"so it does not prevent insertion of the new filament and can itself be reinserted later. This phase is important and different materials can require different " +"extrusion speeds to get the good shape. For this reason, the extrusion rates during ramming are adjustable.\n" "\n" -"This is an expert-level setting, incorrect adjustment will likely lead to " -"jams, extruder wheel grinding into filament etc." +"This is an expert-level setting, incorrect adjustment will likely lead to jams, extruder wheel grinding into filament etc." msgstr "" -"Рэмминг (ramming, дословно утрамбовка) означает быстрое экструдирование " -"непосредственно перед сменой инструмента в одноэкструдерном " -"мультиматериальном принтере. Цель процесса состоит в том, чтобы правильно " -"сформировать конец выгружаемого прутка, чтобы он не препятствовал вставке " -"нового прутка или этого же прутка, вставленного позже. Эта фаза важна и " -"разные материалы могут потребовать разных скоростей экструзии, чтобы " -"получить хорошую форму. По этой причине скорость экструзии во время рэмминга " -"регулируется.\n" +"Рэмминг (ramming, дословно утрамбовка) означает быстрое экструдирование непосредственно перед сменой инструмента в одноэкструдерном мультиматериальном принтере. " +"Цель процесса состоит в том, чтобы правильно сформировать конец выгружаемого прутка, чтобы он не препятствовал вставке нового прутка или этого же прутка, " +"вставленного позже. Эта фаза важна и разные материалы могут потребовать разных скоростей экструзии, чтобы получить хорошую форму. По этой причине скорость " +"экструзии во время рэмминга регулируется.\n" "\n" -"Эта опция для опытных пользователей, неправильная настройка может привести к " -"замятию, протиранию прутка приводом экструдера и т.д." +"Эта опция для опытных пользователей, неправильная настройка может привести к замятию, протиранию прутка приводом экструдера и т.д." msgid "Total ramming time" msgstr "Общее время рэмминга" @@ -7841,12 +7242,8 @@ msgstr "Пересчитать" msgid "Flushing volumes for filament change" msgstr "Объёмы очистки при смене пластиковой нити" -msgid "" -"Orca would re-calculate your flushing volumes everytime the filaments color " -"changed. You could disable the auto-calculate in Orca Slicer > Preferences" -msgstr "" -"Программа будет пересчитывать объёмы очистки каждый раз при изменении цвета " -"пластиковых нитей. Это можно отключить в меню Orca Slicer > Параметры." +msgid "Orca would re-calculate your flushing volumes everytime the filaments color changed. You could disable the auto-calculate in Orca Slicer > Preferences" +msgstr "Программа будет пересчитывать объёмы очистки каждый раз при изменении цвета пластиковых нитей. Это можно отключить в меню Orca Slicer > Параметры." msgid "Flushing volume (mm³) for each filament pair." msgstr "" @@ -7889,8 +7286,7 @@ msgid "Login" msgstr "Войти" msgid "The configuration package is changed in previous Config Guide" -msgstr "" -"Пакет конфигурации был изменён при предыдущем запуске мастера настройки." +msgstr "Пакет конфигурации был изменён при предыдущем запуске мастера настройки." msgid "Configuration package changed" msgstr "Пакет конфигурации изменён" @@ -7946,13 +7342,9 @@ msgid "Shift+R" msgstr "Shift+R" msgid "" -"Auto orientates selected objects or all objects.If there are selected " -"objects, it just orientates the selected ones.Otherwise, it will orientates " -"all objects in the current disk." -msgstr "" -"Автоориентация выбранных или всех моделей. При выбранных моделях, " -"ориентируются только они, противном случае ориентируются все модели на " -"текущем столе." +"Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in " +"the current disk." +msgstr "Автоориентация выбранных или всех моделей. При выбранных моделях, ориентируются только они, противном случае ориентируются все модели на текущем столе." msgid "Shift+Tab" msgstr "Shift+Tab" @@ -8141,8 +7533,7 @@ msgid "Horizontal slider - Move active thumb Right" msgstr "Горизонтальный ползунок - Сдвинуть активный ползунок вправо" msgid "On/Off one layer mode of the vertical slider" -msgstr "" -"Включение/Отключение функции «Режим одного слоя» у вертикального ползунка" +msgstr "Включение/Отключение функции «Режим одного слоя» у вертикального ползунка" msgid "On/Off g-code window" msgstr "Показать/скрыть окно отображения G-кода" @@ -8163,10 +7554,8 @@ msgstr "Информация об обновлении версии %s:" msgid "Network plug-in update" msgstr "Обновление сетевого плагина" -msgid "" -"Click OK to update the Network plug-in when Orca Slicer launches next time." -msgstr "" -"Нажмите OK, чтобы обновить сетевой плагин при следующем запуске Orca Slicer." +msgid "Click OK to update the Network plug-in when Orca Slicer launches next time." +msgstr "Нажмите OK, чтобы обновить сетевой плагин при следующем запуске Orca Slicer." #, c-format, boost-format msgid "A new Network plug-in(%s) available, Do you want to install it?" @@ -8187,18 +7576,11 @@ msgstr "Подтвердить и обновить сопло" msgid "LAN Connection Failed (Sending print file)" msgstr "Сбой подключения к локальной сети (отправка файла на печать)" -msgid "" -"Step 1, please confirm Orca Slicer and your printer are in the same LAN." -msgstr "" -"Шаг 1. Пожалуйста, убедитесь, что Orca Slicer и ваш принтер находятся в " -"одной локальной сети." +msgid "Step 1, please confirm Orca Slicer and your printer are in the same LAN." +msgstr "Шаг 1. Пожалуйста, убедитесь, что Orca Slicer и ваш принтер находятся в одной локальной сети." -msgid "" -"Step 2, if the IP and Access Code below are different from the actual values " -"on your printer, please correct them." -msgstr "" -"Шаг 2. Если приведенный ниже IP-адрес и код доступа отличаются от " -"фактических значений на вашем принтере, пожалуйста, исправьте их." +msgid "Step 2, if the IP and Access Code below are different from the actual values on your printer, please correct them." +msgstr "Шаг 2. Если приведенный ниже IP-адрес и код доступа отличаются от фактических значений на вашем принтере, пожалуйста, исправьте их." msgid "IP" msgstr "IP" @@ -8210,8 +7592,7 @@ msgid "Where to find your printer's IP and Access Code?" msgstr "Где найти IP-адрес и код доступа к вашему принтеру?" msgid "Step 3: Ping the IP address to check for packet loss and latency." -msgstr "" -"Шаг 3. Пропингуйте IP-адрес, чтобы проверить потерю пакетов и задержку." +msgstr "Шаг 3. Пропингуйте IP-адрес, чтобы проверить потерю пакетов и задержку." msgid "Test" msgstr "Тест" @@ -8220,8 +7601,7 @@ msgid "IP and Access Code Verified! You may close the window" msgstr "IP-адрес и код доступа подтверждены! Вы можете закрыть окно." msgid "Connection failed, please double check IP and Access Code" -msgstr "" -"Не удалось подключиться, пожалуйста, перепроверьте IP-адрес и код доступа" +msgstr "Не удалось подключиться, пожалуйста, перепроверьте IP-адрес и код доступа" msgid "" "Connection failed! If your IP and Access Code is correct, \n" @@ -8263,30 +7643,21 @@ msgstr "Сбой при обновлении" msgid "Updating successful" msgstr "Обновление успешно выполнено" -msgid "" -"Are you sure you want to update? This will take about 10 minutes. Do not " -"turn off the power while the printer is updating." -msgstr "" -"Вы уверены, что хотите обновить? Это займёт около 10 минут. Не выключайте " -"питание во время обновления принтера." +msgid "Are you sure you want to update? This will take about 10 minutes. Do not turn off the power while the printer is updating." +msgstr "Вы уверены, что хотите обновить? Это займёт около 10 минут. Не выключайте питание во время обновления принтера." msgid "" -"An important update was detected and needs to be run before printing can " -"continue. Do you want to update now? You can also update later from 'Upgrade " -"firmware'." +"An important update was detected and needs to be run before printing can continue. Do you want to update now? You can also update later from 'Upgrade firmware'." msgstr "" -"Было обнаружено важное обновление, которое необходимо установить перед " -"продолжением печати. Хотите обновиться сейчас? Обновление можно выполнить и " -"позже, нажав «Обновить прошивку»." +"Было обнаружено важное обновление, которое необходимо установить перед продолжением печати. Хотите обновиться сейчас? Обновление можно выполнить и позже, нажав " +"«Обновить прошивку»." msgid "" -"The firmware version is abnormal. Repairing and updating are required before " -"printing. Do you want to update now? You can also update later on printer or " -"update next time starting the studio." +"The firmware version is abnormal. Repairing and updating are required before printing. Do you want to update now? You can also update later on printer or update " +"next time starting the studio." msgstr "" -"Ошибка в версии прошивки. Перед печатью её необходимо исправить и обновить. " -"Хотите обновить сейчас? Вы можете сделать это позже с принтера или при " -"следующем запуске программы." +"Ошибка в версии прошивки. Перед печатью её необходимо исправить и обновить. Хотите обновить сейчас? Вы можете сделать это позже с принтера или при следующем " +"запуске программы." msgid "Extension Board" msgstr "Плата расширения" @@ -8344,8 +7715,7 @@ msgid "Copying of file %1% to %2% failed: %3%" msgstr "Не удалось скопировать файл %1% в %2%: %3%" msgid "Need to check the unsaved changes before configuration updates." -msgstr "" -"Перед обновлением конфигурации необходимо проверить несохранённые изменения." +msgstr "Перед обновлением конфигурации необходимо проверить несохранённые изменения." msgid "Configuration package: " msgstr "Пакет конфигурации: " @@ -8356,12 +7726,8 @@ msgstr " обновлён до " msgid "Open G-code file:" msgstr "Выберите G-код файл:" -msgid "" -"One object has empty initial layer and can't be printed. Please Cut the " -"bottom or enable supports." -msgstr "" -"Одна модель имеет пустой начальный слой и не может быть напечатана. " -"Пожалуйста, обрежьте нижнюю часть или включите поддержки." +msgid "One object has empty initial layer and can't be printed. Please Cut the bottom or enable supports." +msgstr "Одна модель имеет пустой начальный слой и не может быть напечатана. Пожалуйста, обрежьте нижнюю часть или включите поддержки." #, boost-format msgid "Object can't be printed for empty layer between %1% and %2%." @@ -8371,12 +7737,8 @@ msgstr "Модель не может быть напечатан из-за пу msgid "Object: %1%" msgstr "Модель: %1%" -msgid "" -"Maybe parts of the object at these height are too thin, or the object has " -"faulty mesh" -msgstr "" -"Возможно, части модели на этой высоте слишком тонкие, или она имеет " -"дефектную сетку." +msgid "Maybe parts of the object at these height are too thin, or the object has faulty mesh" +msgstr "Возможно, части модели на этой высоте слишком тонкие, или она имеет дефектную сетку." msgid "No object can be printed. Maybe too small" msgstr "Печать моделей невозможна. Возможно, они слишком маленькие." @@ -8384,14 +7746,10 @@ msgstr "Печать моделей невозможна. Возможно, он msgid "" "Failed to generate gcode for invalid custom G-code.\n" "\n" -msgstr "" -"Не удалось сгенерировать G-код из-за недопустимого пользовательского G-" -"кода.\n" +msgstr "Не удалось сгенерировать G-код из-за недопустимого пользовательского G-кода.\n" msgid "Please check the custom G-code or use the default custom G-code." -msgstr "" -"Пожалуйста, проверьте пользовательский G-код или используйте " -"пользовательский G-код по умолчанию." +msgstr "Пожалуйста, проверьте пользовательский G-код или используйте пользовательский G-код по умолчанию." #, boost-format msgid "Generating G-code: layer %1%" @@ -8438,15 +7796,10 @@ msgstr "Множитель" #, boost-format msgid "Failed to calculate line width of %1%. Can not get value of \"%2%\" " -msgstr "" -"Не удалось вычислить ширину линии %1%. Не удается получить значение \"%2%\". " +msgstr "Не удалось вычислить ширину линии %1%. Не удается получить значение \"%2%\". " -msgid "" -"Invalid spacing supplied to Flow::with_spacing(), check your layer height " -"and extrusion width" -msgstr "" -"Для Flow::with_spacing () был указан недопустимый интервал. Проверьте высоту " -"слоя и ширину экструзии." +msgid "Invalid spacing supplied to Flow::with_spacing(), check your layer height and extrusion width" +msgstr "Для Flow::with_spacing () был указан недопустимый интервал. Проверьте высоту слоя и ширину экструзии." msgid "undefined error" msgstr "неопределённая ошибка" @@ -8542,166 +7895,96 @@ msgid "write callback failed" msgstr "ошибка записи функции обратного вызова" #, boost-format -msgid "" -"%1% is too close to exclusion area, there may be collisions when printing." -msgstr "" -"%1% находится слишком близко к области исключения, что может привести к " -"столкновению при печати." +msgid "%1% is too close to exclusion area, there may be collisions when printing." +msgstr "%1% находится слишком близко к области исключения, что может привести к столкновению при печати." #, boost-format msgid "%1% is too close to others, and collisions may be caused." -msgstr "" -"%1% находится слишком близко к другим, что может привести к столкновению." +msgstr "%1% находится слишком близко к другим, что может привести к столкновению." #, boost-format msgid "%1% is too tall, and collisions will be caused." msgstr "Модель «%1%» слишком высокая, что может привести к столкновению." msgid " is too close to others, there may be collisions when printing." -msgstr "" -" находится слишком близко к другим моделям, что может привести к " -"столкновению при печати." +msgstr " находится слишком близко к другим моделям, что может привести к столкновению при печати." msgid " is too close to exclusion area, there may be collisions when printing." -msgstr "" -" находится слишком близко к области исключения, что может привести к " -"столкновению при печати." +msgstr " находится слишком близко к области исключения, что может привести к столкновению при печати." msgid "Prime Tower" msgstr "Черновая башня" msgid " is too close to others, and collisions may be caused.\n" -msgstr "" -" находится слишком близко к другим моделям, что может привести к " -"столкновению.\n" +msgstr " находится слишком близко к другим моделям, что может привести к столкновению.\n" msgid " is too close to exclusion area, and collisions will be caused.\n" -msgstr "" -" находится слишком близко к области исключения, что может привести к " -"столкновению.\n" +msgstr " находится слишком близко к области исключения, что может привести к столкновению.\n" msgid "" -"Can not print multiple filaments which have large difference of temperature " -"together. Otherwise, the extruder and nozzle may be blocked or damaged " -"during printing" +"Can not print multiple filaments which have large difference of temperature together. Otherwise, the extruder and nozzle may be blocked or damaged during printing" msgstr "" -"Не допускается совместная печать несколькими материалами, имеющими большую " -"разницу в температуре печати. Это может привести к засорению и повреждению " -"сопла и экструдера." +"Не допускается совместная печать несколькими материалами, имеющими большую разницу в температуре печати. Это может привести к засорению и повреждению сопла и " +"экструдера." msgid "No extrusions under current settings." msgstr "При текущих настройках экструзия отсутствует." -msgid "" -"Smooth mode of timelapse is not supported when \"by object\" sequence is " -"enabled." -msgstr "" -"Плавный режим таймлапса не поддерживается, когда включена последовательность " -"печати моделей по очереди." +msgid "Smooth mode of timelapse is not supported when \"by object\" sequence is enabled." +msgstr "Плавный режим таймлапса не поддерживается, когда включена последовательность печати моделей по очереди." -msgid "" -"Please select \"By object\" print sequence to print multiple objects in " -"spiral vase mode." -msgstr "" -"Выберите последовательность печати «По очереди», для поддержки печати " -"несколько моделей в режиме спиральной вазы." +msgid "Please select \"By object\" print sequence to print multiple objects in spiral vase mode." +msgstr "Выберите последовательность печати «По очереди», для поддержки печати несколько моделей в режиме спиральной вазы." -msgid "" -"The spiral vase mode does not work when an object contains more than one " -"materials." -msgstr "" -"Режим «Спиральная ваза» не работает, когда модель печатается несколькими " -"материалами." +msgid "The spiral vase mode does not work when an object contains more than one materials." +msgstr "Режим «Спиральная ваза» не работает, когда модель печатается несколькими материалами." #, boost-format msgid "The object %1% exceeds the maximum build volume height." msgstr "Высота модели %1% превышает максимально допустимую." #, boost-format -msgid "" -"While the object %1% itself fits the build volume, its last layer exceeds " -"the maximum build volume height." -msgstr "" -"Хотя сама модель %1% вписывается в область построения, её последний слой " -"превышает максимальную высоту области построения." +msgid "While the object %1% itself fits the build volume, its last layer exceeds the maximum build volume height." +msgstr "Хотя сама модель %1% вписывается в область построения, её последний слой превышает максимальную высоту области построения." -msgid "" -"You might want to reduce the size of your model or change current print " -"settings and retry." -msgstr "" -"Попробуйте уменьшить размер модели или изменить текущие настройки печати и " -"повторить попытку." +msgid "You might want to reduce the size of your model or change current print settings and retry." +msgstr "Попробуйте уменьшить размер модели или изменить текущие настройки печати и повторить попытку." msgid "Variable layer height is not supported with Organic supports." -msgstr "" -"Функция переменной высоты слоя не совместима органическими поддержками." +msgstr "Функция переменной высоты слоя не совместима органическими поддержками." -msgid "" -"Different nozzle diameters and different filament diameters is not allowed " -"when prime tower is enabled." -msgstr "" -"При включении черновой башни не допускается использования разных диаметров " -"сопел и разных диаметров пластиковой нити." +msgid "Different nozzle diameters and different filament diameters is not allowed when prime tower is enabled." +msgstr "При включении черновой башни не допускается использования разных диаметров сопел и разных диаметров пластиковой нити." -msgid "" -"The Wipe Tower is currently only supported with the relative extruder " -"addressing (use_relative_e_distances=1)." -msgstr "" -"В настоящее время для режима черновой башни поддерживается только " -"относительная адресация экструдера (use_relative_e_distances=1)." +msgid "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)." +msgstr "В настоящее время для режима черновой башни поддерживается только относительная адресация экструдера (use_relative_e_distances=1)." -msgid "" -"Ooze prevention is currently not supported with the prime tower enabled." -msgstr "" -"Предотвращение течи материала с помощью черновой башни в настоящее время не " -"поддерживается." +msgid "Ooze prevention is currently not supported with the prime tower enabled." +msgstr "Предотвращение течи материала с помощью черновой башни в настоящее время не поддерживается." -msgid "" -"The prime tower is currently only supported for the Marlin, RepRap/Sprinter, " -"RepRapFirmware and Repetier G-code flavors." -msgstr "" -"В настоящее время режим черновой башни поддерживается только следующими " -"типами G-кода: Marlin, Klipper, RepRap/Sprinter, RepRapFirmware и Repetier." +msgid "The prime tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors." +msgstr "В настоящее время режим черновой башни поддерживается только следующими типами G-кода: Marlin, Klipper, RepRap/Sprinter, RepRapFirmware и Repetier." msgid "The prime tower is not supported in \"By object\" print." msgstr "Черновая башня не поддерживается при печати в режиме «По очереди»." -msgid "" -"The prime tower is not supported when adaptive layer height is on. It " -"requires that all objects have the same layer height." -msgstr "" -"Черновой башни не поддерживается, когда включена функция переменной высоты " -"слоя. Требуется, чтобы все модели имели одинаковую высоту слоя." +msgid "The prime tower is not supported when adaptive layer height is on. It requires that all objects have the same layer height." +msgstr "Черновой башни не поддерживается, когда включена функция переменной высоты слоя. Требуется, чтобы все модели имели одинаковую высоту слоя." msgid "The prime tower requires \"support gap\" to be multiple of layer height" -msgstr "" -"Для черновой башни требуется, чтобы зазор поддержки был кратен высоте слоя." +msgstr "Для черновой башни требуется, чтобы зазор поддержки был кратен высоте слоя." msgid "The prime tower requires that all objects have the same layer heights" -msgstr "" -"Для использования черновой башни требуется, чтобы у всех моделей была " -"одинаковая высота слоя." +msgstr "Для использования черновой башни требуется, чтобы у всех моделей была одинаковая высота слоя." -msgid "" -"The prime tower requires that all objects are printed over the same number " -"of raft layers" -msgstr "" -"Для черновой башни требуется, чтобы все модели были напечатаны на одинаковом " -"количестве слоёв подложки." +msgid "The prime tower requires that all objects are printed over the same number of raft layers" +msgstr "Для черновой башни требуется, чтобы все модели были напечатаны на одинаковом количестве слоёв подложки." -msgid "" -"The prime tower requires that all objects are sliced with the same layer " -"heights." -msgstr "" -"Для использования черновой башни требуется, чтобы все модели были нарезаны с " -"одинаковой высотой слоя." +msgid "The prime tower requires that all objects are sliced with the same layer heights." +msgstr "Для использования черновой башни требуется, чтобы все модели были нарезаны с одинаковой высотой слоя." -msgid "" -"The prime tower is only supported if all objects have the same variable " -"layer height" -msgstr "" -"Для черновой башни требуется, чтобы все модели имели одинаковую переменную " -"высоту слоя." +msgid "The prime tower is only supported if all objects have the same variable layer height" +msgstr "Для черновой башни требуется, чтобы все модели имели одинаковую переменную высоту слоя." msgid "Too small line width" msgstr "Слишком маленькая ширина экструзии" @@ -8709,121 +7992,69 @@ msgstr "Слишком маленькая ширина экструзии" msgid "Too large line width" msgstr "Слишком большая ширина экструзии" -msgid "" -"The prime tower requires that support has the same layer height with object." -msgstr "" -"Для черновой башни требуется, чтобы поддержка и модель имели одинаковую " -"высоту слоя." +msgid "The prime tower requires that support has the same layer height with object." +msgstr "Для черновой башни требуется, чтобы поддержка и модель имели одинаковую высоту слоя." -msgid "" -"Organic support tree tip diameter must not be smaller than support material " -"extrusion width." -msgstr "" -"Диаметр кончика ветки органической поддержки не должен быть меньше значения " -"ширины экструзии поддержки." +msgid "Organic support tree tip diameter must not be smaller than support material extrusion width." +msgstr "Диаметр кончика ветки органической поддержки не должен быть меньше значения ширины экструзии поддержки." -msgid "" -"Organic support branch diameter must not be smaller than 2x support material " -"extrusion width." -msgstr "" -"Диаметр ветки органической поддержки должен быть хотя бы в два раза больше " -"значения ширины экструзии поддержки." +msgid "Organic support branch diameter must not be smaller than 2x support material extrusion width." +msgstr "Диаметр ветки органической поддержки должен быть хотя бы в два раза больше значения ширины экструзии поддержки." -msgid "" -"Organic support branch diameter must not be smaller than support tree tip " -"diameter." -msgstr "" -"Диаметр ветвей органической поддержки должен быть больше диаметра кончика " -"ветки." +msgid "Organic support branch diameter must not be smaller than support tree tip diameter." +msgstr "Диаметр ветвей органической поддержки должен быть больше диаметра кончика ветки." -msgid "" -"Support enforcers are used but support is not enabled. Please enable support." -msgstr "" -"Используется принудительная поддержка, но её генерация не включена. " -"Пожалуйста, включите генерацию поддержки в настройках слайсера." +msgid "Support enforcers are used but support is not enabled. Please enable support." +msgstr "Используется принудительная поддержка, но её генерация не включена. Пожалуйста, включите генерацию поддержки в настройках слайсера." msgid "Layer height cannot exceed nozzle diameter" msgstr "Высота слоя не может быть больше диаметра сопла" msgid "" -"Relative extruder addressing requires resetting the extruder position at " -"each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to " -"layer_gcode." +"Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode." msgstr "" -"При относительной адресации экструдера его положение необходимо " -"корректировать на каждом слое, чтобы предотвратить потерю точности с " -"плавающей запятой. Добавьте \"G92 E0\" в G-код выполняемый при смене слоя " -"(layer_gcode)." +"При относительной адресации экструдера его положение необходимо корректировать на каждом слое, чтобы предотвратить потерю точности с плавающей запятой. Добавьте " +"\"G92 E0\" в G-код выполняемый при смене слоя (layer_gcode)." -msgid "" -"\"G92 E0\" was found in before_layer_gcode, which is incompatible with " -"absolute extruder addressing." -msgstr "" -"В G-коде выполняемом перед сменой слоя (before_layer_gcode) была найдена " -"команда \"G92 E0\", которая несовместима с абсолютной адресацией экструдера." +msgid "\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing." +msgstr "В G-коде выполняемом перед сменой слоя (before_layer_gcode) была найдена команда \"G92 E0\", которая несовместима с абсолютной адресацией экструдера." -msgid "" -"\"G92 E0\" was found in layer_gcode, which is incompatible with absolute " -"extruder addressing." -msgstr "" -"В G-коде выполняемом при смене слоя (layer_gcode) была найдена команда \"G92 " -"E0\", которая несовместима с абсолютной адресацией экструдера." +msgid "\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing." +msgstr "В G-коде выполняемом при смене слоя (layer_gcode) была найдена команда \"G92 E0\", которая несовместима с абсолютной адресацией экструдера." #, c-format, boost-format msgid "Plate %d: %s does not support filament %s" msgstr "Печатная пластина %d: %s не поддерживает пруток %s" -msgid "" -"Setting the jerk speed too low could lead to artifacts on curved surfaces" -msgstr "" -"Слишком низкая скорость рывка может привести к появлению артефактов на " -"изогнутых поверхностях. " +msgid "Setting the jerk speed too low could lead to artifacts on curved surfaces" +msgstr "Слишком низкая скорость рывка может привести к появлению артефактов на изогнутых поверхностях. " msgid "" -"The jerk setting exceeds the printer's maximum jerk (machine_max_jerk_x/" -"machine_max_jerk_y).\n" -"Orca will automatically cap the jerk speed to ensure it doesn't surpass the " -"printer's capabilities.\n" -"You can adjust the maximum jerk setting in your printer's configuration to " -"get higher speeds." +"The jerk setting exceeds the printer's maximum jerk (machine_max_jerk_x/machine_max_jerk_y).\n" +"Orca will automatically cap the jerk speed to ensure it doesn't surpass the printer's capabilities.\n" +"You can adjust the maximum jerk setting in your printer's configuration to get higher speeds." msgstr "" -"Значение максимального рывка (machine_max_jerk_x/machine_max_jerk_y) " -"превышает значение заданное в настройках принтера.\n" -"Программа автоматически ограничит рывок, чтобы он не превышал возможности " -"принтера.\n" -"Если хотите получить более высокие скорости, вы можете изменить это значение " -"в настройках принтера (вкладка «Ограничение принтера»)." +"Значение максимального рывка (machine_max_jerk_x/machine_max_jerk_y) превышает значение заданное в настройках принтера.\n" +"Программа автоматически ограничит рывок, чтобы он не превышал возможности принтера.\n" +"Если хотите получить более высокие скорости, вы можете изменить это значение в настройках принтера (вкладка «Ограничение принтера»)." msgid "" -"The acceleration setting exceeds the printer's maximum acceleration " -"(machine_max_acceleration_extruding).\n" -"Orca will automatically cap the acceleration speed to ensure it doesn't " -"surpass the printer's capabilities.\n" -"You can adjust the machine_max_acceleration_extruding value in your " -"printer's configuration to get higher speeds." +"The acceleration setting exceeds the printer's maximum acceleration (machine_max_acceleration_extruding).\n" +"Orca will automatically cap the acceleration speed to ensure it doesn't surpass the printer's capabilities.\n" +"You can adjust the machine_max_acceleration_extruding value in your printer's configuration to get higher speeds." msgstr "" -"Значение максимального ускорения подачи у экструдера " -"(machine_max_acceleration_extruding) превышает значение заданное в " -"настройках принтера.\n" -"Программа автоматически ограничит это ускорение, чтобы оно не превышало " -"возможности принтера.\n" -"Если хотите получить более высокие скорости, вы можете изменить это значение " -"в настройках принтера (вкладка «Ограничение принтера»)." +"Значение максимального ускорения при печати (machine_max_acceleration_extruding) превышает значение заданное в настройках принтера.\n" +"Программа автоматически ограничит это ускорение, чтобы оно не превышало возможности принтера.\n" +"Если хотите получить более высокие скорости, вы можете изменить это значение в настройках принтера (вкладка «Ограничение принтера»)." msgid "" -"The travel acceleration setting exceeds the printer's maximum travel " -"acceleration (machine_max_acceleration_travel).\n" -"Orca will automatically cap the travel acceleration speed to ensure it " -"doesn't surpass the printer's capabilities.\n" -"You can adjust the machine_max_acceleration_travel value in your printer's " -"configuration to get higher speeds." +"The travel acceleration setting exceeds the printer's maximum travel acceleration (machine_max_acceleration_travel).\n" +"Orca will automatically cap the travel acceleration speed to ensure it doesn't surpass the printer's capabilities.\n" +"You can adjust the machine_max_acceleration_travel value in your printer's configuration to get higher speeds." msgstr "" -"Значение ускорения перемещения превышает значение заданное в настройках " -"принтера (machine_max_acceleration_travel).\n" -"Программа автоматически ограничит это ускорение, чтобы оно не превышало " -"возможности принтера. \n" -"Если хотите получить более высокие скорости, вы можете изменить это значение " -"в настройках принтера (вкладка «Ограничение принтера»)." +"Значение ускорения перемещения превышает значение заданное в настройках принтера (machine_max_acceleration_travel).\n" +"Программа автоматически ограничит это ускорение, чтобы оно не превышало возможности принтера. \n" +"Если хотите получить более высокие скорости, вы можете изменить это значение в настройках принтера (вкладка «Ограничение принтера»)." msgid "Generating skirt & brim" msgstr "Генерация юбки и каймы" @@ -8844,14 +8075,11 @@ msgid "Bed exclude area" msgstr "Область исключения" msgid "" -"Unprintable area in XY plane. For example, X1 Series printers use the front " -"left corner to cut filament during filament change. The area is expressed as " -"polygon by points in following format: \"XxY, XxY, ...\"" +"Unprintable area in XY plane. For example, X1 Series printers use the front left corner to cut filament during filament change. The area is expressed as polygon " +"by points in following format: \"XxY, XxY, ...\"" msgstr "" -"Непечатаемая область в плоскости XY. Например, в принтерах серии X1 передний " -"левый угол используется для обрезания материала при его замене. Область " -"выражается в виде многоугольника по точкам в следующем формате: \"XxY, " -"XxY, ...\"" +"Непечатаемая область в плоскости XY. Например, в принтерах серии X1 передний левый угол используется для обрезания материала при его замене. Область выражается в " +"виде многоугольника по точкам в следующем формате: \"XxY, XxY, ...\"" msgid "Bed custom texture" msgstr "Пользовательская текстура стола" @@ -8862,35 +8090,24 @@ msgstr "Пользовательская модель стола" msgid "Elephant foot compensation" msgstr "Компенсация «слоновьей ноги»" -msgid "" -"Shrink the initial layer on build plate to compensate for elephant foot " -"effect" -msgstr "" -"Уменьшение первого слоя в плоскости XY на заданное значение, чтобы " -"компенсировать эффект слоновьей ноги." +msgid "Shrink the initial layer on build plate to compensate for elephant foot effect" +msgstr "Уменьшение первого слоя в плоскости XY на заданное значение, чтобы компенсировать эффект слоновьей ноги." msgid "Elephant foot compensation layers" msgstr "Компенсирующих слоёв «слоновьей ноги»" msgid "" -"The number of layers on which the elephant foot compensation will be active. " -"The first layer will be shrunk by the elephant foot compensation value, then " -"the next layers will be linearly shrunk less, up to the layer indicated by " -"this value." +"The number of layers on which the elephant foot compensation will be active. The first layer will be shrunk by the elephant foot compensation value, then the " +"next layers will be linearly shrunk less, up to the layer indicated by this value." msgstr "" -"Количество слоёв, на которые будет распространяться компенсация слоновьей " -"ноги. Первый слой будет уменьшен на величину компенсации слоновьей ноги с " -"последующим линейным уменьшением до слоя, указанного здесь." +"Количество слоёв, на которые будет распространяться компенсация слоновьей ноги. Первый слой будет уменьшен на величину компенсации слоновьей ноги с последующим " +"линейным уменьшением до слоя, указанного здесь." msgid "layers" msgstr "слой(-я)" -msgid "" -"Slicing height for each layer. Smaller layer height means more accurate and " -"more printing time" -msgstr "" -"Высота каждого слоя. Чем меньше значение, тем лучше качество, но требуется " -"больше времени для печати, и наоборот." +msgid "Slicing height for each layer. Smaller layer height means more accurate and more printing time" +msgstr "Высота каждого слоя. Чем меньше значение, тем лучше качество, но требуется больше времени для печати, и наоборот." msgid "Printable height" msgstr "Высота печати" @@ -8917,36 +8134,25 @@ msgid "Hostname, IP or URL" msgstr "Имя хоста, IP/URL-адрес" msgid "" -"Orca Slicer can upload G-code files to a printer host. This field should " -"contain the hostname, IP address or URL of the printer host instance. Print " -"host behind HAProxy with basic auth enabled can be accessed by putting the " -"user name and password into the URL in the following format: https://" -"username:password@your-octopi-address/" +"Orca Slicer can upload G-code files to a printer host. This field should contain the hostname, IP address or URL of the printer host instance. Print host behind " +"HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL in the following format: https://username:password@your-octopi-" +"address/" msgstr "" -"Orca Slicer может загружать G-код файлы на хост принтера. В этом поле нужно " -"указать имя хоста, IP-адрес или URL-адрес хост-экземпляра принтера. Доступ к " -"узлу печати на основе HAProxy с включенной базовой аутентификацией можно " -"получить, указав имя пользователя и пароль в поле URL-адрес в следующем " -"формате: https://username:password@your-octopi-address/" +"Orca Slicer может загружать G-код файлы на хост принтера. В этом поле нужно указать имя хоста, IP-адрес или URL-адрес хост-экземпляра принтера. Доступ к узлу " +"печати на основе HAProxy с включенной базовой аутентификацией можно получить, указав имя пользователя и пароль в поле URL-адрес в следующем формате: https://" +"username:password@your-octopi-address/" msgid "Device UI" msgstr "URL-адрес хоста" -msgid "" -"Specify the URL of your device user interface if it's not same as print_host" -msgstr "" -"Укажите URL-адрес пользовательского интерфейса вашего устройства, если он не " -"совпадает с print_host" +msgid "Specify the URL of your device user interface if it's not same as print_host" +msgstr "Укажите URL-адрес пользовательского интерфейса вашего устройства, если он не совпадает с print_host" msgid "API Key / Password" msgstr "API-ключ / Пароль" -msgid "" -"Orca Slicer can upload G-code files to a printer host. This field should " -"contain the API Key or the password required for authentication." -msgstr "" -"Orca Slicerможет загружать файл G-кода на хост принтера. Это поле должно " -"содержать API ключ или пароль, необходимые для проверки подлинности." +msgid "Orca Slicer can upload G-code files to a printer host. This field should contain the API Key or the password required for authentication." +msgstr "Orca Slicerможет загружать файл G-кода на хост принтера. Это поле должно содержать API ключ или пароль, необходимые для проверки подлинности." msgid "Name of the printer" msgstr "Название принтера" @@ -8955,13 +8161,10 @@ msgid "HTTPS CA File" msgstr "Файл корневого сертификата HTTPS" msgid "" -"Custom CA certificate file can be specified for HTTPS OctoPrint connections, " -"in crt/pem format. If left blank, the default OS CA certificate repository " -"is used." +"Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. If left blank, the default OS CA certificate repository is used." msgstr "" -"Для подключений по HTTPS к OctoPrint укажите пользовательский файл корневого " -"сертификата в формате crt/pem. Если оставить поле пустым, будет " -"использоваться хранилище сертификатов ОС по умолчанию." +"Для подключений по HTTPS к OctoPrint укажите пользовательский файл корневого сертификата в формате crt/pem. Если оставить поле пустым, будет использоваться " +"хранилище сертификатов ОС по умолчанию." msgid "User" msgstr "Пользователь" @@ -8973,13 +8176,11 @@ msgid "Ignore HTTPS certificate revocation checks" msgstr "Игнорировать проверки отзыва HTTPS сертификата" msgid "" -"Ignore HTTPS certificate revocation checks in case of missing or offline " -"distribution points. One may want to enable this option for self signed " -"certificates if connection fails." +"Ignore HTTPS certificate revocation checks in case of missing or offline distribution points. One may want to enable this option for self signed certificates if " +"connection fails." msgstr "" -"Игнорировать проверки отзыва HTTPS сертификата в случае его отсутствия или " -"автономности точек распространения. Можно включить эту опцию для " -"самоподписанных сертификатов в случае сбоя подключения." +"Игнорировать проверки отзыва HTTPS сертификата в случае его отсутствия или автономности точек распространения. Можно включить эту опцию для самоподписанных " +"сертификатов в случае сбоя подключения." msgid "Names of presets related to the physical printer" msgstr "Имена профилей, связанных с физическим принтером" @@ -8997,24 +8198,18 @@ msgid "Avoid crossing wall" msgstr "Избегать пересечения периметров" msgid "Detour and avoid to travel across wall which may cause blob on surface" -msgstr "" -"Объезжать и избегать пересечения периметров, для предотвращения образования " -"дефектов на поверхности модели." +msgstr "Объезжать и избегать пересечения периметров, для предотвращения образования дефектов на поверхности модели." msgid "Avoid crossing wall - Max detour length" msgstr "Избегать пересечения периметров - Макс. длина обхода" msgid "" -"Maximum detour distance for avoiding crossing wall. Don't detour if the " -"detour distance is large than this value. Detour length could be specified " -"either as an absolute value or as percentage (for example 50%) of a direct " -"travel path. Zero to disable" +"Maximum detour distance for avoiding crossing wall. Don't detour if the detour distance is large than this value. Detour length could be specified either as an " +"absolute value or as percentage (for example 50%) of a direct travel path. Zero to disable" msgstr "" -"Максимальное расстояние обхода сопла от модели во избежание пересечения " -"периметров при движении. Если расстояние обхода превышает это значение, то " -"для данного маршрута эта опция не применяется. Длина обхода может быть " -"задана как в абсолютном значении, так и в процентах (например, 50%) от " -"прямого пути перемещения. 0 - отключено." +"Максимальное расстояние обхода сопла от модели во избежание пересечения периметров при движении. Если расстояние обхода превышает это значение, то для данного " +"маршрута эта опция не применяется. Длина обхода может быть задана как в абсолютном значении, так и в процентах (например, 50%) от прямого пути перемещения. 0 - " +"отключено." msgid "mm or %" msgstr "мм или %" @@ -9022,36 +8217,20 @@ msgstr "мм или %" msgid "Other layers" msgstr "Последующие слои" -msgid "" -"Bed temperature for layers except the initial one. Value 0 means the " -"filament does not support to print on the Cool Plate" -msgstr "" -"Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая " -"нить не поддерживает печать на этой печатной пластине." +msgid "Bed temperature for layers except the initial one. Value 0 means the filament does not support to print on the Cool Plate" +msgstr "Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "°C" msgstr "°C" -msgid "" -"Bed temperature for layers except the initial one. Value 0 means the " -"filament does not support to print on the Engineering Plate" -msgstr "" -"Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая " -"нить не поддерживает печать на этой печатной пластине." +msgid "Bed temperature for layers except the initial one. Value 0 means the filament does not support to print on the Engineering Plate" +msgstr "Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." -msgid "" -"Bed temperature for layers except the initial one. Value 0 means the " -"filament does not support to print on the High Temp Plate" -msgstr "" -"Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая " -"нить не поддерживает печать на этой печатной пластине." +msgid "Bed temperature for layers except the initial one. Value 0 means the filament does not support to print on the High Temp Plate" +msgstr "Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." -msgid "" -"Bed temperature for layers except the initial one. Value 0 means the " -"filament does not support to print on the Textured PEI Plate" -msgstr "" -"Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая " -"нить не поддерживает печать на этой печатной пластине." +msgid "Bed temperature for layers except the initial one. Value 0 means the filament does not support to print on the Textured PEI Plate" +msgstr "Температура стола для всех слоёв, кроме первого. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "Initial layer" msgstr "Первый слой" @@ -9059,33 +8238,17 @@ msgstr "Первый слой" msgid "Initial layer bed temperature" msgstr "Температура стола для первого слоя" -msgid "" -"Bed temperature of the initial layer. Value 0 means the filament does not " -"support to print on the Cool Plate" -msgstr "" -"Температура стола для первого слоя. 0 означает, что пластиковая нить не " -"поддерживает печать на этой печатной пластине." +msgid "Bed temperature of the initial layer. Value 0 means the filament does not support to print on the Cool Plate" +msgstr "Температура стола для первого слоя. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." -msgid "" -"Bed temperature of the initial layer. Value 0 means the filament does not " -"support to print on the Engineering Plate" -msgstr "" -"Температура стола для первого слоя. 0 означает, что пластиковая нить не " -"поддерживает печать на этой печатной пластине." +msgid "Bed temperature of the initial layer. Value 0 means the filament does not support to print on the Engineering Plate" +msgstr "Температура стола для первого слоя. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." -msgid "" -"Bed temperature of the initial layer. Value 0 means the filament does not " -"support to print on the High Temp Plate" -msgstr "" -"Температура стола для первого слоя. 0 означает, что пластиковая нить не " -"поддерживает печать на этой печатной пластине." +msgid "Bed temperature of the initial layer. Value 0 means the filament does not support to print on the High Temp Plate" +msgstr "Температура стола для первого слоя. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." -msgid "" -"Bed temperature of the initial layer. Value 0 means the filament does not " -"support to print on the Textured PEI Plate" -msgstr "" -"Температура стола для первого слоя. 0 означает, что пластиковая нить не " -"поддерживает печать на этой печатной пластине." +msgid "Bed temperature of the initial layer. Value 0 means the filament does not support to print on the Textured PEI Plate" +msgstr "Температура стола для первого слоя. 0 означает, что пластиковая нить не поддерживает печать на этой печатной пластине." msgid "Bed types supported by the printer" msgstr "Типы столов, поддерживаемые принтером" @@ -9100,62 +8263,45 @@ msgid "First layer print sequence" msgstr "Последовательность печати первого слоя" msgid "This G-code is inserted at every layer change before lifting z" -msgstr "" -"Этот G-код вставляется при каждой смене слоя, непосредственно перед " -"перемещения оси Z." +msgstr "Этот G-код вставляется при каждой смене слоя, непосредственно перед перемещения оси Z." msgid "Bottom shell layers" msgstr "Сплошных слоёв снизу" msgid "" -"This is the number of solid layers of bottom shell, including the bottom " -"surface layer. When the thickness calculated by this value is thinner than " -"bottom shell thickness, the bottom shell layers will be increased" +"This is the number of solid layers of bottom shell, including the bottom surface layer. When the thickness calculated by this value is thinner than bottom shell " +"thickness, the bottom shell layers will be increased" msgstr "" -"Количество сплошных слоёв при печати нижней поверхности модели, включая " -"нижний поверхностный слой. Если толщина, рассчитанная с помощью этого " -"значения, меньше толщины оболочки снизу, количество слоёв оболочки снизу " -"будет увеличено." +"Количество сплошных слоёв при печати нижней поверхности модели, включая нижний поверхностный слой. Если толщина, рассчитанная с помощью этого значения, меньше " +"толщины оболочки снизу, количество слоёв оболочки снизу будет увеличено." msgid "Bottom shell thickness" msgstr "Толщина оболочки снизу" msgid "" -"The number of bottom solid layers is increased when slicing if the thickness " -"calculated by bottom shell layers is thinner than this value. This can avoid " -"having too thin shell when layer height is small. 0 means that this setting " -"is disabled and thickness of bottom shell is absolutely determained by " -"bottom shell layers" +"The number of bottom solid layers is increased when slicing if the thickness calculated by bottom shell layers is thinner than this value. This can avoid having " +"too thin shell when layer height is small. 0 means that this setting is disabled and thickness of bottom shell is absolutely determained by bottom shell layers" msgstr "" -"Минимальная толщина оболочки снизу в мм. Если толщина оболочки, рассчитанная " -"по количеству сплошных слоёв снизу, меньше этого значения, количество " -"сплошных слоёв снизу будет автоматически увеличено при нарезке, для " -"удовлетворения минимальной толщины оболочки. Это позволяет избежать слишком " -"тонкой оболочки при небольшой высоте слоя. 0 означает, что этот параметр " -"отключён, а толщина оболочки снизу полностью задаётся количеством сплошных " -"слоёв снизу." +"Минимальная толщина оболочки снизу в мм. Если толщина оболочки, рассчитанная по количеству сплошных слоёв снизу, меньше этого значения, количество сплошных слоёв " +"снизу будет автоматически увеличено при нарезке, для удовлетворения минимальной толщины оболочки. Это позволяет избежать слишком тонкой оболочки при небольшой " +"высоте слоя. 0 означает, что этот параметр отключён, а толщина оболочки снизу полностью задаётся количеством сплошных слоёв снизу." msgid "Apply gap fill" msgstr "Заполнять пробелы" msgid "" -"Enables gap fill for the selected surfaces. The minimum gap length that will " -"be filled can be controlled from the filter out tiny gaps option below.\n" +"Enables gap fill for the selected surfaces. The minimum gap length that will be filled can be controlled from the filter out tiny gaps option below.\n" "\n" "Options:\n" "1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n" -"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces " -"only\n" +"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces only\n" "3. Nowhere: Disables gap fill\n" msgstr "" -"Включает заполнение пробелов для выбранных поверхностей. Минимальной длиной " -"пробела, который будет заполнен, можно управлять с помощью нижерасположенной " -"опции «Игнорировать небольшие пробелы».\n" +"Включает заполнение пробелов для выбранных поверхностей. Минимальной длиной пробела, который будет заполнен, можно управлять с помощью нижерасположенной опции " +"«Игнорировать небольшие пробелы».\n" "Доступные режимы:\n" -"1. Везде (заполнение пробелов применяется на верхних, нижних и внутренних " -"сплошных поверхностях)\n" -"2. Верхняя и нижняя поверхности (заполнение пробелов применяется только к " -"верхней и нижней поверхностям)\n" +"1. Везде (заполнение пробелов применяется на верхних, нижних и внутренних сплошных поверхностях)\n" +"2. Верхняя и нижняя поверхности (заполнение пробелов применяется только к верхней и нижней поверхностям)\n" "3. Нигде (заполнение пробелов отключено)\n" msgid "Everywhere" @@ -9170,170 +8316,121 @@ msgstr "Нигде" msgid "Force cooling for overhang and bridge" msgstr "Принудительный обдув навесов и мостов" -msgid "" -"Enable this option to optimize part cooling fan speed for overhang and " -"bridge to get better cooling" -msgstr "" -"Включите, чтобы оптимизировать скорость вентилятора охлаждения моделей для " -"нависаний и мостов для обеспечения лучшего их охлаждения." +msgid "Enable this option to optimize part cooling fan speed for overhang and bridge to get better cooling" +msgstr "Включите, чтобы оптимизировать скорость вентилятора охлаждения моделей для нависаний и мостов для обеспечения лучшего их охлаждения." msgid "Fan speed for overhang" msgstr "Скорость вентилятора на нависанияx" msgid "" -"Force part cooling fan to be this speed when printing bridge or overhang " -"wall which has large overhang degree. Forcing cooling for overhang and " -"bridge can get better quality for these part" +"Force part cooling fan to be this speed when printing bridge or overhang wall which has large overhang degree. Forcing cooling for overhang and bridge can get " +"better quality for these part" msgstr "" -"Заставляет вентилятор обдува модели работать на этой скорости при печати " -"мостов или нависающих периметров, имеющих большую степень свеса. " -"Принудительное охлаждение позволяет повысить качество печати этих частей." +"Заставляет вентилятор обдува модели работать на этой скорости при печати мостов или нависающих периметров, имеющих большую степень свеса. Принудительное " +"охлаждение позволяет повысить качество печати этих частей." msgid "Cooling overhang threshold" msgstr "Порог включения обдува на нависаниях" msgid "" -"Force cooling fan to be specific speed when overhang degree of printed part " -"exceeds this value. Expressed as percentage which indicides how much width " -"of the line without support from lower layer. 0% means forcing cooling for " -"all outer wall no matter how much overhang degree" +"Force cooling fan to be specific speed when overhang degree of printed part exceeds this value. Expressed as percentage which indicides how much width of the " +"line without support from lower layer. 0% means forcing cooling for all outer wall no matter how much overhang degree" msgstr "" -"Принудительное включение вентилятора обдува модели на определенную скорость, " -"если степень нависания печатаемой части превышает данное значение. " -"Выражается в процентах и показывает, насколько велика ширина периметра без " -"поддержки со стороны нижнего слоя. 0% означает принудительное охлаждение " -"всего внешнего периметра независимо от степени нависания." +"Принудительное включение вентилятора обдува модели на определенную скорость, если степень нависания печатаемой части превышает данное значение. Выражается в " +"процентах и показывает, насколько велика ширина периметра без поддержки со стороны нижнего слоя. 0% означает принудительное охлаждение всего внешнего периметра " +"независимо от степени нависания." msgid "Bridge infill direction" msgstr "Угол печати мостов" msgid "" -"Bridging angle override. If left to zero, the bridging angle will be " -"calculated automatically. Otherwise the provided angle will be used for " -"external bridges. Use 180°for zero angle." +"Bridging angle override. If left to zero, the bridging angle will be calculated automatically. Otherwise the provided angle will be used for external bridges. " +"Use 180°for zero angle." msgstr "" -"Переопределение угла печати мостов. Если задано 0, угол печати мостов " -"рассчитывается автоматически. В противном случае заданный угол будет " -"использоваться для наружных мостов. Для нулевого угла установите 180°." +"Переопределение угла печати мостов. Если задано 0, угол печати мостов рассчитывается автоматически. В противном случае заданный угол будет использоваться для " +"наружных мостов. Для нулевого угла установите 180°." msgid "Bridge density" msgstr "Плотность мостов" msgid "Density of external bridges. 100% means solid bridge. Default is 100%." -msgstr "" -"Плотность наружных мостов. 100% - сплошной мост. По умолчанию задано 100%." +msgstr "Плотность наружных мостов. 100% - сплошной мост. По умолчанию задано 100%." msgid "Bridge flow ratio" msgstr "Коэффициент подачи пластика при печати мостов" -msgid "" -"Decrease this value slightly(for example 0.9) to reduce the amount of " -"material for bridge, to improve sag" +msgid "Decrease this value slightly(for example 0.9) to reduce the amount of material for bridge, to improve sag" msgstr "" -"Параметр задаёт количество пластика, затрачиваемое для построения мостов. В " -"большинстве случаев настроек по умолчанию достаточно, тем не менее, при " -"печати некоторых моделей уменьшение параметра может сократить провисание " -"пластика при печати мостов." +"Параметр задаёт количество пластика, затрачиваемое для построения мостов. В большинстве случаев настроек по умолчанию достаточно, тем не менее, при печати " +"некоторых моделей уменьшение параметра может сократить провисание пластика при печати мостов." msgid "Internal bridge flow ratio" msgstr "Поток внутреннего моста" msgid "" -"This value governs the thickness of the internal bridge layer. This is the " -"first layer over sparse infill. Decrease this value slightly (for example " -"0.9) to improve surface quality over sparse infill." +"This value governs the thickness of the internal bridge layer. This is the first layer over sparse infill. Decrease this value slightly (for example 0.9) to " +"improve surface quality over sparse infill." msgstr "" -"Это значение определяет толщину слоя внутреннего моста, печатаемого поверх " -"разреженного заполнения. Немного уменьшите это значение (например 0,9), " -"чтобы улучшить качество поверхности печатаемой поверх разреженного " -"заполнения." +"Это значение определяет толщину слоя внутреннего моста, печатаемого поверх разреженного заполнения. Немного уменьшите это значение (например 0,9), чтобы улучшить " +"качество поверхности печатаемой поверх разреженного заполнения." msgid "Top surface flow ratio" msgstr "Коэффициент потока на верхней поверхности" -msgid "" -"This factor affects the amount of material for top solid infill. You can " -"decrease it slightly to have smooth surface finish" +msgid "This factor affects the amount of material for top solid infill. You can decrease it slightly to have smooth surface finish" msgstr "" -"Этот параметр задаёт количество выдавливаемого материала для верхнего " -"сплошного слоя заполнения. Вы можете немного уменьшить его, чтобы получить " -"более гладкую поверхность." +"Этот параметр задаёт количество выдавливаемого материала для верхнего сплошного слоя заполнения. Вы можете немного уменьшить его, чтобы получить более гладкую " +"поверхность." msgid "Bottom surface flow ratio" msgstr "Коэффициент потока на нижней поверхности" msgid "This factor affects the amount of material for bottom solid infill" -msgstr "" -"Этот параметр задаёт количество выдавливаемого материала для нижнего " -"сплошного слоя заполнения." +msgstr "Этот параметр задаёт количество выдавливаемого материала для нижнего сплошного слоя заполнения." msgid "Precise wall" msgstr "Точные периметры" msgid "" -"Improve shell precision by adjusting outer wall spacing. This also improves " -"layer consistency.\n" -"Note: This setting will only take effect if the wall sequence is configured " -"to Inner-Outer" +"Improve shell precision by adjusting outer wall spacing. This also improves layer consistency.\n" +"Note: This setting will only take effect if the wall sequence is configured to Inner-Outer" msgstr "" -"Повышение точности оболочки за счет регулировки расстояния между внешними " -"периметрами. Это также позволяет уменьшить расслоение слоёв.\n" -"Примечание: параметр будет действовать только в том случае, если " -"последовательность печати периметров задана «Внутренний/внешний»." +"Повышение точности оболочки за счет регулировки расстояния между внешними периметрами. Это также позволяет уменьшить расслоение слоёв.\n" +"Примечание: параметр будет действовать только в том случае, если последовательность печати периметров задана «Внутренний/внешний»." msgid "Only one wall on top surfaces" msgstr "Только один периметр на верхней поверхности" -msgid "" -"Use only one wall on flat top surface, to give more space to the top infill " -"pattern" -msgstr "" -"Печатать только один периметр на верхней поверхности, чтобы оставить больше " -"пространства для верхнего шаблона заполнения." +msgid "Use only one wall on flat top surface, to give more space to the top infill pattern" +msgstr "Печатать только один периметр на верхней поверхности, чтобы оставить больше пространства для верхнего шаблона заполнения." msgid "One wall threshold" msgstr "Порог одного периметра" #, no-c-format, no-boost-format msgid "" -"If a top surface has to be printed and it's partially covered by another " -"layer, it won't be considered at a top layer where its width is below this " -"value. This can be useful to not let the 'one perimeter on top' trigger on " -"surface that should be covered only by perimeters. This value can be a mm or " -"a % of the perimeter extrusion width.\n" -"Warning: If enabled, artifacts can be created if you have some thin features " -"on the next layer, like letters. Set this setting to 0 to remove these " -"artifacts." +"If a top surface has to be printed and it's partially covered by another layer, it won't be considered at a top layer where its width is below this value. This " +"can be useful to not let the 'one perimeter on top' trigger on surface that should be covered only by perimeters. This value can be a mm or a % of the perimeter " +"extrusion width.\n" +"Warning: If enabled, artifacts can be created if you have some thin features on the next layer, like letters. Set this setting to 0 to remove these artifacts." msgstr "" -"Если должна быть напечатана верхняя поверхность и частично покрыта другим " -"слоем, она не будет рассматриваться как верхний слой, ширина которого ниже " -"этого значения. Это может быть полезно, чтобы не допустить срабатывания " -"функции «Только один периметр на верхней поверхности» на поверхности, " -"которая должна быть покрыта только периметрами. Это значение может быть " -"задано в мм или % от ширины экструзии периметра.\n" -"Предупреждение: если этот параметр включён, то могут возникнуть дефекты, " -"если у вас на следующем слое имеются какие-то тонкие элементы, например, " -"буквы. Установите значение 0, чтобы избавиться от этих дефектов." +"Если должна быть напечатана верхняя поверхность и частично покрыта другим слоем, она не будет рассматриваться как верхний слой, ширина которого ниже этого " +"значения. Это может быть полезно, чтобы не допустить срабатывания функции «Только один периметр на верхней поверхности» на поверхности, которая должна быть " +"покрыта только периметрами. Это значение может быть задано в мм или % от ширины экструзии периметра.\n" +"Предупреждение: если этот параметр включён, то могут возникнуть дефекты, если у вас на следующем слое имеются какие-то тонкие элементы, например, буквы. " +"Установите значение 0, чтобы избавиться от этих дефектов." msgid "Only one wall on first layer" msgstr "Только один периметр на первом слое" -msgid "" -"Use only one wall on first layer, to give more space to the bottom infill " -"pattern" -msgstr "" -"Печатать только один периметр на первом слое, чтобы оставить больше " -"пространства для нижнего шаблона заполнения." +msgid "Use only one wall on first layer, to give more space to the bottom infill pattern" +msgstr "Печатать только один периметр на первом слое, чтобы оставить больше пространства для нижнего шаблона заполнения." msgid "Extra perimeters on overhangs" msgstr "Дополнительные периметры на нависаниях" -msgid "" -"Create additional perimeter paths over steep overhangs and areas where " -"bridges cannot be anchored. " -msgstr "" -"Создание дополнительных дорожек по периметру над крутыми нависаниями и " -"участками, где мосты не могут быть закреплены. " +msgid "Create additional perimeter paths over steep overhangs and areas where bridges cannot be anchored. " +msgstr "Создание дополнительных дорожек по периметру над крутыми нависаниями и участками, где мосты не могут быть закреплены. " msgid "Reverse on odd" msgstr "Реверс на нависаниях" @@ -9342,18 +8439,13 @@ msgid "Overhang reversal" msgstr "Реверс на нависаниях" msgid "" -"Extrude perimeters that have a part over an overhang in the reverse " -"direction on odd layers. This alternating pattern can drastically improve " -"steep overhangs.\n" +"Extrude perimeters that have a part over an overhang in the reverse direction on odd layers. This alternating pattern can drastically improve steep overhangs.\n" "\n" -"This setting can also help reduce part warping due to the reduction of " -"stresses in the part walls." +"This setting can also help reduce part warping due to the reduction of stresses in the part walls." msgstr "" -"Печать нависающих периметров в обратном направлении на нечётных слоях. Такое " -"чередование может значительно улучшить качество печати крутых нависаний.\n" +"Печать нависающих периметров в обратном направлении на нечётных слоях. Такое чередование может значительно улучшить качество печати крутых нависаний.\n" "\n" -"Эта настройка также может помочь уменьшить деформацию детали за счет " -"уменьшения напряжений в её стенках." +"Эта настройка также может помочь уменьшить деформацию детали за счет уменьшения напряжений в её стенках." msgid "Reverse only internal perimeters" msgstr "Реверс только для внутренних периметров" @@ -9361,48 +8453,35 @@ msgstr "Реверс только для внутренних периметро msgid "" "Apply the reverse perimeters logic only on internal perimeters. \n" "\n" -"This setting greatly reduces part stresses as they are now distributed in " -"alternating directions. This should reduce part warping while also " -"maintaining external wall quality. This feature can be very useful for warp " -"prone material, like ABS/ASA, and also for elastic filaments, like TPU and " -"Silk PLA. It can also help reduce warping on floating regions over " -"supports.\n" +"This setting greatly reduces part stresses as they are now distributed in alternating directions. This should reduce part warping while also maintaining external " +"wall quality. This feature can be very useful for warp prone material, like ABS/ASA, and also for elastic filaments, like TPU and Silk PLA. It can also help " +"reduce warping on floating regions over supports.\n" "\n" -"For this setting to be the most effective, it is recomended to set the " -"Reverse Threshold to 0 so that all internal walls print in alternating " -"directions on odd layers irrespective of their overhang degree." +"For this setting to be the most effective, it is recomended to set the Reverse Threshold to 0 so that all internal walls print in alternating directions on odd " +"layers irrespective of their overhang degree." msgstr "" -"Применяется логика реверса печати периметров только для внутренних " -"периметров.\n" +"Применяется логика реверса печати периметров только для внутренних периметров.\n" "\n" -"Эта настройка значительно снижает напряжения в деталях, поскольку теперь они " -"распределяются в чередующихся направлениях. Это должно уменьшить деформацию " -"детали, сохраняя при этом качество внешнего периметра. Эта функция может " -"быть очень полезна для материалов, склонных к деформации, таких как ABS/ASA, " -"а также для эластичных материалов, таких как TPU и Silk PLA. Это также может " -"помочь уменьшить деформацию нависающих над поддержкой частей.\n" +"Эта настройка значительно снижает напряжения в деталях, поскольку теперь они распределяются в чередующихся направлениях. Это должно уменьшить деформацию детали, " +"сохраняя при этом качество внешнего периметра. Эта функция может быть очень полезна для материалов, склонных к деформации, таких как ABS/ASA, а также для " +"эластичных материалов, таких как TPU и Silk PLA. Это также может помочь уменьшить деформацию нависающих над поддержкой частей.\n" "\n" -"Чтобы эта настройка была наиболее эффективной, рекомендуется установить " -"параметр «Порог для реверса» равным 0, чтобы все внутренние периметры " -"печатались в чередующихся направлениях на нечётных слоях независимо от " -"степени их нависания." +"Чтобы эта настройка была наиболее эффективной, рекомендуется установить параметр «Порог для реверса» равным 0, чтобы все внутренние периметры печатались в " +"чередующихся направлениях на нечётных слоях независимо от степени их нависания." msgid "Bridge counterbore holes" msgstr "Мост для зенкованных отверстий" msgid "" -"This option creates bridges for counterbore holes, allowing them to be " -"printed without support. Available modes include:\n" +"This option creates bridges for counterbore holes, allowing them to be printed without support. Available modes include:\n" "1. None: No bridge is created.\n" "2. Partially Bridged: Only a part of the unsupported area will be bridged.\n" "3. Sacrificial Layer: A full sacrificial bridge layer is created." msgstr "" -"Эта опция создаёт мосты для отверстий с зенковкой, позволяя печатать их без " -"поддержки. \n" +"Эта опция создаёт мосты для отверстий с зенковкой, позволяя печатать их без поддержки. \n" "Доступные режимы:\n" "1. Нет (т.е. отключено)\n" -"2. Частичный мост (мост будет построен только над частью неподдерживаемой " -"области)\n" +"2. Частичный мост (мост будет построен только над частью неподдерживаемой области)\n" "3. Жертвенный слой (создаётся полноценный жертвенный слой моста)" msgid "Partially bridged" @@ -9419,12 +8498,10 @@ msgstr "Порог разворота на свесах" #, no-c-format, no-boost-format msgid "" -"Number of mm the overhang need to be for the reversal to be considered " -"useful. Can be a % of the perimeter width.\n" +"Number of mm the overhang need to be for the reversal to be considered useful. Can be a % of the perimeter width.\n" "Value 0 enables reversal on every odd layers regardless." msgstr "" -"Величина свеса периметра при которой она считается достаточной для активации " -"функции реверса печати нависаний.\n" +"Величина свеса периметра при которой она считается достаточной для активации функции реверса печати нависаний.\n" "Может быть задано как в процентах, так и в миллиметрах от ширины периметра." msgid "Classic mode" @@ -9442,12 +8519,8 @@ msgstr "Включение динамического управления ск msgid "Slow down for curled perimeters" msgstr "Снижение скорости на изогнутых периметрах" -msgid "" -"Enable this option to slow printing down in areas where potential curled " -"perimeters may exist" -msgstr "" -"Включите эту опцию для замедления печати в тех областях, где потенциально " -"могут возникать изогнутые периметры." +msgid "Enable this option to slow printing down in areas where potential curled perimeters may exist" +msgstr "Включите эту опцию для замедления печати в тех областях, где потенциально могут возникать изогнутые периметры." msgid "mm/s or %" msgstr "мм/с или %" @@ -9464,13 +8537,10 @@ msgstr "мм/с" msgid "Internal" msgstr "Внутренние" -msgid "" -"Speed of internal bridge. If the value is expressed as a percentage, it will " -"be calculated based on the bridge_speed. Default value is 150%." +msgid "Speed of internal bridge. If the value is expressed as a percentage, it will be calculated based on the bridge_speed. Default value is 150%." msgstr "" -"Скорость печати внутреннего моста. Если задано в процентах, то значение " -"вычисляться относительно скорости внешнего моста (bridge_speed). Значение по " -"умолчанию равно 150%." +"Скорость печати внутреннего моста. Если задано в процентах, то значение вычисляться относительно скорости внешнего моста (bridge_speed). Значение по умолчанию " +"равно 150%." msgid "Brim width" msgstr "Ширина каймы" @@ -9481,20 +8551,14 @@ msgstr "Расстояние от модели до внешней линии к msgid "Brim type" msgstr "Тип каймы" -msgid "" -"This controls the generation of the brim at outer and/or inner side of " -"models. Auto means the brim width is analysed and calculated automatically." +msgid "This controls the generation of the brim at outer and/or inner side of models. Auto means the brim width is analysed and calculated automatically." msgstr "" -"Этот параметр управляет формированием каймы на внешней/внутренней стороне " -"моделей. Авто означает, что ширина каймы анализируется и рассчитывается " -"автоматически." +"Этот параметр управляет формированием каймы на внешней/внутренней стороне моделей. Авто означает, что ширина каймы анализируется и рассчитывается автоматически." msgid "Brim-object gap" msgstr "Смещение каймы" -msgid "" -"A gap between innermost brim line and object can make brim be removed more " -"easily" +msgid "A gap between innermost brim line and object can make brim be removed more easily" msgstr "Смещение каймы от печатаемой модели, может облегчить её удаление." msgid "Brim ears" @@ -9519,12 +8583,10 @@ msgid "Brim ear detection radius" msgstr "Радиус обнаружения ушек каймы" msgid "" -"The geometry will be decimated before dectecting sharp angles. This " -"parameter indicates the minimum length of the deviation for the decimation.\n" +"The geometry will be decimated before dectecting sharp angles. This parameter indicates the minimum length of the deviation for the decimation.\n" "0 to deactivate" msgstr "" -"Геометрия модели будет упрощена перед обнаружением острых углов. Этот " -"параметр задаёт минимальную длину отклонения для её упрощения.\n" +"Геометрия модели будет упрощена перед обнаружением острых углов. Этот параметр задаёт минимальную длину отклонения для её упрощения.\n" "Установите 0 для отключения." msgid "Compatible machine" @@ -9566,23 +8628,17 @@ msgid "Slow printing down for better layer cooling" msgstr "Замедлять печать для лучшего охлаждения слоёв" msgid "" -"Enable this option to slow printing speed down to make the final layer time " -"not shorter than the layer time threshold in \"Max fan speed threshold\", so " -"that layer can be cooled for longer time. This can improve the cooling " -"quality for needle and small details" +"Enable this option to slow printing speed down to make the final layer time not shorter than the layer time threshold in \"Max fan speed threshold\", so that " +"layer can be cooled for longer time. This can improve the cooling quality for needle and small details" msgstr "" -"Включите эту опцию для разрешения замедления скорости печати в зависимости " -"от времени печати слоя, чтобы слой мог охлаждаться дольше. Это позволяет " -"улучшить качество охлаждения острых концов и мелких деталей." +"Включите эту опцию для разрешения замедления скорости печати в зависимости от времени печати слоя, чтобы слой мог охлаждаться дольше. Это позволяет улучшить " +"качество охлаждения острых концов и мелких деталей." msgid "Normal printing" msgstr "Ускорение по умолчанию" -msgid "" -"The default acceleration of both normal printing and travel except initial " -"layer" -msgstr "" -"Ускорение по умолчанию для обычной печати и перемещения, кроме первого слоя." +msgid "The default acceleration of both normal printing and travel except initial layer" +msgstr "Ускорение по умолчанию для обычной печати и перемещения, кроме первого слоя." msgid "mm/s²" msgstr "мм/с²" @@ -9591,33 +8647,25 @@ msgid "Default filament profile" msgstr "Профиль прутка по умолчанию" msgid "Default filament profile when switch to this machine profile" -msgstr "" -"Профиль пластиковой нити по умолчанию при переключении на этот профиль " -"принтера." +msgstr "Профиль пластиковой нити по умолчанию при переключении на этот профиль принтера." msgid "Default process profile" msgstr "Профиль процесса по умолчанию" msgid "Default process profile when switch to this machine profile" -msgstr "" -"Профиль процесса по умолчанию при переключении на этот профиль принтера." +msgstr "Профиль процесса по умолчанию при переключении на этот профиль принтера." msgid "Activate air filtration" -msgstr "Вкл. фильтрацию воздуха" +msgstr "Вкл. вытяжной вентилятор" msgid "Activate for better air filtration. G-code command: M106 P3 S(0-255)" -msgstr "" -"Активировать для лучшей фильтрации воздуха. G-код команда: M106 P3 S(0-255)" +msgstr "Включение вытяжного вентилятора для лучшего охлаждения области внутри принтера. G-код команда: M106 P3 S(0-255)" msgid "Fan speed" msgstr "Скорость вентилятора" -msgid "" -"Speed of exhaust fan during printing.This speed will overwrite the speed in " -"filament custom gcode" -msgstr "" -"Скорость вытяжного вентилятора во время печати. Эта скорость переопределяет " -"скорость в пользовательском G-коде прутка." +msgid "Speed of exhaust fan during printing.This speed will overwrite the speed in filament custom gcode" +msgstr "Скорость вытяжного вентилятора во время печати. Эта скорость переопределяет скорость в пользовательском G-коде прутка." msgid "Speed of exhaust fan after printing completes" msgstr "Скорость вытяжного вентилятора после завершения печати" @@ -9625,105 +8673,74 @@ msgstr "Скорость вытяжного вентилятора после з msgid "No cooling for the first" msgstr "Не включать вентилятор на первых" -msgid "" -"Close all cooling fan for the first certain layers. Cooling fan of the first " -"layer used to be closed to get better build plate adhesion" +msgid "Close all cooling fan for the first certain layers. Cooling fan of the first layer used to be closed to get better build plate adhesion" msgstr "" -"Вы можете задать положительное значение, чтобы отключить все вентиляторы " -"охлаждения модели при печати первых нескольких слоёв, чтобы не ухудшить " -"адгезию к столу." +"Вы можете задать положительное значение, чтобы отключить все вентиляторы охлаждения модели при печати первых нескольких слоёв, чтобы не ухудшить адгезию к столу." msgid "Don't support bridges" msgstr "Не печатать поддержки под мостами" -msgid "" -"Don't support the whole bridge area which make support very large. Bridge " -"usually can be printing directly without support if not very long" -msgstr "" -"Опция, препятствующая печати поддержки под мостами. Мост обычно можно " -"печатать без поддержки, если он не очень длинный." +msgid "Don't support the whole bridge area which make support very large. Bridge usually can be printing directly without support if not very long" +msgstr "Опция, препятствующая печати поддержки под мостами. Мост обычно можно печатать без поддержки, если он не очень длинный." msgid "Thick bridges" msgstr "Толстые мосты" msgid "" -"If enabled, bridges are more reliable, can bridge longer distances, but may " -"look worse. If disabled, bridges look better but are reliable just for " -"shorter bridged distances." +"If enabled, bridges are more reliable, can bridge longer distances, but may look worse. If disabled, bridges look better but are reliable just for shorter " +"bridged distances." msgstr "" -"Если включено, мосты печатаются более надежные и на большие расстояния. Если " -"отключено, мосты выглядят лучше, но они надежны только на коротких " -"расстояниях." +"Если включено, мосты печатаются более надежные и на большие расстояния. Если отключено, мосты выглядят лучше, но они надежны только на коротких расстояниях." msgid "Thick internal bridges" msgstr "Толстые внутренние мосты" msgid "" -"If enabled, thick internal bridges will be used. It's usually recommended to " -"have this feature turned on. However, consider turning it off if you are " -"using large nozzles." +"If enabled, thick internal bridges will be used. It's usually recommended to have this feature turned on. However, consider turning it off if you are using large " +"nozzles." msgstr "" -"Если включено, будут использоваться толстые внутренние мосты. Обычно " -"рекомендуется включить эту функцию. Однако при использовании сопел больших " -"диаметров рекомендуется отключить эту опцию." +"Если включено, будут использоваться толстые внутренние мосты. Обычно рекомендуется включить эту функцию. Однако при использовании сопел больших диаметров " +"рекомендуется отключить эту опцию." msgid "Don't filter out small internal bridges (beta)" msgstr "Не отфильтровать небольшие внутренние мосты (beta)" msgid "" -"This option can help reducing pillowing on top surfaces in heavily slanted " -"or curved models.\n" +"This option can help reducing pillowing on top surfaces in heavily slanted or curved models.\n" "\n" -"By default, small internal bridges are filtered out and the internal solid " -"infill is printed directly over the sparse infill. This works well in most " -"cases, speeding up printing without too much compromise on top surface " -"quality. \n" +"By default, small internal bridges are filtered out and the internal solid infill is printed directly over the sparse infill. This works well in most cases, " +"speeding up printing without too much compromise on top surface quality. \n" "\n" -"However, in heavily slanted or curved models especially where too low sparse " -"infill density is used, this may result in curling of the unsupported solid " -"infill, causing pillowing.\n" +"However, in heavily slanted or curved models especially where too low sparse infill density is used, this may result in curling of the unsupported solid infill, " +"causing pillowing.\n" "\n" -"Enabling this option will print internal bridge layer over slightly " -"unsupported internal solid infill. The options below control the amount of " -"filtering, i.e. the amount of internal bridges created.\n" +"Enabling this option will print internal bridge layer over slightly unsupported internal solid infill. The options below control the amount of filtering, i.e. " +"the amount of internal bridges created.\n" "\n" -"Disabled - Disables this option. This is the default behaviour and works " -"well in most cases.\n" +"Disabled - Disables this option. This is the default behaviour and works well in most cases.\n" "\n" -"Limited filtering - Creates internal bridges on heavily slanted surfaces, " -"while avoiding creating uncessesary interal bridges. This works well for " -"most difficult models.\n" +"Limited filtering - Creates internal bridges on heavily slanted surfaces, while avoiding creating uncessesary interal bridges. This works well for most difficult " +"models.\n" "\n" -"No filtering - Creates internal bridges on every potential internal " -"overhang. This option is useful for heavily slanted top surface models. " -"However, in most cases it creates too many unecessary bridges." +"No filtering - Creates internal bridges on every potential internal overhang. This option is useful for heavily slanted top surface models. However, in most " +"cases it creates too many unecessary bridges." msgstr "" -"Эта опция может помочь уменьшить образование эффекта «дырявой подушки» на " -"верхних сильно наклонных поверхностях или изогнутых моделях.\n" +"Эта опция может помочь уменьшить образование эффекта «дырявой подушки» на верхних сильно наклонных поверхностях или изогнутых моделях.\n" "\n" -"По умолчанию, маленькие внутренние мосты фильтруются и внутреннее сплошное " -"заполнение печатается непосредственно поверх разреженного заполнения. В " -"большинстве случаев это хорошо работает, ускоряя печать без особого ущерба " -"для качества верхней поверхности. Однако, на сильно наклонных поверхностях " -"или изогнутых моделях, особенно при низкой плотности заполнения, это может " -"привести к скручиванию неподдерживаемого сплошного заполнения и образованию " -"эффекта «дырявой подушки».\n" +"По умолчанию, маленькие внутренние мосты фильтруются и внутреннее сплошное заполнение печатается непосредственно поверх разреженного заполнения. В большинстве " +"случаев это хорошо работает, ускоряя печать без особого ущерба для качества верхней поверхности. Однако, на сильно наклонных поверхностях или изогнутых моделях, " +"особенно при низкой плотности заполнения, это может привести к скручиванию неподдерживаемого сплошного заполнения и образованию эффекта «дырявой подушки».\n" "\n" -"Включение позволит печатать слой внутреннего моста над слабо поддерживаемым " -"внутренним сплошным заполнением. Приведённые ниже параметры управляют " -"степенью фильтрации, т.е. количеством создаваемых внутренних мостов.\n" +"Включение позволит печатать слой внутреннего моста над слабо поддерживаемым внутренним сплошным заполнением. Приведённые ниже параметры управляют степенью " +"фильтрации, т.е. количеством создаваемых внутренних мостов.\n" "\n" -"Отключение - отключает эту опцию. Это задано по умолчанию и в большинстве " -"случаев работает хорошо.\n" +"Отключение - отключает эту опцию. Это задано по умолчанию и в большинстве случаев работает хорошо.\n" "\n" -"Ограниченная фильтрация - создаёт внутренние мосты на сильно наклонных " -"поверхностях, при этом избегая создания ненужных внутренних мостов. Это " -"хорошо работает на большинстве сложных моделях.\n" +"Ограниченная фильтрация - создаёт внутренние мосты на сильно наклонных поверхностях, при этом избегая создания ненужных внутренних мостов. Это хорошо работает на " +"большинстве сложных моделях.\n" "\n" -"Без фильтрации - мосты создаются над каждым потенциально внутреннем " -"нависании. Этот вариант полезен для моделей с сильно наклонной верхней " -"поверхностью. Однако в большинстве случаев этот вариант создаёт слишком " -"много ненужных мостов." +"Без фильтрации - мосты создаются над каждым потенциально внутреннем нависании. Этот вариант полезен для моделей с сильно наклонной верхней поверхностью. Однако в " +"большинстве случаев этот вариант создаёт слишком много ненужных мостов." msgid "Disabled" msgstr "Отключено" @@ -9738,13 +8755,11 @@ msgid "Max bridge length" msgstr "Максимальная длина моста" msgid "" -"Max length of bridges that don't need support. Set it to 0 if you want all " -"bridges to be supported, and set it to a very large value if you don't want " -"any bridges to be supported." +"Max length of bridges that don't need support. Set it to 0 if you want all bridges to be supported, and set it to a very large value if you don't want any " +"bridges to be supported." msgstr "" -"Максимальная длина мостов, не нуждающихся в поддержке. Установите 0, если " -"требуется поддержка всех мостов, или очень большое значение, если поддержка " -"мостов не требуется." +"Максимальная длина мостов, не нуждающихся в поддержке. Установите 0, если требуется поддержка всех мостов, или очень большое значение, если поддержка мостов не " +"требуется." msgid "End G-code" msgstr "Завершающий G-код" @@ -9755,12 +8770,8 @@ msgstr "Завершающий G-код при окончании всей пе msgid "Between Object Gcode" msgstr "G-код выполняемый между моделями" -msgid "" -"Insert Gcode between objects. This parameter will only come into effect when " -"you print your models object by object" -msgstr "" -"G-код выполняемый между моделями. Этот код будет действовать только при " -"печати моделей «По очереди»." +msgid "Insert Gcode between objects. This parameter will only come into effect when you print your models object by object" +msgstr "G-код выполняемый между моделями. Этот код будет действовать только при печати моделей «По очереди»." msgid "End G-code when finish the printing of this filament" msgstr "Завершающий G-код при окончании печати этой пластиковой нитью." @@ -9770,25 +8781,19 @@ msgstr "Обеспечивать верт. толщину оболочки" # ??? msgid "" -"Add solid infill near sloping surfaces to guarantee the vertical shell " -"thickness (top+bottom solid layers)\n" -"None: No solid infill will be added anywhere. Caution: Use this option " -"carefully if your model has sloped surfaces\n" +"Add solid infill near sloping surfaces to guarantee the vertical shell thickness (top+bottom solid layers)\n" +"None: No solid infill will be added anywhere. Caution: Use this option carefully if your model has sloped surfaces\n" "Critical Only: Avoid adding solid infill for walls\n" "Moderate: Add solid infill for heavily sloping surfaces only\n" "All: Add solid infill for all suitable sloping surfaces\n" "Default value is All." msgstr "" -"Добавление сплошного заполнения вблизи наклонных поверхностей для " -"обеспечения вертикальной толщины оболочки (верхний+нижний сплошные слои).\n" +"Добавление сплошного заполнения вблизи наклонных поверхностей для обеспечения вертикальной толщины оболочки (верхний+нижний сплошные слои).\n" "\n" -"Нет - сплошное заполнение нигде не будет добавляться. Внимание: если ваша " -"модель имеет наклонные поверхности, подумайте стоит ли выбирать эту опцию.\n" +"Нет - сплошное заполнение нигде не будет добавляться. Внимание: если ваша модель имеет наклонные поверхности, подумайте стоит ли выбирать эту опцию.\n" "Только критические - избегать добавления сплошного заполнения для стен.\n" -"Умеренное - добавление сплошного заполнения только для сильно наклонных " -"поверхностей.\n" -"Везде - добавление сплошного заполнения для всех подходящих наклонных " -"поверхностей.\n" +"Умеренное - добавление сплошного заполнения только для сильно наклонных поверхностей.\n" +"Везде - добавление сплошного заполнения для всех подходящих наклонных поверхностей.\n" "Значение по умолчанию - Везде." msgid "Critical Only" @@ -9836,49 +8841,32 @@ msgstr "Шаблон заполнения нижней поверхности, msgid "Internal solid infill pattern" msgstr "Шаблон сплошного заполнения" -msgid "" -"Line pattern of internal solid infill. if the detect narrow internal solid " -"infill be enabled, the concentric pattern will be used for the small area." +msgid "Line pattern of internal solid infill. if the detect narrow internal solid infill be enabled, the concentric pattern will be used for the small area." msgstr "" -"Шаблон печати внутреннего сплошного заполнения. Если включена функция " -"«Обнаруживать узкую область сплошного заполнения», то для небольшой области " -"будет использоваться концентрический шаблон заполнения." +"Шаблон печати внутреннего сплошного заполнения. Если включена функция «Обнаруживать узкую область сплошного заполнения», то для небольшой области будет " +"использоваться концентрический шаблон заполнения." -msgid "" -"Line width of outer wall. If expressed as a %, it will be computed over the " -"nozzle diameter." -msgstr "" -"Ширина экструзии для внешнего периметра. Если задано в процентах, то " -"значение вычисляться относительно диаметра сопла." +msgid "Line width of outer wall. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для внешнего периметра. Если задано в процентах, то значение вычисляться относительно диаметра сопла." -msgid "" -"Speed of outer wall which is outermost and visible. It's used to be slower " -"than inner wall speed to get better quality." -msgstr "" -"Скорость печати внешнего периметра (видимого). Для улучшения качества, эту " -"скорость делают ниже скорости внутренних периметров." +msgid "Speed of outer wall which is outermost and visible. It's used to be slower than inner wall speed to get better quality." +msgstr "Скорость печати внешнего периметра (видимого). Для улучшения качества, эту скорость делают ниже скорости внутренних периметров." msgid "Small perimeters" msgstr "Маленькие периметры" msgid "" -"This separate setting will affect the speed of perimeters having radius <= " -"small_perimeter_threshold (usually holes). If expressed as percentage (for " -"example: 80%) it will be calculated on the outer wall speed setting above. " -"Set to zero for auto." +"This separate setting will affect the speed of perimeters having radius <= small_perimeter_threshold (usually holes). If expressed as percentage (for example: " +"80%) it will be calculated on the outer wall speed setting above. Set to zero for auto." msgstr "" -"Этот параметр влияет на скорость печати периметров, имеющих радиус <= " -"значению порога маленьких периметров (обычно это отверстия). Если задано в " -"процентах, параметр вычисляется относительно скорости печати внешнего " -"периметра указанного выше. Установите 0 для автонастройки." +"Этот параметр влияет на скорость печати периметров, имеющих радиус <= значению порога маленьких периметров (обычно это отверстия). Если задано в процентах, " +"параметр вычисляется относительно скорости печати внешнего периметра указанного выше. Установите 0 для автонастройки." msgid "Small perimeters threshold" msgstr "Порог маленьких периметров" -msgid "" -"This sets the threshold for small perimeter length. Default threshold is 0mm" -msgstr "" -"Пороговое значение длины маленьких периметров. Значение по умолчанию - 0 мм." +msgid "This sets the threshold for small perimeter length. Default threshold is 0mm" +msgstr "Пороговое значение длины маленьких периметров. Значение по умолчанию - 0 мм." msgid "Walls printing order" msgstr "Порядок печати периметров" @@ -9886,48 +8874,33 @@ msgstr "Порядок печати периметров" msgid "" "Print sequence of the internal (inner) and external (outer) walls. \n" "\n" -"Use Inner/Outer for best overhangs. This is because the overhanging walls " -"can adhere to a neighouring perimeter while printing. However, this option " -"results in slightly reduced surface quality as the external perimeter is " -"deformed by being squashed to the internal perimeter.\n" +"Use Inner/Outer for best overhangs. This is because the overhanging walls can adhere to a neighouring perimeter while printing. However, this option results in " +"slightly reduced surface quality as the external perimeter is deformed by being squashed to the internal perimeter.\n" "\n" -"Use Inner/Outer/Inner for the best external surface finish and dimensional " -"accuracy as the external wall is printed undisturbed from an internal " -"perimeter. However, overhang performance will reduce as there is no internal " -"perimeter to print the external wall against. This option requires a minimum " -"of 3 walls to be effective as it prints the internal walls from the 3rd " -"perimeter onwards first, then the external perimeter and, finally, the first " -"internal perimeter. This option is recomended against the Outer/Inner option " -"in most cases. \n" +"Use Inner/Outer/Inner for the best external surface finish and dimensional accuracy as the external wall is printed undisturbed from an internal perimeter. " +"However, overhang performance will reduce as there is no internal perimeter to print the external wall against. This option requires a minimum of 3 walls to be " +"effective as it prints the internal walls from the 3rd perimeter onwards first, then the external perimeter and, finally, the first internal perimeter. This " +"option is recomended against the Outer/Inner option in most cases. \n" "\n" -"Use Outer/Inner for the same external wall quality and dimensional accuracy " -"benefits of Inner/Outer/Inner option. However, the z seams will appear less " -"consistent as the first extrusion of a new layer starts on a visible " -"surface.\n" +"Use Outer/Inner for the same external wall quality and dimensional accuracy benefits of Inner/Outer/Inner option. However, the z seams will appear less " +"consistent as the first extrusion of a new layer starts on a visible surface.\n" "\n" " " msgstr "" "Последовательность печати внутреннего/внешнего периметров.\n" "\n" -"Используйте порядок печати периметров «Внутренний/Внешний» для получения " -"наилучших нависаний. Однако этот вариант приводит к небольшому снижению " -"качества внешней поверхности.\n" +"Используйте порядок печати периметров «Внутренний/Внешний» для получения наилучших нависаний. Однако этот вариант приводит к небольшому снижению качества внешней " +"поверхности.\n" "\n" -"Используйте порядок печати периметров «Внутренний/Внешний/Внутренний» для " -"получения наилучшего качества внешней поверхности и точности размеров, так " -"как внешний периметр печатается без помех со стороны внутреннего периметра. " -"Однако при этом снижается качество печати нависаний, поскольку отсутствует " -"внутренний периметр к которому прикрепляется внешний. Для этого варианта " -"требуется минимум 3 периметра, так как сначала печатаются внутренние " -"периметры, начиная с 3-го периметра, затем внешний периметр и, наконец, " -"первый внутренний периметр. В большинстве случаев этот вариант рекомендуется " -"использовать вместо варианта «Внешний/Внутренний». \n" +"Используйте порядок печати периметров «Внутренний/Внешний/Внутренний» для получения наилучшего качества внешней поверхности и точности размеров, так как внешний " +"периметр печатается без помех со стороны внутреннего периметра. Однако при этом снижается качество печати нависаний, поскольку отсутствует внутренний периметр к " +"которому прикрепляется внешний. Для этого варианта требуется минимум 3 периметра, так как сначала печатаются внутренние периметры, начиная с 3-го периметра, " +"затем внешний периметр и, наконец, первый внутренний периметр. В большинстве случаев этот вариант рекомендуется использовать вместо варианта «Внешний/" +"Внутренний». \n" "\n" -"Используйте порядок печати периметров «Внешний/Внутренний», чтобы получить " -"то же качество внешних периметров и точность размеров, что и при " -"использовании варианта «Внутренний/Внешний/Внутренний». Однако, поскольку " -"первая экструзия нового слоя начинается на видимой поверхности, швы по оси Z " -"будут выглядеть менее равномерными." +"Используйте порядок печати периметров «Внешний/Внутренний», чтобы получить то же качество внешних периметров и точность размеров, что и при использовании " +"варианта «Внутренний/Внешний/Внутренний». Однако, поскольку первая экструзия нового слоя начинается на видимой поверхности, швы по оси Z будут выглядеть менее " +"равномерными." msgid "Inner/Outer" msgstr "Внутренний/Внешний" @@ -9942,45 +8915,33 @@ msgid "Print infill first" msgstr "Сначала печатать заполнение" msgid "" -"Order of wall/infill. When the tickbox is unchecked the walls are printed " -"first, which works best in most cases.\n" +"Order of wall/infill. When the tickbox is unchecked the walls are printed first, which works best in most cases.\n" "\n" -"Printing walls first may help with extreme overhangs as the walls have the " -"neighbouring infill to adhere to. However, the infill will slighly push out " -"the printed walls where it is attached to them, resulting in a worse " -"external surface finish. It can also cause the infill to shine through the " -"external surfaces of the part." +"Printing walls first may help with extreme overhangs as the walls have the neighbouring infill to adhere to. However, the infill will slighly push out the " +"printed walls where it is attached to them, resulting in a worse external surface finish. It can also cause the infill to shine through the external surfaces of " +"the part." msgstr "" -"Последовательность печати периметров/заполнения. Когда отключено, сначала " -"печатаются периметры, что в большинстве случаев работает лучше всего.\n" +"Последовательность печати периметров/заполнения. Когда отключено, сначала печатаются периметры, что в большинстве случаев работает лучше всего.\n" "\n" -"Печать периметров первыми может помочь при экстремальных нависаниях, " -"поскольку периметры должны прилегать к соседнему заполнению. Однако в этом " -"случае последующее заполнение будет слегка выдавливать напечатанные " -"периметры в местах примыкания к ним, что приводит к ухудшению качества " -"внешней поверхности. Кроме того, это может приводить к тому, что заполнение " -"будет просвечиваться через внешнюю поверхность детали." +"Печать периметров первыми может помочь при экстремальных нависаниях, поскольку периметры должны прилегать к соседнему заполнению. Однако в этом случае " +"последующее заполнение будет слегка выдавливать напечатанные периметры в местах примыкания к ним, что приводит к ухудшению качества внешней поверхности. Кроме " +"того, это может приводить к тому, что заполнение будет просвечиваться через внешнюю поверхность детали." msgid "Wall loop direction" msgstr "Направление петель периметров" msgid "" -"The direction which the wall loops are extruded when looking down from the " -"top.\n" +"The direction which the wall loops are extruded when looking down from the top.\n" "\n" -"By default all walls are extruded in counter-clockwise, unless Reverse on " -"odd is enabled. Set this to any option other than Auto will force the wall " -"direction regardless of the Reverse on odd.\n" +"By default all walls are extruded in counter-clockwise, unless Reverse on odd is enabled. Set this to any option other than Auto will force the wall direction " +"regardless of the Reverse on odd.\n" "\n" "This option will be disabled if sprial vase mode is enabled." msgstr "" -"Направление, в котором выдавливаются петли периметров при взгляде сверху " -"вниз.\n" +"Направление, в котором выдавливаются петли периметров при взгляде сверху вниз.\n" "\n" -"По умолчанию все периметры выдавливаются против часовой стрелки, если не " -"включена опция «Реверс на нависаниях». При установке этого параметра в " -"значение, отличное от автоматического, направление периметров будет " -"задаваться независимо от опция «Реверс на нависаниях».\n" +"По умолчанию все периметры выдавливаются против часовой стрелки, если не включена опция «Реверс на нависаниях». При установке этого параметра в значение, " +"отличное от автоматического, направление периметров будет задаваться независимо от опция «Реверс на нависаниях».\n" "\n" "Эта опция будет отключена, если включен режим спиральной вазы." @@ -9993,105 +8954,65 @@ msgstr "По часовой стрелке" msgid "Height to rod" msgstr "Высота до вала" -msgid "" -"Distance of the nozzle tip to the lower rod. Used for collision avoidance in " -"by-object printing." -msgstr "" -"Расстояние от кончика сопла до нижнего вала. Значение важно при печати " -"моделей «По очереди» для предотвращения столкновений." +msgid "Distance of the nozzle tip to the lower rod. Used for collision avoidance in by-object printing." +msgstr "Расстояние от кончика сопла до нижнего вала. Значение важно при печати моделей «По очереди» для предотвращения столкновений." msgid "Height to lid" msgstr "Высота до крышки" -msgid "" -"Distance of the nozzle tip to the lid. Used for collision avoidance in by-" -"object printing." -msgstr "" -"Расстояние от кончика сопла до крышки. Значение важно при печати моделей «По " -"очереди» для предотвращения столкновений." +msgid "Distance of the nozzle tip to the lid. Used for collision avoidance in by-object printing." +msgstr "Расстояние от кончика сопла до крышки. Значение важно при печати моделей «По очереди» для предотвращения столкновений." -msgid "" -"Clearance radius around extruder. Used for collision avoidance in by-object " -"printing." -msgstr "" -"Безопасное расстояние вокруг экструдера. Используется для предотвращения " -"столкновений при печати отдельно стоящих моделей." +msgid "Clearance radius around extruder. Used for collision avoidance in by-object printing." +msgstr "Безопасное расстояние вокруг экструдера. Используется для предотвращения столкновений при печати отдельно стоящих моделей." msgid "Bed mesh min" msgstr "Мин. сетка стола" msgid "" -"This option sets the min point for the allowed bed mesh area. Due to the " -"probe's XY offset, most printers are unable to probe the entire bed. To " -"ensure the probe point does not go outside the bed area, the minimum and " -"maximum points of the bed mesh should be set appropriately. OrcaSlicer " -"ensures that adaptive_bed_mesh_min/adaptive_bed_mesh_max values do not " -"exceed these min/max points. This information can usually be obtained from " -"your printer manufacturer. The default setting is (-99999, -99999), which " -"means there are no limits, thus allowing probing across the entire bed." +"This option sets the min point for the allowed bed mesh area. Due to the probe's XY offset, most printers are unable to probe the entire bed. To ensure the probe " +"point does not go outside the bed area, the minimum and maximum points of the bed mesh should be set appropriately. OrcaSlicer ensures that adaptive_bed_mesh_min/" +"adaptive_bed_mesh_max values do not exceed these min/max points. This information can usually be obtained from your printer manufacturer. The default setting is " +"(-99999, -99999), which means there are no limits, thus allowing probing across the entire bed." msgstr "" -"Этот параметр устанавливает минимальную точку для допустимой области сетки " -"стола. Большинство принтеров из-за смещения датчика по оси XY не могут " -"производить зондирование всей площади стола. Чтобы точка зондирования не " -"выходила за пределы области стола, нужно правильно задать эти минимальные и " -"максимальные точки. OrcaSlicer следит за тем, чтобы значения " -"adaptive_bed_mesh_min/adaptive_bed_mesh_max не превышают эти минимальные/" -"максимальные значения. Эту информацию можно получить у производителя " -"принтера. По умолчанию установлено значение (-99999, -99999), которое " -"означает отсутствие ограничений, что позволяет проводить зондирование по " -"всему столу." +"Этот параметр устанавливает минимальную точку для допустимой области сетки стола. Большинство принтеров из-за смещения датчика по оси XY не могут производить " +"зондирование всей площади стола. Чтобы точка зондирования не выходила за пределы области стола, нужно правильно задать эти минимальные и максимальные точки. " +"OrcaSlicer следит за тем, чтобы значения adaptive_bed_mesh_min/adaptive_bed_mesh_max не превышают эти минимальные/максимальные значения. Эту информацию можно " +"получить у производителя принтера. По умолчанию установлено значение (-99999, -99999), которое означает отсутствие ограничений, что позволяет проводить " +"зондирование по всему столу." msgid "Bed mesh max" msgstr "Макс. сетка стола" msgid "" -"This option sets the max point for the allowed bed mesh area. Due to the " -"probe's XY offset, most printers are unable to probe the entire bed. To " -"ensure the probe point does not go outside the bed area, the minimum and " -"maximum points of the bed mesh should be set appropriately. OrcaSlicer " -"ensures that adaptive_bed_mesh_min/adaptive_bed_mesh_max values do not " -"exceed these min/max points. This information can usually be obtained from " -"your printer manufacturer. The default setting is (99999, 99999), which " -"means there are no limits, thus allowing probing across the entire bed." +"This option sets the max point for the allowed bed mesh area. Due to the probe's XY offset, most printers are unable to probe the entire bed. To ensure the probe " +"point does not go outside the bed area, the minimum and maximum points of the bed mesh should be set appropriately. OrcaSlicer ensures that adaptive_bed_mesh_min/" +"adaptive_bed_mesh_max values do not exceed these min/max points. This information can usually be obtained from your printer manufacturer. The default setting is " +"(99999, 99999), which means there are no limits, thus allowing probing across the entire bed." msgstr "" -"Этот параметр устанавливает максимальную точку для допустимой области сетки " -"стола. Большинство принтеров из-за смещения датчика по оси XY не могут " -"производить зондирование всей площади стола. Чтобы точка зондирования не " -"выходила за пределы области стола, нужно правильно задать эти минимальные и " -"максимальные точки. OrcaSlicer следит за тем, чтобы значения " -"adaptive_bed_mesh_min/adaptive_bed_mesh_max не превышают эти минимальные/" -"максимальные значения. Эту информацию можно получить у производителя " -"принтера. По умолчанию установлено значение (-99999, -99999), которое " -"означает отсутствие ограничений, что позволяет проводить зондирование по " -"всему столу." +"Этот параметр устанавливает максимальную точку для допустимой области сетки стола. Большинство принтеров из-за смещения датчика по оси XY не могут производить " +"зондирование всей площади стола. Чтобы точка зондирования не выходила за пределы области стола, нужно правильно задать эти минимальные и максимальные точки. " +"OrcaSlicer следит за тем, чтобы значения adaptive_bed_mesh_min/adaptive_bed_mesh_max не превышают эти минимальные/максимальные значения. Эту информацию можно " +"получить у производителя принтера. По умолчанию установлено значение (-99999, -99999), которое означает отсутствие ограничений, что позволяет проводить " +"зондирование по всему столу." msgid "Probe point distance" msgstr "Расстояние между точками зондирования" -msgid "" -"This option sets the preferred distance between probe points (grid size) for " -"the X and Y directions, with the default being 50mm for both X and Y." -msgstr "" -"Этот параметр задаёт расстояние между точками зондирования (размер сетки) в " -"направлениях XY. По умолчанию оно равно 50 мм как для X, так и для Y." +msgid "This option sets the preferred distance between probe points (grid size) for the X and Y directions, with the default being 50mm for both X and Y." +msgstr "Этот параметр задаёт расстояние между точками зондирования (размер сетки) в направлениях XY. По умолчанию оно равно 50 мм как для X, так и для Y." msgid "Mesh margin" msgstr "Граница сетки" -msgid "" -"This option determines the additional distance by which the adaptive bed " -"mesh area should be expanded in the XY directions." -msgstr "" -"Этот параметр определяет дополнительное расстояние, на которое должна быть " -"расширена адаптивная сетка стола в направлениях XY." +msgid "This option determines the additional distance by which the adaptive bed mesh area should be expanded in the XY directions." +msgstr "Этот параметр определяет дополнительное расстояние, на которое должна быть расширена адаптивная сетка стола в направлениях XY." msgid "Extruder Color" msgstr "Цвет экструдера" msgid "Only used as a visual help on UI" -msgstr "" -"Используется только в качестве визуальной помощи в пользовательском " -"интерфейсе" +msgstr "Используется только в качестве визуальной помощи в пользовательском интерфейсе" msgid "Extruder offset" msgstr "Смещение экструдера по осям X/Y" @@ -10100,63 +9021,44 @@ msgid "Flow ratio" msgstr "Коэффициент потока" msgid "" -"The material may have volumetric change after switching between molten state " -"and crystalline state. This setting changes all extrusion flow of this " -"filament in gcode proportionally. Recommended value range is between 0.95 " -"and 1.05. Maybe you can tune this value to get nice flat surface when there " -"has slight overflow or underflow" +"The material may have volumetric change after switching between molten state and crystalline state. This setting changes all extrusion flow of this filament in " +"gcode proportionally. Recommended value range is between 0.95 and 1.05. Maybe you can tune this value to get nice flat surface when there has slight overflow or " +"underflow" msgstr "" -"Коэффициент пропорционального изменения величины потока подаваемого " -"пластика. Рекомендуемый диапазон значений от 0,95 до 1,05.\n" -"При небольшом переливе или недоливе на поверхности, корректировка этого " -"параметра поможет получить хорошую гладкую поверхность." +"Коэффициент пропорционального изменения величины потока подаваемого пластика. Рекомендуемый диапазон значений от 0,95 до 1,05.\n" +"При небольшом переливе или недоливе на поверхности, корректировка этого параметра поможет получить хорошую гладкую поверхность." msgid "Enable pressure advance" msgstr "Включить Pressure advance" -msgid "" -"Enable pressure advance, auto calibration result will be overwriten once " -"enabled." -msgstr "" -"Включить Pressure advance (Прогнозирование давления). Результат " -"автокалибровки будет перезаписан после включения." +msgid "Enable pressure advance, auto calibration result will be overwriten once enabled." +msgstr "Включить Pressure advance (Прогнозирование давления). Результат автокалибровки будет перезаписан после включения." msgid "Pressure advance(Klipper) AKA Linear advance factor(Marlin)" -msgstr "" -"Pressure advance (Прогнозирование давления) в прошивки Klipper, это одно и " -"тоже что Linear advance в прошивке Marlin." +msgstr "Pressure advance (Прогнозирование давления) в прошивки Klipper, это одно и тоже что Linear advance в прошивке Marlin." -msgid "" -"Default line width if other line widths are set to 0. If expressed as a %, " -"it will be computed over the nozzle diameter." +msgid "Default line width if other line widths are set to 0. If expressed as a %, it will be computed over the nozzle diameter." msgstr "" -"Ширина экструзии по умолчанию, если какие-либо из значений ширины экструзии " -"установлены равные нулю. Если задано в процентах, то значение вычисляться " +"Ширина экструзии по умолчанию, если какие-либо из значений ширины экструзии установлены равные нулю. Если задано в процентах, то значение вычисляться " "относительно диаметра сопла." msgid "Keep fan always on" msgstr "Вентилятор включён всегда" -msgid "" -"If enable this setting, part cooling fan will never be stoped and will run " -"at least at minimum speed to reduce the frequency of starting and stoping" +msgid "If enable this setting, part cooling fan will never be stoped and will run at least at minimum speed to reduce the frequency of starting and stoping" msgstr "" -"Если включено, вентилятор охлаждения модели никогда не будет останавливаться " -"и будет работать на минимальной скорости, чтобы сократить частоту его " -"запуска и остановки." +"Если включено, вентилятор охлаждения модели никогда не будет останавливаться и будет работать на минимальной скорости, чтобы сократить частоту его запуска и " +"остановки." msgid "Layer time" msgstr "Время слоя" msgid "" -"Part cooling fan will be enabled for layers of which estimated time is " -"shorter than this value. Fan speed is interpolated between the minimum and " -"maximum fan speeds according to layer printing time" +"Part cooling fan will be enabled for layers of which estimated time is shorter than this value. Fan speed is interpolated between the minimum and maximum fan " +"speeds according to layer printing time" msgstr "" -"Вентилятор охлаждения моделей будет включён для слоёв, расчётное время " -"которых меньше этого значения. Скорость вентилятора интерполируется между " -"минимальной и максимальной скоростями вентилятора зависимости от времени " -"печати слоя." +"Вентилятор охлаждения моделей будет включён для слоёв, расчётное время которых меньше этого значения. Скорость вентилятора интерполируется между минимальной и " +"максимальной скоростями вентилятора зависимости от времени печати слоя." msgid "Default color" msgstr "Цвет по умолчанию" @@ -10173,22 +9075,15 @@ msgstr "Здесь вы можете написать свои замечани msgid "Required nozzle HRC" msgstr "Необходимая твёрдость сопла" -msgid "" -"Minimum HRC of nozzle required to print the filament. Zero means no checking " -"of nozzle's HRC." -msgstr "" -"Минимальная твёрдость материала сопла (HRC), необходимая для печати " -"пластиковой нитью. 0 - отключение контроля сопел на твёрдость." +msgid "Minimum HRC of nozzle required to print the filament. Zero means no checking of nozzle's HRC." +msgstr "Минимальная твёрдость материала сопла (HRC), необходимая для печати пластиковой нитью. 0 - отключение контроля сопел на твёрдость." msgid "" -"This setting stands for how much volume of filament can be melted and " -"extruded per second. Printing speed is limited by max volumetric speed, in " -"case of too high and unreasonable speed setting. Can't be zero" +"This setting stands for how much volume of filament can be melted and extruded per second. Printing speed is limited by max volumetric speed, in case of too high " +"and unreasonable speed setting. Can't be zero" msgstr "" -"Этот параметр определяет, какой объём материала может быть расплавлен и " -"выдавлен в секунду. Скорость печати ограничена максимальной объёмной " -"скоростью в случае слишком высокой и необоснованной установки скорости. " -"Параметр не может быть нулевым." +"Этот параметр определяет, какой объём материала может быть расплавлен и выдавлен в секунду. Скорость печати ограничена максимальной объёмной скоростью в случае " +"слишком высокой и необоснованной установки скорости. Параметр не может быть нулевым." msgid "mm³/s" msgstr "мм³/с" @@ -10197,41 +9092,29 @@ msgid "Filament load time" msgstr "Время загрузки прутка" msgid "Time to load new filament when switch filament. For statistics only" -msgstr "" -"Время загрузки новой пластиковой нити при её смене. Только для статистики." +msgstr "Время загрузки новой пластиковой нити при её смене. Только для статистики." msgid "Filament unload time" msgstr "Время выгрузки прутка" msgid "Time to unload old filament when switch filament. For statistics only" -msgstr "" -"Время выгрузки старой пластиковой нити при её смене. Только для статистики." +msgstr "Время выгрузки старой пластиковой нити при её смене. Только для статистики." -msgid "" -"Filament diameter is used to calculate extrusion in gcode, so it's important " -"and should be accurate" -msgstr "" -"Диаметр пластиковой нити используется для расчёта экструзии, поэтому он " -"важен и должен быть точным" +msgid "Filament diameter is used to calculate extrusion in gcode, so it's important and should be accurate" +msgstr "Диаметр пластиковой нити используется для расчёта экструзии, поэтому он важен и должен быть точным" msgid "Shrinkage" msgstr "Усадка материала" #, no-c-format, no-boost-format msgid "" -"Enter the shrinkage percentage that the filament will get after cooling (94% " -"if you measure 94mm instead of 100mm). The part will be scaled in xy to " -"compensate. Only the filament used for the perimeter is taken into account.\n" -"Be sure to allow enough space between objects, as this compensation is done " -"after the checks." +"Enter the shrinkage percentage that the filament will get after cooling (94% if you measure 94mm instead of 100mm). The part will be scaled in xy to compensate. " +"Only the filament used for the perimeter is taken into account.\n" +"Be sure to allow enough space between objects, as this compensation is done after the checks." msgstr "" -"Введите процент усадки пластиковой нити, которую получит она после " -"охлаждения (пишите 94%, если вы намерили 94 мм, вместо 100 мм). Для " -"компенсации усадки деталь будет отмасштабированна по оси XY. При этом " -"учитывается только пластиковая нить, используемая для печати внешнего " -"\"периметра.\n" -"Убедитесь, что между моделями достаточно места, так как эта компенсация " -"выполняется после проверок." +"Введите процент усадки пластиковой нити, которую получит она после охлаждения (пишите 94%, если вы намерили 94 мм, вместо 100 мм). Для компенсации усадки деталь " +"будет отмасштабированна по оси XY. При этом учитывается только пластиковая нить, используемая для печати внешнего \"периметра.\n" +"Убедитесь, что между моделями достаточно места, так как эта компенсация выполняется после проверок." msgid "Loading speed" msgstr "Скорость загрузки" @@ -10248,41 +9131,30 @@ msgstr "Скорость в начальной фазе загрузки пру msgid "Unloading speed" msgstr "Скорость выгрузки" -msgid "" -"Speed used for unloading the filament on the wipe tower (does not affect " -"initial part of unloading just after ramming)." -msgstr "" -"Скорость выгрузки прутка на черновую башню. (не влияет на начальную фазу " -"выгрузки сразу после рэмминга)." +msgid "Speed used for unloading the filament on the wipe tower (does not affect initial part of unloading just after ramming)." +msgstr "Скорость выгрузки прутка на черновую башню. (не влияет на начальную фазу выгрузки сразу после рэмминга)." msgid "Unloading speed at the start" msgstr "Начальная скорость выгрузки" -msgid "" -"Speed used for unloading the tip of the filament immediately after ramming." +msgid "Speed used for unloading the tip of the filament immediately after ramming." msgstr "Скорость выгрузки кончика прутка сразу после рэмминга." msgid "Delay after unloading" msgstr "Задержка после выгрузки" msgid "" -"Time to wait after the filament is unloaded. May help to get reliable " -"toolchanges with flexible materials that may need more time to shrink to " -"original dimensions." +"Time to wait after the filament is unloaded. May help to get reliable toolchanges with flexible materials that may need more time to shrink to original " +"dimensions." msgstr "" -"Время ожидания после выгрузки прутка. Это может помочь вам легко сменить " -"сопло при печати гибкими материалами, которым требуется больше времени, " -"чтобы вернуться к своим первоначальным размерам." +"Время ожидания после выгрузки прутка. Это может помочь вам легко сменить сопло при печати гибкими материалами, которым требуется больше времени, чтобы вернуться " +"к своим первоначальным размерам." msgid "Number of cooling moves" msgstr "Количество охлаждающих движений" -msgid "" -"Filament is cooled by being moved back and forth in the cooling tubes. " -"Specify desired number of these moves." -msgstr "" -"Пруток охлаждается в охлаждающих трубках путём перемещения назад и вперёд. " -"Укажите желаемое количество таких движений." +msgid "Filament is cooled by being moved back and forth in the cooling tubes. Specify desired number of these moves." +msgstr "Пруток охлаждается в охлаждающих трубках путём перемещения назад и вперёд. Укажите желаемое количество таких движений." msgid "Speed of the first cooling move" msgstr "Скорость первого охлаждающего движения" @@ -10294,18 +9166,13 @@ msgid "Minimal purge on wipe tower" msgstr "Мин. объём сброса на черновой башне" msgid "" -"After a tool change, the exact position of the newly loaded filament inside " -"the nozzle may not be known, and the filament pressure is likely not yet " -"stable. Before purging the print head into an infill or a sacrificial " -"object, Orca Slicer will always prime this amount of material into the wipe " -"tower to produce successive infill or sacrificial object extrusions reliably." +"After a tool change, the exact position of the newly loaded filament inside the nozzle may not be known, and the filament pressure is likely not yet stable. " +"Before purging the print head into an infill or a sacrificial object, Orca Slicer will always prime this amount of material into the wipe tower to produce " +"successive infill or sacrificial object extrusions reliably." msgstr "" -"После смены инструмента, точное положение вновь загруженного прутка внутри " -"него может быть неизвестно, и давление прутка, вероятно, ещё не стабильно. " -"Перед тем, как очистить печатающую головку в заполнение или в «жертвенную» " -"модель Orca Slicer всегда будет выдавливать это количество материала на " -"черновую башню, чтобы обеспечить надёжную печать заполнения или «жертвенной» " -"модели." +"После смены инструмента, точное положение вновь загруженного прутка внутри него может быть неизвестно, и давление прутка, вероятно, ещё не стабильно. Перед тем, " +"как очистить печатающую головку в заполнение или в «жертвенную» модель Orca Slicer всегда будет выдавливать это количество материала на черновую башню, чтобы " +"обеспечить надёжную печать заполнения или «жертвенной» модели." msgid "Speed of the last cooling move" msgstr "Скорость последнего охлаждающего движения" @@ -10314,49 +9181,35 @@ msgid "Cooling moves are gradually accelerating towards this speed." msgstr "Охлаждающие движения постепенно ускоряют до этой скорости." msgid "" -"Time for the printer firmware (or the Multi Material Unit 2.0) to load a new " -"filament during a tool change (when executing the T code). This time is " -"added to the total print time by the G-code time estimator." +"Time for the printer firmware (or the Multi Material Unit 2.0) to load a new filament during a tool change (when executing the T code). This time is added to the " +"total print time by the G-code time estimator." msgstr "" -"Время за которое прошивка принтера (или Multi Material Unit 2.0) выгружает " -"пруток во время смены инструмента (при выполнении кода Т). Это время " -"добавляется к общему времени печати с помощью алгоритма оценки времени " -"выполнения G-кода." +"Время за которое прошивка принтера (или Multi Material Unit 2.0) выгружает пруток во время смены инструмента (при выполнении кода Т). Это время добавляется к " +"общему времени печати с помощью алгоритма оценки времени выполнения G-кода." msgid "Ramming parameters" msgstr "Параметры рэмминга" -msgid "" -"This string is edited by RammingDialog and contains ramming specific " -"parameters." -msgstr "" -"Эта строка редактируется диалоговым окном рэмминга и содержит его конкретные " -"параметры." +msgid "This string is edited by RammingDialog and contains ramming specific parameters." +msgstr "Эта строка редактируется диалоговым окном рэмминга и содержит его конкретные параметры." msgid "" -"Time for the printer firmware (or the Multi Material Unit 2.0) to unload a " -"filament during a tool change (when executing the T code). This time is " -"added to the total print time by the G-code time estimator." +"Time for the printer firmware (or the Multi Material Unit 2.0) to unload a filament during a tool change (when executing the T code). This time is added to the " +"total print time by the G-code time estimator." msgstr "" -"Время за которое прошивка принтера (или Multi Material Unit 2.0) выгружает " -"пруток во время смены инструмента (при выполнении кода Т). Это время " -"добавляется к общему времени печати с помощью алгоритма оценки времени " -"выполнения G-кода." +"Время за которое прошивка принтера (или Multi Material Unit 2.0) выгружает пруток во время смены инструмента (при выполнении кода Т). Это время добавляется к " +"общему времени печати с помощью алгоритма оценки времени выполнения G-кода." msgid "Enable ramming for multitool setups" msgstr "Включить рэмминг для мультиинструментальных устройств" msgid "" -"Perform ramming when using multitool printer (i.e. when the 'Single Extruder " -"Multimaterial' in Printer Settings is unchecked). When checked, a small " -"amount of filament is rapidly extruded on the wipe tower just before the " -"toolchange. This option is only used when the wipe tower is enabled." +"Perform ramming when using multitool printer (i.e. when the 'Single Extruder Multimaterial' in Printer Settings is unchecked). When checked, a small amount of " +"filament is rapidly extruded on the wipe tower just before the toolchange. This option is only used when the wipe tower is enabled." msgstr "" -"Выполнять рэмминг при использовании мультиинструментального принтера (т. е. " -"когда в настройках принтера снят флажок «Мультиматериальный одиночный " -"экструдер»). При включении этой опции, небольшое количество материала быстро " -"выдавливается на черновую башню непосредственно перед сменой инструмента. " -"Эта опция используется только в том случае, если включена черновая башня." +"Выполнять рэмминг при использовании мультиинструментального принтера (т. е. когда в настройках принтера снят флажок «Мультиматериальный одиночный экструдер»). " +"При включении этой опции, небольшое количество материала быстро выдавливается на черновую башню непосредственно перед сменой инструмента. Эта опция используется " +"только в том случае, если включена черновая башня." msgid "Multitool ramming volume" msgstr "Объём рэмминга мультиинструмента" @@ -10385,32 +9238,24 @@ msgstr "Тип материала пластиковой нити." msgid "Soluble material" msgstr "Растворимый материал" -msgid "" -"Soluble material is commonly used to print support and support interface" -msgstr "" -"Растворимый материал обычно используется для печати поддержки и связующего " -"слоя поддержки." +msgid "Soluble material is commonly used to print support and support interface" +msgstr "Растворимый материал обычно используется для печати поддержки и связующего слоя поддержки." msgid "Support material" msgstr "Поддержка" -msgid "" -"Support material is commonly used to print support and support interface" -msgstr "" -"«Материал для поддержки» обычно используется для печати поддержки и " -"связующего слоя поддержки." +msgid "Support material is commonly used to print support and support interface" +msgstr "«Материал для поддержки» обычно используется для печати поддержки и связующего слоя поддержки." msgid "Softening temperature" msgstr "Температура размягчения" msgid "" -"The material softens at this temperature, so when the bed temperature is " -"equal to or greater than it, it's highly recommended to open the front door " -"and/or remove the upper glass to avoid cloggings." +"The material softens at this temperature, so when the bed temperature is equal to or greater than it, it's highly recommended to open the front door and/or " +"remove the upper glass to avoid cloggings." msgstr "" -"При этой температуре материал размягчается, поэтому, когда температура стола " -"равна или превышает её, настоятельно рекомендуется открыть переднюю дверцу и/" -"или верхнюю крышку принтера, чтобы избежать засорения сопла." +"При этой температуре материал размягчается, поэтому, когда температура стола равна или превышает её, настоятельно рекомендуется открыть переднюю дверцу и/или " +"верхнюю крышку принтера, чтобы избежать засорения сопла." msgid "Price" msgstr "Стоимость" @@ -10433,23 +9278,15 @@ msgstr "(Не указано)" msgid "Infill direction" msgstr "Угол печати заполнения" -msgid "" -"Angle for sparse infill pattern, which controls the start or main direction " -"of line" -msgstr "" -"Базовый угол для ориентации шаблона заполнения, который определяет начало " -"или основное направление линий." +msgid "Angle for sparse infill pattern, which controls the start or main direction of line" +msgstr "Базовый угол для ориентации шаблона заполнения, который определяет начало или основное направление линий." msgid "Sparse infill density" msgstr "Плотность заполнения" #, no-c-format, no-boost-format -msgid "" -"Density of internal sparse infill, 100% turns all sparse infill into solid " -"infill and internal solid infill pattern will be used" -msgstr "" -"Плотность внутреннего заполнения, выраженная в процентах. 100% означает " -"сплошное заполнение." +msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used" +msgstr "Плотность внутреннего заполнения, выраженная в процентах. 100% означает сплошное заполнение." msgid "Sparse infill pattern" msgstr "Шаблон заполнения" @@ -10491,28 +9328,17 @@ msgid "Sparse infill anchor length" msgstr "Длина привязок разреженного заполнения" msgid "" -"Connect an infill line to an internal perimeter with a short segment of an " -"additional perimeter. If expressed as percentage (example: 15%) it is " -"calculated over infill extrusion width. Orca Slicer tries to connect two " -"close infill lines to a short perimeter segment. If no such perimeter " -"segment shorter than infill_anchor_max is found, the infill line is " -"connected to a perimeter segment at just one side and the length of the " -"perimeter segment taken is limited to this parameter, but no longer than " -"anchor_length_max. \n" -"Set this parameter to zero to disable anchoring perimeters connected to a " -"single infill line." +"Connect an infill line to an internal perimeter with a short segment of an additional perimeter. If expressed as percentage (example: 15%) it is calculated over " +"infill extrusion width. Orca Slicer tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment shorter than " +"infill_anchor_max is found, the infill line is connected to a perimeter segment at just one side and the length of the perimeter segment taken is limited to this " +"parameter, but no longer than anchor_length_max. \n" +"Set this parameter to zero to disable anchoring perimeters connected to a single infill line." msgstr "" -"Соединять линию заполнения с внутренним периметром с помощью короткого " -"отрезка дополнительного периметра (привязок). Если выражено в процентах, то " -"она вычисляется по ширине экструзии заполнения. Программа пытается соединить " -"две ближайшие линии заполнения с коротким отрезком периметра. Если не " -"найдено такого отрезка периметра короче «Максимальной длины привязок " -"разреженного заполнения» (anchor_length_max), то линия заполнения " -"соединяется с отрезком периметра только с одной стороны, а длина отрезка " -"периметра ограничена этим параметром, но не больше «Максимальной длины " -"привязок разреженного заполнения» (anchor_length_max).\n" -"Установите этот параметр равным нулю для отключения привязок периметров, " -"соединённых с одной линии заполнения." +"Соединять линию заполнения с внутренним периметром с помощью короткого отрезка дополнительного периметра (привязок). Если выражено в процентах, то она " +"вычисляется по ширине экструзии заполнения. Программа пытается соединить две ближайшие линии заполнения с коротким отрезком периметра. Если не найдено такого " +"отрезка периметра короче «Максимальной длины привязок разреженного заполнения» (anchor_length_max), то линия заполнения соединяется с отрезком периметра только с " +"одной стороны, а длина отрезка периметра ограничена этим параметром, но не больше «Максимальной длины привязок разреженного заполнения» (anchor_length_max).\n" +"Установите этот параметр равным нулю для отключения привязок периметров, соединённых с одной линии заполнения." msgid "0 (no open anchors)" msgstr "0 (нет открытых привязок)" @@ -10524,27 +9350,17 @@ msgid "Maximum length of the infill anchor" msgstr "Максимальная длина привязок разреженного заполнения" msgid "" -"Connect an infill line to an internal perimeter with a short segment of an " -"additional perimeter. If expressed as percentage (example: 15%) it is " -"calculated over infill extrusion width. Orca Slicer tries to connect two " -"close infill lines to a short perimeter segment. If no such perimeter " -"segment shorter than this parameter is found, the infill line is connected " -"to a perimeter segment at just one side and the length of the perimeter " -"segment taken is limited to infill_anchor, but no longer than this " -"parameter. \n" -"If set to 0, the old algorithm for infill connection will be used, it should " -"create the same result as with 1000 & 0." +"Connect an infill line to an internal perimeter with a short segment of an additional perimeter. If expressed as percentage (example: 15%) it is calculated over " +"infill extrusion width. Orca Slicer tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment shorter than this " +"parameter is found, the infill line is connected to a perimeter segment at just one side and the length of the perimeter segment taken is limited to " +"infill_anchor, but no longer than this parameter. \n" +"If set to 0, the old algorithm for infill connection will be used, it should create the same result as with 1000 & 0." msgstr "" -"Соединять линию заполнения с внутренним периметром с помощью короткого " -"отрезка дополнительного периметра (привязок). Если выражено в процентах, то " -"она вычисляется по ширине экструзии заполнения. Slic3r пытается соединить " -"две ближайшие линии заполнения с коротким отрезком периметра. Если не " -"найдено такого отрезка периметра короче этого параметра, линия заполнения " -"соединяется с отрезком периметра только с одной стороны, а длина отрезка " -"периметра ограничена значением «Длина привязок разреженного " -"заполнения» (infill_anchor), но не больше этого параметра.\n" -"Если установить 0, то будет использоваться старый алгоритм для соединения " -"заполнения, который даёт такой же результат, как и при значениях 1000 и 0." +"Соединять линию заполнения с внутренним периметром с помощью короткого отрезка дополнительного периметра (привязок). Если выражено в процентах, то она " +"вычисляется по ширине экструзии заполнения. Slic3r пытается соединить две ближайшие линии заполнения с коротким отрезком периметра. Если не найдено такого " +"отрезка периметра короче этого параметра, линия заполнения соединяется с отрезком периметра только с одной стороны, а длина отрезка периметра ограничена " +"значением «Длина привязок разреженного заполнения» (infill_anchor), но не больше этого параметра.\n" +"Если установить 0, то будет использоваться старый алгоритм для соединения заполнения, который даёт такой же результат, как и при значениях 1000 и 0." msgid "0 (Simple connect)" msgstr "0 (без привязок)" @@ -10558,71 +9374,43 @@ msgstr "Ускорение на внутренних периметрах." msgid "Acceleration of travel moves" msgstr "Ускорение холостого перемещения." -msgid "" -"Acceleration of top surface infill. Using a lower value may improve top " -"surface quality" -msgstr "" -"Ускорение на верхней поверхности. Использование меньшего значения может " -"улучшить качество верхней поверхности." +msgid "Acceleration of top surface infill. Using a lower value may improve top surface quality" +msgstr "Ускорение на верхней поверхности. Использование меньшего значения может улучшить качество верхней поверхности." msgid "Acceleration of outer wall. Using a lower value can improve quality" -msgstr "" -"Ускорение на внешнем периметре. Использование более низкого значения может " -"улучшить качество." +msgstr "Ускорение на внешнем периметре. Использование более низкого значения может улучшить качество." -msgid "" -"Acceleration of bridges. If the value is expressed as a percentage (e.g. " -"50%), it will be calculated based on the outer wall acceleration." -msgstr "" -"Ускорение на мостах. Если задано в процентах, то значение вычисляться " -"относительно ускорения внешнего периметра." +msgid "Acceleration of bridges. If the value is expressed as a percentage (e.g. 50%), it will be calculated based on the outer wall acceleration." +msgstr "Ускорение на мостах. Если задано в процентах, то значение вычисляться относительно ускорения внешнего периметра." msgid "mm/s² or %" msgstr "мм/с² или %" -msgid "" -"Acceleration of sparse infill. If the value is expressed as a percentage (e." -"g. 100%), it will be calculated based on the default acceleration." -msgstr "" -"Ускорение на разреженном заполнении. Если задано в процентах, то значение " -"вычисляться относительно ускорения по умолчанию." +msgid "Acceleration of sparse infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration." +msgstr "Ускорение на разреженном заполнении. Если задано в процентах, то значение вычисляться относительно ускорения по умолчанию." -msgid "" -"Acceleration of internal solid infill. If the value is expressed as a " -"percentage (e.g. 100%), it will be calculated based on the default " -"acceleration." -msgstr "" -"Ускорение на внутреннем сплошном заполнении. Если задано в процентах, то " -"значение вычисляться относительно ускорения по умолчанию." +msgid "Acceleration of internal solid infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration." +msgstr "Ускорение на внутреннем сплошном заполнении. Если задано в процентах, то значение вычисляться относительно ускорения по умолчанию." -msgid "" -"Acceleration of initial layer. Using a lower value can improve build plate " -"adhesive" -msgstr "" -"Ускорение на первом слое. Использование более низкого значения может " -"улучшить адгезию к столу." +msgid "Acceleration of initial layer. Using a lower value can improve build plate adhesive" +msgstr "Ускорение на первом слое. Использование более низкого значения может улучшить адгезию к столу." msgid "Enable accel_to_decel" msgstr "Вкл. ограничение ускорения зигзагов" msgid "Klipper's max_accel_to_decel will be adjusted automatically" msgstr "" -"Значение max_accel_to_decel (ограничение ускорения зигзагов) в Klipper будет " -"скорректировано автоматически.\n" +"Значение max_accel_to_decel (ограничение ускорения зигзагов) в Klipper будет скорректировано автоматически.\n" "\n" -"Параметр предназначен для ограничения влияния экстремальных переходов от " -"ускорения к замедлению, типичных для коротких зигзагообразных перемещений." +"Параметр предназначен для ограничения влияния экстремальных переходов от ускорения к замедлению, типичных для коротких зигзагообразных перемещений." # ??? Ускорение к замедлению, Ускорение торможения, Скорость торможения, Скорость торможения перед поворотом, Соотношение ускорения к замедлению, Скорость движения при переходе от ускорения к замедлению и наоборот msgid "accel_to_decel" msgstr "Ограничение ускорение зигзагов" #, c-format, boost-format -msgid "" -"Klipper's max_accel_to_decel will be adjusted to this %% of acceleration" -msgstr "" -"Значение max_accel_to_decel (ограничение ускорения зигзагов) в Klipper будет " -"скорректировано на заданный процент ускорения." +msgid "Klipper's max_accel_to_decel will be adjusted to this %% of acceleration" +msgstr "Значение max_accel_to_decel (ограничение ускорения зигзагов) в Klipper будет скорректировано на заданный процент ускорения." msgid "Jerk of outer walls" msgstr "Рывок для внешних периметров." @@ -10642,22 +9430,14 @@ msgstr "Рывок для первого слоя." msgid "Jerk for travel" msgstr "Рывок при перемещении." -msgid "" -"Line width of initial layer. If expressed as a %, it will be computed over " -"the nozzle diameter." -msgstr "" -"Ширина экструзии для первого слоя. Если задано в процентах, то значение " -"вычисляться относительно диаметра сопла." +msgid "Line width of initial layer. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для первого слоя. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Initial layer height" msgstr "Высота первого слоя" -msgid "" -"Height of initial layer. Making initial layer height to be thick slightly " -"can improve build plate adhension" -msgstr "" -"Высота первого слоя. Незначительное увеличение толщины первого слоя может " -"улучшить сцепление со столом." +msgid "Height of initial layer. Making initial layer height to be thick slightly can improve build plate adhension" +msgstr "Высота первого слоя. Незначительное увеличение толщины первого слоя может улучшить сцепление со столом." msgid "Speed of initial layer except the solid infill part" msgstr "Скорость печати первого слоя, кроме сплошного заполнения." @@ -10677,59 +9457,41 @@ msgstr "Скорость перемещения на первом слое." msgid "Number of slow layers" msgstr "Количество медленных слоёв" -msgid "" -"The first few layers are printed slower than normal. The speed is gradually " -"increased in a linear fashion over the specified number of layers." -msgstr "" -"Первые несколько слоёв печатаются медленнее, чем обычно. Скорость постепенно " -"линейно увеличивается в течение заданного количества слоёв." +msgid "The first few layers are printed slower than normal. The speed is gradually increased in a linear fashion over the specified number of layers." +msgstr "Первые несколько слоёв печатаются медленнее, чем обычно. Скорость постепенно линейно увеличивается в течение заданного количества слоёв." msgid "Initial layer nozzle temperature" msgstr "Температура сопла на первом слое" msgid "Nozzle temperature to print initial layer when using this filament" -msgstr "" -"Температура сопла для печати первого слоя при использовании данной " -"пластиковой нити." +msgstr "Температура сопла для печати первого слоя при использовании данной пластиковой нити." msgid "Full fan speed at layer" msgstr "Полная скорость вентилятора на слое" msgid "" -"Fan speed will be ramped up linearly from zero at layer " -"\"close_fan_the_first_x_layers\" to maximum at layer " -"\"full_fan_speed_layer\". \"full_fan_speed_layer\" will be ignored if lower " -"than \"close_fan_the_first_x_layers\", in which case the fan will be running " -"at maximum allowed speed at layer \"close_fan_the_first_x_layers\" + 1." +"Fan speed will be ramped up linearly from zero at layer \"close_fan_the_first_x_layers\" to maximum at layer \"full_fan_speed_layer\". \"full_fan_speed_layer\" " +"will be ignored if lower than \"close_fan_the_first_x_layers\", in which case the fan will be running at maximum allowed speed at layer " +"\"close_fan_the_first_x_layers\" + 1." msgstr "" -"Скорость вентилятора будет нарастать линейно от нуля на слое " -"\"close_fan_the_first_x_layers\" до максимума на слое " -"\"full_fan_speed_layer\". Значение \"full_fan_speed_layer\" будет " -"игнорироваться, если оно меньше значения \"close_fan_the_first_x_layers\", в " -"этом случае вентилятор будет работать на максимально допустимой скорости на " -"слое \"close_fan_the_first_x_layers\" + 1." +"Скорость вентилятора будет нарастать линейно от нуля на слое \"close_fan_the_first_x_layers\" до максимума на слое \"full_fan_speed_layer\". Значение " +"\"full_fan_speed_layer\" будет игнорироваться, если оно меньше значения \"close_fan_the_first_x_layers\", в этом случае вентилятор будет работать на максимально " +"допустимой скорости на слое \"close_fan_the_first_x_layers\" + 1." msgid "Support interface fan speed" msgstr "Скорость вентилятора на связующем слое" msgid "" -"This fan speed is enforced during all support interfaces, to be able to " -"weaken their bonding with a high fan speed.\n" +"This fan speed is enforced during all support interfaces, to be able to weaken their bonding with a high fan speed.\n" "Set to -1 to disable this override.\n" "Can only be overriden by disable_fan_first_layers." msgstr "" -"Скорость, применяемая ко всем связующим слоях, чтобы высокой скоростью " -"вентилятора ослабить сцепление между слоями.\n" +"Скорость, применяемая ко всем связующим слоях, чтобы высокой скоростью вентилятора ослабить сцепление между слоями.\n" "Установите значение -1, чтобы запретить переопределять этот параметр.\n" "Может быть отменено только командой disable_fan_first_layers." -msgid "" -"Randomly jitter while printing the wall, so that the surface has a rough " -"look. This setting controls the fuzzy position" -msgstr "" -"Случайное дрожание сопла при печати внешнего периметра для создания эффекта " -"шероховатой поверхности. Эта настройка определяет положение нечетной " -"оболочки." +msgid "Randomly jitter while printing the wall, so that the surface has a rough look. This setting controls the fuzzy position" +msgstr "Случайное дрожание сопла при печати внешнего периметра для создания эффекта шероховатой поверхности. Эта настройка определяет положение нечетной оболочки." msgid "Contour" msgstr "Внешний периметр" @@ -10743,22 +9505,14 @@ msgstr "Все периметры" msgid "Fuzzy skin thickness" msgstr "Толщина нечёткой оболочки" -msgid "" -"The width within which to jitter. It's adversed to be below outer wall line " -"width" -msgstr "" -"Ширина, в пределах которой будет происходить дрожание. Желательно, чтобы она " -"была меньше ширины линии внешнего периметра." +msgid "The width within which to jitter. It's adversed to be below outer wall line width" +msgstr "Ширина, в пределах которой будет происходить дрожание. Желательно, чтобы она была меньше ширины линии внешнего периметра." msgid "Fuzzy skin point distance" msgstr "Расстояние «дрожания» при печати нечёткой оболочки" -msgid "" -"The average diatance between the random points introducded on each line " -"segment" -msgstr "" -"Среднее расстояние между случайно вставленными точками при генерации " -"нечётной оболочки." +msgid "The average diatance between the random points introducded on each line segment" +msgstr "Среднее расстояние между случайно вставленными точками при генерации нечётной оболочки." msgid "Apply fuzzy skin to first layer" msgstr "Нечёткая оболочки на первом слое" @@ -10775,49 +9529,32 @@ msgstr "Слои и периметры" msgid "Filter out gaps smaller than the threshold specified" msgstr "Небольшие промежутки меньше указанного порога не будут заполняться." -msgid "" -"Speed of gap infill. Gap usually has irregular line width and should be " -"printed more slowly" -msgstr "" -"Скорость заполнения пробелов. Пробелы обычно имеют неравномерную ширину " -"линии и должен печататься медленнее." +msgid "Speed of gap infill. Gap usually has irregular line width and should be printed more slowly" +msgstr "Скорость заполнения пробелов. Пробелы обычно имеют неравномерную ширину линии и должен печататься медленнее." msgid "Arc fitting" msgstr "Поддержка движения по дуге окружности" -msgid "" -"Enable this to get a G-code file which has G2 and G3 moves. And the fitting " -"tolerance is same with resolution" -msgstr "" -"Включите, если хотите использовать в G-коде команды перемещения по дуге " -"окружности G2/G3. Значение допуска траектории такое же как разрешение G-кода " -"выше." +msgid "Enable this to get a G-code file which has G2 and G3 moves. And the fitting tolerance is same with resolution" +msgstr "Включите, если хотите использовать в G-коде команды перемещения по дуге окружности G2/G3. Значение допуска траектории такое же как разрешение G-кода выше." msgid "Add line number" msgstr "Добавить номер строки" msgid "Enable this to add line number(Nx) at the beginning of each G-Code line" -msgstr "" -"При включении, в начало каждой строки G-кода, будет добавляться номер строки " -"(Nx)." +msgstr "При включении, в начало каждой строки G-кода, будет добавляться номер строки (Nx)." msgid "Scan first layer" msgstr "Проверка первого слоя" -msgid "" -"Enable this to enable the camera on printer to check the quality of first " -"layer" +msgid "Enable this to enable the camera on printer to check the quality of first layer" msgstr "При включении, камера принтера будет проверять качество первого слоя." msgid "Nozzle type" msgstr "Тип сопла" -msgid "" -"The metallic material of nozzle. This determines the abrasive resistance of " -"nozzle, and what kind of filament can be printed" -msgstr "" -"Материал сопла. Определяет абразивную стойкость сопла, а также то, каким " -"материалом можно печатать." +msgid "The metallic material of nozzle. This determines the abrasive resistance of nozzle, and what kind of filament can be printed" +msgstr "Материал сопла. Определяет абразивную стойкость сопла, а также то, каким материалом можно печатать." msgid "Undefine" msgstr "Не задано" @@ -10834,11 +9571,8 @@ msgstr "Латунь" msgid "Nozzle HRC" msgstr "Твердость сопла (HRC)" -msgid "" -"The nozzle's hardness. Zero means no checking for nozzle's hardness during " -"slicing." -msgstr "" -"Твёрдость сопел. 0 - отключение контроля сопел на твёрдость во время нарезки." +msgid "The nozzle's hardness. Zero means no checking for nozzle's hardness during slicing." +msgstr "Твёрдость сопел. 0 - отключение контроля сопел на твёрдость во время нарезки." msgid "HRC" msgstr "HRC" @@ -10865,37 +9599,24 @@ msgid "Best object position" msgstr "Наилучшее расположение модели" msgid "Best auto arranging position in range [0,1] w.r.t. bed shape." -msgstr "" -"Наилучшее расположение модели при авторасстановке в диапазоне [0,1] " -"относительно формы стола." +msgstr "Наилучшее расположение модели при авторасстановке в диапазоне [0,1] относительно формы стола." -msgid "" -"Enable this option if machine has auxiliary part cooling fan. G-code " -"command: M106 P2 S(0-255)." +msgid "Enable this option if machine has auxiliary part cooling fan. G-code command: M106 P2 S(0-255)." msgstr "" -"Если в принтере имеет вспомогательный вентилятор для охлаждения моделей, " -"можете включить эту опцию. \n" +"Если в принтере имеет вспомогательный вентилятор для охлаждения моделей, можете включить эту опцию. \n" "G-код команда: M106 P2 S(0-255)." msgid "" -"Start the fan this number of seconds earlier than its target start time (you " -"can use fractional seconds). It assumes infinite acceleration for this time " -"estimation, and will only take into account G1 and G0 moves (arc fitting is " -"unsupported).\n" -"It won't move fan comands from custom gcodes (they act as a sort of " -"'barrier').\n" -"It won't move fan comands into the start gcode if the 'only custom start " -"gcode' is activated.\n" +"Start the fan this number of seconds earlier than its target start time (you can use fractional seconds). It assumes infinite acceleration for this time " +"estimation, and will only take into account G1 and G0 moves (arc fitting is unsupported).\n" +"It won't move fan comands from custom gcodes (they act as a sort of 'barrier').\n" +"It won't move fan comands into the start gcode if the 'only custom start gcode' is activated.\n" "Use 0 to deactivate." msgstr "" -"Запуск вентилятора на указанное количество секунд раньше целевого времени " -"запуска (поддерживаются доли секунды). При этом предполагается бесконечное " -"ускорение для оценки этого времени, и учёт только перемещений G1 и G0 " -"(Поддержка движения по дуге окружности не поддерживается).\n" -"Это не приведёт к сдвигу команд вентилятора из пользовательских G-кодов (они " -"действуют как своего рода барьер).\n" -"Это не приведёт к сдвигу команд вентилятора в стартовом G-коде, если " -"активировано «только пользовательский стартовый G-код».\n" +"Запуск вентилятора на указанное количество секунд раньше целевого времени запуска (поддерживаются доли секунды). При этом предполагается бесконечное ускорение " +"для оценки этого времени, и учёт только перемещений G1 и G0 (Поддержка движения по дуге окружности не поддерживается).\n" +"Это не приведёт к сдвигу команд вентилятора из пользовательских G-кодов (они действуют как своего рода барьер).\n" +"Это не приведёт к сдвигу команд вентилятора в стартовом G-коде, если активировано «только пользовательский стартовый G-код».\n" "Установите 0 для отключения." msgid "Only overhangs" @@ -10908,17 +9629,13 @@ msgid "Fan kick-start time" msgstr "Продолжительность принудительного запуска вентилятора" msgid "" -"Emit a max fan speed command for this amount of seconds before reducing to " -"target speed to kick-start the cooling fan.\n" -"This is useful for fans where a low PWM/power may be insufficient to get the " -"fan started spinning from a stop, or to get the fan up to speed faster.\n" +"Emit a max fan speed command for this amount of seconds before reducing to target speed to kick-start the cooling fan.\n" +"This is useful for fans where a low PWM/power may be insufficient to get the fan started spinning from a stop, or to get the fan up to speed faster.\n" "Set to 0 to deactivate." msgstr "" -"Время принудительного запуска (kick-start) вентилятора на максимальной " -"скорости, после чего скорость снижается до целевой. Это необходимо для " -"вентиляторов у которых низкое значение уровня ШИМ/мощности может быть " -"недостаточен для запуска вентилятора после остановки или для более быстрого " -"увеличения скорости его вращения.\n" +"Время принудительного запуска (kick-start) вентилятора на максимальной скорости, после чего скорость снижается до целевой. Это необходимо для вентиляторов у " +"которых низкое значение уровня ШИМ/мощности может быть недостаточен для запуска вентилятора после остановки или для более быстрого увеличения скорости его " +"вращения.\n" "Установите 0 для отключения." msgid "Time cost" @@ -10937,20 +9654,17 @@ msgid "" "This option is enabled if machine support controlling chamber temperature\n" "G-code command: M141 S(0-255)" msgstr "" -"Если принтер поддерживает контроль температуры в камере, включите эту " -"опцию.\n" +"Если принтер поддерживает контроль температуры в камере, включите эту опцию.\n" "G-код команда: M141 S(0-255)" msgid "Support air filtration" -msgstr "Фильтрация выдуваемого воздуха" +msgstr "Вытяжной вентилятор" msgid "" "Enable this if printer support air filtration\n" "G-code command: M106 P3 S(0-255)" msgstr "" -"Если принтер поддерживает фильтрацию выдуваемого воздуха, включите эту " -"опцию. \n" -"G-код команда: M106 P3 S(0-255)" +"Если в принтере имеется вытяжной вентилятор и вам требуется дополнительное охлаждение области внутри принтера, включите эту опцию. G-код команда: M106 P3 S(0-255)" msgid "G-code flavor" msgstr "Тип G-кода" @@ -10971,66 +9685,47 @@ msgid "Label objects" msgstr "Название моделей" msgid "" -"Enable this to add comments into the G-Code labeling print moves with what " -"object they belong to, which is useful for the Octoprint CancelObject " -"plugin. This settings is NOT compatible with Single Extruder Multi Material " -"setup and Wipe into Object / Wipe into Infill." +"Enable this to add comments into the G-Code labeling print moves with what object they belong to, which is useful for the Octoprint CancelObject plugin. This " +"settings is NOT compatible with Single Extruder Multi Material setup and Wipe into Object / Wipe into Infill." msgstr "" -"Включите эту опцию, чтобы добавить комментарии в G-код с указанием того, к " -"какой модели он принадлежит, что полезно для плагина Octoprint CancelObject. " -"Эта настройка не совместима с настройкой «Мультиматериальный одиночный " -"экструдер» и «Очистка в модель» / «Очистка в заполнение модели»." +"Включите эту опцию, чтобы добавить комментарии в G-код с указанием того, к какой модели он принадлежит, что полезно для плагина Octoprint CancelObject. Эта " +"настройка не совместима с настройкой «Мультиматериальный одиночный экструдер» и «Очистка в модель» / «Очистка в заполнение модели»." msgid "Exclude objects" msgstr "Исключить модели" msgid "Enable this option to add EXCLUDE OBJECT command in g-code" -msgstr "" -"Включите эту опцию, чтобы добавить команду EXCLUDE OBJECT (исключения " -"моделей) в G-код." +msgstr "Включите эту опцию, чтобы добавить команду EXCLUDE OBJECT (исключения моделей) в G-код." msgid "Verbose G-code" msgstr "Подробный G-код" msgid "" -"Enable this to get a commented G-code file, with each line explained by a " -"descriptive text. If you print from SD card, the additional weight of the " -"file could make your firmware slow down." +"Enable this to get a commented G-code file, with each line explained by a descriptive text. If you print from SD card, the additional weight of the file could " +"make your firmware slow down." msgstr "" -"Включите эту опцию, чтобы в каждой строке файла G-кода, присутствовал " -"комментарий с поясняющим текстом. При печати с SD-карты, скорость чтение " -"данных вашей прошивкой может снизится за счёт увеличения размера файла." +"Включите эту опцию, чтобы в каждой строке файла G-кода, присутствовал комментарий с поясняющим текстом. При печати с SD-карты, скорость чтение данных вашей " +"прошивкой может снизится за счёт увеличения размера файла." msgid "Infill combination" msgstr "Комбинированное заполнение" -msgid "" -"Automatically Combine sparse infill of several layers to print together to " -"reduce time. Wall is still printed with original layer height." +msgid "Automatically Combine sparse infill of several layers to print together to reduce time. Wall is still printed with original layer height." msgstr "" -"Для сокращения времени печати есть возможность печатать заполнение не на " -"каждом слое, а на двух слоях сразу. \n" +"Для сокращения времени печати есть возможность печатать заполнение не на каждом слое, а на двух слоях сразу. \n" "Периметры по-прежнему печатаются с исходной высотой слоя." msgid "Filament to print internal sparse infill." msgstr "Пластиковая нить для печати заполнения." -msgid "" -"Line width of internal sparse infill. If expressed as a %, it will be " -"computed over the nozzle diameter." -msgstr "" -"Ширина экструзии для заполнения. Если задано в процентах, то значение " -"вычисляться относительно диаметра сопла." +msgid "Line width of internal sparse infill. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для заполнения. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Infill/Wall overlap" msgstr "Перекрытие линий заполнения с линиями периметра" -msgid "" -"Infill area is enlarged slightly to overlap with wall for better bonding. " -"The percentage value is relative to line width of sparse infill" -msgstr "" -"Параметр указывает на сколько процентов заполнение будет перекрываться с " -"периметром для лучшего соединения друг с другом." +msgid "Infill area is enlarged slightly to overlap with wall for better bonding. The percentage value is relative to line width of sparse infill" +msgstr "Параметр указывает на сколько процентов заполнение будет перекрываться с периметром для лучшего соединения друг с другом." msgid "Speed of internal sparse infill" msgstr "Скорость заполнения" @@ -11039,41 +9734,31 @@ msgid "Interface shells" msgstr "Связующие оболочки" msgid "" -"Force the generation of solid shells between adjacent materials/volumes. " -"Useful for multi-extruder prints with translucent materials or manual " -"soluble support material" +"Force the generation of solid shells between adjacent materials/volumes. Useful for multi-extruder prints with translucent materials or manual soluble support " +"material" msgstr "" -"Принудительное создание замкнутых (сплошных) оболочек между смежными " -"материалами/объёмами. Полезно для многоэкструдерных принтеров при печати " -"полупрозрачными материалами или растворимой поддержкой. Помогает избежать " -"диффузию материалов." +"Принудительное создание замкнутых (сплошных) оболочек между смежными материалами/объёмами. Полезно для многоэкструдерных принтеров при печати полупрозрачными " +"материалами или растворимой поддержкой. Помогает избежать диффузию материалов." msgid "Maximum width of a segmented region" msgstr "Максимальная ширина сегментированной области" msgid "Maximum width of a segmented region. Zero disables this feature." -msgstr "" -"Максимальная ширина сегментированной области. Установите 0 для отключения " -"этой функции." +msgstr "Максимальная ширина сегментированной области. Установите 0 для отключения этой функции." msgid "Interlocking depth of a segmented region" msgstr "Глубина взаимосвязи сегментированной области" msgid "Interlocking depth of a segmented region. Zero disables this feature." -msgstr "" -"Глубина взаимосвязи сегментированной области. Установите 0 для отключения " -"этой функции." +msgstr "Глубина взаимосвязи сегментированной области. Установите 0 для отключения этой функции." msgid "Ironing Type" msgstr "Тип разглаживания" -msgid "" -"Ironing is using small flow to print on same height of surface again to make " -"flat surface more smooth. This setting controls which layer being ironed" +msgid "Ironing is using small flow to print on same height of surface again to make flat surface more smooth. This setting controls which layer being ironed" msgstr "" -"При разглаживании сопло выполняет вторую фазу заполнения на том же слое (с " -"небольшим потоком), чтобы заполнить отверстия и сгладить выступающие части " -"пластика. Этот параметр контролирует, какой слой необходимо сгладить." +"При разглаживании сопло выполняет вторую фазу заполнения на том же слое (с небольшим потоком), чтобы заполнить отверстия и сгладить выступающие части пластика. " +"Этот параметр контролирует, какой слой необходимо сгладить." msgid "No ironing" msgstr "Без разглаживания" @@ -11096,12 +9781,8 @@ msgstr "Шаблон по которому будет производиться msgid "Ironing flow" msgstr "Поток" -msgid "" -"The amount of material to extrude during ironing. Relative to flow of normal " -"layer height. Too high value results in overextrusion on the surface" -msgstr "" -"Количество материала, которое необходимо выдавить во время разглаживания " -"относительно потока при нормальной высоте слоя." +msgid "The amount of material to extrude during ironing. Relative to flow of normal layer height. Too high value results in overextrusion on the surface" +msgstr "Количество материала, которое необходимо выдавить во время разглаживания относительно потока при нормальной высоте слоя." msgid "Ironing line spacing" msgstr "Расстояние между линиями разглаживания" @@ -11118,26 +9799,17 @@ msgstr "Скорость разглаживания" msgid "Ironing angle" msgstr "Угол разглаживания" -msgid "" -"The angle ironing is done at. A negative number disables this function and " -"uses the default method." -msgstr "" -"Выбор угла разглаживания. Отрицательное число отключает эту функцию и " -"использует метод по умолчанию." +msgid "The angle ironing is done at. A negative number disables this function and uses the default method." +msgstr "Выбор угла разглаживания. Отрицательное число отключает эту функцию и использует метод по умолчанию." msgid "This gcode part is inserted at every layer change after lift z" -msgstr "" -"Этот G-код вставляется при каждой смене слоя, сразу после перемещения оси Z." +msgstr "Этот G-код вставляется при каждой смене слоя, сразу после перемещения оси Z." msgid "Supports silent mode" msgstr "Поддержка тихого режима" -msgid "" -"Whether the machine supports silent mode in which machine use lower " -"acceleration to print" -msgstr "" -"Поддержка тихого режима, в котором принтер использует меньшее ускорение " -"печати для уменьшения уровня шума." +msgid "Whether the machine supports silent mode in which machine use lower acceleration to print" +msgstr "Поддержка тихого режима, в котором принтер использует меньшее ускорение печати для уменьшения уровня шума." msgid "Emit limits to G-code" msgstr "Отправлять в G-код" @@ -11152,12 +9824,8 @@ msgstr "" "Если включено, ограничения принтера будут передаваться в файл G-кода.\n" "Если в качестве типа G-кода выбран Klipper опция будет игнорироваться." -msgid "" -"This G-code will be used as a code for the pause print. User can insert " -"pause G-code in gcode viewer" -msgstr "" -"Этот G-код используется для задания паузы печати. Пользователь может " -"вставить G-код паузы в просмотрщике G-кода." +msgid "This G-code will be used as a code for the pause print. User can insert pause G-code in gcode viewer" +msgstr "Этот G-код используется для задания паузы печати. Пользователь может вставить G-код паузы в просмотрщике G-кода." msgid "This G-code will be used as a custom code" msgstr "Этот G-код будет использоваться для пользовательского кода." @@ -11172,14 +9840,11 @@ msgid "Flow Compensation Model" msgstr "Модель компенсации потока" msgid "" -"Flow Compensation Model, used to adjust the flow for small infill areas. The " -"model is expressed as a comma separated pair of values for extrusion length " -"and flow correction factors, one per line, in the following format: " -"\"1.234,5.678\"" +"Flow Compensation Model, used to adjust the flow for small infill areas. The model is expressed as a comma separated pair of values for extrusion length and flow " +"correction factors, one per line, in the following format: \"1.234,5.678\"" msgstr "" -"Модель представлена в виде разделенных запятыми пар значений, длины " -"экструзии и поправочного коэффициента потока, по одному на строку в " -"следующем формате: \"1.234,5.678\"." +"Модель представлена в виде разделенных запятыми пар значений, длины экструзии и поправочного коэффициента потока, по одному на строку в следующем формате: " +"\"1.234,5.678\"." msgid "Maximum speed X" msgstr "Максимальная скорость перемещения по X" @@ -11281,87 +9946,59 @@ msgid "Maximum acceleration for travel" msgstr "Максимальное ускорение при перемещении" msgid "Maximum acceleration for travel (M204 T), it only applies to Marlin 2" -msgstr "" -"Максимальное ускорение при перемещении (M204 T), применяемое только для " -"Marlin 2" +msgstr "Максимальное ускорение при перемещении (M204 T), применяемое только для Marlin 2" -msgid "" -"Part cooling fan speed may be increased when auto cooling is enabled. This " -"is the maximum speed limitation of part cooling fan" +msgid "Part cooling fan speed may be increased when auto cooling is enabled. This is the maximum speed limitation of part cooling fan" msgstr "" -"Скорость вентилятора охлаждения моделей может быть увеличена, если включено " -"автоматическое охлаждение. Это максимальное ограничение скорости вентилятора " -"для охлаждения моделей." +"Скорость вентилятора охлаждения моделей может быть увеличена, если включено автоматическое охлаждение. Это максимальное ограничение скорости вентилятора для " +"охлаждения моделей." msgid "Max" msgstr "Макс." -msgid "" -"The largest printable layer height for extruder. Used tp limits the maximum " -"layer hight when enable adaptive layer height" -msgstr "" -"Это наибольшая высота печатаемого слоя для этого экструдера, которая " -"используется для ограничения функции «Переменная высота слоёв»." +msgid "The largest printable layer height for extruder. Used tp limits the maximum layer hight when enable adaptive layer height" +msgstr "Это наибольшая высота печатаемого слоя для этого экструдера, которая используется для ограничения функции «Переменная высота слоёв»." msgid "Extrusion rate smoothing" msgstr "Сглаживание скорости экструзии" msgid "" -"This parameter smooths out sudden extrusion rate changes that happen when " -"the printer transitions from printing a high flow (high speed/larger width) " -"extrusion to a lower flow (lower speed/smaller width) extrusion and vice " -"versa.\n" +"This parameter smooths out sudden extrusion rate changes that happen when the printer transitions from printing a high flow (high speed/larger width) extrusion " +"to a lower flow (lower speed/smaller width) extrusion and vice versa.\n" "\n" -"It defines the maximum rate by which the extruded volumetric flow in mm3/sec " -"can change over time. Higher values mean higher extrusion rate changes are " -"allowed, resulting in faster speed transitions.\n" +"It defines the maximum rate by which the extruded volumetric flow in mm3/sec can change over time. Higher values mean higher extrusion rate changes are allowed, " +"resulting in faster speed transitions.\n" "\n" "A value of 0 disables the feature. \n" "\n" -"For a high speed, high flow direct drive printer (like the Bambu lab or " -"Voron) this value is usually not needed. However it can provide some " -"marginal benefit in certain cases where feature speeds vary greatly. For " -"example, when there are aggressive slowdowns due to overhangs. In these " -"cases a high value of around 300-350mm3/s2 is recommended as this allows for " -"just enough smoothing to assist pressure advance achieve a smoother flow " -"transition.\n" +"For a high speed, high flow direct drive printer (like the Bambu lab or Voron) this value is usually not needed. However it can provide some marginal benefit in " +"certain cases where feature speeds vary greatly. For example, when there are aggressive slowdowns due to overhangs. In these cases a high value of around " +"300-350mm3/s2 is recommended as this allows for just enough smoothing to assist pressure advance achieve a smoother flow transition.\n" "\n" -"For slower printers without pressure advance, the value should be set much " -"lower. A value of 10-15mm3/s2 is a good starting point for direct drive " -"extruders and 5-10mm3/s2 for Bowden style. \n" +"For slower printers without pressure advance, the value should be set much lower. A value of 10-15mm3/s2 is a good starting point for direct drive extruders and " +"5-10mm3/s2 for Bowden style. \n" "\n" "This feature is known as Pressure Equalizer in Prusa slicer.\n" "\n" "Note: this parameter disables arc fitting." msgstr "" -"Этот параметр сглаживает резкие изменения скорости экструзии, которые " -"происходят, когда принтер переходит от печати с большим расходом (высокая " -"скорость/большая ширина) к печати с меньшим расходом (меньшая скорость/" -"меньшая ширина) и наоборот.\n" +"Этот параметр сглаживает резкие изменения скорости экструзии, которые происходят, когда принтер переходит от печати с большим расходом (высокая скорость/большая " +"ширина) к печати с меньшим расходом (меньшая скорость/меньшая ширина) и наоборот.\n" "\n" -"Параметр задаёт максимальную скорость, с которой объёмный расход " -"экструдируемого материала может изменяться с течением времени (мм³/с). Более " -"высокие значения означают, что допускаются более высокие изменения скорости " -"экструзии, что приводит к более быстрому переключению скоростей.\n" +"Параметр задаёт максимальную скорость, с которой объёмный расход экструдируемого материала может изменяться с течением времени (мм³/с). Более высокие значения " +"означают, что допускаются более высокие изменения скорости экструзии, что приводит к более быстрому переключению скоростей.\n" "\n" "Значение 0 отключает эту функцию. \n" "\n" -"Для высокоскоростных принтеров с прямым приводом (например, Bambu lab или " -"Voron) обычно не требуется использование данного значения. Однако в " -"некоторых случаях, когда скорость печати сильно различается, это может " -"принести некоторую дополнительную пользу. Например, когда происходят резкие " -"замедления из-за нависаний. В этих случаях рекомендуется использовать " -"высокое значение, составляющее около 300-350 мм³/с², так как это " -"обеспечивает достаточное сглаживание, помогающее прогнозированию давления " -"достичь более плавного перехода потока.\n" +"Для высокоскоростных принтеров с прямым приводом (например, Bambu lab или Voron) обычно не требуется использование данного значения. Однако в некоторых случаях, " +"когда скорость печати сильно различается, это может принести некоторую дополнительную пользу. Например, когда происходят резкие замедления из-за нависаний. В " +"этих случаях рекомендуется использовать высокое значение, составляющее около 300-350 мм³/с², так как это обеспечивает достаточное сглаживание, помогающее " +"прогнозированию давления достичь более плавного перехода потока.\n" "\n" -"Для более медленных принтеров, не использующих прогнозирование давления " -"(pressure advance), это значение должно быть значительно ниже. Значение " -"10-15 мм³/с² является хорошей отправной точкой для экструдеров с прямым " -"приводом и 5-10 мм³/с² для боуден экструдеров.\n" +"Для более медленных принтеров, не использующих прогнозирование давления (pressure advance), это значение должно быть значительно ниже. Значение 10-15 мм³/с² " +"является хорошей отправной точкой для экструдеров с прямым приводом и 5-10 мм³/с² для боуден экструдеров.\n" "\n" -"В Prusa Slicer эта функция известна как «Выравнивание давления» (Pressure " -"equalizer).\n" +"В Prusa Slicer эта функция известна как «Выравнивание давления» (Pressure equalizer).\n" "\n" "Примечание: этот параметр отключает поддержку движения по дуге окружности." @@ -11372,22 +10009,18 @@ msgid "Smoothing segment length" msgstr "Длина сглаживающего сегмента" msgid "" -"A lower value results in smoother extrusion rate transitions. However, this " -"results in a significantly larger gcode file and more instructions for the " -"printer to process. \n" +"A lower value results in smoother extrusion rate transitions. However, this results in a significantly larger gcode file and more instructions for the printer to " +"process. \n" "\n" -"Default value of 3 works well for most cases. If your printer is stuttering, " -"increase this value to reduce the number of adjustments made\n" +"Default value of 3 works well for most cases. If your printer is stuttering, increase this value to reduce the number of adjustments made\n" "\n" "Allowed values: 1-5" msgstr "" -"Меньшее значение приводит к более плавному изменению скорости экструзии. " -"Однако это приводит к значительному увеличению размера G-код файла и " -"увеличению количества инструкций для обработки принтером. \n" +"Меньшее значение приводит к более плавному изменению скорости экструзии. Однако это приводит к значительному увеличению размера G-код файла и увеличению " +"количества инструкций для обработки принтером. \n" "\n" -"Значение по умолчанию, равное 3, хорошо подходит для большинства случаев. " -"Если принтер печатает с мини-фризами, увеличьте это значение, чтобы " -"уменьшить количество выполняемых изменений.\n" +"Значение по умолчанию, равное 3, хорошо подходит для большинства случаев. Если принтер печатает с мини-фризами, увеличьте это значение, чтобы уменьшить " +"количество выполняемых изменений.\n" "\n" "Допустимые значения: 1–5." @@ -11395,40 +10028,29 @@ msgid "Minimum speed for part cooling fan" msgstr "Минимальная скорость вентилятора обдува модели." msgid "" -"Speed of auxiliary part cooling fan. Auxiliary fan will run at this speed " -"during printing except the first several layers which is defined by no " -"cooling layers.\n" -"Please enable auxiliary_fan in printer settings to use this feature. G-code " -"command: M106 P2 S(0-255)" +"Speed of auxiliary part cooling fan. Auxiliary fan will run at this speed during printing except the first several layers which is defined by no cooling layers.\n" +"Please enable auxiliary_fan in printer settings to use this feature. G-code command: M106 P2 S(0-255)" msgstr "" -"Скорость вращения вспомогательного вентилятора для охлаждения моделей. Он " -"всегда будет работать с этой скоростью, за исключением первых нескольких " -"слоёв, которые обычно настроены на работу без охлаждения.\n" -"Пожалуйста, включите вспомогательный вентилятор для охлаждения моделей " -"(auxiliary_fan) в настройках принтера, чтобы использовать эту функцию. \n" +"Скорость вращения вспомогательного вентилятора для охлаждения моделей. Он всегда будет работать с этой скоростью, за исключением первых нескольких слоёв, которые " +"обычно настроены на работу без охлаждения.\n" +"Пожалуйста, включите вспомогательный вентилятор для охлаждения моделей (auxiliary_fan) в настройках принтера, чтобы использовать эту функцию. \n" "G-код команда: M106 P2 S(0-255)." msgid "Min" msgstr "Мин." -msgid "" -"The lowest printable layer height for extruder. Used tp limits the minimum " -"layer hight when enable adaptive layer height" -msgstr "" -"Это наименьшая высота печатаемого слоя для данного экструдера и в то же " -"время нижний предел для функции «Переменная высота слоёв»." +msgid "The lowest printable layer height for extruder. Used tp limits the minimum layer hight when enable adaptive layer height" +msgstr "Это наименьшая высота печатаемого слоя для данного экструдера и в то же время нижний предел для функции «Переменная высота слоёв»." msgid "Min print speed" msgstr "Минимальная скорость печати" msgid "" -"The minimum printing speed that the printer will slow down to to attempt to " -"maintain the minimum layer time above, when slow down for better layer " -"cooling is enabled." +"The minimum printing speed that the printer will slow down to to attempt to maintain the minimum layer time above, when slow down for better layer cooling is " +"enabled." msgstr "" -"Минимальная скорость печати, до которой принтер замедлится, чтобы попытаться " -"сохранить минимальное время слоя, указанное выше, если включена опция " -"«Замедлять печать для лучшего охлаждения слоёв»." +"Минимальная скорость печати, до которой принтер замедлится, чтобы попытаться сохранить минимальное время слоя, указанное выше, если включена опция «Замедлять " +"печать для лучшего охлаждения слоёв»." msgid "Nozzle diameter" msgstr "Диаметр сопла" @@ -11439,22 +10061,14 @@ msgstr "Диаметр сопла" msgid "Configuration notes" msgstr "Примечание конфигурации" -msgid "" -"You can put here your personal notes. This text will be added to the G-code " -"header comments." -msgstr "" -"Здесь вы можете написать свои замечания для текущего профиля. Этот текст " -"будет добавлен к комментариям в заголовок G-кода." +msgid "You can put here your personal notes. This text will be added to the G-code header comments." +msgstr "Здесь вы можете написать свои замечания для текущего профиля. Этот текст будет добавлен к комментариям в заголовок G-кода." msgid "Host Type" msgstr "Тип хоста" -msgid "" -"Orca Slicer can upload G-code files to a printer host. This field must " -"contain the kind of the host." -msgstr "" -"Orca Slicer может загружать файл G-кода на хост принтера. Это поле должно " -"содержать тип хоста." +msgid "Orca Slicer can upload G-code files to a printer host. This field must contain the kind of the host." +msgstr "Orca Slicer может загружать файл G-кода на хост принтера. Это поле должно содержать тип хоста." msgid "Nozzle volume" msgstr "Объём сопла" @@ -11466,52 +10080,39 @@ msgid "Cooling tube position" msgstr "Позиция охлаждающей трубки" msgid "Distance of the center-point of the cooling tube from the extruder tip." -msgstr "" -"Расстояние между центральной точкой охлаждающей трубки и кончиком экструдера." +msgstr "Расстояние между центральной точкой охлаждающей трубки и кончиком экструдера." msgid "Cooling tube length" msgstr "Длина охлаждающей трубки" msgid "Length of the cooling tube to limit space for cooling moves inside it." -msgstr "" -"Длина трубки охлаждения для ограничения перемещения при охлаждающих " -"движениях." +msgstr "Длина трубки охлаждения для ограничения перемещения при охлаждающих движениях." msgid "High extruder current on filament swap" msgstr "Повышение тока экструдера при замене прутка" msgid "" -"It may be beneficial to increase the extruder motor current during the " -"filament exchange sequence to allow for rapid ramming feed rates and to " -"overcome resistance when loading a filament with an ugly shaped tip." +"It may be beneficial to increase the extruder motor current during the filament exchange sequence to allow for rapid ramming feed rates and to overcome " +"resistance when loading a filament with an ugly shaped tip." msgstr "" -"Это может быть полезно для увеличения тока двигателя экструдера во время " -"замены прутка, чтобы быстро увеличить скорость подачи и преодолеть " -"сопротивление при загрузке прутка с плохой формой кончика." +"Это может быть полезно для увеличения тока двигателя экструдера во время замены прутка, чтобы быстро увеличить скорость подачи и преодолеть сопротивление при " +"загрузке прутка с плохой формой кончика." msgid "Filament parking position" msgstr "Положение парковки прутка" -msgid "" -"Distance of the extruder tip from the position where the filament is parked " -"when unloaded. This should match the value in printer firmware." -msgstr "" -"Расстояние от кончика экструдера до точки, где размещается пруток при " -"выгрузке. Расстояние должно соответствовать значению в прошивке принтера." +msgid "Distance of the extruder tip from the position where the filament is parked when unloaded. This should match the value in printer firmware." +msgstr "Расстояние от кончика экструдера до точки, где размещается пруток при выгрузке. Расстояние должно соответствовать значению в прошивке принтера." msgid "Extra loading distance" msgstr "Дополнительная длина загрузки" msgid "" -"When set to zero, the distance the filament is moved from parking position " -"during load is exactly the same as it was moved back during unload. When " -"positive, it is loaded further, if negative, the loading move is shorter " -"than unloading." +"When set to zero, the distance the filament is moved from parking position during load is exactly the same as it was moved back during unload. When positive, it " +"is loaded further, if negative, the loading move is shorter than unloading." msgstr "" -"Если установлено 0, то расстояние, которое проходит пруток при перемещении " -"из положения парковки во время загрузки, точно такое же, как и при выгрузке. " -"При положительном значении, она загружается дальше; при отрицательном, ход " -"загрузки короче (по сравнению с выгрузкой)." +"Если установлено 0, то расстояние, которое проходит пруток при перемещении из положения парковки во время загрузки, точно такое же, как и при выгрузке. При " +"положительном значении, она загружается дальше; при отрицательном, ход загрузки короче (по сравнению с выгрузкой)." msgid "Start end points" msgstr "Начальные и конечные точки" @@ -11523,14 +10124,11 @@ msgid "Reduce infill retraction" msgstr "Уменьшать отката при заполнении" msgid "" -"Don't retract when the travel is in infill area absolutely. That means the " -"oozing can't been seen. This can reduce times of retraction for complex " -"model and save printing time, but make slicing and G-code generating slower" +"Don't retract when the travel is in infill area absolutely. That means the oozing can't been seen. This can reduce times of retraction for complex model and save " +"printing time, but make slicing and G-code generating slower" msgstr "" -"Отключает откат, когда перемещения полностью совершаются в области " -"заполнения (и, таким образом, любые подтёки скорее всего будут не заметны). " -"Это поможет снизить количество откатов при печати сложной модели и " -"сэкономить время печати, но увеличит время нарезки и генерации G-кода." +"Отключает откат, когда перемещения полностью совершаются в области заполнения (и, таким образом, любые подтёки скорее всего будут не заметны). Это поможет " +"снизить количество откатов при печати сложной модели и сэкономить время печати, но увеличит время нарезки и генерации G-кода." msgid "Filename format" msgstr "Формат имени файла" @@ -11548,24 +10146,18 @@ msgid "Make overhangs printable - Maximum angle" msgstr "Делать нависания пригодными для печати под максимальным углом" msgid "" -"Maximum angle of overhangs to allow after making more steep overhangs " -"printable.90° will not change the model at all and allow any overhang, while " -"0 will replace all overhangs with conical material." +"Maximum angle of overhangs to allow after making more steep overhangs printable.90° will not change the model at all and allow any overhang, while 0 will replace " +"all overhangs with conical material." msgstr "" -"Максимальный угол нависания, получаемый после изменения геометрии крутых " -"нависаний. При 90°не происходит изменения формы модели. При 0° же, все " -"нависания заменяются материалом конической геометрии." +"Максимальный угол нависания, получаемый после изменения геометрии крутых нависаний. При 90°не происходит изменения формы модели. При 0° же, все нависания " +"заменяются материалом конической геометрии." msgid "Make overhangs printable - Hole area" msgstr "Делать нависания отверстий пригодными для печати" -msgid "" -"Maximum area of a hole in the base of the model before it's filled by " -"conical material.A value of 0 will fill all the holes in the model base." +msgid "Maximum area of a hole in the base of the model before it's filled by conical material.A value of 0 will fill all the holes in the model base." msgstr "" -"Максимальная площадь отверстия в основании модели до его заполнения " -"материалом конической геометрии. При 0 все отверстия в основании модели " -"будут заполнены." +"Максимальная площадь отверстия в основании модели до его заполнения материалом конической геометрии. При 0 все отверстия в основании модели будут заполнены." msgid "mm²" msgstr "мм²" @@ -11574,19 +10166,11 @@ msgid "Detect overhang wall" msgstr "Определять нависающие периметры" #, c-format, boost-format -msgid "" -"Detect the overhang percentage relative to line width and use different " -"speed to print. For 100%% overhang, bridge speed is used." -msgstr "" -"Определяет процент нависания относительно ширины линии и использует разную " -"скорость печати. Для 100%%-го свеса используется скорость печати мостов." +msgid "Detect the overhang percentage relative to line width and use different speed to print. For 100%% overhang, bridge speed is used." +msgstr "Определяет процент нависания относительно ширины линии и использует разную скорость печати. Для 100%%-го свеса используется скорость печати мостов." -msgid "" -"Line width of inner wall. If expressed as a %, it will be computed over the " -"nozzle diameter." -msgstr "" -"Ширина экструзии внутренних периметров. Если задано в процентах, то значение " -"вычисляться относительно диаметра сопла." +msgid "Line width of inner wall. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии внутренних периметров. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Speed of inner wall" msgstr "Скорость печати внутренних периметров." @@ -11598,38 +10182,27 @@ msgid "Alternate extra wall" msgstr "Чередующаяся дополнительная стенка" msgid "" -"This setting adds an extra wall to every other layer. This way the infill " -"gets wedged vertically between the walls, resulting in stronger prints. \n" +"This setting adds an extra wall to every other layer. This way the infill gets wedged vertically between the walls, resulting in stronger prints. \n" "\n" -"When this option is enabled, the ensure vertical shell thickness option " -"needs to be disabled. \n" +"When this option is enabled, the ensure vertical shell thickness option needs to be disabled. \n" "\n" -"Using lightning infill together with this option is not recommended as there " -"is limited infill to anchor the extra perimeters to." +"Using lightning infill together with this option is not recommended as there is limited infill to anchor the extra perimeters to." msgstr "" -"Печать дополнительного периметра через каждый слой. Таким образом, линии " -"заполнения заключаются между этими дополнительными стенками, что приводит к " -"повышению прочности печати.\n" +"Печать дополнительного периметра через каждый слой. Таким образом, линии заполнения заключаются между этими дополнительными стенками, что приводит к повышению " +"прочности печати.\n" "\n" -"При включении этой опции необходимо отключить опцию «Обеспечивать верт. " -"толщину оболочки».\n" +"При включении этой опции необходимо отключить опцию «Обеспечивать верт. толщину оболочки».\n" "\n" -"Использование шаблона заполнения «Молния» вместе с этой опцией не " -"рекомендуется, поскольку количество заполнения, к которому можно прикрепить " -"дополнительные периметры, ограничено." +"Использование шаблона заполнения «Молния» вместе с этой опцией не рекомендуется, поскольку количество заполнения, к которому можно прикрепить дополнительные " +"периметры, ограничено." msgid "" -"If you want to process the output G-code through custom scripts, just list " -"their absolute paths here. Separate multiple scripts with a semicolon. " -"Scripts will be passed the absolute path to the G-code file as the first " -"argument, and they can access the Orca Slicer config settings by reading " -"environment variables." +"If you want to process the output G-code through custom scripts, just list their absolute paths here. Separate multiple scripts with a semicolon. Scripts will be " +"passed the absolute path to the G-code file as the first argument, and they can access the Orca Slicer config settings by reading environment variables." msgstr "" -"Если вы хотите обработать выходной G-код с помощью пользовательских " -"скриптов, просто перечислите здесь абсолютные пути к ним. Разделяйте скрипты " -"точкой с запятой. Скриптам будет передан абсолютный путь к файлу G-кода в " -"качестве первого аргумента, и они смогут получить доступ к настройкам " -"конфигурации Orca Slicer, читая переменные окружения." +"Если вы хотите обработать выходной G-код с помощью пользовательских скриптов, просто перечислите здесь абсолютные пути к ним. Разделяйте скрипты точкой с " +"запятой. Скриптам будет передан абсолютный путь к файлу G-кода в качестве первого аргумента, и они смогут получить доступ к настройкам конфигурации Orca Slicer, " +"читая переменные окружения." msgid "Printer notes" msgstr "Примечания к принтеру" @@ -11641,9 +10214,7 @@ msgid "Raft contact Z distance" msgstr "Расстояние от подложки до модели по вертикали" msgid "Z gap between object and raft. Ignored for soluble interface" -msgstr "" -"Зазор между моделью и подложкой. Значение игнорируется при выборе " -"растворимого материала." +msgstr "Зазор между моделью и подложкой. Значение игнорируется при выборе растворимого материала." msgid "Raft expansion" msgstr "Расширение подложки" @@ -11661,48 +10232,34 @@ msgid "Initial layer expansion" msgstr "Расширение первого слоя" msgid "Expand the first raft or support layer to improve bed plate adhesion" -msgstr "" -"Расширение первого слоя подложки или поддержки в плоскости XY для улучшения " -"адгезии с материалами склонными к отлипанию и закручиванию." +msgstr "Расширение первого слоя подложки или поддержки в плоскости XY для улучшения адгезии с материалами склонными к отлипанию и закручиванию." msgid "Raft layers" msgstr "Слоёв в подложке" -msgid "" -"Object will be raised by this number of support layers. Use this function to " -"avoid wrapping when print ABS" +msgid "Object will be raised by this number of support layers. Use this function to avoid wrapping when print ABS" msgstr "" -"Параметр устанавливает высоту подложки в слоях, тем самым поднимая модель на " -"заданное количество слоёв от стола. Используйте эту функцию, чтобы избежать " +"Параметр устанавливает высоту подложки в слоях, тем самым поднимая модель на заданное количество слоёв от стола. Используйте эту функцию, чтобы избежать " "деформации при печати ABS пластиком." msgid "" -"G-code path is genereated after simplifing the contour of model to avoid too " -"much points and gcode lines in gcode file. Smaller value means higher " -"resolution and more time to slice" +"G-code path is genereated after simplifing the contour of model to avoid too much points and gcode lines in gcode file. Smaller value means higher resolution and " +"more time to slice" msgstr "" -"Разрешение G-кода. Путь G-кода создаётся после упрощения контура модели, " -"чтобы избежать слишком большого количества точек и линий в G-коде. Меньшее " -"значение означает более высокое разрешение и больше времени для нарезки." +"Разрешение G-кода. Путь G-кода создаётся после упрощения контура модели, чтобы избежать слишком большого количества точек и линий в G-коде. Меньшее значение " +"означает более высокое разрешение и больше времени для нарезки." msgid "Travel distance threshold" msgstr "Порог перемещения для отката" -msgid "" -"Only trigger retraction when the travel distance is longer than this " -"threshold" -msgstr "" -"Откат будет срабатывать только в том случае, если расстояние перемещения " -"превысит этот порог." +msgid "Only trigger retraction when the travel distance is longer than this threshold" +msgstr "Откат будет срабатывать только в том случае, если расстояние перемещения превысит этот порог." msgid "Retract amount before wipe" msgstr "Величина отката перед очисткой" -msgid "" -"The length of fast retraction before wipe, relative to retraction length" -msgstr "" -"Длина быстрого отката перед очисткой, выраженная в процентах от общей длины " -"отката." +msgid "The length of fast retraction before wipe, relative to retraction length" +msgstr "Длина быстрого отката перед очисткой, выраженная в процентах от общей длины отката." msgid "Retract when change layer" msgstr "Откат при смене слоя" @@ -11713,47 +10270,34 @@ msgstr "Эта опция включает принудительный отка msgid "Retraction Length" msgstr "Длина отката" -msgid "" -"Some amount of material in extruder is pulled back to avoid ooze during long " -"travel. Set zero to disable retraction" -msgstr "" -"Некоторое количество материала в экструдере откатывается назад, чтобы " -"избежать его течи при длительном перемещении. 0 - отключение отката." +msgid "Some amount of material in extruder is pulled back to avoid ooze during long travel. Set zero to disable retraction" +msgstr "Некоторое количество материала в экструдере откатывается назад, чтобы избежать его течи при длительном перемещении. 0 - отключение отката." msgid "Z hop when retract" msgstr "Подъём оси Z при откате" msgid "" -"Whenever the retraction is done, the nozzle is lifted a little to create " -"clearance between nozzle and the print. It prevents nozzle from hitting the " -"print when travel move. Using spiral line to lift z can prevent stringing" +"Whenever the retraction is done, the nozzle is lifted a little to create clearance between nozzle and the print. It prevents nozzle from hitting the print when " +"travel move. Using spiral line to lift z can prevent stringing" msgstr "" -"Здесь задаётся на сколько миллиметров будет каждый раз приподниматься ось Z, " -"когда срабатывает откат. Это предотвращает задевание соплом печатаемой " -"модели при перемещении. Использование спирального типа подъёма оси Z может " -"предотвратить образование паутины." +"Здесь задаётся на сколько миллиметров будет каждый раз приподниматься ось Z, когда срабатывает откат. Это предотвращает задевание соплом печатаемой модели при " +"перемещении. Использование спирального типа подъёма оси Z может предотвратить образование паутины." msgid "Z hop lower boundary" msgstr "Приподнимать ось Z только ниже" -msgid "" -"Z hop will only come into effect when Z is above this value and is below the " -"parameter: \"Z hop upper boundary\"" +msgid "Z hop will only come into effect when Z is above this value and is below the parameter: \"Z hop upper boundary\"" msgstr "" -"Если указать положительное значение, ось Z будет подниматься только ниже " -"(до) заданной здесь высоты (высота считается от стола). Таким образом вы " -"можете запретить подъём оси Z выше установленной высоты." +"Если указать положительное значение, ось Z будет подниматься только ниже (до) заданной здесь высоты (высота считается от стола). Таким образом вы можете " +"запретить подъём оси Z выше установленной высоты." msgid "Z hop upper boundary" msgstr "Приподнимать ось Z только выше" -msgid "" -"If this value is positive, Z hop will only come into effect when Z is above " -"the parameter: \"Z hop lower boundary\" and is below this value" +msgid "If this value is positive, Z hop will only come into effect when Z is above the parameter: \"Z hop lower boundary\" and is below this value" msgstr "" -"Если указать положительное значение, ось Z будет подниматься только выше " -"(после) заданной здесь высоты (высота считается от стола). Таким образом вы " -"можете отключить подъём оси Z при печати на первых слоях (в начале печати)." +"Если указать положительное значение, ось Z будет подниматься только выше (после) заданной здесь высоты (высота считается от стола). Таким образом вы можете " +"отключить подъём оси Z при печати на первых слоях (в начале печати)." msgid "Z hop type" msgstr "Тип подъёма оси Z" @@ -11767,34 +10311,24 @@ msgstr "Спиральный" msgid "Only lift Z above" msgstr "Приподнимать ось Z только выше" -msgid "" -"If you set this to a positive value, Z lift will only take place above the " -"specified absolute Z." +msgid "If you set this to a positive value, Z lift will only take place above the specified absolute Z." msgstr "" -"Если указать положительное значение, ось Z будет подниматься только выше " -"(после) заданной здесь высоты (высота считается от стола). Таким образом вы " -"можете отключить подъём оси Z при печати первых слоёв." +"Если указать положительное значение, ось Z будет подниматься только выше (после) заданной здесь высоты (высота считается от стола). Таким образом вы можете " +"отключить подъём оси Z при печати первых слоёв." msgid "Only lift Z below" msgstr "Приподнимать ось Z только ниже" -msgid "" -"If you set this to a positive value, Z lift will only take place below the " -"specified absolute Z." +msgid "If you set this to a positive value, Z lift will only take place below the specified absolute Z." msgstr "" -"Если указать положительное значение, ось Z будет подниматься только ниже " -"(до) заданной здесь высоты (высота считается от стола). Таким образом вы " -"можете запретить подъём оси Z выше установленной высоты." +"Если указать положительное значение, ось Z будет подниматься только ниже (до) заданной здесь высоты (высота считается от стола). Таким образом вы можете " +"запретить подъём оси Z выше установленной высоты." msgid "On surfaces" msgstr "На поверхностях" -msgid "" -"Enforce Z Hop behavior. This setting is impacted by the above settings (Only " -"lift Z above/below)." -msgstr "" -"Принудительное поднятие оси Z. На этот параметр влияют указанные выше " -"параметры (Приподнимать ось Z только выше/ниже)." +msgid "Enforce Z Hop behavior. This setting is impacted by the above settings (Only lift Z above/below)." +msgstr "Принудительное поднятие оси Z. На этот параметр влияют указанные выше параметры (Приподнимать ось Z только выше/ниже)." msgid "All Surfaces" msgstr "Все верхние поверхности" @@ -11811,22 +10345,13 @@ msgstr "На верхней и нижней" msgid "Extra length on restart" msgstr "Доп. длина подачи перед возобновлением печати" -msgid "" -"When the retraction is compensated after the travel move, the extruder will " -"push this additional amount of filament. This setting is rarely needed." +msgid "When the retraction is compensated after the travel move, the extruder will push this additional amount of filament. This setting is rarely needed." msgstr "" -"После того как экструдер совершил откат и переместился в другое место " -"печати, происходит обратная подача того же количества материала + заданное " -"тут значение. Для увеличения длины выдавливания ставится положительное " -"значение (например 0.5 мм), для уменьшения отрицательное. Этот параметр " -"редко нуждается в правке." +"После того как экструдер совершил откат и переместился в другое место печати, происходит обратная подача того же количества материала + заданное тут значение. " +"Для увеличения длины выдавливания ставится положительное значение (например 0.5 мм), для уменьшения отрицательное. Этот параметр редко нуждается в правке." -msgid "" -"When the retraction is compensated after changing tool, the extruder will " -"push this additional amount of filament." -msgstr "" -"Компенсация длины выдавливаемого пластика перед возобновлением печати после " -"смены сопла." +msgid "When the retraction is compensated after changing tool, the extruder will push this additional amount of filament." +msgstr "Компенсация длины выдавливаемого пластика перед возобновлением печати после смены сопла." msgid "Retraction Speed" msgstr "Скорость извлечения при откате" @@ -11837,23 +10362,14 @@ msgstr "Скорость извлечения материала при отка msgid "Deretraction Speed" msgstr "Скорость заправки при откате" -msgid "" -"Speed for reloading filament into extruder. Zero means same speed with " -"retraction" -msgstr "" -"Скорость возврата материала при откате. Если оставить 0, будет " -"использоваться та же скорость что и при извлечении." +msgid "Speed for reloading filament into extruder. Zero means same speed with retraction" +msgstr "Скорость возврата материала при откате. Если оставить 0, будет использоваться та же скорость что и при извлечении." msgid "Use firmware retraction" msgstr "Исп. откат из прошивки" -msgid "" -"This experimental setting uses G10 and G11 commands to have the firmware " -"handle the retraction. This is only supported in recent Marlin." -msgstr "" -"Эта экспериментальная опция использует команды G10 и G11, чтобы сама " -"прошивка обрабатывала откаты. Поддерживается только в последних версиях " -"Marlin." +msgid "This experimental setting uses G10 and G11 commands to have the firmware handle the retraction. This is only supported in recent Marlin." +msgstr "Эта экспериментальная опция использует команды G10 и G11, чтобы сама прошивка обрабатывала откаты. Поддерживается только в последних версиях Marlin." msgid "Show auto-calibration marks" msgstr "Отображать на столе линии автокалибровки" @@ -11861,11 +10377,8 @@ msgstr "Отображать на столе линии автокалибров msgid "Disable set remaining print time" msgstr "Откл. генерацию оставшегося времени печати" -msgid "" -"Disable generating of the M73: Set remaining print time in the final gcode" -msgstr "" -"Отключение генерации команды M73 - вывода оставшегося времени печати в " -"конечный G-код." +msgid "Disable generating of the M73: Set remaining print time in the final gcode" +msgstr "Отключение генерации команды M73 - вывода оставшегося времени печати в конечный G-код." msgid "Seam position" msgstr "Позиция шва" @@ -11888,34 +10401,24 @@ msgstr "Случайно" msgid "Staggered inner seams" msgstr "Смещение внутренних швов" -msgid "" -"This option causes the inner seams to be shifted backwards based on their " -"depth, forming a zigzag pattern." -msgstr "" -"Этот параметр заставляет внутренние швы смещаться назад в зависимости от их " -"глубины, образуя зигзагообразный рисунок." +msgid "This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern." +msgstr "Этот параметр заставляет внутренние швы смещаться назад в зависимости от их глубины, образуя зигзагообразный рисунок." msgid "Seam gap" msgstr "Зазор шва" msgid "" -"In order to reduce the visibility of the seam in a closed loop extrusion, " -"the loop is interrupted and shortened by a specified amount.\n" -"This amount can be specified in millimeters or as a percentage of the " -"current extruder diameter. The default value for this parameter is 10%." +"In order to reduce the visibility of the seam in a closed loop extrusion, the loop is interrupted and shortened by a specified amount.\n" +"This amount can be specified in millimeters or as a percentage of the current extruder diameter. The default value for this parameter is 10%." msgstr "" -"Чтобы уменьшить видимость шва при печати замкнутого контура, контур будет " -"укорачиваться на заданную величину.\n" -"Это величина может быть указана в миллиметрах или в процентах от текущего " -"диаметра сопла. Значение по умолчанию - 10%." +"Чтобы уменьшить видимость шва при печати замкнутого контура, контур будет укорачиваться на заданную величину.\n" +"Это величина может быть указана в миллиметрах или в процентах от текущего диаметра сопла. Значение по умолчанию - 10%." msgid "Scarf joint seam (beta)" msgstr "Клиновидный шов (beta)" msgid "Use scarf joint to minimize seam visibility and increase seam strength." -msgstr "" -"Использование клиновидного шва для минимизации его видимости и повышения " -"прочности." +msgstr "Использование клиновидного шва для минимизации его видимости и повышения прочности." # ??? msgid "Conditional scarf joint" @@ -11923,67 +10426,47 @@ msgstr "Условие для клиновидного шва" # ??? Будет использоваться клиновидный шов, когда на стене нет достаточно острого угла для эффективного скрытия шва. # Использовать клиновидный шов только на гладких периметрах, где традиционные швы не могут быть эффективно скрыты. -msgid "" -"Apply scarf joints only to smooth perimeters where traditional seams do not " -"conceal the seams at sharp corners effectively." -msgstr "" -"Использовать клиновидный шов только на гладких периметрах, где без острого " -"угла невозможно эффективно скрыть традиционный шов." +msgid "Apply scarf joints only to smooth perimeters where traditional seams do not conceal the seams at sharp corners effectively." +msgstr "Использовать клиновидный шов только на гладких периметрах, где без острого угла невозможно эффективно скрыть традиционный шов." msgid "Conditional angle threshold" msgstr "Пороговый угол для клиновидного шва" msgid "" -"This option sets the threshold angle for applying a conditional scarf joint " -"seam.\n" -"If the maximum angle within the perimeter loop exceeds this value " -"(indicating the absence of sharp corners), a scarf joint seam will be used. " -"The default value is 155°." +"This option sets the threshold angle for applying a conditional scarf joint seam.\n" +"If the maximum angle within the perimeter loop exceeds this value (indicating the absence of sharp corners), a scarf joint seam will be used. The default value " +"is 155°." msgstr "" -"Этот параметр задаёт пороговое значение угола для применения клиновидного " -"шва.\n" -"Если максимальный угол в контуре периметра превышает это значение (что " -"указывает на отсутствие острых углов), будет использован клиновидный шов. " -"Значение по умолчанию - 155°." +"Этот параметр задаёт пороговое значение угола для применения клиновидного шва.\n" +"Если максимальный угол в контуре периметра превышает это значение (что указывает на отсутствие острых углов), будет использован клиновидный шов. Значение по " +"умолчанию - 155°." msgid "Conditional overhang threshold" msgstr "Пороговая величина нависания" #, no-c-format, no-boost-format msgid "" -"This option determines the overhang threshold for the application of scarf " -"joint seams. If the unsupported portion of the perimeter is less than this " -"threshold, scarf joint seams will be applied. The default threshold is set " -"at 40% of the external wall's width. Due to performance considerations, the " -"degree of overhang is estimated." +"This option determines the overhang threshold for the application of scarf joint seams. If the unsupported portion of the perimeter is less than this threshold, " +"scarf joint seams will be applied. The default threshold is set at 40% of the external wall's width. Due to performance considerations, the degree of overhang is " +"estimated." msgstr "" -"Этот параметр задаёт пороговое значение нависания для применения " -"клиновидного шва. Если неподдерживаемая часть периметра меньше этого " -"порогового значения, то будут применён клиновидный шов. Пороговое значение " -"по умолчанию установлено на 40% от ширины внешней периметра. Из соображений " -"производительности оценивается степень нависания." +"Этот параметр задаёт пороговое значение нависания для применения клиновидного шва. Если неподдерживаемая часть периметра меньше этого порогового значения, то " +"будут применён клиновидный шов. Пороговое значение по умолчанию установлено на 40% от ширины внешней периметра. Из соображений производительности оценивается " +"степень нависания." msgid "Scarf joint speed" msgstr "Скорость клиновидного шва" msgid "" -"This option sets the printing speed for scarf joints. It is recommended to " -"print scarf joints at a slow speed (less than 100 mm/s). It's also " -"advisable to enable 'Extrusion rate smoothing' if the set speed varies " -"significantly from the speed of the outer or inner walls. If the speed " -"specified here is higher than the speed of the outer or inner walls, the " -"printer will default to the slower of the two speeds. When specified as a " -"percentage (e.g., 80%), the speed is calculated based on the respective " -"outer or inner wall speed. The default value is set to 100%." +"This option sets the printing speed for scarf joints. It is recommended to print scarf joints at a slow speed (less than 100 mm/s). It's also advisable to " +"enable 'Extrusion rate smoothing' if the set speed varies significantly from the speed of the outer or inner walls. If the speed specified here is higher than " +"the speed of the outer or inner walls, the printer will default to the slower of the two speeds. When specified as a percentage (e.g., 80%), the speed is " +"calculated based on the respective outer or inner wall speed. The default value is set to 100%." msgstr "" -"Этот параметр задает скорость печати клиновидного шва. Рекомендуется " -"печатать его на низкой скорости (менее 100 мм/с). Также рекомендуется " -"включить функцию «Сглаживание скорости экструзии«, если заданная скорость " -"значительно отличается от скорости внешних или внутренних периметров. Если " -"заданная здесь скорость выше скорости внешних или внутренних периметров, " -"принтер по умолчанию будет использовать более медленную из двух скоростей. " -"Если скорость указана в процентах, то она рассчитывается на основе скорости " -"внешнего или внутреннего периметра. По умолчанию - 100%." +"Этот параметр задает скорость печати клиновидного шва. Рекомендуется печатать его на низкой скорости (менее 100 мм/с). Также рекомендуется включить функцию " +"«Сглаживание скорости экструзии«, если заданная скорость значительно отличается от скорости внешних или внутренних периметров. Если заданная здесь скорость выше " +"скорости внешних или внутренних периметров, принтер по умолчанию будет использовать более медленную из двух скоростей. Если скорость указана в процентах, то она " +"рассчитывается на основе скорости внешнего или внутреннего периметра. По умолчанию - 100%." msgid "Scarf joint flow ratio" msgstr "Поток клиновидного шва" @@ -11996,12 +10479,10 @@ msgstr "Начальная высота клиновидного шва" msgid "" "Start height of the scarf.\n" -"This amount can be specified in millimeters or as a percentage of the " -"current layer height. The default value for this parameter is 0." +"This amount can be specified in millimeters or as a percentage of the current layer height. The default value for this parameter is 0." msgstr "" "Начальная высота клиновидного шва.\n" -"Значение может быть задано в миллиметрах или в процентах от высоты текущего " -"слоя. Значение по умолчанию - 0." +"Значение может быть задано в миллиметрах или в процентах от высоты текущего слоя. Значение по умолчанию - 0." msgid "Scarf around entire wall" msgstr "Клиновидный шов по всей стене" @@ -12012,12 +10493,8 @@ msgstr "Клиновидный шов простирается на всю вы msgid "Scarf length" msgstr "Длина клиновидного шва" -msgid "" -"Length of the scarf. Setting this parameter to zero effectively disables the " -"scarf." -msgstr "" -"Длина клиновидного шва. Установка этого параметра на ноль фактически " -"отключает шарф." +msgid "Length of the scarf. Setting this parameter to zero effectively disables the scarf." +msgstr "Длина клиновидного шва. Установка этого параметра на ноль фактически отключает шарф." msgid "Scarf steps" msgstr "Шагов клиновидного шва" @@ -12035,60 +10512,43 @@ msgid "Role base wipe speed" msgstr "Скорость очистки по типу экструзии" msgid "" -"The wipe speed is determined by the speed of the current extrusion role.e.g. " -"if a wipe action is executed immediately following an outer wall extrusion, " -"the speed of the outer wall extrusion will be utilized for the wipe action." +"The wipe speed is determined by the speed of the current extrusion role.e.g. if a wipe action is executed immediately following an outer wall extrusion, the " +"speed of the outer wall extrusion will be utilized for the wipe action." msgstr "" -"Скорость очистки будет определяться скоростью текущего типа экструзии, т.е " -"если операция очистки выполняется сразу после экструзии внешнего периметра, " -"то для очистки используется скорость экструзии внешнего периметра." +"Скорость очистки будет определяться скоростью текущего типа экструзии, т.е если операция очистки выполняется сразу после экструзии внешнего периметра, то для " +"очистки используется скорость экструзии внешнего периметра." msgid "Wipe on loops" msgstr "Очистка в периметры" -msgid "" -"To minimize the visibility of the seam in a closed loop extrusion, a small " -"inward movement is executed before the extruder leaves the loop." -msgstr "" -"Чтобы минимизировать видимость шва при экструзии по замкнутому контуру, " -"перед выходом экструдера из контура выполняется небольшое движение внутрь." +msgid "To minimize the visibility of the seam in a closed loop extrusion, a small inward movement is executed before the extruder leaves the loop." +msgstr "Чтобы минимизировать видимость шва при экструзии по замкнутому контуру, перед выходом экструдера из контура выполняется небольшое движение внутрь." msgid "Wipe before external loop" msgstr "Очистка перед печатью внешнего периметра" msgid "" -"To minimise visibility of potential overextrusion at the start of an " -"external perimeter when printing with Outer/Inner or Inner/Outer/Inner wall " -"print order, the deretraction is performed slightly on the inside from the " -"start of the external perimeter. That way any potential over extrusion is " -"hidden from the outside surface. \n" +"To minimise visibility of potential overextrusion at the start of an external perimeter when printing with Outer/Inner or Inner/Outer/Inner wall print order, the " +"deretraction is performed slightly on the inside from the start of the external perimeter. That way any potential over extrusion is hidden from the outside " +"surface. \n" "\n" -"This is useful when printing with Outer/Inner or Inner/Outer/Inner wall " -"print order as in these modes it is more likely an external perimeter is " -"printed immediately after a deretraction move." +"This is useful when printing with Outer/Inner or Inner/Outer/Inner wall print order as in these modes it is more likely an external perimeter is printed " +"immediately after a deretraction move." msgstr "" -"Чтобы минимизировать возможную переэкструзию в начале внешнего периметра при " -"порядке печати «Внешний/Внутренний» или «Внутренний/Внешний/Внутренний», " -"выдавливание выполняется немного внутрь от точки начала внешнего периметра. " -"Таким образом, возможная избыточная экструзия не будет видна на внешней " -"поверхности.\n" +"Чтобы минимизировать возможную переэкструзию в начале внешнего периметра при порядке печати «Внешний/Внутренний» или «Внутренний/Внешний/Внутренний», " +"выдавливание выполняется немного внутрь от точки начала внешнего периметра. Таким образом, возможная избыточная экструзия не будет видна на внешней поверхности.\n" "\n" -"Это полезно при порядке печати периметров «Внешний/Внутренний» или " -"«Внутренний/Внешний/Внутренний», так как в этих режимах внешний периметр " -"чаще всего печатается сразу после подачи." +"Это полезно при порядке печати периметров «Внешний/Внутренний» или «Внутренний/Внешний/Внутренний», так как в этих режимах внешний периметр чаще всего печатается " +"сразу после подачи." msgid "Wipe speed" msgstr "Скорость очистки" msgid "" -"The wipe speed is determined by the speed setting specified in this " -"configuration.If the value is expressed as a percentage (e.g. 80%), it will " -"be calculated based on the travel speed setting above.The default value for " -"this parameter is 80%" +"The wipe speed is determined by the speed setting specified in this configuration.If the value is expressed as a percentage (e.g. 80%), it will be calculated " +"based on the travel speed setting above.The default value for this parameter is 80%" msgstr "" -"Скорость очистки определяется текущей настройкой. Если задано в процентах, " -"то она вычисляться относительно скорости перемещения. 80% - значение по " -"умолчанию." +"Скорость очистки определяется текущей настройкой. Если задано в процентах, то она вычисляться относительно скорости перемещения. 80% - значение по умолчанию." msgid "Skirt distance" msgstr "Расстояние до юбки" @@ -12114,87 +10574,55 @@ msgstr "Скорость печати юбки" msgid "Speed of skirt, in mm/s. Zero means use default layer extrusion speed." msgstr "Скорость печати юбки (мм/с). 0 - скорость экструзии слоя по умолчанию." -msgid "" -"The printing speed in exported gcode will be slowed down, when the estimated " -"layer time is shorter than this value, to get better cooling for these layers" +msgid "The printing speed in exported gcode will be slowed down, when the estimated layer time is shorter than this value, to get better cooling for these layers" msgstr "" -"Скорость печати в экспортированном G-коде будет замедлена, если расчётное " -"время печати слоя меньше этого значения, для обеспечения лучшего охлаждения " -"этих слоёв." +"Скорость печати в экспортированном G-коде будет замедлена, если расчётное время печати слоя меньше этого значения, для обеспечения лучшего охлаждения этих слоёв." msgid "Minimum sparse infill threshold" msgstr "Мин. порог разреженного заполнения" -msgid "" -"Sparse infill area which is smaller than threshold value is replaced by " -"internal solid infill" -msgstr "" -"Область с разреженным заполнением, размер которого меньше этого порогового " -"значения, заменяется сплошным заполнением." +msgid "Sparse infill area which is smaller than threshold value is replaced by internal solid infill" +msgstr "Область с разреженным заполнением, размер которого меньше этого порогового значения, заменяется сплошным заполнением." -msgid "" -"Line width of internal solid infill. If expressed as a %, it will be " -"computed over the nozzle diameter." -msgstr "" -"Ширина экструзии для внутреннего сплошного заполнения. Если задано в " -"процентах, то значение вычисляться относительно диаметра сопла." +msgid "Line width of internal solid infill. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для внутреннего сплошного заполнения. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Speed of internal solid infill, not the top and bottom surface" -msgstr "" -"Скорость печати внутреннего сплошного заполнения, за исключением верхней и " -"нижней поверхностей." +msgstr "Скорость печати внутреннего сплошного заполнения, за исключением верхней и нижней поверхностей." msgid "Spiral vase" msgstr "Спиральная ваза" msgid "" -"Spiralize smooths out the z moves of the outer contour. And turns a solid " -"model into a single walled print with solid bottom layers. The final " -"generated model has no seam" +"Spiralize smooths out the z moves of the outer contour. And turns a solid model into a single walled print with solid bottom layers. The final generated model " +"has no seam" msgstr "" -"Печать спиральных и пустотелых, а также тонкостенных моделей. Модель " -"печатается в одну стенку без верхней поверхности, заполнения и поддержки. " -"При этом сопло движется вдоль периметра непрерывно постепенно поднимаясь, " -"так получаются ровные красивые вазы без видимых швов." +"Печать спиральных и пустотелых, а также тонкостенных моделей. Модель печатается в одну стенку без верхней поверхности, заполнения и поддержки. При этом сопло " +"движется вдоль периметра непрерывно постепенно поднимаясь, так получаются ровные красивые вазы без видимых швов." msgid "Smooth Spiral" msgstr "Сглаживать спиральные контуры" -msgid "" -"Smooth Spiral smoothes out X and Y moves as wellresulting in no visible seam " -"at all, even in the XY directions on walls that are not vertical" -msgstr "" -"Опция сглаживает перемещение по осям X и Y, в результате чего шов " -"отсутствует даже в направлении XY на невертикальных периметрах." +msgid "Smooth Spiral smoothes out X and Y moves as wellresulting in no visible seam at all, even in the XY directions on walls that are not vertical" +msgstr "Опция сглаживает перемещение по осям X и Y, в результате чего шов отсутствует даже в направлении XY на невертикальных периметрах." msgid "Max XY Smoothing" msgstr "Макс. сглаживание по XY" -msgid "" -"Maximum distance to move points in XY to try to achieve a smooth spiralIf " -"expressed as a %, it will be computed over nozzle diameter" +msgid "Maximum distance to move points in XY to try to achieve a smooth spiralIf expressed as a %, it will be computed over nozzle diameter" msgstr "" -"Максимальное расстояние перемещения точек по XY для достижения плавной " -"спирали. Если задано в процентах, то значение вычисляться относительно " -"диаметра сопла." +"Максимальное расстояние перемещения точек по XY для достижения плавной спирали. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "" -"If smooth or traditional mode is selected, a timelapse video will be " -"generated for each print. After each layer is printed, a snapshot is taken " -"with the chamber camera. All of these snapshots are composed into a " -"timelapse video when printing completes. If smooth mode is selected, the " -"toolhead will move to the excess chute after each layer is printed and then " -"take a snapshot. Since the melt filament may leak from the nozzle during the " -"process of taking a snapshot, prime tower is required for smooth mode to " -"wipe nozzle." +"If smooth or traditional mode is selected, a timelapse video will be generated for each print. After each layer is printed, a snapshot is taken with the chamber " +"camera. All of these snapshots are composed into a timelapse video when printing completes. If smooth mode is selected, the toolhead will move to the excess " +"chute after each layer is printed and then take a snapshot. Since the melt filament may leak from the nozzle during the process of taking a snapshot, prime tower " +"is required for smooth mode to wipe nozzle." msgstr "" -"Если выбран плавный или обычный режим записи, то при каждой печати будет " -"создаваться ускоренное видео печати. После печати каждого слоя встроенная " -"камера делает снимок и по её завершении все эти снимки объединяются в единое " -"ускоренное видео. Если включён плавный режим, то после печати каждого слоя " -"головка перемещается к лотку для удаления излишков, а уже затем делается " -"снимок. Очистка сопла на черновой башне обязательна, т.к. при плавном режиме " -"возможно вытекание материалы из сопла когда делается снимок." +"Если выбран плавный или обычный режим записи, то при каждой печати будет создаваться ускоренное видео печати. После печати каждого слоя встроенная камера делает " +"снимок и по её завершении все эти снимки объединяются в единое ускоренное видео. Если включён плавный режим, то после печати каждого слоя головка перемещается к " +"лотку для удаления излишков, а уже затем делается снимок. Очистка сопла на черновой башне обязательна, т.к. при плавном режиме возможно вытекание материалы из " +"сопла когда делается снимок." msgid "Traditional" msgstr "Обычный" @@ -12209,32 +10637,23 @@ msgid "Start G-code when start the whole printing" msgstr "G-код выполняемый при каждом запуске печати." msgid "Start G-code when start the printing of this filament" -msgstr "" -"Стартовый G-код выполняемый при запуске печати с текущей пластиковой нитью." +msgstr "Стартовый G-код выполняемый при запуске печати с текущей пластиковой нитью." msgid "Single Extruder Multi Material" msgstr "Мультиматериальный одиночный экструдер" msgid "Use single nozzle to print multi filament" -msgstr "" -"Использование одной экструзионной головы для печати несколькими видами/" -"цветами пластика." +msgstr "Использование одной экструзионной головы для печати несколькими видами/цветами пластика." msgid "Manual Filament Change" msgstr "Ручная замена прутка" msgid "" -"Enable this option to omit the custom Change filament G-code only at the " -"beginning of the print. The tool change command (e.g., T0) will be skipped " -"throughout the entire print. This is useful for manual multi-material " -"printing, where we use M600/PAUSE to trigger the manual filament change " -"action." +"Enable this option to omit the custom Change filament G-code only at the beginning of the print. The tool change command (e.g., T0) will be skipped throughout " +"the entire print. This is useful for manual multi-material printing, where we use M600/PAUSE to trigger the manual filament change action." msgstr "" -"Включите эту опцию, если хотите пропустить пользовательский G-код смены " -"прутка только в начале печати. Команда смены инструмента (например, T0) " -"будет пропускаться на протяжении всей печати. Это полезно при ручной " -"мультиматериальной печати, где для запуска операции ручной смены прутка " -"используется команда M600." +"Включите эту опцию, если хотите пропустить пользовательский G-код смены прутка только в начале печати. Команда смены инструмента (например, T0) будет " +"пропускаться на протяжении всей печати. Это полезно при ручной мультиматериальной печати, где для запуска операции ручной смены прутка используется команда M600." msgid "Purge in prime tower" msgstr "Очистка в черновую башню" @@ -12250,54 +10669,36 @@ msgid "No sparse layers (beta)" msgstr "Без разреженных слоёв (beta)" msgid "" -"If enabled, the wipe tower will not be printed on layers with no " -"toolchanges. On layers with a toolchange, extruder will travel downward to " -"print the wipe tower. User is responsible for ensuring there is no collision " -"with the print." +"If enabled, the wipe tower will not be printed on layers with no toolchanges. On layers with a toolchange, extruder will travel downward to print the wipe tower. " +"User is responsible for ensuring there is no collision with the print." msgstr "" -"Если включено, черновая башня не будет печататься на слоях где не происходит " -"смена материала/инструмента. На слоях, где происходит смена материала, " -"экструдер будет опускаться вниз до верхней части черновой башни, чтобы " -"напечатать её. Это экономит материал и практически во всех случаях сокращает " -"время печати. Рекомендуется помещать черновую башню в задний правый угол " -"печатного стола, а модель в противоположный угол. Функция находится в бета " -"тестировании и в настоящее время программа не проверяет столкновение " -"экструдера с печатаемой моделью при его опускании вниз до черновой башни. " -"Поэтому пользователь сам несет ответственность за правильную настройку всех " -"соответствующих параметров." +"Если включено, черновая башня не будет печататься на слоях где не происходит смена материала/инструмента. На слоях, где происходит смена материала, экструдер " +"будет опускаться вниз до верхней части черновой башни, чтобы напечатать её. Это экономит материал и практически во всех случаях сокращает время печати. " +"Рекомендуется помещать черновую башню в задний правый угол печатного стола, а модель в противоположный угол. Функция находится в бета тестировании и в настоящее " +"время программа не проверяет столкновение экструдера с печатаемой моделью при его опускании вниз до черновой башни. Поэтому пользователь сам несет " +"ответственность за правильную настройку всех соответствующих параметров." msgid "Prime all printing extruders" msgstr "Подготовка всех печатающих экструдеров" -msgid "" -"If enabled, all printing extruders will be primed at the front edge of the " -"print bed at the start of the print." -msgstr "" -"Если этот параметр включён, все печатающие экструдеры в начале печати будут " -"подготавливаться на переднем крае стола." +msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." +msgstr "Если этот параметр включён, все печатающие экструдеры в начале печати будут подготавливаться на переднем крае стола." msgid "Slice gap closing radius" msgstr "Радиус закрытия пробелов при нарезке" msgid "" -"Cracks smaller than 2x gap closing radius are being filled during the " -"triangle mesh slicing. The gap closing operation may reduce the final print " -"resolution, therefore it is advisable to keep the value reasonably low." +"Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. The gap closing operation may reduce the final print resolution, " +"therefore it is advisable to keep the value reasonably low." msgstr "" -"Трещины, меньше чем 2-кратный радиус закрытия пробелов, будут заполняться во " -"время нарезки треугольной сетки. Операция закрытия пробелов может уменьшить " -"окончательное разрешение печати, поэтому рекомендуется выставлять это " -"значение достаточно низким." +"Трещины, меньше чем 2-кратный радиус закрытия пробелов, будут заполняться во время нарезки треугольной сетки. Операция закрытия пробелов может уменьшить " +"окончательное разрешение печати, поэтому рекомендуется выставлять это значение достаточно низким." msgid "Slicing Mode" msgstr "Режим нарезки" -msgid "" -"Use \"Even-odd\" for 3DLabPrint airplane models. Use \"Close holes\" to " -"close all holes in the model." -msgstr "" -"Режим нарезки «чётный-нечётный» используется для моделей самолетов с ресурса " -"3DLabPrint. А «Закрытие отверстий» для закрытия всех отверстий в модели." +msgid "Use \"Even-odd\" for 3DLabPrint airplane models. Use \"Close holes\" to close all holes in the model." +msgstr "Режим нарезки «чётный-нечётный» используется для моделей самолетов с ресурса 3DLabPrint. А «Закрытие отверстий» для закрытия всех отверстий в модели." msgid "Regular" msgstr "Обычный" @@ -12312,14 +10713,11 @@ msgid "Z offset" msgstr "Смещение координат оси Z" msgid "" -"This value will be added (or subtracted) from all the Z coordinates in the " -"output G-code. It is used to compensate for bad Z endstop position: for " -"example, if your endstop zero actually leaves the nozzle 0.3mm far from the " -"print bed, set this to -0.3 (or fix your endstop)." +"This value will be added (or subtracted) from all the Z coordinates in the output G-code. It is used to compensate for bad Z endstop position: for example, if " +"your endstop zero actually leaves the nozzle 0.3mm far from the print bed, set this to -0.3 (or fix your endstop)." msgstr "" -"Это значение будет прибавлено (или вычтено) из всех Z координат в выходном G-" -"коде. Это, например, используется для компенсации неправильного положения " -"концевика оси Z." +"Это значение будет прибавлено (или вычтено) из всех Z координат в выходном G-коде. Это, например, используется для компенсации неправильного положения концевика " +"оси Z." msgid "Enable support" msgstr "Включить поддержку" @@ -12327,15 +10725,10 @@ msgstr "Включить поддержку" msgid "Enable support generation." msgstr "Включить генерацию поддержки." -msgid "" -"normal(auto) and tree(auto) is used to generate support automatically. If " -"normal(manual) or tree(manual) is selected, only support enforcers are " -"generated" +msgid "normal(auto) and tree(auto) is used to generate support automatically. If normal(manual) or tree(manual) is selected, only support enforcers are generated" msgstr "" -"Тип поддержки «Обычная (авто)» и «Древовидная (авто)» используются для " -"автоматического создания поддержки. Если выбран тип поддержки «Обычная " -"(вручную)» или «Древовидная (вручную)», генерируется только принудительная " -"поддержка." +"Тип поддержки «Обычная (авто)» и «Древовидная (авто)» используются для автоматического создания поддержки. Если выбран тип поддержки «Обычная (вручную)» или " +"«Древовидная (вручную)», генерируется только принудительная поддержка." msgid "normal(auto)" msgstr "Обычная (авто)" @@ -12359,9 +10752,7 @@ msgid "Pattern angle" msgstr "Угол печати шаблона поддержки" msgid "Use this setting to rotate the support pattern on the horizontal plane." -msgstr "" -"Используйте эту настройку для поворота шаблона поддержки в горизонтальной " -"плоскости." +msgstr "Используйте эту настройку для поворота шаблона поддержки в горизонтальной плоскости." msgid "On build plate only" msgstr "Поддержка только от стола" @@ -12372,81 +10763,54 @@ msgstr "Создавать поддержку только от стола." msgid "Support critical regions only" msgstr "Поддержка только критических областей" -msgid "" -"Only create support for critical regions including sharp tail, cantilever, " -"etc." -msgstr "" -"Создание поддержек только для критических областей, включая острые концы, " -"консоли (горизонтально выступающие элементы) и т.д." +msgid "Only create support for critical regions including sharp tail, cantilever, etc." +msgstr "Создание поддержек только для критических областей, включая острые концы, консоли (горизонтально выступающие элементы) и т.д." msgid "Remove small overhangs" msgstr "Игнорировать небольшие нависания" msgid "Remove small overhangs that possibly need no supports." -msgstr "" -"Не печатать поддержку под небольшими нависаниями, которые, как вам казалось, " -"нуждаются в них." +msgstr "Не печатать поддержку под небольшими нависаниями, которые, как вам казалось, нуждаются в них." msgid "Top Z distance" msgstr "Зазор поддержки сверху" msgid "The z gap between the top support interface and object" -msgstr "" -"Вертикальное расстояние между верхней частью модели и связующим слоем " -"поддержки." +msgstr "Вертикальное расстояние между верхней частью модели и связующим слоем поддержки." msgid "Bottom Z distance" msgstr "Зазор поддержки снизу" msgid "The z gap between the bottom support interface and object" -msgstr "" -"Вертикальное расстояние между нижней частью модели и связующим слоем " -"поддержки." +msgstr "Вертикальное расстояние между нижней частью модели и связующим слоем поддержки." msgid "Support/raft base" msgstr "Базовая поддержка/подложка" -msgid "" -"Filament to print support base and raft. \"Default\" means no specific " -"filament for support and current filament is used" -msgstr "" -"Пластиковая нить для печати базовой поддержки и подложки. Значение «По " -"умолчанию» означает, что для поддержки используется текущая пластиковая нить." +msgid "Filament to print support base and raft. \"Default\" means no specific filament for support and current filament is used" +msgstr "Пластиковая нить для печати базовой поддержки и подложки. Значение «По умолчанию» означает, что для поддержки используется текущая пластиковая нить." msgid "Avoid interface filament for base" msgstr "Избегать исп. связующего прутка для тела поддержки" -msgid "" -"Avoid using support interface filament to print support base if possible." -msgstr "" -"Избегать использования прутка связующего слоя поддержки для тела поддержки." +msgid "Avoid using support interface filament to print support base if possible." +msgstr "Избегать использования прутка связующего слоя поддержки для тела поддержки." -msgid "" -"Line width of support. If expressed as a %, it will be computed over the " -"nozzle diameter." -msgstr "" -"Ширина экструзии для поддержки. Если задано в процентах, то значение " -"вычисляться относительно диаметра сопла." +msgid "Line width of support. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для поддержки. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Interface use loop pattern" msgstr "Связующий слой петлями" -msgid "" -"Cover the top contact layer of the supports with loops. Disabled by default." -msgstr "" -"Печатать контактный слой связующего слоя поддержки петлями. По умолчанию " -"отключено." +msgid "Cover the top contact layer of the supports with loops. Disabled by default." +msgstr "Печатать контактный слой связующего слоя поддержки петлями. По умолчанию отключено." msgid "Support/raft interface" msgstr "Связующий слой поддержки/подложки" -msgid "" -"Filament to print support interface. \"Default\" means no specific filament " -"for support interface and current filament is used" +msgid "Filament to print support interface. \"Default\" means no specific filament for support interface and current filament is used" msgstr "" -"Пластиковая нить для печати связующего слоя поддержки. Значение «По " -"умолчанию» означает, что для связующего слоя поддержки используется текущая " -"пластиковая нить." +"Пластиковая нить для печати связующего слоя поддержки. Значение «По умолчанию» означает, что для связующего слоя поддержки используется текущая пластиковая нить." msgid "Top interface layers" msgstr "Связующих слоёв сверху" @@ -12467,17 +10831,13 @@ msgid "Top interface spacing" msgstr "Расстояние между линиями связующего слоя сверху" msgid "Spacing of interface lines. Zero means solid interface" -msgstr "" -"Расстояние между линиями связующего слоя сверху. Установите 0, чтобы " -"получить сплошной слой." +msgstr "Расстояние между линиями связующего слоя сверху. Установите 0, чтобы получить сплошной слой." msgid "Bottom interface spacing" msgstr "Расстояние между линиями связующего слоя снизу" msgid "Spacing of bottom interface lines. Zero means solid interface" -msgstr "" -"Расстояние между линиями связующего слоя снизу. Установите 0, чтобы получить " -"сплошной слой." +msgstr "Расстояние между линиями связующего слоя снизу. Установите 0, чтобы получить сплошной слой." msgid "Speed of support interface" msgstr "Скорость печати связующего слоя поддержки." @@ -12498,13 +10858,11 @@ msgid "Interface pattern" msgstr "Шаблон связующего слоя" msgid "" -"Line pattern of support interface. Default pattern for non-soluble support " -"interface is Rectilinear, while default pattern for soluble support " -"interface is Concentric" +"Line pattern of support interface. Default pattern for non-soluble support interface is Rectilinear, while default pattern for soluble support interface is " +"Concentric" msgstr "" -"Шаблон, по которому будет происходить печать связующего слоя поддержки. При " -"выборе по умолчанию, шаблон для нерастворимой связующей поддержки - " -"прямолинейный, для растворимой - концентрический." +"Шаблон, по которому будет происходить печать связующего слоя поддержки. При выборе по умолчанию, шаблон для нерастворимой связующей поддержки - прямолинейный, " +"для растворимой - концентрический." msgid "Rectilinear Interlaced" msgstr "Прямолинейный (чередование направлений)" @@ -12519,31 +10877,23 @@ msgid "Normal Support expansion" msgstr "Горизонтальное расширение поддержки" msgid "Expand (+) or shrink (-) the horizontal span of normal support" -msgstr "" -"Горизонтальное расширение (+) или сужение (-) базовой поддержки в плоскости " -"XY." +msgstr "Горизонтальное расширение (+) или сужение (-) базовой поддержки в плоскости XY." msgid "Speed of support" msgstr "Скорость печати поддержки." msgid "" -"Style and shape of the support. For normal support, projecting the supports " -"into a regular grid will create more stable supports (default), while snug " -"support towers will save material and reduce object scarring.\n" -"For tree support, slim and organic style will merge branches more " -"aggressively and save a lot of material (default organic), while hybrid " -"style will create similar structure to normal support under large flat " -"overhangs." +"Style and shape of the support. For normal support, projecting the supports into a regular grid will create more stable supports (default), while snug support " +"towers will save material and reduce object scarring.\n" +"For tree support, slim and organic style will merge branches more aggressively and save a lot of material (default organic), while hybrid style will create " +"similar structure to normal support under large flat overhangs." msgstr "" "Стиль и форма создаваемой поддержки.\n" "\n" -"Стиль «Сетка» создаёт более устойчивые опоры (по умолчанию). Стиль " -"«Аккуратный» экономит материал и уменьшает образование дефектов на моделях.\n" +"Стиль «Сетка» создаёт более устойчивые опоры (по умолчанию). Стиль «Аккуратный» экономит материал и уменьшает образование дефектов на моделях.\n" "\n" -"Для древовидной поддержки, при стройном и органическом стиле происходит " -"более агрессивное объединение ветвей и экономия материала (по умолчанию " -"органический). В то время как гибридный стиль создаёт структуру, схожую с " -"обычную поддержкой при больших плоских нависаниях." +"Для древовидной поддержки, при стройном и органическом стиле происходит более агрессивное объединение ветвей и экономия материала (по умолчанию органический). В " +"то время как гибридный стиль создаёт структуру, схожую с обычную поддержкой при больших плоских нависаниях." msgid "Snug" msgstr "Аккуратный" @@ -12564,93 +10914,67 @@ msgid "Independent support layer height" msgstr "Независимая высота слоя поддержки" msgid "" -"Support layer uses layer height independent with object layer. This is to " -"support customizing z-gap and save print time.This option will be invalid " -"when the prime tower is enabled." +"Support layer uses layer height independent with object layer. This is to support customizing z-gap and save print time.This option will be invalid when the " +"prime tower is enabled." msgstr "" -"Слои поддержки будут иметь высоту слоя, отличную от высоты слоя модели. Это " -"необходимо для настройки зазора между моделью и поддержкой для экономии " -"времени печати. Опция неактивна, когда включена черновая башня." +"Слои поддержки будут иметь высоту слоя, отличную от высоты слоя модели. Это необходимо для настройки зазора между моделью и поддержкой для экономии времени " +"печати. Опция неактивна, когда включена черновая башня." msgid "Threshold angle" msgstr "Пороговый угол поддержки" -msgid "" -"Support will be generated for overhangs whose slope angle is below the " -"threshold." -msgstr "" -"Для нависаний, угол наклона которых ниже заданного порогового значения, " -"будут использоваться поддержки." +msgid "Support will be generated for overhangs whose slope angle is below the threshold." +msgstr "Для нависаний, угол наклона которых ниже заданного порогового значения, будут использоваться поддержки." msgid "Tree support branch angle" msgstr "Угол нависания ветвей древовидной поддержки" msgid "" -"This setting determines the maximum overhang angle that t he branches of " -"tree support allowed to make.If the angle is increased, the branches can be " -"printed more horizontally, allowing them to reach farther." +"This setting determines the maximum overhang angle that t he branches of tree support allowed to make.If the angle is increased, the branches can be printed more " +"horizontally, allowing them to reach farther." msgstr "" -"Этот параметр определяет максимальный угол нависания ветвей древовидной " -"поддержки. При увеличении угла, ветви печатаются более горизонтально, что " -"позволяет им достигать большего охвата. При указании меньшего угла, " -"поддержка будет более вертикальной и устойчивой." +"Этот параметр определяет максимальный угол нависания ветвей древовидной поддержки. При увеличении угла, ветви печатаются более горизонтально, что позволяет им " +"достигать большего охвата. При указании меньшего угла, поддержка будет более вертикальной и устойчивой." msgid "Preferred Branch Angle" msgstr "Предпочтительный угол ответвления" #. TRN PrintSettings: "Organic supports" > "Preferred Branch Angle" msgid "" -"The preferred angle of the branches, when they do not have to avoid the " -"model. Use a lower angle to make them more vertical and more stable. Use a " -"higher angle for branches to merge faster." +"The preferred angle of the branches, when they do not have to avoid the model. Use a lower angle to make them more vertical and more stable. Use a higher angle " +"for branches to merge faster." msgstr "" -"Предпочтительный угол ответвления ветвей, при котором не нужно избегать " -"модель. При указании меньшего угла поддержка будет более вертикальной и " -"устойчивой. Для получения большего охвата указывайте более высокий угол." +"Предпочтительный угол ответвления ветвей, при котором не нужно избегать модель. При указании меньшего угла поддержка будет более вертикальной и устойчивой. Для " +"получения большего охвата указывайте более высокий угол." msgid "Tree support branch distance" msgstr "Расстояние между ветвями древовидной поддержки" -msgid "" -"This setting determines the distance between neighboring tree support nodes." -msgstr "" -"Этот параметр определяет, насколько далеко должны друг от друга " -"располагаться ветви при касании модели." +msgid "This setting determines the distance between neighboring tree support nodes." +msgstr "Этот параметр определяет, насколько далеко должны друг от друга располагаться ветви при касании модели." msgid "Branch Density" msgstr "Плотность ветвей" #. TRN PrintSettings: "Organic supports" > "Branch Density" msgid "" -"Adjusts the density of the support structure used to generate the tips of " -"the branches. A higher value results in better overhangs but the supports " -"are harder to remove, thus it is recommended to enable top support " -"interfaces instead of a high branch density value if dense interfaces are " -"needed." +"Adjusts the density of the support structure used to generate the tips of the branches. A higher value results in better overhangs but the supports are harder to " +"remove, thus it is recommended to enable top support interfaces instead of a high branch density value if dense interfaces are needed." msgstr "" -"Регулирует плотность создания ветвей в месте контакта с моделью. Большее " -"значение приводит к улучшению качества печати нависаний, но такие поддержки " -"сложнее удалять, поэтому рекомендуется вместо высокого значения плотности " -"ветвей включать связующие слои поддержки." +"Регулирует плотность создания ветвей в месте контакта с моделью. Большее значение приводит к улучшению качества печати нависаний, но такие поддержки сложнее " +"удалять, поэтому рекомендуется вместо высокого значения плотности ветвей включать связующие слои поддержки." msgid "Adaptive layer height" msgstr "Переменная высота слоёв" -msgid "" -"Enabling this option means the height of tree support layer except the " -"first will be automatically calculated " -msgstr "" -"Включение автоматического расчёта высоты слоя древовидной поддержки, кроме " -"первого слоя. " +msgid "Enabling this option means the height of tree support layer except the first will be automatically calculated " +msgstr "Включение автоматического расчёта высоты слоя древовидной поддержки, кроме первого слоя. " msgid "Auto brim width" msgstr "Автоширина каймы" -msgid "" -"Enabling this option means the width of the brim for tree support will be " -"automatically calculated" -msgstr "" -"Включение автоматического расчёта ширины каймы для древовидной поддержки." +msgid "Enabling this option means the width of the brim for tree support will be automatically calculated" +msgstr "Включение автоматического расчёта ширины каймы для древовидной поддержки." msgid "Tree support brim width" msgstr "Ширина каймы древовидной поддержки" @@ -12669,9 +10993,7 @@ msgid "Tree support branch diameter" msgstr "Диаметр ветвей древовидной поддержки" msgid "This setting determines the initial diameter of support nodes." -msgstr "" -"Этот параметр определяет начальный диаметр ветвей, т.е. их диаметр в месте " -"контакта с моделью." +msgstr "Этот параметр определяет начальный диаметр ветвей, т.е. их диаметр в месте контакта с моделью." #. TRN PrintSettings: #lmFIXME msgid "Branch Diameter Angle" @@ -12679,28 +11001,19 @@ msgstr "Угол изменения диаметра ветвей" #. TRN PrintSettings: "Organic supports" > "Branch Diameter Angle" msgid "" -"The angle of the branches' diameter as they gradually become thicker towards " -"the bottom. An angle of 0 will cause the branches to have uniform thickness " -"over their length. A bit of an angle can increase stability of the organic " -"support." +"The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over " +"their length. A bit of an angle can increase stability of the organic support." msgstr "" -"Угол изменения диаметра ветвей по мере их постепенного утолщения к " -"основанию. Если значение угла равно 0, ветви будут иметь одинаковую толщину " -"по всей своей длине. Небольшой угол может повысить устойчивость органической " -"поддержки." +"Угол изменения диаметра ветвей по мере их постепенного утолщения к основанию. Если значение угла равно 0, ветви будут иметь одинаковую толщину по всей своей " +"длине. Небольшой угол может повысить устойчивость органической поддержки." msgid "Branch Diameter with double walls" msgstr "Диаметр ветвей с двойными стенками" #. TRN PrintSettings: "Organic supports" > "Branch Diameter" msgid "" -"Branches with area larger than the area of a circle of this diameter will be " -"printed with double walls for stability. Set this value to zero for no " -"double walls." -msgstr "" -"Ветви, толщина которых больше указанного диаметра, будут напечатаны с " -"двойными стенками для прочности. Установите 0, если двойные стенки у ветвей " -"не нужны." +"Branches with area larger than the area of a circle of this diameter will be printed with double walls for stability. Set this value to zero for no double walls." +msgstr "Ветви, толщина которых больше указанного диаметра, будут напечатаны с двойными стенками для прочности. Установите 0, если двойные стенки у ветвей не нужны." msgid "Support wall loops" msgstr "Периметров поддержки" @@ -12711,45 +11024,31 @@ msgstr "Этот параметр определяет количество пе msgid "Tree support with infill" msgstr "Древовидная поддержка с заполнением" -msgid "" -"This setting specifies whether to add infill inside large hollows of tree " -"support" -msgstr "" -"Этот параметр определяет, следует ли заполнять большие полости внутри " -"древовидной поддержки." +msgid "This setting specifies whether to add infill inside large hollows of tree support" +msgstr "Этот параметр определяет, следует ли заполнять большие полости внутри древовидной поддержки." msgid "Activate temperature control" msgstr "Вкл. контроль температуры" msgid "" -"Enable this option for chamber temperature control. An M191 command will be " -"added before \"machine_start_gcode\"\n" +"Enable this option for chamber temperature control. An M191 command will be added before \"machine_start_gcode\"\n" "G-code commands: M141/M191 S(0-255)" msgstr "" -"Для контроля температуры в камере принтера включите эту опцию. Команда M191 " -"будет добавлена перед стартовый G-кодом принтера (machine_start_gcode).\n" +"Для контроля температуры в камере принтера включите эту опцию. Команда M191 будет добавлена перед стартовый G-кодом принтера (machine_start_gcode).\n" "G-код команда: M141/M191 S(0-255)" msgid "Chamber temperature" msgstr "Температура термокамеры" msgid "" -"Higher chamber temperature can help suppress or reduce warping and " -"potentially lead to higher interlayer bonding strength for high temperature " -"materials like ABS, ASA, PC, PA and so on.At the same time, the air " -"filtration of ABS and ASA will get worse.While for PLA, PETG, TPU, PVA and " -"other low temperature materials,the actual chamber temperature should not be " -"high to avoid cloggings, so 0 which stands for turning off is highly " -"recommended" +"Higher chamber temperature can help suppress or reduce warping and potentially lead to higher interlayer bonding strength for high temperature materials like " +"ABS, ASA, PC, PA and so on.At the same time, the air filtration of ABS and ASA will get worse.While for PLA, PETG, TPU, PVA and other low temperature materials," +"the actual chamber temperature should not be high to avoid cloggings, so 0 which stands for turning off is highly recommended" msgstr "" -"Более высокая температура в камере может помочь уменьшить или даже исключить " -"коробление материала. Так же это улучшает межслойное соединения у " -"высокотемпературных материалов, таких как ABS, ASA, PC, PA и т.д. (в то же " -"время фильтрация воздуха при печати ABS и ASA сделает её хуже). Для " -"низкотемпературных материалов, таких как PLA, PETG, TPU, PVA и т. д., " -"фактическая температура в камере не должна быть слишком высокой, чтобы " -"избежать засорения сопла, поэтому настоятельно рекомендуется установить " -"температуру в камере равной 0°C." +"Более высокая температура в камере может помочь уменьшить или даже исключить коробление материала. Так же это улучшает межслойное соединения у " +"высокотемпературных материалов, таких как ABS, ASA, PC, PA и т.д. (в то же время фильтрация воздуха при печати ABS и ASA сделает её хуже). Для низкотемпературных " +"материалов, таких как PLA, PETG, TPU, PVA и т. д., фактическая температура в камере не должна быть слишком высокой, чтобы избежать засорения сопла, поэтому " +"настоятельно рекомендуется установить температуру в камере равной 0°C." msgid "Nozzle temperature for layers after the initial one" msgstr "Температура сопла при печати для слоёв после первого." @@ -12757,30 +11056,19 @@ msgstr "Температура сопла при печати для слоёв msgid "Detect thin wall" msgstr "Обнаружение тонких стенок" -msgid "" -"Detect thin wall which can't contain two line width. And use single line to " -"print. Maybe printed not very well, because it's not closed loop" +msgid "Detect thin wall which can't contain two line width. And use single line to print. Maybe printed not very well, because it's not closed loop" msgstr "" -"Обнаружение тонких стенок (стенки одинарной ширины), которые можно " -"напечатать только в один проход экструдера. Возможно, будет напечатано не " -"очень хорошо, так как это не замкнутый контур." +"Обнаружение тонких стенок (стенки одинарной ширины), которые можно напечатать только в один проход экструдера. Возможно, будет напечатано не очень хорошо, так " +"как это не замкнутый контур." -msgid "" -"This gcode is inserted when change filament, including T command to trigger " -"tool change" -msgstr "" -"Этот G-код вставляется при смене материала, включая команду T для запуска " -"смены инструмента." +msgid "This gcode is inserted when change filament, including T command to trigger tool change" +msgstr "Этот G-код вставляется при смене материала, включая команду T для запуска смены инструмента." msgid "This gcode is inserted when the extrusion role is changed" msgstr "Этот G-код вставляется при смене роли экструзии." -msgid "" -"Line width for top surfaces. If expressed as a %, it will be computed over " -"the nozzle diameter." -msgstr "" -"Ширина экструзии для верхней поверхности. Если задано в процентах, то " -"значение вычисляться относительно диаметра сопла." +msgid "Line width for top surfaces. If expressed as a %, it will be computed over the nozzle diameter." +msgstr "Ширина экструзии для верхней поверхности. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Speed of top surface infill which is solid" msgstr "Скорость печати верхних сплошных поверхностей." @@ -12789,13 +11077,11 @@ msgid "Top shell layers" msgstr "Сплошных слоёв сверху" msgid "" -"This is the number of solid layers of top shell, including the top surface " -"layer. When the thickness calculated by this value is thinner than top shell " +"This is the number of solid layers of top shell, including the top surface layer. When the thickness calculated by this value is thinner than top shell " "thickness, the top shell layers will be increased" msgstr "" -"Количество сплошных слоёв при печати верхней поверхности модели. Если " -"толщина, рассчитанная с помощью этого значения, меньше толщины оболочки " -"сверху, количество сплошных слоёв сверху будет увеличено." +"Количество сплошных слоёв при печати верхней поверхности модели. Если толщина, рассчитанная с помощью этого значения, меньше толщины оболочки сверху, количество " +"сплошных слоёв сверху будет увеличено." msgid "Top solid layers" msgstr "Верхних сплошных слоёв" @@ -12804,19 +11090,12 @@ msgid "Top shell thickness" msgstr "Толщина оболочки сверху" msgid "" -"The number of top solid layers is increased when slicing if the thickness " -"calculated by top shell layers is thinner than this value. This can avoid " -"having too thin shell when layer height is small. 0 means that this setting " -"is disabled and thickness of top shell is absolutely determained by top " -"shell layers" +"The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too " +"thin shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is absolutely determained by top shell layers" msgstr "" -"Минимальная толщина оболочки сверху в мм. Если толщина оболочки, " -"рассчитанная по количеству сплошных слоёв сверху, меньше этого значения, " -"количество сплошных слоёв сверху будет автоматически увеличено при нарезке, " -"для удовлетворения минимальной толщины оболочки. Это позволяет избежать " -"слишком тонкой оболочки при небольшой высоте слоя. 0 означает, что этот " -"параметр отключён, а толщина оболочки сверху полностью задаётся количеством " -"сплошных слоёв снизу." +"Минимальная толщина оболочки сверху в мм. Если толщина оболочки, рассчитанная по количеству сплошных слоёв сверху, меньше этого значения, количество сплошных " +"слоёв сверху будет автоматически увеличено при нарезке, для удовлетворения минимальной толщины оболочки. Это позволяет избежать слишком тонкой оболочки при " +"небольшой высоте слоя. 0 означает, что этот параметр отключён, а толщина оболочки сверху полностью задаётся количеством сплошных слоёв снизу." msgid "Speed of travel which is faster and without extrusion" msgstr "Скорость перемещения экструдера при позиционировании без печати." @@ -12824,47 +11103,34 @@ msgstr "Скорость перемещения экструдера при по msgid "Wipe while retracting" msgstr "Очистка сопла при откате" -msgid "" -"Move nozzle along the last extrusion path when retracting to clean leaked " -"material on nozzle. This can minimize blob when print new part after travel" +msgid "Move nozzle along the last extrusion path when retracting to clean leaked material on nozzle. This can minimize blob when print new part after travel" msgstr "" -"Позволяет соплу совершать движение очистки во время отката, перемещая его " -"вдоль последнего пути экструзии. Это может снизить появление дефектов " -"(каплей, пупырышек) при печати новой детали после перемещения." +"Позволяет соплу совершать движение очистки во время отката, перемещая его вдоль последнего пути экструзии. Это может снизить появление дефектов (каплей, " +"пупырышек) при печати новой детали после перемещения." msgid "Wipe Distance" msgstr "Расстояние очистки" msgid "" -"Discribe how long the nozzle will move along the last path when " -"retracting. \n" +"Discribe how long the nozzle will move along the last path when retracting. \n" "\n" -"Depending on how long the wipe operation lasts, how fast and long the " -"extruder/filament retraction settings are, a retraction move may be needed " -"to retract the remaining filament. \n" +"Depending on how long the wipe operation lasts, how fast and long the extruder/filament retraction settings are, a retraction move may be needed to retract the " +"remaining filament. \n" "\n" -"Setting a value in the retract amount before wipe setting below will perform " -"any excess retraction before the wipe, else it will be performed after." +"Setting a value in the retract amount before wipe setting below will perform any excess retraction before the wipe, else it will be performed after." msgstr "" -"Задаёт расстояние перемещения, добавленное после печати последнего участка " -"пути при совершении отката.\n" +"Задаёт расстояние перемещения, добавленное после печати последнего участка пути при совершении отката.\n" "\n" -"В зависимости от продолжительности операция очистки, заданной скорости и " -"величины отката экструдера/прутка, может потребоваться движение отката, " -"чтобы втянуть оставшийся материал. \n" +"В зависимости от продолжительности операция очистки, заданной скорости и величины отката экструдера/прутка, может потребоваться движение отката, чтобы втянуть " +"оставшийся материал. \n" "\n" -"Установка значения в приведенном ниже параметре «Величина отката перед " -"очисткой» приведёт к выполнению дополнительного отката перед очисткой, в " -"противном случае это будет выполнено после." +"Установка значения в приведенном ниже параметре «Величина отката перед очисткой» приведёт к выполнению дополнительного отката перед очисткой, в противном случае " +"это будет выполнено после." msgid "" -"The wiping tower can be used to clean up the residue on the nozzle and " -"stabilize the chamber pressure inside the nozzle, in order to avoid " -"appearance defects when printing objects." -msgstr "" -"Башня очистки используется для очистки сопла от остатков материала и " -"стабилизации давления внутри сопла, чтобы избежать дефектов снаружи " -"печатаемой модели." +"The wiping tower can be used to clean up the residue on the nozzle and stabilize the chamber pressure inside the nozzle, in order to avoid appearance defects " +"when printing objects." +msgstr "Башня очистки используется для очистки сопла от остатков материала и стабилизации давления внутри сопла, чтобы избежать дефектов снаружи печатаемой модели." msgid "Purging volumes" msgstr "Объём очистки" @@ -12872,19 +11138,14 @@ msgstr "Объём очистки" msgid "Flush multiplier" msgstr "Множитель очистки" -msgid "" -"The actual flushing volumes is equal to the flush multiplier multiplied by " -"the flushing volumes in the table." -msgstr "" -"Реальные объёмы очистки равны множителю очистки, умноженному на объёмы " -"очистки указанные в таблице." +msgid "The actual flushing volumes is equal to the flush multiplier multiplied by the flushing volumes in the table." +msgstr "Реальные объёмы очистки равны множителю очистки, умноженному на объёмы очистки указанные в таблице." msgid "Prime volume" msgstr "Объём сброса на черновой башни" msgid "The volume of material to prime extruder on tower." -msgstr "" -"Объём выдавленного материала для заправки экструдера на черновой башне." +msgstr "Объём выдавленного материала для заправки экструдера на черновой башне." msgid "Width of prime tower" msgstr "Ширина черновой башни." @@ -12898,13 +11159,10 @@ msgstr "Угол поворота черновой башни относител msgid "Stabilization cone apex angle" msgstr "Угол вершины стабилизирующего конуса" -msgid "" -"Angle at the apex of the cone that is used to stabilize the wipe tower. " -"Larger angle means wider base." +msgid "Angle at the apex of the cone that is used to stabilize the wipe tower. Larger angle means wider base." msgstr "" -"Регулировка угла «стабилизирующего конуса», который используется для " -"предотвращения опрокидывания черновой башни. Больший угол означает более " -"широкое основание конуса." +"Регулировка угла «стабилизирующего конуса», который используется для предотвращения опрокидывания черновой башни. Больший угол означает более широкое основание " +"конуса." msgid "Wipe tower purge lines spacing" msgstr "Расстояние между линиями очистки черновой башни" @@ -12915,99 +11173,76 @@ msgstr "Расстояние между линиями очистки на че msgid "Wipe tower extruder" msgstr "Экструдер черновой башни" -msgid "" -"The extruder to use when printing perimeter of the wipe tower. Set to 0 to " -"use the one that is available (non-soluble would be preferred)." -msgstr "" -"Номер экструдера, которым печатаются периметры черновой башни. Установите 0, " -"чтобы использовать тот, который доступен (предпочтительнее нерастворимый)." +msgid "The extruder to use when printing perimeter of the wipe tower. Set to 0 to use the one that is available (non-soluble would be preferred)." +msgstr "Номер экструдера, которым печатаются периметры черновой башни. Установите 0, чтобы использовать тот, который доступен (предпочтительнее нерастворимый)." msgid "Purging volumes - load/unload volumes" msgstr "Объём очистки - Объём загрузки/выгрузки" msgid "" -"This vector saves required volumes to change from/to each tool used on the " -"wipe tower. These values are used to simplify creation of the full purging " -"volumes below." +"This vector saves required volumes to change from/to each tool used on the wipe tower. These values are used to simplify creation of the full purging volumes " +"below." msgstr "" -"Этот параметр задаёт объём материала, который будет выдавлен на черновую " -"башню для прочистки сопла при смене экструдеров/инструментов. Эти значения " -"используются для упрощения создания полноты объёмов очистки указанной ниже." +"Этот параметр задаёт объём материала, который будет выдавлен на черновую башню для прочистки сопла при смене экструдеров/инструментов. Эти значения используются " +"для упрощения создания полноты объёмов очистки указанной ниже." msgid "" -"Purging after filament change will be done inside objects' infills. This may " -"lower the amount of waste and decrease the print time. If the walls are " -"printed with transparent filament, the mixed color infill will be seen " -"outside. It will not take effect, unless the prime tower is enabled." +"Purging after filament change will be done inside objects' infills. This may lower the amount of waste and decrease the print time. If the walls are printed with " +"transparent filament, the mixed color infill will be seen outside. It will not take effect, unless the prime tower is enabled." msgstr "" -"Очистка сопла после смены материала будет производиться в заполнение модели. " -"Это снижает количество отходов и сокращает время печати. Эта функция " -"работает только при включенной черновой башне." +"Очистка сопла после смены материала будет производиться в заполнение модели. Это снижает количество отходов и сокращает время печати. Эта функция работает только " +"при включенной черновой башне." msgid "" -"Purging after filament change will be done inside objects' support. This may " -"lower the amount of waste and decrease the print time. It will not take " -"effect, unless the prime tower is enabled." +"Purging after filament change will be done inside objects' support. This may lower the amount of waste and decrease the print time. It will not take effect, " +"unless the prime tower is enabled." msgstr "" -"Очистка сопла после смены материала будет производиться в поддержку модели. " -"Это снижает количество отходов и сокращает время печати. Эта функция " -"работает только при включенной черновой башне." +"Очистка сопла после смены материала будет производиться в поддержку модели. Это снижает количество отходов и сокращает время печати. Эта функция работает только " +"при включенной черновой башне." msgid "" -"This object will be used to purge the nozzle after a filament change to save " -"filament and decrease the print time. Colours of the objects will be mixed " -"as a result. It will not take effect, unless the prime tower is enabled." +"This object will be used to purge the nozzle after a filament change to save filament and decrease the print time. Colours of the objects will be mixed as a " +"result. It will not take effect, unless the prime tower is enabled." msgstr "" -"Эта модель будет использоваться для очистки сопла после смены материала для " -"его экономии и сокращения времени печати. В результате цвета будут " -"смешиваться. Это не будет действовать, если не будет включена черновая башня." +"Эта модель будет использоваться для очистки сопла после смены материала для его экономии и сокращения времени печати. В результате цвета будут смешиваться. Это " +"не будет действовать, если не будет включена черновая башня." msgid "Maximal bridging distance" msgstr "Максимальное длина моста" msgid "Maximal distance between supports on sparse infill sections." -msgstr "" -"Максимальное расстояние между опорами на разряженных участках заполнения." +msgstr "Максимальное расстояние между опорами на разряженных участках заполнения." msgid "X-Y hole compensation" msgstr "Коррекция размеров отверстий по XY" msgid "" -"Holes of object will be grown or shrunk in XY plane by the configured value. " -"Positive value makes holes bigger. Negative value makes holes smaller. This " -"function is used to adjust size slightly when the object has assembling issue" +"Holes of object will be grown or shrunk in XY plane by the configured value. Positive value makes holes bigger. Negative value makes holes smaller. This function " +"is used to adjust size slightly when the object has assembling issue" msgstr "" -"Отверстия модели будут увеличены или уменьшены в плоскости XY на заданное " -"значение. Положительное значение увеличивает отверстия, отрицательное - " -"уменьшает. Эта функция используется для небольшой корректировки размера, " -"когда возникают проблемы со сборкой." +"Отверстия модели будут увеличены или уменьшены в плоскости XY на заданное значение. Положительное значение увеличивает отверстия, отрицательное - уменьшает. Эта " +"функция используется для небольшой корректировки размера, когда возникают проблемы со сборкой." msgid "X-Y contour compensation" msgstr "Коррекция размеров модели по XY" msgid "" -"Contour of object will be grown or shrunk in XY plane by the configured " -"value. Positive value makes contour bigger. Negative value makes contour " -"smaller. This function is used to adjust size slightly when the object has " -"assembling issue" +"Contour of object will be grown or shrunk in XY plane by the configured value. Positive value makes contour bigger. Negative value makes contour smaller. This " +"function is used to adjust size slightly when the object has assembling issue" msgstr "" -"Параметр отвечает за смещение границы контура печатаемой модели в плоскости " -"XY на заданное значение. Положительное значение увеличивает контур. " -"Отрицательное значение уменьшает контур. Эта функция используется для " -"небольшой корректировки размера, когда возникают проблемы со сборкой." +"Параметр отвечает за смещение границы контура печатаемой модели в плоскости XY на заданное значение. Положительное значение увеличивает контур. Отрицательное " +"значение уменьшает контур. Эта функция используется для небольшой корректировки размера, когда возникают проблемы со сборкой." msgid "Convert holes to polyholes" msgstr "Многогранные отверстия" msgid "" -"Search for almost-circular holes that span more than one layer and convert " -"the geometry to polyholes. Use the nozzle size and the (biggest) diameter to " -"compute the polyhole.\n" +"Search for almost-circular holes that span more than one layer and convert the geometry to polyholes. Use the nozzle size and the (biggest) diameter to compute " +"the polyhole.\n" "See http://hydraraptor.blogspot.com/2011/02/polyholes.html" msgstr "" -"Поиск цилиндрических отверстий в двух или более слоях и преобразование их " -"геометрии в многогранники. Для расчёта многогранного отверстия используется " -"размер сопла и наибольший диаметр найденного отверстия.\n" +"Поиск цилиндрических отверстий в двух или более слоях и преобразование их геометрии в многогранники. Для расчёта многогранного отверстия используется размер " +"сопла и наибольший диаметр найденного отверстия.\n" "Подробнее на http://hydraraptor.blogspot.com/2011/02/polyholes.html" msgid "Polyhole detection margin" @@ -13016,15 +11251,13 @@ msgstr "Предел обнаружения" #, no-c-format, no-boost-format msgid "" "Maximum defection of a point to the estimated radius of the circle.\n" -"As cylinders are often exported as triangles of varying size, points may not " -"be on the circle circumference. This setting allows you some leway to " -"broaden the detection.\n" +"As cylinders are often exported as triangles of varying size, points may not be on the circle circumference. This setting allows you some leway to broaden the " +"detection.\n" "In mm or in % of the radius." msgstr "" "Максимальное отклонение точки от расчётного радиуса окружности.\n" -"Поскольку цилиндры часто экспортируются в виде треугольников разного " -"размера, точки могут находиться не на окружности. Эта параметр позволяет " -"немного расширить область обнаружения.\n" +"Поскольку цилиндры часто экспортируются в виде треугольников разного размера, точки могут находиться не на окружности. Эта параметр позволяет немного расширить " +"область обнаружения.\n" "В мм или в % от радиуса." msgid "Polyhole twist" @@ -13036,47 +11269,31 @@ msgstr "Вращение многогранного отверстия на ка msgid "G-code thumbnails" msgstr "Эскизы G-кода" -msgid "" -"Picture sizes to be stored into a .gcode and .sl1 / .sl1s files, in the " -"following format: \"XxY, XxY, ...\"" -msgstr "" -"Размеры изображения, которые будут сохранены в файлах .sl1 / .sl1s в " -"следующем формате: \"XxY, XxY, ...\"" +msgid "Picture sizes to be stored into a .gcode and .sl1 / .sl1s files, in the following format: \"XxY, XxY, ...\"" +msgstr "Размеры изображения, которые будут сохранены в файлах .sl1 / .sl1s в следующем формате: \"XxY, XxY, ...\"" msgid "Format of G-code thumbnails" msgstr "Формат эскизов G-кода" -msgid "" -"Format of G-code thumbnails: PNG for best quality, JPG for smallest size, " -"QOI for low memory firmware" -msgstr "" -"Формат эскизов G-кода: PNG для наилучшего качества, JPG для наименьшего " -"размера, QOI для прошивки с малым объемом памяти." +msgid "Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware" +msgstr "Формат эскизов G-кода: PNG для наилучшего качества, JPG для наименьшего размера, QOI для прошивки с малым объемом памяти." msgid "Use relative E distances" msgstr "Исп. относительные координаты для экструдера" msgid "" -"Relative extrusion is recommended when using \"label_objects\" option.Some " -"extruders work better with this option unckecked (absolute extrusion mode). " -"Wipe tower is only compatible with relative mode. It is recommended on most " -"printers. Default is checked" +"Relative extrusion is recommended when using \"label_objects\" option.Some extruders work better with this option unckecked (absolute extrusion mode). Wipe tower " +"is only compatible with relative mode. It is recommended on most printers. Default is checked" msgstr "" -"Относительная экструзия рекомендуется при использовании опции «Название " -"моделей». Некоторые экструдеры работают лучше при отключении этой опции " -"(абсолютный режим экструзии). Черновая башня совместима только с " -"относительной экструзии. Рекомендуется включить для большинства принтеров " -"(по умолчанию включено)." +"Относительная экструзия рекомендуется при использовании опции «Название моделей». Некоторые экструдеры работают лучше при отключении этой опции (абсолютный режим " +"экструзии). Черновая башня совместима только с относительной экструзии. Рекомендуется включить для большинства принтеров (по умолчанию включено)." msgid "" -"Classic wall generator produces walls with constant extrusion width and for " -"very thin areas is used gap-fill. Arachne engine produces walls with " -"variable extrusion width" +"Classic wall generator produces walls with constant extrusion width and for very thin areas is used gap-fill. Arachne engine produces walls with variable " +"extrusion width" msgstr "" -"Движок классического генератора периметров создаёт их с постоянной шириной " -"экструзии, а для очень тонких участков используется параметр «Заполнение " -"пробелов». Движок Arachne же создает периметры с переменной шириной " -"экструзии." +"Движок классического генератора периметров создаёт их с постоянной шириной экструзии, а для очень тонких участков используется параметр «Заполнение пробелов». " +"Движок Arachne же создает периметры с переменной шириной экструзии." msgid "Classic" msgstr "Классический" @@ -13088,142 +11305,102 @@ msgid "Wall transition length" msgstr "Длина перехода к периметру" msgid "" -"When transitioning between different numbers of walls as the part becomes " -"thinner, a certain amount of space is allotted to split or join the wall " -"segments. It's expressed as a percentage over nozzle diameter" +"When transitioning between different numbers of walls as the part becomes thinner, a certain amount of space is allotted to split or join the wall segments. It's " +"expressed as a percentage over nozzle diameter" msgstr "" -"При переходе между разным количеством периметров по мере того, как деталь " -"становится тоньше, выделяется определенное пространство для разделения или " -"соединения линий периметров. Выражается в процентах от диаметра сопла." +"При переходе между разным количеством периметров по мере того, как деталь становится тоньше, выделяется определенное пространство для разделения или соединения " +"линий периметров. Выражается в процентах от диаметра сопла." msgid "Wall transitioning filter margin" msgstr "Поле фильтра при переходе между периметрами" msgid "" -"Prevent transitioning back and forth between one extra wall and one less. " -"This margin extends the range of extrusion widths which follow to [Minimum " -"wall width - margin, 2 * Minimum wall width + margin]. Increasing this " -"margin reduces the number of transitions, which reduces the number of " -"extrusion starts/stops and travel time. However, large extrusion width " -"variation can lead to under- or overextrusion problems. It's expressed as a " -"percentage over nozzle diameter" +"Prevent transitioning back and forth between one extra wall and one less. This margin extends the range of extrusion widths which follow to [Minimum wall width - " +"margin, 2 * Minimum wall width + margin]. Increasing this margin reduces the number of transitions, which reduces the number of extrusion starts/stops and travel " +"time. However, large extrusion width variation can lead to under- or overextrusion problems. It's expressed as a percentage over nozzle diameter" msgstr "" -"Предотвращает переход туда и обратно между одним лишним периметром и одним " -"недостающим. Это поле расширяет диапазон значений ширины экструзии, который " -"определяется как [Минимальная ширина периметра - Поле, 2 * Минимальная " -"ширина периметра + Поле]. Расширение этого поля позволяет сократить " -"количество переходов, что в свою очередь позволяет сократить количество " -"запусков/остановок экструдирования и время перемещения. Однако большой " -"разброс значений ширины экструзии может привести к проблемам недо/" -"переэкструзии материала. Если задано в процентах, то расчёт производится " -"относительно диаметра сопла." +"Предотвращает переход туда и обратно между одним лишним периметром и одним недостающим. Это поле расширяет диапазон значений ширины экструзии, который " +"определяется как [Минимальная ширина периметра - Поле, 2 * Минимальная ширина периметра + Поле]. Расширение этого поля позволяет сократить количество переходов, " +"что в свою очередь позволяет сократить количество запусков/остановок экструдирования и время перемещения. Однако большой разброс значений ширины экструзии может " +"привести к проблемам недо/переэкструзии материала. Если задано в процентах, то расчёт производится относительно диаметра сопла." msgid "Wall transitioning threshold angle" msgstr "Пороговый угол перехода между периметрами" msgid "" -"When to create transitions between even and odd numbers of walls. A wedge " -"shape with an angle greater than this setting will not have transitions and " -"no walls will be printed in the center to fill the remaining space. Reducing " -"this setting reduces the number and length of these center walls, but may " -"leave gaps or overextrude" +"When to create transitions between even and odd numbers of walls. A wedge shape with an angle greater than this setting will not have transitions and no walls " +"will be printed in the center to fill the remaining space. Reducing this setting reduces the number and length of these center walls, but may leave gaps or " +"overextrude" msgstr "" -"Когда требуется создавать переходы между чётным и нечётным количеством " -"периметров. Клиновидная форма с углом, превышающим этот параметр, не будет " -"иметь переходов, и периметры не будут напечатаны в центре для заполнения " -"оставшегося пространства. Уменьшение значения этого параметра позволяет " -"сократить количество и длину этих центральных периметров, но при этом могут " -"остаться зазоры или произойти чрезмерное экструдирование." +"Когда требуется создавать переходы между чётным и нечётным количеством периметров. Клиновидная форма с углом, превышающим этот параметр, не будет иметь " +"переходов, и периметры не будут напечатаны в центре для заполнения оставшегося пространства. Уменьшение значения этого параметра позволяет сократить количество и " +"длину этих центральных периметров, но при этом могут остаться зазоры или произойти чрезмерное экструдирование." msgid "Wall distribution count" msgstr "Счётчик распределений по периметрам" -msgid "" -"The number of walls, counted from the center, over which the variation needs " -"to be spread. Lower values mean that the outer walls don't change in width" +msgid "The number of walls, counted from the center, over which the variation needs to be spread. Lower values mean that the outer walls don't change in width" msgstr "" -"Количество периметров, отсчитываемое от центра, на которые необходимо " -"распространить изменения. Более низкое значение означает, что ширина внешних " -"периметров не изменяется." +"Количество периметров, отсчитываемое от центра, на которые необходимо распространить изменения. Более низкое значение означает, что ширина внешних периметров не " +"изменяется." msgid "Minimum feature size" msgstr "Минимальный размер элемента" msgid "" -"Minimum thickness of thin features. Model features that are thinner than " -"this value will not be printed, while features thicker than the Minimum " -"feature size will be widened to the Minimum wall width. It's expressed as a " -"percentage over nozzle diameter" +"Minimum thickness of thin features. Model features that are thinner than this value will not be printed, while features thicker than the Minimum feature size " +"will be widened to the Minimum wall width. It's expressed as a percentage over nozzle diameter" msgstr "" -"Минимальная толщина тонких элементов. Элементы модели, которые тоньше этого " -"значения, не будут напечатаны, в то время как элементы, толщина которых " -"превышает «Минимальный размер элемента», будут расширены до минимальной " -"ширины периметра. Выражается в процентах от диаметра сопла." +"Минимальная толщина тонких элементов. Элементы модели, которые тоньше этого значения, не будут напечатаны, в то время как элементы, толщина которых превышает " +"«Минимальный размер элемента», будут расширены до минимальной ширины периметра. Выражается в процентах от диаметра сопла." msgid "Minimum wall length" msgstr "Минимальная длина периметра" msgid "" -"Adjust this value to prevent short, unclosed walls from being printed, which " -"could increase print time. Higher values remove more and longer walls.\n" +"Adjust this value to prevent short, unclosed walls from being printed, which could increase print time. Higher values remove more and longer walls.\n" "\n" -"NOTE: Bottom and top surfaces will not be affected by this value to prevent " -"visual gaps on the ouside of the model. Adjust 'One wall threshold' in the " -"Advanced settings below to adjust the sensitivity of what is considered a " -"top-surface. 'One wall threshold' is only visibile if this setting is set " -"above the default value of 0.5, or if single-wall top surfaces is enabled." +"NOTE: Bottom and top surfaces will not be affected by this value to prevent visual gaps on the ouside of the model. Adjust 'One wall threshold' in the Advanced " +"settings below to adjust the sensitivity of what is considered a top-surface. 'One wall threshold' is only visibile if this setting is set above the default " +"value of 0.5, or if single-wall top surfaces is enabled." msgstr "" -"Отрегулируйте это значение, чтобы предотвратить печать коротких незамкнутых " -"периметров, что может увеличить временя печати. Более высокие значения " -"удаляют большие и более длинные периметры.\n" +"Отрегулируйте это значение, чтобы предотвратить печать коротких незамкнутых периметров, что может увеличить временя печати. Более высокие значения удаляют " +"большие и более длинные периметры.\n" "\n" -"Примечание: нижние и верхние поверхности не будут затронуты этим значением, " -"чтобы избежать визуальных пробелов с наружной стороны модели. Настройте " -"параметр «Порог одного периметра» в расширенных настройках ниже, чтобы " -"настроить чувствительность определения верхней поверхности. «Порог одного " -"периметра» будет отображаться только в том случае, если этот параметр " -"установлен выше значения по умолчанию, равным 0,5 или если включён параметр " -"«Только один периметр на верхней поверхности»." +"Примечание: нижние и верхние поверхности не будут затронуты этим значением, чтобы избежать визуальных пробелов с наружной стороны модели. Настройте параметр " +"«Порог одного периметра» в расширенных настройках ниже, чтобы настроить чувствительность определения верхней поверхности. «Порог одного периметра» будет " +"отображаться только в том случае, если этот параметр установлен выше значения по умолчанию, равным 0,5 или если включён параметр «Только один периметр на верхней " +"поверхности»." msgid "First layer minimum wall width" msgstr "Минимальная ширина периметра первого слоя" msgid "" -"The minimum wall width that should be used for the first layer is " -"recommended to be set to the same size as the nozzle. This adjustment is " -"expected to enhance adhesion." +"The minimum wall width that should be used for the first layer is recommended to be set to the same size as the nozzle. This adjustment is expected to enhance " +"adhesion." msgstr "" -"Минимальная ширина периметра, используемая для печати первого слоя. Значение " -"рекомендуется устанавливать равным диаметру сопла. Ожидается, что такая " -"регулировка повышает адгезию." +"Минимальная ширина периметра, используемая для печати первого слоя. Значение рекомендуется устанавливать равным диаметру сопла. Ожидается, что такая регулировка " +"повышает адгезию." msgid "Minimum wall width" msgstr "Минимальная ширина периметра" msgid "" -"Width of the wall that will replace thin features (according to the Minimum " -"feature size) of the model. If the Minimum wall width is thinner than the " -"thickness of the feature, the wall will become as thick as the feature " -"itself. It's expressed as a percentage over nozzle diameter" +"Width of the wall that will replace thin features (according to the Minimum feature size) of the model. If the Minimum wall width is thinner than the thickness " +"of the feature, the wall will become as thick as the feature itself. It's expressed as a percentage over nozzle diameter" msgstr "" -"Ширина периметра, которая заменит тонкие элементы (в соответствии с " -"минимальным размера элемента) модели. Если минимальная ширина периметра " -"меньше толщины элемента, толщина периметра будет приведена к толщине самого " -"элемента. Если задано в процентах, то значение вычисляться относительно " -"диаметра сопла." +"Ширина периметра, которая заменит тонкие элементы (в соответствии с минимальным размера элемента) модели. Если минимальная ширина периметра меньше толщины " +"элемента, толщина периметра будет приведена к толщине самого элемента. Если задано в процентах, то значение вычисляться относительно диаметра сопла." msgid "Detect narrow internal solid infill" msgstr "Обнаруживать узкую область сплошного заполнения" msgid "" -"This option will auto detect narrow internal solid infill area. If enabled, " -"concentric pattern will be used for the area to speed printing up. " -"Otherwise, rectilinear pattern is used defaultly." +"This option will auto detect narrow internal solid infill area. If enabled, concentric pattern will be used for the area to speed printing up. Otherwise, " +"rectilinear pattern is used defaultly." msgstr "" -"Этот параметр автоматически определяет узкую внутреннюю область сплошного " -"заполнения. Если включено, для ускорения печати будет использоваться " -"концентрический шаблон. В противном случае по умолчанию используется " -"прямолинейный шаблон." +"Этот параметр автоматически определяет узкую внутреннюю область сплошного заполнения. Если включено, для ускорения печати будет использоваться концентрический " +"шаблон. В противном случае по умолчанию используется прямолинейный шаблон." msgid "invalid value " msgstr "недопустимое значение " @@ -13247,25 +11424,19 @@ msgid "No check" msgstr "Без проверки" msgid "Do not run any validity checks, such as gcode path conflicts check." -msgstr "" -"Не запускать никакие проверки валидности, такие как проверка на конфликт " -"путей в G-коде." +msgstr "Не запускать никакие проверки валидности, такие как проверка на конфликт путей в G-коде." msgid "Ensure on bed" msgstr "Обеспечивать размещение на столе" -msgid "" -"Lift the object above the bed when it is partially below. Disabled by default" -msgstr "" -"Поднимает модель над столом, когда она частично находится ниже его уровня. " -"По умолчанию отключено." +msgid "Lift the object above the bed when it is partially below. Disabled by default" +msgstr "Поднимает модель над столом, когда она частично находится ниже его уровня. По умолчанию отключено." msgid "Orient Options" msgstr "Параметры ориентации" msgid "Orient options: 0-disable, 1-enable, others-auto" -msgstr "" -"Параметры ориентации: 0 - отключить, 1 - включить, другие - автоматически" +msgstr "Параметры ориентации: 0 - отключить, 1 - включить, другие - автоматически" msgid "Rotation angle around the Z axis in degrees." msgstr "Угол поворота вокруг оси Z в градусах." @@ -13279,14 +11450,8 @@ msgstr "Угол поворота вокруг оси Y в градусах." msgid "Data directory" msgstr "Папка конфигурации пользователя" -msgid "" -"Load and store settings at the given directory. This is useful for " -"maintaining different profiles or including configurations from a network " -"storage." -msgstr "" -"Загрузка и сохранение настроек будет производиться в заданную папку. Это " -"полезно для сохранения различных профилей или конфигураций из сетевого " -"хранилища." +msgid "Load and store settings at the given directory. This is useful for maintaining different profiles or including configurations from a network storage." +msgstr "Загрузка и сохранение настроек будет производиться в заданную папку. Это полезно для сохранения различных профилей или конфигураций из сетевого хранилища." msgid "Load custom gcode" msgstr "Загрузить пользовательский G-код" @@ -13298,30 +11463,21 @@ msgid "Current z-hop" msgstr "Подъём оси Z" msgid "Contains z-hop present at the beginning of the custom G-code block." -msgstr "" -"Содержит текущее значение вертикального подъём оси Z, заданное в начале " -"пользовательского G-кода." +msgstr "Содержит текущее значение вертикального подъём оси Z, заданное в начале пользовательского G-кода." msgid "" -"Position of the extruder at the beginning of the custom G-code block. If the " -"custom G-code travels somewhere else, it should write to this variable so " +"Position of the extruder at the beginning of the custom G-code block. If the custom G-code travels somewhere else, it should write to this variable so " "PrusaSlicer knows where it travels from when it gets control back." msgstr "" -"Положение экструдера в начале пользовательского G-кода. Если " -"пользовательский G-код перемещает экструдер в другое место, то информация о " -"его новом положении должна записываться в данную переменную, чтобы " -"PrusaSlicer знал, откуда он перемещается, когда управление возвращается " -"назад." +"Положение экструдера в начале пользовательского G-кода. Если пользовательский G-код перемещает экструдер в другое место, то информация о его новом положении " +"должна записываться в данную переменную, чтобы PrusaSlicer знал, откуда он перемещается, когда управление возвращается назад." msgid "" -"Retraction state at the beginning of the custom G-code block. If the custom " -"G-code moves the extruder axis, it should write to this variable so " -"PrusaSlicer deretracts correctly when it gets control back." +"Retraction state at the beginning of the custom G-code block. If the custom G-code moves the extruder axis, it should write to this variable so PrusaSlicer " +"deretracts correctly when it gets control back." msgstr "" -"Статус отката в начале пользовательского G-кода. Если пользовательский G-код " -"перемещает ось экструдера, то информация о статусе отката должна " -"записываться в данную переменную, чтобы программа корректно совершала " -"подачу, при возврате контроля над процессом печати." +"Статус отката в начале пользовательского G-кода. Если пользовательский G-код перемещает ось экструдера, то информация о статусе отката должна записываться в " +"данную переменную, чтобы программа корректно совершала подачу, при возврате контроля над процессом печати." msgid "Extra deretraction" msgstr "Доп. выдавливание" @@ -13338,12 +11494,8 @@ msgstr "Отсчитываемый от нуля номер используем msgid "Current object index" msgstr "Номер текущей модели" -msgid "" -"Specific for sequential printing. Zero-based index of currently printed " -"object." -msgstr "" -"Предназначено для последовательной печати. Отсчитываемый от нуля номер " -"текущей печатаемой модели." +msgid "Specific for sequential printing. Zero-based index of currently printed object." +msgstr "Предназначено для последовательной печати. Отсчитываемый от нуля номер текущей печатаемой модели." msgid "Has wipe tower" msgstr "Имеется черновая башня" @@ -13354,37 +11506,26 @@ msgstr "Независимо от того, генерируется ли при msgid "Initial extruder" msgstr "Начальный экструдер" -msgid "" -"Zero-based index of the first extruder used in the print. Same as " -"initial_tool." -msgstr "" -"Отсчитываемый от нуля номер первого экструдера, используемого при печати. То " -"же самой, что и initial_tool." +msgid "Zero-based index of the first extruder used in the print. Same as initial_tool." +msgstr "Отсчитываемый от нуля номер первого экструдера, используемого при печати. То же самой, что и initial_tool." msgid "Initial tool" msgstr "Начальный инструмент" -msgid "" -"Zero-based index of the first extruder used in the print. Same as " -"initial_extruder." -msgstr "" -"Отсчитываемый от нуля номер первого экструдера, используемого при печати. То " -"же самой, что и initial_extruder." +msgid "Zero-based index of the first extruder used in the print. Same as initial_extruder." +msgstr "Отсчитываемый от нуля номер первого экструдера, используемого при печати. То же самой, что и initial_extruder." msgid "Is extruder used?" msgstr "Используется ли экструдер?" msgid "Vector of bools stating whether a given extruder is used in the print." -msgstr "" -"Вектор логических значений, указывающий, используется ли данный экструдер в " -"печати." +msgstr "Вектор логических значений, указывающий, используется ли данный экструдер в печати." msgid "Volume per extruder" msgstr "Объём для каждого экструдера" msgid "Total filament volume extruded per extruder during the entire print." -msgstr "" -"Общий объём материала, выдавленного одним экструдером в процесса всей печати." +msgstr "Общий объём материала, выдавленного одним экструдером в процесса всей печати." msgid "Total toolchanges" msgstr "Всего инструментов" @@ -13401,22 +11542,14 @@ msgstr "Общий объём материала, использованного msgid "Weight per extruder" msgstr "Вес для каждого экструдера" -msgid "" -"Weight per extruder extruded during the entire print. Calculated from " -"filament_density value in Filament Settings." -msgstr "" -"Вес материала, выдавленного одним экструдером в процессе всей печати. " -"Рассчитывается исходя из плотности материала указанной в настройках прутка." +msgid "Weight per extruder extruded during the entire print. Calculated from filament_density value in Filament Settings." +msgstr "Вес материала, выдавленного одним экструдером в процессе всей печати. Рассчитывается исходя из плотности материала указанной в настройках прутка." msgid "Total weight" msgstr "Общий вес" -msgid "" -"Total weight of the print. Calculated from filament_density value in " -"Filament Settings." -msgstr "" -"Общий вес затраченного материала. Рассчитывается исходя из плотности " -"материала указанной в настройках прутка." +msgid "Total weight of the print. Calculated from filament_density value in Filament Settings." +msgstr "Общий вес затраченного материала. Рассчитывается исходя из плотности материала указанной в настройках прутка." msgid "Total layer count" msgstr "Общее количество слоёв" @@ -13434,21 +11567,18 @@ msgid "Number of instances" msgstr "Количество копий" msgid "Total number of object instances in the print, summed over all objects." -msgstr "" -"Общее количество копий моделей в печати, суммированное по всем моделям." +msgstr "Общее количество копий моделей в печати, суммированное по всем моделям." msgid "Scale per object" msgstr "Масштаб для каждой модели" msgid "" -"Contains a string with the information about what scaling was applied to the " -"individual objects. Indexing of the objects is zero-based (first object has " -"index 0).\n" +"Contains a string with the information about what scaling was applied to the individual objects. Indexing of the objects is zero-based (first object has index " +"0).\n" "Example: 'x:100% y:50% z:100'." msgstr "" -"Содержит строку с информацией о том, какое масштабирование было применено к " -"отдельным моделям. Нумерация моделей начинается с нуля (первая модель имеет " -"номер 0).\n" +"Содержит строку с информацией о том, какое масштабирование было применено к отдельным моделям. Нумерация моделей начинается с нуля (первая модель имеет номер " +"0).\n" "Пример: 'x:100% y:50% z:100%'." msgid "Input filename without extension" @@ -13457,29 +11587,19 @@ msgstr "Имя входного файла без расширения" msgid "Source filename of the first object, without extension." msgstr "Имя исходного файла первой модели без расширения." -msgid "" -"The vector has two elements: x and y coordinate of the point. Values in mm." -msgstr "" -"Вектор состоит из двух элементов: координаты точки x и y. Значения заданы в " -"мм." +msgid "The vector has two elements: x and y coordinate of the point. Values in mm." +msgstr "Вектор состоит из двух элементов: координаты точки x и y. Значения заданы в мм." -msgid "" -"The vector has two elements: x and y dimension of the bounding box. Values " -"in mm." -msgstr "" -"Вектор состоит из двух элементов: ширина (x-размер) и высота (y-размер) " -"ограничивающего прямоугольника. Значения заданы в мм." +msgid "The vector has two elements: x and y dimension of the bounding box. Values in mm." +msgstr "Вектор состоит из двух элементов: ширина (x-размер) и высота (y-размер) ограничивающего прямоугольника. Значения заданы в мм." msgid "First layer convex hull" msgstr "Выпуклая оболочка первого слоя" -msgid "" -"Vector of points of the first layer convex hull. Each element has the " -"following format:'[x, y]' (x and y are floating-point numbers in mm)." +msgid "Vector of points of the first layer convex hull. Each element has the following format:'[x, y]' (x and y are floating-point numbers in mm)." msgstr "" -"Вектор точек выпуклой оболочки первого слоя. Каждый элемент вектора имеет " -"следующий формат: '[x, y]' (Координаты x и y - числа с плавающей запятой " -"измеряемые в мм)." +"Вектор точек выпуклой оболочки первого слоя. Каждый элемент вектора имеет следующий формат: '[x, y]' (Координаты x и y - числа с плавающей запятой измеряемые в " +"мм)." msgid "Bottom-left corner of first layer bounding box" msgstr "Нижний левый угол ограничивающего прямоугольника первого слоя" @@ -13523,12 +11643,8 @@ msgstr "Имя профиля печати, используемого для н msgid "Filament preset name" msgstr "Имя профиля прутка" -msgid "" -"Names of the filament presets used for slicing. The variable is a vector " -"containing one name for each extruder." -msgstr "" -"Имя профиля прутка, используемого для нарезки. Это переменная является " -"вектором, содержащим одно имя профиля для каждого экструдера." +msgid "Names of the filament presets used for slicing. The variable is a vector containing one name for each extruder." +msgstr "Имя профиля прутка, используемого для нарезки. Это переменная является вектором, содержащим одно имя профиля для каждого экструдера." msgid "Printer preset name" msgstr "Имя профиля принтера" @@ -13546,18 +11662,13 @@ msgid "Layer number" msgstr "Номер слоя" msgid "Index of the current layer. One-based (i.e. first layer is number 1)." -msgstr "" -"Номер текущего слоя отсчитываемый от единицы (т.е. первый слой имеет номер " -"1)." +msgstr "Номер текущего слоя отсчитываемый от единицы (т.е. первый слой имеет номер 1)." msgid "Layer z" msgstr "Высота слоя над столом" -msgid "" -"Height of the current layer above the print bed, measured to the top of the " -"layer." -msgstr "" -"Высота текущего слоя над печатным столом, измеренная до верхней части слоя." +msgid "Height of the current layer above the print bed, measured to the top of the layer." +msgstr "Высота текущего слоя над печатным столом, измеренная до верхней части слоя." msgid "Maximal layer z" msgstr "Макс. высота слоя над столом" @@ -13602,9 +11713,7 @@ msgid "large overhangs" msgstr "большая области нависания" #, c-format, boost-format -msgid "" -"It seems object %s has %s. Please re-orient the object or enable support " -"generation." +msgid "It seems object %s has %s. Please re-orient the object or enable support generation." msgstr "" "Похоже, что у модели %s имеются замечания - %s. \n" "Переориентируйте её или включите генерацию поддержки." @@ -13615,22 +11724,15 @@ msgstr "Оптимизация траектории инструмента" msgid "Slicing mesh" msgstr "Нарезка сетки" -msgid "" -"No layers were detected. You might want to repair your STL file(s) or check " -"their size or thickness and retry.\n" -msgstr "" -"Слоёв не обнаружено. Возможно, требуется починить STL файл(ы) или проверить " -"размер/толщину и повторить попытку.\n" +msgid "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n" +msgstr "Слоёв не обнаружено. Возможно, требуется починить STL файл(ы) или проверить размер/толщину и повторить попытку.\n" msgid "" -"An object's XY size compensation will not be used because it is also color-" -"painted.\n" +"An object's XY size compensation will not be used because it is also color-painted.\n" "XY Size compensation can not be combined with color-painting." msgstr "" -"Коррекция горизонтальных размеров модели не будет действовать, поскольку для " -"этой модели была выполнена операция окрашивания.\n" -"Коррекция горизонтальных размеров модели не может использоваться в сочетании " -"с функцией раскрашивания." +"Коррекция горизонтальных размеров модели не будет действовать, поскольку для этой модели была выполнена операция окрашивания.\n" +"Коррекция горизонтальных размеров модели не может использоваться в сочетании с функцией раскрашивания." #, c-format, boost-format msgid "Support: generate toolpath at layer %d" @@ -13663,11 +11765,8 @@ msgstr "Поддержка: ремонт отверстий на слое %d" msgid "Support: propagate branches at layer %d" msgstr "Поддержка: построение ветвей на слое %d" -msgid "" -"Unknown file format. Input file must have .stl, .obj, .amf(.xml) extension." -msgstr "" -"Неизвестный формат файла. Входной файл должен иметь расширение *.stl, *.obj, " -"*.amf(.xml)." +msgid "Unknown file format. Input file must have .stl, .obj, .amf(.xml) extension." +msgstr "Неизвестный формат файла. Входной файл должен иметь расширение *.stl, *.obj, *.amf(.xml)." msgid "Loading of a model file failed." msgstr "Не удалось загрузить файл модели." @@ -13676,9 +11775,7 @@ msgid "The supplied file couldn't be read because it's empty" msgstr "Предоставленный файл не может быть прочитан, так как он пуст." msgid "Unknown file format. Input file must have .3mf or .zip.amf extension." -msgstr "" -"Неизвестный формат файла. Входной файл должен иметь расширение *.3mf или *." -"zip.amf." +msgstr "Неизвестный формат файла. Входной файл должен иметь расширение *.3mf или *.zip.amf." msgid "Canceled" msgstr "Отменено" @@ -13734,10 +11831,8 @@ msgstr "Завершить" msgid "How to use calibration result?" msgstr "Как использовать результаты калибровки?" -msgid "" -"You could change the Flow Dynamics Calibration Factor in material editing" -msgstr "" -"Коэффициент калибровки динамики потока можно изменить в настройках материала." +msgid "You could change the Flow Dynamics Calibration Factor in material editing" +msgstr "Коэффициент калибровки динамики потока можно изменить в настройках материала." msgid "" "The current firmware version of the printer does not support calibration.\n" @@ -13800,11 +11895,8 @@ msgstr "Имя совпадает с именем другого существ msgid "create new preset failed." msgstr "не удалось создать новый профиль." -msgid "" -"Are you sure to cancel the current calibration and return to the home page?" -msgstr "" -"Вы уверены, что хотите отменить текущую калибровку и вернуться на главную " -"страницу?" +msgid "Are you sure to cancel the current calibration and return to the home page?" +msgstr "Вы уверены, что хотите отменить текущую калибровку и вернуться на главную страницу?" msgid "No Printer Connected!" msgstr "Принтер не подключён!" @@ -13843,24 +11935,17 @@ msgid "When do you need Flow Dynamics Calibration" msgstr "В каких случаях необходима калибровка динамики потока" msgid "" -"We now have added the auto-calibration for different filaments, which is " -"fully automated and the result will be saved into the printer for future " -"use. You only need to do the calibration in the following limited cases:\n" -"1. If you introduce a new filament of different brands/models or the " -"filament is damp;\n" +"We now have added the auto-calibration for different filaments, which is fully automated and the result will be saved into the printer for future use. You only " +"need to do the calibration in the following limited cases:\n" +"1. If you introduce a new filament of different brands/models or the filament is damp;\n" "2. if the nozzle is worn out or replaced with a new one;\n" -"3. If the max volumetric speed or print temperature is changed in the " -"filament setting." +"3. If the max volumetric speed or print temperature is changed in the filament setting." msgstr "" -"Мы добавили функцию автоматической калибровки для различных материалов, " -"которая полностью автоматизирована, а результат калибровки сохраняется в " -"принтере для дальнейшего использования. Калибровка требуется только в " -"следующих ограниченных случаях:\n" -"1. При использовании нового материала другого производителя/типа или при " -"отсыревании материала;\n" +"Мы добавили функцию автоматической калибровки для различных материалов, которая полностью автоматизирована, а результат калибровки сохраняется в принтере для " +"дальнейшего использования. Калибровка требуется только в следующих ограниченных случаях:\n" +"1. При использовании нового материала другого производителя/типа или при отсыревании материала;\n" "2. При износе сопла или его замене на новое;\n" -"3. При изменении в настройках материала максимальной объёмной скорости или " -"температуры печати." +"3. При изменении в настройках материала максимальной объёмной скорости или температуры печати." msgid "About this calibration" msgstr "О данном виде калибровки" @@ -13868,129 +11953,85 @@ msgstr "О данном виде калибровки" msgid "" "Please find the details of Flow Dynamics Calibration from our wiki.\n" "\n" -"Usually the calibration is unnecessary. When you start a single color/" -"material print, with the \"flow dynamics calibration\" option checked in the " -"print start menu, the printer will follow the old way, calibrate the " -"filament before the print; When you start a multi color/material print, the " -"printer will use the default compensation parameter for the filament during " -"every filament switch which will have a good result in most cases.\n" +"Usually the calibration is unnecessary. When you start a single color/material print, with the \"flow dynamics calibration\" option checked in the print start " +"menu, the printer will follow the old way, calibrate the filament before the print; When you start a multi color/material print, the printer will use the default " +"compensation parameter for the filament during every filament switch which will have a good result in most cases.\n" "\n" -"Please note there are a few cases that will make the calibration result not " -"reliable: using a texture plate to do the calibration; the build plate does " -"not have good adhesion (please wash the build plate or apply gluestick!) ..." -"You can find more from our wiki.\n" +"Please note there are a few cases that will make the calibration result not reliable: using a texture plate to do the calibration; the build plate does not have " +"good adhesion (please wash the build plate or apply gluestick!) ...You can find more from our wiki.\n" "\n" -"The calibration results have about 10 percent jitter in our test, which may " -"cause the result not exactly the same in each calibration. We are still " -"investigating the root cause to do improvements with new updates." +"The calibration results have about 10 percent jitter in our test, which may cause the result not exactly the same in each calibration. We are still investigating " +"the root cause to do improvements with new updates." msgstr "" -"Подробную информацию про калибровку динамики потока можно найти на нашем " -"вики-сайте.\n" +"Подробную информацию про калибровку динамики потока можно найти на нашем вики-сайте.\n" "\n" "При обычных обстоятельствах калибровка не требуется. \n" -"Если при запуске печати одним цветом/материалом в меню запуска печати " -"отмечена опция «Калибровка динамики потока», то калибровка пластиковой нити " -"будет производится старым способом. \n" -"При запуске печати несколькими цветами/материалами, принтер будет " -"использовать параметр компенсации по умолчанию для материала при каждой его " -"смене, что в большинстве случаев позволяет получить хороший результат.\n" +"Если при запуске печати одним цветом/материалом в меню запуска печати отмечена опция «Калибровка динамики потока», то калибровка пластиковой нити будет " +"производится старым способом. \n" +"При запуске печати несколькими цветами/материалами, принтер будет использовать параметр компенсации по умолчанию для материала при каждой его смене, что в " +"большинстве случаев позволяет получить хороший результат.\n" "\n" -"Обратите внимание, что есть несколько случаев, когда результат калибровки " -"будет недостоверным. Это использование для калибровки текстурированной " -"печатной пластины и когда у печатной пластины плохая адгезия с материалом. " -"Более подробную информацию можно найти на нашем вики-сайте.\n" +"Обратите внимание, что есть несколько случаев, когда результат калибровки будет недостоверным. Это использование для калибровки текстурированной печатной " +"пластины и когда у печатной пластины плохая адгезия с материалом. Более подробную информацию можно найти на нашем вики-сайте.\n" "\n" -"По нашим тестам, результаты калибровки имеют погрешность примерно 10%, что " -"может приводить к разным результатам при каждой калибровке. Мы продолжаем " -"выяснять причину, чтобы улучшить ситуацию в новых обновлениях." +"По нашим тестам, результаты калибровки имеют погрешность примерно 10%, что может приводить к разным результатам при каждой калибровке. Мы продолжаем выяснять " +"причину, чтобы улучшить ситуацию в новых обновлениях." msgid "When to use Flow Rate Calibration" msgstr "В каких случаях необходима калибровка скорости потока" msgid "" -"After using Flow Dynamics Calibration, there might still be some extrusion " -"issues, such as:\n" -"1. Over-Extrusion: Excess material on your printed object, forming blobs or " -"zits, or the layers seem thicker than expected and not uniform.\n" -"2. Under-Extrusion: Very thin layers, weak infill strength, or gaps in the " -"top layer of the model, even when printing slowly.\n" +"After using Flow Dynamics Calibration, there might still be some extrusion issues, such as:\n" +"1. Over-Extrusion: Excess material on your printed object, forming blobs or zits, or the layers seem thicker than expected and not uniform.\n" +"2. Under-Extrusion: Very thin layers, weak infill strength, or gaps in the top layer of the model, even when printing slowly.\n" "3. Poor Surface Quality: The surface of your prints seems rough or uneven.\n" -"4. Weak Structural Integrity: Prints break easily or don't seem as sturdy as " -"they should be." +"4. Weak Structural Integrity: Prints break easily or don't seem as sturdy as they should be." msgstr "" -"После проведения калибровки динамики потока всё ещё могут возникать " -"некоторые проблемы с экструзией, такие как:\n" -"1. Избыточная экструзия. Это приводит к образованию на модели капель или " -"сгустков, слои кажутся толще и неравномерными, чем ожидалось.\n" -"2. Недоэкструзия. Очень тонкие слои, слабая прочность заполнения или пробелы " -"на верхнем слое модели, даже при медленной печати.\n" -"3. Низкое качество поверхности. Поверхность деталей кажется шероховатой или " -"неровной.\n" -"4. Слабая конструкционная прочность. Напечатанное легко ломается или кажется " -"не таким прочным, как должно быть." +"После проведения калибровки динамики потока всё ещё могут возникать некоторые проблемы с экструзией, такие как:\n" +"1. Избыточная экструзия. Это приводит к образованию на модели капель или сгустков, слои кажутся толще и неравномерными, чем ожидалось.\n" +"2. Недоэкструзия. Очень тонкие слои, слабая прочность заполнения или пробелы на верхнем слое модели, даже при медленной печати.\n" +"3. Низкое качество поверхности. Поверхность деталей кажется шероховатой или неровной.\n" +"4. Слабая конструкционная прочность. Напечатанное легко ломается или кажется не таким прочным, как должно быть." msgid "" -"In addition, Flow Rate Calibration is crucial for foaming materials like LW-" -"PLA used in RC planes. These materials expand greatly when heated, and " -"calibration provides a useful reference flow rate." +"In addition, Flow Rate Calibration is crucial for foaming materials like LW-PLA used in RC planes. These materials expand greatly when heated, and calibration " +"provides a useful reference flow rate." msgstr "" -"Кроме того, калибровка скорости потока крайне важна для вспенивающихся " -"материалов, таких как LW-PLA, используемых при печати деталей для " -"радиоуправляемых самолетов. Эти материалы сильно расширяются при нагревании, " -"а калибровка позволяет получить эталонную скорости потока." +"Кроме того, калибровка скорости потока крайне важна для вспенивающихся материалов, таких как LW-PLA, используемых при печати деталей для радиоуправляемых " +"самолетов. Эти материалы сильно расширяются при нагревании, а калибровка позволяет получить эталонную скорости потока." msgid "" -"Flow Rate Calibration measures the ratio of expected to actual extrusion " -"volumes. The default setting works well in Bambu Lab printers and official " -"filaments as they were pre-calibrated and fine-tuned. For a regular " -"filament, you usually won't need to perform a Flow Rate Calibration unless " -"you still see the listed defects after you have done other calibrations. For " -"more details, please check out the wiki article." +"Flow Rate Calibration measures the ratio of expected to actual extrusion volumes. The default setting works well in Bambu Lab printers and official filaments as " +"they were pre-calibrated and fine-tuned. For a regular filament, you usually won't need to perform a Flow Rate Calibration unless you still see the listed " +"defects after you have done other calibrations. For more details, please check out the wiki article." msgstr "" -"Калибровка скорости потока измеряет соотношение ожидаемого и фактического " -"объёмов экструзии. На принтерах Bambu Lab с официальными материалами, " -"стандартные настройки работают хорошо, так как они были предварительно " -"откалиброваны и тщательно настроены. Для обычного материала обычно не " -"требуется выполнять калибровку скорости потока, если только после выполнения " -"других калибровок вы всё ещё видите перечисленные дефекты. Более подробную " -"информацию можно найти на нашем вики-сайте." +"Калибровка скорости потока измеряет соотношение ожидаемого и фактического объёмов экструзии. На принтерах Bambu Lab с официальными материалами, стандартные " +"настройки работают хорошо, так как они были предварительно откалиброваны и тщательно настроены. Для обычного материала обычно не требуется выполнять калибровку " +"скорости потока, если только после выполнения других калибровок вы всё ещё видите перечисленные дефекты. Более подробную информацию можно найти на нашем вики-" +"сайте." msgid "" -"Auto Flow Rate Calibration utilizes Bambu Lab's Micro-Lidar technology, " -"directly measuring the calibration patterns. However, please be advised that " -"the efficacy and accuracy of this method may be compromised with specific " -"types of materials. Particularly, filaments that are transparent or semi-" -"transparent, sparkling-particled, or have a high-reflective finish may not " -"be suitable for this calibration and can produce less-than-desirable " -"results.\n" +"Auto Flow Rate Calibration utilizes Bambu Lab's Micro-Lidar technology, directly measuring the calibration patterns. However, please be advised that the efficacy " +"and accuracy of this method may be compromised with specific types of materials. Particularly, filaments that are transparent or semi-transparent, sparkling-" +"particled, or have a high-reflective finish may not be suitable for this calibration and can produce less-than-desirable results.\n" "\n" -"The calibration results may vary between each calibration or filament. We " -"are still improving the accuracy and compatibility of this calibration " -"through firmware updates over time.\n" +"The calibration results may vary between each calibration or filament. We are still improving the accuracy and compatibility of this calibration through firmware " +"updates over time.\n" "\n" -"Caution: Flow Rate Calibration is an advanced process, to be attempted only " -"by those who fully understand its purpose and implications. Incorrect usage " -"can lead to sub-par prints or printer damage. Please make sure to carefully " -"read and understand the process before doing it." +"Caution: Flow Rate Calibration is an advanced process, to be attempted only by those who fully understand its purpose and implications. Incorrect usage can lead " +"to sub-par prints or printer damage. Please make sure to carefully read and understand the process before doing it." msgstr "" -"Автоматическая калибровка скорости потока использует технологию микролидара " -"Bambu Lab, непосредственно измеряя калибровочные шаблоны. Однако имейте " -"ввиду, что эффективность и точность этого метода может быть снижена при " -"использовании определенных типов материалов. В частности, прозрачные или " -"полупрозрачные материалы, материалы с блестящими частицами или с " -"высокоотражающим покрытием могут не подойти для данной калибровки и привести " -"к нежелательным результатам.\n" +"Автоматическая калибровка скорости потока использует технологию микролидара Bambu Lab, непосредственно измеряя калибровочные шаблоны. Однако имейте ввиду, что " +"эффективность и точность этого метода может быть снижена при использовании определенных типов материалов. В частности, прозрачные или полупрозрачные материалы, " +"материалы с блестящими частицами или с высокоотражающим покрытием могут не подойти для данной калибровки и привести к нежелательным результатам.\n" "\n" "\n" -"Результаты калибровки могут различаться от калибровки к калибровке или от " -"материала к материалу. Мы продолжаем улучшать точность и совместимость этой " -"калибровки путем обновления прошивки принтера.\n" +"Результаты калибровки могут различаться от калибровки к калибровке или от материала к материалу. Мы продолжаем улучшать точность и совместимость этой калибровки " +"путем обновления прошивки принтера.\n" "\n" -"Внимание: калибровка скорости потока - это сложный процесс, к которому " -"следует прибегать только тем, кто полностью понимает её назначение и " -"последствия. Неправильное использование может привести к некачественной " -"печати или повреждению принтера. Пожалуйста, внимательно прочитайте и " -"поймите суть процесса, прежде чем приступать к его выполнению." +"Внимание: калибровка скорости потока - это сложный процесс, к которому следует прибегать только тем, кто полностью понимает её назначение и последствия. " +"Неправильное использование может привести к некачественной печати или повреждению принтера. Пожалуйста, внимательно прочитайте и поймите суть процесса, прежде " +"чем приступать к его выполнению." msgid "When you need Max Volumetric Speed Calibration" msgstr "В каких случаях необходима калибровка максимальной объемной скорости" @@ -13999,13 +12040,10 @@ msgid "Over-extrusion or under extrusion" msgstr "Избыточная или недостаточная экструзия" msgid "Max Volumetric Speed calibration is recommended when you print with:" -msgstr "" -"Калибровка максимальной объёмной скорости рекомендуется при печати с " -"использованием:" +msgstr "Калибровка максимальной объёмной скорости рекомендуется при печати с использованием:" msgid "material with significant thermal shrinkage/expansion, such as..." -msgstr "" -"материалов со значительной термической усадкой/расширением, например..." +msgstr "материалов со значительной термической усадкой/расширением, например..." msgid "materials with inaccurate filament diameter" msgstr "материалов с неточным диаметром пластиковой нити" @@ -14013,39 +12051,25 @@ msgstr "материалов с неточным диаметром пласти msgid "We found the best Flow Dynamics Calibration Factor" msgstr "Мы нашли лучший коэффициент калибровки динамики потока" -msgid "" -"Part of the calibration failed! You may clean the plate and retry. The " -"failed test result would be dropped." -msgstr "" -"Часть калибровки выполнена неудачно! Вы можете очистить печатную пластину и " -"повторить попытку. Результат неудачного теста будет удалён." +msgid "Part of the calibration failed! You may clean the plate and retry. The failed test result would be dropped." +msgstr "Часть калибровки выполнена неудачно! Вы можете очистить печатную пластину и повторить попытку. Результат неудачного теста будет удалён." -msgid "" -"*We recommend you to add brand, materia, type, and even humidity level in " -"the Name" -msgstr "" -"*Мы рекомендуем добавить к названию материала, производителя, тип и даже " -"уровень влажности" +msgid "*We recommend you to add brand, materia, type, and even humidity level in the Name" +msgstr "*Мы рекомендуем добавить к названию материала, производителя, тип и даже уровень влажности" msgid "Failed" msgstr "Неудачно" -msgid "" -"Only one of the results with the same name will be saved. Are you sure you " -"want to overrides the other results?" -msgstr "" -"Будет сохранен только один из результатов с таким же именем. Вы уверены, что " -"хотите перезаписать другие результаты?" +msgid "Only one of the results with the same name will be saved. Are you sure you want to overrides the other results?" +msgstr "Будет сохранен только один из результатов с таким же именем. Вы уверены, что хотите перезаписать другие результаты?" #, c-format, boost-format msgid "" -"There is already a historical calibration result with the same name: %s. " -"Only one of the results with the same name is saved. Are you sure you want " -"to overrides the historical result?" +"There is already a historical calibration result with the same name: %s. Only one of the results with the same name is saved. Are you sure you want to overrides " +"the historical result?" msgstr "" -"Результат калибровки с таким именем уже существует: %s. Будет сохранён " -"только один результат с таким же именем. Вы уверены, что хотите перезаписать " -"текущий результат?" +"Результат калибровки с таким именем уже существует: %s. Будет сохранён только один результат с таким же именем. Вы уверены, что хотите перезаписать текущий " +"результат?" msgid "Please find the best line on your plate" msgstr "Пожалуйста, найдите лучшую линию на столе" @@ -14117,12 +12141,9 @@ msgstr "Точная калибровка на основе коэффициен msgid "Title" msgstr "Заголовок" -msgid "" -"A test model will be printed. Please clear the build plate and place it back " -"to the hot bed before calibration." +msgid "A test model will be printed. Please clear the build plate and place it back to the hot bed before calibration." msgstr "" -"Будет напечатана тестовая модель. Перед калибровкой очистите печатную " -"пластину \n" +"Будет напечатана тестовая модель. Перед калибровкой очистите печатную пластину \n" "и установите её обратно на нагреваемый стол." msgid "Printing Parameters" @@ -14153,8 +12174,7 @@ msgid "" msgstr "" "Советы по выбору материала для калибровки: \n" "- Материалы, которые имеют близкие значения температуры нагреваемого стола\n" -"- Различные марки и семейства расходных материалов (Производитель = Bambu, " -"семейство = Basic - базовый, Matte - матовый)" +"- Различные марки и семейства расходных материалов (Производитель = Bambu, семейство = Basic - базовый, Matte - матовый)" msgid "Pattern" msgstr "Шаблон" @@ -14571,11 +12591,8 @@ msgstr "Не выбран производитель, пожалуйста, вы msgid "Custom vendor is not input, please input custom vendor." msgstr "Не задан производитель, пожалуйста, введите производителя." -msgid "" -"\"Bambu\" or \"Generic\" can not be used as a Vendor for custom filaments." -msgstr "" -"\"Bambu\" или \"Generic\" не могут быть заданы в качестве производителей для " -"пользовательский пластиковых нитей." +msgid "\"Bambu\" or \"Generic\" can not be used as a Vendor for custom filaments." +msgstr "\"Bambu\" или \"Generic\" не могут быть заданы в качестве производителей для пользовательский пластиковых нитей." msgid "Filament type is not selected, please reselect type." msgstr "Не выбран тип прутка, пожалуйста, выберите его заново." @@ -14583,12 +12600,8 @@ msgstr "Не выбран тип прутка, пожалуйста, выбер msgid "Filament serial is not inputed, please input serial." msgstr "Пожалуйста, введите серию прутка." -msgid "" -"There may be escape characters in the vendor or serial input of filament. " -"Please delete and re-enter." -msgstr "" -"В имени производителя или серии прутка могут присутствовать управляющие " -"символы. Пожалуйста, удалите их и введите повторно." +msgid "There may be escape characters in the vendor or serial input of filament. Please delete and re-enter." +msgstr "В имени производителя или серии прутка могут присутствовать управляющие символы. Пожалуйста, удалите их и введите повторно." msgid "All inputs in the custom vendor or serial are spaces. Please re-enter." msgstr "" @@ -14596,17 +12609,13 @@ msgstr "" "Пожалуйста, введите нормальное имя." msgid "The vendor can not be a number. Please re-enter." -msgstr "" -"Имя производителя не может начинаться с числа. Пожалуйста, введите " -"нормальное имя." +msgstr "Имя производителя не может начинаться с числа. Пожалуйста, введите нормальное имя." -msgid "" -"You have not selected a printer or preset yet. Please select at least one." +msgid "You have not selected a printer or preset yet. Please select at least one." msgstr "Выберите хотя бы один принтер или профиль." msgid "Some existing presets have failed to be created, as follows:\n" -msgstr "" -"При создании некоторых имеющихся профилей произошла ошибка, а именно:\n" +msgstr "При создании некоторых имеющихся профилей произошла ошибка, а именно:\n" msgid "" "\n" @@ -14616,8 +12625,7 @@ msgstr "" "Хотите перезаписать его?" msgid "" -"We would rename the presets as \"Vendor Type Serial @printer you " -"selected\". \n" +"We would rename the presets as \"Vendor Type Serial @printer you selected\". \n" "To add preset for more printers, Please go to printer selection" msgstr "" "Мы переименуем профиль в \"Производитель Тип Серия @выбранный принтер\".\n" @@ -14688,19 +12696,13 @@ msgstr "Максимальная высота печати" #, c-format, boost-format msgid "The file exceeds %d MB, please import again." -msgstr "" -"Размер файла превышает %d МБ, пожалуйста, попробуйте импортировать его ещё " -"раз." +msgstr "Размер файла превышает %d МБ, пожалуйста, попробуйте импортировать его ещё раз." msgid "Exception in obtaining file size, please import again." -msgstr "" -"Ошибка при получении размера файла, пожалуйста, попробуйте импортировать его " -"ещё раз." +msgstr "Ошибка при получении размера файла, пожалуйста, попробуйте импортировать его ещё раз." msgid "Preset path is not find, please reselect vendor." -msgstr "" -"Не найдет путь к предустановленному профилю, пожалуйста, повторно выберите " -"производителя." +msgstr "Не найдет путь к предустановленному профилю, пожалуйста, повторно выберите производителя." msgid "The printer model was not found, please reselect." msgstr "Модель принтера не найдена, пожалуйста, выберите заново." @@ -14726,36 +12728,25 @@ msgstr "Шаблон профиля процесса" msgid "Back Page 1" msgstr "Вернуться на 1-ю страницу" -msgid "" -"You have not yet chosen which printer preset to create based on. Please " -"choose the vendor and model of the printer" +msgid "You have not yet chosen which printer preset to create based on. Please choose the vendor and model of the printer" msgstr "" -"Вы не выбрали на базе какого профиля принтера хотите создать новый профиль " -"принтера. \n" +"Вы не выбрали на базе какого профиля принтера хотите создать новый профиль принтера. \n" "Пожалуйста, выберите производителя и модель принтера." -msgid "" -"You have entered an illegal input in the printable area section on the first " -"page. Please check before creating it." -msgstr "" -"В разделе «Область печати» на первой странице введено недопустимое значение. " -"Проверьте введение значение перед созданием." +msgid "You have entered an illegal input in the printable area section on the first page. Please check before creating it." +msgstr "В разделе «Область печати» на первой странице введено недопустимое значение. Проверьте введение значение перед созданием." msgid "The custom printer or model is not inputed, place input." msgstr "Пожалуйста, введите имя пользовательского принтера или модель." msgid "" -"The printer preset you created already has a preset with the same name. Do " -"you want to overwrite it?\n" -"\tYes: Overwrite the printer preset with the same name, and filament and " -"process presets with the same preset name will be recreated \n" -"and filament and process presets without the same preset name will be " -"reserve.\n" +"The printer preset you created already has a preset with the same name. Do you want to overwrite it?\n" +"\tYes: Overwrite the printer preset with the same name, and filament and process presets with the same preset name will be recreated \n" +"and filament and process presets without the same preset name will be reserve.\n" "\tCancel: Do not create a preset, return to the creation interface." msgstr "" "Профиль принтера с таким именем уже существует. Хотите перезаписать его?\n" -"\tДа: перезаписать профиль принтера. Профили прутка и процесса с теми же " -"именами будут созданы заново, а профили без имени будут зарезервированы.\n" +"\tДа: перезаписать профиль принтера. Профили прутка и процесса с теми же именами будут созданы заново, а профили без имени будут зарезервированы.\n" "\tОтмена: не создавать профиль и вернуться на экран создания." msgid "You need to select at least one filament preset." @@ -14774,25 +12765,15 @@ msgid "Vendor is not find, please reselect." msgstr "Производитель не найден, пожалуйста, выберите заново." msgid "Current vendor has no models, please reselect." -msgstr "" -"У текущего производителя отсутствуют модели принтеров, пожалуйста, выберите " -"заново." +msgstr "У текущего производителя отсутствуют модели принтеров, пожалуйста, выберите заново." -msgid "" -"You have not selected the vendor and model or inputed the custom vendor and " -"model." +msgid "You have not selected the vendor and model or inputed the custom vendor and model." msgstr "Вы не выбрали или не ввели производителя и модель принтера." -msgid "" -"There may be escape characters in the custom printer vendor or model. Please " -"delete and re-enter." -msgstr "" -"В имени производителя или модели пользовательского принтера могут " -"присутствовать управляющие символы. Пожалуйста, удалите их и введите " -"повторно." +msgid "There may be escape characters in the custom printer vendor or model. Please delete and re-enter." +msgstr "В имени производителя или модели пользовательского принтера могут присутствовать управляющие символы. Пожалуйста, удалите их и введите повторно." -msgid "" -"All inputs in the custom printer vendor or model are spaces. Please re-enter." +msgid "All inputs in the custom printer vendor or model are spaces. Please re-enter." msgstr "" "В поле ввода производителя/модели принтера введены пробелы. \n" "Пожалуйста, введите нормальное имя." @@ -14800,8 +12781,7 @@ msgstr "" msgid "Please check bed printable shape and origin input." msgstr "Пожалуйста, проверьте правильность введённых значений области печати." -msgid "" -"You have not yet selected the printer to replace the nozzle, please choose." +msgid "You have not yet selected the printer to replace the nozzle, please choose." msgstr "Для замены сопла сначала выберите принтер." msgid "Create Printer Successful" @@ -14821,15 +12801,11 @@ msgstr "Профиль прутка создан" msgid "" "Please go to filament setting to edit your presets if you need.\n" -"Please note that nozzle temperature, hot bed temperature, and maximum " -"volumetric speed have a significant impact on printing quality. Please set " -"them carefully." +"Please note that nozzle temperature, hot bed temperature, and maximum volumetric speed have a significant impact on printing quality. Please set them carefully." msgstr "" -"При необходимости перейдите в настройку прутка для редактирования настроек " -"профиля.\n" -"Пожалуйста, обратите внимание, что температура сопла, температура " -"нагреваемого стола и максимальная объёмная скорость существенно влияют на " -"качество печати. Пожалуйста, тщательнее подбирайте настройки." +"При необходимости перейдите в настройку прутка для редактирования настроек профиля.\n" +"Пожалуйста, обратите внимание, что температура сопла, температура нагреваемого стола и максимальная объёмная скорость существенно влияют на качество печати. " +"Пожалуйста, тщательнее подбирайте настройки." msgid "Printer Setting" msgstr "Настройка принтера" @@ -14872,10 +12848,8 @@ msgstr "Успешно экспортировано!" #, c-format, boost-format msgid "" -"The '%s' folder already exists in the current directory. Do you want to " -"clear it and rebuild it.\n" -"If not, a time suffix will be added, and you can modify the name after " -"creation." +"The '%s' folder already exists in the current directory. Do you want to clear it and rebuild it.\n" +"If not, a time suffix will be added, and you can modify the name after creation." msgstr "" "Файл '%s' уже существует в текущем каталоге. Хотите перезаписать его?\n" "Если нет, то к имени будет добавлен временной суффикс." @@ -14894,40 +12868,30 @@ msgstr "" "Набор пользовательских профилей пластиковых нитей. \n" "Можно будет поделиться с другими пользователями." -msgid "" -"Only display printer names with changes to printer, filament, and process " -"presets." -msgstr "" -"Будут отображаться только профили принтеров, пластиковых нитей и процессов, " -"которые были изменены." +msgid "Only display printer names with changes to printer, filament, and process presets." +msgstr "Будут отображаться только профили принтеров, пластиковых нитей и процессов, которые были изменены." msgid "Only display the filament names with changes to filament presets." msgstr "Будут отображаться только изменённые профили пластиковых нитей." -msgid "" -"Only printer names with user printer presets will be displayed, and each " -"preset you choose will be exported as a zip." +msgid "Only printer names with user printer presets will be displayed, and each preset you choose will be exported as a zip." msgstr "" "Будут отображаться только пользовательские профили принтеров. \n" "Каждый выбранный профиль будет экспортирован в zip-файл." msgid "" "Only the filament names with user filament presets will be displayed, \n" -"and all user filament presets in each filament name you select will be " -"exported as a zip." +"and all user filament presets in each filament name you select will be exported as a zip." msgstr "" "Будут отображаться только пользовательские профили пластиковых нитей.\n" "Все они будут экспортированы в zip-файл." msgid "" "Only printer names with changed process presets will be displayed, \n" -"and all user process presets in each printer name you select will be " -"exported as a zip." +"and all user process presets in each printer name you select will be exported as a zip." msgstr "" -"Будут отображаться только профили принтеров с изменёнными профилями " -"процесса. \n" -"Все пользовательские профили процессов для каждого выбранного профиля " -"принтера будут экспортированы в zip-файл." +"Будут отображаться только профили принтеров с изменёнными профилями процесса. \n" +"Все пользовательские профили процессов для каждого выбранного профиля принтера будут экспортированы в zip-файл." msgid "Please select at least one printer or filament." msgstr "Пожалуйста, выберите хотя бы один принтер или пластиковую нить." @@ -14941,9 +12905,7 @@ msgstr "Изменение прутка" msgid "Filament presets under this filament" msgstr "Профили прутка под эту пластиковую нить" -msgid "" -"Note: If the only preset under this filament is deleted, the filament will " -"be deleted after exiting the dialog." +msgid "Note: If the only preset under this filament is deleted, the filament will be deleted after exiting the dialog." msgstr "" "Примечание: если удаляется единственный профиль для этого материала, \n" "то сам материал также будет удалён после закрытия окна." @@ -14974,12 +12936,10 @@ msgstr "Удалить пруток" msgid "" "All the filament presets belong to this filament would be deleted. \n" -"If you are using this filament on your printer, please reset the filament " -"information for that slot." +"If you are using this filament on your printer, please reset the filament information for that slot." msgstr "" -"Все профили прутка, относящиеся к этому материалу, будут удалены. Если вы " -"используете этот пруток в принтере, пожалуйста, сбросьте информацию о прутке " -"для этого слота." +"Все профили прутка, относящиеся к этому материалу, будут удалены. Если вы используете этот пруток в принтере, пожалуйста, сбросьте информацию о прутке для этого " +"слота." msgid "Delete filament" msgstr "Удаление прутка" @@ -15017,12 +12977,8 @@ msgstr "Нужно выбрать принтер" msgid "The start, end or step is not valid value." msgstr "Недопустимое значение: начальное, конечное или шаг." -msgid "" -"Unable to calibrate: maybe because the set calibration value range is too " -"large, or the step is too small" -msgstr "" -"Невозможно выполнить калибровку: возможно, установленный диапазон значений " -"калибровки слишком велик или шаг слишком мал." +msgid "Unable to calibrate: maybe because the set calibration value range is too large, or the step is too small" +msgstr "Невозможно выполнить калибровку: возможно, установленный диапазон значений калибровки слишком велик или шаг слишком мал." msgid "Physical Printer" msgstr "Физический принтер" @@ -15043,12 +12999,8 @@ msgstr "Вы уверены, что хотите выйти из системы? msgid "Refresh Printers" msgstr "Обновить принтеры" -msgid "" -"HTTPS CA file is optional. It is only needed if you use HTTPS with a self-" -"signed certificate." -msgstr "" -"Файл корневого сертификата HTTPS не обязателен. Он необходим только при " -"использовании HTTPS с самоподписанным сертификатом." +msgid "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate." +msgstr "Файл корневого сертификата HTTPS не обязателен. Он необходим только при использовании HTTPS с самоподписанным сертификатом." msgid "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*" msgstr "Файлы сертификатов (*.crt, *.pem)|*.crt;*.pem|Все файлы|*.*" @@ -15057,19 +13009,11 @@ msgid "Open CA certificate file" msgstr "Открыть файл корневого сертификата" #, c-format, boost-format -msgid "" -"On this system, %s uses HTTPS certificates from the system Certificate Store " -"or Keychain." -msgstr "" -"В этой системе %s использует HTTPS сертификаты из системного хранилища " -"сертификатов/Keychain." +msgid "On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain." +msgstr "В этой системе %s использует HTTPS сертификаты из системного хранилища сертификатов/Keychain." -msgid "" -"To use a custom CA file, please import your CA file into Certificate Store / " -"Keychain." -msgstr "" -"Чтобы использовать пользовательский файл корневого сертификата, импортируйте " -"его в хранилище сертификатов/Keychain." +msgid "To use a custom CA file, please import your CA file into Certificate Store / Keychain." +msgstr "Чтобы использовать пользовательский файл корневого сертификата, импортируйте его в хранилище сертификатов/Keychain." msgid "Login/Test" msgstr "Вход/Тест" @@ -15114,12 +13058,8 @@ msgstr "Подключение к FlashAir работает корректно. msgid "Could not connect to FlashAir" msgstr "Не удаётся подключиться к FlashAir" -msgid "" -"Note: FlashAir with firmware 2.00.02 or newer and activated upload function " -"is required." -msgstr "" -"Примечание: для активации функцией загрузки, требуется FlashAir с прошивкой " -"2.00.02 и выше." +msgid "Note: FlashAir with firmware 2.00.02 or newer and activated upload function is required." +msgstr "Примечание: для активации функцией загрузки, требуется FlashAir с прошивкой 2.00.02 и выше." msgid "Connection to MKS works correctly." msgstr "Подключение к MKS успешно установлено." @@ -15222,16 +13162,10 @@ msgid "Could not connect to SimplyPrint" msgstr "Не удалось подключиться к SimplyPrint" msgid "SimplyPrint account not linked. Go to Connect options to set it up." -msgstr "" -"Учётная запись SimplyPrint не привязана. Перейдите в раздел подключения для " -"настройки." +msgstr "Учётная запись SimplyPrint не привязана. Перейдите в раздел подключения для настройки." -msgid "" -"File size exceeds the 100MB upload limit. Please upload your file through " -"the panel." -msgstr "" -"Размер файла превышает лимит загрузки в 100 МБ. Пожалуйста, загрузите файл " -"через панель." +msgid "File size exceeds the 100MB upload limit. Please upload your file through the panel." +msgstr "Размер файла превышает лимит загрузки в 100 МБ. Пожалуйста, загрузите файл через панель." msgid "Unknown error" msgstr "Неизвестная ошибка" @@ -15246,9 +13180,7 @@ msgid "The provided state is not correct." msgstr "Указано неверное состояние." msgid "Please give the required permissions when authorizing this application." -msgstr "" -"Пожалуйста, предоставьте необходимые разрешения при авторизации этого " -"приложения." +msgstr "Пожалуйста, предоставьте необходимые разрешения при авторизации этого приложения." msgid "Something unexpected happened when trying to log in, please try again." msgstr "При попытке войти произошла какая-то ошибка, попробуйте ещё раз." @@ -15259,24 +13191,19 @@ msgstr "Отменено пользователем." #: resources/data/hints.ini: [hint:Precise wall] msgid "" "Precise wall\n" -"Did you know that turning on precise wall can improve precision and layer " -"consistency?" +"Did you know that turning on precise wall can improve precision and layer consistency?" msgstr "" "Точные периметры\n" -"Знаете ли вы, что включение точных периметров позволяет повысить точность и " -"однородность слоёв?" +"Знаете ли вы, что включение точных периметров позволяет повысить точность и однородность слоёв?" #: resources/data/hints.ini: [hint:Sandwich mode] msgid "" "Sandwich mode\n" -"Did you know that you can use sandwich mode (inner-outer-inner) to improve " -"precision and layer consistency if your model doesn't have very steep " -"overhangs?" +"Did you know that you can use sandwich mode (inner-outer-inner) to improve precision and layer consistency if your model doesn't have very steep overhangs?" msgstr "" "Порядок печати периметров «Сэндвич»\n" -"Знаете ли вы, что можно использовать порядок печати периметров «Сэндвич» (т." -"е. внутренний-внешний-внутренний) для повышения точности и согласованности " -"слоёв, если у вашей модели не очень крутые нависания?" +"Знаете ли вы, что можно использовать порядок печати периметров «Сэндвич» (т.е. внутренний-внешний-внутренний) для повышения точности и согласованности слоёв, " +"если у вашей модели не очень крутые нависания?" #: resources/data/hints.ini: [hint:Chamber temperature] msgid "" @@ -15284,18 +13211,15 @@ msgid "" "Did you know that OrcaSlicer supports chamber temperature?" msgstr "" "Температура термокамеры\n" -"Знаете ли вы, что OrcaSlicer поддерживает управление температурой в камере " -"принтера?" +"Знаете ли вы, что OrcaSlicer поддерживает управление температурой в камере принтера?" #: resources/data/hints.ini: [hint:Calibration] msgid "" "Calibration\n" -"Did you know that calibrating your printer can do wonders? Check out our " -"beloved calibration solution in OrcaSlicer." +"Did you know that calibrating your printer can do wonders? Check out our beloved calibration solution in OrcaSlicer." msgstr "" "Калибровка\n" -"Знаете ли вы, что калибровка принтера может творить чудеса? Ознакомьтесь с " -"нашим избранными калибровками в OrcaSlicer." +"Знаете ли вы, что калибровка принтера может творить чудеса? Ознакомьтесь с нашим избранными калибровками в OrcaSlicer." #: resources/data/hints.ini: [hint:Auxiliary fan] msgid "" @@ -15303,17 +13227,15 @@ msgid "" "Did you know that OrcaSlicer supports Auxiliary part cooling fan?" msgstr "" "Вспомогательный вентилятор для охлаждения моделей\n" -"Знаете ли вы, что OrcaSlicer поддерживает управление вспомогательным " -"вентилятором для охлаждения моделей?" +"Знаете ли вы, что OrcaSlicer поддерживает управление вспомогательным вентилятором для охлаждения моделей?" #: resources/data/hints.ini: [hint:Air filtration] msgid "" "Air filtration/Exhaust Fan\n" "Did you know that OrcaSlicer can support Air filtration/Exhaust Fan?" msgstr "" -"Фильтрация воздуха/Вытяжной вентилятор\n" -"Знаете ли вы, что OrcaSlicer поддерживает управление фильтрацией воздуха/" -"вытяжным вентилятором?" +"Вытяжной вентилятор\n" +"Знаете ли вы, что OrcaSlicer поддерживает управление вытяжным вентилятором?" #: resources/data/hints.ini: [hint:G-code window] msgid "" @@ -15326,52 +13248,42 @@ msgstr "" #: resources/data/hints.ini: [hint:Switch workspaces] msgid "" "Switch workspaces\n" -"You can switch between Prepare and Preview workspaces by " -"pressing the Tab key." +"You can switch between Prepare and Preview workspaces by pressing the Tab key." msgstr "" "Переключение между вкладками\n" -"Вы можете переключаться между вкладками Подготовка и Предпросмотр " -"нарезки, нажав клавишу Tab." +"Вы можете переключаться между вкладками Подготовка и Предпросмотр нарезки, нажав клавишу Tab." #: resources/data/hints.ini: [hint:How to use keyboard shortcuts] msgid "" "How to use keyboard shortcuts\n" -"Did you know that Orca Slicer offers a wide range of keyboard shortcuts and " -"3D scene operations." +"Did you know that Orca Slicer offers a wide range of keyboard shortcuts and 3D scene operations." msgstr "" "Использование горячих клавиш\n" -"Знаете ли вы, что в Orca Slicer имеется большой список горячих клавиш для " -"облегчения и ускорения работы с программой?" +"Знаете ли вы, что в Orca Slicer имеется большой список горячих клавиш для облегчения и ускорения работы с программой?" #: resources/data/hints.ini: [hint:Reverse on odd] msgid "" "Reverse on odd\n" -"Did you know that Reverse on odd feature can significantly improve " -"the surface quality of your overhangs?" +"Did you know that Reverse on odd feature can significantly improve the surface quality of your overhangs?" msgstr "" "Реверс на нависаниях\n" -"Знаете ли вы, что функция Реверс на нависаниях может значительно " -"улучшить качество поверхности нависающий частей?" +"Знаете ли вы, что функция Реверс на нависаниях может значительно улучшить качество поверхности нависающий частей?" #: resources/data/hints.ini: [hint:Cut Tool] msgid "" "Cut Tool\n" -"Did you know that you can cut a model at any angle and position with the " -"cutting tool?" +"Did you know that you can cut a model at any angle and position with the cutting tool?" msgstr "" "Режущий инструмент\n" -"Знаете ли вы, что можно разрезать модель под любым углом с помощью режущего " -"инструмента?" +"Знаете ли вы, что можно разрезать модель под любым углом с помощью режущего инструмента?" #: resources/data/hints.ini: [hint:Fix Model] msgid "" "Fix Model\n" -"Did you know that you can fix a corrupted 3D model to avoid a lot of slicing " -"problems on the Windows system?" +"Did you know that you can fix a corrupted 3D model to avoid a lot of slicing problems on the Windows system?" msgstr "" "Починка модели\n" -"Знаете ли вы, что можно починить повреждённую модель в системе Windows, " -"чтобы избежать множества проблем при нарезке?" +"Знаете ли вы, что можно починить повреждённую модель в системе Windows, чтобы избежать множества проблем при нарезке?" #: resources/data/hints.ini: [hint:Timelapse] msgid "" @@ -15392,204 +13304,163 @@ msgstr "" #: resources/data/hints.ini: [hint:Auto-Orient] msgid "" "Auto-Orient\n" -"Did you know that you can rotate objects to an optimal orientation for " -"printing by a simple click?" +"Did you know that you can rotate objects to an optimal orientation for printing by a simple click?" msgstr "" "Автоориентация\n" -"Знаете ли вы, что можно повернуть модели в оптимальную для печати ориентацию " -"простым щелчком мыши?" +"Знаете ли вы, что можно повернуть модели в оптимальную для печати ориентацию простым щелчком мыши?" #: resources/data/hints.ini: [hint:Lay on Face] msgid "" "Lay on Face\n" -"Did you know that you can quickly orient a model so that one of its faces " -"sits on the print bed? Select the \"Place on face\" function or press the " -"F key." +"Did you know that you can quickly orient a model so that one of its faces sits on the print bed? Select the \"Place on face\" function or press the F key." msgstr "" "Поверхностью на стол\n" -"Знаете ли вы, что можно быстро сориентировать модель так, чтобы одна из её " -"граней лежала на столе? Используйте функцию «Поверхностью на стол» или " -"нажмите клавишу F." +"Знаете ли вы, что можно быстро сориентировать модель так, чтобы одна из её граней лежала на столе? Используйте функцию «Поверхностью на стол» или нажмите клавишу " +"F." #: resources/data/hints.ini: [hint:Object List] msgid "" "Object List\n" -"Did you know that you can view all objects/parts in a list and change " -"settings for each object/part?" +"Did you know that you can view all objects/parts in a list and change settings for each object/part?" msgstr "" "Список моделей\n" -"Знаете ли вы, что можно просматривать все модели/части в списке и изменять " -"настройки для каждой из них?" +"Знаете ли вы, что можно просматривать все модели/части в списке и изменять настройки для каждой из них?" #: resources/data/hints.ini: [hint:Search Functionality] msgid "" "Search Functionality\n" -"Did you know that you use the Search tool to quickly find a specific Orca " -"Slicer setting?" +"Did you know that you use the Search tool to quickly find a specific Orca Slicer setting?" msgstr "" "Функция поиска\n" -"Знаете ли вы, что используя инструментПоискможно быстро найти нужную " -"вам настройку Orca Slicer?" +"Знаете ли вы, что используя инструментПоискможно быстро найти нужную вам настройку Orca Slicer?" #: resources/data/hints.ini: [hint:Simplify Model] msgid "" "Simplify Model\n" -"Did you know that you can reduce the number of triangles in a mesh using the " -"Simplify mesh feature? Right-click the model and select Simplify model." +"Did you know that you can reduce the number of triangles in a mesh using the Simplify mesh feature? Right-click the model and select Simplify model." msgstr "" "Упростить сетку модели\n" -"Знаете ли вы, что можно уменьшить количество треугольников в полигональной " -"сетке, используя функцию упрощения сетки? Щёлкните правой кнопкой мыши на " -"модели и выберите «Упростить полигональную сетку»." +"Знаете ли вы, что можно уменьшить количество треугольников в полигональной сетке, используя функцию упрощения сетки? Щёлкните правой кнопкой мыши на модели и " +"выберите «Упростить полигональную сетку»." #: resources/data/hints.ini: [hint:Slicing Parameter Table] msgid "" "Slicing Parameter Table\n" -"Did you know that you can view all objects/parts on a table and change " -"settings for each object/part?" +"Did you know that you can view all objects/parts on a table and change settings for each object/part?" msgstr "" "Таблица параметров нарезки\n" -"Знаете ли вы, что можно просмотреть все модели/части в таблице и изменить " -"параметры печати для каждой из них?" +"Знаете ли вы, что можно просмотреть все модели/части в таблице и изменить параметры печати для каждой из них?" #: resources/data/hints.ini: [hint:Split to Objects/Parts] msgid "" "Split to Objects/Parts\n" -"Did you know that you can split a big object into small ones for easy " -"colorizing or printing?" +"Did you know that you can split a big object into small ones for easy colorizing or printing?" msgstr "" "Разделение на модели/части\n" -"Знаете ли вы, что можно разделить большую модель на маленькие для удобства " -"раскрашивания или печати?" +"Знаете ли вы, что можно разделить большую модель на маленькие для удобства раскрашивания или печати?" #: resources/data/hints.ini: [hint:Subtract a Part] msgid "" "Subtract a Part\n" -"Did you know that you can subtract one mesh from another using the Negative " -"part modifier? That way you can, for example, create easily resizable holes " -"directly in Orca Slicer." +"Did you know that you can subtract one mesh from another using the Negative part modifier? That way you can, for example, create easily resizable holes directly " +"in Orca Slicer." msgstr "" "Вычитание объёмов\n" -"Знаете ли вы, что можно вычесть одну сетку из другой с помощью модификатора " -"«Объём для вычитания»? Таким образом, например, отверстия в модели можно " -"создавать непосредственно в Orca Slicer." +"Знаете ли вы, что можно вычесть одну сетку из другой с помощью модификатора «Объём для вычитания»? Таким образом, например, отверстия в модели можно создавать " +"непосредственно в Orca Slicer." #: resources/data/hints.ini: [hint:STEP] msgid "" "STEP\n" -"Did you know that you can improve your print quality by slicing a STEP file " -"instead of an STL?\n" -"Orca Slicer supports slicing STEP files, providing smoother results than a " -"lower resolution STL. Give it a try!" +"Did you know that you can improve your print quality by slicing a STEP file instead of an STL?\n" +"Orca Slicer supports slicing STEP files, providing smoother results than a lower resolution STL. Give it a try!" msgstr "" "STEP\n" -"Знаете ли вы, что можно улучшить качество печати, используя STEP файлы " -"вместо STL?\n" -"Orca Slicer поддерживает нарезку STEP файлов, что обеспечивает более точное " -"представление геометрии, чем при нарезке STL файлов." +"Знаете ли вы, что можно улучшить качество печати, используя STEP файлы вместо STL?\n" +"Orca Slicer поддерживает нарезку STEP файлов, что обеспечивает более точное представление геометрии, чем при нарезке STL файлов." #: resources/data/hints.ini: [hint:Z seam location] msgid "" "Z seam location\n" -"Did you know that you can customize the location of the Z seam, and even " -"paint it on your print, to have it in a less visible location? This improves " -"the overall look of your model. Check it out!" +"Did you know that you can customize the location of the Z seam, and even paint it on your print, to have it in a less visible location? This improves the overall " +"look of your model. Check it out!" msgstr "" "Позиция шва\n" -"Знаете ли вы, что можно изменить расположение шва и даже нарисовать его на " -"модели, чтобы он был менее заметен? Это улучшает общий вид модели. " -"Попробуйте это!" +"Знаете ли вы, что можно изменить расположение шва и даже нарисовать его на модели, чтобы он был менее заметен? Это улучшает общий вид модели. Попробуйте это!" #: resources/data/hints.ini: [hint:Fine-tuning for flow rate] msgid "" "Fine-tuning for flow rate\n" -"Did you know that flow rate can be fine-tuned for even better-looking " -"prints? Depending on the material, you can improve the overall finish of the " -"printed model by doing some fine-tuning." +"Did you know that flow rate can be fine-tuned for even better-looking prints? Depending on the material, you can improve the overall finish of the printed model " +"by doing some fine-tuning." msgstr "" "Точная настройка потока\n" -"Знаете ли вы, что поток можно точно настроить для получения ещё более " -"качественной печати? В зависимости от материала можно внести некоторые " -"корректировки, чтобы улучшить общее качество печати." +"Знаете ли вы, что поток можно точно настроить для получения ещё более качественной печати? В зависимости от материала можно внести некоторые корректировки, чтобы " +"улучшить общее качество печати." #: resources/data/hints.ini: [hint:Split your prints into plates] msgid "" "Split your prints into plates\n" -"Did you know that you can split a model that has a lot of parts into " -"individual plates ready to print? This will simplify the process of keeping " -"track of all the parts." +"Did you know that you can split a model that has a lot of parts into individual plates ready to print? This will simplify the process of keeping track of all the " +"parts." msgstr "" "Распределение печатаемого на другие столы\n" -"Знаете ли вы, что модель, состоящую из большого количества частей, можно " -"распределить на несколько столов? Это упрощает процесс отслеживания всех " -"деталей при печати." +"Знаете ли вы, что модель, состоящую из большого количества частей, можно распределить на несколько столов? Это упрощает процесс отслеживания всех деталей при " +"печати." -#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer -#: Height] +#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer Height] msgid "" "Speed up your print with Adaptive Layer Height\n" -"Did you know that you can print a model even faster, by using the Adaptive " -"Layer Height option? Check it out!" +"Did you know that you can print a model even faster, by using the Adaptive Layer Height option? Check it out!" msgstr "" "Ускорение печати с функцией «Перем. высота слоёв»\n" -"Знаете ли вы, что можно печатать ещё быстрее, используя функцию «Переменная " -"высота слоёв». Попробуйте!" +"Знаете ли вы, что можно печатать ещё быстрее, используя функцию «Переменная высота слоёв». Попробуйте!" #: resources/data/hints.ini: [hint:Support painting] msgid "" "Support painting\n" -"Did you know that you can paint the location of your supports? This feature " -"makes it easy to place the support material only on the sections of the " -"model that actually need it." +"Did you know that you can paint the location of your supports? This feature makes it easy to place the support material only on the sections of the model that " +"actually need it." msgstr "" "Рисование поддержек\n" -"Знаете ли вы, что можно прямо на модели рисовать где будет размещаться " -"принудительная поддержка, а где поддержка будет заблокирована? Используйте " -"для этого функцию «Рисование поддержек»." +"Знаете ли вы, что можно прямо на модели рисовать где будет размещаться принудительная поддержка, а где поддержка будет заблокирована? Используйте для этого " +"функцию «Рисование поддержек»." #: resources/data/hints.ini: [hint:Different types of supports] msgid "" "Different types of supports\n" -"Did you know that you can choose from multiple types of supports? Tree " -"supports work great for organic models, while saving filament and improving " -"print speed. Check them out!" +"Did you know that you can choose from multiple types of supports? Tree supports work great for organic models, while saving filament and improving print speed. " +"Check them out!" msgstr "" "Различные типы поддержек\n" -"Знаете ли вы, что можно выбрать один из нескольких типов поддержек? " -"Древовидная поддержка отлично подходит для органических моделей, экономя при " -"этом материал и уменьшая время печати." +"Знаете ли вы, что можно выбрать один из нескольких типов поддержек? Древовидная поддержка отлично подходит для органических моделей, экономя при этом материал и " +"уменьшая время печати." #: resources/data/hints.ini: [hint:Printing Silk Filament] msgid "" "Printing Silk Filament\n" -"Did you know that Silk filament needs special consideration to print it " -"successfully? Higher temperature and lower speed are always recommended for " -"the best results." +"Did you know that Silk filament needs special consideration to print it successfully? Higher temperature and lower speed are always recommended for the best " +"results." msgstr "" "Печать блестящей пластиковой нитью\n" -"Знаете ли вы, что блестящая пластиковая нить требует особого внимания для " -"успешной печати? Для достижения наилучшего результата рекомендуется более " -"высокая температура и более низкая скорость печати." +"Знаете ли вы, что блестящая пластиковая нить требует особого внимания для успешной печати? Для достижения наилучшего результата рекомендуется более высокая " +"температура и более низкая скорость печати." #: resources/data/hints.ini: [hint:Brim for better adhesion] msgid "" "Brim for better adhesion\n" -"Did you know that when printing models have a small contact interface with " -"the printing surface, it's recommended to use a brim?" +"Did you know that when printing models have a small contact interface with the printing surface, it's recommended to use a brim?" msgstr "" "Кайма для лучшей адгезии\n" -"Знаете ли вы, что при печати модели имеющей небольшой контакт с поверхностью " -"стола, рекомендуется использовать кайму?" +"Знаете ли вы, что при печати модели имеющей небольшой контакт с поверхностью стола, рекомендуется использовать кайму?" #: resources/data/hints.ini: [hint:Set parameters for multiple objects] msgid "" "Set parameters for multiple objects\n" -"Did you know that you can set slicing parameters for all selected objects at " -"one time?" +"Did you know that you can set slicing parameters for all selected objects at one time?" msgstr "" "Задание параметров для нескольких моделей\n" -"Знаете ли вы, что можно задать параметры нарезки сразу для всех выбранных " -"моделей?" +"Знаете ли вы, что можно задать параметры нарезки сразу для всех выбранных моделей?" #: resources/data/hints.ini: [hint:Stack objects] msgid "" @@ -15597,145 +13468,42 @@ msgid "" "Did you know that you can stack objects as a whole one?" msgstr "" "Объединение моделей\n" -"Знаете ли вы, что можно объединить несколько моделей в единую? Используйте " -"для этого команду «Объединить в сборку», выбрав несколько моделей." +"Знаете ли вы, что можно объединить несколько моделей в единую? Используйте для этого команду «Объединить в сборку», выбрав несколько моделей." #: resources/data/hints.ini: [hint:Flush into support/objects/infill] msgid "" "Flush into support/objects/infill\n" -"Did you know that you can save the wasted filament by flushing them into " -"support/objects/infill during filament change?" +"Did you know that you can save the wasted filament by flushing them into support/objects/infill during filament change?" msgstr "" "Очистка в поддержку/модель/заполнение\n" -"Знаете ли вы, что при смене пластиковой нити, можно сохранить материал, " -"который иначе попал бы на черновую башню, сбросив его в поддержку/модель/" -"заполнение?" +"Знаете ли вы, что при смене пластиковой нити, можно сохранить материал, который иначе попал бы на черновую башню, сбросив его в поддержку/модель/заполнение?" #: resources/data/hints.ini: [hint:Improve strength] msgid "" "Improve strength\n" -"Did you know that you can use more wall loops and higher sparse infill " -"density to improve the strength of the model?" +"Did you know that you can use more wall loops and higher sparse infill density to improve the strength of the model?" msgstr "" "Увеличение прочности\n" -"Знаете ли вы, что для повышения прочности модели можно увеличить количество " -"периметров и плотность заполнения?" +"Знаете ли вы, что для повышения прочности модели можно увеличить количество периметров и плотность заполнения?" -#: resources/data/hints.ini: [hint:When need to print with the printer door -#: opened] +#: resources/data/hints.ini: [hint:When need to print with the printer door opened] msgid "" "When need to print with the printer door opened\n" -"Did you know that opening the printer door can reduce the probability of " -"extruder/hotend clogging when printing lower temperature filament with a " -"higher enclosure temperature. More info about this in the Wiki." +"Did you know that opening the printer door can reduce the probability of extruder/hotend clogging when printing lower temperature filament with a higher " +"enclosure temperature. More info about this in the Wiki." msgstr "" "Когда печатать с открытой дверцей принтера?\n" -"Знаете ли вы, что при печати низкотемпературным материалом при более высокой " -"температуре в камере, открытие дверцы принтера снижает вероятность засорения " +"Знаете ли вы, что при печати низкотемпературным материалом при более высокой температуре в камере, открытие дверцы принтера снижает вероятность засорения " "экструдера/хотэнда? Более подробную информацию читайте на вики-сайте." #: resources/data/hints.ini: [hint:Avoid warping] msgid "" "Avoid warping\n" -"Did you know that when printing materials that are prone to warping such as " -"ABS, appropriately increasing the heatbed temperature can reduce the " -"probability of warping." +"Did you know that when printing materials that are prone to warping such as ABS, appropriately increasing the heatbed temperature can reduce the probability of " +"warping." msgstr "" "Предотвращение коробления материала\n" -"Знаете ли вы, что при печати материалами, склонными к короблению, таких как " -"ABS, повышение температуры подогреваемого стола может снизить эту " -"вероятность?" +"Знаете ли вы, что при печати материалами, склонными к короблению, таких как ABS, повышение температуры подогреваемого стола может снизить эту вероятность?" -#~ msgid "" -#~ "Alternate extra wall only works with ensure vertical shell thickness " -#~ "disabled. " -#~ msgstr "" -#~ "Альтернативный дополнительный периметр работает только при отключенной " -#~ "опции «Обеспечивать верт. толщину оболочки». " - -#~ msgid "" -#~ "Change these settings automatically? \n" -#~ "Yes - Disable ensure vertical shell thickness and enable alternate extra " -#~ "wall\n" -#~ "No - Dont use alternate extra wall" -#~ msgstr "" -#~ "Изменить эти настройки автоматически?\n" -#~ "Да - Отключить обеспечение вертикальной толщины оболочки и включить " -#~ "альтернативный дополнительный периметр\n" -#~ "Нет - Отказаться от использования альтернативного дополнительного " -#~ "периметра" - -#~ msgid "" -#~ "The speed setting exceeds the printer's maximum speed " -#~ "(machine_max_speed_x/machine_max_speed_y).\n" -#~ "Orca will automatically cap the print speed to ensure it doesn't surpass " -#~ "the printer's capabilities.\n" -#~ "You can adjust the maximum speed setting in your printer's configuration " -#~ "to get higher speeds." -#~ msgstr "" -#~ "Значение максимальной скорости перемещения (machine_max_speed_x/" -#~ "machine_max_speed_y) превышает значение заданное в настройках принтера.\n" -#~ "Программа автоматически ограничит это ускорение, чтобы оно не превышало " -#~ "возможности принтера.\n" -#~ "Если хотите получить более высокие скорости, вы можете изменить это " -#~ "значение в настройках принтера (вкладка «Ограничение принтера»)." - -#~ msgid "Bridge counterbole holes" -#~ msgstr "Мост для зенкованных отверстий" - -#~ msgid "Studio Version:" -#~ msgstr "Версия программы:" - -#~ msgid "Test BambuLab" -#~ msgstr "Тест BambuLab" - -#~ msgid "Test BambuLab:" -#~ msgstr "Тест BambuLab:" - -#~ msgid "Test HTTP" -#~ msgstr "Тест HTTP" - -#~ msgid "Test HTTP Service:" -#~ msgstr "Тест HTTP сервера:" - -#~ msgid "Test storage" -#~ msgstr "Тест накопителя" - -#~ msgid "Test Storage Upload:" -#~ msgstr "Тест накопителя (отправка):" - -#~ msgid "Test storage upgrade" -#~ msgstr "Тест накопителя (обновление)" - -#~ msgid "Test Storage Upgrade:" -#~ msgstr "Тест накопителя (обновление):" - -#~ msgid "Test storage download" -#~ msgstr "Тест накопителя (загрузка)" - -#~ msgid "Test Storage Download:" -#~ msgstr "Тест накопителя (загрузка):" - -#~ msgid "Test plugin download" -#~ msgstr "Тест загрузки плагина" - -#~ msgid "Test Plugin Download:" -#~ msgstr "Тест загрузки плагина:" - -#~ msgid "Test Storage Upload" -#~ msgstr "Тест накопителя (отправка)" - -#~ msgid "AMS %s" -#~ msgstr "АСПП №%s" - -#~ msgid "Left Preset Value" -#~ msgstr "Значение в левом профиле" - -#~ msgid "Right Preset Value" -#~ msgstr "Значение в правом профиле" - -#~ msgid "Undef category" -#~ msgstr "Неопределённая категория" - -#~ msgid "Undef group" -#~ msgstr "Неопределённая группа" +msgid "AMS %s" +msgstr "АСПП №%s" From 1bb8fad63fa4f4bcaeb039aec030b1247055c88a Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 14 Apr 2024 22:07:00 +0800 Subject: [PATCH 05/21] Merge some changes from BS 1.9 (#4994) * FIX: do not touch the plate with different printing sequence jira: STUDIO-5424 Change-Id: I8ad00fa991b753de126a5bef0d320c452033e2e7 (cherry picked from commit c4adfe16e285f238f2c5cd8938b2167fdfb6b1b0) * FIX: global arrange setting is wrong global arrange setting is wrong if a plate's setting is changed from object list jira: STUDIO-5438 Change-Id: Iaa7f35837edbacff9b97ca17a8ab34c8e6bb023d (cherry picked from commit fa2f56575b2e4305e35dd59ff55e0881720de025) * FIX: temperature symbols not shown correctly Need to use wxString::FromUTF8 to convert unicode symbols to wxString. jira: none Change-Id: Ia8b559d437c956a2cc28916d8963823356402d05 * FIX:Repair calculation process of plate_box Jira: STUDIO-5520 Change-Id: I4c3f9597542ad2dfec4d7849e75fa28272fa4ea3 * FIX:frequent calls to _update_imgui_select_plate_toolbar Jira: STUDIO-5488 Change-Id: I12e6f37c2fe94de004aa6da43421970d6df10f0f * FIX: & is not displayed on the sending print page Jira: STUDIO-5343 Signed-off-by: wenjie.guo Change-Id: I1736bb97433581ff117bfe09afe8ee70c1b08fc4 * FIX: file name is not fully displayed if it is too long Jira: STUDIO-5230 Signed-off-by: wenjie.guo Change-Id: I992fa0c0575afbd2eecb2af02c8a305eda028f7f (cherry picked from commit d0d7fb0b1394429ee9d28d8ef4060a286ba0112d) * FIX: The warning box still exits when the temperature has reset. Jira: STUDIO-5562 Signed-off-by: wenjie.guo Change-Id: I7532db69880449eb3fa0a14fc4dfc61e7f6d518e (cherry picked from commit 589ed5fe045b5e7ec3effe437c9685085960c0fc) * FIX: White circle is not clear on auto refill page Jira: STUDIO-3262 Signed-off-by: wenjie.guo Change-Id: I05ac6257638063d32a9943c09bb7c14cc9229b3a * FIX: Groove text ctrl is not wide engough Jira: STUDIO-5434 Signed-off-by: wenjie.guo Change-Id: I93c0995473a72b5c19bc413c38c090906e360455 (cherry picked from commit e4a8b0ef5e62ba0053dc782c30ea79b237a46ac3) * FIX: values are not saved when clicking on an empty space Jira: STUDIO-4637 Signed-off-by: wenjie.guo Change-Id: I837050029635f673b3ae671ea1ad049aaf4fdd16 * FIX: Temperature warning is not fully displayed Jira: STUDIO-5038 Signed-off-by: wenjie.guo Change-Id: I460cbe2a5d0a092c4257b7bd5192058bf2e4707b * NEW: display bitmap when calibrating Jira: STUDIO-4661 Signed-off-by: wenjie.guo Change-Id: I60cf4f9769feca74699012418880e93fcfe34432 (cherry picked from commit 1213aea816694405311dc0c1061655a4c2a1d067) * FIX: remember the flow ratio calibration type Jira: STUDIO-5181 Signed-off-by: wenjie.guo Change-Id: Id6125d1d4ea58972ce55c2c2498259596b25111e (cherry picked from commit 1af1038fd4824d989e992cb630cf34e00c787af7) * FIX: File panel crash on scroll Change-Id: I56833a376fa52c960efea5fbd60003367ba410c2 Jira: STUDIO-5337, STUDIO-5513 * FIX: auto arranging skip unprintable high items Jira: STUDIO-5646 Change-Id: I72dc3d8c71a075bab8204f4418e869a7a34c0c8e (cherry picked from commit 0afdf8361493485da2254c426719594fd9a982ed) * FIX: MediaFilePanel error state Change-Id: I318ef59fb97478ffee16dff594022b2b9029964a Jira: STUDIO-5638 * FIX: sync whole preset vendor directory Change-Id: I191dbe979a87ff35d38cab1149b7975664344838 Jira: STUDIO-5534 * ENH: support turn off liveview auto retry Change-Id: I24b39f74e0a40a13277d6eae3830c95c5c9de333 Jira: none (cherry picked from commit f6ceb3fb8e4df3f876c50a1c4ba96b4a1be60190) * FIX: SwitchButton auto scale font Change-Id: If4004c0963cc8bb2f41e8e71c304d5239bf252ab Jira: STUDIO-4969 STUDIO-4921 * FIX: set WEBKIT_DISABLE_COMPOSITING_MODE=1 for linux gtk Change-Id: I8a500585ca815948bab1210578ba5c45858ed78e Jira: STUDIO-5199 * FIX: Prefer old selection when sync AMS not compatible Change-Id: I6b18db51887132a997cf78d70fff9a92e23bc44a Jira: STUDIO-5416 * ENH: show liveview stat Change-Id: I70d1f458aa2ed379ad7fe07dee76fbe035316420 Jira: none * NEW:remember custom color Jira: STUDIO-5635 Change-Id: I439080f6a8ddb6fde3899cffbabc3b6e66afbd96 * FIX: copy live555 dll Change-Id: Idf727b8e26107e93aa9934299e87dc71531d1c63 Jira: STUDIO-4480 * FIX: optimize batch update object list on macOS Change-Id: I92e24cc53c0b3bf0658d15abc64292f0e17c0a82 Jira: STUDIO-5440 STUDIO-5515 * FIX: network plugins tip disappear on dark mode Change-Id: I422ab63f71158a49920438f01dd9c39774c27744 Jira: STUDIO-4891 * FIX: Display inconsistence in parameter table JIra: STUDIO-3716 Signed-off-by: wenjie.guo Change-Id: I986473bcbb3efff4abd9c5917926d9e888a4f28c * FIX: Incomplete copy display in Transfer or discard dialog Jira: 5569 5549 Change-Id: I757b636259d7e1a222b9fc09276c12235360fd57 * FIX: Limit the max length of k when calibrating Jira: STUDIO-4291 Signed-off-by: wenjie.guo Change-Id: Ie7cff086cf2a3c744213525d5d83f9ac4b55333d * fix build break * FIX: delete sdcard file crash Change-Id: I814fd4b557fa92ac4060cbeb18a53f5616e49662 Jira: STUDIO-5977 * FIX: Yield when join media thread Change-Id: I746d7df88a0de8363da7d9507cb63c9e0ffe970a Jira: STUDIO-5952 * FIX: Guide page can't show in screen with mainframe Jira: STUDIO-4911 Change-Id: I7e89614e0f1585263456c847a1b38dcfd0ad59e6 * FIX: filament combox has blank line Change-Id: Ia39ddb564b3c9cc943d0ea4c0cf7cc4d24bef799 * FIX: load 3mf crash when studio has no base filament Jira: none Change-Id: I4387f425f60e6a53a53cf68addb1ab2d6f8f8901 Signed-off-by: maosheng.wei * FIX:add resume button JIRA:github:2860 Change-Id: I39035d929876ab3c84c5f5c3494376967300938c * FIX: CLI: fix an arrange issue when duplicate failed restore the wipe_tower position to original when duplicate fail JIRA: MAK-2638 Change-Id: I355056f1d87648cc1f6aafa15a98ff569359b44f * FIX: fix printer list without nozzle such as 0.35 or 0.75 Jira: 5409 Change-Id: I1a258fd10bcc03e297b791256880f2518d602905 * ENH:The first object should locate at plate center Jira: STUDIO-6023 Change-Id: If4284136fe63ca576463445f3ab16b6e18ead30f * FIX: Colored filament is not matched against. github: #2190 Colored filament is not matched against the same color in AMS slot. Signed-off-by: Kunlong Ma Change-Id: Id4588fc9c8115a46881e2f5d198d79fe831f4371 * FIX: Revert "[STUDIO-4284] not set max height of liveview window" This reverts commit 0312aee4d9b92e23884be8802da9801ff3b9fe93. Reason for revert: STUDIO-5653 Jira: STUDIO-5653 Change-Id: If9d5f3e63968a0a54f9af1a2dae8f95f7f1f3f80 * ENH:modify file name rules when export stl Jira: STUDIO-6091 Change-Id: Ic27e4e341cc09099e98a5eab7dfd48416f2922ae * FIX: Flow calibration stage incorrect when switching printers Jira: 6093 Change-Id: I41f1ac10ac9422ac808eab3254f32ea14a0d3b76 * FIX: UserGuide Can not Click When Computer User name has chinese JIRA: None Change-Id: If50baa8c6a13eb501918fd5cdaf0ea3da7c788ef (cherry picked from commit 4e5ccc9f2de5ac429af6541c6a8bd412848801d0) * ENH: Little Optimize JS Code Execute Progress JIRA: STUDIO-5792 Change-Id: I12b03d8b968a9dd8dfce9eb3ef925fa8768e2046 (cherry picked from commit 2bf861092c9e306e1311eda8ac36fd981e73b6c2) * FIX: Delete Test Code JIRA: NONE Change-Id: I838a348edb22e09d2b1d5c41600c6fade535d184 (cherry picked from commit 51e664da0209ae8a3de5cbf30a72505c0b5bd028) * FIX: the object list order changed after clone github: 2798 Change-Id: I10a05ee7e00b05cb1255cfb708876ed784cabac7 * ENH: add alias for custom Filament preset Jira: XXXX Change-Id: I2fecc8b2bdb63618155e3d21f9db374a6119e416 * FIX: [5779] fix show alias logic when load preset Jira: 5779 Change-Id: I4fefe3c1ffbca9bd8296f1b3fdd5de48c6a36a28 * ENH: Optimize the logic for deleting third-party printers Mark the Filament and Process presets to be deleted first then delete the child presets first and then the parent presets. Jira: none Change-Id: I100b873baae96c6ba27af258e708e6ab8e6ee4ab * ENH:default selection of virtual tray jira:[for def selected] Change-Id: I0661f179f8e4bcac33ae12fbbeaeaf95c5b7c110 * ENH:add protection when no thumbnail data jira:[for protection] Change-Id: I3834a5ffde11ff54567dd854271184f06f94547f * FIX:fixed issue with chinese path jira:[Fixed the issue of failed loading of configuration files under Chinese path] Change-Id: I9badd8fc158fcf49f46411ac4e5f72d58823eeb2 * NEW:add new msg notification for hms jira:[STUDIO-6154] Change-Id: If1aa33030a99550d0c859d594a2711aea4dcea4a * NEW:using new humidity display ui jira:[STUDIO-5967] Change-Id: I13be4212e6b97f646d21e0af64cbc5006753fdeb * NEW:Dye materials above grade 10 with shortcut keys JIRA:STUDIO-5827 Change-Id: I002ecdd19167fb36772e4b4e9e2f7760e21079db * NEW:update automatically when inserting materials JIRA: STUDIO-6157 Change-Id: I2cefbb7b330ca4f13e841066548992b3fb3740f1 * FIX: check sdcard exists for file connect Change-Id: I69199a29294c04d1fe46ee66682085b1f1d1d049 Jira: none * FIX: not load printer files when it's busy Change-Id: Ie5a58befcfc0d7fa0d4e587e8429c0b1bfeff72a Jira: STUDIO-6105 * ENH: save video ctrl size to reduce layout change Change-Id: I470f29d7f029d304c9badeeb8f94bed281080b29 Jira: STUDIO-6141 * ENH: stop liveview track record Change-Id: Id4f236b239740bd919f2aa2f2892c1e63ce233bd Jira: STUDIO-6131 * FIX: thread safe of http extra headers Change-Id: I6ffa424be7ccb6abd78a66cc8be535f038b05469 Jira: none * optimize MeshBoolean * FIX: parse printer_model_id from 3mf Change-Id: Ib149c986885ee6412898f1f51dd5a4aaad0a596d Jira: none * ENH: find grid empty cells for fill bed if the item is too small jira: STUDIO-6015 Change-Id: I4e5eafdadd77482a27a8903d32bb83325283088d (cherry picked from commit 8df4da4a863cdc42c790a9d5da37f8633423e406) * ENH: always return product for firmware and lifycycle JIRA: STUDIO-6282 Change-Id: I1f942babdcb7afee2c9a9076ac539063c5406ad7 Signed-off-by: Stone Li * ENH:STL tracking restricted area jira:[STUDIO-6155] Change-Id: I289c8b8aa8f62f0e5cc7004fb60437aa3337ca85 * NEW:add nozzle settings jira:[STUDIO-6226] Change-Id: I0db8333e5b5c8195add111fdcfa2e92387997815 * ENH:display the current humidity of AMS jira:[ENH] Change-Id: I98bdd6d70cd173ed640f0d96692fcb6836416bb8 * FIX: [6123] create printer for exist printer can not into next page Jira: 6123 Change-Id: I338ac0fde4f69b6f312f20e53851d91339e8156f * ENH: Display value of flushing volumes JIRA:STUDIO-6139 Signed-off-by: Kunlong Ma Change-Id: I273fb22b0d378a839c34e9e0e9c414f0e5134799 * FIX: show printer file path & title Change-Id: Ie5eff188c3039deeca5da96b54407194bf8910a0 Jira: STUDIO-6268 * FIX: liveview error message Change-Id: Ie437e07916d7b6feae2dbcfa166c4e73bdcf31a1 Jira: STUDIO-6107 * FIX: file proto error message Change-Id: I2c4117961c615e424780fb3830441e6a93c50bcc Jira: none * ENH: earse sensitive fields when export configs Jira: None Change-Id: Id9ca0637240b80773f39d2308192f8c78a5de3c6 * fix build errors * FIX: unexpected layers in multi color print github: 3131 Change-Id: I2a42e3bbd2247fbc0957022e1baae43c9375a8fb * ENH: Add "New" button for PA cali Jira: XXXX Change-Id: Ic39f2508f2f9d390c2b9246fb3d3e281cde9b064 * NEW:add printer compatible check from sd card view jira:[STUDIO-5969] Change-Id: I86d10ebe2e9bc77e6350e26aeed6b4f0f9fdcecb * NEW:enable loadl/unload when printing pause jira:[STUDIO-5968] Change-Id: Ieb3ef2423378e44b81a61a2b18c16f68aa335922 * FIX:fixed HMS message not cleared jira:[STUDIO-6296] Change-Id: Ic7692ce337fd00ece4ab8d65214a8c406f8543f8 * ENH:error code setting default value jira:[for error code] Change-Id: Ica61344c8217d41adb2947a40f633dc8d19a197a * ENH:display conflict information jira:[STUDIO-6297] Change-Id: Ie1501323a7e8d9ceb4060ae6c0b4eab20f8b088a * ENH: refresh printer file list Change-Id: Ic86942d2b0b2e8383ef0f06311164aad59e837ad Github: 3383 * FIX: Unnecessary prime tower error prompts Custom gcode on other plate causes unnecessary prime tower error prompts Jira: 6305 Change-Id: If499659b364a6b6898db1587b7b2aeed03758667 * FIX:multi colour displayed as gradient color on AMS JIRA:5925 Change-Id: Ic7a925dda2e3bde066ba40ba27002569040f9518 * NEW:Color painting shortcut keys 10~16 JIRA:STUDIO-6238 Change-Id: I3cce838fad5e73d41f109b32f2e563716fd5b0da * ENH: Print when unnamed project, task named as object names github: #2286 Change-Id: I9be3fd25d16a00b78326ec43db9afcf3645d90f1 * ENH:reset user access code jira:[for lan mode] Change-Id: I2d0ed48411d683c3f20b2febc0d54747287870a7 * FIX:fixed crash when selecting new printer jira:[fix] Change-Id: I6a81186e822eb6bf6ce7aa70561dfae35d4de0e7 * FIX: not show printer's camera error when updating Jira: STUDIO-6232 Change-Id: I985d75b3772849e07100799c4f13db5d4cbafde3 * FIX: clear error after reload file list ok Change-Id: I5d5e4f2870302b198d3a9d40603a6fa8010b7e76 Jira: STUDIO-6306 * ENH: custom filament sync with printer 1. prompt sync user presets when create custom filament 2. Fix the issue of not displaying printers when creating custom Filaments based on presets when selecting PLA Aero Type. 3. Optimizing the traversal logic during AMS Setting Pop up reduces time complexity and allows for quick pop ups. Additionally, using nozzle calibers for retrieval and repairing custom materials may result in inaccurate retrieval. 4. Implement synchronization logic with the printer -a. Received slot information, reset the slot when the "filament_id" in the information does not exist in Studio -b. Received slot information, the nozzle temperature in the information is different from the preset nozzle temperature in Studio, reset the current temperature. Jira: none Change-Id: I511dc82563ec77a341839671d398607048ce1985 Signed-off-by: maosheng.wei * NEW: add api of "toggle_selected_volume_visibility" Jira: STUDIO-6166 Change-Id: I77eb988a3ea43cd37d50888d1753b973795d8b36 * FIX: No data in the drop-down menu of the AMS settings page Jira: 6342 6343 Change-Id: I6938fb4a7ae2816a4675d8d739622e25f219f469 * fix build error * FIX: label wrap all & ping test for liveview Change-Id: I7767ed0740e20bb578b6ef9f5e9873c8c79d172a Jira: STUDIO-5821 * ENH: reuse controls in param Field Change-Id: I42bb4da01e1e9b64c343b7fda4357a9553cf8684 Jira: STUDIO-5983 * FIX: use wide path to create camera process Change-Id: I5de31fce0dea14df9a0ad363f3cb16dc40c275bc Jira: STUDIO-4946 * ENH: optimize the get_tool_order func Use Dp to refine performance jira:[NEW] Signed-off-by: xun.zhang Change-Id: I38b0c875e4deee9d9fbe926087fb5b2e274f8f90 (cherry picked from commit 9b7b66dc7a1f5e3efa318227ae7694bec5ec1216) * Fix build errors * ENH: add customize other layers print sequence Jira: 6338 Change-Id: Ic14b2671ade37ab37583b81c5b509447b6c0d8f8 * ENH: [#3236] Unsaved changes to interface copy adjustment github: #3236 Change-Id: I53931859bdcdfedfa9f63f6239d0fd2fd6d2766c * NEW: support to adjust other layers print sequence Jira: 6338 Change-Id: I5e6aef71aa9e6e97c1859aaaeb9ada5f1340414a * FIX: imgui support toolbar window text wrapping issue jira: STUDIO-5821 Change-Id: I57ee984baffbb2f00a7ecc5d5c8061074b06aff6 * FIX: updater: fix force upgrade logic JIRA: STUDIO-6393 Change-Id: I46c51e09e7390e5ab0de40215911aac9635ab476 (cherry picked from commit 673ba6ff4ebda039d71dcbfdaa28c1252f5b8821) * FIX:final step of slicing is to execute post-processing script JIRA: STUDIO-5828 Change-Id: I8c33e2a66ac5c692244c778586040663b7b54bd7 * NEW:enable 3dMouse detect in .conf JIRA: 5830 Change-Id: I8731e0244d2f551130c84bcfbbb46967ae6b19cd * FIX:finish init "return" icon and hide it Jira: STUDIO-6350 Change-Id: I0f1efd4a64ea204daeac7de822602ef6dfa3e4a5 * FIX: seq_print: fix an invalid warning caused by sinking github: https://github.com/bambulab/BambuStudio/issues/3007 Change-Id: I1111910f2c625d5a871ea01b37dbfa7b04a849ee (cherry picked from commit a3db95bb0940d5afe07ef0bb07113cc2acd7cd0a) * ENH: plater: optimize the loading time of 3mf with large objects JIRA: STUDIO-6021 Change-Id: Ia97f681041bb553c5c4b5b1d9109e5e5c42daf6b * FIX:Fixed HMS issue jira:[STUDIO-6344 STUDIO-6310 STUDIO-6356 STUDIO-6348] Change-Id: I9d6660e7c349775004b69bfe41b651bfa8b359b7 * ENH:handling dirty data after nozzle settings jira:[STUDIO-6332] Change-Id: I00d6d1324376f973ec3cf9f2154ae83ef3302705 * ENH: use Bambu_StartStreamEx for agora tunnel Change-Id: I5c28dea49d267bf7ff967d0982dd83555899c8c4 Jira: none * FIX: use safe language code for http Change-Id: Id1f4927308350ee35b891a5352cbf1e2d0c2577e Github: 3655 * FIX: add cli_id, cli_ver to bambu url Change-Id: Ic527d1497c6dee0c723d7b4629f0be825a8f7545 Jira: none * FIX: not throw when _add_auxiliary_dir_to_archive Change-Id: Idf54bbbd0ef557ec5e1a8e51ed669a1eb1fb4261 Jira: STUDIO-6339 * NEW: vase mode can be applied to one plate jira: STUDIO-5838 Change-Id: Ifb315f7d79b570aeb7ee31d3495b4d465e3af0c6 * fix crashes * ENH: update overhang degree method on calssic mode Jira: none Signed-off-by: qing.zhang Change-Id: I90f6e4c2ef618fdaef00bdaf1ca309893f484c1e * FIX: auto-arranging unprintable items may crash github: #3676 Change-Id: I68eb87c73ad2c0c269f60e661136fd1a72ee5e2f (cherry picked from commit 7e3c57eaa811424935fe8db6a4e77dd142ee2b58) * FIX: use old slicer_uuid for client_id Change-Id: I6c45e83213d613fc28eef04115f9cfb19dea703e Jira: none * ci: update network module based on commit 542ced8 Change-Id: I3ad5032cc56a99d1c3a687b2891d147b13af066d * NEW:Support OLTP file Jira: STUDIO-6421 Change-Id: I58bc94e978e6d2dd136ea370fb01f6ec80e14b23 * ENH: detect in_head_wrap_zone more precisly 1.Union first layer convex hull with object's bbox to detect whether model enter head_wrap_detect_zone jira:NEW Signed-off-by: XunZhangBambu Change-Id: I11f26967d7421f41e9c824e62794c96591e6ae71 * FIX: fix the plate cannot be searched JIRA: STUDIO-6283 Signed-off-by: Kunlong Ma Change-Id: I88206c91ea24c6a41a0bd06f05f0f3c2fdc58a36 * NEW:hms error code JIRA: STUDIO-6302 Change-Id: Ia33511f4c636c8ada39ed5a4e52d9b185da9c00b * FIX:Color adaptation for numpad JIRA:STUDIO-6410 Change-Id: If6e49638af8616fd349367073883592e6bebb503 * FIX: error overhang degree mapping Jira: none Signed-off-by: qing.zhang Change-Id: Ifa24aa0cad0a06b09ee62a8be8781188a765d1d0 * FIX:display correct humidity jira:[fix] Change-Id: I27aae54a8355911b5d88ed45be320d3c9178081c * ENH:Hide confirmation button when unable to send print jira:[STUDIO-6355, STUDIO-6332] Change-Id: I8f9c0edea4d5ee70e9fef1e9d42838d598dc32c4 * NEW: new type for Custom Filament Type: "PE", "PP", "EVA", "PHA", "BVOH", "PE-CF", "PP-CF", "PP-GF" Github: 3205 3169 3127 Change-Id: I8a30dd806c35460d9dae0f808190ce013b125d51 Signed-off-by: maosheng.wei * FIX:fixed filament settings page display error in French jira:[STUDIO-5821] Change-Id: I6cc6dd9b83c7570688c2adc55efe2407cbcb4390 * FIX:fixed thumbnail not updating when using multiple plates jira:[STUDIO-6313] Change-Id: If49daa5b38b9a580ae226ff00a1e0085d167c15c * FIX: Color Bleed in slicer github: 3681 jira: 6450 Change-Id: Icb6274f7ddb238c238c133b95167310b1af905f7 * ci: update network module based on commit 8befd46 Change-Id: I3a6420684f106bdde5897a50d27dfec69e0aa37f * ci: update network module based on commit e411785 Change-Id: I3a9c7bfa5ac5a942f339ad0194a24d9170847371 * FIX:reload paint after background process apply Jira: STUDIO-6493 Change-Id: I9a1986152f05163f236f58bb24210b690ca3d562 * FIX: use object name of plate when send task in untitled project Jira: 6430 Change-Id: I78ec811fab1cf028c0d5f81ac7738abdbeb6145f * FIX: auto arranging spacing can't be adjusted correctly jira: none Change-Id: Ibddfe85aab9f3fad6a1612e8db437e52c40e20a3 (cherry picked from commit 136bca01f45e62042bd699a9a0a9f6d13519712c) * FIX: fix change nozzle temp in Studio but printer not change Jira: 6510 Change-Id: Ia0e1ac586ff41ddbabdac0845415e70774299387 Signed-off-by: maosheng.wei * ENH:rename some img files jira:[STUDIO-6512] Change-Id: I69872533cccda37b94384bc219cc35c5dec9310b * ENH:PEI bed is no longer unchecked by default jira:[STUDIO-6508] Change-Id: Ic9ca99860d46c27ca4c36a735df3f57fe71417df * FIX:fix the load status of vtray jira:[STUDIO-6435] Change-Id: I8cafcc0b6caf19492aae6c153fb509f470dc7e83 * FIX: Supports automatic calibration of textured PEI jira: 6504 Change-Id: I3234fb555b9bf0ea97e73387651874733e761ee7 * ENH:add tooltip for search item JIRA: STUDIO-6459 Signed-off-by: Kunlong Ma Change-Id: I7602a32159d21de8f37ea0208dd6a9f59b90dcce * ENH: CLI: add version check logic add option allow_newer_file Change-Id: I8e8e4a45f77ebdd6dae6189841e4a9952e95ca82 * ci: update build version to 01.09.00.52 Change-Id: Id6e32b5afcf5eaabce9c0c7ab2c422e97b00e632 * NEW: switch to object panel if double click on object jira: none switch to object panel if double click on object, otherwise switch to global panel if double click on background. Change-Id: I6e54d7957aa19f1ebb1f993bc38125bbee8a1c98 (cherry picked from commit cc2e07bc9489c76a7d767acff0406c83c996504c) * FIX:fixed loading img resource failure jira:[for fix img load] Change-Id: Ifb26b2ca23029abeda000322bf2ef7d2b3cda3b4 * FIX: Project Title can Click JIRA: none Change-Id: I614c60e76efe04875e36e3a8ef7a10acd3ef9ecf * FIX:Prioritize selecting filament with smaller serial numbers in AMS JIRA: 5909 Change-Id: If3030d4dd8d59af36bc1ae1801be1b89b0027a71 * NEW:material adaptation in select machine dialog JIRA:xxxx Change-Id: I625eac75c88cad804dd3741f750c5ea68a975421 * FIX:mac ams setting display JIRA: STUDIO-6228\6409 Change-Id: I432a3aa96601a8e223b5949bc0ad5234c1374dca * FIX: Image Scale Mode and Online Display JIRA: none Change-Id: I528f16e93b82748d86dc93e2dd3d85f317babaa7 * FIX: sequential_print_clearance_valid not working not working correctly with short objects jira: STUDIO-6489 Change-Id: I33e1a165f448e1c3e272d4045934c63ad345db2f (cherry picked from commit 9348eaa22a056db5384a38ea966cec9ba4a533a7) * NEW: add nozzle_height to machine profile and do not detect conflict Jira: request from 1.9 1. add nozzle_height to machine profile 2. auto arranging and sequential_print_clearance_valid don't consider objects conflicting if they are all shorter than nozzle_height and close. 3. do not detect conflict when all models are short. Change-Id: I8d1eebb15d5bfa8c40d7491e033149e360531b89 (cherry picked from commit 6b4b52653db5f08d724a556c5c766c0bfa00f34d) * FIX: sequential_print_clearance_valid not working not working correctly with short objects jira: STUDIO-6489 Change-Id: I33e1a165f448e1c3e272d4045934c63ad345db2f (cherry picked from commit 9348eaa22a056db5384a38ea966cec9ba4a533a7) * FIX: [6510] set nozzle temp incorrectly when popup AMS Setting Change-Id: I898f0b94794a3d67017b1917ce196c4019f5eb4a * FIX: auto-calculate flushing volumes JIRA: STUDIO-6547 FIX the first modification of consumable color after synchronizing filaments, without automatically calculating the flushing volumes Signed-off-by: Kunlong Ma Change-Id: I2bc76a29afde5241d100cc42a5161db0f9b901c4 * FIX: custom layer sequence from End to End comboBox display issue jira: new Change-Id: I413cd5896d7e921f2c7c03b91b08788fefb9a4f3 * FIX:fix the v tray's filament unload logic jira:[STUDIO-6627] Change-Id: I34420bc4d1d27b6b36defb9852bba2eaf77fdcf2 * NEW:reducing purge through retracting filament 1.reducing purge through retracting filament.Currently only applicable to X&P series github: PR#3100 Signed-off-by: XunZhangBambu Change-Id: Ie328039872e50e699dc5e5082fa99f68ac5f5fd1 * FIX: wrong role cache in wipe tower 1. Add wipe tower role cache in GCodeProcessor result 2. Add wiki link for prime tower jira:NEW Signed-off-by: xun.zhang Change-Id: Ia766c7218df68fb1ffba567af193d6bfecacf588 * Fix plate settng icon * NEW:revert hms error code Change-Id: Ib5cc8bb8b8ced0f70d5bbe4751a1f97258218c6f * FIX: calibration page button broken display issue jira: STUDIO-3913 Change-Id: I2fd488e829d898b7d81d09db814ed6518f0c54a8 * FIX: do not check spiral vase mode config if an object is loaded jira: STUDIO-6514 Change-Id: Ib44ec8322ff178b5765f7fe94b588aa38339691d * FIX: implicitly set spiral vase config for objects just loading jira: 6514 Change-Id: I04bb2b1abeb62d4dfff4e526b723b1cf1bd5fd7f * FIX: filling bed fails if the bed is already full JIRA: STUDIO-6490 Signed-off-by: Kunlong Ma Change-Id: I71b5a01a95cdffef7c0750e6347fa8911dcd781d * ci: update network module based on commit 868f5d7 Change-Id: I5584e4441e1f2ab400addaa87ee8013927fb9e15 * FIX: add query_real_volume_idx_from_other_view api Jira: STUDIO-6545 Change-Id: Ib8216981c5d2945a0221a5caa1fbc14ed74e930b * FIX: Can't edit text github: 3750 Change-Id: I1caecaa968e60cadcdbe9f7aa67cba141bb88230 * FIX: Slicer creates invalid color pattern github: 3749 Change-Id: I3fd74a9ca59b75873fcbca4437e4858c749ee853 * ENH: hide tuck did Change-Id: I9021d3f51c9a73bc9208b479f96b1ddbe7a2f8f8 Jira: none * FIX: PrinterFileSystem: retry connect on user action Change-Id: I3e8902298385ed2e5906fd15d1817b6e33522a76 Jira: STUDIO-6354 * FIX: Remove user ID and other information Jira: XXXX Change-Id: Ia63ec88a335d88fd40a29952abe6d40d8991efee * ENH: refine retraction before cut 1. Add filament retraction before cut control jira:NEW Signed-off-by: xun.zhang Change-Id: Ifcb087c9791c0461b793ef811b21ebd4c007d880 * FIX: enable resumed read only Field Change-Id: Id09e671932458699c020f0a061d8cfc11a6958ab Jira: STUDIO-6641 * ENH: add precise_z_height jira: none Change-Id: Idb9fcf0063e773f1531a49961478460b91ded10f * ENH: modify the multi-material segmentation and voronoi This patch is cherry pick from Prusa, thanks to Prusa Rework multi-material segmentation to work directly on the Voronoi diagram without creating a copy of it. Previous algorithms assume that they can get an invalid Voronoi diagram. Because of that, during the multi-material segmentation, a copy of the Voronoi diagram was created, and there were several attempts to fix missing vertices and edges. But as it shows, this wasn't a good enough approach and sometimes led to several issues like bleeding layers. After generalization, our approach for detection and repairs of invalid Voronoi diagrams from Arachne, we could assume that multi-material segmentation gets non-invalid Voronoi diagrams. With this assumption, we reimplement multi-materials segmentation to work directly on the Voronoi diagram. That should make multi-material segmentation more stable. So, this should fix several issues like bleeding layers. Also, memory consumption should decrease by a lot. Also, there should be some speedup of multi-materials segmentation. Jira: none Change-Id: I72aa6e1f9634d9ee8759aa469a0b39a36ace62f5 * FIX: infill speed not work on region level Jira: none Signed-off-by: qing.zhang Change-Id: Ie3d17c5e3cbf91a8854e3b4cd80babeb2b1bd121 * ENH: support saving PA calibration results for P series Jira: none Change-Id: I9402b8bcce7b48a63d0e97e0708080701d065e7a * ENH: refine long retraction ui 1. associate button display logic 2. Add valid range tip 3. seperate the printer into three types jira:NEW Signed-off-by: xun.zhang Change-Id: Ie14c8746eb20456dacd5c129a5449c1e7c7db372 * FIX:height range cut = volume_count * 2 Jira: none Change-Id: I539c2f9cda7985b4b3c318ca8aa1eb7c52fdce82 * FIX: auto arranging gets wrong object height obj->bounding_box().size() is not the real object size if the object has been rotated. jira: STUDIO-5999 Change-Id: I6553d4c990696efd674e3e57063802127d5d5282 (cherry picked from commit 479ea9fb02f55d24f27c94633f3d852bd5c62c83) * ENH: seperate support weight from model jira:NEW Signed-off-by: XunZhangBambu Change-Id: I86bb34941269bf1aa29436a94ebbdff675497e85 * ENH: add support for gcodeviewer statistics jira: new Change-Id: Ied6d61e8c48ac82daf16579d9caed9723cf8e29d * FIX: invalid support weight per extruder jira:NEW Signed-off-by: xun.zhang Change-Id: I0e4b857c9c758ab7c54ef13aee1bf596f975640b * FIX: do not need reset bed_type for pa calibration jira: none Change-Id: I411064cf14d94a9bd1f0f6668ee23aa10d372f3d * FIX: P1P/S can not modify the k value in old version jira: 6745 Change-Id: I5c9dffe8e998213e6af6e1d01a6b0ae82521e8db * Add rotation support for 3D Honeycomb Ported from BS * ENH: add default params for long retraction 1. Only auto calculate flush when enabled 2. Add default params for long retraction 3. Disable filament override for unsupport machines jira:NEW Signed-off-by: xun.zhang Change-Id: Ib5d51505b58101839527e944f9a237483951f9fe * misc fixes * ENH: remove long retraction warning jira:NEW Signed-off-by: tao wang Change-Id: If60236b3282991a2d94df7d125427cff86899536 * avoid zero length path * FIX: check recommended nozzle temperature Jira: XXXX Change-Id: I4dbb274cf27ef9c6d20a8479b29af1069652b2bc * FIX: fix not popping up a prompt when the temperature is set to 0 Jira: 6497 Change-Id: I6498fc6962e7da376d4c652dab0a99a161932eef Signed-off-by: maosheng.wei * ENH: When creating a custom Filament, use the system Filament type. Jira: 6301 Change-Id: I1bfddcf43d2ebaebca4eb494d1f64165c3d59e9e Signed-off-by: maosheng.wei * FIX: seam and unretarct pos error on smooth vase casused by invalid path of smooth vase mode Signed-off-by: qing.zhang Change-Id: Ib597e8c05760886aae2c42e42e8d46e82b844578 * FIX: unable to map if filament not used in model 1.Fix filament can not map if it's not used in model body jira:NEW Signed-off-by: xun.zhang Change-Id: Ibd2685ffd198b2e17dbf44289d0144b5b7c25788 * NEW:Update data only on device pages jira:[STUDIO-6776] Change-Id: I33b0c9f35c1dc6df2db3b6bd4f446f46b31ecf6c * set(SLIC3R_VERSION "01.09.00.70") * update BBL machine profile 01.09.00.04 * scarf clip start and end Ported from BambuStudio * fix linux build error --------- Co-authored-by: Arthur Co-authored-by: zhou.xu Co-authored-by: wenjie.guo Co-authored-by: chunmao.guo Co-authored-by: maosheng.wei Co-authored-by: hu.wang Co-authored-by: lane.wei Co-authored-by: Kunlong Ma Co-authored-by: zhimin.zeng Co-authored-by: zorro.zhang Co-authored-by: tao wang Co-authored-by: Stone Li Co-authored-by: xun.zhang Co-authored-by: liz.li Co-authored-by: qing.zhang Co-authored-by: gerrit Co-authored-by: Leon Fisher-Skipper <47602359+LeonFisherSkipper@users.noreply.github.com> Co-authored-by: Lukas Matena Co-authored-by: jianjia.ma --- resources/images/fd_pattern_manual_device.png | Bin 0 -> 239574 bytes resources/images/hum_level1_dark.svg | 5 + resources/images/hum_level1_light.svg | 5 + resources/images/hum_level2_dark.svg | 5 + resources/images/hum_level2_light.svg | 5 + resources/images/hum_level3_dark.svg | 5 + resources/images/hum_level3_light.svg | 5 + resources/images/hum_level4_dark.svg | 5 + resources/images/hum_level4_light.svg | 5 + resources/images/hum_level5_dark.svg | 5 + resources/images/hum_level5_light.svg | 5 + resources/images/hum_popup_close.svg | 4 + resources/images/humidity_list_background.png | Bin 0 -> 44573 bytes resources/images/monitor_hms_new.svg | 3 + resources/printers/N1.json | 1 - resources/printers/N2S.json | 1 - resources/profiles/BBL.json | 242 ++- .../Bambu ABS @BBL A1 0.2 nozzle.json | 3 + .../BBL/filament/Bambu ABS @BBL A1.json | 3 + .../Bambu ABS @BBL X1C 0.2 nozzle.json | 6 + .../Bambu ABS @BBL X1C 0.8 nozzle.json | 6 + .../BBL/filament/Bambu ABS @BBL X1C.json | 6 + .../BBL/filament/Bambu ABS-GF @BBL A1.json | 13 + .../BBL/filament/Bambu ABS-GF @BBL P1P.json | 13 + .../BBL/filament/Bambu ABS-GF @BBL X1C.json | 22 + .../BBL/filament/Bambu ABS-GF @base.json | 41 + .../Bambu ASA @BBL A1 0.6 nozzle.json | 3 - .../Bambu ASA @BBL X1 0.2 nozzle.json | 3 - .../Bambu ASA @BBL X1 0.6 nozzle.json | 3 - .../BBL/filament/Bambu ASA @BBL X1C.json | 3 - .../BBL/filament/Bambu ASA @base.json | 23 +- .../BBL/filament/Bambu ASA-Aero @BBL A1.json | 13 + .../BBL/filament/Bambu ASA-Aero @BBL P1P.json | 13 + .../BBL/filament/Bambu ASA-Aero @BBL X1C.json | 22 + .../BBL/filament/Bambu ASA-Aero @base.json | 62 + .../BBL/filament/Bambu PA6-GF @BBL A1.json | 22 + .../BBL/filament/Bambu PA6-GF @BBL P1P.json | 22 + .../BBL/filament/Bambu PA6-GF @BBL X1C.json | 34 + .../BBL/filament/Bambu PA6-GF @base.json | 44 + .../filament/Bambu PC @BBL A1 0.2 nozzle.json | 3 + .../BBL/filament/Bambu PC @BBL A1.json | 3 + .../Bambu PC @BBL X1C 0.2 nozzle.json | 6 + .../Bambu PC @BBL X1C 0.6 nozzle.json | 6 + .../Bambu PC @BBL X1C 0.8 nozzle.json | 6 + .../BBL/filament/Bambu PC @BBL X1C.json | 6 + .../Bambu PETG Basic @BBL X1C 0.2 nozzle.json | 6 + .../Bambu PETG Basic @BBL X1C 0.8 nozzle.json | 6 + .../filament/Bambu PETG Basic @BBL X1C.json | 6 + .../BBL/filament/Bambu PLA Aero @BBL X1C.json | 3 + .../BBL/filament/Bambu PLA Basic @BBL X1.json | 6 + .../Bambu PLA Basic @BBL X1C 0.2 nozzle.json | 9 + .../Bambu PLA Basic @BBL X1C 0.8 nozzle.json | 9 + .../filament/Bambu PLA Basic @BBL X1C.json | 9 + ...Bambu PLA Dynamic @BBL X1C 0.2 nozzle.json | 3 + ...Bambu PLA Dynamic @BBL X1C 0.8 nozzle.json | 3 + .../filament/Bambu PLA Dynamic @BBL X1C.json | 3 + .../Bambu PLA Galaxy @BBL X1C 0.2 nozzle.json | 3 + .../Bambu PLA Galaxy @BBL X1C 0.8 nozzle.json | 3 + .../filament/Bambu PLA Galaxy @BBL X1C.json | 3 + .../BBL/filament/Bambu PLA Glow @BBL X1C.json | 3 + .../BBL/filament/Bambu PLA Glow @BBL X1E.json | 3 + .../BBL/filament/Bambu PLA Impact @base.json | 9 +- .../filament/Bambu PLA Marble @BBL X1C.json | 3 + .../BBL/filament/Bambu PLA Matte @BBL X1.json | 3 + .../Bambu PLA Matte @BBL X1C 0.2 nozzle.json | 3 + .../Bambu PLA Matte @BBL X1C 0.8 nozzle.json | 3 + .../filament/Bambu PLA Matte @BBL X1C.json | 3 + .../Bambu PLA Metal @BBL X1C 0.2 nozzle.json | 3 + .../filament/Bambu PLA Metal @BBL X1C.json | 3 + .../Bambu PLA Silk @BBL X1C 0.2 nozzle.json | 3 + .../BBL/filament/Bambu PLA Silk @BBL X1C.json | 3 + .../filament/Bambu PLA Sparkle @BBL X1C.json | 3 + .../Bambu PLA Tough @BBL X1C 0.2 nozzle.json | 3 + .../filament/Bambu PLA Tough @BBL X1C.json | 3 + .../Bambu PLA-CF @BBL X1C 0.8 nozzle.json | 3 + .../BBL/filament/Bambu PLA-CF @BBL X1C.json | 3 + ...pport For PLA-PETG @BBL A1 0.2 nozzle.json | 32 + .../Bambu Support For PLA-PETG @BBL A1.json | 31 + ...port For PLA-PETG @BBL A1M 0.2 nozzle.json | 32 + .../Bambu Support For PLA-PETG @BBL A1M.json | 31 + ...port For PLA-PETG @BBL P1P 0.2 nozzle.json | 32 + .../Bambu Support For PLA-PETG @BBL P1P.json | 31 + ...port For PLA-PETG @BBL X1C 0.2 nozzle.json | 23 + .../Bambu Support For PLA-PETG @BBL X1C.json | 28 + .../Bambu Support For PLA-PETG @base.json | 53 + .../BBL/filament/Generic BVOH @BBL A1.json | 13 + .../BBL/filament/Generic BVOH @BBL A1M.json | 13 + .../BBL/filament/Generic BVOH @BBL X1C.json | 25 + .../BBL/filament/Generic BVOH @base.json | 8 + .../BBL/filament/Generic EVA @BBL A1.json | 14 + .../BBL/filament/Generic EVA @BBL A1M.json | 14 + .../BBL/filament/Generic EVA @BBL X1C.json | 26 + .../BBL/filament/Generic EVA @base.json | 86 + .../BBL/filament/Generic PCTG @BBL A1.json | 13 + .../BBL/filament/Generic PCTG @BBL A1M.json | 13 + .../BBL/filament/Generic PCTG @BBL X1C.json | 25 + .../BBL/filament/Generic PCTG @base.json | 74 + .../BBL/filament/Generic PE @BBL A1.json | 14 + .../BBL/filament/Generic PE @BBL A1M.json | 14 + .../BBL/filament/Generic PE @BBL X1C.json | 26 + .../BBL/filament/Generic PE @base.json | 35 + .../BBL/filament/Generic PE-CF @BBL A1.json | 14 + .../BBL/filament/Generic PE-CF @BBL A1M.json | 14 + .../BBL/filament/Generic PE-CF @BBL X1C.json | 25 + .../BBL/filament/Generic PE-CF @base.json | 38 + .../BBL/filament/Generic PHA @BBL A1.json | 14 + .../BBL/filament/Generic PHA @BBL A1M.json | 14 + .../BBL/filament/Generic PHA @BBL X1C.json | 26 + .../BBL/filament/Generic PHA @base.json | 8 + .../Generic PLA High Speed @BBL X1C.json | 3 + .../BBL/filament/Generic PLA Silk.json | 3 + .../BBL/filament/Generic PP @BBL A1.json | 14 + .../BBL/filament/Generic PP @BBL A1M.json | 14 + .../BBL/filament/Generic PP @BBL X1C.json | 26 + .../BBL/filament/Generic PP @base.json | 8 + .../BBL/filament/Generic PP-CF @BBL A1.json | 14 + .../BBL/filament/Generic PP-CF @BBL X1C.json | 26 + .../BBL/filament/Generic PP-CF @base.json | 20 + .../BBL/filament/Generic PP-GF @BBL A1.json | 14 + .../BBL/filament/Generic PP-GF @BBL X1C.json | 26 + .../BBL/filament/Generic PP-GF @base.json | 20 + .../filament/Overture Matte PLA @BBL X1.json | 3 + .../filament/Overture Matte PLA @BBL X1C.json | 3 + .../BBL/filament/Overture PLA @BBL X1.json | 3 + .../BBL/filament/Overture PLA @BBL X1C.json | 3 + .../P1P/Bambu ABS @BBL P1P 0.2 nozzle.json | 3 + .../BBL/filament/P1P/Bambu ABS @BBL P1P.json | 3 + .../P1P/Bambu PC @BBL P1P 0.2 nozzle.json | 3 + .../BBL/filament/P1P/Bambu PC @BBL P1P.json | 3 + .../filament/P1P/PolyTerra PLA @BBL P1P.json | 3 + .../BBL/filament/PolyLite PLA @BBL X1.json | 3 + .../BBL/filament/PolyLite PLA @BBL X1C.json | 3 + .../BBL/filament/PolyTerra PLA @BBL X1.json | 3 + .../BBL/filament/PolyTerra PLA @BBL X1C.json | 3 + .../BBL/filament/fdm_filament_bvoh.json | 85 + .../BBL/filament/fdm_filament_common.json | 6 + .../BBL/filament/fdm_filament_eva.json | 10 + .../BBL/filament/fdm_filament_pc.json | 88 +- .../BBL/filament/fdm_filament_pe.json | 85 + .../BBL/filament/fdm_filament_pha.json | 85 + .../BBL/filament/fdm_filament_pp.json | 85 + .../BBL/machine/Bambu Lab A1 0.2 nozzle.json | 6 + .../BBL/machine/Bambu Lab A1 0.4 nozzle.json | 7 +- .../machine/Bambu Lab A1 mini 0.4 nozzle.json | 5 +- .../BBL/machine/Bambu Lab P1P 0.2 nozzle.json | 2 +- .../BBL/machine/Bambu Lab P1P 0.4 nozzle.json | 7 +- .../BBL/machine/Bambu Lab P1P 0.6 nozzle.json | 2 +- .../BBL/machine/Bambu Lab P1P 0.8 nozzle.json | 2 +- .../BBL/machine/Bambu Lab P1S 0.2 nozzle.json | 2 +- .../BBL/machine/Bambu Lab P1S 0.4 nozzle.json | 7 +- .../BBL/machine/Bambu Lab P1S 0.6 nozzle.json | 2 +- .../BBL/machine/Bambu Lab P1S 0.8 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1 0.2 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1 0.4 nozzle.json | 7 +- .../BBL/machine/Bambu Lab X1 0.6 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1 0.8 nozzle.json | 2 +- .../Bambu Lab X1 Carbon 0.2 nozzle.json | 2 +- .../Bambu Lab X1 Carbon 0.4 nozzle.json | 7 +- .../Bambu Lab X1 Carbon 0.6 nozzle.json | 2 +- .../Bambu Lab X1 Carbon 0.8 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1 Carbon.json | 2 +- .../profiles/BBL/machine/Bambu Lab X1.json | 2 +- .../BBL/machine/Bambu Lab X1E 0.2 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1E 0.4 nozzle.json | 7 +- .../BBL/machine/Bambu Lab X1E 0.6 nozzle.json | 2 +- .../BBL/machine/Bambu Lab X1E 0.8 nozzle.json | 2 +- .../BBL/machine/fdm_machine_common.json | 4 +- .../0.06mm Fine @BBL A1 0.2 nozzle.json | 1 + .../0.06mm Fine @BBL A1M 0.2 nozzle.json | 1 + .../0.06mm Fine @BBL P1P 0.2 nozzle.json | 1 + ....06mm High Quality @BBL A1 0.2 nozzle.json | 1 + ...06mm High Quality @BBL A1M 0.2 nozzle.json | 1 + ...06mm High Quality @BBL P1P 0.2 nozzle.json | 1 + ...06mm High Quality @BBL X1C 0.2 nozzle.json | 1 + .../0.06mm Standard @BBL X1C 0.2 nozzle.json | 1 + .../process/0.08mm Extra Fine @BBL A1.json | 1 + .../process/0.08mm Extra Fine @BBL A1M.json | 1 + .../process/0.08mm Extra Fine @BBL P1P.json | 1 + .../process/0.08mm Extra Fine @BBL X1C.json | 1 + ....08mm High Quality @BBL A1 0.2 nozzle.json | 1 + .../process/0.08mm High Quality @BBL A1.json | 1 + ...08mm High Quality @BBL A1M 0.2 nozzle.json | 1 + .../process/0.08mm High Quality @BBL A1M.json | 1 + ...08mm High Quality @BBL P1P 0.2 nozzle.json | 1 + .../process/0.08mm High Quality @BBL P1P.json | 1 + ...08mm High Quality @BBL X1C 0.2 nozzle.json | 1 + .../process/0.08mm High Quality @BBL X1C.json | 1 + .../0.08mm Optimal @BBL A1 0.2 nozzle.json | 1 + .../0.08mm Optimal @BBL A1M 0.2 nozzle.json | 1 + .../0.08mm Optimal @BBL P1P 0.2 nozzle.json | 1 + .../0.08mm Standard @BBL X1C 0.2 nozzle.json | 1 + ....10mm High Quality @BBL A1 0.2 nozzle.json | 1 + ...10mm High Quality @BBL A1M 0.2 nozzle.json | 1 + ...10mm High Quality @BBL P1P 0.2 nozzle.json | 1 + ...10mm High Quality @BBL X1C 0.2 nozzle.json | 1 + .../0.10mm Standard @BBL A1 0.2 nozzle.json | 1 + .../0.10mm Standard @BBL A1M 0.2 nozzle.json | 1 + .../0.10mm Standard @BBL P1P 0.2 nozzle.json | 1 + .../0.10mm Standard @BBL X1C 0.2 nozzle.json | 1 + .../0.12mm Draft @BBL A1 0.2 nozzle.json | 1 + .../0.12mm Draft @BBL A1M 0.2 nozzle.json | 1 + .../0.12mm Draft @BBL P1P 0.2 nozzle.json | 1 + .../BBL/process/0.12mm Fine @BBL A1.json | 1 + .../BBL/process/0.12mm Fine @BBL A1M.json | 1 + .../BBL/process/0.12mm Fine @BBL P1P.json | 1 + .../BBL/process/0.12mm Fine @BBL X1C.json | 1 + .../process/0.12mm High Quality @BBL A1.json | 1 + .../process/0.12mm High Quality @BBL A1M.json | 1 + .../process/0.12mm High Quality @BBL P1P.json | 1 + .../process/0.12mm High Quality @BBL X1C.json | 1 + .../0.12mm Standard @BBL X1C 0.2 nozzle.json | 1 + ...0.14mm Extra Draft @BBL A1 0.2 nozzle.json | 1 + ....14mm Extra Draft @BBL A1M 0.2 nozzle.json | 1 + ....14mm Extra Draft @BBL P1P 0.2 nozzle.json | 1 + .../0.14mm Standard @BBL X1C 0.2 nozzle.json | 1 + .../process/0.16mm High Quality @BBL A1.json | 1 + .../process/0.16mm High Quality @BBL A1M.json | 1 + .../process/0.16mm High Quality @BBL P1P.json | 1 + .../process/0.16mm High Quality @BBL X1C.json | 1 + .../BBL/process/0.16mm Optimal @BBL A1.json | 1 + .../BBL/process/0.16mm Optimal @BBL A1M.json | 1 + .../BBL/process/0.16mm Optimal @BBL P1P.json | 1 + .../BBL/process/0.16mm Optimal @BBL X1C.json | 1 + .../0.18mm Fine @BBL A1 0.6 nozzle.json | 1 + .../0.18mm Fine @BBL A1M 0.6 nozzle.json | 1 + .../0.18mm Fine @BBL P1P 0.6 nozzle.json | 1 + .../0.18mm Standard @BBL X1C 0.6 nozzle.json | 1 + .../BBL/process/0.20mm Standard @BBL A1.json | 1 + .../BBL/process/0.20mm Standard @BBL A1M.json | 1 + .../BBL/process/0.20mm Standard @BBL P1P.json | 1 + .../BBL/process/0.20mm Standard @BBL X1C.json | 1 + .../BBL/process/0.20mm Strength @BBL A1.json | 1 + .../BBL/process/0.20mm Strength @BBL A1M.json | 1 + .../BBL/process/0.20mm Strength @BBL P1P.json | 1 + .../BBL/process/0.20mm Strength @BBL X1C.json | 3 +- .../BBL/process/0.24mm Draft @BBL A1.json | 1 + .../BBL/process/0.24mm Draft @BBL A1M.json | 1 + .../BBL/process/0.24mm Draft @BBL P1P.json | 1 + .../BBL/process/0.24mm Draft @BBL X1C.json | 1 + .../0.24mm Fine @BBL A1 0.8 nozzle.json | 1 + .../0.24mm Fine @BBL A1M 0.8 nozzle.json | 1 + .../0.24mm Fine @BBL P1P 0.8 nozzle.json | 1 + .../0.24mm Optimal @BBL A1 0.6 nozzle.json | 1 + .../0.24mm Optimal @BBL A1M 0.6 nozzle.json | 1 + .../0.24mm Optimal @BBL P1P 0.6 nozzle.json | 1 + .../0.24mm Standard @BBL X1C 0.6 nozzle.json | 1 + .../0.24mm Standard @BBL X1C 0.8 nozzle.json | 1 + .../process/0.28mm Extra Draft @BBL A1.json | 1 + .../process/0.28mm Extra Draft @BBL A1M.json | 1 + .../process/0.28mm Extra Draft @BBL P1P.json | 1 + .../process/0.28mm Extra Draft @BBL X1C.json | 1 + .../0.30mm Standard @BBL A1 0.6 nozzle.json | 1 + .../0.30mm Standard @BBL A1M 0.6 nozzle.json | 1 + .../0.30mm Standard @BBL P1P 0.6 nozzle.json | 1 + .../0.30mm Standard @BBL X1 0.6 nozzle.json | 1 + .../0.30mm Standard @BBL X1C 0.6 nozzle.json | 1 + .../0.30mm Strength @BBL A1 0.6 nozzle.json | 1 + .../0.30mm Strength @BBL A1M 0.6 nozzle.json | 1 + .../0.30mm Strength @BBL P1P 0.6 nozzle.json | 1 + .../0.30mm Strength @BBL X1C 0.6 nozzle.json | 1 + .../0.32mm Optimal @BBL A1 0.8 nozzle.json | 1 + .../0.32mm Optimal @BBL A1M 0.8 nozzle.json | 1 + .../0.32mm Optimal @BBL P1P 0.8 nozzle.json | 1 + .../0.32mm Standard @BBL X1C 0.8 nozzle.json | 1 + .../0.36mm Draft @BBL A1 0.6 nozzle.json | 1 + .../0.36mm Draft @BBL A1M 0.6 nozzle.json | 1 + .../0.36mm Draft @BBL P1P 0.6 nozzle.json | 1 + .../0.36mm Standard @BBL X1C 0.6 nozzle.json | 1 + .../0.40mm Standard @BBL A1 0.8 nozzle.json | 1 + .../0.40mm Standard @BBL A1M 0.8 nozzle.json | 1 + .../0.40mm Standard @BBL P1P 0.8 nozzle.json | 1 + .../0.40mm Standard @BBL X1 0.8 nozzle.json | 1 + .../0.40mm Standard @BBL X1C 0.8 nozzle.json | 1 + ...0.42mm Extra Draft @BBL A1 0.6 nozzle.json | 1 + ....42mm Extra Draft @BBL A1M 0.6 nozzle.json | 1 + ....42mm Extra Draft @BBL P1P 0.6 nozzle.json | 1 + .../0.42mm Standard @BBL X1C 0.6 nozzle.json | 1 + .../0.48mm Draft @BBL A1 0.8 nozzle.json | 1 + .../0.48mm Draft @BBL A1M 0.8 nozzle.json | 1 + .../0.48mm Draft @BBL P1P 0.8 nozzle.json | 1 + .../0.48mm Standard @BBL X1C 0.8 nozzle.json | 1 + ...0.56mm Extra Draft @BBL A1 0.8 nozzle.json | 1 + ....56mm Extra Draft @BBL A1M 0.8 nozzle.json | 1 + ....56mm Extra Draft @BBL P1P 0.8 nozzle.json | 1 + .../0.56mm Standard @BBL X1C 0.8 nozzle.json | 1 + .../fdm_process_bbl_0.06_nozzle_0.2.json | 4 +- .../BBL/process/fdm_process_bbl_0.08.json | 4 +- .../fdm_process_bbl_0.08_nozzle_0.2.json | 4 +- .../fdm_process_bbl_0.10_nozzle_0.2.json | 4 +- .../BBL/process/fdm_process_bbl_0.12.json | 4 +- .../fdm_process_bbl_0.12_nozzle_0.2.json | 4 +- .../fdm_process_bbl_0.14_nozzle_0.2.json | 4 +- .../BBL/process/fdm_process_bbl_0.16.json | 4 +- .../fdm_process_bbl_0.18_nozzle_0.6.json | 4 +- resources/web/homepage/js/home.js | 36 +- resources/web/homepage2/css/online.css | 162 ++ resources/web/homepage2/css/recent.css | 257 +++ resources/web/model/model.js | 6 + src/OrcaSlicer.cpp | 83 +- src/admesh/stl.h | 12 +- src/admesh/stl_io.cpp | 2 +- src/admesh/stlinit.cpp | 49 +- src/libslic3r/AppConfig.cpp | 8 + .../Arachne/SkeletalTrapezoidation.cpp | 384 +---- .../Arachne/SkeletalTrapezoidation.hpp | 54 +- .../Arachne/utils/PolygonsSegmentIndex.hpp | 19 + src/libslic3r/Arachne/utils/VoronoiUtils.cpp | 251 --- src/libslic3r/Arachne/utils/VoronoiUtils.hpp | 47 - src/libslic3r/Arrange.cpp | 10 +- src/libslic3r/Arrange.hpp | 1 + src/libslic3r/CMakeLists.txt | 7 +- src/libslic3r/CSGMesh/CSGMesh.hpp | 1 + src/libslic3r/CSGMesh/ModelToCSGMesh.hpp | 2 +- .../CSGMesh/PerformCSGMeshBooleans.hpp | 73 +- src/libslic3r/ExtrusionEntity.cpp | 79 +- src/libslic3r/ExtrusionEntity.hpp | 27 +- src/libslic3r/Fill/Fill.cpp | 24 +- src/libslic3r/Fill/Fill3DHoneycomb.cpp | 31 +- src/libslic3r/Format/STL.cpp | 6 +- src/libslic3r/Format/STL.hpp | 2 +- src/libslic3r/Format/bbs_3mf.cpp | 57 +- src/libslic3r/GCode.cpp | 114 +- src/libslic3r/GCode.hpp | 1 + src/libslic3r/GCode/GCodeProcessor.cpp | 36 +- src/libslic3r/GCode/GCodeProcessor.hpp | 11 + src/libslic3r/GCode/SpiralVase.cpp | 16 +- src/libslic3r/GCode/ToolOrdering.cpp | 140 +- src/libslic3r/GCode/ToolOrdering.hpp | 6 +- src/libslic3r/GCodeReader.hpp | 1 + src/libslic3r/Geometry/MedialAxis.cpp | 2 +- src/libslic3r/Geometry/Voronoi.cpp | 354 +++++ src/libslic3r/Geometry/Voronoi.hpp | 186 ++- src/libslic3r/Geometry/VoronoiOffset.cpp | 6 - src/libslic3r/Geometry/VoronoiUtils.cpp | 283 ++++ src/libslic3r/Geometry/VoronoiUtils.hpp | 120 ++ src/libslic3r/Geometry/VoronoiUtilsCgal.cpp | 269 +++- src/libslic3r/Geometry/VoronoiUtilsCgal.hpp | 9 +- src/libslic3r/MeshBoolean.cpp | 10 +- src/libslic3r/Model.cpp | 18 +- src/libslic3r/Model.hpp | 2 + src/libslic3r/ModelArrange.cpp | 3 +- src/libslic3r/MultiMaterialSegmentation.cpp | 1397 +++++------------ src/libslic3r/MultiMaterialSegmentation.hpp | 30 +- src/libslic3r/ParameterUtils.cpp | 45 + src/libslic3r/ParameterUtils.hpp | 14 + src/libslic3r/PerimeterGenerator.cpp | 308 +++- src/libslic3r/PerimeterGenerator.hpp | 13 +- src/libslic3r/Preset.cpp | 93 +- src/libslic3r/Preset.hpp | 8 +- src/libslic3r/PresetBundle.cpp | 95 +- src/libslic3r/PresetBundle.hpp | 9 + src/libslic3r/Print.cpp | 41 +- src/libslic3r/Print.hpp | 10 +- src/libslic3r/PrintApply.cpp | 7 +- src/libslic3r/PrintConfig.cpp | 95 +- src/libslic3r/PrintConfig.hpp | 16 +- src/libslic3r/PrintObject.cpp | 3 +- src/libslic3r/PrintObjectSlice.cpp | 2 +- src/libslic3r/ProjectTask.hpp | 2 + src/libslic3r/Slicing.cpp | 99 +- src/libslic3r/Slicing.hpp | 3 +- src/libslic3r/TriangleMesh.cpp | 10 +- src/libslic3r/TriangleMesh.hpp | 2 +- src/libslic3r/Utils.hpp | 1 + src/libslic3r/calib.hpp | 6 + src/slic3r/GUI/AMSMaterialsSetting.cpp | 163 +- src/slic3r/GUI/AMSMaterialsSetting.hpp | 2 +- src/slic3r/GUI/AMSSetting.cpp | 69 +- src/slic3r/GUI/AMSSetting.hpp | 4 +- src/slic3r/GUI/AmsMappingPopup.cpp | 367 +++-- src/slic3r/GUI/AmsMappingPopup.hpp | 48 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 36 +- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 1 + src/slic3r/GUI/CaliHistoryDialog.cpp | 279 +++- src/slic3r/GUI/CaliHistoryDialog.hpp | 34 + src/slic3r/GUI/CalibrationWizard.cpp | 103 +- src/slic3r/GUI/CalibrationWizardCaliPage.cpp | 5 +- .../GUI/CalibrationWizardPresetPage.cpp | 77 +- .../GUI/CalibrationWizardPresetPage.hpp | 12 +- src/slic3r/GUI/CalibrationWizardSavePage.cpp | 18 +- src/slic3r/GUI/CalibrationWizardStartPage.cpp | 19 +- src/slic3r/GUI/CameraPopup.cpp | 19 + src/slic3r/GUI/CameraPopup.hpp | 2 + src/slic3r/GUI/ConfigManipulation.cpp | 116 +- src/slic3r/GUI/ConfigManipulation.hpp | 7 +- src/slic3r/GUI/CreatePresetsDialog.cpp | 208 ++- src/slic3r/GUI/CreatePresetsDialog.hpp | 5 +- src/slic3r/GUI/DeviceManager.cpp | 317 ++-- src/slic3r/GUI/DeviceManager.hpp | 10 +- src/slic3r/GUI/Field.cpp | 167 +- src/slic3r/GUI/GCodeViewer.cpp | 393 +++-- src/slic3r/GUI/GLCanvas3D.cpp | 120 +- src/slic3r/GUI/GLCanvas3D.hpp | 41 +- src/slic3r/GUI/GUI_App.cpp | 105 +- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/GUI_Factories.cpp | 4 +- src/slic3r/GUI/GUI_ObjectList.cpp | 21 +- src/slic3r/GUI/GUI_ObjectSettings.cpp | 45 +- src/slic3r/GUI/GUI_ObjectTable.cpp | 72 +- src/slic3r/GUI/GUI_Preview.hpp | 3 + src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 6 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 43 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoText.cpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 29 +- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 4 + src/slic3r/GUI/HMSPanel.cpp | 39 + src/slic3r/GUI/HMSPanel.hpp | 8 + src/slic3r/GUI/IMToolbar.cpp | 7 + src/slic3r/GUI/IMToolbar.hpp | 4 +- src/slic3r/GUI/ImageGrid.cpp | 27 +- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 40 +- src/slic3r/GUI/Jobs/ArrangeJob.hpp | 2 + src/slic3r/GUI/Jobs/FillBedJob.cpp | 26 +- src/slic3r/GUI/Jobs/PrintJob.cpp | 39 +- src/slic3r/GUI/MediaFilePanel.cpp | 125 +- src/slic3r/GUI/MediaFilePanel.h | 4 + src/slic3r/GUI/MediaPlayCtrl.cpp | 298 ++-- src/slic3r/GUI/MediaPlayCtrl.h | 2 + src/slic3r/GUI/Monitor.cpp | 57 +- src/slic3r/GUI/Monitor.hpp | 5 + src/slic3r/GUI/Mouse3DController.cpp | 6 +- src/slic3r/GUI/MsgDialog.cpp | 120 ++ src/slic3r/GUI/MsgDialog.hpp | 26 +- src/slic3r/GUI/ObjectDataViewModel.cpp | 34 +- src/slic3r/GUI/ObjectDataViewModel.hpp | 8 +- src/slic3r/GUI/OptionsGroup.cpp | 14 +- src/slic3r/GUI/PartPlate.cpp | 206 ++- src/slic3r/GUI/PartPlate.hpp | 22 +- src/slic3r/GUI/PlateSettingsDialog.cpp | 442 +++++- src/slic3r/GUI/PlateSettingsDialog.hpp | 99 +- src/slic3r/GUI/Plater.cpp | 318 +++- src/slic3r/GUI/Plater.hpp | 5 + src/slic3r/GUI/Preferences.cpp | 4 + src/slic3r/GUI/PresetComboBoxes.cpp | 57 +- src/slic3r/GUI/PresetComboBoxes.hpp | 2 + src/slic3r/GUI/PrintOptionsDialog.cpp | 181 +++ src/slic3r/GUI/PrintOptionsDialog.hpp | 21 + src/slic3r/GUI/Printer/BambuTunnel.h | 6 +- src/slic3r/GUI/Printer/PrinterFileSystem.cpp | 34 +- src/slic3r/GUI/ReleaseNote.cpp | 100 +- src/slic3r/GUI/ReleaseNote.hpp | 26 +- src/slic3r/GUI/Search.cpp | 14 +- src/slic3r/GUI/Search.hpp | 2 +- src/slic3r/GUI/SelectMachine.cpp | 217 ++- src/slic3r/GUI/SelectMachine.hpp | 30 +- src/slic3r/GUI/Selection.cpp | 24 +- src/slic3r/GUI/Selection.hpp | 1 + src/slic3r/GUI/SendToPrinter.hpp | 2 +- src/slic3r/GUI/StatusPanel.cpp | 230 ++- src/slic3r/GUI/StatusPanel.hpp | 14 +- src/slic3r/GUI/Tab.cpp | 175 ++- src/slic3r/GUI/Tab.hpp | 1 + src/slic3r/GUI/TabButton.cpp | 16 +- src/slic3r/GUI/TabButton.hpp | 4 + src/slic3r/GUI/Tabbook.cpp | 6 + src/slic3r/GUI/Tabbook.hpp | 2 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 44 +- src/slic3r/GUI/WebGuideDialog.cpp | 57 +- src/slic3r/GUI/WebViewDialog.cpp | 11 +- src/slic3r/GUI/Widgets/AMSControl.cpp | 138 +- src/slic3r/GUI/Widgets/AMSControl.hpp | 6 +- src/slic3r/GUI/Widgets/ComboBox.cpp | 1 + src/slic3r/GUI/Widgets/Label.cpp | 34 +- src/slic3r/GUI/Widgets/ProgressDialog.cpp | 15 +- src/slic3r/GUI/Widgets/ProgressDialog.hpp | 5 +- src/slic3r/GUI/Widgets/SwitchButton.cpp | 7 + src/slic3r/GUI/Widgets/TempInput.cpp | 2 +- src/slic3r/GUI/Widgets/TempInput.hpp | 2 +- src/slic3r/GUI/Widgets/TextInput.cpp | 8 + src/slic3r/GUI/Widgets/TextInput.hpp | 2 + src/slic3r/GUI/WipeTowerDialog.cpp | 21 +- src/slic3r/GUI/WipeTowerDialog.hpp | 8 +- src/slic3r/GUI/wxMediaCtrl2.cpp | 15 +- src/slic3r/GUI/wxMediaCtrl2.h | 6 +- src/slic3r/GUI/wxMediaCtrl2.mm | 10 + src/slic3r/Utils/CalibUtils.cpp | 19 + src/slic3r/Utils/CalibUtils.hpp | 1 + src/slic3r/Utils/Http.cpp | 3 + src/slic3r/Utils/PresetUpdater.cpp | 77 +- src/slic3r/Utils/bambu_networking.hpp | 2 +- version.inc | 2 +- 484 files changed, 11279 insertions(+), 3579 deletions(-) create mode 100644 resources/images/fd_pattern_manual_device.png create mode 100644 resources/images/hum_level1_dark.svg create mode 100644 resources/images/hum_level1_light.svg create mode 100644 resources/images/hum_level2_dark.svg create mode 100644 resources/images/hum_level2_light.svg create mode 100644 resources/images/hum_level3_dark.svg create mode 100644 resources/images/hum_level3_light.svg create mode 100644 resources/images/hum_level4_dark.svg create mode 100644 resources/images/hum_level4_light.svg create mode 100644 resources/images/hum_level5_dark.svg create mode 100644 resources/images/hum_level5_light.svg create mode 100644 resources/images/hum_popup_close.svg create mode 100644 resources/images/humidity_list_background.png create mode 100644 resources/images/monitor_hms_new.svg create mode 100644 resources/profiles/BBL/filament/Bambu ABS-GF @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Bambu ABS-GF @BBL P1P.json create mode 100644 resources/profiles/BBL/filament/Bambu ABS-GF @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Bambu ABS-GF @base.json create mode 100644 resources/profiles/BBL/filament/Bambu ASA-Aero @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Bambu ASA-Aero @BBL P1P.json create mode 100644 resources/profiles/BBL/filament/Bambu ASA-Aero @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Bambu ASA-Aero @base.json create mode 100644 resources/profiles/BBL/filament/Bambu PA6-GF @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Bambu PA6-GF @BBL P1P.json create mode 100644 resources/profiles/BBL/filament/Bambu PA6-GF @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Bambu PA6-GF @base.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1 0.2 nozzle.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M 0.2 nozzle.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P 0.2 nozzle.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C 0.2 nozzle.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Bambu Support For PLA-PETG @base.json create mode 100644 resources/profiles/BBL/filament/Generic BVOH @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic BVOH @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic BVOH @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic BVOH @base.json create mode 100644 resources/profiles/BBL/filament/Generic EVA @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic EVA @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic EVA @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic EVA @base.json create mode 100644 resources/profiles/BBL/filament/Generic PCTG @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PCTG @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic PCTG @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PCTG @base.json create mode 100644 resources/profiles/BBL/filament/Generic PE @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PE @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic PE @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PE @base.json create mode 100644 resources/profiles/BBL/filament/Generic PE-CF @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PE-CF @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic PE-CF @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PE-CF @base.json create mode 100644 resources/profiles/BBL/filament/Generic PHA @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PHA @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic PHA @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PHA @base.json create mode 100644 resources/profiles/BBL/filament/Generic PP @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PP @BBL A1M.json create mode 100644 resources/profiles/BBL/filament/Generic PP @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PP @base.json create mode 100644 resources/profiles/BBL/filament/Generic PP-CF @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PP-CF @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PP-CF @base.json create mode 100644 resources/profiles/BBL/filament/Generic PP-GF @BBL A1.json create mode 100644 resources/profiles/BBL/filament/Generic PP-GF @BBL X1C.json create mode 100644 resources/profiles/BBL/filament/Generic PP-GF @base.json create mode 100644 resources/profiles/BBL/filament/fdm_filament_bvoh.json create mode 100644 resources/profiles/BBL/filament/fdm_filament_eva.json create mode 100644 resources/profiles/BBL/filament/fdm_filament_pe.json create mode 100644 resources/profiles/BBL/filament/fdm_filament_pha.json create mode 100644 resources/profiles/BBL/filament/fdm_filament_pp.json create mode 100644 resources/web/homepage2/css/online.css create mode 100644 resources/web/homepage2/css/recent.css delete mode 100644 src/libslic3r/Arachne/utils/VoronoiUtils.cpp delete mode 100644 src/libslic3r/Arachne/utils/VoronoiUtils.hpp create mode 100644 src/libslic3r/Geometry/Voronoi.cpp create mode 100644 src/libslic3r/Geometry/VoronoiUtils.cpp create mode 100644 src/libslic3r/Geometry/VoronoiUtils.hpp create mode 100644 src/libslic3r/ParameterUtils.cpp create mode 100644 src/libslic3r/ParameterUtils.hpp diff --git a/resources/images/fd_pattern_manual_device.png b/resources/images/fd_pattern_manual_device.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d5b90bc1c256264a4f6978751cd6ade26a0237 GIT binary patch literal 239574 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%0D>(dZ#fWu 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�`;Q?s82dDv3041*h&y!ASsC@=9 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%0A1n1;M={? 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�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 z zT)k{B%osq+mpFaqw3IEa`QWe@VJsc^8YoWUGI66=OkpeA>eD$x0VFf717zUi9=;hJ z0nBQUu#>RAp5KoNgDqJ^G0Ow3yh34kfVXZ`{pVBmUyI5zJ~!p@j*9P#`}VjB4s0Scfe8(UA^RwfIE zBo2~tP(ayPZ2jZFFLOTM+X^Q%3FG0OkX^;WTEJ0#01oN7&@bRjbP!*B^jJ*wVJQ8JFkj6Mzi3YKvjO zRfv@c0sV%B1Dq{eP763KF9t}*w8PP^15d)1P6^A70td92=uC0X!PGpX>K(ZNLO@?z z?NR5Vz^F{DwVgC=Q-%yR5@$8HP+S#)O-w3q|7w>UOlT8YE{aw_DgBg269H zf9L>zVNbsRv1hMXxgzbFU0`gi0HK8(>=8r6%;^fCEw@c@2pGzUEs29Y%VZC30ZJ?p zo@f*B6_Nuueb>C2B2^>6*vMX zh5L+>)@pPFYQiL)G%BpYu>wxevc-r0fjI+|`FBQ^O%GHx9ynkmzUQd6oyWDcND`26 zO~+Uw7-2@tL^I0tP;uZ@AQ499erK=R>cjs4XaEcVWXc!-EY$#v3!nnF-i+#6OcOZj zI3WQB(JXB+fESaM!yH>y18l-I_)ygkU}Mg% zIUy{o*AJMZF;E{s$PX&;mtbMBOa_d0?!x(PUS>}|E6N8PfD7h9faeFatS&P(jGw?; z%E!DVXxPf?wHw;{jay2X`OYu~drUDefCvPbbQJzqf9*E{0$p(S)>BU}5MqA$9XRqC zVZZ=!v*R^$KR^-;?zsSo;s86(Ap8^^SOeoyx`1HM_hkV^8BAU#x>d~;E7wHmZN0Q& zJ-YzH{hp%?rZ)FOFGnDy#oDxw*(f9j(77HUKddBdUeAb zff!IxzWy<}=m%M)v0C9qy>`@sPwJrU<;P52fRlxjUL8GO-B~u$^8sH#2k6xScnRy8 zGiQEuCbF6SJp0`9@|y|NwmJLM`TG_J6uM9(Ks7I*$YKyvX*?@NHf_i3$UO3+eDYWA z3m5}L{k(47#%d!5sK1msefq4bCydZ<}8i}Rb4bL69BCAvQ;gv1N*!4f!x3HD-{mCvVWbBDjV;>bR%0iXql zlY-U)q$w|R*&bv7<{dynT;{a+Ld=cwD#R@3q1}Bp;KwXx=A|+i41i?*xySXs7ne99 zrgA@rNyTgikXFnFgo!e(D71Un^2&nh8iBp(2s49023|U#XCj(eu&pw^(|JGu3+o&9 z*)z)lsB3|xYjm`M*ADCr3-deQA|E8Ss?!aa#R<&V^EkYL77%njPc2$!Mp(1T@OS90>wfLoZv97sob+i(zV)?|>?RG#grlQwBdypNxrv-em|@AJ>^x zPl}+3fy0aWR*A+ubM@1*N<`6KdIwu_#$pTmygr9if&+3Ny6jaP^w7 z()1yLr@+iZePX;Z7K+DLO0lpxECTEF9FBH?!vDmK#=uNo6cW1wqI_QN0}7OqGTQEi z;bI;XQQZK}&^&`F>{%uo!N^v^g`ohQE!ON&F(j2WDl_1^}uLrS)#Y1|Vco zxRKRaE&`ya?aHNl0KMn4yX^8S^7q67S>O9ke*mdos8#7`>V>gl*qET_O^!K#={qhj zrfEXZZ%q5ad8q?3WP&i3CN)+8zawiv{Gz^B{+Ltv(7WU%y#f6i0_9yW%IB9p_uTU% zCu3{UWv0_}zp-YPE?-^?gXFt>qmgwojl2k>p?7rC_2im-Gmq(geV;O60X+rYMM~z+ z53^ofSj1*n_RQHc(umF!9XzxP(Xsk`{Bhl) zP6241p%1T`oqL&ef4X$+b*TAmaP-GcY^T@n#f*G%)wuNx z=AA=+>5Ao5FD8VTH9#p*su|RvtCQ~lvg>L_Wl{_{u?^0|g*juY$_Mllrv}VZzEy4+ zb9yWq!=V&_z~Y9_l$wu;`D1sDSTtrX(-|uQK*BjFC)ONfvJOBj6z4;2aJK=(wL8cgz{n`UcRTe%t`&NE}kuX2>@af zK+iKUI;Lvhv>BTN27I9uj~|vo>4TfplFvP9fPHShMb8ZO8fC38g~gGjH8%ax@p|)Suc|{6Ue%-GXdCi z3!7unNON}H1?LxW5M59%u8<{Qh^!zebc=3lQ|VoP>se0#zD(oPnI5~xHd|z+w(Uk| zJRknRCl)90W7WbU_+(sr>k@KT@-y14(noe?%uq51jBr+LcwsXqoY1F|G^}60rp>hf zcS1K?^vq(F^k5HAC}!v3fX`8F^V| zYP(%r&sV}EcMX4_Iuw}YUeESDp|-+2Du6vH&s`EgwLjeV$`GT)5pN=3equKmP~9J8 zu$qmDVQ|hFeB`Pf@6T^oqu8KCWtouk>4;88~-U(kL8J#}iVx7Gfx|SrbNQHU=bPiD@OKq+7yyEMrG zdj0BtatGYGpFH1pov*L6x>z^1_IZwRVP4nR6`NOHtg?)q@Gy%%-6Sxj7`JEgEgF-> zOO~de=4R~p7&|M>8h}U-z-Pkrolu(6q2LK!rStT?{OBWx7l^J~zwT|~CMuy@l~!M8 zIF)=vhhYpdhO`019#Q+rI!C||P60veuo!T@W0k_PK1^d_G8Kd!1~NL8w2(3=Y;9_o z#`J*GP+*Y?KzRkb2B>+M!n}MBbpaFRsM6k1Q@{Be59uTLglm!$N1ynVEqa z*;cHKg6FyR6I+16B*zE10fSEMOpq=qgAO&zh(#KgSwu(#rD2vXOF1VE?gF;U%ueS4 z1t5i`^n8pMADsd_MT%&zVX0ww{S0+Hi@Bpc2S)2imwfdF&46>OI7&Dob zdqTf%0jUY#a6y4Z*T#Wu zc*bWy`gv%^lwwoHcfIR9rNI6AJJAqW%XaJ-1N~(eP?wbVgCF{Z^rabdPGwc`Y(6fF z3&4f1jcK?nAalWmm(+b&TW=<3dbvh?B9=uNDXp!47@5Ti{w#`Qfq=swa9GWyXcb(Y z`nVQ@nrfF%%&vJ0=2e&$0p7HAOKo*C*3-hIfi3?S;4r@S>GGSZul}+(nV-!hpg*w0 z-rig*!6pJGIRD!f?~|w)NkjUcYZtL%(Loxpwq3c2ki1ptg=l1^bNo_VKCwK8NlM2 zsBsM7nczH!Y*B6tD)K+_Yl>WO4`vFijhV5r0JLh=+L{owtrl|v+;nB~WQ!;!&;RQy z1%mp~-xhbY8<3i`_&^btz8OCzvK8)bMZU{+RpD_VR!rR9LLy>O#47ED5y*+Wp=8l- z7FhHJhD!(BTMMSS*E?V&7tT@XWVL^>LklOcp)ewK>aBSIL8J{a6K>-jfl~+g)kkvElu~e(i7^AIzClARC5);i#=328cQ_>7FWA@CNL3%znem2=fYEdNg z980vKW#hN+fQI^dF3QaZ$8RBNr!sWB844T29#QlPs|f%xQQdELtM?2Bh9}{zXA2+T z!vs_{aH%6Obe->&s~o=Anjq5VVtttm^o>O(gX}ZV9~;5Z9_3)sfLEJqwo}ji?b=!# z%JciBUxf*|W>Wgz$~Lf_8o(f|#VE>O)cOAk+#<+KCuSR;6|=vTF)YXmC{U;!AAR|d zI!4!XD^w=!QU*b|T{<`4V|17olN7_UMUjb#eNmWGPd_7L-DNkSP`2-#7BCwY-ejvUkTdDh?v8ukhB04`tzT*?PN%H`)XtD*gV7YkT}ocnA) zs@3wC3z$qr*oOrJH0AL`1U ziGbgbvU4j8N%`7mA`!EQA!2}D{IlE$cHD?Ttb`r8PJaTlVpRoVgWA#npFZZk;1lc? z_J&tXqDCF(%mUTp1cLTmCk{>4a{tAK{vr*$uD(LWqifs(`$8 zfD9XyKo(e{u1sq{T7sEMLTMGTisf(Dd+$Zj17x8v0w~83kbneUu&C>c^ z`8u^`lXL3;5EW62Jf<5aS0V9RBvA zoL1ri9cBsi1Z-E^)H&A!bWCcsEW;_oerG1NAZ1Ef`)tDm^c9CZ@L+Cr;Z)2X3fQeS z6Kslz`2ZHojezSzN@D>4W3pWgW5GHs$S}|NxxBmAZvd83dSQNZYe8UW6j>%E6P3Og5mxOQjIjCGnQ4-JTVCbQ0hgVkOjh@E@a4xpe; zfRk@bdlrPLEL^;#+zP(;Y^kBKM)I3o=FH15IRM6F1q-V^5KfRbiKOp4KvZ1 z#rj2DB%m}oDOX=Ge@$>0qk0sZx25!LM(RH7-sA;T0h>B#i{Fh|-vC;-=*G`)QL78f zVxk+1eyJ01(N^ZSMHo7RvC>Cm$YPg?A0be#Ns!(E!&za4eE4+6_E;>@HAoK~g+;6p z6DqJ{aUu=$uuSS$74*<=bQ%7P4oS0~;aY$5A<|*7itm5_`+tH%eJqxUL*y^qv}wan z08FO?HY?41UOEm1wFm>uddO@r09=R6U4BCBPACrw%LJzE%G5v)_1TM=t}H%DtWp_P zxZS4%Tr+)!BM_}NiM|&CV&$`2$mx|cE^SbTd%RF+ev6uoGAIDNg1G}`%vYTUJeZyU zy>BK3Ac27ZGAzw!6dxlq^YBxc>6lm8+k%A)3Vg6ZpjR_k+N@k@iORgq^Z7LvEm=~G z+2{ESqi_)f<#-VUV61-FsCoc5d$I|I!SA23m=cD|M~UIOe)QXb4 zMCFywGtZ!yOgf6;fF;UkApnrrW~d(k0iT||rt{~gE&(k{N@@L8{S~2O-ua&J_u?9r z)ytkji7+F-yU(++5-iJ(2dqq;03eeZ+oB+pnSYF5P>7H^N-@Qxr-(oov%;t-tCIqI z;8%(m0oTV;hZQ?3-<`er9lJ3Ba0PJx06{Cd7V&PE$r}p$~sMMDCfnOUY6^+ zJbW0~>b2|ZfG%dCegGCd*2&xjWS(ykt9)&dw|BqisscU0h@~-8fe;4QWzyjj>tX?= z(ZWcNJ6_=O(CU*}0Yql7zR`ALR_r_N@?y@Lv^$r9!_bWW9CfQgo zX$x!58UdC%Br-8L?ctYHukt-denm)_;B7&5fYh+)tx3;!CVIMpv~cJ2Lg#=t9q`$L zjm+9Wll5Q`()S1rd_o#nfP9t$yt(lFjxn-onafvPaYf-t0U}m6K=?)~C&UKI+L2-Z z;*_ZdEKDkuVOqPkmq{DAoqV!rZzu0zY~5Bqg}UCgGT-=pa=-ylGR=Dc=wPTZVSm$S zObr`dRv^YqcaATBWkQ=tfTMF>)Ja3UAU}|U@KTmp6mragWE7(^aM&o2LXUNdg$hR% zm@VvO2KF;%%&cbu8-P&eY}y9oDlj_tmeS@sV8?_8R&`841R3zC8%4$R44jTHliQ?` zexy{u7bRDw=bE|r3IQGlX~vX@!i)@*3>?3T0WLpb`pk|Tr^o?BOi>xkJc42yqk8eL zcs}qpHa?dLGO`QK?T(h@D33WGWd#oE*Ui?FaY(Y-Wjxlml$>B=GW8@))vJd7jt>h5}_rXKMX)rd|Lp)^G=9jyXNvMVyXwY zUDG9B#cVo1pt67iKvOp$MxlYH&>Q|NtjVGQ)@A}^4$7%$VTW03Y_%U72B;PQEGU=& zn9NLT4Aum&akGP|78huBJ~|WF#7u-U3htb*uxP6=9Ou{QAMN$(0=v8Y;oKC;tBE4*)qYIa z_+h*i>U5%L1vwPET!*964@`Kg!xr7N%Yuu(<^o|^7`K{8BI}qmKy{7&dC+ojfTPXu#T}0X%yaAsMzNKz_*{B0SYE5n zuAe<`PWkVV2w8AkPanAGkQw?%Cro-QUf+8zFyudkS2E%-p&cvGr<67(v)Dkuf+=Ex z*dBnvAZG-$B$4fblHY{sIG1_i#9pc}=CGBV2xrilax=dLegisS*$eviypDBJ3g-Br zTEqdE-755eLUKS_reqXVPDSA68Vxh^0&nKLdU@828Pkgr1H(F3C5?4I0Cl|qatuHz zeLAp!BlW}xF+0iwY&!p&m@cc+d~nBChjZo^hy~c}3_;m@peNv)&@-{IxDwX4KQjvf zlzN#7fhJQKFp7HuDH#8hGjS=BaE%lDb>|=J0}KS%VR}|HDLiHapa2g*n>fkj zHop8xl*{59#gR>hZ?EFi@@(Z;{q@dlc7LU>iV5mIeI{Xtoi4yhKl@I5Js$vShkp0H zx+@nTxCR^O6QB`V!=!c%U)aV?TdF+l2$;BMUKACW3&sY9K)e#WroQe4EOX}p4?edp zOAxjN%mko2s7jrfr2KJyFUB1fWwFL$2LQE$L!Xfop-7dLCw1v$bVdb}Tiv!o&81OC z%4Ur04HkA}f>9SMx5f?gQGd?^=6sMQD8b^wx3Em+ZJ$2f0*c9vd2Hn!+cYWas{+zo zt34fvccCdW(nlRYa~H*Gh@4yC(oSuV8JyhcFKrWeT|v@mlSLO38TU*Vp42ZaenRP= zIU=W)-d2-AendL7VRg8_G;KV}50&N6b>U}P|v z0A?BN&`e~J#B9W8g}NIoC;tOMpaW#P70+%F$qZ!Rd~d)o3ycro0i_y{w2$vg{FPY@ zJ@m!t|JiSdIJi4=@2@ zmtJ~#wL#s5@i03v;rCthQ#Fx!KDo1?heZQ({lLVPsCW5_j@=p;=Q5jsik+t%{e$J% zxdhOGt1)9y0Dj35^ktXv=j1jwCa%57e6GNdxqrzemsY*WxUtoD67|-R3F&LVRf{;7 zZ-B9DAHA^X7#WPru?WN&0%l|D2-8zjU;S8di+MJ=2P(#EQTiI=?27eXG~4t^NG~l8XxQ zpnu2&>l6X9AR`>dIzn$vg!Slm;H?dH$kc!Ve1^J_E7xzp7vK>l6;%iK+EeX& zWlQk`+yDi09-u2{cm!qB#*LxqlAo&6kTO}#D*krA>=qLzbb**yCPC~03;^`v8`S9z z4DW!e+l-Di^3|EOICz0w=YY1_1`Il21gu!6=Xp*o(BwWF&oNNHD_4QqdfBB_Cf9?&bEZ2`1d=8ZKnnnYI2Nl<0H(>c!mu(<uC?KmYvHBhQXrSz!5% m-}sFJME5&aW!$)N?f(aou$F{$t4)vq0000 + + + + diff --git a/resources/images/hum_level1_light.svg b/resources/images/hum_level1_light.svg new file mode 100644 index 0000000000..37870888f9 --- /dev/null +++ b/resources/images/hum_level1_light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level2_dark.svg b/resources/images/hum_level2_dark.svg new file mode 100644 index 0000000000..66951ad474 --- /dev/null +++ b/resources/images/hum_level2_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level2_light.svg b/resources/images/hum_level2_light.svg new file mode 100644 index 0000000000..4d62440ae4 --- /dev/null +++ b/resources/images/hum_level2_light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level3_dark.svg b/resources/images/hum_level3_dark.svg new file mode 100644 index 0000000000..be9f85965d --- /dev/null +++ b/resources/images/hum_level3_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level3_light.svg b/resources/images/hum_level3_light.svg new file mode 100644 index 0000000000..2c0334ee35 --- /dev/null +++ b/resources/images/hum_level3_light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level4_dark.svg b/resources/images/hum_level4_dark.svg new file mode 100644 index 0000000000..4dc749ccb9 --- /dev/null +++ b/resources/images/hum_level4_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level4_light.svg b/resources/images/hum_level4_light.svg new file mode 100644 index 0000000000..299c1506c8 --- /dev/null +++ b/resources/images/hum_level4_light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level5_dark.svg b/resources/images/hum_level5_dark.svg new file mode 100644 index 0000000000..d7ef458e09 --- /dev/null +++ b/resources/images/hum_level5_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_level5_light.svg b/resources/images/hum_level5_light.svg new file mode 100644 index 0000000000..4121832f98 --- /dev/null +++ b/resources/images/hum_level5_light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/images/hum_popup_close.svg b/resources/images/hum_popup_close.svg new file mode 100644 index 0000000000..cf48700ee1 --- /dev/null +++ b/resources/images/hum_popup_close.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/images/humidity_list_background.png b/resources/images/humidity_list_background.png new file mode 100644 index 0000000000000000000000000000000000000000..d482fb1b329fc69ce4b5e8c2e4efaae59a982043 GIT binary patch literal 44573 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 vxP|9miH84+WAof`a4`1f>Q<$j6I}q{sA=jqK3R + + diff --git a/resources/printers/N1.json b/resources/printers/N1.json index 85da862315..8bcd035a5e 100644 --- a/resources/printers/N1.json +++ b/resources/printers/N1.json @@ -28,7 +28,6 @@ "support_print_all":false, "support_print_without_sd":false, "support_flow_calibration":true, - "support_build_plate_marker_detect":false, "support_lidar_calibration":false, "support_ai_monitoring":false, "support_first_layer_inspect":false, diff --git a/resources/printers/N2S.json b/resources/printers/N2S.json index e287cd1fab..2857bb17eb 100644 --- a/resources/printers/N2S.json +++ b/resources/printers/N2S.json @@ -28,7 +28,6 @@ "support_print_all":false, "support_print_without_sd":false, "support_flow_calibration":true, - "support_build_plate_marker_detect":false, "support_lidar_calibration":false, "support_ai_monitoring":false, "support_first_layer_inspect":false, diff --git a/resources/profiles/BBL.json b/resources/profiles/BBL.json index 4c70999b14..2afe0897df 100644 --- a/resources/profiles/BBL.json +++ b/resources/profiles/BBL.json @@ -1,7 +1,7 @@ { "name": "Bambulab", "url": "http://www.bambulab.com/Parameters/vendor/BBL.json", - "version": "01.08.00.25", + "version": "01.09.00.04", "force_update": "0", "description": "the initial version of BBL configurations", "machine_model_list": [ @@ -649,6 +649,26 @@ "name": "fdm_filament_ppa", "sub_path": "filament/fdm_filament_ppa.json" }, + { + "name": "fdm_filament_pe", + "sub_path": "filament/fdm_filament_pe.json" + }, + { + "name": "fdm_filament_pp", + "sub_path": "filament/fdm_filament_pp.json" + }, + { + "name": "fdm_filament_eva", + "sub_path": "filament/fdm_filament_eva.json" + }, + { + "name": "fdm_filament_pha", + "sub_path": "filament/fdm_filament_pha.json" + }, + { + "name": "fdm_filament_bvoh", + "sub_path": "filament/fdm_filament_bvoh.json" + }, { "name": "Bambu PLA Matte @base", "sub_path": "filament/Bambu PLA Matte @base.json" @@ -745,6 +765,10 @@ "name": "Bambu PLA Galaxy @base", "sub_path": "filament/Bambu PLA Galaxy @base.json" }, + { + "name": "Bambu Support For PLA/PETG @base", + "sub_path": "filament/Bambu Support For PLA-PETG @base.json" + }, { "name": "Bambu TPU 95A @base", "sub_path": "filament/Bambu TPU 95A @base.json" @@ -789,6 +813,10 @@ "name": "Bambu PETG Translucent @base", "sub_path": "filament/Bambu PETG Translucent @base.json" }, + { + "name": "Generic PCTG @base", + "sub_path": "filament/Generic PCTG @base.json" + }, { "name": "Bambu ABS @base", "sub_path": "filament/Bambu ABS @base.json" @@ -801,6 +829,10 @@ "name": "PolyLite ABS @base", "sub_path": "filament/PolyLite ABS @base.json" }, + { + "name": "Bambu ABS-GF @base", + "sub_path": "filament/Bambu ABS-GF @base.json" + }, { "name": "Bambu PC @base", "sub_path": "filament/Bambu PC @base.json" @@ -821,6 +853,10 @@ "name": "PolyLite ASA @base", "sub_path": "filament/PolyLite ASA @base.json" }, + { + "name": "Bambu ASA-Aero @base", + "sub_path": "filament/Bambu ASA-Aero @base.json" + }, { "name": "Generic PVA @base", "sub_path": "filament/Generic PVA @base.json" @@ -865,6 +901,10 @@ "name": "Bambu PA6-CF @base", "sub_path": "filament/Bambu PA6-CF @base.json" }, + { + "name": "Bambu PA6-GF @base", + "sub_path": "filament/Bambu PA6-GF @base.json" + }, { "name": "Generic HIPS @base", "sub_path": "filament/Generic HIPS @base.json" @@ -885,6 +925,38 @@ "name": "Generic PPA-GF @base", "sub_path": "filament/Generic PPA-GF @base.json" }, + { + "name": "Generic PE @base", + "sub_path": "filament/Generic PE @base.json" + }, + { + "name": "Generic PE-CF @base", + "sub_path": "filament/Generic PE-CF @base.json" + }, + { + "name": "Generic PP @base", + "sub_path": "filament/Generic PP @base.json" + }, + { + "name": "Generic PP-CF @base", + "sub_path": "filament/Generic PP-CF @base.json" + }, + { + "name": "Generic PP-GF @base", + "sub_path": "filament/Generic PP-GF @base.json" + }, + { + "name": "Generic EVA @base", + "sub_path": "filament/Generic EVA @base.json" + }, + { + "name": "Generic PHA @base", + "sub_path": "filament/Generic PHA @base.json" + }, + { + "name": "Generic BVOH @base", + "sub_path": "filament/Generic BVOH @base.json" + }, { "name": "Bambu PLA Matte @BBL X1C", "sub_path": "filament/Bambu PLA Matte @BBL X1C.json" @@ -1553,6 +1625,38 @@ "name": "Bambu PLA Galaxy @BBL A1M 0.2 nozzle", "sub_path": "filament/Bambu PLA Galaxy @BBL A1M 0.2 nozzle.json" }, + { + "name": "Bambu Support For PLA/PETG @BBL X1C", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL X1C.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL X1C 0.2 nozzle", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL X1C 0.2 nozzle.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL P1P", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL P1P.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL P1P 0.2 nozzle", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL P1P 0.2 nozzle.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL A1M", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL A1M.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL A1M 0.2 nozzle", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL A1M 0.2 nozzle.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL A1", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL A1.json" + }, + { + "name": "Bambu Support For PLA/PETG @BBL A1 0.2 nozzle", + "sub_path": "filament/Bambu Support For PLA-PETG @BBL A1 0.2 nozzle.json" + }, { "name": "Bambu TPU 95A @BBL X1C", "sub_path": "filament/Bambu TPU 95A @BBL X1C.json" @@ -1761,6 +1865,18 @@ "name": "Bambu PETG Translucent @BBL A1", "sub_path": "filament/Bambu PETG Translucent @BBL A1.json" }, + { + "name": "Generic PCTG @BBL X1C", + "sub_path": "filament/Generic PCTG @BBL X1C.json" + }, + { + "name": "Generic PCTG @BBL A1", + "sub_path": "filament/Generic PCTG @BBL A1.json" + }, + { + "name": "Generic PCTG @BBL A1M", + "sub_path": "filament/Generic PCTG @BBL A1M.json" + }, { "name": "Bambu ABS @BBL X1C", "sub_path": "filament/Bambu ABS @BBL X1C.json" @@ -1829,6 +1945,18 @@ "name": "PolyLite ABS @BBL A1 0.2 nozzle", "sub_path": "filament/PolyLite ABS @BBL A1 0.2 nozzle.json" }, + { + "name": "Bambu ABS-GF @BBL X1C", + "sub_path": "filament/Bambu ABS-GF @BBL X1C.json" + }, + { + "name": "Bambu ABS-GF @BBL P1P", + "sub_path": "filament/Bambu ABS-GF @BBL P1P.json" + }, + { + "name": "Bambu ABS-GF @BBL A1", + "sub_path": "filament/Bambu ABS-GF @BBL A1.json" + }, { "name": "Bambu PC @BBL X1C", "sub_path": "filament/Bambu PC @BBL X1C.json" @@ -1957,6 +2085,18 @@ "name": "PolyLite ASA @BBL A1", "sub_path": "filament/PolyLite ASA @BBL A1.json" }, + { + "name": "Bambu ASA-Aero @BBL X1C", + "sub_path": "filament/Bambu ASA-Aero @BBL X1C.json" + }, + { + "name": "Bambu ASA-Aero @BBL P1P", + "sub_path": "filament/Bambu ASA-Aero @BBL P1P.json" + }, + { + "name": "Bambu ASA-Aero @BBL A1", + "sub_path": "filament/Bambu ASA-Aero @BBL A1.json" + }, { "name": "Generic PVA @0.2 nozzle", "sub_path": "filament/Generic PVA @0.2 nozzle.json" @@ -2093,6 +2233,18 @@ "name": "Bambu PA6-CF @BBL A1", "sub_path": "filament/Bambu PA6-CF @BBL A1.json" }, + { + "name": "Bambu PA6-GF @BBL X1C", + "sub_path": "filament/Bambu PA6-GF @BBL X1C.json" + }, + { + "name": "Bambu PA6-GF @BBL P1P", + "sub_path": "filament/Bambu PA6-GF @BBL P1P.json" + }, + { + "name": "Bambu PA6-GF @BBL A1", + "sub_path": "filament/Bambu PA6-GF @BBL A1.json" + }, { "name": "Generic HIPS @BBL X1C", "sub_path": "filament/Generic HIPS @BBL X1C.json" @@ -2141,6 +2293,94 @@ "name": "Generic PPA-GF @BBL X1E", "sub_path": "filament/Generic PPA-GF @BBL X1E.json" }, + { + "name": "Generic PE @BBL X1C", + "sub_path": "filament/Generic PE @BBL X1C.json" + }, + { + "name": "Generic PE @BBL A1", + "sub_path": "filament/Generic PE @BBL A1.json" + }, + { + "name": "Generic PE @BBL A1M", + "sub_path": "filament/Generic PE @BBL A1M.json" + }, + { + "name": "Generic PE-CF @BBL X1C", + "sub_path": "filament/Generic PE-CF @BBL X1C.json" + }, + { + "name": "Generic PE-CF @BBL A1", + "sub_path": "filament/Generic PE-CF @BBL A1.json" + }, + { + "name": "Generic PE-CF @BBL A1M", + "sub_path": "filament/Generic PE-CF @BBL A1M.json" + }, + { + "name": "Generic PP @BBL X1C", + "sub_path": "filament/Generic PP @BBL X1C.json" + }, + { + "name": "Generic PP @BBL A1", + "sub_path": "filament/Generic PP @BBL A1.json" + }, + { + "name": "Generic PP @BBL A1M", + "sub_path": "filament/Generic PP @BBL A1M.json" + }, + { + "name": "Generic PP-CF @BBL X1C", + "sub_path": "filament/Generic PP-CF @BBL X1C.json" + }, + { + "name": "Generic PP-CF @BBL A1", + "sub_path": "filament/Generic PP-CF @BBL A1.json" + }, + { + "name": "Generic PP-GF @BBL X1C", + "sub_path": "filament/Generic PP-GF @BBL X1C.json" + }, + { + "name": "Generic PP-GF @BBL A1", + "sub_path": "filament/Generic PP-GF @BBL A1.json" + }, + { + "name": "Generic EVA @BBL X1C", + "sub_path": "filament/Generic EVA @BBL X1C.json" + }, + { + "name": "Generic EVA @BBL A1", + "sub_path": "filament/Generic EVA @BBL A1.json" + }, + { + "name": "Generic EVA @BBL A1M", + "sub_path": "filament/Generic EVA @BBL A1M.json" + }, + { + "name": "Generic PHA @BBL X1C", + "sub_path": "filament/Generic PHA @BBL X1C.json" + }, + { + "name": "Generic PHA @BBL A1M", + "sub_path": "filament/Generic PHA @BBL A1M.json" + }, + { + "name": "Generic PHA @BBL A1", + "sub_path": "filament/Generic PHA @BBL A1.json" + }, + { + "name": "Generic BVOH @BBL X1C", + "sub_path": "filament/Generic BVOH @BBL X1C.json" + }, + { + "name": "Generic BVOH @BBL A1M", + "sub_path": "filament/Generic BVOH @BBL A1M.json" + }, + { + "name": "Generic BVOH @BBL A1", + "sub_path": "filament/Generic BVOH @BBL A1.json" + }, { "name": "PolyTerra PLA @BBL X1C 0.2 nozzle", "sub_path": "filament/PolyTerra PLA @BBL X1C 0.2 nozzle.json" diff --git a/resources/profiles/BBL/filament/Bambu ABS @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu ABS @BBL A1 0.2 nozzle.json index 352292b1ea..413d8ce795 100644 --- a/resources/profiles/BBL/filament/Bambu ABS @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ABS @BBL A1 0.2 nozzle.json @@ -20,6 +20,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/Bambu ABS @BBL A1.json b/resources/profiles/BBL/filament/Bambu ABS @BBL A1.json index 3358a7fc74..f85009c07b 100644 --- a/resources/profiles/BBL/filament/Bambu ABS @BBL A1.json +++ b/resources/profiles/BBL/filament/Bambu ABS @BBL A1.json @@ -20,6 +20,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.2 nozzle.json index 3949e18511..f21efe7f80 100644 --- a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.2 nozzle.json @@ -5,9 +5,15 @@ "from": "system", "setting_id": "GFSB00_00", "instantiation": "true", + "fan_max_speed": [ + "60" + ], "filament_max_volumetric_speed": [ "2" ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", "Bambu Lab X1 0.2 nozzle", diff --git a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.8 nozzle.json index 10bfd2565a..6145a910b6 100644 --- a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C 0.8 nozzle.json @@ -5,12 +5,18 @@ "from": "system", "setting_id": "GFSB00_01", "instantiation": "true", + "fan_max_speed": [ + "60" + ], "filament_max_volumetric_speed": [ "18" ], "nozzle_temperature": [ "260" ], + "slow_down_layer_time": [ + "12" + ], "slow_down_min_speed": [ "10" ], diff --git a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C.json b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C.json index 80f4f7c920..88ad1a408f 100644 --- a/resources/profiles/BBL/filament/Bambu ABS @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu ABS @BBL X1C.json @@ -5,9 +5,15 @@ "from": "system", "setting_id": "GFSB00", "instantiation": "true", + "fan_max_speed": [ + "60" + ], "filament_max_volumetric_speed": [ "16" ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/filament/Bambu ABS-GF @BBL A1.json b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL A1.json new file mode 100644 index 0000000000..ff5f41cae7 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL A1.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Bambu ABS-GF @BBL A1", + "inherits": "Bambu ABS-GF @base", + "from": "system", + "setting_id": "GFSB50_02", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ABS-GF @BBL P1P.json b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL P1P.json new file mode 100644 index 0000000000..37acd12522 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL P1P.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Bambu ABS-GF @BBL P1P", + "inherits": "Bambu ABS-GF @base", + "from": "system", + "setting_id": "GFSB50_01", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.4 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ABS-GF @BBL X1C.json b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL X1C.json new file mode 100644 index 0000000000..89916b17b3 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ABS-GF @BBL X1C.json @@ -0,0 +1,22 @@ +{ + "type": "filament", + "name": "Bambu ABS-GF @BBL X1C", + "inherits": "Bambu ABS-GF @base", + "from": "system", + "setting_id": "GFSB50_00", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ABS-GF @base.json b/resources/profiles/BBL/filament/Bambu ABS-GF @base.json new file mode 100644 index 0000000000..777cf85080 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ABS-GF @base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Bambu ABS-GF @base", + "inherits": "fdm_filament_abs", + "from": "system", + "filament_id": "GFB50", + "instantiation": "false", + "fan_cooling_layer_time": [ + "12" + ], + "fan_max_speed": [ + "30" + ], + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.08" + ], + "filament_type": [ + "ABS-GF" + ], + "filament_flow_ratio": [ + "0.95" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_vendor": [ + "Bambu Lab" + ], + "overhang_fan_speed": [ + "30" + ], + "overhang_fan_threshold": [ + "10%" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ASA @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/filament/Bambu ASA @BBL A1 0.6 nozzle.json index a934418ec1..916abbfbe3 100644 --- a/resources/profiles/BBL/filament/Bambu ASA @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ASA @BBL A1 0.6 nozzle.json @@ -5,9 +5,6 @@ "from": "system", "setting_id": "GFSB01_08", "instantiation": "true", - "fan_max_speed": [ - "90" - ], "fan_min_speed": [ "25" ], diff --git a/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.2 nozzle.json index abaa62c35e..90b80ac8dc 100644 --- a/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.2 nozzle.json @@ -5,9 +5,6 @@ "from": "system", "setting_id": "GFSB01_03", "instantiation": "true", - "fan_max_speed": [ - "80" - ], "filament_max_volumetric_speed": [ "2" ], diff --git a/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.6 nozzle.json b/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.6 nozzle.json index e98e02789d..5e6a6788c3 100644 --- a/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.6 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu ASA @BBL X1 0.6 nozzle.json @@ -5,9 +5,6 @@ "from": "system", "setting_id": "GFSB01_04", "instantiation": "true", - "fan_max_speed": [ - "90" - ], "fan_min_speed": [ "25" ], diff --git a/resources/profiles/BBL/filament/Bambu ASA @BBL X1C.json b/resources/profiles/BBL/filament/Bambu ASA @BBL X1C.json index 5693a2c1d0..4c9c47f1a3 100644 --- a/resources/profiles/BBL/filament/Bambu ASA @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu ASA @BBL X1C.json @@ -8,9 +8,6 @@ "fan_min_speed": [ "25" ], - "fan_max_speed": [ - "90" - ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/filament/Bambu ASA @base.json b/resources/profiles/BBL/filament/Bambu ASA @base.json index 4eb57181d1..7ae30500d9 100644 --- a/resources/profiles/BBL/filament/Bambu ASA @base.json +++ b/resources/profiles/BBL/filament/Bambu ASA @base.json @@ -5,28 +5,31 @@ "from": "system", "filament_id": "GFB01", "instantiation": "false", - "filament_density": [ - "1.05" + "fan_max_speed": [ + "35" ], "filament_cost": [ "31.99" ], - "nozzle_temperature_initial_layer": [ - "270" - ], - "nozzle_temperature": [ - "270" + "filament_density": [ + "1.05" ], "filament_flow_ratio": [ "0.95" ], - "fan_max_speed": [ - "50" - ], "filament_max_volumetric_speed": [ "18" ], "filament_vendor": [ "Bambu Lab" + ], + "nozzle_temperature": [ + "270" + ], + "nozzle_temperature_initial_layer": [ + "270" + ], + "slow_down_layer_time": [ + "12" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL A1.json b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL A1.json new file mode 100644 index 0000000000..ceca584ce1 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL A1.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Bambu ASA-Aero @BBL A1", + "inherits": "Bambu ASA-Aero @base", + "from": "system", + "setting_id": "GFSB02_02", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL P1P.json b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL P1P.json new file mode 100644 index 0000000000..03be549c97 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL P1P.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Bambu ASA-Aero @BBL P1P", + "inherits": "Bambu ASA-Aero @base", + "from": "system", + "setting_id": "GFSB02_01", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL X1C.json b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL X1C.json new file mode 100644 index 0000000000..2a0eaaa792 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ASA-Aero @BBL X1C.json @@ -0,0 +1,22 @@ +{ + "type": "filament", + "name": "Bambu ASA-Aero @BBL X1C", + "inherits": "Bambu ASA-Aero @base", + "from": "system", + "setting_id": "GFSB02_00", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu ASA-Aero @base.json b/resources/profiles/BBL/filament/Bambu ASA-Aero @base.json new file mode 100644 index 0000000000..f469aeebc6 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu ASA-Aero @base.json @@ -0,0 +1,62 @@ +{ + "type": "filament", + "name": "Bambu ASA-Aero @base", + "inherits": "fdm_filament_asa", + "from": "system", + "filament_id": "GFB02", + "instantiation": "false", + "fan_cooling_layer_time": [ + "30" + ], + "fan_max_speed": [ + "50" + ], + "fan_min_speed": [ + "30" + ], + "filament_cost": [ + "49.99" + ], + "filament_density": [ + "0.99" + ], + "filament_flow_ratio": [ + "0.52" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_retract_before_wipe": [ + "nil" + ], + "filament_retraction_length": [ + "1.5" + ], + "filament_type": [ + "ASA-Aero" + ], + "filament_vendor": [ + "Bambu Lab" + ], + "filament_wipe_distance": [ + "5" + ], + "filament_z_hop_types": [ + "Normal Lift" + ], + "nozzle_temperature": [ + "270" + ], + "nozzle_temperature_initial_layer": [ + "270" + ], + "overhang_fan_speed": [ + "50" + ], + "reduce_fan_stop_start_freq": [ + "0" + ], + "slow_down_layer_time": [ + "5" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PA6-GF @BBL A1.json b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL A1.json new file mode 100644 index 0000000000..76b7da4332 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL A1.json @@ -0,0 +1,22 @@ +{ + "type": "filament", + "name": "Bambu PA6-GF @BBL A1", + "inherits": "Bambu PA6-GF @base", + "from": "system", + "setting_id": "GFSN08_02", + "instantiation": "true", + "filament_max_volumetric_speed": [ + "10.5" + ], + "nozzle_temperature": [ + "265" + ], + "nozzle_temperature_initial_layer": [ + "265" + ], + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PA6-GF @BBL P1P.json b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL P1P.json new file mode 100644 index 0000000000..d0ff9e318a --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL P1P.json @@ -0,0 +1,22 @@ +{ + "type": "filament", + "name": "Bambu PA6-GF @BBL P1P", + "inherits": "Bambu PA6-GF @base", + "from": "system", + "setting_id": "GFSN08_01", + "instantiation": "true", + "filament_max_volumetric_speed": [ + "10.5" + ], + "nozzle_temperature": [ + "265" + ], + "nozzle_temperature_initial_layer": [ + "265" + ], + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PA6-GF @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL X1C.json new file mode 100644 index 0000000000..cf166026aa --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu PA6-GF @BBL X1C.json @@ -0,0 +1,34 @@ +{ + "type": "filament", + "name": "Bambu PA6-GF @BBL X1C", + "inherits": "Bambu PA6-GF @base", + "from": "system", + "setting_id": "GFSN08_00", + "instantiation": "true", + "chamber_temperatures": [ + "60" + ], + "filament_max_volumetric_speed": [ + "10.5" + ], + "nozzle_temperature": [ + "265" + ], + "nozzle_temperature_initial_layer": [ + "265" + ], + "compatible_printers": [ + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PA6-GF @base.json b/resources/profiles/BBL/filament/Bambu PA6-GF @base.json new file mode 100644 index 0000000000..24a6fa15b0 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu PA6-GF @base.json @@ -0,0 +1,44 @@ +{ + "type": "filament", + "name": "Bambu PA6-GF @base", + "inherits": "fdm_filament_pa", + "from": "system", + "filament_id": "GFN08", + "instantiation": "false", + "fan_cooling_layer_time": [ + "5" + ], + "fan_max_speed": [ + "30" + ], + "fan_min_speed": [ + "10" + ], + "filament_cost": [ + "59.99" + ], + "filament_density": [ + "1.14" + ], + "filament_flow_ratio": [ + "0.96" + ], + "filament_type": [ + "PA-GF" + ], + "filament_vendor": [ + "Bambu Lab" + ], + "full_fan_speed_layer": [ + "2" + ], + "overhang_fan_speed": [ + "40" + ], + "overhang_fan_threshold": [ + "0%" + ], + "temperature_vitrification": [ + "180" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PC @BBL A1 0.2 nozzle.json index 3a65f1d44c..790ddb7c4a 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL A1 0.2 nozzle.json @@ -29,6 +29,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL A1.json b/resources/profiles/BBL/filament/Bambu PC @BBL A1.json index 5d291b7b7c..fa10655ee8 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL A1.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL A1.json @@ -23,6 +23,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.2 nozzle.json index 31d13f48e8..fd33b77786 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.2 nozzle.json @@ -5,12 +5,18 @@ "from": "system", "setting_id": "GFSC00_02", "instantiation": "true", + "fan_max_speed": [ + "40" + ], "filament_max_volumetric_speed": [ "1" ], "nozzle_temperature": [ "260" ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", "Bambu Lab X1 0.2 nozzle" diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.6 nozzle.json index 3b5399efa2..ec8d95d22f 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.6 nozzle.json @@ -5,9 +5,15 @@ "from": "system", "setting_id": "GFSC00_01", "instantiation": "true", + "fan_max_speed": [ + "40" + ], "nozzle_temperature": [ "260" ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", "Bambu Lab X1 0.6 nozzle" diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.8 nozzle.json index b1cc742c2c..6cd58cc061 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL X1C 0.8 nozzle.json @@ -5,9 +5,15 @@ "from": "system", "setting_id": "GFSC00_00", "instantiation": "true", + "fan_max_speed": [ + "40" + ], "nozzle_temperature": [ "260" ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", "Bambu Lab X1 0.8 nozzle" diff --git a/resources/profiles/BBL/filament/Bambu PC @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PC @BBL X1C.json index 7ee2131465..cccf6aad59 100644 --- a/resources/profiles/BBL/filament/Bambu PC @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PC @BBL X1C.json @@ -5,6 +5,12 @@ "from": "system", "setting_id": "GFSC00", "instantiation": "true", + "fan_max_speed": [ + "40" + ], + "slow_down_layer_time": [ + "12" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle" diff --git a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.2 nozzle.json index c7dd9923cd..24857fa2e0 100644 --- a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.2 nozzle.json @@ -8,6 +8,12 @@ "filament_max_volumetric_speed": [ "1" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", "Bambu Lab X1 0.2 nozzle", diff --git a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.8 nozzle.json index 0a24cb5a1a..73d7aab022 100644 --- a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C 0.8 nozzle.json @@ -11,6 +11,12 @@ "fan_min_speed": [ "20" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "filament_max_volumetric_speed": [ "16" ], diff --git a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C.json index d68745bb17..18b87c5879 100644 --- a/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PETG Basic @BBL X1C.json @@ -8,6 +8,12 @@ "filament_max_volumetric_speed": [ "13" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/filament/Bambu PLA Aero @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Aero @BBL X1C.json index f3160585a6..fd83a7dfdf 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Aero @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Aero @BBL X1C.json @@ -21,5 +21,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1.json b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1.json index 3a70c808a4..6f016020a4 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1.json +++ b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1.json @@ -8,6 +8,12 @@ "filament_max_volumetric_speed": [ "21" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "slow_down_layer_time": [ "8" ], diff --git a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.2 nozzle.json index ddaeb7a616..0ef0264d43 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.2 nozzle.json @@ -5,6 +5,12 @@ "from": "system", "setting_id": "GFSA00_00", "instantiation": "true", + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "filament_max_volumetric_speed": [ "2" ], @@ -13,5 +19,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.8 nozzle.json index d8d8307fc0..671e010328 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C 0.8 nozzle.json @@ -8,9 +8,18 @@ "filament_max_volumetric_speed": [ "21" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C.json index 2cb005d6f5..8619d452d7 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Basic @BBL X1C.json @@ -8,6 +8,12 @@ "filament_max_volumetric_speed": [ "21" ], + "filament_long_retractions_when_cut": [ + "1" + ], + "filament_retraction_distances_when_cut": [ + "18" + ], "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 Carbon 0.6 nozzle", @@ -15,5 +21,8 @@ "Bambu Lab P1S 0.6 nozzle", "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.2 nozzle.json index 68496df697..fb09d370f5 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.2 nozzle.json @@ -19,5 +19,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.8 nozzle.json index 3a18c1f6f0..029cc864be 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C 0.8 nozzle.json @@ -19,5 +19,8 @@ "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.8 nozzle", "Bambu Lab X1 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C.json index 608465d6d6..ff52a275ee 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Dynamic @BBL X1C.json @@ -23,5 +23,8 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.6 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.2 nozzle.json index 9251208bdf..7bb8e8f94b 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.2 nozzle.json @@ -13,5 +13,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.8 nozzle.json index b3e250b6eb..43457c192d 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C 0.8 nozzle.json @@ -10,5 +10,8 @@ "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.8 nozzle", "Bambu Lab X1 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C.json index cf3e399b37..d95ffa6a6d 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Galaxy @BBL X1C.json @@ -14,5 +14,8 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.6 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1C.json index 115adb144a..5d0c2705a7 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1C.json @@ -12,5 +12,8 @@ "Bambu Lab P1S 0.8 nozzle", "Bambu Lab P1S 0.6 nozzle", "Bambu Lab P1S 0.4 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1E.json b/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1E.json index 51137bdeec..30c339132c 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1E.json +++ b/resources/profiles/BBL/filament/Bambu PLA Glow @BBL X1E.json @@ -9,5 +9,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Impact @base.json b/resources/profiles/BBL/filament/Bambu PLA Impact @base.json index 7cdc6f3e42..029a5f66a3 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Impact @base.json +++ b/resources/profiles/BBL/filament/Bambu PLA Impact @base.json @@ -5,13 +5,16 @@ "from": "system", "filament_id": "GFA03", "instantiation": "false", - "filament_vendor": [ - "Bambu Lab" - ], "filament_cost": [ "25.4" ], "filament_flow_ratio": [ "0.95" + ], + "filament_vendor": [ + "Bambu Lab" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Marble @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Marble @BBL X1C.json index 4199fd943d..29592f9b4f 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Marble @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Marble @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1.json b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1.json index 7721eacbc8..c0b3df5555 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1.json +++ b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1.json @@ -15,5 +15,8 @@ "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.6 nozzle", "Bambu Lab X1 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.2 nozzle.json index 824e96a5e3..04b51f8104 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.2 nozzle.json @@ -13,5 +13,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.8 nozzle.json index 7e2d1f4fc9..fc0962cd0e 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C 0.8 nozzle.json @@ -12,5 +12,8 @@ "Bambu Lab X1 Carbon 0.8 nozzle", "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C.json index a7e1e76634..0987393ec6 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Matte @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab P1S 0.6 nozzle", "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C 0.2 nozzle.json index 7ed6ab8f3e..8a1934d52a 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C 0.2 nozzle.json @@ -13,5 +13,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C.json index 91995ef069..81e5b51d60 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Metal @BBL X1C.json @@ -18,5 +18,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C 0.2 nozzle.json index 85c560fcdb..31478a9988 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C 0.2 nozzle.json @@ -13,5 +13,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C.json index 5d75934310..33d9312ab2 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Silk @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Sparkle @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Sparkle @BBL X1C.json index fdc02d06c5..40ef931764 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Sparkle @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Sparkle @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C 0.2 nozzle.json index eb6f63a2f3..ea19cfcc5e 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C 0.2 nozzle.json @@ -13,5 +13,8 @@ "Bambu Lab X1 0.2 nozzle", "Bambu Lab P1S 0.2 nozzle", "Bambu Lab X1E 0.2 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C.json index 418cc8f9ca..d2b9a46030 100644 --- a/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA Tough @BBL X1C.json @@ -18,5 +18,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C 0.8 nozzle.json index 3b5c25a41f..204237570b 100644 --- a/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C 0.8 nozzle.json @@ -23,5 +23,8 @@ "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C.json b/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C.json index c917e0745a..2e4aa2e93c 100644 --- a/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C.json +++ b/resources/profiles/BBL/filament/Bambu PLA-CF @BBL X1C.json @@ -19,5 +19,8 @@ "Bambu Lab X1 0.4 nozzle", "Bambu Lab P1S 0.4 nozzle", "Bambu Lab X1E 0.4 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\nM142 P1 R35 S40\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1 0.2 nozzle.json new file mode 100644 index 0000000000..52f12d83ed --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1 0.2 nozzle.json @@ -0,0 +1,32 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL A1 0.2 nozzle", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_07", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "filament_max_volumetric_speed": [ + "0.5" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab A1 0.2 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1.json new file mode 100644 index 0000000000..cc081f215f --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1.json @@ -0,0 +1,31 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL A1", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_06", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M 0.2 nozzle.json new file mode 100644 index 0000000000..e896919e4e --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M 0.2 nozzle.json @@ -0,0 +1,32 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL A1M 0.2 nozzle", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_05", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "filament_max_volumetric_speed": [ + "0.5" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab A1 mini 0.2 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M.json new file mode 100644 index 0000000000..ad2bc888ac --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL A1M.json @@ -0,0 +1,31 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL A1M", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_04", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P 0.2 nozzle.json new file mode 100644 index 0000000000..0352dc891a --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P 0.2 nozzle.json @@ -0,0 +1,32 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL P1P 0.2 nozzle", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_03", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "filament_max_volumetric_speed": [ + "0.5" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab P1P 0.2 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P.json new file mode 100644 index 0000000000..1f47df1ec9 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL P1P.json @@ -0,0 +1,31 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL P1P", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_02", + "instantiation": "true", + "eng_plate_temp": [ + "65" + ], + "eng_plate_temp_initial_layer": [ + "65" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ], + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C 0.2 nozzle.json new file mode 100644 index 0000000000..fa58a048a7 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C 0.2 nozzle.json @@ -0,0 +1,23 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL X1C 0.2 nozzle", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_01", + "instantiation": "true", + "eng_plate_temp": [ + "60" + ], + "eng_plate_temp_initial_layer": [ + "60" + ], + "filament_max_volumetric_speed": [ + "0.5" + ], + "compatible_printers": [ + "Bambu Lab P1S 0.2 nozzle", + "Bambu Lab X1 0.2 nozzle", + "Bambu Lab X1 Carbon 0.2 nozzle", + "Bambu Lab X1E 0.2 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C.json new file mode 100644 index 0000000000..8672833ea7 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @BBL X1C.json @@ -0,0 +1,28 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @BBL X1C", + "inherits": "Bambu Support For PLA/PETG @base", + "from": "system", + "setting_id": "GFSS05_00", + "instantiation": "true", + "eng_plate_temp": [ + "60" + ], + "eng_plate_temp_initial_layer": [ + "60" + ], + "compatible_printers": [ + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @base.json b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @base.json new file mode 100644 index 0000000000..4e62835862 --- /dev/null +++ b/resources/profiles/BBL/filament/Bambu Support For PLA-PETG @base.json @@ -0,0 +1,53 @@ +{ + "type": "filament", + "name": "Bambu Support For PLA/PETG @base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFS05", + "instantiation": "false", + "fan_cooling_layer_time": [ + "80" + ], + "fan_max_speed": [ + "30" + ], + "fan_min_speed": [ + "20" + ], + "filament_cost": [ + "69.98" + ], + "filament_density": [ + "1.19" + ], + "filament_is_support": [ + "1" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "filament_vendor": [ + "Bambu Lab" + ], + "hot_plate_temp": [ + "60" + ], + "hot_plate_temp_initial_layer": [ + "60" + ], + "nozzle_temperature": [ + "210" + ], + "nozzle_temperature_initial_layer": [ + "210" + ], + "slow_down_layer_time": [ + "8" + ], + "textured_plate_temp": [ + "60" + ], + "textured_plate_temp_initial_layer": [ + "60" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic BVOH @BBL A1.json b/resources/profiles/BBL/filament/Generic BVOH @BBL A1.json new file mode 100644 index 0000000000..c719bc4f8d --- /dev/null +++ b/resources/profiles/BBL/filament/Generic BVOH @BBL A1.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Generic BVOH @BBL A1", + "inherits": "Generic BVOH @base", + "from": "system", + "setting_id": "GFSS97_02", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic BVOH @BBL A1M.json b/resources/profiles/BBL/filament/Generic BVOH @BBL A1M.json new file mode 100644 index 0000000000..c7c2bb1fbc --- /dev/null +++ b/resources/profiles/BBL/filament/Generic BVOH @BBL A1M.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Generic BVOH @BBL A1M", + "inherits": "Generic BVOH @base", + "from": "system", + "setting_id": "GFSS97_01", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic BVOH @BBL X1C.json b/resources/profiles/BBL/filament/Generic BVOH @BBL X1C.json new file mode 100644 index 0000000000..12205f9c9a --- /dev/null +++ b/resources/profiles/BBL/filament/Generic BVOH @BBL X1C.json @@ -0,0 +1,25 @@ +{ + "type": "filament", + "name": "Generic BVOH @BBL X1C", + "inherits": "Generic BVOH @base", + "from": "system", + "setting_id": "GFSS97_00", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic BVOH @base.json b/resources/profiles/BBL/filament/Generic BVOH @base.json new file mode 100644 index 0000000000..34b3d72d1a --- /dev/null +++ b/resources/profiles/BBL/filament/Generic BVOH @base.json @@ -0,0 +1,8 @@ +{ + "type": "filament", + "name": "Generic BVOH @base", + "inherits": "fdm_filament_bvoh", + "from": "system", + "filament_id": "GFS97", + "instantiation": "false" +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic EVA @BBL A1.json b/resources/profiles/BBL/filament/Generic EVA @BBL A1.json new file mode 100644 index 0000000000..1090e57594 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic EVA @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic EVA @BBL A1", + "inherits": "Generic EVA @base", + "from": "system", + "setting_id": "GFSR99_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic EVA @BBL A1M.json b/resources/profiles/BBL/filament/Generic EVA @BBL A1M.json new file mode 100644 index 0000000000..9d903da18d --- /dev/null +++ b/resources/profiles/BBL/filament/Generic EVA @BBL A1M.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic EVA @BBL A1M", + "inherits": "Generic EVA @base", + "from": "system", + "setting_id": "GFSR99_02", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.8 nozzle", + "Bambu Lab A1 mini 0.6 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic EVA @BBL X1C.json b/resources/profiles/BBL/filament/Generic EVA @BBL X1C.json new file mode 100644 index 0000000000..c10fe78b5e --- /dev/null +++ b/resources/profiles/BBL/filament/Generic EVA @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic EVA @BBL X1C", + "inherits": "Generic EVA @base", + "from": "system", + "setting_id": "GFSR99_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic EVA @base.json b/resources/profiles/BBL/filament/Generic EVA @base.json new file mode 100644 index 0000000000..6a24cfdba5 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic EVA @base.json @@ -0,0 +1,86 @@ +{ + "type": "filament", + "name": "Generic EVA @base", + "inherits": "fdm_filament_eva", + "from": "system", + "filament_id": "GFR99", + "instantiation": "false", + "additional_cooling_fan_speed": [ + "70" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "cool_plate_temp": [ + "35" + ], + "cool_plate_temp_initial_layer": [ + "35" + ], + "eng_plate_temp": [ + "0" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "fan_cooling_layer_time": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_cost": [ + "21.99" + ], + "filament_density": [ + "0.94" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_type": [ + "EVA" + ], + "hot_plate_temp": [ + "55" + ], + "hot_plate_temp_initial_layer": [ + "55" + ], + "nozzle_temperature": [ + "210" + ], + "nozzle_temperature_initial_layer": [ + "210" + ], + "nozzle_temperature_range_high": [ + "220" + ], + "nozzle_temperature_range_low": [ + "175" + ], + "overhang_fan_threshold": [ + "50%" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "slow_down_layer_time": [ + "4" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "70" + ], + "textured_plate_temp": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PCTG @BBL A1.json b/resources/profiles/BBL/filament/Generic PCTG @BBL A1.json new file mode 100644 index 0000000000..0d7ddda1cb --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PCTG @BBL A1.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Generic PCTG @BBL A1", + "inherits": "Generic PCTG @base", + "from": "system", + "setting_id": "GFSG97_01", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PCTG @BBL A1M.json b/resources/profiles/BBL/filament/Generic PCTG @BBL A1M.json new file mode 100644 index 0000000000..3f02a3a3e8 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PCTG @BBL A1M.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "name": "Generic PCTG @BBL A1M", + "inherits": "Generic PCTG @base", + "from": "system", + "setting_id": "GFSG97_02", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PCTG @BBL X1C.json b/resources/profiles/BBL/filament/Generic PCTG @BBL X1C.json new file mode 100644 index 0000000000..e7802ed3d7 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PCTG @BBL X1C.json @@ -0,0 +1,25 @@ +{ + "type": "filament", + "name": "Generic PCTG @BBL X1C", + "inherits": "Generic PCTG @base", + "from": "system", + "setting_id": "GFSG97_00", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PCTG @base.json b/resources/profiles/BBL/filament/Generic PCTG @base.json new file mode 100644 index 0000000000..ca51974e25 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PCTG @base.json @@ -0,0 +1,74 @@ +{ + "type": "filament", + "name": "Generic PCTG @base", + "inherits": "fdm_filament_pet", + "from": "system", + "filament_id": "GFG97", + "instantiation": "false", + "cool_plate_temp": [ + "0" + ], + "cool_plate_temp_initial_layer": [ + "0" + ], + "eng_plate_temp": [ + "70" + ], + "eng_plate_temp_initial_layer": [ + "70" + ], + "fan_cooling_layer_time": [ + "30" + ], + "fan_max_speed": [ + "40" + ], + "fan_min_speed": [ + "10" + ], + "filament_cost": [ + "28.99" + ], + "filament_density": [ + "1.29" + ], + "filament_flow_ratio": [ + "0.95" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "hot_plate_temp": [ + "70" + ], + "hot_plate_temp_initial_layer": [ + "70" + ], + "nozzle_temperature_range_high": [ + "270" + ], + "nozzle_temperature_range_low": [ + "240" + ], + "overhang_fan_speed": [ + "90" + ], + "overhang_fan_threshold": [ + "10%" + ], + "slow_down_layer_time": [ + "12" + ], + "temperature_vitrification": [ + "90" + ], + "textured_plate_temp": [ + "70" + ], + "textured_plate_temp_initial_layer": [ + "70" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >80)||(bed_temperature_initial_layer[current_extruder] >80)}M106 P3 S255\n{elsif (bed_temperature[current_extruder] >60)||(bed_temperature_initial_layer[current_extruder] >60)}M106 P3 S180\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE @BBL A1.json b/resources/profiles/BBL/filament/Generic PE @BBL A1.json new file mode 100644 index 0000000000..39e2445109 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PE @BBL A1", + "inherits": "Generic PE @base", + "from": "system", + "setting_id": "GFSP99_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE @BBL A1M.json b/resources/profiles/BBL/filament/Generic PE @BBL A1M.json new file mode 100644 index 0000000000..c1127d4123 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE @BBL A1M.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PE @BBL A1M", + "inherits": "Generic PE @base", + "from": "system", + "setting_id": "GFSP99_02", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE @BBL X1C.json b/resources/profiles/BBL/filament/Generic PE @BBL X1C.json new file mode 100644 index 0000000000..da34e44a63 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic PE @BBL X1C", + "inherits": "Generic PE @base", + "from": "system", + "setting_id": "GFSP99_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE @base.json b/resources/profiles/BBL/filament/Generic PE @base.json new file mode 100644 index 0000000000..c93659062f --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE @base.json @@ -0,0 +1,35 @@ +{ + "type": "filament", + "name": "Generic PE @base", + "inherits": "fdm_filament_pe", + "from": "system", + "filament_id": "GFP99", + "instantiation": "false", + "filament_cost": [ + "40.99" + ], + "filament_density": [ + "0.95" + ], + "filament_max_volumetric_speed": [ + "8" + ], + "nozzle_temperature": [ + "210" + ], + "nozzle_temperature_initial_layer": [ + "210" + ], + "nozzle_temperature_range_high": [ + "220" + ], + "nozzle_temperature_range_low": [ + "175" + ], + "temperature_vitrification": [ + "70" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE-CF @BBL A1.json b/resources/profiles/BBL/filament/Generic PE-CF @BBL A1.json new file mode 100644 index 0000000000..50584fff90 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE-CF @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PE-CF @BBL A1", + "inherits": "Generic PE-CF @base", + "from": "system", + "setting_id": "GFSP98_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE-CF @BBL A1M.json b/resources/profiles/BBL/filament/Generic PE-CF @BBL A1M.json new file mode 100644 index 0000000000..2e3b4b4bf4 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE-CF @BBL A1M.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PE-CF @BBL A1M", + "inherits": "Generic PE-CF @base", + "from": "system", + "setting_id": "GFSP98_02", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE-CF @BBL X1C.json b/resources/profiles/BBL/filament/Generic PE-CF @BBL X1C.json new file mode 100644 index 0000000000..bf95029646 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE-CF @BBL X1C.json @@ -0,0 +1,25 @@ +{ + "type": "filament", + "name": "Generic PE-CF @BBL X1C", + "inherits": "Generic PE-CF @base", + "from": "system", + "setting_id": "GFSP98_00", + "instantiation": "true", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PE-CF @base.json b/resources/profiles/BBL/filament/Generic PE-CF @base.json new file mode 100644 index 0000000000..929d738ffc --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PE-CF @base.json @@ -0,0 +1,38 @@ +{ + "type": "filament", + "name": "Generic PE-CF @base", + "inherits": "fdm_filament_pe", + "from": "system", + "filament_id": "GFP98", + "instantiation": "false", + "filament_cost": [ + "65.99" + ], + "filament_density": [ + "0.95" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "filament_type": [ + "PE-CF" + ], + "nozzle_temperature": [ + "210" + ], + "nozzle_temperature_initial_layer": [ + "210" + ], + "nozzle_temperature_range_high": [ + "220" + ], + "nozzle_temperature_range_low": [ + "175" + ], + "temperature_vitrification": [ + "70" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PHA @BBL A1.json b/resources/profiles/BBL/filament/Generic PHA @BBL A1.json new file mode 100644 index 0000000000..32f3fd84a9 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PHA @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PHA @BBL A1", + "inherits": "Generic PHA @base", + "from": "system", + "setting_id": "GFSR98_02", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle", + "Bambu Lab A1 0.4 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PHA @BBL A1M.json b/resources/profiles/BBL/filament/Generic PHA @BBL A1M.json new file mode 100644 index 0000000000..a3c6158000 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PHA @BBL A1M.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PHA @BBL A1M", + "inherits": "Generic PHA @base", + "from": "system", + "setting_id": "GFSR98_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PHA @BBL X1C.json b/resources/profiles/BBL/filament/Generic PHA @BBL X1C.json new file mode 100644 index 0000000000..0305af0ee6 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PHA @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic PHA @BBL X1C", + "inherits": "Generic PHA @base", + "from": "system", + "setting_id": "GFSR98_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1P 0.4 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PHA @base.json b/resources/profiles/BBL/filament/Generic PHA @base.json new file mode 100644 index 0000000000..f91285ad49 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PHA @base.json @@ -0,0 +1,8 @@ +{ + "type": "filament", + "name": "Generic PHA @base", + "inherits": "fdm_filament_pha", + "from": "system", + "filament_id": "GFR98", + "instantiation": "false" +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PLA High Speed @BBL X1C.json b/resources/profiles/BBL/filament/Generic PLA High Speed @BBL X1C.json index f2e682804f..7263d42f85 100644 --- a/resources/profiles/BBL/filament/Generic PLA High Speed @BBL X1C.json +++ b/resources/profiles/BBL/filament/Generic PLA High Speed @BBL X1C.json @@ -21,5 +21,8 @@ "Bambu Lab P1S 0.8 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PLA Silk.json b/resources/profiles/BBL/filament/Generic PLA Silk.json index c1011d708b..40fa7b252c 100644 --- a/resources/profiles/BBL/filament/Generic PLA Silk.json +++ b/resources/profiles/BBL/filament/Generic PLA Silk.json @@ -24,5 +24,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP @BBL A1.json b/resources/profiles/BBL/filament/Generic PP @BBL A1.json new file mode 100644 index 0000000000..4c4b6c1710 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PP @BBL A1", + "inherits": "Generic PP @base", + "from": "system", + "setting_id": "GFSP97_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP @BBL A1M.json b/resources/profiles/BBL/filament/Generic PP @BBL A1M.json new file mode 100644 index 0000000000..3c4907f8c9 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP @BBL A1M.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PP @BBL A1M", + "inherits": "Generic PP @base", + "from": "system", + "setting_id": "GFSP97_02", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 mini 0.4 nozzle", + "Bambu Lab A1 mini 0.6 nozzle", + "Bambu Lab A1 mini 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP @BBL X1C.json b/resources/profiles/BBL/filament/Generic PP @BBL X1C.json new file mode 100644 index 0000000000..664b7be27f --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic PP @BBL X1C", + "inherits": "Generic PP @base", + "from": "system", + "setting_id": "GFSP97_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP @base.json b/resources/profiles/BBL/filament/Generic PP @base.json new file mode 100644 index 0000000000..faf0a211fa --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP @base.json @@ -0,0 +1,8 @@ +{ + "type": "filament", + "name": "Generic PP @base", + "inherits": "fdm_filament_pp", + "from": "system", + "filament_id": "GFP97", + "instantiation": "false" +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-CF @BBL A1.json b/resources/profiles/BBL/filament/Generic PP-CF @BBL A1.json new file mode 100644 index 0000000000..3c3ad6cfd1 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-CF @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PP-CF @BBL A1", + "inherits": "Generic PP-CF @base", + "from": "system", + "setting_id": "GFSP96_01", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-CF @BBL X1C.json b/resources/profiles/BBL/filament/Generic PP-CF @BBL X1C.json new file mode 100644 index 0000000000..2653f7acc8 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-CF @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic PP-CF @BBL X1C", + "inherits": "Generic PP-CF @base", + "from": "system", + "setting_id": "GFSP96_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-CF @base.json b/resources/profiles/BBL/filament/Generic PP-CF @base.json new file mode 100644 index 0000000000..c131f95878 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-CF @base.json @@ -0,0 +1,20 @@ +{ + "type": "filament", + "name": "Generic PP-CF @base", + "inherits": "fdm_filament_pp", + "from": "system", + "filament_id": "GFP96", + "instantiation": "false", + "filament_cost": [ + "77.99" + ], + "filament_density": [ + "1.01" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "filament_type": [ + "PP-CF" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-GF @BBL A1.json b/resources/profiles/BBL/filament/Generic PP-GF @BBL A1.json new file mode 100644 index 0000000000..b8d3231f45 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-GF @BBL A1.json @@ -0,0 +1,14 @@ +{ + "type": "filament", + "name": "Generic PP-GF @BBL A1", + "inherits": "Generic PP-GF @base", + "from": "system", + "setting_id": "GFSP95_00", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab A1 0.4 nozzle", + "Bambu Lab A1 0.6 nozzle", + "Bambu Lab A1 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-GF @BBL X1C.json b/resources/profiles/BBL/filament/Generic PP-GF @BBL X1C.json new file mode 100644 index 0000000000..7a94c1ad98 --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-GF @BBL X1C.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Generic PP-GF @BBL X1C", + "inherits": "Generic PP-GF @base", + "from": "system", + "setting_id": "GFSP97_03", + "instantiation": "true", + "description": "This is neither a commonly used filament, nor one of Bambu filaments, and it varies a lot from brand to brand. So, it's highly recommended to ask its vendor for suitable profile before printing and adjust some parameters according to its performances.", + "compatible_printers": [ + "Bambu Lab P1P 0.4 nozzle", + "Bambu Lab P1P 0.6 nozzle", + "Bambu Lab P1P 0.8 nozzle", + "Bambu Lab P1S 0.4 nozzle", + "Bambu Lab P1S 0.6 nozzle", + "Bambu Lab P1S 0.8 nozzle", + "Bambu Lab X1 0.4 nozzle", + "Bambu Lab X1 0.6 nozzle", + "Bambu Lab X1 0.8 nozzle", + "Bambu Lab X1 Carbon 0.4 nozzle", + "Bambu Lab X1 Carbon 0.6 nozzle", + "Bambu Lab X1 Carbon 0.8 nozzle", + "Bambu Lab X1E 0.4 nozzle", + "Bambu Lab X1E 0.6 nozzle", + "Bambu Lab X1E 0.8 nozzle" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Generic PP-GF @base.json b/resources/profiles/BBL/filament/Generic PP-GF @base.json new file mode 100644 index 0000000000..b58eace53c --- /dev/null +++ b/resources/profiles/BBL/filament/Generic PP-GF @base.json @@ -0,0 +1,20 @@ +{ + "type": "filament", + "name": "Generic PP-GF @base", + "inherits": "fdm_filament_pp", + "from": "system", + "filament_id": "GFP95", + "instantiation": "false", + "filament_cost": [ + "59.99" + ], + "filament_density": [ + "1.05" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "filament_type": [ + "PP-GF" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1.json b/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1.json index cedb6ba843..ba16728a53 100644 --- a/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1.json +++ b/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1.json @@ -12,5 +12,8 @@ "Bambu Lab X1 0.6 nozzle", "Bambu Lab X1 0.8 nozzle", "Bambu Lab X1 0.4 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1C.json b/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1C.json index 7d5a7ecd57..bdfcdeef90 100644 --- a/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1C.json +++ b/resources/profiles/BBL/filament/Overture Matte PLA @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Overture PLA @BBL X1.json b/resources/profiles/BBL/filament/Overture PLA @BBL X1.json index c36384a9e7..28b917ca5f 100644 --- a/resources/profiles/BBL/filament/Overture PLA @BBL X1.json +++ b/resources/profiles/BBL/filament/Overture PLA @BBL X1.json @@ -12,5 +12,8 @@ "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.8 nozzle", "Bambu Lab X1 0.6 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/Overture PLA @BBL X1C.json b/resources/profiles/BBL/filament/Overture PLA @BBL X1C.json index 15c06a2ca6..62a0d4d9e8 100644 --- a/resources/profiles/BBL/filament/Overture PLA @BBL X1C.json +++ b/resources/profiles/BBL/filament/Overture PLA @BBL X1C.json @@ -15,5 +15,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P 0.2 nozzle.json index e703e3d6a6..f99a91cfb0 100644 --- a/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P 0.2 nozzle.json @@ -20,6 +20,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P.json b/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P.json index b1206b169d..63d6bb3f21 100644 --- a/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P.json +++ b/resources/profiles/BBL/filament/P1P/Bambu ABS @BBL P1P.json @@ -20,6 +20,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P 0.2 nozzle.json index b4bcf75507..bbf4b7ee51 100644 --- a/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P 0.2 nozzle.json @@ -29,6 +29,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P.json b/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P.json index a34eef36af..2a5769421e 100644 --- a/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P.json +++ b/resources/profiles/BBL/filament/P1P/Bambu PC @BBL P1P.json @@ -23,6 +23,9 @@ "reduce_fan_stop_start_freq": [ "0" ], + "slow_down_layer_time": [ + "12" + ], "textured_plate_temp": [ "100" ], diff --git a/resources/profiles/BBL/filament/P1P/PolyTerra PLA @BBL P1P.json b/resources/profiles/BBL/filament/P1P/PolyTerra PLA @BBL P1P.json index 7504020d8f..5728ac0c5a 100644 --- a/resources/profiles/BBL/filament/P1P/PolyTerra PLA @BBL P1P.json +++ b/resources/profiles/BBL/filament/P1P/PolyTerra PLA @BBL P1P.json @@ -33,5 +33,8 @@ "Bambu Lab P1P 0.4 nozzle", "Bambu Lab P1P 0.6 nozzle", "Bambu Lab P1P 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/PolyLite PLA @BBL X1.json b/resources/profiles/BBL/filament/PolyLite PLA @BBL X1.json index 4ed5821921..77a037efd8 100644 --- a/resources/profiles/BBL/filament/PolyLite PLA @BBL X1.json +++ b/resources/profiles/BBL/filament/PolyLite PLA @BBL X1.json @@ -15,5 +15,8 @@ "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.6 nozzle", "Bambu Lab X1 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/PolyLite PLA @BBL X1C.json b/resources/profiles/BBL/filament/PolyLite PLA @BBL X1C.json index c9c27d9143..a24021705e 100644 --- a/resources/profiles/BBL/filament/PolyLite PLA @BBL X1C.json +++ b/resources/profiles/BBL/filament/PolyLite PLA @BBL X1C.json @@ -18,5 +18,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1.json b/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1.json index d3fd2251c3..46e2144b4e 100644 --- a/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1.json +++ b/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1.json @@ -15,5 +15,8 @@ "Bambu Lab X1 0.4 nozzle", "Bambu Lab X1 0.6 nozzle", "Bambu Lab X1 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1C.json b/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1C.json index c3444436a2..72378493df 100644 --- a/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1C.json +++ b/resources/profiles/BBL/filament/PolyTerra PLA @BBL X1C.json @@ -18,5 +18,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab X1E 0.6 nozzle", "Bambu Lab X1E 0.8 nozzle" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_bvoh.json b/resources/profiles/BBL/filament/fdm_filament_bvoh.json new file mode 100644 index 0000000000..2b481e35d8 --- /dev/null +++ b/resources/profiles/BBL/filament/fdm_filament_bvoh.json @@ -0,0 +1,85 @@ +{ + "type": "filament", + "name": "fdm_filament_bvoh", + "inherits": "fdm_filament_common", + "from": "system", + "instantiation": "false", + "additional_cooling_fan_speed": [ + "70" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "cool_plate_temp": [ + "40" + ], + "cool_plate_temp_initial_layer": [ + "40" + ], + "eng_plate_temp": [ + "0" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "fan_cooling_layer_time": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_cost": [ + "69.99" + ], + "filament_density": [ + "1.13" + ], + "filament_is_support": [ + "1" + ], + "filament_max_volumetric_speed": [ + "8" + ], + "filament_type": [ + "BVOH" + ], + "hot_plate_temp": [ + "55" + ], + "hot_plate_temp_initial_layer": [ + "55" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "overhang_fan_threshold": [ + "50%" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "45" + ], + "textured_plate_temp": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >55)||(bed_temperature_initial_layer[current_extruder] >55)}M106 P3 S200\n{elsif(bed_temperature[current_extruder] >50)||(bed_temperature_initial_layer[current_extruder] >50)}M106 P3 S150\n{elsif(bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S50\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_common.json b/resources/profiles/BBL/filament/fdm_filament_common.json index 6f1291c6ec..6ec95db4a8 100644 --- a/resources/profiles/BBL/filament/fdm_filament_common.json +++ b/resources/profiles/BBL/filament/fdm_filament_common.json @@ -57,6 +57,9 @@ "filament_is_support": [ "0" ], + "filament_long_retractions_when_cut": [ + "nil" + ], "filament_max_volumetric_speed": [ "0" ], @@ -72,6 +75,9 @@ "filament_retract_when_changing_layer": [ "nil" ], + "filament_retraction_distances_when_cut": [ + "nil" + ], "filament_retraction_length": [ "nil" ], diff --git a/resources/profiles/BBL/filament/fdm_filament_eva.json b/resources/profiles/BBL/filament/fdm_filament_eva.json new file mode 100644 index 0000000000..1b2efe2999 --- /dev/null +++ b/resources/profiles/BBL/filament/fdm_filament_eva.json @@ -0,0 +1,10 @@ +{ + "type": "filament", + "name": "fdm_filament_eva", + "inherits": "fdm_filament_common", + "from": "system", + "instantiation": "false", + "filament_type": [ + "EVA" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_pc.json b/resources/profiles/BBL/filament/fdm_filament_pc.json index 5729114297..03bc9e5663 100644 --- a/resources/profiles/BBL/filament/fdm_filament_pc.json +++ b/resources/profiles/BBL/filament/fdm_filament_pc.json @@ -7,76 +7,76 @@ "cool_plate_temp": [ "0" ], - "eng_plate_temp": [ - "110" - ], - "hot_plate_temp": [ - "110" - ], - "textured_plate_temp": [ - "110" - ], "cool_plate_temp_initial_layer": [ "0" ], + "eng_plate_temp": [ + "110" + ], "eng_plate_temp_initial_layer": [ "110" ], - "hot_plate_temp_initial_layer": [ - "110" - ], - "textured_plate_temp_initial_layer": [ - "110" - ], "fan_cooling_layer_time": [ "30" ], - "filament_max_volumetric_speed": [ - "23.2" - ], - "filament_type": [ - "PC" - ], - "filament_density": [ - "1.04" - ], - "filament_cost": [ - "20" - ], - "nozzle_temperature_initial_layer": [ - "270" - ], - "reduce_fan_stop_start_freq": [ - "1" - ], "fan_max_speed": [ "60" ], "fan_min_speed": [ "10" ], - "overhang_fan_threshold": [ - "25%" + "filament_cost": [ + "20" ], - "overhang_fan_speed": [ - "60" + "filament_density": [ + "1.04" + ], + "filament_max_volumetric_speed": [ + "18" + ], + "filament_type": [ + "PC" + ], + "hot_plate_temp": [ + "110" + ], + "hot_plate_temp_initial_layer": [ + "110" ], "nozzle_temperature": [ "280" ], - "temperature_vitrification": [ - "120" - ], - "nozzle_temperature_range_low": [ - "260" + "nozzle_temperature_initial_layer": [ + "270" ], "nozzle_temperature_range_high": [ "290" ], - "slow_down_min_speed": [ - "20" + "nozzle_temperature_range_low": [ + "260" + ], + "overhang_fan_speed": [ + "60" + ], + "overhang_fan_threshold": [ + "25%" + ], + "reduce_fan_stop_start_freq": [ + "1" ], "slow_down_layer_time": [ "2" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "120" + ], + "textured_plate_temp": [ + "110" + ], + "textured_plate_temp_initial_layer": [ + "110" ] } \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_pe.json b/resources/profiles/BBL/filament/fdm_filament_pe.json new file mode 100644 index 0000000000..8ce20df68a --- /dev/null +++ b/resources/profiles/BBL/filament/fdm_filament_pe.json @@ -0,0 +1,85 @@ +{ + "type": "filament", + "name": "fdm_filament_pe", + "inherits": "fdm_filament_common", + "from": "system", + "instantiation": "false", + "additional_cooling_fan_speed": [ + "70" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "cool_plate_temp": [ + "35" + ], + "cool_plate_temp_initial_layer": [ + "35" + ], + "eng_plate_temp": [ + "0" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "fan_cooling_layer_time": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_cost": [ + "20" + ], + "filament_density": [ + "1.24" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_type": [ + "PE" + ], + "hot_plate_temp": [ + "55" + ], + "hot_plate_temp_initial_layer": [ + "55" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "overhang_fan_threshold": [ + "50%" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "slow_down_layer_time": [ + "4" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "45" + ], + "textured_plate_temp": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S255\n{elsif(bed_temperature[current_extruder] >35)||(bed_temperature_initial_layer[current_extruder] >35)}M106 P3 S180\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_pha.json b/resources/profiles/BBL/filament/fdm_filament_pha.json new file mode 100644 index 0000000000..82519f1b2e --- /dev/null +++ b/resources/profiles/BBL/filament/fdm_filament_pha.json @@ -0,0 +1,85 @@ +{ + "type": "filament", + "name": "fdm_filament_pha", + "inherits": "fdm_filament_common", + "from": "system", + "instantiation": "false", + "additional_cooling_fan_speed": [ + "70" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "cool_plate_temp": [ + "35" + ], + "cool_plate_temp_initial_layer": [ + "35" + ], + "eng_plate_temp": [ + "0" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "fan_cooling_layer_time": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_cost": [ + "27.99" + ], + "filament_density": [ + "1.24" + ], + "filament_max_volumetric_speed": [ + "6" + ], + "filament_type": [ + "PHA" + ], + "hot_plate_temp": [ + "55" + ], + "hot_plate_temp_initial_layer": [ + "55" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "overhang_fan_threshold": [ + "50%" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "slow_down_layer_time": [ + "4" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "120" + ], + "textured_plate_temp": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S255\n{elsif(bed_temperature[current_extruder] >35)||(bed_temperature_initial_layer[current_extruder] >35)}M106 P3 S180\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/filament/fdm_filament_pp.json b/resources/profiles/BBL/filament/fdm_filament_pp.json new file mode 100644 index 0000000000..83a4278250 --- /dev/null +++ b/resources/profiles/BBL/filament/fdm_filament_pp.json @@ -0,0 +1,85 @@ +{ + "type": "filament", + "name": "fdm_filament_pp", + "inherits": "fdm_filament_common", + "from": "system", + "instantiation": "false", + "additional_cooling_fan_speed": [ + "70" + ], + "close_fan_the_first_x_layers": [ + "1" + ], + "cool_plate_temp": [ + "35" + ], + "cool_plate_temp_initial_layer": [ + "35" + ], + "eng_plate_temp": [ + "0" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "fan_cooling_layer_time": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_cost": [ + "34.99" + ], + "filament_density": [ + "0.93" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_type": [ + "PP" + ], + "hot_plate_temp": [ + "55" + ], + "hot_plate_temp_initial_layer": [ + "55" + ], + "nozzle_temperature": [ + "235" + ], + "nozzle_temperature_initial_layer": [ + "235" + ], + "nozzle_temperature_range_high": [ + "250" + ], + "nozzle_temperature_range_low": [ + "220" + ], + "overhang_fan_threshold": [ + "50%" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "slow_down_layer_time": [ + "4" + ], + "slow_down_min_speed": [ + "20" + ], + "temperature_vitrification": [ + "110" + ], + "textured_plate_temp": [ + "55" + ], + "textured_plate_temp_initial_layer": [ + "55" + ], + "filament_start_gcode": [ + "; filament start gcode\n{if (bed_temperature[current_extruder] >45)||(bed_temperature_initial_layer[current_extruder] >45)}M106 P3 S255\n{elsif(bed_temperature[current_extruder] >35)||(bed_temperature_initial_layer[current_extruder] >35)}M106 P3 S180\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}" + ] +} \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab A1 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab A1 0.2 nozzle.json index 700b24df85..3e0225bb70 100644 --- a/resources/profiles/BBL/machine/Bambu Lab A1 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab A1 0.2 nozzle.json @@ -13,6 +13,12 @@ "default_filament_profile": [ "Bambu PLA Basic @BBL A1 0.2 nozzle" ], + "max_layer_height": [ + "0.14" + ], + "min_layer_height": [ + "0.04" + ], "default_print_profile": "0.10mm Standard @BBL A1 0.2 nozzle", "upward_compatible_machine": [] } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab A1 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab A1 0.4 nozzle.json index 7feaa0a6a3..078e12ae45 100644 --- a/resources/profiles/BBL/machine/Bambu Lab A1 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab A1 0.4 nozzle.json @@ -52,17 +52,18 @@ "30" ], "machine_unload_filament_time": "29", + "nozzle_height": "4.76", "nozzle_type": "stainless_steel", - "nozzle_volume": "117", + "nozzle_volume": "92", "printable_height": "256", "printer_structure": "i3", "retract_lift_below": [ "255" ], "scan_first_layer": "0", - "machine_start_gcode": ";===== machine: A1 =========================\n;===== date: 20240104 =====================\nG392 S0\n;M400\n;M73 P1.717\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM104 S140\nM140 S[bed_temperature_initial_layer_single]\n\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\nM1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A43 B10 L100 C46 D10 M70 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C43 D10 M60 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C41 D10 M80 E41 F10 N80\nM1006 A0 B10 L100 C44 D10 M80 E44 F10 N80\nM1006 A0 B10 L100 C49 D10 M80 E49 F10 N80\nM1006 A0 B10 L100 C0 D10 M80 E0 F10 N80\nM1006 A44 B10 L100 C48 D10 M60 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C44 D10 M80 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A43 B10 L100 C46 D10 M60 E39 F10 N80\nM1006 W\nM18\n;=====start printer sound ===================\n\n;=====avoid end stop =================\nG91\nG380 S2 Z40 F1200\nG380 S2 Z-15 F1200\nG90\n\n;===== reset machine status =================\n;M290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.65 Y1.2 Z0.6 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;M211 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\nM1002 gcode_claim_action : 13\n\nG28 X\nG91\nG1 Z5 F1200\nG90\nG0 X128 F30000\nG0 Y254 F3000\nG91\nG1 Z-5 F1200\n\nM109 S10 H140\n\nM17 E0.3\nM83\nG1 E10 F1200\nG1 E-0.5 F30\nM17 D\n\nG28 Z P0 T140; home z with low precision,permit 300deg temperature\nM104 S{nozzle_temperature_initial_layer[initial_extruder]}\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n G90\n G1 Z5 F1200\nM623\n\n;M400\n;M73 P1.717\n\n;===== prepare print temperature and material ==========\nM1002 gcode_claim_action : 24\n\nM400\n;G392 S1\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on\n\nG90\nG1 X-28.5 F30000\nG1 X-48.2 F3000\n\nM620 M ;enable remap\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S[nozzle_temperature_initial_layer]\n M104 S250\n M400\n T[initial_no_support_extruder]\n G1 X-48.2 F3000\n M400\n\n M620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM621 S[initial_no_support_extruder]A\n\nM109 S{nozzle_temperature_range_high[initial_no_support_extruder]} H300\nG92 E0\nG1 E50 F200 ; lower extrusion speed to avoid clog\nM400\nM106 P1 S178\nG92 E0\nG1 E5 F200\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG92 E0\nG1 E-0.5 F300\n\nG1 X-28.5 F30000\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\n\n;G392 S0\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n;M400\n;M73 P1.717\n\n;===== auto extrude cali start =========================\nM975 S1\n;G392 S1\n\nG90\nM83\nT1000\nG1 X-48.2 Y0 Z10 F10000\nM400\nM1002 set_filament_type:UNKNOWN\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\n\nM622 J1\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_extruder]}\n G1 E10 F{outer_wall_volumetric_speed/2.4*60}\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n \n G1 X-48.2 F3000\n M400\n M984 A0.1 E1 S1 F{outer_wall_volumetric_speed/2.4}\n M106 P1 S178\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000\n M400\n M106 P1 S0\nM623 ; end of \"draw extrinsic para cali paint\"\n\n;G392 S0\n;===== auto extrude cali end ========================\n\n;M400\n;M73 P1.717\n\nM104 S170 ; prepare to wipe nozzle\nM106 S255 ; turn on fan\n\n;===== mech mode fast check start =====================\nM1002 gcode_claim_action : 3\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q1 A5 K0 O3\nM974 Q1 S2 P0\n\nM970.2 Q1 K1 W58 Z0.11\nM974 S2\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q0 A10 K0 O1\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X0 Y5\nG28 X ; re-home XY\n\n;===== mech mode fast check end =======================\n\n;M400\n;M73 P1.717\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\n\nM975 S1\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\n;===== remove waste by touching start =====\n\nM104 S170 ; set temp down to heatbed acceptable\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nG0 X108 Y-0.5 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X110 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X112 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X114 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X116 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X118 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X120 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X122 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X124 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X126 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X128 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X130 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X132 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X134 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X136 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X138 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X140 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X142 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X144 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X146 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X148 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;===== remove waste by touching end =====\n\nG1 Z10 F1200\nG0 X118 Y261 F30000\nG1 Z5 F1200\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-50}\n\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S140 ; prepare to abl\nG0 Z5 F20000\n\nG0 X128 Y261 F20000 ; move to exposed steel surface\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z10 F1200\n\n;===== brush material wipe nozzle =====\n\nG90\nG1 Y250 F30000\nG1 X55\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X-35 F30000\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Z5.000 F1200\n\nG90\nG1 X30 Y250.000 F30000\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X35 F30000\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Z10.000 F1200\n\n;===== brush material wipe nozzle end =====\n\nG90\n;G0 X128 Y261 F20000 ; move to exposed steel surface\nG1 Y250 F30000\nG1 X138\nG1 Y261\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nM109 S140\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM211 R; pop softend status\n\n;===== wipe nozzle end ================================\n\n;M400\n;M73 P1.717\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\n\nG90\nG1 Z5 F1200\nG1 X0 Y0 F30000\nG29.2 S1 ; turn on ABL\n\nM190 S[bed_temperature_initial_layer_single]; ensure bed temp\nM109 S140\nM106 S0 ; turn off fan , too noisy\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n\n;===== home after wipe mouth end =======================\n\n;M400\n;M73 P1.717\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; prepare to print\n\n;===== nozzle load line ===============================\n;G90\n;M83\n;G1 Z5 F1200\n;G1 X88 Y-0.5 F20000\n;G1 Z0.3 F1200\n\n;M109 S{nozzle_temperature_initial_layer[initial_extruder]}\n\n;G1 E2 F300\n;G1 X168 E4.989 F6000\n;G1 Z1 F1200\n;===== noozle load line end ===========================\n\n;===== extrude cali test ===============================\n\nM400\n M900 S\n\n M900 C\n G90\n M83\n G1 X78.000 Y-0.500 F30000\n G1 Z0.300 F1200\n\n M109 S{nozzle_temperature_initial_layer[initial_extruder]}\n G1 E3 F300\n\n G1 X83.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X88.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X93.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X98.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X103.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X108.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X113.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X118.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X123.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X128.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X133.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X138.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X143.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X148.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X153.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X158.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X163.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X168.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X173.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X178.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X179 Z0\n G1 X183\n G1 Z1\n M400\n\n M900 R\n G90\n M83\n G1 X78.000 Y4.500 F30000\n G1 Z0.300 F1200\n G1 E0.5 F300\n G1 X83.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X88.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X93.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X98.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X103.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X108.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X113.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X118.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X123.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X128.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X133.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X138.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X143.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X148.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X153.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X158.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X163.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X168.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X173.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X178.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X179 Z0\n G1 X183\n G1 Z1\n M400\n\nG1 Z0.2\n\n;M400\n;M73 P1.717\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\n;G392 S1 ; turn on clog detection\nM1007 S1 ; turn on mass estimation\nG29.4\n", + "machine_start_gcode": ";===== machine: A1 =========================\n;===== date: 20240311 =====================\nG392 S0\n;M400\n;M73 P1.717\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM104 S140\nM140 S[bed_temperature_initial_layer_single]\n\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B10 L100 C37 D10 M60 E37 F10 N60\nM1006 A0 B10 L100 C41 D10 M60 E41 F10 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A43 B10 L100 C46 D10 M70 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C43 D10 M60 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C41 D10 M80 E41 F10 N80\nM1006 A0 B10 L100 C44 D10 M80 E44 F10 N80\nM1006 A0 B10 L100 C49 D10 M80 E49 F10 N80\nM1006 A0 B10 L100 C0 D10 M80 E0 F10 N80\nM1006 A44 B10 L100 C48 D10 M60 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A0 B10 L100 C44 D10 M80 E39 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A43 B10 L100 C46 D10 M60 E39 F10 N80\nM1006 W\nM18 \n;=====start printer sound ===================\n\n;=====avoid end stop =================\nG91\nG380 S2 Z40 F1200\nG380 S3 Z-15 F1200\nG90\n\n;===== reset machine status =================\n;M290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.65 Y1.2 Z0.6 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;M211 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\nM1002 gcode_claim_action : 13\n\nG28 X\nG91\nG1 Z5 F1200\nG90\nG0 X128 F30000\nG0 Y254 F3000\nG91\nG1 Z-5 F1200\n\nM109 S25 H140\n\nM17 E0.3\nM83\nG1 E10 F1200\nG1 E-0.5 F30\nM17 D\n\nG28 Z P0 T140; home z with low precision,permit 300deg temperature\nM104 S{nozzle_temperature_initial_layer[initial_extruder]}\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n G90\n G1 Z5 F1200\nM623\n\n;M400\n;M73 P1.717\n\n;===== prepare print temperature and material ==========\nM1002 gcode_claim_action : 24\n\nM400\n;G392 S1\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on\n\nG90\nG1 X-28.5 F30000\nG1 X-48.2 F3000\n\nM620 M ;enable remap\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S[nozzle_temperature_initial_layer]\n M104 S250\n M400\n T[initial_no_support_extruder]\n G1 X-48.2 F3000\n M400\n\n M620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM621 S[initial_no_support_extruder]A\n\nM109 S{nozzle_temperature_range_high[initial_no_support_extruder]} H300\nG92 E0\nG1 E50 F200 ; lower extrusion speed to avoid clog\nM400\nM106 P1 S178\nG92 E0\nG1 E5 F200\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG92 E0\nG1 E-0.5 F300\n\nG1 X-28.5 F30000\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\nG1 X-28.5 F30000 ;wipe and shake\nG1 X-48.2 F3000\n\n;G392 S0\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n;M400\n;M73 P1.717\n\n;===== auto extrude cali start =========================\nM975 S1\n;G392 S1\n\nG90\nM83\nT1000\nG1 X-48.2 Y0 Z10 F10000\nM400\nM1002 set_filament_type:UNKNOWN\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\n\nM622 J1\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_extruder]}\n G1 E10 F{outer_wall_volumetric_speed/2.4*60}\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S255\n M400 S5\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n \n G1 X-48.2 F3000\n M400\n M984 A0.1 E1 S1 F{outer_wall_volumetric_speed/2.4}\n M106 P1 S178\n M400 S7\n G1 X-28.5 F18000\n G1 X-48.2 F3000\n G1 X-28.5 F18000 ;wipe and shake\n G1 X-48.2 F3000\n G1 X-28.5 F12000 ;wipe and shake\n G1 X-48.2 F3000\n M400\n M106 P1 S0\nM623 ; end of \"draw extrinsic para cali paint\"\n\n;G392 S0\n;===== auto extrude cali end ========================\n\n;M400\n;M73 P1.717\n\nM104 S170 ; prepare to wipe nozzle\nM106 S255 ; turn on fan\n\n;===== mech mode fast check start =====================\nM1002 gcode_claim_action : 3\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q1 A5 K0 O3\nM974 Q1 S2 P0\n\nM970.2 Q1 K1 W58 Z0.11\nM974 S2\n\nG1 X128 Y128 F20000\nG1 Z5 F1200\nM400 P200\nM970.3 Q0 A10 K0 O1\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X0 Y5\nG28 X ; re-home XY\n\nG1 Z4 F1200\n\n;===== mech mode fast check end =======================\n\n;M400\n;M73 P1.717\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\n\nM975 S1\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\n;===== remove waste by touching start =====\n\nM104 S170 ; set temp down to heatbed acceptable\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nG0 X108 Y-0.5 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X110 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X112 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X114 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X116 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X118 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X120 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X122 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X124 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X126 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X128 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X130 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X132 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X134 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X136 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X138 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X140 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X142 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X144 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X146 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X148 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;===== remove waste by touching end =====\n\nG1 Z10 F1200\nG0 X118 Y261 F30000\nG1 Z5 F1200\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-50}\n\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S140 ; prepare to abl\nG0 Z5 F20000\n\nG0 X128 Y261 F20000 ; move to exposed steel surface\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z10 F1200\n\n;===== brush material wipe nozzle =====\n\nG90\nG1 Y250 F30000\nG1 X55\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X-35 F30000\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Z5.000 F1200\n\nG90\nG1 X30 Y250.000 F30000\nG1 Z1.300 F1200\nG1 Y262.5 F6000\nG91\nG1 X35 F30000\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Y-0.5\nG1 X45\nG1 Y-0.5\nG1 X-45\nG1 Z10.000 F1200\n\n;===== brush material wipe nozzle end =====\n\nG90\n;G0 X128 Y261 F20000 ; move to exposed steel surface\nG1 Y250 F30000\nG1 X138\nG1 Y261\nG0 Z-1.01 F1200 ; stop the nozzle\n\nG91\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nM109 S140\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM211 R; pop softend status\n\n;===== wipe nozzle end ================================\n\n;M400\n;M73 P1.717\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\n\nG90\nG1 Z5 F1200\nG1 X0 Y0 F30000\nG29.2 S1 ; turn on ABL\n\nM190 S[bed_temperature_initial_layer_single]; ensure bed temp\nM109 S140\nM106 S0 ; turn off fan , too noisy\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n\n;===== home after wipe mouth end =======================\n\n;M400\n;M73 P1.717\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; prepare to print\n\n;===== nozzle load line ===============================\n;G90\n;M83\n;G1 Z5 F1200\n;G1 X88 Y-0.5 F20000\n;G1 Z0.3 F1200\n\n;M109 S{nozzle_temperature_initial_layer[initial_extruder]}\n\n;G1 E2 F300\n;G1 X168 E4.989 F6000\n;G1 Z1 F1200\n;===== nozzle load line end ===========================\n\n;===== extrude cali test ===============================\n\nM400\n M900 S\n\n M900 C\n G90\n M83\n G1 X78.000 Y-0.500 F30000\n G1 Z0.300 F1200\n\n M109 S{nozzle_temperature_initial_layer[initial_extruder]}\n G1 E3 F300\n\n G1 X83.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X88.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X93.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X98.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X103.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X108.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X113.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X118.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X123.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X128.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X133.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X138.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X143.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X148.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X153.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X158.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X163.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X168.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X173.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X178.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X179 Z0\n G1 X183\n G1 Z1\n M400\n\n M900 R\n G90\n M83\n G1 X78.000 Y1.000 F30000\n G1 Z0.300 F1200\n G1 E0.5 F300\n G1 X83.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X88.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X93.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X98.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X103.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X108.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X113.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X118.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X123.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X128.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X133.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X138.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X143.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X148.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X153.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X158.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X163.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X168.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X173.000 E0.3118 F{outer_wall_volumetric_speed*0.4 /(0.3*0.5) * 60}\n G1 X178.000 E0.3118 F{outer_wall_volumetric_speed*1.0 /(0.3*0.5) * 60}\n G1 X179 Z0\n G1 X183\n G1 Z1\n M400\n\nG1 Z0.2\n\n;M400\n;M73 P1.717\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\n;G392 S1 ; turn on clog detection\nM1007 S1 ; turn on mass estimation\nG29.4\n", "machine_end_gcode": ";===== date: 20231229 =====================\nG392 S0 ;turn off nozzle clog detect\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X0 Y{first_layer_center_no_wipe_tower[1]} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !spiral_mode && print_sequence != \"by object\"}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X267 F15000\nT255\nG1 X-28.5 F18000\nG1 X-48.2 F3000\nG1 X-28.5 F18000\nG1 X-48.2 F3000\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 256}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z256 F600\n G1 Z256\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-48 Y180 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M40 E42 F20 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C46 D10 M80 E46 F10 N80\nM1006 A44 B20 L100 C39 D20 M60 E48 F20 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A0 B10 L100 C39 D10 M60 E39 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A0 B10 L100 C44 D10 M60 E44 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A0 B10 L100 C39 D10 M60 E39 F10 N60\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N60\nM1006 A0 B10 L100 C48 D10 M60 E44 F10 N80\nM1006 A0 B10 L100 C0 D10 M60 E0 F10 N80\nM1006 A44 B20 L100 C49 D20 M80 E41 F20 N80\nM1006 A0 B20 L100 C0 D20 M60 E0 F20 N80\nM1006 A0 B20 L100 C37 D20 M30 E37 F20 N60\nM1006 W\n;=====printer finish sound=========\n\n;M17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM400\nM18 X Y Z\n\n", "layer_change_gcode": "; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change", - "time_lapse_gcode": ";===================== date: 20231107 =====================\n{if !spiral_mode && print_sequence != \"by object\"}\n; don't support timelapse gcode in spiral_mode and by object sequence for I3 structure printer\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\nG92 E0\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 Z{max_layer_z + 0.4}\nG1 X0 Y{first_layer_center_no_wipe_tower[1]} F18000 ; move to safe pos\nG1 X-48.2 F3000 ; move to safe pos\nM400 P300\nM971 S11 C11 O0\nG92 E0\nG1 X0 F18000\nM623\n\n; enable nozzle clog detect at 3rd layer\n{if layer_num == 2}\n M400\n G90\n M83\n M204 S5000\n G0 Z2 F4000\n G0 X-4.2 Y240 F20000\n M400 P200\n G39 S1\n G0 Z2 F4000\n G0 X128 Y128 F30000\n{endif}\n{endif}", + "time_lapse_gcode": ";===================== date: 20231215 =====================\n{if !spiral_mode && print_sequence != \"by object\"}\n; don't support timelapse gcode in spiral_mode and by object sequence for I3 structure printer\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\nG92 E0\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 Z{max_layer_z + 0.4}\nG1 X0 Y{first_layer_center_no_wipe_tower[1]} F18000 ; move to safe pos\nG1 X-48.2 F3000 ; move to safe pos\nM400 P300\nM971 S11 C11 O0\nG92 E0\nG1 X0 F18000\nM623\n\nM622.1 S1\nM1002 judge_flag g39_detection_flag\nM622 J1 \n ; enable nozzle clog detect at 3rd layer\n {if layer_num == 2}\n M400\n G90\n M83\n M204 S5000\n G0 Z2 F4000\n G0 X261 Y250 F20000\n M400 P200\n G39 S1\n G0 Z2 F4000\n {endif}\n\n {if !in_head_wrap_detect_zone}\n M622.1 S0\n M1002 judge_flag g39_mass_exceed_flag\n M622 J1\n {if layer_num > 2}\n G392 S0\n M400\n G90\n M83\n M204 S5000\n G0 Z{max_layer_z + 0.4} F4000\n G39.3 S1\n G0 Z{max_layer_z + 0.4} F4000\n G392 S0\n {endif}\n M623\n {endif}\nM623\n{endif}\n", "change_filament_gcode": ";===== machine: A1 =========================\n;===== date: 20231225 =======================\nM1007 S0 ; turn off mass estimation\nG392 S0\nM620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1}\nG17\nG2 Z{max_layer_z + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n\nG1 X267 F18000\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nM620.10 A0 F[old_filament_e_feedrate]\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\nM620.10 A1 F[new_filament_e_feedrate] L[flush_length] H[nozzle_diameter] T[nozzle_temperature_range_high]\n\nG1 Y128 F9000\n\n{if next_extruder < 255}\nM400\n\nG92 E0\nM628 S0\n\n{if flush_length_1 > 1}\n; FLUSH_START\n; always use highest temperature to flush\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S[nozzle_temperature_range_high]\nM106 P1 S60\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\nM400\nM1002 set_filament_type:{filament_type[next_extruder]}\n{endif}\n\n{if flush_length_1 > 45 && flush_length_2 > 1}\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n{endif}\n\n{if flush_length_2 > 1}\nM106 P1 S60\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 45 && flush_length_3 > 1}\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n{endif}\n\n{if flush_length_3 > 1}\nM106 P1 S60\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 45 && flush_length_4 > 1}\n; WIPE\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nM400\nM106 P1 S0\n{endif}\n\n{if flush_length_4 > 1}\nM106 P1 S60\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n\nM629\n\nM400\nM106 P1 S60\nM109 S[new_filament_temp]\nG1 E6 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM400\nM106 P1 S178\nM400 S3\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nG1 X-48.2 F3000\nG1 X-38.2 F18000\nM400\nG1 Z{max_layer_z + 3.0} F3000\nM106 P1 S0\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\nG392 S0\n\nM1007 S1\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab A1 mini 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab A1 mini 0.4 nozzle.json index 5673773267..8478b5c818 100644 --- a/resources/profiles/BBL/machine/Bambu Lab A1 mini 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab A1 mini 0.4 nozzle.json @@ -44,8 +44,9 @@ "30" ], "machine_unload_filament_time": "34", + "nozzle_height": "4.76", "nozzle_type": "stainless_steel", - "nozzle_volume": "32", + "nozzle_volume": "92", "printable_area": [ "0x0", "180x0", @@ -66,7 +67,7 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: A1 mini =========================\n;===== date: 20231226 =====================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM104 S170\nM140 S[bed_temperature_initial_layer_single]\nG392 S0 ;turn off clog detect\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S2 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM290 X39 Y39 Z8\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S[nozzle_temperature_initial_layer]\n M104 S250\n M400\n T[initial_no_support_extruder]\n G1 X-13.5 F3000\n M400\n M620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n M104 S{nozzle_temperature_range_high[initial_no_support_extruder]}\n G92 E0\n G1 E50 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-40}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-40}\n G392 S0 ;turn off clog detect\nM621 S[initial_no_support_extruder]A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S[bed_temperature_initial_layer_single];set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{nozzle_temperature[initial_extruder]}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n \n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.2 F18000 ;Move to start position\n M400\n G0 X88 E10 F{outer_wall_volumetric_speed/(24/20) * 60}\n G0 X93 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 X98 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X103 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 X108 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X113 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 Y0 Z0 F20000\n M400\n \n G1 X-13.5 Y0 Z10 F10000\n M400\n \n G1 E10 F{outer_wall_volumetric_speed/2.4*60}\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n \n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{outer_wall_volumetric_speed/2.4}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n;===== extrude cali test ===============================\nM104 S{nozzle_temperature_initial_layer[initial_extruder]}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.2 F18000 ;Move to start position\nG0 X88 E10 F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X93 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X98 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 X103 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X108 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 X113 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n", + "machine_start_gcode": ";===== machine: A1 mini =========================\n;===== date: 20240204 =====================\n\n;===== start to heat heatbead&hotend==========\nM1002 gcode_claim_action : 2\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\nM104 S170\nM140 S[bed_temperature_initial_layer_single]\nG392 S0 ;turn off clog detect\n;=====start printer sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A0 B0 L100 C37 D10 M100 E37 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E43 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C41 D10 M100 E41 F10 N100\nM1006 A0 B0 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C49 D10 M100 E49 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C39 D10 M100 E48 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B0 L100 C39 D10 M100 E44 F10 N100\nM1006 A0 B0 L100 C0 D10 M100 E0 F10 N100\nM1006 A43 B10 L100 C39 D10 M100 E46 F10 N100\nM1006 W\nM18\n;=====avoid end stop =================\nG91\nG380 S2 Z30 F1200\nG380 S3 Z-20 F1200\nG1 Z5 F1200\nG90\n\n;===== reset machine status =================\nM204 S6000\n\nM630 S0 P0\nG91\nM17 Z0.3 ; lower the z-motor current\n\nG90\nM17 X0.7 Y0.9 Z0.5 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM83\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== prepare print temperature and material ==========\nM400\nM18\nM109 S100 H170\nM104 S170\nM400\nM17\nM400\nG28 X\n\nM211 X0 Y0 Z0 ;turn off soft endstop ; turn off soft endstop to prevent protential logic problem\n\nM975 S1 ; turn on\n\nG1 X0.0 F30000\nG1 X-13.5 F3000\n\nM620 M ;enable remap\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n G392 S0 ;turn on clog detect\n M1002 gcode_claim_action : 4\n M400\n M1002 set_filament_type:UNKNOWN\n M109 S[nozzle_temperature_initial_layer]\n M104 S250\n M400\n T[initial_no_support_extruder]\n G1 X-13.5 F3000\n M400\n M620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n M109 S250 ;set nozzle to common flush temp\n M106 P1 S0\n G92 E0\n G1 E50 F200\n M400\n M1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n M104 S{nozzle_temperature_range_high[initial_no_support_extruder]}\n G92 E0\n G1 E50 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n M400\n M106 P1 S178\n G92 E0\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-40}\n G92 E0\n G1 E-0.5 F300\n\n G1 X0 F30000\n G1 X-13.5 F3000\n G1 X0 F30000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X0 F30000\n G1 X-13.5 F3000\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-40}\n G392 S0 ;turn off clog detect\nM621 S[initial_no_support_extruder]A\n\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== mech mode fast check============================\nM1002 gcode_claim_action : 3\nG0 X25 Y175 F20000 ; find a soft place to home\n;M104 S0\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nM104 S170\n\n; build plate detect\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n G39.4\n M400\nM623\n\nG1 Z5 F3000\nG1 X90 Y-1 F30000\nM400 P200\nM970.3 Q1 A7 K0 O2\nM974 Q1 S2 P0\n\nG1 X90 Y0 Z5 F30000\nM400 P200\nM970 Q0 A10 B50 C90 H15 K0 M20 O3\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X-1 Y10\nG28 X ; re-home XY\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\n\nM104 S170 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\nM211 S; push soft endstop status\nM211 X0 Y0 Z0 ;turn off Z axis endstop\n\nM83\nG1 E-1 F500\nG90\nM83\n\nM109 S170\nM104 S140\nG0 X90 Y-4 F30000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X91 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X92 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X93 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X94 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X95 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X96 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X97 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X98 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\nG1 Z2 F1200\nG1 X99 F10000\nG380 S3 Z-5 F1200\n\nG1 Z5 F30000\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5 F3000\nG0 X50 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG0 X85 Y185 F10000 ;move to exposed steel surface and stop the nozzle\nG0 Z-1.01 F10000\nG91\n\nG2 I1 J0 X2 Y0 F2000.1\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\nG2 I1 J0 X2\nG2 I-0.75 J0 X-1.5\n\nG90\nG1 Z5 F30000\nG1 X25 Y175 F30000.1 ;Brush material\nG1 Z0.2 F30000.1\nG1 Y185\nG91\nG1 X-30 F30000\nG1 Y-2\nG1 X27\nG1 Y1.5\nG1 X-28\nG1 Y-2\nG1 X30\nG1 Y1.5\nG1 X-30\nG90\nM83\n\nG1 Z5\nG0 X55 Y175 F20000 ; find a soft place to home\nG28 Z P0 T300; home z with low precision, permit 300deg temperature\nG29.2 S0 ; turn off ABL\n\nG1 Z10\nG1 X85 Y185\nG1 Z-1.01\nG1 X95\nG1 X90\n\nM211 R; pop softend status\n\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== wait heatbed ====================\nM1002 gcode_claim_action : 2\nM104 S0\nM190 S[bed_temperature_initial_layer_single];set bed temp\nM109 S140\n\nG1 Z5 F3000\nG29.2 S1\nG1 X10 Y10 F20000\n\n;===== bed leveling ==================================\n;M1002 set_flag g29_before_print_flag=1\nM1002 judge_flag g29_before_print_flag\nM622 J1\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28 T145\n\nM623\n\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\n\nG1 X-13.5 Y0 Z10 F10000\nG1 E1.2 F500\nM400\nM1002 set_filament_type:UNKNOWN\nM109 S{nozzle_temperature[initial_extruder]}\nM400\n\nM412 S1 ; ===turn on filament runout detection===\nM400 P10\n\nG392 S0 ;turn on clog detect\n\nM620.3 W1; === turn on filament tangle detection===\nM400 S2\n\nM1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n;M1002 set_flag extrude_cali_flag=1\nM1002 judge_flag extrude_cali_flag\nM622 J1\n M1002 gcode_claim_action : 8\n \n M400\n M900 K0.0 L1000.0 M1.0\n G90\n M83\n G0 X68 Y-4 F30000\n G0 Z0.2 F18000 ;Move to start position\n M400\n G0 X88 E10 F{outer_wall_volumetric_speed/(24/20) * 60}\n G0 X93 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 X98 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X103 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 X108 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X113 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\n G0 Y0 Z0 F20000\n M400\n \n G1 X-13.5 Y0 Z10 F10000\n M400\n \n G1 E10 F{outer_wall_volumetric_speed/2.4*60}\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\n M1002 judge_last_extrude_cali_success\n M622 J0\n M983 F{outer_wall_volumetric_speed/2.4} A0.3 H[nozzle_diameter]; cali dynamic extrusion compensation\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n M400\n M106 P1 S0\n M623\n \n G1 X-13.5 F3000\n M400\n M984 A0.1 E1 S1 F{outer_wall_volumetric_speed/2.4}\n M106 P1 S178\n M400 S7\n G1 X0 F18000\n G1 X-13.5 F3000\n G1 X0 F18000 ;wipe and shake\n G1 X-13.5 F3000\n G1 X0 F12000 ;wipe and shake\n G1 X-13.5 F3000\n M400\n M106 P1 S0\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n;===== extrude cali test ===============================\nM104 S{nozzle_temperature_initial_layer[initial_extruder]}\nG90\nM83\nG0 X68 Y-2.5 F30000\nG0 Z0.2 F18000 ;Move to start position\nG0 X88 E10 F{outer_wall_volumetric_speed/(24/20) * 60}\nG0 X93 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X98 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 X103 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X108 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 X113 E.3742 F{outer_wall_volumetric_speed/(0.3*0.5)/4 * 60}\nG0 X115 Z0 F20000\nG0 Z5\nM400\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\n\nM400 ; wait all motion done before implement the emprical L parameters\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.02} ; for Textured PEI Plate\n{endif}\n\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\n\nM211 X0 Y0 Z0 ;turn off soft endstop\nM1007 S1\n\n\n\n", "machine_end_gcode": ";===== date: 20231229 =====================\n;turn off nozzle clog detect\nG392 S0\n\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X0 Y{first_layer_center_no_wipe_tower[1]} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\n{if !spiral_mode && print_sequence != \"by object\"}\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM400 P100\nM971 S11 C11 O0\nM991 S0 P-1 ;end timelapse at safe pos\nM623\n{endif}\n\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n;G1 X27 F15000 ; wipe\n\n; pull back filament to AMS\nM620 S255\nG1 X181 F12000\nT255\nG1 X0 F18000\nG1 X-13.0 F3000\nG1 X0 F18000 ; wipe\nM621 S255\n\nM104 S0 ; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 180}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z180 F600\n G1 Z180\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X-13 Y180 F3600\n\nG91\nG1 Z-1 F600\nG90\nM83\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A0 B20 L100 C37 D20 M100 E42 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C46 D10 M100 E46 F10 N100\nM1006 A44 B20 L100 C39 D20 M100 E48 F20 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C44 D10 M100 E44 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A0 B10 L100 C39 D10 M100 E39 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B10 L100 C0 D10 M100 E48 F10 N100\nM1006 A0 B10 L100 C0 D10 M100 E0 F10 N100\nM1006 A44 B20 L100 C41 D20 M100 E49 F20 N100\nM1006 A0 B20 L100 C0 D20 M100 E0 F20 N100\nM1006 A0 B20 L100 C37 D20 M100 E37 F20 N100\nM1006 W\n;=====printer finish sound=========\nM400 S1\nM18 X Y Z\n", "layer_change_gcode": "; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change\n", "time_lapse_gcode": ";===================== date: 202312028 =====================\n{if !spiral_mode && print_sequence != \"by object\"}\n; don't support timelapse gcode in spiral_mode and by object sequence for I3 structure printer\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\nG92 E0\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 Z{max_layer_z + 0.4}\nG1 X0 Y{first_layer_center_no_wipe_tower[1]} F18000 ; move to safe pos\nG1 X-13.0 F3000 ; move to safe pos\nM400 P300\nM971 S11 C11 O0\nG92 E0\nG1 X0 F18000\nM623\n\nM622.1 S1\nM1002 judge_flag g39_detection_flag\nM622 J1\n ; enable nozzle clog detect at 3rd layer\n {if layer_num == 2}\n M400\n G90\n M83\n M204 S5000\n G0 Z2 F4000\n G0 X-6 Y170 F20000\n G39 S1 X-6 Y170\n G0 Z2 F4000\n G0 X90 Y90 F30000\n {endif}\n\n\n {if !in_head_wrap_detect_zone}\n M622.1 S0\n M1002 judge_flag g39_mass_exceed_flag\n M622 J1\n {if layer_num > 2}\n G392 S0\n M400\n G90\n M83\n M204 S5000\n G0 Z{max_layer_z + 0.4} F4000\n G39.3 S1\n G0 Z{max_layer_z + 0.4} F4000\n G392 S0\n {endif}\n M623\n {endif}\nM623\n{endif}\n", diff --git a/resources/profiles/BBL/machine/Bambu Lab P1P 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1P 0.2 nozzle.json index 62526620ef..b1219b59df 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1P 0.2 nozzle.json @@ -30,5 +30,5 @@ "Bambu Lab X1E 0.2 nozzle", "Bambu Lab A1 0.2 nozzle" ], - "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z-0.04 ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" + "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z-0.04 ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json index d7e4726a40..b39a7e0250 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json @@ -21,11 +21,13 @@ "Bambu PLA Basic @BBL X1" ], "default_print_profile": "0.20mm Standard @BBL P1P", + "enable_long_retraction_when_cut" : "1", "extruder_offset": [ "0x2" ], "machine_load_filament_time": "29", "machine_unload_filament_time": "28", + "nozzle_height": "4.2", "nozzle_type": "stainless_steel", "scan_first_layer": "0", "upward_compatible_machine": [ @@ -35,7 +37,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression", + "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression", + "machine_end_gcode": ";===== date: 20230428 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n", "layer_change_gcode": "; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n{if timelapse_type == 0} ; timelapse without wipe tower\nM971 S11 C10 O0\n{elsif timelapse_type == 1} ; timelapse with wipe tower\nG92 E0\nG1 E-[retraction_length] F1800\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 X65 Y245 F20000 ; move to safe pos\nG17\nG2 Z{layer_z} I0.86 J0.86 P1 F20000\nG1 Y265 F3000\nM400 P300\nM971 S11 C11 O0\nG92 E0\nG1 E[retraction_length] F300\nG1 X100 F5000\nG1 Y255 F20000\n{endif}\nM623\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change", - "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n\nG92 E0\n{if flush_length_1 > 1}\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S220\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\n{if (flush_length_2 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_3 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_4 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" + "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E-[retraction_distance_when_cut] F200\nM400\n{endif}\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E{retraction_distance_when_cut - 2} F200\nG1 E2 F20\nM400\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S260\n{elsif filament_type[next_extruder] == \"PVA\"}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1P 0.6 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1P 0.6 nozzle.json index 528dcad10f..e3952a891e 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1P 0.6 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab A1 0.6 nozzle" ], - "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X18 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" + "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X18 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1P 0.8 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1P 0.8 nozzle.json index 1ae5c22b3a..3364e0744f 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1P 0.8 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.8 nozzle", "Bambu Lab A1 0.8 nozzle" ], - "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y15 E1.500 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.500\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X18 E15\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" + "machine_start_gcode": ";===== machine: P1P ========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y15 E1.500 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.500\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X18 E15\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1S 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1S 0.2 nozzle.json index 8e021245c2..45ce15c990 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1S 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1S 0.2 nozzle.json @@ -30,5 +30,5 @@ "Bambu Lab X1E 0.2 nozzle", "Bambu Lab A1 0.2 nozzle" ], - "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z-0.04 ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" + "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z-0.04 ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1S 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1S 0.4 nozzle.json index 8da15f1add..a5a55c74ed 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1S 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1S 0.4 nozzle.json @@ -20,11 +20,13 @@ "Bambu PLA Basic @BBL X1C" ], "default_print_profile": "0.20mm Standard @BBL X1C", + "enable_long_retraction_when_cut" : "1", "extruder_offset": [ "0x2" ], "machine_load_filament_time": "29", "machine_unload_filament_time": "28", + "nozzle_height": "4.2", "nozzle_type": "stainless_steel", "scan_first_layer": "0", "upward_compatible_machine": [ @@ -34,7 +36,8 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n", + "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n", + "machine_end_gcode": ";===== date: 20230428 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n", "layer_change_gcode": "; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n{if timelapse_type == 0} ; timelapse without wipe tower\nM971 S11 C10 O0\n{elsif timelapse_type == 1} ; timelapse with wipe tower\nG92 E0\nG1 E-[retraction_length] F1800\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 X65 Y245 F20000 ; move to safe pos\nG17\nG2 Z{layer_z} I0.86 J0.86 P1 F20000\nG1 Y265 F3000\nM400 P300\nM971 S11 C11 O0\nG92 E0\nG1 E[retraction_length] F300\nG1 X100 F5000\nG1 Y255 F20000\n{endif}\nM623\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change", - "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n\nG92 E0\n{if flush_length_1 > 1}\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S220\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\n{if (flush_length_2 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_3 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_4 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" + "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E-[retraction_distance_when_cut] F200\nM400\n{endif}\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E{retraction_distance_when_cut - 2} F200\nG1 E2 F20\nM400\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S260\n{elsif filament_type[next_extruder] == \"PVA\"}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1S 0.6 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1S 0.6 nozzle.json index 058eae33f2..195857d3ee 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1S 0.6 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1S 0.6 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab A1 0.6 nozzle" ], - "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X18 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" + "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ;turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X18 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab P1S 0.8 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab P1S 0.8 nozzle.json index ae628412cd..0db7e015bb 100644 --- a/resources/profiles/BBL/machine/Bambu Lab P1S 0.8 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab P1S 0.8 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.8 nozzle", "Bambu Lab A1 0.8 nozzle" ], - "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ; turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y15 E1.500 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.500\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X18 E15\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" + "machine_start_gcode": ";===== machine: P1S ========================\n;===== date: 20231107 =====================\n;===== turn on the HB fan & MC board fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\nM710 A1 S255 ; turn on MC fan by default(P1S)\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X230 Y15\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_extruder]==\"PLA\"}\n {if (bed_temperature[initial_extruder] >45)||(bed_temperature_initial_layer[initial_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_extruder] >50)||(bed_temperature_initial_layer[initial_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n\nM104 S{nozzle_temperature_initial_layer[initial_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== fmech mode fast check============================\n\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y15 E1.500 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.500\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X18 E15\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 0.2 nozzle.json index af54617e2d..a5196e5c75 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 0.2 nozzle.json @@ -30,5 +30,5 @@ "Bambu Lab X1E 0.2 nozzle", "Bambu Lab A1 0.2 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 0.4 nozzle.json index 22c7cf476d..4b96419d2f 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 0.4 nozzle.json @@ -21,11 +21,13 @@ "Bambu PLA Basic @BBL X1" ], "default_print_profile": "0.20mm Standard @BBL X1C", + "enable_long_retraction_when_cut": "2", "extruder_offset": [ "0x2" ], "machine_load_filament_time": "29", "machine_unload_filament_time": "28", + "nozzle_height": "4.2", "nozzle_type": "stainless_steel", "scan_first_layer": "1", "upward_compatible_machine": [ @@ -35,6 +37,7 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4", - "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n\nG92 E0\n{if flush_length_1 > 1}\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S220\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\n{if (flush_length_2 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_3 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_4 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4", + "machine_end_gcode": ";===== date: 20240402 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM960 S5 P0 ; turn off logo lamp\n\n", + "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S260\n{elsif filament_type[next_extruder] == \"PVA\"}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 0.6 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 0.6 nozzle.json index 34b6e1894c..74f5b0e3b9 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 0.6 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 0.6 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab A1 0.6 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 0.8 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 0.8 nozzle.json index 06b1cdc2a1..9741939bda 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 0.8 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 0.8 nozzle.json @@ -34,5 +34,5 @@ "Bambu Lab X1E 0.8 nozzle", "Bambu Lab A1 0.8 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== nozzle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.2 nozzle.json index 61bdacbbdf..115fab918a 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.2 nozzle.json @@ -31,5 +31,5 @@ "Bambu Lab X1E 0.2 nozzle", "Bambu Lab A1 0.2 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230824 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.4 nozzle.json index 5b13c5adba..d64d979208 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.4 nozzle.json @@ -20,11 +20,13 @@ "Bambu PLA Basic @BBL X1C" ], "default_print_profile": "0.20mm Standard @BBL X1C", + "enable_long_retraction_when_cut": "2", "extruder_offset": [ "0x2" ], "machine_load_filament_time": "29", "machine_unload_filament_time": "28", + "nozzle_height": "4.2", "scan_first_layer": "1", "upward_compatible_machine": [ "Bambu Lab P1S 0.4 nozzle", @@ -33,6 +35,7 @@ "Bambu Lab X1E 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4", - "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n\nG92 E0\n{if flush_length_1 > 1}\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S220\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\n{if (flush_length_2 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_3 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\n{if (flush_length_4 > 1) && (filament_type[next_extruder]==\"PLA-CF\" || filament_type[next_extruder]==\"PETG\")}\nM106 P1 S255\nM400 S3\nM106 P1 S0\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y245 F21000\nG1 X65 \nG1 Y265 F3000\n{endif}\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\nG1 X80 F15000\nG1 X60 F15000\nG1 X80 F15000\nG1 X60 F15000; shake to put down garbage\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230824 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4", + "machine_end_gcode": ";===== date: 20240402 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM960 S5 P0 ; turn off logo lamp\n\n", + "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E-{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\n{else}\nM620.11 S0\n{endif}\nM400\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\n{if long_retractions_when_cut[previous_extruder]}\nM620.11 S1 I[previous_extruder] E{retraction_distances_when_cut[previous_extruder]} F{old_filament_e_feedrate}\nM628 S1\nG92 E0\nG1 E{retraction_distances_when_cut[previous_extruder]} F[old_filament_e_feedrate]\nM400\nM629 S1\n{else}\nM620.11 S0\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S260\n{elsif filament_type[next_extruder] == \"PVA\"}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.6 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.6 nozzle.json index eb4bd945b0..0ed084037f 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.6 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.6 nozzle.json @@ -33,5 +33,5 @@ "Bambu Lab X1E 0.6 nozzle", "Bambu Lab A1 0.6 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230824 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.8 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.8 nozzle.json index 84fb5a17fd..46ab176b0d 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.8 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon 0.8 nozzle.json @@ -33,5 +33,5 @@ "Bambu Lab X1E 0.8 nozzle", "Bambu Lab A1 0.8 nozzle" ], - "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230707 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1 =========================\n;===== date: 20230824 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S250 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon.json b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon.json index 8407b6e270..3b36361af0 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1 Carbon.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1 Carbon.json @@ -4,7 +4,7 @@ "nozzle_diameter": "0.4;0.2;0.6;0.8", "bed_model": "bbl-3dp-X1.stl", "bed_texture": "bbl-3dp-logo.svg", - "default_bed_type": "Cool Plate", + "default_bed_type": "Textured PEI Plate", "family": "BBL-3DP", "machine_tech": "FFF", "model_id": "BL-P001", diff --git a/resources/profiles/BBL/machine/Bambu Lab X1.json b/resources/profiles/BBL/machine/Bambu Lab X1.json index aca4485aee..d8e4794eab 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1.json @@ -4,7 +4,7 @@ "nozzle_diameter": "0.4;0.2;0.6;0.8", "bed_model": "bbl-3dp-X1.stl", "bed_texture": "bbl-3dp-logo.svg", - "default_bed_type": "Cool Plate", + "default_bed_type": "Textured PEI Plate", "family": "BBL-3DP", "machine_tech": "FFF", "model_id": "BL-P002", diff --git a/resources/profiles/BBL/machine/Bambu Lab X1E 0.2 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1E 0.2 nozzle.json index a81d539114..1799d2773a 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1E 0.2 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1E 0.2 nozzle.json @@ -31,5 +31,5 @@ "Bambu Lab X1 Carbon 0.2 nozzle", "Bambu Lab A1 0.2 nozzle" ], - "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z200\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z75\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n\t{if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.160\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.080\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.080 K0.160\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.08 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.08}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1E 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1E 0.4 nozzle.json index bcbcca7a0f..99f878f4fc 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1E 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1E 0.4 nozzle.json @@ -20,11 +20,13 @@ "Bambu PLA Basic @BBL X1C" ], "default_print_profile": "0.20mm Standard @BBL X1C", + "enable_long_retraction_when_cut": "1", "extruder_offset": [ "0x2" ], "machine_load_filament_time": "29", "machine_unload_filament_time": "28", + "nozzle_height": "4.2", "scan_first_layer": "1", "support_air_filtration": "1", "support_chamber_temp_control": "1", @@ -35,6 +37,7 @@ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab A1 0.4 nozzle" ], - "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z200\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4\n\n", - "machine_end_gcode": ";===== date: 20230428 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM141 S0 ; turn off chamber \nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nG90\nG1 X128 Y250 F3600\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\n" + "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z75\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y11 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E0.700\nG0 X231 E0.700 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n T1000\n\n G0 F1200.0 X231 Y15 Z0.2 E0.741\n G0 F1200.0 X226 Y15 Z0.2 E0.275\n G0 F1200.0 X226 Y8 Z0.2 E0.384\n G0 F1200.0 X216 Y8 Z0.2 E0.549\n G0 F1200.0 X216 Y1.5 Z0.2 E0.357\n\n G0 X48.0 E12.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E0.92 F1200.0\n G0 X35.0 Y6.0 E1.03 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E9.35441 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.040\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.020\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E14.3 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.020 K0.040\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E1.24726 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.02 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.02}\n M623\n\n G1 X140.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.31181 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4\n\n", + "machine_end_gcode": ";===== date: 20240402 =====================\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\nG1 X65 Y245 F12000 ; move to safe pos \nG1 Y265 F3000\n\nG1 X65 Y245 F12000\nG1 Y265 F3000\nM141 S0 ; turn off chamber \nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\nG1 X100 F12000 ; wipe\n; pull back filament to AMS\nM620 S255\nG1 X20 Y50 F12000\nG1 Y-3\nT255\nG1 X65 F12000\nG1 Y265\nG1 X100 F12000 ; wipe\nM621 S255\nM104 S0 ; turn off hotend\n\nM622.1 S1 ; for prev firware, default turned on\nM1002 judge_flag timelapse_record_flag\nM622 J1\n M400 ; wait all motion done\n M991 S0 P-1 ;end smooth timelapse at safe pos\n M400 S3 ;wait for last picture to be taken\nM623; end of \"timelapse_record_flag\"\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 250}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z250 F600\n G1 Z248\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM17 X0.8 Y0.8 Z0.5 ; lower motor current to 45% power\nM960 S5 P0 ; turn off logo lamp\n\n", + "change_filament_gcode": "M620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\nG1 Z{max_layer_z + 3.0} F1200\n\nG1 X70 F21000\nG1 Y245\nG1 Y265 F3000\nM400\nM106 P1 S0\nM106 P2 S0\n{if old_filament_temp > 142 && next_extruder < 255}\nM104 S[old_filament_temp]\n{endif}\nG1 X90 F3000\nG1 Y255 F4000\nG1 X100 F5000\nG1 X120 F15000\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E-[retraction_distance_when_cut] F200\nM400\n{endif}\nG1 X20 Y50 F21000\nG1 Y-3\n{if toolchange_count == 2}\n; get travel path for change filament\nM620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\nM620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\nM620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\nM620.1 E F[old_filament_e_feedrate] T{nozzle_temperature_range_high[previous_extruder]}\nT[next_extruder]\nM620.1 E F[new_filament_e_feedrate] T{nozzle_temperature_range_high[next_extruder]}\n\n{if next_extruder < 255}\nM400\n{if long_retraction_when_cut && retraction_distance_when_cut > 2}\nG1 E{retraction_distance_when_cut - 2} F200\nG1 E2 F20\nM400\n{endif}\nG92 E0\n{if flush_length_1 > 1}\nM83\n; FLUSH_START\n; always use highest temperature to flush\nM400\n{if filament_type[next_extruder] == \"PETG\"}\nM109 S260\n{elsif filament_type[next_extruder] == \"PVA\"}\nM109 S210\n{else}\nM109 S[nozzle_temperature_range_high]\n{endif}\n{if flush_length_1 > 23.7}\nG1 E23.7 F{old_filament_e_feedrate} ; do not need pulsatile flushing for start part\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{old_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\nG1 E{(flush_length_1 - 23.7) * 0.02} F50\nG1 E{(flush_length_1 - 23.7) * 0.23} F{new_filament_e_feedrate}\n{else}\nG1 E{flush_length_1} F{old_filament_e_feedrate}\n{endif}\n; FLUSH_END\nG1 E-[old_retract_length_toolchange] F1800\nG1 E[old_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_2 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\nG1 E{flush_length_2 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_2 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_3 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\nG1 E{flush_length_3 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_3 * 0.02} F50\n; FLUSH_END\nG1 E-[new_retract_length_toolchange] F1800\nG1 E[new_retract_length_toolchange] F300\n{endif}\n\n{if flush_length_4 > 1}\n\nG91\nG1 X3 F12000; move aside to extrude\nG90\nM83\n\n; FLUSH_START\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\nG1 E{flush_length_4 * 0.18} F{new_filament_e_feedrate}\nG1 E{flush_length_4 * 0.02} F50\n; FLUSH_END\n{endif}\n; FLUSH_START\nM400\nM109 S[new_filament_temp]\nG1 E2 F{new_filament_e_feedrate} ;Compensate for filament spillage during waiting temperature\n; FLUSH_END\nM400\nG92 E0\nG1 E-[new_retract_length_toolchange] F1800\nM106 P1 S255\nM400 S3\n\nG1 X70 F5000\nG1 X90 F3000\nG1 Y255 F4000\nG1 X105 F5000\nG1 Y265 F5000\nG1 X70 F10000\nG1 X100 F5000\nG1 X70 F10000\nG1 X100 F5000\n\nG1 X70 F10000\nG1 X80 F15000\nG1 X60\nG1 X80\nG1 X60\nG1 X80 ; shake to put down garbage\nG1 X100 F5000\nG1 X165 F15000; wipe and shake\nG1 Y256 ; move Y to aside, prevent collision\nM400\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1E 0.6 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1E 0.6 nozzle.json index 4ccc2d081b..6e116866e5 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1E 0.6 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1E 0.6 nozzle.json @@ -33,5 +33,5 @@ "Bambu Lab X1 Carbon 0.6 nozzle", "Bambu Lab A1 0.6 nozzle" ], - "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z200\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z75\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y1.0 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X240 E25 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nG0 Y15 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\nG0 X239.5\nG0 E0.2\nG0 Y1.5 E1.166\nG0 X231 E1.166 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.333\n G0 F1200.0 X226 Y15 Z0.2 E0.495\n G0 F1200.0 X226 Y8 Z0.2 E0.691\n G0 F1200.0 X216 Y8 Z0.2 E0.988\n G0 F1200.0 X216 Y1.5 Z0.2 E0.642\n\n G0 X48.0 E20.56 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.56 F1200.0\n G0 X35.0 Y6.0 E1.75 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X185.000 E16.9 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.030\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.015\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.9) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X18 E23.9 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.015 K0.030\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.25000 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X70.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X75.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X80.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X85.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X90.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X95.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X100.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X105.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X110.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X115.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X120.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X125.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X130.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X135.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.015 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*0.015}\n M623\n\n G1 X140.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X145.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X150.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X155.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X160.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X165.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X170.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X175.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X180.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X185.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X190.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X195.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X200.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X205.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X210.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X215.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G1 X220.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5)/ 4 * 60}\n G1 X225.000 E0.56250 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/Bambu Lab X1E 0.8 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab X1E 0.8 nozzle.json index 3d3a04e2a1..eea8eab1a0 100644 --- a/resources/profiles/BBL/machine/Bambu Lab X1E 0.8 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab X1E 0.8 nozzle.json @@ -33,5 +33,5 @@ "Bambu Lab X1 Carbon 0.8 nozzle", "Bambu Lab A1 0.8 nozzle" ], - "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z200\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" + "machine_start_gcode": ";===== machine: X1E =========================\n;===== date: 20230815 =====================\n;===== turn on the HB fan =================\nM104 S75 ;set extruder temp to turn on the HB fan and prevent filament oozing from nozzle\n;===== reset machine status =================\nM290 X40 Y40 Z2.6666666\nG91\nM17 Z0.4 ; lower the z-motor current\nG380 S2 Z30 F300 ; G380 is same as G38; lower the hotbed , to prevent the nozzle is below the hotbed\nG380 S2 Z-25 F300 ;\nG1 Z5 F300;\nG90\nM17 X1.2 Y1.2 Z0.75 ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 5\nM221 X0 Y0 Z0 ; turn off soft endstop to prevent protential logic problem\nG29.1 Z{+0.0} ; clear z-trim value first\nM204 S10000 ; init ACC set to 10m/s^2\n\n;==== if Chamber Cooling is necessary ==== \n\n{if (filament_type[initial_no_support_extruder]==\"PLA\") || (filament_type[initial_no_support_extruder]==\"PETG\") || (filament_type[initial_no_support_extruder]==\"TPU\") || (filament_type[initial_no_support_extruder]==\"PVA\") || (filament_type[initial_no_support_extruder]==\"PLA-CF\") || (filament_type[initial_no_support_extruder]==\"PETG-CF\")}\nM1002 gcode_claim_action : 29\nG28\nG90\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nG1 Z75\nM140 S0 ; stop heatbed from heating\nM106 P2 S255 ; open auxiliary fan for cooling\nM106 P3 S255 ; open chamber fan for cooling\nM191 S0 ; wait for chamber temp\nM106 P3 S0 ; reset chamber fan cmd\nM106 P2 S0; reset auxiliary fan cmd\n{endif}\n\n;===== heatbed preheat ====================\nM1002 gcode_claim_action : 2\nM140 S[bed_temperature_initial_layer_single] ;set bed temp\nM190 S[bed_temperature_initial_layer_single] ;wait for bed temp\n\n{if scan_first_layer}\n;=========register first layer scan=====\nM977 S1 P60\n{endif}\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\n;===== prepare print temperature and material ==========\nM104 S[nozzle_temperature_initial_layer] ;set extruder temp\nG91\nG0 Z10 F1200\nG90\nG28 X\nM975 S1 ; turn on\nG1 X60 F12000\nG1 Y245\nG1 Y265 F3000\nM620 M\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\n M109 S[nozzle_temperature_initial_layer]\n G1 X120 F12000\n\n G1 X20 Y50 F12000\n G1 Y-3\n T[initial_no_support_extruder]\n G1 X54 F12000\n G1 Y265\n M400\nM621 S[initial_no_support_extruder]A\nM620.1 E F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} T{nozzle_temperature_range_high[initial_no_support_extruder]}\n\n\nM412 S1 ; ===turn on filament runout detection===\n\nM109 S290 ;set nozzle to common flush temp\nM106 P1 S0\nG92 E0\nG1 E50 F200\nM400\nM104 S[nozzle_temperature_initial_layer]\nG92 E0\nG1 E50 F200\nM400\nM106 P1 S255\nG92 E0\nG1 E5 F300\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20} ; drop nozzle temp, make filament shink a bit\nG92 E0\nG1 E-0.5 F300\n\nG1 X70 F9000\nG1 X76 F15000\nG1 X65 F15000\nG1 X76 F15000\nG1 X65 F15000; shake to put down garbage\nG1 X80 F6000\nG1 X95 F15000\nG1 X80 F15000\nG1 X165 F15000; wipe and shake\nM400\nM106 P1 S0\n\n;===== set chamber temperature ==========\n{if (overall_chamber_temperature >= 40)}\nM106 P2 S255 ; open big fan to help heating\nM141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n{endif}\n\n;===== prepare print temperature and material end =====\n\n\n;===== wipe nozzle ===============================\nM1002 gcode_claim_action : 14\nM975 S1\nM106 S255\nG1 X65 Y230 F18000\nG1 Y264 F6000\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-20}\nG1 X100 F18000 ; first wipe mouth\n\nG0 X135 Y253 F20000 ; move to exposed steel surface edge\nG28 Z P0 T300; home z with low precision,permit 300deg temperature\nG29.2 S0 ; turn off ABL\nG0 Z5 F20000\n\nG1 X60 Y265\nG92 E0\nG1 E-0.5 F300 ; retrack more\nG1 X100 F5000; second wipe mouth\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X100 F5000\nG1 X70 F15000\nG1 X90 F5000\nG0 X128 Y261 Z-1.5 F20000 ; move to exposed steel surface and stop the nozzle\nM104 S140 ; set temp down to heatbed acceptable\nM106 S255 ; turn on fan (G28 has turn off fan)\n\nM221 S; push soft endstop status\nM221 Z0 ;turn off Z axis endstop\nG0 Z0.5 F20000\nG0 X125 Y259.5 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y262.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y260.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.5\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 Z0.5 F20000\nG0 X125 Y261.0\nG0 Z-1.01\nG0 X131 F211\nG0 X124\nG0 X128\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\nG2 I0.5 J0 F300\n\nM109 S140 ; wait nozzle temp down to heatbed acceptable\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\nG2 I0.5 J0 F3000\n\nM221 R; pop softend status\nG1 Z10 F1200\nM400\nG1 Z10\nG1 F30000\nG1 X128 Y128\nG29.2 S1 ; turn on ABL\n;G28 ; home again after hard wipe mouth\nM106 S0 ; turn off fan , too noisy\n;===== wipe nozzle end ================================\n\n;===== check scanner clarity ===========================\nG1 X128 Y128 F24000\nG28 Z P0\nM972 S5 P0\nG1 X230 Y15 F24000\n;===== check scanner clarity end =======================\n\n;===== bed leveling ==================================\nM1002 judge_flag g29_before_print_flag\nM622 J1\n\n M1002 gcode_claim_action : 1\n G29 A X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]}\n M400\n M500 ; save cali data\n\nM623\n;===== bed leveling end ================================\n\n;===== home after wipe mouth============================\nM1002 judge_flag g29_before_print_flag\nM622 J0\n\n M1002 gcode_claim_action : 13\n G28\n\nM623\n;===== home after wipe mouth end =======================\n\nM975 S1 ; turn on vibration supression\n\n;=============turn on fans to prevent PLA jamming=================\n{if filament_type[initial_no_support_extruder]==\"PLA\"}\n {if (bed_temperature[initial_no_support_extruder] >45)||(bed_temperature_initial_layer[initial_no_support_extruder] >45)}\n M106 P3 S180\n {elsif (bed_temperature[initial_no_support_extruder] >50)||(bed_temperature_initial_layer[initial_no_support_extruder] >50)}\n M106 P3 S255\n {endif};Prevent PLA from jamming\n{endif}\nM142 P1 R35 S40\nM106 P2 S100 ; turn on big fan ,to cool down toolhead\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; set extrude temp earlier, to reduce wait time\n\n;===== mech mode fast check============================\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q1 A7 B30 C80 H15 K0\nM974 Q1 S2 P0\n\nG1 X128 Y128 Z10 F20000\nM400 P200\nM970.3 Q0 A7 B30 C90 Q0 H15 K0\nM974 Q0 S2 P0\n\nM975 S1\nG1 F30000\nG1 X230 Y15\nG28 X ; re-home XY\n;===== mech mode fast check============================\n\n{if scan_first_layer}\n;start heatbed scan====================================\nM976 S2 P1\nG90\nG1 X128 Y128 F20000\nM976 S3 P2 ;register void printing detection\n{endif}\n\n;===== noozle load line ===============================\nM975 S1\nG90\nM83\nT1000\nG1 X18.0 Y0.5 Z0.8 F18000;Move to start position\nM109 S{nozzle_temperature[initial_no_support_extruder]}\nG1 Z0.2\nG0 E2 F300\nG0 X129 E15 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\nG0 X240 E15\nG0 Y11 E1.364 F{outer_wall_volumetric_speed/(0.3*1.0)/ 4 * 60}\nG0 X239.5\nG0 E0.3\nG0 Y1.5 E1.300\nG0 X231 E1.160 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM400\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n;curr_bed_type={curr_bed_type}\n{if curr_bed_type==\"Textured PEI Plate\"}\nG29.1 Z{-0.04} ; for Textured PEI Plate\n{endif}\n\n;===== draw extrinsic para cali paint =================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M1002 gcode_claim_action : 8\n\n G0 F1200.0 X231 Y15 Z0.2 E1.482\n G0 F1200.0 X226 Y15 Z0.2 E0.550\n G0 F1200.0 X226 Y8 Z0.2 E0.768\n G0 F1200.0 X216 Y8 Z0.2 E1.098\n G0 F1200.0 X216 Y1.5 Z0.2 E0.714\n\n G0 X48.0 E25.0 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\n G0 X48.0 Y14 E1.70 F1200.0\n G0 X35.0 Y6.0 E1.90 F1200.0\n\n ;=========== extruder cali extrusion ==================\n T1000\n M83\n {if default_acceleration > 0}\n {if outer_wall_acceleration > 0}\n M204 S[outer_wall_acceleration]\n {else}\n M204 S[default_acceleration]\n {endif}\n {endif}\n G0 X35.000 Y6.000 Z0.300 F30000 E0\n G1 F1500.000 E0.800\n M106 S0 ; turn off fan\n G0 X110.000 E9.35441 F4800\n G0 X185.000 E9.35441 F4800\n G0 X187 Z0\n G1 F1500.000 E-0.800\n G0 Z1\n G0 X180 Z0.3 F18000\n\n M900 L1000.0 M1.0\n M900 K0.020\n G0 X45.000 F30000\n G0 Y8.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.010\n G0 X45.000 F30000\n G0 Y10.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n M400\n\n G0 X45.000 F30000\n M900 K0.000\n G0 X45.000 F30000\n G0 Y12.000 F30000\n G1 F1500.000 E0.800\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 F1500.000 E-0.800\n G1 X183 Z0.15 F30000\n G1 X185\n G1 Z1.0\n G0 Y6.000 F30000 ; move y to clear pos\n G1 Z0.3\n\n G0 X45.000 F30000 ; move to start point\n\nM623 ; end of \"draw extrinsic para cali paint\"\n\nM1002 judge_flag extrude_cali_flag\nM622 J0\n G0 X231 Y1.5 F30000\n G0 X129 E14 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G0 X18 E15 F{outer_wall_volumetric_speed/(0.3*0.5) * 60}\nM623\n\nM104 S140\n\n\n;=========== laser and rgb calibration ===========\nM400\nM18 E\nM500 R\n\nM973 S3 P14\n\nG1 X120 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nT1100\nG1 X235.0 Y1.0 Z0.3 F18000.0;Move to first extrude line pos\nM400 P100\nM960 S1 P1\nM400 P100\nM973 S6 P0; use auto exposure for horizontal laser by xcam\nM960 S0 P0\n\nG1 X240.0 Y6.0 Z0.3 F18000.0;Move to vertical extrude line pos\nM960 S2 P1\nM400 P100\nM973 S6 P1; use auto exposure for vertical laser by xcam\nM960 S0 P0\n\n;=========== handeye calibration ======================\nM1002 judge_flag extrude_cali_flag\nM622 J1\n\n M973 S3 P1 ; camera start stream\n M400 P500\n M973 S1\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G0 F6000 X228.500 Y4.500 Z0.000\n M960 S0 P1\n M973 S1\n M400 P800\n M971 S6 P0\n M973 S2 P0\n M400 P500\n G0 Z0.000 F12000\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P200\n M971 S5 P1\n M973 S2 P1\n M400 P500\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P3\n G0 Z0.500 F12000\n M960 S0 P0\n M960 S2 P1\n G0 X228.5 Y11.0\n M400 P200\n M971 S5 P4\n M973 S2 P0\n M400 P500\n M960 S0 P0\n M960 S1 P1\n G0 X221.00 Y4.50\n M400 P500\n M971 S5 P2\n M963 S1\n M400 P1500\n M964\n T1100\n G1 Z3 F3000\n\n M400\n M500 ; save cali data\n\n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]} ; rise nozzle temp now ,to reduce temp waiting time.\n\n T1100\n M400 P400\n M960 S0 P0\n G0 F30000.000 Y10.000 X65.000 Z0.000\n M400 P400\n M960 S1 P1\n M400 P50\n\n M969 S1 N3 A2000\n G0 F360.000 X181.000 Z0.000\n M980.3 A70.000 B{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60/4} C5.000 D{outer_wall_volumetric_speed/(1.75*1.75/4*3.14)*60} E5.000 F175.000 H1.000 I0.000 J0.010 K0.020\n M400 P100\n G0 F20000\n G0 Z1 ; rise nozzle up\n T1000 ; change to nozzle space\n G0 X45.000 Y4.000 F30000 ; move to test line pos\n M969 S0 ; turn off scanning\n M960 S0 P0\n\n\n G1 Z2 F20000\n T1000\n G0 X45.000 Y4.000 F30000 E0\n M109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\n G0 Z0.3\n G1 F1500.000 E3.600\n G1 X65.000 E2.4945 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X70.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X75.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X80.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X85.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X90.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X95.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X100.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X105.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X110.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X115.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X120.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X125.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X130.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X135.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n\n ; see if extrude cali success, if not ,use default value\n M1002 judge_last_extrude_cali_success\n M622 J0\n M400\n M900 K0.01 M{outer_wall_volumetric_speed/(1.75*1.75/4*3.14) *0.01}\n M623\n\n G1 X140.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X145.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X150.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X155.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X160.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X165.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X170.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X175.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X180.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X185.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X190.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X195.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X200.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X205.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X210.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X215.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n G1 X220.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) / 4 * 60}\n G1 X225.000 E0.6236 F{outer_wall_volumetric_speed/(0.3*1.0) * 60}\n M973 S4\n\nM623\n\n;===== wait chamber temperature reaching the reference value =======\n{if (overall_chamber_temperature >= 40)}\nM191 S[overall_chamber_temperature] ; wait for chamber temp\nM106 P2 S0 ; reset chamber fan cmd\n{endif}\n\n;========turn off light and wait extrude temperature =============\nM1002 gcode_claim_action : 0\nM973 S4 ; turn off scanner\nM400 ; wait all motion done before implement the emprical L parameters\n;M900 L500.0 ; Empirical parameters\nM109 S[nozzle_temperature_initial_layer]\nM960 S1 P0 ; turn off laser\nM960 S2 P0 ; turn off laser\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off big fan\nM106 P3 S0 ; turn off chamber fan\n\nM975 S1 ; turn on mech mode supression\nG90\nM83\nT1000\nG1 E{-retraction_length[initial_no_support_extruder]} F1800\nG1 X128.0 Y253.0 Z0.2 F24000.0;Move to start position\nG1 E{retraction_length[initial_no_support_extruder]} F1800\nM109 S{nozzle_temperature_initial_layer[initial_no_support_extruder]}\nG0 X253 E6.4 F{outer_wall_volumetric_speed/(0.3*0.6) * 60}\nG0 Y128 E6.4\nG0 X252.5\nG0 Y252.5 E6.4\nG0 X128 E6.4" } \ No newline at end of file diff --git a/resources/profiles/BBL/machine/fdm_machine_common.json b/resources/profiles/BBL/machine/fdm_machine_common.json index 067e53b5d2..e736dc6662 100644 --- a/resources/profiles/BBL/machine/fdm_machine_common.json +++ b/resources/profiles/BBL/machine/fdm_machine_common.json @@ -76,7 +76,7 @@ ], "printable_height": "250", "extruder_clearance_radius": "65", - "extruder_clearance_height_to_rod": "36", + "extruder_clearance_height_to_rod": "34", "extruder_clearance_height_to_lid": "140", "printer_settings_id": "", "retraction_minimum_travel": [ @@ -106,7 +106,7 @@ "retraction_speed": [ "60" ], - "single_extruder_multi_material": "1", + "single_extruder_multi_material": "0", "support_air_filtration": "0", "wipe": [ "1" diff --git a/resources/profiles/BBL/process/0.06mm Fine @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm Fine @BBL A1 0.2 nozzle.json index 0b5df08973..a46163008e 100644 --- a/resources/profiles/BBL/process/0.06mm Fine @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm Fine @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP084", "instantiation": "true", + "description": "Compared with the default profile of 0.2 mm nozzle, it has a smaller layer height, and results in minimal layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.06mm Fine @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm Fine @BBL A1M 0.2 nozzle.json index 152b44e9ab..829e917675 100644 --- a/resources/profiles/BBL/process/0.06mm Fine @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm Fine @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP050", "instantiation": "true", + "description": "Compared with the default profile of 0.2 mm nozzle, it has a smaller layer height, and results in minimal layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "6000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.06mm Fine @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm Fine @BBL P1P 0.2 nozzle.json index deb52983a4..d05620a789 100644 --- a/resources/profiles/BBL/process/0.06mm Fine @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm Fine @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP063", "instantiation": "true", + "description": "Compared with the default profile of 0.2 mm nozzle, it has a smaller layer height, and results in minimal layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "5000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2500", diff --git a/resources/profiles/BBL/process/0.06mm High Quality @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm High Quality @BBL A1 0.2 nozzle.json index 000a6d08d6..19c218e4e3 100644 --- a/resources/profiles/BBL/process/0.06mm High Quality @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm High Quality @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP118", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in minimal layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.06mm High Quality @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm High Quality @BBL A1M 0.2 nozzle.json index 0ce2996347..15f97d190e 100644 --- a/resources/profiles/BBL/process/0.06mm High Quality @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm High Quality @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP117", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in minimal layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "3000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.06mm High Quality @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm High Quality @BBL P1P 0.2 nozzle.json index 66e56802f2..da1f6a89c3 100644 --- a/resources/profiles/BBL/process/0.06mm High Quality @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm High Quality @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP116", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in minimal layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.06mm High Quality @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm High Quality @BBL X1C 0.2 nozzle.json index 502c4cdaef..70e54ac6c2 100644 --- a/resources/profiles/BBL/process/0.06mm High Quality @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm High Quality @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP115", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in minimal layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.06mm Standard @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.06mm Standard @BBL X1C 0.2 nozzle.json index 06a7a9eecb..5ffde15e91 100644 --- a/resources/profiles/BBL/process/0.06mm Standard @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.06mm Standard @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP024", "instantiation": "true", + "description": "Compared with the default profile of 0.2 mm nozzle, it has a smaller layer height, and results in minimal layer lines and higher printing quality, but shorter printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", diff --git a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1.json b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1.json index 8e7e8cab90..a77c85e631 100644 --- a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1.json +++ b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP076", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1M.json b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1M.json index 0a87af8bb3..b54ff1ac71 100644 --- a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1M.json +++ b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP049", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL P1P.json b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL P1P.json index bc9f93e282..080e4005ec 100644 --- a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL P1P.json +++ b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP018", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and longer printing time.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL X1C.json b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL X1C.json index f591722386..ddb385860c 100644 --- a/resources/profiles/BBL/process/0.08mm Extra Fine @BBL X1C.json +++ b/resources/profiles/BBL/process/0.08mm Extra Fine @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP001", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and longer printing time.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1 0.2 nozzle.json index 2cbd3c2c9d..7745977387 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP119", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost invisible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1.json index 15c848b8b0..7d7f7be457 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP102", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "gap_infill_speed": "210", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M 0.2 nozzle.json index 6865d2fed0..2d181eae1b 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP120", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost invisible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "3000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M.json index 069a975b0d..71e2f43b7d 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP101", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "3000", "elefant_foot_compensation": "0", "gap_infill_speed": "210", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P 0.2 nozzle.json index c7d6188f2e..6424eae3c0 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP121", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost invisible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P.json index 454b86baf4..f135573cf2 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP100", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "gap_infill_speed": "210", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C 0.2 nozzle.json index aeb1c1765e..5b04803ced 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP122", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer lines, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost invisible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C.json b/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C.json index 777e9f4e44..1c7a15e91b 100644 --- a/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C.json +++ b/resources/profiles/BBL/process/0.08mm High Quality @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP099", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "gap_infill_speed": "210", "inner_wall_speed": "120", diff --git a/resources/profiles/BBL/process/0.08mm Optimal @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm Optimal @BBL A1 0.2 nozzle.json index ad2143b2c2..072bfd59b0 100644 --- a/resources/profiles/BBL/process/0.08mm Optimal @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm Optimal @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP085", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer height, and results in almost invisible layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.08mm Optimal @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm Optimal @BBL A1M 0.2 nozzle.json index 15a9dc636c..19f8577822 100644 --- a/resources/profiles/BBL/process/0.08mm Optimal @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm Optimal @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP051", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer height, and results in almost invisible layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "6000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.08mm Optimal @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm Optimal @BBL P1P 0.2 nozzle.json index b0ccea0029..9995057586 100644 --- a/resources/profiles/BBL/process/0.08mm Optimal @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm Optimal @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP064", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer height, and results in almost invisible layer lines and higher printing quality, but shorter printing time.", "default_acceleration": "5000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2500", diff --git a/resources/profiles/BBL/process/0.08mm Standard @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.08mm Standard @BBL X1C 0.2 nozzle.json index 7c8e7bbbef..4d1c9fa00e 100644 --- a/resources/profiles/BBL/process/0.08mm Standard @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.08mm Standard @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP025", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a smaller layer height, and results in almost invisible layer lines and higher printing quality, but shorter printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", diff --git a/resources/profiles/BBL/process/0.10mm High Quality @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm High Quality @BBL A1 0.2 nozzle.json index c848de06cd..23393e37b9 100644 --- a/resources/profiles/BBL/process/0.10mm High Quality @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm High Quality @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP114", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in much higher printing quality, but a much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.10mm High Quality @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm High Quality @BBL A1M 0.2 nozzle.json index 5eb21ef675..cb96b785af 100644 --- a/resources/profiles/BBL/process/0.10mm High Quality @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm High Quality @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP113", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in much higher printing quality, but a much longer printing time.", "default_acceleration": "3000", "elefant_foot_compensation": "0", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.10mm High Quality @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm High Quality @BBL P1P 0.2 nozzle.json index 8167ee4df0..f463a9e060 100644 --- a/resources/profiles/BBL/process/0.10mm High Quality @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm High Quality @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP112", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in much higher printing quality, but a much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.10mm High Quality @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm High Quality @BBL X1C 0.2 nozzle.json index af661fd789..60f8e2686b 100644 --- a/resources/profiles/BBL/process/0.10mm High Quality @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm High Quality @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP111", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in much higher printing quality, but a much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2000", diff --git a/resources/profiles/BBL/process/0.10mm Standard @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm Standard @BBL A1 0.2 nozzle.json index 4b2576ef0b..56a9bfaced 100644 --- a/resources/profiles/BBL/process/0.10mm Standard @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm Standard @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP083", "instantiation": "true", + "description": "It has a small layer height, and results in almost negligible layer lines and high printing quality. It is suitable for most general printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.10mm Standard @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm Standard @BBL A1M 0.2 nozzle.json index 972961766e..9841209d7e 100644 --- a/resources/profiles/BBL/process/0.10mm Standard @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm Standard @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP039", "instantiation": "true", + "description": "It has a small layer height, and results in almost negligible layer lines and high printing quality. It is suitable for most general printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.10mm Standard @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm Standard @BBL P1P 0.2 nozzle.json index 0b50342c13..37a2a12777 100644 --- a/resources/profiles/BBL/process/0.10mm Standard @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm Standard @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP014", "instantiation": "true", + "description": "It has a small layer height, and results in almost negligible layer lines and high printing quality. It is suitable for most general printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.2 nozzle" diff --git a/resources/profiles/BBL/process/0.10mm Standard @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.10mm Standard @BBL X1C 0.2 nozzle.json index 9b04506d03..241c0a358f 100644 --- a/resources/profiles/BBL/process/0.10mm Standard @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.10mm Standard @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP007", "instantiation": "true", + "description": "It has a small layer height, and results in almost negligible layer lines and high printing quality. It is suitable for most general printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", diff --git a/resources/profiles/BBL/process/0.12mm Draft @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.12mm Draft @BBL A1 0.2 nozzle.json index 3a711c372e..549a6d7fe5 100644 --- a/resources/profiles/BBL/process/0.12mm Draft @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.12mm Draft @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP086", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a slightly bigger layer height, and results in almost negligible layer lines, and slightly shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.12mm Draft @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.12mm Draft @BBL A1M 0.2 nozzle.json index 917812c462..66a9004da7 100644 --- a/resources/profiles/BBL/process/0.12mm Draft @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.12mm Draft @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP052", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a slightly bigger layer height, and results in almost negligible layer lines, and slightly shorter printing time.", "default_acceleration": "6000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.12mm Draft @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.12mm Draft @BBL P1P 0.2 nozzle.json index faef462ee4..675c21747d 100644 --- a/resources/profiles/BBL/process/0.12mm Draft @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.12mm Draft @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP065", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a slightly bigger layer height, and results in almost negligible layer lines, and slightly shorter printing time.", "default_acceleration": "5000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2500", diff --git a/resources/profiles/BBL/process/0.12mm Fine @BBL A1.json b/resources/profiles/BBL/process/0.12mm Fine @BBL A1.json index 4bf79151e2..6cb7369ad2 100644 --- a/resources/profiles/BBL/process/0.12mm Fine @BBL A1.json +++ b/resources/profiles/BBL/process/0.12mm Fine @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP077", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.12mm Fine @BBL A1M.json b/resources/profiles/BBL/process/0.12mm Fine @BBL A1M.json index 3fb96a9078..74d30722a0 100644 --- a/resources/profiles/BBL/process/0.12mm Fine @BBL A1M.json +++ b/resources/profiles/BBL/process/0.12mm Fine @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP044", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.12mm Fine @BBL P1P.json b/resources/profiles/BBL/process/0.12mm Fine @BBL P1P.json index 03afc8bee0..172d506eca 100644 --- a/resources/profiles/BBL/process/0.12mm Fine @BBL P1P.json +++ b/resources/profiles/BBL/process/0.12mm Fine @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP019", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and higher printing quality, but longer printing time.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.12mm Fine @BBL X1C.json b/resources/profiles/BBL/process/0.12mm Fine @BBL X1C.json index 16c75d85ce..d42c4dcd66 100644 --- a/resources/profiles/BBL/process/0.12mm Fine @BBL X1C.json +++ b/resources/profiles/BBL/process/0.12mm Fine @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP002", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in almost negligible layer lines and higher printing quality, but longer printing time.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.12mm High Quality @BBL A1.json b/resources/profiles/BBL/process/0.12mm High Quality @BBL A1.json index 131b39e8b2..0a1a283141 100644 --- a/resources/profiles/BBL/process/0.12mm High Quality @BBL A1.json +++ b/resources/profiles/BBL/process/0.12mm High Quality @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP106", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "gap_infill_speed": "230", diff --git a/resources/profiles/BBL/process/0.12mm High Quality @BBL A1M.json b/resources/profiles/BBL/process/0.12mm High Quality @BBL A1M.json index 8305849949..dbe1743fbc 100644 --- a/resources/profiles/BBL/process/0.12mm High Quality @BBL A1M.json +++ b/resources/profiles/BBL/process/0.12mm High Quality @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP105", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "3000", "elefant_foot_compensation": "0", "gap_infill_speed": "230", diff --git a/resources/profiles/BBL/process/0.12mm High Quality @BBL P1P.json b/resources/profiles/BBL/process/0.12mm High Quality @BBL P1P.json index da83aa8137..1acd431c12 100644 --- a/resources/profiles/BBL/process/0.12mm High Quality @BBL P1P.json +++ b/resources/profiles/BBL/process/0.12mm High Quality @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP104", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "gap_infill_speed": "230", "inner_wall_speed": "150", diff --git a/resources/profiles/BBL/process/0.12mm High Quality @BBL X1C.json b/resources/profiles/BBL/process/0.12mm High Quality @BBL X1C.json index df9625b60b..f2e438994e 100644 --- a/resources/profiles/BBL/process/0.12mm High Quality @BBL X1C.json +++ b/resources/profiles/BBL/process/0.12mm High Quality @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP103", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in almost negligible layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "gap_infill_speed": "230", "inner_wall_speed": "150", diff --git a/resources/profiles/BBL/process/0.12mm Standard @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.12mm Standard @BBL X1C 0.2 nozzle.json index 5d3d9b8d63..e909017319 100644 --- a/resources/profiles/BBL/process/0.12mm Standard @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.12mm Standard @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP026", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a slightly bigger layer height, and results in almost negligible layer lines, and slightly shorter printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", diff --git a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1 0.2 nozzle.json index 342f481afe..c1ff7b34a3 100644 --- a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP087", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a bigger layer height, and results in slightly visible layer lines, but shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "initial_layer_infill_speed": "28", diff --git a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1M 0.2 nozzle.json index 1c5b9def3f..c8b97600b7 100644 --- a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL A1M 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP053", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a bigger layer height, and results in slightly visible layer lines, but shorter printing time.", "default_acceleration": "6000", "initial_layer_infill_speed": "28", "initial_layer_speed": "16", diff --git a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL P1P 0.2 nozzle.json index 568f51d502..d19c428cd4 100644 --- a/resources/profiles/BBL/process/0.14mm Extra Draft @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.14mm Extra Draft @BBL P1P 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP066", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a bigger layer height, and results in slightly visible layer lines, but shorter printing time.", "default_acceleration": "5000", "elefant_foot_compensation": "0.15", "outer_wall_acceleration": "2500", diff --git a/resources/profiles/BBL/process/0.14mm Standard @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/process/0.14mm Standard @BBL X1C 0.2 nozzle.json index 227940298d..b6d8ecc230 100644 --- a/resources/profiles/BBL/process/0.14mm Standard @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/process/0.14mm Standard @BBL X1C 0.2 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP027", "instantiation": "true", + "description": "Compared with the default profile of a 0.2 mm nozzle, it has a bigger layer height, and results in slightly visible layer lines, but shorter printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.2 nozzle", diff --git a/resources/profiles/BBL/process/0.16mm High Quality @BBL A1.json b/resources/profiles/BBL/process/0.16mm High Quality @BBL A1.json index 1f246929f8..5632bdbe26 100644 --- a/resources/profiles/BBL/process/0.16mm High Quality @BBL A1.json +++ b/resources/profiles/BBL/process/0.16mm High Quality @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP110", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in less apparent layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "elefant_foot_compensation": "0.075", "gap_infill_speed": "250", diff --git a/resources/profiles/BBL/process/0.16mm High Quality @BBL A1M.json b/resources/profiles/BBL/process/0.16mm High Quality @BBL A1M.json index 58ac77c4c5..fe51c4740f 100644 --- a/resources/profiles/BBL/process/0.16mm High Quality @BBL A1M.json +++ b/resources/profiles/BBL/process/0.16mm High Quality @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP109", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in less apparent layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "3000", "elefant_foot_compensation": "0", "gap_infill_speed": "250", diff --git a/resources/profiles/BBL/process/0.16mm High Quality @BBL P1P.json b/resources/profiles/BBL/process/0.16mm High Quality @BBL P1P.json index d36e464f86..a3cd2eb87c 100644 --- a/resources/profiles/BBL/process/0.16mm High Quality @BBL P1P.json +++ b/resources/profiles/BBL/process/0.16mm High Quality @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP108", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in less apparent layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "gap_infill_speed": "250", "inner_wall_speed": "150", diff --git a/resources/profiles/BBL/process/0.16mm High Quality @BBL X1C.json b/resources/profiles/BBL/process/0.16mm High Quality @BBL X1C.json index 32295f8e82..e5f73eab5b 100644 --- a/resources/profiles/BBL/process/0.16mm High Quality @BBL X1C.json +++ b/resources/profiles/BBL/process/0.16mm High Quality @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP107", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, lower speeds and acceleration, and the sparse infill pattern is Gyroid. So, it results in less apparent layer lines and much higher printing quality, but much longer printing time.", "default_acceleration": "4000", "gap_infill_speed": "250", "inner_wall_speed": "150", diff --git a/resources/profiles/BBL/process/0.16mm Optimal @BBL A1.json b/resources/profiles/BBL/process/0.16mm Optimal @BBL A1.json index 1ec6906d6d..eedbf6577d 100644 --- a/resources/profiles/BBL/process/0.16mm Optimal @BBL A1.json +++ b/resources/profiles/BBL/process/0.16mm Optimal @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP078", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.16mm Optimal @BBL A1M.json b/resources/profiles/BBL/process/0.16mm Optimal @BBL A1M.json index 88ef46e482..509404f9cd 100644 --- a/resources/profiles/BBL/process/0.16mm Optimal @BBL A1M.json +++ b/resources/profiles/BBL/process/0.16mm Optimal @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP045", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.16mm Optimal @BBL P1P.json b/resources/profiles/BBL/process/0.16mm Optimal @BBL P1P.json index 1e0462da79..6df7fae3f2 100644 --- a/resources/profiles/BBL/process/0.16mm Optimal @BBL P1P.json +++ b/resources/profiles/BBL/process/0.16mm Optimal @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP020", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.16mm Optimal @BBL X1C.json b/resources/profiles/BBL/process/0.16mm Optimal @BBL X1C.json index 2465e38c1d..0d12d4ddb8 100644 --- a/resources/profiles/BBL/process/0.16mm Optimal @BBL X1C.json +++ b/resources/profiles/BBL/process/0.16mm Optimal @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP003", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.18mm Fine @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.18mm Fine @BBL A1 0.6 nozzle.json index 447c7994aa..f19e70c25f 100644 --- a/resources/profiles/BBL/process/0.18mm Fine @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.18mm Fine @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP088", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.18mm Fine @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.18mm Fine @BBL A1M 0.6 nozzle.json index 7bc6534c79..7b1612a79d 100644 --- a/resources/profiles/BBL/process/0.18mm Fine @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.18mm Fine @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP062", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.18mm Fine @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.18mm Fine @BBL P1P 0.6 nozzle.json index a1635bd9d6..53d29a785f 100644 --- a/resources/profiles/BBL/process/0.18mm Fine @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.18mm Fine @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP072", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.18mm Standard @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.18mm Standard @BBL X1C 0.6 nozzle.json index ae327ef129..15ebedb2ac 100644 --- a/resources/profiles/BBL/process/0.18mm Standard @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.18mm Standard @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP028", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and higher printing quality, but longer printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", diff --git a/resources/profiles/BBL/process/0.20mm Standard @BBL A1.json b/resources/profiles/BBL/process/0.20mm Standard @BBL A1.json index e1c6f5ebd7..91feaa6774 100644 --- a/resources/profiles/BBL/process/0.20mm Standard @BBL A1.json +++ b/resources/profiles/BBL/process/0.20mm Standard @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP079", "instantiation": "true", + "description": "It has a general layer height, and results in general layer lines and printing quality. It is suitable for most general printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.20mm Standard @BBL A1M.json b/resources/profiles/BBL/process/0.20mm Standard @BBL A1M.json index 33edabab4d..78b09fc677 100644 --- a/resources/profiles/BBL/process/0.20mm Standard @BBL A1M.json +++ b/resources/profiles/BBL/process/0.20mm Standard @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP000", "instantiation": "true", + "description": "It has a general layer height, and results in general layer lines and printing quality. It is suitable for most general printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.20mm Standard @BBL P1P.json b/resources/profiles/BBL/process/0.20mm Standard @BBL P1P.json index 1b60746efc..cea5a44b6d 100644 --- a/resources/profiles/BBL/process/0.20mm Standard @BBL P1P.json +++ b/resources/profiles/BBL/process/0.20mm Standard @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP015", "instantiation": "true", + "description": "It has a general layer height, and results in general layer lines and printing quality. It is suitable for most general printing cases.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.20mm Standard @BBL X1C.json b/resources/profiles/BBL/process/0.20mm Standard @BBL X1C.json index 1d05bdfa6f..2f38b67fa7 100644 --- a/resources/profiles/BBL/process/0.20mm Standard @BBL X1C.json +++ b/resources/profiles/BBL/process/0.20mm Standard @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP004", "instantiation": "true", + "description": "It has a general layer height, and results in general layer lines and printing quality. It is suitable for most general printing cases.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.20mm Strength @BBL A1.json b/resources/profiles/BBL/process/0.20mm Strength @BBL A1.json index 17c882470b..30e9ca38ee 100644 --- a/resources/profiles/BBL/process/0.20mm Strength @BBL A1.json +++ b/resources/profiles/BBL/process/0.20mm Strength @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP080", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "outer_wall_speed": "60", diff --git a/resources/profiles/BBL/process/0.20mm Strength @BBL A1M.json b/resources/profiles/BBL/process/0.20mm Strength @BBL A1M.json index 2c2595cc9a..3a261d636d 100644 --- a/resources/profiles/BBL/process/0.20mm Strength @BBL A1M.json +++ b/resources/profiles/BBL/process/0.20mm Strength @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP046", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.20mm Strength @BBL P1P.json b/resources/profiles/BBL/process/0.20mm Strength @BBL P1P.json index c38f5f7118..9edb0342ad 100644 --- a/resources/profiles/BBL/process/0.20mm Strength @BBL P1P.json +++ b/resources/profiles/BBL/process/0.20mm Strength @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP021", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "outer_wall_speed": "60", "sparse_infill_density": "25%", "wall_loops": "6", diff --git a/resources/profiles/BBL/process/0.20mm Strength @BBL X1C.json b/resources/profiles/BBL/process/0.20mm Strength @BBL X1C.json index 27b9c03128..a621376300 100644 --- a/resources/profiles/BBL/process/0.20mm Strength @BBL X1C.json +++ b/resources/profiles/BBL/process/0.20mm Strength @BBL X1C.json @@ -5,9 +5,10 @@ "from": "system", "setting_id": "GP013", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "outer_wall_speed": "60", - "wall_loops": "6", "sparse_infill_density": "25%", + "wall_loops": "6", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.24mm Draft @BBL A1.json b/resources/profiles/BBL/process/0.24mm Draft @BBL A1.json index abdd58e9b9..20e452f19b 100644 --- a/resources/profiles/BBL/process/0.24mm Draft @BBL A1.json +++ b/resources/profiles/BBL/process/0.24mm Draft @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP081", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but slightly shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.24mm Draft @BBL A1M.json b/resources/profiles/BBL/process/0.24mm Draft @BBL A1M.json index 3915f80f48..4c791c4600 100644 --- a/resources/profiles/BBL/process/0.24mm Draft @BBL A1M.json +++ b/resources/profiles/BBL/process/0.24mm Draft @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP047", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but slightly shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.24mm Draft @BBL P1P.json b/resources/profiles/BBL/process/0.24mm Draft @BBL P1P.json index 87866d4f72..ed3bd535f9 100644 --- a/resources/profiles/BBL/process/0.24mm Draft @BBL P1P.json +++ b/resources/profiles/BBL/process/0.24mm Draft @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP022", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but slightly shorter printing time.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.24mm Draft @BBL X1C.json b/resources/profiles/BBL/process/0.24mm Draft @BBL X1C.json index 4ef6dae40e..01505bf228 100644 --- a/resources/profiles/BBL/process/0.24mm Draft @BBL X1C.json +++ b/resources/profiles/BBL/process/0.24mm Draft @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP005", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but slightly shorter printing time.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.24mm Fine @BBL A1 0.8 nozzle.json b/resources/profiles/BBL/process/0.24mm Fine @BBL A1 0.8 nozzle.json index af778978f4..629884dc7c 100644 --- a/resources/profiles/BBL/process/0.24mm Fine @BBL A1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Fine @BBL A1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP092", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a smaller layer height, and results in less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.24mm Fine @BBL A1M 0.8 nozzle.json b/resources/profiles/BBL/process/0.24mm Fine @BBL A1M 0.8 nozzle.json index 8a542171d2..ca2631fb71 100644 --- a/resources/profiles/BBL/process/0.24mm Fine @BBL A1M 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Fine @BBL A1M 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP057", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a smaller layer height, and results in less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.24mm Fine @BBL P1P 0.8 nozzle.json b/resources/profiles/BBL/process/0.24mm Fine @BBL P1P 0.8 nozzle.json index 5b02a41a12..7f7934ad5a 100644 --- a/resources/profiles/BBL/process/0.24mm Fine @BBL P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Fine @BBL P1P 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP068", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a smaller layer height, and results in less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.24mm Optimal @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.24mm Optimal @BBL A1 0.6 nozzle.json index f616ccd800..f8388f6262 100644 --- a/resources/profiles/BBL/process/0.24mm Optimal @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Optimal @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP089", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and slight higher printing quality, but longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.24mm Optimal @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.24mm Optimal @BBL A1M 0.6 nozzle.json index e5eaf7207b..28082afef5 100644 --- a/resources/profiles/BBL/process/0.24mm Optimal @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Optimal @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP054", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and slight higher printing quality, but longer printing time.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.24mm Optimal @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.24mm Optimal @BBL P1P 0.6 nozzle.json index 54941c5327..a143d7b635 100644 --- a/resources/profiles/BBL/process/0.24mm Optimal @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Optimal @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP069", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and slight higher printing quality, but longer printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.6 nozzle.json index 47ee33688a..992bb0f1c5 100644 --- a/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP029", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a smaller layer height, and results in less apparent layer lines and slight higher printing quality, but longer printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", diff --git a/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.8 nozzle.json index a45123964c..9be5eed988 100644 --- a/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.24mm Standard @BBL X1C 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP032", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a smaller layer height, and results in less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1.json b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1.json index 432bb9292b..490c0026cd 100644 --- a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1.json +++ b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP082", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1M.json b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1M.json index f2ea4704d8..f1923e0d69 100644 --- a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1M.json +++ b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL A1M.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP048", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL P1P.json b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL P1P.json index ca64d1e316..4f9bb7b53e 100644 --- a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL P1P.json +++ b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL P1P.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP023", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time.", "compatible_printers": [ "Bambu Lab P1P 0.4 nozzle" ] diff --git a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL X1C.json b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL X1C.json index 211a43a31e..8c2e794dab 100644 --- a/resources/profiles/BBL/process/0.28mm Extra Draft @BBL X1C.json +++ b/resources/profiles/BBL/process/0.28mm Extra Draft @BBL X1C.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP006", "instantiation": "true", + "description": "Compared with the default profile of a 0.4 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time.", "compatible_printers": [ "Bambu Lab X1 Carbon 0.4 nozzle", "Bambu Lab X1 0.4 nozzle", diff --git a/resources/profiles/BBL/process/0.30mm Standard @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Standard @BBL A1 0.6 nozzle.json index b05e7cea1e..26ad6e5806 100644 --- a/resources/profiles/BBL/process/0.30mm Standard @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Standard @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP096", "instantiation": "true", + "description": "It has a big layer height, and results in apparent layer lines and ordinary printing quality and printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.30mm Standard @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Standard @BBL A1M 0.6 nozzle.json index ef0567d6d1..910c119ebd 100644 --- a/resources/profiles/BBL/process/0.30mm Standard @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Standard @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP038", "instantiation": "true", + "description": "It has a big layer height, and results in apparent layer lines and ordinary printing quality and printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.30mm Standard @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Standard @BBL P1P 0.6 nozzle.json index 37b7593e8d..164c03866f 100644 --- a/resources/profiles/BBL/process/0.30mm Standard @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Standard @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP016", "instantiation": "true", + "description": "It has a big layer height, and results in apparent layer lines and ordinary printing quality and printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.30mm Standard @BBL X1 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Standard @BBL X1 0.6 nozzle.json index f53720838f..e501731193 100644 --- a/resources/profiles/BBL/process/0.30mm Standard @BBL X1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Standard @BBL X1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP011", "instantiation": "true", + "description": "It has a big layer height, and results in apparent layer lines and ordinary printing quality and printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.30mm Standard @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Standard @BBL X1C 0.6 nozzle.json index c09f04e219..3f0a4dacbe 100644 --- a/resources/profiles/BBL/process/0.30mm Standard @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Standard @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP010", "instantiation": "true", + "description": "It has a big layer height, and results in apparent layer lines and ordinary printing quality and printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", diff --git a/resources/profiles/BBL/process/0.30mm Strength @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Strength @BBL A1 0.6 nozzle.json index f4978b869f..775523f0d6 100644 --- a/resources/profiles/BBL/process/0.30mm Strength @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Strength @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP097", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "sparse_infill_density": "25%", diff --git a/resources/profiles/BBL/process/0.30mm Strength @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Strength @BBL A1M 0.6 nozzle.json index 5eac111e7e..044c7c24cb 100644 --- a/resources/profiles/BBL/process/0.30mm Strength @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Strength @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP061", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.30mm Strength @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Strength @BBL P1P 0.6 nozzle.json index c5bcdf6cd6..284206f4fa 100644 --- a/resources/profiles/BBL/process/0.30mm Strength @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Strength @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP067", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "elefant_foot_compensation": "0.15", "sparse_infill_density": "25%", "wall_loops": "4", diff --git a/resources/profiles/BBL/process/0.30mm Strength @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.30mm Strength @BBL X1C 0.6 nozzle.json index 08493a2232..affc545389 100644 --- a/resources/profiles/BBL/process/0.30mm Strength @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.30mm Strength @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP036", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has more wall loops and a higher sparse infill density. So, it results in higher strength of the prints, but more filament consumption and longer printing time.", "elefant_foot_compensation": "0.15", "sparse_infill_density": "25%", "wall_loops": "4", diff --git a/resources/profiles/BBL/process/0.32mm Optimal @BBL A1 0.8 nozzle.json b/resources/profiles/BBL/process/0.32mm Optimal @BBL A1 0.8 nozzle.json index fbeab32f62..b1e8658fce 100644 --- a/resources/profiles/BBL/process/0.32mm Optimal @BBL A1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.32mm Optimal @BBL A1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP093", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a slightly smaller layer height, and results in slightly less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.32mm Optimal @BBL A1M 0.8 nozzle.json b/resources/profiles/BBL/process/0.32mm Optimal @BBL A1M 0.8 nozzle.json index f793ab2063..e3778f3709 100644 --- a/resources/profiles/BBL/process/0.32mm Optimal @BBL A1M 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.32mm Optimal @BBL A1M 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP058", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a slightly smaller layer height, and results in slightly less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.32mm Optimal @BBL P1P 0.8 nozzle.json b/resources/profiles/BBL/process/0.32mm Optimal @BBL P1P 0.8 nozzle.json index 54463e5b3a..7586ed84bf 100644 --- a/resources/profiles/BBL/process/0.32mm Optimal @BBL P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.32mm Optimal @BBL P1P 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP075", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a slightly smaller layer height, and results in slightly less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.32mm Standard @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/process/0.32mm Standard @BBL X1C 0.8 nozzle.json index 0a61d6aaa0..a75637780f 100644 --- a/resources/profiles/BBL/process/0.32mm Standard @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.32mm Standard @BBL X1C 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP033", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a slightly smaller layer height, and results in slightly less but still apparent layer lines and slightly higher printing quality, but longer printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/process/0.36mm Draft @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.36mm Draft @BBL A1 0.6 nozzle.json index 3448a0f1bb..e5ebbcfe31 100644 --- a/resources/profiles/BBL/process/0.36mm Draft @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.36mm Draft @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP090", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.36mm Draft @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.36mm Draft @BBL A1M 0.6 nozzle.json index 4a40cfb3d5..0268a0ea0f 100644 --- a/resources/profiles/BBL/process/0.36mm Draft @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.36mm Draft @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP055", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.36mm Draft @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.36mm Draft @BBL P1P 0.6 nozzle.json index b7a618da19..51251017b3 100644 --- a/resources/profiles/BBL/process/0.36mm Draft @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.36mm Draft @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP070", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.36mm Standard @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.36mm Standard @BBL X1C 0.6 nozzle.json index 24acdebf3b..f259218f18 100644 --- a/resources/profiles/BBL/process/0.36mm Standard @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.36mm Standard @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP030", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in more apparent layer lines and lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", diff --git a/resources/profiles/BBL/process/0.40mm Standard @BBL A1 0.8 nozzle.json b/resources/profiles/BBL/process/0.40mm Standard @BBL A1 0.8 nozzle.json index e642efe3f4..de5ffe19c3 100644 --- a/resources/profiles/BBL/process/0.40mm Standard @BBL A1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.40mm Standard @BBL A1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP098", "instantiation": "true", + "description": "It has a very big layer height, and results in very apparent layer lines, low printing quality and general printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.40mm Standard @BBL A1M 0.8 nozzle.json b/resources/profiles/BBL/process/0.40mm Standard @BBL A1M 0.8 nozzle.json index 39300abc52..e4a2b2aaa1 100644 --- a/resources/profiles/BBL/process/0.40mm Standard @BBL A1M 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.40mm Standard @BBL A1M 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP037", "instantiation": "true", + "description": "It has a very big layer height, and results in very apparent layer lines, low printing quality and general printing time.", "default_acceleration": "6000", "elefant_foot_compensation": "0", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.40mm Standard @BBL P1P 0.8 nozzle.json b/resources/profiles/BBL/process/0.40mm Standard @BBL P1P 0.8 nozzle.json index 547915d19e..a647b300b6 100644 --- a/resources/profiles/BBL/process/0.40mm Standard @BBL P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.40mm Standard @BBL P1P 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP017", "instantiation": "true", + "description": "It has a very big layer height, and results in very apparent layer lines, low printing quality and general printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.40mm Standard @BBL X1 0.8 nozzle.json b/resources/profiles/BBL/process/0.40mm Standard @BBL X1 0.8 nozzle.json index 649f3e803f..f5115f43b7 100644 --- a/resources/profiles/BBL/process/0.40mm Standard @BBL X1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.40mm Standard @BBL X1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP012", "instantiation": "true", + "description": "It has a very big layer height, and results in very apparent layer lines, low printing quality and general printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.40mm Standard @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/process/0.40mm Standard @BBL X1C 0.8 nozzle.json index ed00b1679f..2c7cb9ba80 100644 --- a/resources/profiles/BBL/process/0.40mm Standard @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.40mm Standard @BBL X1C 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP009", "instantiation": "true", + "description": "It has a very big layer height, and results in very apparent layer lines, low printing quality and general printing time.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1 0.6 nozzle.json b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1 0.6 nozzle.json index b0eda75687..d6b15c6eba 100644 --- a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP091", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in much more apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1M 0.6 nozzle.json b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1M 0.6 nozzle.json index b29e070b82..571ab55f0d 100644 --- a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1M 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL A1M 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP056", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in much more apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL P1P 0.6 nozzle.json b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL P1P 0.6 nozzle.json index 9305139f2d..69578536be 100644 --- a/resources/profiles/BBL/process/0.42mm Extra Draft @BBL P1P 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.42mm Extra Draft @BBL P1P 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP073", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in much more apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.6 nozzle" diff --git a/resources/profiles/BBL/process/0.42mm Standard @BBL X1C 0.6 nozzle.json b/resources/profiles/BBL/process/0.42mm Standard @BBL X1C 0.6 nozzle.json index 38b90393da..dbf8255105 100644 --- a/resources/profiles/BBL/process/0.42mm Standard @BBL X1C 0.6 nozzle.json +++ b/resources/profiles/BBL/process/0.42mm Standard @BBL X1C 0.6 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP031", "instantiation": "true", + "description": "Compared with the default profile of a 0.6 mm nozzle, it has a bigger layer height, and results in much more apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.6 nozzle", diff --git a/resources/profiles/BBL/process/0.48mm Draft @BBL A1 0.8 nozzle.json b/resources/profiles/BBL/process/0.48mm Draft @BBL A1 0.8 nozzle.json index a03f301b78..d3e5e0c26a 100644 --- a/resources/profiles/BBL/process/0.48mm Draft @BBL A1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.48mm Draft @BBL A1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP094", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a bigger layer height, and results in very apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.48mm Draft @BBL A1M 0.8 nozzle.json b/resources/profiles/BBL/process/0.48mm Draft @BBL A1M 0.8 nozzle.json index 29d78d74d5..dc3159fb7f 100644 --- a/resources/profiles/BBL/process/0.48mm Draft @BBL A1M 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.48mm Draft @BBL A1M 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP059", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a bigger layer height, and results in very apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.48mm Draft @BBL P1P 0.8 nozzle.json b/resources/profiles/BBL/process/0.48mm Draft @BBL P1P 0.8 nozzle.json index 0299ac8fec..7a5062a369 100644 --- a/resources/profiles/BBL/process/0.48mm Draft @BBL P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.48mm Draft @BBL P1P 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP074", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a bigger layer height, and results in very apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.48mm Standard @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/process/0.48mm Standard @BBL X1C 0.8 nozzle.json index 4075696088..77c2585943 100644 --- a/resources/profiles/BBL/process/0.48mm Standard @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.48mm Standard @BBL X1C 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP034", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a bigger layer height, and results in very apparent layer lines and much lower printing quality, but shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1 0.8 nozzle.json b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1 0.8 nozzle.json index 8b1312dfb9..7669c35cdc 100644 --- a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP095", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a much bigger layer height, and results in extremely apparent layer lines and much lower printing quality, but much shorter printing time in some printing cases.", "default_acceleration": "6000", "elefant_foot_compensation": "0.075", "travel_speed": "700", diff --git a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1M 0.8 nozzle.json b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1M 0.8 nozzle.json index 43895dd832..8090a64617 100644 --- a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1M 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL A1M 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP060", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a much bigger layer height, and results in extremely apparent layer lines and much lower printing quality, but much shorter printing time in some printing cases.", "default_acceleration": "6000", "travel_speed": "700", "compatible_printers": [ diff --git a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL P1P 0.8 nozzle.json b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL P1P 0.8 nozzle.json index ca90e061ea..fcc8b66b82 100644 --- a/resources/profiles/BBL/process/0.56mm Extra Draft @BBL P1P 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.56mm Extra Draft @BBL P1P 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP071", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a much bigger layer height, and results in extremely apparent layer lines and much lower printing quality, but much shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab P1P 0.8 nozzle" diff --git a/resources/profiles/BBL/process/0.56mm Standard @BBL X1C 0.8 nozzle.json b/resources/profiles/BBL/process/0.56mm Standard @BBL X1C 0.8 nozzle.json index 48cb2aac2e..64d3187b44 100644 --- a/resources/profiles/BBL/process/0.56mm Standard @BBL X1C 0.8 nozzle.json +++ b/resources/profiles/BBL/process/0.56mm Standard @BBL X1C 0.8 nozzle.json @@ -5,6 +5,7 @@ "from": "system", "setting_id": "GP035", "instantiation": "true", + "description": "Compared with the default profile of a 0.8 mm nozzle, it has a much bigger layer height, and results in extremely apparent layer lines and much lower printing quality, but much shorter printing time in some printing cases.", "elefant_foot_compensation": "0.15", "compatible_printers": [ "Bambu Lab X1 Carbon 0.8 nozzle", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.06_nozzle_0.2.json b/resources/profiles/BBL/process/fdm_process_bbl_0.06_nozzle_0.2.json index c01ea54987..0857a48e0e 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.06_nozzle_0.2.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.06_nozzle_0.2.json @@ -21,5 +21,7 @@ "initial_layer_speed": "40", "initial_layer_infill_speed": "70", "sparse_infill_speed": "100", - "top_surface_speed": "150" + "top_surface_speed": "150", + "support_top_z_distance": "0.06", + "support_bottom_z_distance": "0.06" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.08.json b/resources/profiles/BBL/process/fdm_process_bbl_0.08.json index 836980d3fd..61897f7a73 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.08.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.08.json @@ -20,5 +20,7 @@ "overhang_1_4_speed": "60", "overhang_2_4_speed": "30", "overhang_3_4_speed": "10", - "support_threshold_angle": "15" + "support_threshold_angle": "15", + "support_top_z_distance": "0.08", + "support_bottom_z_distance": "0.08" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.08_nozzle_0.2.json b/resources/profiles/BBL/process/fdm_process_bbl_0.08_nozzle_0.2.json index 43a8b60f07..80670ce3b6 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.08_nozzle_0.2.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.08_nozzle_0.2.json @@ -21,5 +21,7 @@ "initial_layer_speed": "40", "initial_layer_infill_speed": "70", "sparse_infill_speed": "100", - "top_surface_speed": "150" + "top_surface_speed": "150", + "support_top_z_distance": "0.08", + "support_bottom_z_distance": "0.08" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.10_nozzle_0.2.json b/resources/profiles/BBL/process/fdm_process_bbl_0.10_nozzle_0.2.json index cc7d773953..9d54d14c18 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.10_nozzle_0.2.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.10_nozzle_0.2.json @@ -21,5 +21,7 @@ "initial_layer_speed": "40", "initial_layer_infill_speed": "70", "sparse_infill_speed": "100", - "top_surface_speed": "150" + "top_surface_speed": "150", + "support_top_z_distance": "0.1", + "support_bottom_z_distance": "0.1" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.12.json b/resources/profiles/BBL/process/fdm_process_bbl_0.12.json index e76673b434..e22593fb30 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.12.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.12.json @@ -20,5 +20,7 @@ "overhang_1_4_speed": "60", "overhang_2_4_speed": "30", "overhang_3_4_speed": "10", - "support_threshold_angle": "20" + "support_threshold_angle": "20", + "support_top_z_distance": "0.12", + "support_bottom_z_distance": "0.12" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.12_nozzle_0.2.json b/resources/profiles/BBL/process/fdm_process_bbl_0.12_nozzle_0.2.json index 040df9f8a9..9d35f2501e 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.12_nozzle_0.2.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.12_nozzle_0.2.json @@ -21,5 +21,7 @@ "initial_layer_speed": "40", "initial_layer_infill_speed": "70", "sparse_infill_speed": "100", - "top_surface_speed": "150" + "top_surface_speed": "150", + "support_top_z_distance": "0.12", + "support_bottom_z_distance": "0.12" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.14_nozzle_0.2.json b/resources/profiles/BBL/process/fdm_process_bbl_0.14_nozzle_0.2.json index be12c21e1c..573669d4a5 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.14_nozzle_0.2.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.14_nozzle_0.2.json @@ -21,5 +21,7 @@ "initial_layer_speed": "40", "initial_layer_infill_speed": "70", "sparse_infill_speed": "100", - "top_surface_speed": "150" + "top_surface_speed": "150", + "support_top_z_distance": "0.14", + "support_bottom_z_distance": "0.14" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.16.json b/resources/profiles/BBL/process/fdm_process_bbl_0.16.json index ecc31c5421..3d60b01d8b 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.16.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.16.json @@ -20,5 +20,7 @@ "overhang_1_4_speed": "60", "overhang_2_4_speed": "30", "overhang_3_4_speed": "10", - "support_threshold_angle": "25" + "support_threshold_angle": "25", + "support_top_z_distance": "0.16", + "support_bottom_z_distance": "0.16" } \ No newline at end of file diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.18_nozzle_0.6.json b/resources/profiles/BBL/process/fdm_process_bbl_0.18_nozzle_0.6.json index 3baf1fd45d..0220f43a0d 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.18_nozzle_0.6.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.18_nozzle_0.6.json @@ -20,5 +20,7 @@ "sparse_infill_speed": "100", "top_surface_speed": "150", "bridge_speed": "30", - "overhang_3_4_speed": "15" + "overhang_3_4_speed": "15", + "support_top_z_distance": "0.18", + "support_bottom_z_distance": "0.18" } \ No newline at end of file diff --git a/resources/web/homepage/js/home.js b/resources/web/homepage/js/home.js index 17de9d6b3e..2fbaa43304 100644 --- a/resources/web/homepage/js/home.js +++ b/resources/web/homepage/js/home.js @@ -1,20 +1,15 @@ -/*var TestData={"sequence_id":"0","command":"studio_send_recentfile","data":[{"path":"D:\\work\\Models\\Toy\\3d-puzzle-cube-model_files\\3d-puzzle-cube.3mf","time":"2022\/3\/24 20:33:10"},{"path":"D:\\work\\Models\\Art\\Carved Stone Vase - remeshed+drainage\\Carved Stone Vase.3mf","time":"2022\/3\/24 17:11:51"},{"path":"D:\\work\\Models\\Art\\Kity & Cat\\Cat.3mf","time":"2022\/3\/24 17:07:55"},{"path":"D:\\work\\Models\\Toy\\鐩村墤.3mf","time":"2022\/3\/24 17:06:02"},{"path":"D:\\work\\Models\\Toy\\minimalistic-dual-tone-whistle-model_files\\minimalistic-dual-tone-whistle.3mf","time":"2022\/3\/22 21:12:22"},{"path":"D:\\work\\Models\\Toy\\spiral-city-model_files\\spiral-city.3mf","time":"2022\/3\/22 18:58:37"},{"path":"D:\\work\\Models\\Toy\\impossible-dovetail-puzzle-box-model_files\\impossible-dovetail-puzzle-box.3mf","time":"2022\/3\/22 20:08:40"}]};*/ +//var TestData={"sequence_id":"0","command":"get_recent_projects","response":[{"path":"D:\\work\\Models\\Toy\\3d-puzzle-cube-model_files\\3d-puzzle-cube.3mf","time":"2022\/3\/24 20:33:10"},{"path":"D:\\work\\Models\\Art\\Carved Stone Vase - remeshed+drainage\\Carved Stone Vase.3mf","time":"2022\/3\/24 17:11:51"},{"path":"D:\\work\\Models\\Art\\Kity & Cat\\Cat.3mf","time":"2022\/3\/24 17:07:55"},{"path":"D:\\work\\Models\\Toy\\鐩村墤.3mf","time":"2022\/3\/24 17:06:02"},{"path":"D:\\work\\Models\\Toy\\minimalistic-dual-tone-whistle-model_files\\minimalistic-dual-tone-whistle.3mf","time":"2022\/3\/22 21:12:22"},{"path":"D:\\work\\Models\\Toy\\spiral-city-model_files\\spiral-city.3mf","time":"2022\/3\/22 18:58:37"},{"path":"D:\\work\\Models\\Toy\\impossible-dovetail-puzzle-box-model_files\\impossible-dovetail-puzzle-box.3mf","time":"2022\/3\/22 20:08:40"}]}; var m_HotModelList=null; function OnInit() -{ - //-----Test----- - //Set_RecentFile_MouseRightBtn_Event(); - +{ //-----Official----- TranslatePage(); SendMsg_GetLoginInfo(); SendMsg_GetRecentFile(); SendMsg_GetStaffPick(); - - //InitStaffPick(); } //------最佳打开文件的右键菜单功能---------- @@ -311,14 +306,7 @@ function OnOpenRecentFile( strPath ) function OnDeleteRecentFile( ) { - var tSend={}; - tSend['sequence_id']=Math.round(new Date() / 1000); - tSend['command']="homepage_delete_recentfile"; - tSend['data']={}; - tSend['data']['path']=decodeURI(RightBtnFilePath); - - SendWXMessage( JSON.stringify(tSend) ); - + //Clear in UI $("#recnet_context_menu").hide(); let AllFile=$(".FileItem"); @@ -331,19 +319,27 @@ function OnDeleteRecentFile( ) } UpdateRecentClearBtnDisplay(); + + //Send Msg to C++ + var tSend={}; + tSend['sequence_id']=Math.round(new Date() / 1000); + tSend['command']="homepage_delete_recentfile"; + tSend['data']={}; + tSend['data']['path']=RightBtnFilePath; + + SendWXMessage( JSON.stringify(tSend) ); } function OnDeleteAllRecentFiles() { + $('#FileList').html(''); + UpdateRecentClearBtnDisplay(); + var tSend={}; tSend['sequence_id']=Math.round(new Date() / 1000); tSend['command']="homepage_delete_all_recentfile"; - SendWXMessage( JSON.stringify(tSend) ); - - $('#FileList').html(''); - - UpdateRecentClearBtnDisplay(); + SendWXMessage( JSON.stringify(tSend) ); } function UpdateRecentClearBtnDisplay() diff --git a/resources/web/homepage2/css/online.css b/resources/web/homepage2/css/online.css new file mode 100644 index 0000000000..cfed7f41ce --- /dev/null +++ b/resources/web/homepage2/css/online.css @@ -0,0 +1,162 @@ +.RedFont +{ + font-size:12px; + color: #F07E4A; +} + +.LinkBtn +{ + font-size:12px; + color: #1200FF; + cursor: pointer; +} + +.LinkBtn:hover +{ + text-decoration:underline; +} + + +/*------------------*/ + +/*--------------------*/ +#ContentBoard +{ + overflow-y:auto; + padding: 0px 40px; + display: flex; + flex-direction: column; + position: relative; + height: 100%; +} + +#Online_Models_Bar +{ + +} + +#ForU_Models_Bar +{ + display:none; +} + + +/*--Staff Pick--*/ +#HotModelArea +{ + display: none; + width: 100%; +} + +#HotModelList +{ + display: flex; + flex-wrap: wrap; + align-content: flex-start; +} + +.HotModelPiece +{ + display:flex; + flex-direction: column; + cursor: pointer; + border-radius: 8px; +} + +.HotModel_PrevBlock +{ + text-align: center; + background-color: #E4E4E4; + width: 100%; + border-radius: 8px; + line-height: 0px; + padding: 0px; +} + +.HotModel_PrevImg +{ + border-radius: 8px; + width: 100%; + aspect-ratio: 4/3; + object-fit: cover; +} + +.HotModel_Designer_Info +{ + display:flex; + align-items: center; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + padding: 4px 2px; +} + +.HotModel_Author_HeadIcon +{ + margin-right: 6px; + width: 32px; + height: 32px; +} + +.HotModel_Author_HeadIcon img +{ + width: 32px; + height: 32px; + border-radius: 16px; +} + +.HotModel_Right_1 +{ + flex: 1 1 auto; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding: 0px 4px; +} + +.HotModel_Name +{ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: 700; +} + + +.HotModel_Right_1_2 +{ + display:flex; +} + +.HotModel_Author_Name +{ + flex: 1 1 auto; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + margin-right: 4px; +} + + +.HotModel_click_info +{ + flex: 0 0 auto; + display: flex; + justify-content: flex-start; + align-items: center; + font-size: 12px; + overflow: hidden; +} + +.HotModel_click_info img +{ + width: 20px; + height: 20px; +} + +.Model_Click_Number +{ + display: flex; + align-items: center; +} + diff --git a/resources/web/homepage2/css/recent.css b/resources/web/homepage2/css/recent.css new file mode 100644 index 0000000000..1e3729e210 --- /dev/null +++ b/resources/web/homepage2/css/recent.css @@ -0,0 +1,257 @@ + + +#RecentFileArea +{ + flex: 1; + display: flex; + flex-direction: column; + position: relative; + top: 0px; + bottom: 0px; + right: 0px; + left: 0px; +} + +#RecentTitleBlock +{ + display:flex; + align-items: center; + justify-content:space-between; + padding: 6px 10px; +} + +#RecentClearAllBtn +{ + border-width: 1px; + border-style: solid; + padding: 0px 10px; + border-radius: 6px; + line-height: 26px; + height: 26px; + margin-left: 20px; + cursor: pointer; + display: none; +} + +#RecentClearAllBtn:hover +{ + background-color:#CDCECE; +} + +#Recent_LEFT_Title +{ + display:flex; + align-items: center; + padding: 0px 0px; +} + +#Right_Title_Block +{ + display:flex; + align-items: center; +} + +.Right_Title_Btn +{ + display:flex; + align-items: center; + margin-right: 16px; +} + +.Right_Title_Btn_Icon +{ + width:16px; + height: 16px; + margin-right: 6px; +} + +#Menu_Delete +{ + display:none; +} + +#Menu_Cancel +{ + display:none; +} + +#FileList +{ + flex: 1; + display: flex; + flex-wrap: wrap; + align-content: flex-start; + overflow-y: auto; +} + +.FileItem +{ + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + word-break: break-all; + position: relative; + cursor: pointer; + border-radius: 8px; +} + +.FileMask +{ + position:absolute; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + background-color: darkgrey; + opacity: 0.3; + display: none; +} + +.FileCheckBox +{ + position:absolute; + top: 14px; + left: 14px; + width: 26px; + height: 26px; + border:1px solid grey; + border-radius: 4px; + background-color: white; + display: none; +} + +.FileCheckBox_checked +{ + background-image: url("../img/checkbox.svg"); + background-size: contain; +} + +.FileCheckBox_checked:hover +{ + background-image: url("../img/checkbox_hover.svg"); +} + +.FileTip +{ + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; +} + +.FileImg +{ + text-align: center; + background-color: #E4E4E4; + width: 100%; + border-radius: 8px; + line-height: 0px; +} + +.FileImg img +{ + border-radius: 8px; + width: 100%; + aspect-ratio: 4/3; + object-fit: cover; +} + +.FileName +{ + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + word-break: break-all; + line-height: 32px; + font-weight: 700; + padding: 0px 4px; +} + +.FileDate +{ + color: #A8A8A8; + font-size: 10px; + padding: 0px 4px; +} + +#recnet_context_menu +{ + position: absolute; + margin: 0px; + padding: 10px; + border: 0px; + min-width: 100px; + border: 1px solid #D7D7D7; + top: 100px; + border-radius: 5px; + color: #323A3D; + background-color: #fff; + display: none; + z-index: 1; +} + +.CT_Item +{ + padding: 4px 12px; + display: flex; + flex-direction: row; + align-items: center; +} + +.CT_Item:hover +{ + cursor: pointer; + background-color: #0078D4; + border-radius: 4px; + color: #fff; +} + + +.CT_Icon +{ + margin-right: 6px; + width: 16px; + height: 16px; +} + +#CT_Delete_Bar:hover .CT_Delete +{ + background: url("../img/remove2.svg"); + background-repeat: no-repeat; + background-size: contain; +} + +.CT_Delete +{ + background: url("../img/remove.svg"); + background-repeat: no-repeat; + background-size: contain; +} + +#CT_Folder_Bar:hover .CT_Explore +{ + background: url("../img/open_folder2.svg"); + background-repeat: no-repeat; + background-size: contain; +} + +.CT_Explore +{ + background: url("../img/open_folder.svg"); + background-repeat: no-repeat; + background-size: contain; +} + + +.CT_Seperate +{ + border-bottom:1px solid #C5C5C5; +} + +.CT_Text +{ + line-height: 20px; + height: 20px; + display: block; +} \ No newline at end of file diff --git a/resources/web/model/model.js b/resources/web/model/model.js index 30bbdce678..b401bea75b 100644 --- a/resources/web/model/model.js +++ b/resources/web/model/model.js @@ -206,6 +206,12 @@ function ShowModelInfo( pModel ) let sLicence=pModel.license.toUpperCase(); let sModelDesc=decodeURIComponent(pModel.description); + if( pModel.hasOwnProperty('model_id') ) + { + let m_id=pModel['model_id']+''; + UpdateModelID( m_id.trim() ); + } + SendWXDebugInfo("Model Name: "+sModelName); $('#ModelName').html(sModelName); diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index 1a3b6ca859..b5530bc628 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -80,6 +80,7 @@ using namespace nlohmann; #include "slic3r/GUI/OpenGLManager.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/Camera.hpp" +#include "slic3r/GUI/Plater.hpp" #include #ifdef __WXGTK__ @@ -124,6 +125,7 @@ std::map cli_errors = { {CLI_OBJECT_ARRANGE_FAILED, "An error occurred when auto-arranging object(s)."}, {CLI_OBJECT_ORIENT_FAILED, "An error occurred when auto-orienting object(s)."}, {CLI_MODIFIED_PARAMS_TO_PRINTER, "Found modified parameter in printer preset in the 3mf file, which should not be changed."}, + {CLI_FILE_VERSION_NOT_SUPPORTED, "Unsupported 3MF version. Please make sure the 3MF file was created with the official version of Bambu Studio, not a beta version."}, {CLI_NO_SUITABLE_OBJECTS, "One of the plate is empty or has no object fully inside it. Please check that the 3mf contains no empty plate in Orca Slicer before uploading."}, {CLI_VALIDATE_ERROR, "There are some incorrect slicing parameters in the 3mf. Please verify the slicing of all plates in Orca Slicer before uploading."}, {CLI_OBJECTS_PARTLY_INSIDE, "Some objects are located over the boundary of the heated bed."}, @@ -889,6 +891,8 @@ int CLI::run(int argc, char **argv) // instruct the window manager to fall back to X server mode. ::setenv("GDK_BACKEND", "x11", /* replace */ true); + ::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false); + // Also on Linux, we need to tell Xlib that we will be using threads, // lest we crash when we fire up GStreamer. XInitThreads(); @@ -1028,7 +1032,7 @@ int CLI::run(int argc, char **argv) int arrange_option; int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0; bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false; - bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false; + bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false; Semver file_version; std::map orients_requirement; std::vector project_presets; @@ -1073,6 +1077,14 @@ int CLI::run(int argc, char **argv) if (skip_modified_gcodes_option) skip_modified_gcodes = skip_modified_gcodes_option->value; + ConfigOptionBool* skip_useless_picks_option = m_config.option("skip_useless_pick"); + if (skip_useless_picks_option) + skip_useless_pick = skip_useless_picks_option->value; + + ConfigOptionBool* allow_newer_file_option = m_config.option("allow_newer_file"); + if (allow_newer_file_option) + allow_newer_file = allow_newer_file_option->value; + ConfigOptionBool* avoid_extrusion_cali_region_option = m_config.option("avoid_extrusion_cali_region"); if (avoid_extrusion_cali_region_option) avoid_extrusion_cali_region = avoid_extrusion_cali_region_option->value; @@ -1124,8 +1136,8 @@ int CLI::run(int argc, char **argv) const std::vector clone_objects = m_config.option("clone_objects", true)->values; //when load objects from stl/obj, the total used filaments set std::set used_filament_set; - BOOST_LOG_TRIVIAL(info) << boost::format("allow_multicolor_oneplate %1%, allow_rotations %2% skip_modified_gcodes %3% avoid_extrusion_cali_region %4% loaded_filament_ids size %5%, clone_objects size %6%") - %allow_multicolor_oneplate %allow_rotations %skip_modified_gcodes %avoid_extrusion_cali_region %loaded_filament_ids.size() %clone_objects.size(); + BOOST_LOG_TRIVIAL(info) << boost::format("allow_multicolor_oneplate %1%, allow_rotations %2% skip_modified_gcodes %3% avoid_extrusion_cali_region %4% loaded_filament_ids size %5%, clone_objects size %6%, skip_useless_pick %7%, allow_newer_file %8%") + %allow_multicolor_oneplate %allow_rotations %skip_modified_gcodes %avoid_extrusion_cali_region %loaded_filament_ids.size() %clone_objects.size() %skip_useless_pick %allow_newer_file; if (clone_objects.size() > 0) { if (clone_objects.size() != m_input_files.size()) @@ -1223,6 +1235,12 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << "object "<name <<", id :" << o->id().id << ", from bbl 3mf\n"; }*/ + Semver cli_ver = *Semver::parse(SLIC3R_VERSION); + if (!allow_newer_file && ((cli_ver.maj() != file_version.maj()) || (cli_ver.min() < file_version.min()))){ + BOOST_LOG_TRIVIAL(error) << boost::format("Version Check: File Version %1% not supported by current cli version %2%")%file_version.to_string() %SLIC3R_VERSION; + record_exit_reson(outfile_dir, CLI_FILE_VERSION_NOT_SUPPORTED, 0, cli_errors[CLI_FILE_VERSION_NOT_SUPPORTED], sliced_info); + flush_and_exit(CLI_FILE_VERSION_NOT_SUPPORTED); + } Semver old_version(1, 5, 9), old_version2(1, 5, 9); if ((file_version < old_version) && !config.empty()) { translate_old = true; @@ -2605,8 +2623,8 @@ int CLI::run(int argc, char **argv) //flush_vol_vector.resize(project_filament_count); //set multiplier to 1? m_print_config.option("flush_multiplier", true)->set(new ConfigOptionFloat(1.f)); - ConfigOption* extra_flush_volume_opt = m_print_config.option("nozzle_volume"); - int extra_flush_volume = extra_flush_volume_opt ? (int)extra_flush_volume_opt->getFloat() : 0; + + const std::vector& min_flush_volumes = Slic3r::GUI::get_min_flush_volumes(); if (filament_is_support->size() != project_filament_count) { @@ -2615,9 +2633,13 @@ int CLI::run(int argc, char **argv) flush_and_exit(CLI_CONFIG_FILE_ERROR); } - BOOST_LOG_TRIVIAL(info) << boost::format("extra_flush_volume: %1%")%extra_flush_volume; - BOOST_LOG_TRIVIAL(info) << boost::format("filament_is_support: %1%")%filament_is_support->serialize(); - BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix before computing: %1%")%m_print_config.option("flush_volumes_matrix")->serialize(); + { + std::ostringstream volumes_str; + std::copy(min_flush_volumes.begin(), min_flush_volumes.end(), std::ostream_iterator(volumes_str, ",")); + BOOST_LOG_TRIVIAL(info) << boost::format("extra_flush_volume: %1%") % volumes_str.str(); + BOOST_LOG_TRIVIAL(info) << boost::format("filament_is_support: %1%") % filament_is_support->serialize(); + BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix before computing: %1%") % m_print_config.option("flush_volumes_matrix")->serialize(); + } for (int from_idx = 0; from_idx < project_filament_count; from_idx++) { const std::string& from_color = project_filament_colors[from_idx]; unsigned char from_rgb[4] = {}; @@ -2641,7 +2663,7 @@ int CLI::run(int argc, char **argv) //BOOST_LOG_TRIVIAL(info) << boost::format("src_rgba {%1%,%2%,%3%,%4%} dst_rgba {%5%,%6%,%7%,%8%}")%(unsigned int)(from_rgb[0]) %(unsigned int)(from_rgb[1]) %(unsigned int)(from_rgb[2]) %(unsigned int)(from_rgb[3]) // %(unsigned int)(to_rgb[0]) %(unsigned int)(to_rgb[1]) %(unsigned int)(to_rgb[2]) %(unsigned int)(to_rgb[3]); - Slic3r::FlushVolCalculator calculator(extra_flush_volume, Slic3r::g_max_flush_volume); + Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], Slic3r::g_max_flush_volume); flushing_volume = calculator.calc_flush_vol(from_rgb[3], from_rgb[0], from_rgb[1], from_rgb[2], to_rgb[3], to_rgb[0], to_rgb[1], to_rgb[2]); if (is_from_support) { @@ -3540,6 +3562,7 @@ int CLI::run(int argc, char **argv) bool finished_arrange = false, first_run = true; Slic3r::GUI::PartPlate* cur_plate = nullptr; int low_duplicate_count = 0, up_duplicate_count = duplicate_count, arrange_count = 0; + float orig_wipe_x = 0.f, orig_wipe_y = 0.f; if (duplicate_count > 0) { original_model = model; @@ -3566,8 +3589,22 @@ int CLI::run(int argc, char **argv) unprintable.clear(); locked_aps.clear(); } - else + else { first_run = false; + if (plate_to_slice > 0) { + ConfigOptionFloats* wipe_x_option = m_print_config.option("wipe_tower_x"); + ConfigOptionFloats* wipe_y_option = m_print_config.option("wipe_tower_y"); + + if (wipe_x_option && (wipe_x_option->size() > (plate_to_slice-1))) { + orig_wipe_x = wipe_x_option->get_at(plate_to_slice-1); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, plate_to_slice %2%, orig_wipe_x=%3%")%__LINE__%plate_to_slice%orig_wipe_x; + } + if (wipe_y_option && (wipe_y_option->size() > (plate_to_slice-1))) { + orig_wipe_y = wipe_y_option->get_at(plate_to_slice-1); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, plate_to_slice %2%, orig_wipe_y=%3%")%__LINE__%plate_to_slice%orig_wipe_y; + } + } + } cur_plate = (Slic3r::GUI::PartPlate *)partplate_list.get_plate(plate_to_slice-1); cur_plate->duplicate_all_instance(duplicate_count, need_skip, skip_maps); @@ -4000,11 +4037,22 @@ int CLI::run(int argc, char **argv) if (duplicate_count == 0) { //restore to the original - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": restore to the original model and plates"); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": restore to the original model and plates, orig_wipe_x %1%, orig_wipe_y %2%")%orig_wipe_x %orig_wipe_y; finished_arrange = true; model = original_model; partplate_list.load_from_3mf_structure(plate_data_src); partplate_list.reset_size(current_printable_width, current_printable_depth, current_printable_height, true, true); + if ((orig_wipe_x > 0.f) && (orig_wipe_y > 0.f)) + { + ConfigOptionFloat wt_x_opt(orig_wipe_x); + ConfigOptionFloat wt_y_opt(orig_wipe_y); + ConfigOptionFloats* wipe_x_option = m_print_config.option("wipe_tower_x", true); + ConfigOptionFloats* wipe_y_option = m_print_config.option("wipe_tower_y", true); + + wipe_x_option->set_at(&wt_x_opt, plate_to_slice-1, 0); + wipe_y_option->set_at(&wt_y_opt, plate_to_slice-1, 0); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": restore wipe_tower position to {%1%, %2%}")%orig_wipe_x %orig_wipe_y; + } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": exit arrange process"); } continue; @@ -4013,7 +4061,7 @@ int CLI::run(int argc, char **argv) if (duplicate_single_object) { if (real_duplicate_count <= 1) { - BOOST_LOG_TRIVIAL(warning) << "no object can be placed under single object mode, restore to the original model and plates also" << std::endl; + BOOST_LOG_TRIVIAL(warning) << boost::format("no object can be placed under single object mode, restore to the original model and plates also, orig_wipe_x %1%, orig_wipe_y %2%")%orig_wipe_x %orig_wipe_y; //record_exit_reson(outfile_dir, CLI_OBJECT_ARRANGE_FAILED, 0, cli_errors[CLI_OBJECT_ARRANGE_FAILED], sliced_info); //flush_and_exit(CLI_OBJECT_ARRANGE_FAILED); finished_arrange = true; @@ -4021,6 +4069,17 @@ int CLI::run(int argc, char **argv) partplate_list.load_from_3mf_structure(plate_data_src); partplate_list.reset_size(current_printable_width, current_printable_depth, current_printable_height, true, true); duplicate_count = 0; + if ((orig_wipe_x > 0.f) && (orig_wipe_y > 0.f)) + { + ConfigOptionFloat wt_x_opt(orig_wipe_x); + ConfigOptionFloat wt_y_opt(orig_wipe_y); + ConfigOptionFloats* wipe_x_option = m_print_config.option("wipe_tower_x", true); + ConfigOptionFloats* wipe_y_option = m_print_config.option("wipe_tower_y", true); + + wipe_x_option->set_at(&wt_x_opt, plate_to_slice-1, 0); + wipe_y_option->set_at(&wt_y_opt, plate_to_slice-1, 0); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": restore wipe_tower position to {%1%, %2%}")%orig_wipe_x %orig_wipe_y; + } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": exit arrange process"); continue; } diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 2593777969..0f1a0cec88 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -45,7 +45,7 @@ typedef Eigen::Matrix stl_triangle_vertex_indices static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); -typedef std::function ImportstlProgressFn; +typedef std::function ImportstlProgressFn; typedef enum { eNormal, // normal face @@ -98,8 +98,12 @@ struct stl_neighbors { }; struct stl_stats { - stl_stats() { memset(&header, 0, 81); } - char header[81]; + stl_stats() {} + void reset_header(int size) { + header.clear(); + header.resize(size +1); + } + std::vector header; stl_type type = (stl_type)0; // Should always match the number of facets stored inside stl_file::facet_start. uint32_t number_of_facets = 0; @@ -247,7 +251,7 @@ struct indexed_triangle_set } }; -extern bool stl_open(stl_file *stl, const char *file, ImportstlProgressFn stlFn = nullptr); +extern bool stl_open(stl_file *stl, const char *file, ImportstlProgressFn stlFn = nullptr,int custom_header_length = 80); extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file); extern bool stl_print_neighbors(stl_file *stl, char *file); extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label); diff --git a/src/admesh/stl_io.cpp b/src/admesh/stl_io.cpp index 26f5dc3212..221572bca6 100644 --- a/src/admesh/stl_io.cpp +++ b/src/admesh/stl_io.cpp @@ -41,7 +41,7 @@ void stl_stats_out(stl_file *stl, FILE *file, char *input_file) fprintf(file, "File type : Binary STL file\n"); else fprintf(file, "File type : ASCII STL file\n"); - fprintf(file, "Header : %s\n", stl->stats.header); + fprintf(file, "Header : %s\n", stl->stats.header.data()); fprintf(file, "============== Size ==============\n"); fprintf(file, "Min X = % f, Max X = % f\n", stl->stats.min(0), stl->stats.max(0)); fprintf(file, "Min Y = % f, Max Y = % f\n", stl->stats.min(1), stl->stats.max(1)); diff --git a/src/admesh/stlinit.cpp b/src/admesh/stlinit.cpp index ec044f87e5..8196bf10cb 100644 --- a/src/admesh/stlinit.cpp +++ b/src/admesh/stlinit.cpp @@ -45,8 +45,9 @@ extern void stl_internal_reverse_quads(char *buf, size_t cnt); const int LOAD_STL_UNIT_NUM = 5; static std::string model_id = ""; +static std::string country_code = ""; -static FILE* stl_open_count_facets(stl_file *stl, const char *file) +static FILE *stl_open_count_facets(stl_file *stl, const char *file, unsigned int custom_header_length) { // Open the file in binary mode first. FILE *fp = boost::nowide::fopen(file, "rb"); @@ -59,7 +60,8 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) long file_size = ftell(fp); // Check for binary or ASCII file. - fseek(fp, HEADER_SIZE, SEEK_SET); + int header_size = custom_header_length + NUM_FACET_SIZE; + fseek(fp, header_size, SEEK_SET); unsigned char chtest[128]; if (! fread(chtest, sizeof(chtest), 1, fp)) { BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The input is an empty file: " << file; @@ -81,16 +83,16 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) // If the .STL file is binary, then do the following: if (stl->stats.type == binary) { // Test if the STL file has the right size. - if (((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) || (file_size < STL_MIN_FILE_SIZE)) { + if (((file_size - header_size) % SIZEOF_STL_FACET != 0) || (file_size < STL_MIN_FILE_SIZE)) { BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The file " << file << " has the wrong size."; fclose(fp); return nullptr; } - num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET; + num_facets = (file_size - header_size) / SIZEOF_STL_FACET; // Read the header. - if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79) - stl->stats.header[80] = '\0'; + if (fread(stl->stats.header.data(), custom_header_length, 1, fp) > custom_header_length -1) + stl->stats.header[custom_header_length] = '\0'; // Read the int following the header. This should contain # of facets. uint32_t header_num_facets; @@ -134,9 +136,9 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) // Get the header. int i = 0; - for (; i < 80 && (stl->stats.header[i] = getc(fp)) != '\n'; ++ i) ; + for (; i < custom_header_length && (stl->stats.header[i] = getc(fp)) != '\n'; ++ i) ; stl->stats.header[i] = '\0'; // Lose the '\n' - stl->stats.header[80] = '\0'; + stl->stats.header[custom_header_length] = '\0'; num_facets = num_lines / ASCII_LINES_PER_FACET; } @@ -149,10 +151,13 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) /* Reads the contents of the file pointed to by fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ -static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, ImportstlProgressFn stlFn) +static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, ImportstlProgressFn stlFn, int custom_header_length) { if (stl->stats.type == binary) { - fseek(fp, HEADER_SIZE, SEEK_SET); + int header_size = custom_header_length + NUM_FACET_SIZE; + fseek(fp, header_size, SEEK_SET); + model_id = ""; + country_code = ""; } else { rewind(fp); @@ -165,18 +170,22 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor // Extract the value after "MW" char version_str[16]; char model_id_str[128]; - int num_values = sscanf(mw_position + 3, "%s %s", version_str, model_id_str); - if (num_values == 2) { + char country_code_str[16]; + int num_values = sscanf(mw_position + 3, "%s %s %s", version_str, model_id_str, country_code_str); + if (num_values == 3) { if (strcmp(version_str, "1.0") == 0) { model_id = model_id_str; + country_code = country_code_str; } } else { model_id = ""; + country_code = ""; } } else { model_id = ""; // No MW format found + country_code = ""; } } } @@ -195,7 +204,7 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor if ((i % unit) == 0) { bool cb_cancel = false; if (stlFn) { - stlFn(i, facets_num, cb_cancel, model_id); + stlFn(i, facets_num, cb_cancel, model_id, country_code); if (cb_cancel) return false; } @@ -293,20 +302,24 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor return true; } -bool stl_open(stl_file *stl, const char *file, ImportstlProgressFn stlFn) +bool stl_open(stl_file *stl, const char *file, ImportstlProgressFn stlFn, int custom_header_length) { + if (custom_header_length < LABEL_SIZE) { + custom_header_length = LABEL_SIZE; + } Slic3r::CNumericLocalesSetter locales_setter; stl->clear(); - FILE *fp = stl_open_count_facets(stl, file); + stl->stats.reset_header(custom_header_length); + FILE *fp = stl_open_count_facets(stl, file, custom_header_length); if (fp == nullptr) return false; stl_allocate(stl); - bool result = stl_read(stl, fp, 0, true, stlFn); + bool result = stl_read(stl, fp, 0, true, stlFn, custom_header_length); fclose(fp); return result; } -void stl_allocate(stl_file *stl) +void stl_allocate(stl_file *stl) { // Allocate memory for the entire .STL file. stl->facet_start.assign(stl->stats.number_of_facets, stl_facet()); @@ -314,7 +327,7 @@ void stl_allocate(stl_file *stl) stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors()); } -void stl_reallocate(stl_file *stl) +void stl_reallocate(stl_file *stl) { stl->facet_start.resize(stl->stats.number_of_facets); stl->neighbors_start.resize(stl->stats.number_of_facets); diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index bec3f3c9ae..9e9b56e9d8 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -279,6 +279,10 @@ void AppConfig::set_defaults() set_bool("remember_printer_config", true); } + if (get("auto_calculate_when_filament_change").empty()){ + set_bool("auto_calculate_when_filament_change", true); + } + if (get("show_home_page").empty()) { set_bool("show_home_page", true); } @@ -562,6 +566,8 @@ std::string AppConfig::load() cali_info.cali_finished = bool(calis_j["cali_finished"].get()); if (calis_j.contains("flow_ratio")) cali_info.cache_flow_ratio = calis_j["flow_ratio"].get(); + if (calis_j.contains("cache_flow_rate_calibration_type")) + cali_info.cache_flow_rate_calibration_type = static_cast(calis_j["cache_flow_rate_calibration_type"].get()); if (calis_j.contains("presets")) { cali_info.selected_presets.clear(); for (auto cali_it = calis_j["presets"].begin(); cali_it != calis_j["presets"].end(); cali_it++) { @@ -684,6 +690,7 @@ void AppConfig::save() cali_json["dev_id"] = cali_info.dev_id; cali_json["flow_ratio"] = cali_info.cache_flow_ratio; cali_json["cali_finished"] = cali_info.cali_finished ? 1 : 0; + cali_json["cache_flow_rate_calibration_type"] = static_cast(cali_info.cache_flow_rate_calibration_type); for (auto filament_preset : cali_info.selected_presets) { json preset_json; preset_json["tray_id"] = filament_preset.tray_id; @@ -1036,6 +1043,7 @@ void AppConfig::save_printer_cali_infos(const PrinterCaliInfo &cali_info, bool n } (*iter).cache_flow_ratio = cali_info.cache_flow_ratio; (*iter).selected_presets = cali_info.selected_presets; + (*iter).cache_flow_rate_calibration_type = cali_info.cache_flow_rate_calibration_type; } m_dirty = true; } diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp index b7e0ea61e9..5d085f333b 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp @@ -10,37 +10,17 @@ #include #include -#include "utils/VoronoiUtils.hpp" - #include "utils/linearAlg2D.hpp" #include "Utils.hpp" #include "SVG.hpp" #include "Geometry/VoronoiVisualUtils.hpp" #include "Geometry/VoronoiUtilsCgal.hpp" #include "../EdgeGrid.hpp" -#include "ankerl/unordered_dense.h" + +#include "Geometry/VoronoiUtils.hpp" #define SKELETAL_TRAPEZOIDATION_BEAD_SEARCH_MAX 1000 //A limit to how long it'll keep searching for adjacent beads. Increasing will re-use beadings more often (saving performance), but search longer for beading (costing performance). -namespace boost::polygon { - -template<> struct geometry_concept -{ - typedef segment_concept type; -}; - -template<> struct segment_traits -{ - typedef coord_t coordinate_type; - typedef Slic3r::Point point_type; - static inline point_type get(const Slic3r::Arachne::PolygonsSegmentIndex &CSegment, direction_1d dir) - { - return dir.to_int() ? CSegment.p() : CSegment.next().p(); - } -}; - -} // namespace boost::polygon - namespace Slic3r::Arachne { @@ -109,8 +89,7 @@ static void export_graph_to_svg(const std::string } #endif -SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_type& vd_node, Point p) -{ +SkeletalTrapezoidation::node_t &SkeletalTrapezoidation::makeNode(const VD::vertex_type &vd_node, Point p) { auto he_node_it = vd_node_to_he_node.find(&vd_node); if (he_node_it == vd_node_to_he_node.end()) { @@ -125,8 +104,7 @@ SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_ty } } -void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector& segments) -{ +void SkeletalTrapezoidation::transferEdge(Point from, Point to, const VD::edge_type &vd_edge, edge_t *&prev_edge, Point &start_source_point, Point &end_source_point, const std::vector &segments) { auto he_edge_it = vd_edge_to_he_edge.find(vd_edge.twin()); if (he_edge_it != vd_edge_to_he_edge.end()) { // Twin segment(s) have already been made @@ -181,7 +159,7 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& } else { - std::vector discretized = discretize(vd_edge, segments); + Points discretized = discretize(vd_edge, segments); assert(discretized.size() >= 2); if(discretized.size() < 2) { @@ -236,45 +214,42 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& } } -std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector& segments) +Points SkeletalTrapezoidation::discretize(const VD::edge_type& vd_edge, const std::vector& segments) { + assert(Geometry::VoronoiUtils::is_in_range(vd_edge)); + /*Terminology in this function assumes that the edge moves horizontally from left to right. This is not necessarily the case; the edge can go in any direction, but it helps to picture it in a certain direction in your head.*/ - const vd_t::cell_type* left_cell = vd_edge.cell(); - const vd_t::cell_type* right_cell = vd_edge.twin()->cell(); + const VD::cell_type *left_cell = vd_edge.cell(); + const VD::cell_type *right_cell = vd_edge.twin()->cell(); - assert(VoronoiUtils::p(vd_edge.vertex0()).x() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge.vertex0()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge.vertex0()).y() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge.vertex0()).y() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge.vertex1()).x() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge.vertex1()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge.vertex1()).y() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge.vertex1()).y() >= std::numeric_limits::lowest()); + Point start = Geometry::VoronoiUtils::to_point(vd_edge.vertex0()).cast(); + Point end = Geometry::VoronoiUtils::to_point(vd_edge.vertex1()).cast(); - Point start = VoronoiUtils::p(vd_edge.vertex0()).cast(); - Point end = VoronoiUtils::p(vd_edge.vertex1()).cast(); - bool point_left = left_cell->contains_point(); bool point_right = right_cell->contains_point(); if ((!point_left && !point_right) || vd_edge.is_secondary()) // Source vert is directly connected to source segment { - return std::vector({ start, end }); + return Points({ start, end }); } else if (point_left != point_right) //This is a parabolic edge between a point and a line. { - Point p = VoronoiUtils::getSourcePoint(*(point_left ? left_cell : right_cell), segments); - const Segment& s = VoronoiUtils::getSourceSegment(*(point_left ? right_cell : left_cell), segments); - return VoronoiUtils::discretizeParabola(p, s, start, end, discretization_step_size, transitioning_angle); + Point p = Geometry::VoronoiUtils::get_source_point(*(point_left ? left_cell : right_cell), segments.begin(), segments.end()); + const Segment& s = Geometry::VoronoiUtils::get_source_segment(*(point_left ? right_cell : left_cell), segments.begin(), segments.end()); + return Geometry::VoronoiUtils::discretize_parabola(p, s, start, end, discretization_step_size, transitioning_angle); } else //This is a straight edge between two points. { /*While the edge is straight, it is still discretized since the part becomes narrower between the two points. As such it may need different beadings along the way.*/ - Point left_point = VoronoiUtils::getSourcePoint(*left_cell, segments); - Point right_point = VoronoiUtils::getSourcePoint(*right_cell, segments); - coord_t d = (right_point - left_point).cast().norm(); - Point middle = (left_point + right_point) / 2; - Point x_axis_dir = Point(right_point - left_point).rotate_90_degree_ccw(); + Point left_point = Geometry::VoronoiUtils::get_source_point(*left_cell, segments.begin(), segments.end()); + Point right_point = Geometry::VoronoiUtils::get_source_point(*right_cell, segments.begin(), segments.end()); + coord_t d = (right_point - left_point).cast().norm(); + Point middle = (left_point + right_point) / 2; + Point x_axis_dir = perp(Point(right_point - left_point)); coord_t x_axis_length = x_axis_dir.cast().norm(); const auto projected_x = [x_axis_dir, x_axis_length, middle](Point from) //Project a point on the edge. @@ -311,7 +286,7 @@ std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_ //Start generating points along the edge. Point a = start; Point b = end; - std::vector ret; + Points ret; ret.emplace_back(a); //Introduce an extra edge at the borders of the markings? @@ -351,8 +326,7 @@ std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_ } } -bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector& segments) -{ +bool SkeletalTrapezoidation::computePointCellRange(const VD::cell_type &cell, Point &start_source_point, Point &end_source_point, const VD::edge_type *&starting_vd_edge, const VD::edge_type *&ending_vd_edge, const std::vector &segments) { if (cell.incident_edge()->is_infinite()) return false; //Infinite edges only occur outside of the polygon. Don't copy any part of this cell. @@ -360,16 +334,16 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& // Copy whole cell into graph or not at all // If the cell.incident_edge()->vertex0() is far away so much that it doesn't even fit into Vec2i64, then there is no way that it will be inside the input polygon. - if (const vd_t::vertex_type &vert = *cell.incident_edge()->vertex0(); + if (const VD::vertex_type &vert = *cell.incident_edge()->vertex0(); vert.x() >= double(std::numeric_limits::max()) || vert.x() <= double(std::numeric_limits::lowest()) || vert.y() >= double(std::numeric_limits::max()) || vert.y() <= double(std::numeric_limits::lowest())) return false; // Don't copy any part of this cell - const Point source_point = VoronoiUtils::getSourcePoint(cell, segments); - const PolygonsPointIndex source_point_index = VoronoiUtils::getSourcePointIndex(cell, segments); - Vec2i64 some_point = VoronoiUtils::p(cell.incident_edge()->vertex0()); + const Point source_point = Geometry::VoronoiUtils::get_source_point(cell, segments.begin(), segments.end()); + const PolygonsPointIndex source_point_index = Geometry::VoronoiUtils::get_source_point_index(cell, segments.begin(), segments.end()); + Vec2i64 some_point = Geometry::VoronoiUtils::to_point(cell.incident_edge()->vertex0()); if (some_point == source_point.cast()) - some_point = VoronoiUtils::p(cell.incident_edge()->vertex1()); + some_point = Geometry::VoronoiUtils::to_point(cell.incident_edge()->vertex1()); //Test if the some_point is even inside the polygon. //The edge leading out of a polygon must have an endpoint that's not in the corner following the contour of the polygon at that vertex. @@ -378,16 +352,16 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& if (!LinearAlg2D::isInsideCorner(source_point_index.prev().p(), source_point_index.p(), source_point_index.next().p(), some_point)) return false; // Don't copy any part of this cell - vd_t::edge_type* vd_edge = cell.incident_edge(); + const VD::edge_type* vd_edge = cell.incident_edge(); do { assert(vd_edge->is_finite()); - if (Vec2i64 p1 = VoronoiUtils::p(vd_edge->vertex1()); p1 == source_point.cast()) { + if (Vec2i64 p1 = Geometry::VoronoiUtils::to_point(vd_edge->vertex1()); p1 == source_point.cast()) { start_source_point = source_point; end_source_point = source_point; starting_vd_edge = vd_edge->next(); ending_vd_edge = vd_edge; } else { - assert((VoronoiUtils::p(vd_edge->vertex0()) == source_point.cast() || !vd_edge->is_secondary()) && "point cells must end in the point! They cannot cross the point with an edge, because collinear edges are not allowed in the input."); + assert((Geometry::VoronoiUtils::to_point(vd_edge->vertex0()) == source_point.cast() || !vd_edge->is_secondary()) && "point cells must end in the point! They cannot cross the point with an edge, because collinear edges are not allowed in the input."); } } while (vd_edge = vd_edge->next(), vd_edge != cell.incident_edge()); @@ -396,47 +370,6 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& return true; } -void SkeletalTrapezoidation::computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector& segments) -{ - const Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments); - const Point from = source_segment.from(); - const Point to = source_segment.to(); - - // Find starting edge - // Find end edge - bool seen_possible_start = false; - bool after_start = false; - bool ending_edge_is_set_before_start = false; - vd_t::edge_type* edge = cell.incident_edge(); - do { - if (edge->is_infinite()) - continue; - - Vec2i64 v0 = VoronoiUtils::p(edge->vertex0()); - Vec2i64 v1 = VoronoiUtils::p(edge->vertex1()); - - assert(!(v0 == to.cast() && v1 == from.cast() )); - if (v0 == to.cast() && !after_start) { // Use the last edge which starts in source_segment.to - starting_vd_edge = edge; - seen_possible_start = true; - } - else if (seen_possible_start) { - after_start = true; - } - - if (v1 == from.cast() && (!ending_vd_edge || ending_edge_is_set_before_start)) { - ending_edge_is_set_before_start = !after_start; - ending_vd_edge = edge; - } - } while (edge = edge->next(), edge != cell.incident_edge()); - - assert(starting_vd_edge && ending_vd_edge); - assert(starting_vd_edge != ending_vd_edge); - - start_source_point = source_segment.to(); - end_source_point = source_segment.from(); -} - SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const BeadingStrategy& beading_strategy, double transitioning_angle, coord_t discretization_step_size, coord_t transition_filter_dist, coord_t allowed_filter_deviation, @@ -451,128 +384,6 @@ SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const Bead constructFromPolygons(polys); } -static bool has_finite_edge_with_non_finite_vertex(const Geometry::VoronoiDiagram &voronoi_diagram) -{ - for (const VoronoiUtils::vd_t::edge_type &edge : voronoi_diagram.edges()) { - if (edge.is_finite()) { - assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr); - if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || - !VoronoiUtils::is_finite(*edge.vertex1())) - return true; - } - } - return false; -} - -static bool detect_missing_voronoi_vertex(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector &segments) { - if (has_finite_edge_with_non_finite_vertex(voronoi_diagram)) - return true; - - for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) { - if (!cell.incident_edge()) - continue; // There is no spoon - - if (cell.contains_segment()) { - const SkeletalTrapezoidation::Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments); - const Point from = source_segment.from(); - const Point to = source_segment.to(); - - // Find starting edge - // Find end edge - bool seen_possible_start = false; - bool after_start = false; - bool ending_edge_is_set_before_start = false; - VoronoiUtils::vd_t::edge_type *starting_vd_edge = nullptr; - VoronoiUtils::vd_t::edge_type *ending_vd_edge = nullptr; - VoronoiUtils::vd_t::edge_type *edge = cell.incident_edge(); - do { - if (edge->is_infinite() || edge->vertex0() == nullptr || edge->vertex1() == nullptr || !VoronoiUtils::is_finite(*edge->vertex0()) || !VoronoiUtils::is_finite(*edge->vertex1())) - continue; - - Vec2i64 v0 = VoronoiUtils::p(edge->vertex0()); - Vec2i64 v1 = VoronoiUtils::p(edge->vertex1()); - - assert(!(v0 == to.cast() && v1 == from.cast())); - if (v0 == to.cast() && !after_start) { // Use the last edge which starts in source_segment.to - starting_vd_edge = edge; - seen_possible_start = true; - } else if (seen_possible_start) { - after_start = true; - } - - if (v1 == from.cast() && (!ending_vd_edge || ending_edge_is_set_before_start)) { - ending_edge_is_set_before_start = !after_start; - ending_vd_edge = edge; - } - } while (edge = edge->next(), edge != cell.incident_edge()); - - if (!starting_vd_edge || !ending_vd_edge || starting_vd_edge == ending_vd_edge) - return true; - } - } - - return false; -} - -static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph) -{ - for (const auto &edge : graph.edges) - if (edge.twin == nullptr) - return true; - return false; -} - -inline static ankerl::unordered_dense::map try_to_fix_degenerated_voronoi_diagram_by_rotation( - Geometry::VoronoiDiagram &voronoi_diagram, - const Polygons &polys, - Polygons &polys_rotated, - std::vector &segments, - const double fix_angle) -{ - ankerl::unordered_dense::map vertex_mapping; - for (Polygon &poly : polys_rotated) - poly.rotate(fix_angle); - - assert(polys_rotated.size() == polys.size()); - for (size_t poly_idx = 0; poly_idx < polys.size(); ++poly_idx) { - assert(polys_rotated[poly_idx].size() == polys[poly_idx].size()); - for (size_t point_idx = 0; point_idx < polys[poly_idx].size(); ++point_idx) - vertex_mapping.insert({polys_rotated[poly_idx][point_idx], polys[poly_idx][point_idx]}); - } - - segments.clear(); - for (size_t poly_idx = 0; poly_idx < polys_rotated.size(); poly_idx++) - for (size_t point_idx = 0; point_idx < polys_rotated[poly_idx].size(); point_idx++) - segments.emplace_back(&polys_rotated, poly_idx, point_idx); - - voronoi_diagram.clear(); - construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram); - -#ifdef ARACHNE_DEBUG_VORONOI - { - static int iRun = 0; - dump_voronoi_to_svg(debug_out_path("arachne_voronoi-diagram-rotated-%d.svg", iRun++).c_str(), voronoi_diagram, to_points(polys), to_lines(polys)); - } -#endif - - assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram)); - - return vertex_mapping; -} - -inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph, - const double fix_angle, - const ankerl::unordered_dense::map &vertex_mapping) -{ - for (STHalfEdgeNode &node : graph.nodes) { - // If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction. - if (auto node_it = vertex_mapping.find(node.p); node_it != vertex_mapping.end()) - node.p = node_it->second; - else - node.p.rotate(-fix_angle); - } -} - void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys) { #ifdef ARACHNE_DEBUG @@ -604,8 +415,8 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys) } #endif - Geometry::VoronoiDiagram voronoi_diagram; - construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram); + VD voronoi_diagram; + voronoi_diagram.construct_voronoi(segments.cbegin(), segments.cend()); #ifdef ARACHNE_DEBUG_VORONOI { @@ -614,126 +425,59 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys) } #endif - // Try to detect cases when some Voronoi vertex is missing and when - // the Voronoi diagram is not planar. - // When any Voronoi vertex is missing, or the Voronoi diagram is not - // planar, rotate the input polygon and try again. - const bool has_missing_voronoi_vertex = detect_missing_voronoi_vertex(voronoi_diagram, segments); - // Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446. - const bool is_voronoi_diagram_planar = Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram); - const double fix_angle = PI / 6; - - ankerl::unordered_dense::map vertex_mapping; - // polys_copy is referenced through items stored in the std::vector segments. - Polygons polys_copy = polys; - if (has_missing_voronoi_vertex || !is_voronoi_diagram_planar) { - if (has_missing_voronoi_vertex) - BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth."; - else if (!is_voronoi_diagram_planar) - BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth."; - - vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle); - - assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments)); - assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram)); - if (detect_missing_voronoi_vertex(voronoi_diagram, segments)) - BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input."; - else if (!Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram)) - BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input."; - } - - bool degenerated_voronoi_diagram = has_missing_voronoi_vertex || !is_voronoi_diagram_planar; - -process_voronoi_diagram: assert(this->graph.edges.empty() && this->graph.nodes.empty() && this->vd_edge_to_he_edge.empty() && this->vd_node_to_he_node.empty()); - for (vd_t::cell_type cell : voronoi_diagram.cells()) { + for (const VD::cell_type &cell : voronoi_diagram.cells()) { if (!cell.incident_edge()) continue; // There is no spoon - Point start_source_point; - Point end_source_point; - vd_t::edge_type* starting_vonoroi_edge = nullptr; - vd_t::edge_type* ending_vonoroi_edge = nullptr; + Point start_source_point; + Point end_source_point; + const VD::edge_type *starting_voronoi_edge = nullptr; + const VD::edge_type *ending_voronoi_edge = nullptr; // Compute and store result in above variables - + if (cell.contains_point()) { - const bool keep_going = computePointCellRange(cell, start_source_point, end_source_point, starting_vonoroi_edge, ending_vonoroi_edge, segments); + const bool keep_going = computePointCellRange(cell, start_source_point, end_source_point, starting_voronoi_edge, ending_voronoi_edge, segments); if (!keep_going) continue; } else { assert(cell.contains_segment()); - computeSegmentCellRange(cell, start_source_point, end_source_point, starting_vonoroi_edge, ending_vonoroi_edge, segments); + Geometry::SegmentCellRange cell_range = Geometry::VoronoiUtils::compute_segment_cell_range(cell, segments.cbegin(), segments.cend()); + assert(cell_range.is_valid()); + start_source_point = cell_range.segment_start_point; + end_source_point = cell_range.segment_end_point; + starting_voronoi_edge = cell_range.edge_begin; + ending_voronoi_edge = cell_range.edge_end; } - - if (!starting_vonoroi_edge || !ending_vonoroi_edge) { + + if (!starting_voronoi_edge || !ending_voronoi_edge) { assert(false && "Each cell should start / end in a polygon vertex"); continue; } - + // Copy start to end edge to graph - edge_t* prev_edge = nullptr; - assert(VoronoiUtils::p(starting_vonoroi_edge->vertex1()).x() <= std::numeric_limits::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex1()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(starting_vonoroi_edge->vertex1()).y() <= std::numeric_limits::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex1()).y() >= std::numeric_limits::lowest()); - transferEdge(start_source_point, VoronoiUtils::p(starting_vonoroi_edge->vertex1()).cast(), *starting_vonoroi_edge, prev_edge, start_source_point, end_source_point, segments); - node_t* starting_node = vd_node_to_he_node[starting_vonoroi_edge->vertex0()]; + assert(Geometry::VoronoiUtils::is_in_range(*starting_voronoi_edge)); + edge_t *prev_edge = nullptr; + transferEdge(start_source_point, Geometry::VoronoiUtils::to_point(starting_voronoi_edge->vertex1()).cast(), *starting_voronoi_edge, prev_edge, start_source_point, end_source_point, segments); + node_t *starting_node = vd_node_to_he_node[starting_voronoi_edge->vertex0()]; starting_node->data.distance_to_boundary = 0; constexpr bool is_next_to_start_or_end = true; graph.makeRib(prev_edge, start_source_point, end_source_point, is_next_to_start_or_end); - for (vd_t::edge_type* vd_edge = starting_vonoroi_edge->next(); vd_edge != ending_vonoroi_edge; vd_edge = vd_edge->next()) { + for (const VD::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) { assert(vd_edge->is_finite()); + assert(Geometry::VoronoiUtils::is_in_range(*vd_edge)); - assert(VoronoiUtils::p(vd_edge->vertex0()).x() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge->vertex0()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge->vertex0()).y() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge->vertex0()).y() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge->vertex1()).x() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge->vertex1()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(vd_edge->vertex1()).y() <= std::numeric_limits::max() && VoronoiUtils::p(vd_edge->vertex1()).y() >= std::numeric_limits::lowest()); - - Point v1 = VoronoiUtils::p(vd_edge->vertex0()).cast(); - Point v2 = VoronoiUtils::p(vd_edge->vertex1()).cast(); + Point v1 = Geometry::VoronoiUtils::to_point(vd_edge->vertex0()).cast(); + Point v2 = Geometry::VoronoiUtils::to_point(vd_edge->vertex1()).cast(); transferEdge(v1, v2, *vd_edge, prev_edge, start_source_point, end_source_point, segments); - - graph.makeRib(prev_edge, start_source_point, end_source_point, vd_edge->next() == ending_vonoroi_edge); + graph.makeRib(prev_edge, start_source_point, end_source_point, vd_edge->next() == ending_voronoi_edge); } - assert(VoronoiUtils::p(starting_vonoroi_edge->vertex0()).x() <= std::numeric_limits::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex0()).x() >= std::numeric_limits::lowest()); - assert(VoronoiUtils::p(starting_vonoroi_edge->vertex0()).y() <= std::numeric_limits::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex0()).y() >= std::numeric_limits::lowest()); - transferEdge(VoronoiUtils::p(ending_vonoroi_edge->vertex0()).cast(), end_source_point, *ending_vonoroi_edge, prev_edge, start_source_point, end_source_point, segments); + transferEdge(Geometry::VoronoiUtils::to_point(ending_voronoi_edge->vertex0()).cast(), end_source_point, *ending_voronoi_edge, prev_edge, start_source_point, end_source_point, segments); prev_edge->to->data.distance_to_boundary = 0; } - // For some input polygons, as in GH issues #8474 and #8514 resulting Voronoi diagram is degenerated because it is not planar. - // When this degenerated Voronoi diagram is processed, the resulting half-edge structure contains some edges that don't have - // a twin edge. Based on this, we created a fast mechanism that detects those causes and tries to recompute the Voronoi - // diagram on slightly rotated input polygons that usually make the Voronoi generator generate a non-degenerated Voronoi diagram. - if (!degenerated_voronoi_diagram && has_missing_twin_edge(this->graph)) { - BOOST_LOG_TRIVIAL(warning) << "Detected degenerated Voronoi diagram, input polygons will be rotated back and forth."; - degenerated_voronoi_diagram = true; - vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle); - - assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments)); - if (detect_missing_voronoi_vertex(voronoi_diagram, segments)) - BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex after the rotation of input."; - - assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram)); - - this->graph.edges.clear(); - this->graph.nodes.clear(); - this->vd_edge_to_he_edge.clear(); - this->vd_node_to_he_node.clear(); - - goto process_voronoi_diagram; - } - - if (degenerated_voronoi_diagram) { - assert(!has_missing_twin_edge(this->graph)); - - if (has_missing_twin_edge(this->graph)) - BOOST_LOG_TRIVIAL(error) << "Detected degenerated Voronoi diagram even after the rotation of input."; - } - - if (degenerated_voronoi_diagram) - rotate_back_skeletal_trapezoidation_graph_after_fix(this->graph, fix_angle, vertex_mapping); - #ifdef ARACHNE_DEBUG assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(voronoi_diagram)); #endif @@ -742,7 +486,7 @@ process_voronoi_diagram: graph.collapseSmallEdges(); - // Set [incident_edge] the the first possible edge that way we can iterate over all reachable edges from node.incident_edge, + // Set [incident_edge] the first possible edge that way we can iterate over all reachable edges from node.incident_edge, // without needing to iterate backward for (edge_t& edge : graph.edges) if (!edge.prev) @@ -751,7 +495,7 @@ process_voronoi_diagram: void SkeletalTrapezoidation::separatePointyQuadEndNodes() { - ankerl::unordered_dense::set visited_nodes; + NodeSet visited_nodes; for (edge_t& edge : graph.edges) { if (edge.prev) @@ -2221,16 +1965,16 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c void SkeletalTrapezoidation::connectJunctions(ptr_vector_t& edge_junctions) { - ankerl::unordered_dense::set unprocessed_quad_starts(graph.edges.size() * 5 / 2); + EdgeSet unprocessed_quad_starts(graph.edges.size() * 5 / 2); for (edge_t& edge : graph.edges) { if (!edge.prev) { - unprocessed_quad_starts.insert(&edge); + unprocessed_quad_starts.emplace(&edge); } } - ankerl::unordered_dense::set passed_odd_edges; + EdgeSet passed_odd_edges; while (!unprocessed_quad_starts.empty()) { diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp index 225bf53861..75ff940155 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp @@ -7,9 +7,10 @@ #include #include // smart pointers -#include #include // pair +#include + #include "utils/HalfEdgeGraph.hpp" #include "utils/PolygonsSegmentIndex.hpp" #include "utils/ExtrusionJunction.hpp" @@ -23,8 +24,9 @@ //#define ARACHNE_DEBUG //#define ARACHNE_DEBUG_VORONOI -namespace Slic3r::Arachne -{ +namespace Slic3r::Arachne { + +using VD = Slic3r::Geometry::VoronoiDiagram; /*! * Main class of the dynamic beading strategies. @@ -47,8 +49,6 @@ deposition modeling" by Kuipers et al. */ class SkeletalTrapezoidation { - using pos_t = double; - using vd_t = boost::polygon::voronoi_diagram; using graph_t = SkeletalTrapezoidationGraph; using edge_t = STHalfEdge; using node_t = STHalfEdgeNode; @@ -79,7 +79,11 @@ class SkeletalTrapezoidation const BeadingStrategy& beading_strategy; public: - using Segment = PolygonsSegmentIndex; + using Segment = PolygonsSegmentIndex; + using NodeSet = ankerl::unordered_dense::set; + using EdgeSet = ankerl::unordered_dense::set; + using EdgeMap = ankerl::unordered_dense::map; + using NodeMap = ankerl::unordered_dense::map; /*! * Construct a new trapezoidation problem to solve. @@ -163,9 +167,9 @@ protected: * mapping each voronoi VD edge to the corresponding halfedge HE edge * In case the result segment is discretized, we map the VD edge to the *last* HE edge */ - ankerl::unordered_dense::map vd_edge_to_he_edge; - ankerl::unordered_dense::map vd_node_to_he_node; - node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet. + EdgeMap vd_edge_to_he_edge; + NodeMap vd_node_to_he_node; + node_t &makeNode(const VD::vertex_type &vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet. /*! * (Eventual) returned 'polylines per index' result (from generateToolpaths): @@ -176,7 +180,7 @@ protected: * Transfer an edge from the VD to the HE and perform discretization of parabolic edges (and vertex-vertex edges) * \p prev_edge serves as input and output. May be null as input. */ - void transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector& segments); + void transferEdge(Point from, Point to, const VD::edge_type &vd_edge, edge_t *&prev_edge, Point &start_source_point, Point &end_source_point, const std::vector &segments); /*! * Discretize a Voronoi edge that represents the medial axis of a vertex- @@ -203,7 +207,7 @@ protected: * \return A number of coordinates along the edge where the edge is broken * up into discrete pieces. */ - std::vector discretize(const vd_t::edge_type& segment, const std::vector& segments); + Points discretize(const VD::edge_type& segment, const std::vector& segments); /*! * Compute the range of line segments that surround a cell of the skeletal @@ -229,33 +233,7 @@ protected: * /return Whether the cell is inside of the polygon. If it's outside of the * polygon we should skip processing it altogether. */ - bool computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector& segments); - - /*! - * Compute the range of line segments that surround a cell of the skeletal - * graph that belongs to a line segment of the medial axis. - * - * This should only be used on cells that belong to a central line segment - * of the skeletal graph, e.g. trapezoid cells, not triangular cells. - * - * The resulting line segments is just the first and the last segment. They - * are linked to the neighboring segments, so you can iterate over the - * segments until you reach the last segment. - * \param cell The cell to compute the range of line segments for. - * \param[out] start_source_point The start point of the source segment of - * this cell. - * \param[out] end_source_point The end point of the source segment of this - * cell. - * \param[out] starting_vd_edge The edge of the Voronoi diagram where the - * loop around the cell starts. - * \param[out] ending_vd_edge The edge of the Voronoi diagram where the loop - * around the cell ends. - * \param points All vertices of the input Polygons. - * \param segments All edges of the input Polygons. - * /return Whether the cell is inside of the polygon. If it's outside of the - * polygon we should skip processing it altogether. - */ - void computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector& segments); + static bool computePointCellRange(const VD::cell_type &cell, Point &start_source_point, Point &end_source_point, const VD::edge_type *&starting_vd_edge, const VD::edge_type *&ending_vd_edge, const std::vector &segments); /*! * For VD cells associated with an input polygon vertex, we need to separate the node at the end and start of the cell into two diff --git a/src/libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp b/src/libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp index 6eff3d62ee..3258b41c7d 100644 --- a/src/libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp +++ b/src/libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp @@ -27,5 +27,24 @@ public: } // namespace Slic3r::Arachne +namespace boost::polygon { + +template<> struct geometry_concept +{ + typedef segment_concept type; +}; + +template<> struct segment_traits +{ + typedef coord_t coordinate_type; + typedef Slic3r::Point point_type; + + static inline point_type get(const Slic3r::Arachne::PolygonsSegmentIndex &CSegment, direction_1d dir) + { + return dir.to_int() ? CSegment.to() : CSegment.from(); + } +}; + +} // namespace boost::polygon #endif//UTILS_POLYGONS_SEGMENT_INDEX_H diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp b/src/libslic3r/Arachne/utils/VoronoiUtils.cpp deleted file mode 100644 index 82bd79523f..0000000000 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp +++ /dev/null @@ -1,251 +0,0 @@ -//Copyright (c) 2021 Ultimaker B.V. -//CuraEngine is released under the terms of the AGPLv3 or higher. - -#include -#include -#include - -#include "linearAlg2D.hpp" -#include "VoronoiUtils.hpp" - -namespace Slic3r::Arachne -{ - -Vec2i64 VoronoiUtils::p(const vd_t::vertex_type *node) -{ - const double x = node->x(); - const double y = node->y(); - assert(std::isfinite(x) && std::isfinite(y)); - assert(x <= double(std::numeric_limits::max()) && x >= std::numeric_limits::lowest()); - assert(y <= double(std::numeric_limits::max()) && y >= std::numeric_limits::lowest()); - return {int64_t(x + 0.5 - (x < 0)), int64_t(y + 0.5 - (y < 0))}; // Round to the nearest integer coordinates. -} - -Point VoronoiUtils::getSourcePoint(const vd_t::cell_type& cell, const std::vector& segments) -{ - assert(cell.contains_point()); - if(!cell.contains_point()) - BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!"; - - switch (cell.source_category()) { - case boost::polygon::SOURCE_CATEGORY_SINGLE_POINT: - assert(false && "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!\n"); - BOOST_LOG_TRIVIAL(error) << "Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!"; - break; - case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: - assert(cell.source_index() < segments.size()); - return segments[cell.source_index()].to(); - break; - case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: - assert(cell.source_index() < segments.size()); - return segments[cell.source_index()].from(); - break; - default: - assert(false && "getSourcePoint should only be called on point cells!\n"); - break; - } - - assert(false && "cell.source_category() is equal to an invalid value!\n"); - BOOST_LOG_TRIVIAL(error) << "cell.source_category() is equal to an invalid value!"; - return {}; -} - -PolygonsPointIndex VoronoiUtils::getSourcePointIndex(const vd_t::cell_type& cell, const std::vector& segments) -{ - assert(cell.contains_point()); - if(!cell.contains_point()) - BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source point!"; - - assert(cell.source_category() != boost::polygon::SOURCE_CATEGORY_SINGLE_POINT); - switch (cell.source_category()) { - case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: { - assert(cell.source_index() < segments.size()); - PolygonsPointIndex ret = segments[cell.source_index()]; - ++ret; - return ret; - break; - } - case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: { - assert(cell.source_index() < segments.size()); - return segments[cell.source_index()]; - break; - } - default: - assert(false && "getSourcePoint should only be called on point cells!\n"); - break; - } - PolygonsPointIndex ret = segments[cell.source_index()]; - return ++ret; -} - -const VoronoiUtils::Segment &VoronoiUtils::getSourceSegment(const vd_t::cell_type &cell, const std::vector &segments) -{ - assert(cell.contains_segment()); - if (!cell.contains_segment()) - BOOST_LOG_TRIVIAL(debug) << "Voronoi cell doesn't contain a source segment!"; - - return segments[cell.source_index()]; -} - -class PointMatrix -{ -public: - double matrix[4]; - - PointMatrix() - { - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 1; - } - - PointMatrix(double rotation) - { - rotation = rotation / 180 * M_PI; - matrix[0] = cos(rotation); - matrix[1] = -sin(rotation); - matrix[2] = -matrix[1]; - matrix[3] = matrix[0]; - } - - PointMatrix(const Point p) - { - matrix[0] = p.x(); - matrix[1] = p.y(); - double f = sqrt((matrix[0] * matrix[0]) + (matrix[1] * matrix[1])); - matrix[0] /= f; - matrix[1] /= f; - matrix[2] = -matrix[1]; - matrix[3] = matrix[0]; - } - - static PointMatrix scale(double s) - { - PointMatrix ret; - ret.matrix[0] = s; - ret.matrix[3] = s; - return ret; - } - - Point apply(const Point p) const - { - return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[1]), coord_t(p.x() * matrix[2] + p.y() * matrix[3])); - } - - Point unapply(const Point p) const - { - return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[2]), coord_t(p.x() * matrix[1] + p.y() * matrix[3])); - } -}; -std::vector VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle) -{ - std::vector discretized; - // x is distance of point projected on the segment ab - // xx is point projected on the segment ab - const Point a = segment.from(); - const Point b = segment.to(); - const Point ab = b - a; - const Point as = s - a; - const Point ae = e - a; - const coord_t ab_size = ab.cast().norm(); - const coord_t sx = as.cast().dot(ab.cast()) / ab_size; - const coord_t ex = ae.cast().dot(ab.cast()) / ab_size; - const coord_t sxex = ex - sx; - - assert((as.cast().dot(ab.cast()) / int64_t(ab_size)) <= std::numeric_limits::max()); - assert((ae.cast().dot(ab.cast()) / int64_t(ab_size)) <= std::numeric_limits::max()); - - const Point ap = p - a; - const coord_t px = ap.cast().dot(ab.cast()) / ab_size; - - assert((ap.cast().dot(ab.cast()) / int64_t(ab_size)) <= std::numeric_limits::max()); - - Point pxx; - Line(a, b).distance_to_infinite_squared(p, &pxx); - const Point ppxx = pxx - p; - const coord_t d = ppxx.cast().norm(); - const PointMatrix rot = PointMatrix(ppxx.rotate_90_degree_ccw()); - - if (d == 0) - { - discretized.emplace_back(s); - discretized.emplace_back(e); - return discretized; - } - - const float marking_bound = atan(transitioning_angle * 0.5); - int64_t msx = - marking_bound * int64_t(d); // projected marking_start - int64_t mex = marking_bound * int64_t(d); // projected marking_end - - assert(msx <= std::numeric_limits::max()); - assert(double(msx) * double(msx) <= double(std::numeric_limits::max())); - assert(mex <= std::numeric_limits::max()); - assert(double(msx) * double(msx) / double(2 * d) + double(d / 2) <= std::numeric_limits::max()); - - const coord_t marking_start_end_h = msx * msx / (2 * d) + d / 2; - Point marking_start = rot.unapply(Point(coord_t(msx), marking_start_end_h)) + pxx; - Point marking_end = rot.unapply(Point(coord_t(mex), marking_start_end_h)) + pxx; - const int dir = (sx > ex) ? -1 : 1; - if (dir < 0) - { - std::swap(marking_start, marking_end); - std::swap(msx, mex); - } - - bool add_marking_start = msx * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && msx * int64_t(dir) < int64_t(ex - px) * int64_t(dir); - bool add_marking_end = mex * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && mex * int64_t(dir) < int64_t(ex - px) * int64_t(dir); - - const Point apex = rot.unapply(Point(0, d / 2)) + pxx; - bool add_apex = int64_t(sx - px) * int64_t(dir) < 0 && int64_t(ex - px) * int64_t(dir) > 0; - - assert(!(add_marking_start && add_marking_end) || add_apex); - if(add_marking_start && add_marking_end && !add_apex) - { - BOOST_LOG_TRIVIAL(warning) << "Failing to discretize parabola! Must add an apex or one of the endpoints."; - } - - const coord_t step_count = static_cast(static_cast(std::abs(ex - sx)) / approximate_step_size + 0.5); - - discretized.emplace_back(s); - for (coord_t step = 1; step < step_count; step++) - { - assert(double(sxex) * double(step) <= double(std::numeric_limits::max())); - const int64_t x = int64_t(sx) + int64_t(sxex) * int64_t(step) / int64_t(step_count) - int64_t(px); - assert(double(x) * double(x) <= double(std::numeric_limits::max())); - assert(double(x) * double(x) / double(2 * d) + double(d / 2) <= double(std::numeric_limits::max())); - const int64_t y = int64_t(x) * int64_t(x) / int64_t(2 * d) + int64_t(d / 2); - - if (add_marking_start && msx * int64_t(dir) < int64_t(x) * int64_t(dir)) - { - discretized.emplace_back(marking_start); - add_marking_start = false; - } - if (add_apex && int64_t(x) * int64_t(dir) > 0) - { - discretized.emplace_back(apex); - add_apex = false; // only add the apex just before the - } - if (add_marking_end && mex * int64_t(dir) < int64_t(x) * int64_t(dir)) - { - discretized.emplace_back(marking_end); - add_marking_end = false; - } - assert(x <= std::numeric_limits::max() && x >= std::numeric_limits::lowest()); - assert(y <= std::numeric_limits::max() && y >= std::numeric_limits::lowest()); - const Point result = rot.unapply(Point(x, y)) + pxx; - discretized.emplace_back(result); - } - if (add_apex) - { - discretized.emplace_back(apex); - } - if (add_marking_end) - { - discretized.emplace_back(marking_end); - } - discretized.emplace_back(e); - return discretized; -} - -}//namespace Slic3r::Arachne diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp b/src/libslic3r/Arachne/utils/VoronoiUtils.hpp deleted file mode 100644 index aa46936437..0000000000 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp +++ /dev/null @@ -1,47 +0,0 @@ -//Copyright (c) 2020 Ultimaker B.V. -//CuraEngine is released under the terms of the AGPLv3 or higher. - - -#ifndef UTILS_VORONOI_UTILS_H -#define UTILS_VORONOI_UTILS_H - -#include - - -#include - -#include "PolygonsSegmentIndex.hpp" - -namespace Slic3r::Arachne -{ - -/*! - */ -class VoronoiUtils -{ -public: - using Segment = PolygonsSegmentIndex; - using voronoi_data_t = double; - using vd_t = boost::polygon::voronoi_diagram; - - static Point getSourcePoint(const vd_t::cell_type &cell, const std::vector &segments); - static const Segment &getSourceSegment(const vd_t::cell_type &cell, const std::vector &segments); - static PolygonsPointIndex getSourcePointIndex(const vd_t::cell_type &cell, const std::vector &segments); - - static Vec2i64 p(const vd_t::vertex_type *node); - - /*! - * Discretize a parabola based on (approximate) step size. - * The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola. - */ - static std::vector discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle); - - static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex) - { - return std::isfinite(vertex.x()) && std::isfinite(vertex.y()); - } -}; - -} // namespace Slic3r::Arachne - -#endif // UTILS_VORONOI_UTILS_H diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 2631b936ed..7952b3aa87 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -101,8 +101,14 @@ void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPri Points bedpts = get_shrink_bedpts(print_cfg, params); BoundingBox bedbb = Polygon(bedpts).bounding_box(); // set obj distance for auto seq_print - if (params.min_obj_distance == 0 && params.is_seq_print) - params.min_obj_distance = scaled(params.cleareance_radius + 0.001); + if (params.is_seq_print) { + bool all_objects_are_short = std::all_of(selected.begin(), selected.end(), [&](ArrangePolygon& ap) { return ap.height < params.nozzle_height; }); + if (all_objects_are_short) { + params.min_obj_distance = std::max(params.min_obj_distance, scaled(double(MAX_OUTER_NOZZLE_DIAMETER)/2+0.001)); + } + else + params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error + } double brim_max = 0; bool plate_has_tree_support = false; std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon& ap) { diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index bf9815be6b..fd53420414 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -132,6 +132,7 @@ struct ArrangeParams { float clearance_height_to_rod = 0; float clearance_height_to_lid = 0; float cleareance_radius = 0; + float nozzle_height = 0; float printable_height = 256.0; Vec2d align_center{ 0.5,0.5 }; diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index ebabfab426..dfd82cbde7 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -194,9 +194,12 @@ set(lisbslic3r_sources Geometry/Curves.hpp Geometry/MedialAxis.cpp Geometry/MedialAxis.hpp + Geometry/Voronoi.cpp Geometry/Voronoi.hpp Geometry/VoronoiOffset.cpp Geometry/VoronoiOffset.hpp + Geometry/VoronoiUtils.hpp + Geometry/VoronoiUtils.cpp Geometry/VoronoiUtilsCgal.cpp Geometry/VoronoiUtilsCgal.hpp Geometry/VoronoiVisualUtils.hpp @@ -238,6 +241,8 @@ set(lisbslic3r_sources NSVGUtils.hpp ObjectID.cpp ObjectID.hpp + ParameterUtils.cpp + ParameterUtils.hpp PerimeterGenerator.cpp PerimeterGenerator.hpp PlaceholderParser.cpp @@ -431,8 +436,6 @@ set(lisbslic3r_sources Arachne/utils/PolygonsSegmentIndex.hpp Arachne/utils/PolylineStitcher.hpp Arachne/utils/PolylineStitcher.cpp - Arachne/utils/VoronoiUtils.hpp - Arachne/utils/VoronoiUtils.cpp Arachne/SkeletalTrapezoidation.hpp Arachne/SkeletalTrapezoidation.cpp Arachne/SkeletalTrapezoidationEdge.hpp diff --git a/src/libslic3r/CSGMesh/CSGMesh.hpp b/src/libslic3r/CSGMesh/CSGMesh.hpp index d14ed76595..177d343296 100644 --- a/src/libslic3r/CSGMesh/CSGMesh.hpp +++ b/src/libslic3r/CSGMesh/CSGMesh.hpp @@ -70,6 +70,7 @@ struct CSGPart { Transform3f trafo; CSGType operation; CSGStackOp stack_operation; + std::string name; CSGPart(AnyPtr ptr = {}, CSGType op = CSGType::Union, diff --git a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp index 446326dc88..5963b29109 100644 --- a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp +++ b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp @@ -64,7 +64,7 @@ bool model_to_csgmesh(const ModelObject &mo, CSGPart part{&(vol->mesh().its), vol->is_model_part() ? CSGType::Union : CSGType::Difference, (trafo * vol->get_matrix()).cast()}; - + part.name = vol->name; *out = std::move(part); ++out; } diff --git a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp index e989033782..a9a48b48c0 100644 --- a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp +++ b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp @@ -11,6 +11,7 @@ #include "libslic3r/MeshBoolean.hpp" namespace Slic3r { namespace csg { + enum class BooleanFailReason { OK, MeshEmpty, NotBoundAVolume, SelfIntersect, NoIntersection}; // This method can be overriden when a specific CSGPart type supports caching // of the voxel grid @@ -256,12 +257,13 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm, template -It check_csgmesh_booleans(const Range &csgrange, Visitor &&vfn) +std::tuple check_csgmesh_booleans(const Range &csgrange, Visitor &&vfn) { using namespace detail_cgal; - + BooleanFailReason fail_reason = BooleanFailReason::OK; + std::string fail_part_name; std::vector cgalmeshes(csgrange.size()); - auto check_part = [&csgrange, &cgalmeshes](size_t i) + auto check_part = [&csgrange, &cgalmeshes,&fail_reason,&fail_part_name](size_t i) { auto it = csgrange.begin(); std::advance(it, i); @@ -275,14 +277,26 @@ It check_csgmesh_booleans(const Range &csgrange, Visitor &&vfn) } try { - if (!m || MeshBoolean::cgal::empty(*m)) + if (!m || MeshBoolean::cgal::empty(*m)) { + BOOST_LOG_TRIVIAL(info) << "check_csgmesh_booleans fails! mesh " << i << "/" << csgrange.size() << " is empty, cannot do boolean!"; + fail_reason= BooleanFailReason::MeshEmpty; + fail_part_name = csgpart.name; return; + } - if (!MeshBoolean::cgal::does_bound_a_volume(*m)) + if (!MeshBoolean::cgal::does_bound_a_volume(*m)) { + BOOST_LOG_TRIVIAL(info) << "check_csgmesh_booleans fails! mesh "< &csgrange, Visitor &&vfn) }; execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part); - It ret = csgrange.end(); - for (size_t i = 0; i < csgrange.size(); ++i) { - if (!cgalmeshes[i]) { - auto it = csgrange.begin(); - std::advance(it, i); - vfn(it); + //It ret = csgrange.end(); + //for (size_t i = 0; i < csgrange.size(); ++i) { + // if (!cgalmeshes[i]) { + // auto it = csgrange.begin(); + // std::advance(it, i); + // vfn(it); - if (ret == csgrange.end()) - ret = it; - } - } + // if (ret == csgrange.end()) + // ret = it; + // } + //} - return ret; + return { fail_reason,fail_part_name }; } template -It check_csgmesh_booleans(const Range &csgrange, bool use_mcut=false) +std::tuple check_csgmesh_booleans(const Range &csgrange, bool use_mcut=false) { if(!use_mcut) return check_csgmesh_booleans(csgrange, [](auto &) {}); else { using namespace detail_mcut; + BooleanFailReason fail_reason = BooleanFailReason::OK; + std::string fail_part_name; std::vector McutMeshes(csgrange.size()); - auto check_part = [&csgrange, &McutMeshes](size_t i) { + auto check_part = [&csgrange, &McutMeshes,&fail_reason,&fail_part_name](size_t i) { auto it = csgrange.begin(); std::advance(it, i); auto& csgpart = *it; @@ -327,27 +343,18 @@ It check_csgmesh_booleans(const Range &csgrange, bool use_mcut=false) } try { - if (!m || MeshBoolean::mcut::empty(*m)) + if (!m || MeshBoolean::mcut::empty(*m)) { + fail_reason=BooleanFailReason::MeshEmpty; + fail_part_name = csgpart.name; return; + } } catch (...) { return; } McutMeshes[i] = std::move(m); }; execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part); - - It ret = csgrange.end(); - for (size_t i = 0; i < csgrange.size(); ++i) { - if (!McutMeshes[i]) { - auto it = csgrange.begin(); - std::advance(it, i); - - if (ret == csgrange.end()) - ret = it; - } - } - - return ret; + return { fail_reason,fail_part_name }; } } diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index dee7477939..942a5d07b0 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -13,6 +13,8 @@ namespace Slic3r { +static const double slope_inner_outer_wall_gap = 0.4; + void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const { this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection), retval); @@ -409,11 +411,8 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths, : ExtrusionLoop(role) { // create slopes - const auto add_slop = [this, slope_max_segment_length, seam_gap](const ExtrusionPath& path, const Polyline& poly, - double ratio_begin, double ratio_end) { - if (poly.empty()) { - return; - } + const auto add_slop = [this, slope_max_segment_length, seam_gap](const ExtrusionPath &path, const Polyline &poly, double ratio_begin, double ratio_end) { + if (poly.empty()) { return; } // Ensure `slope_max_segment_length` Polyline detailed_poly; @@ -421,7 +420,7 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths, detailed_poly.append(poly.first_point()); // Recursively split the line into half until no longer than `slope_max_segment_length` - const std::function handle_line = [slope_max_segment_length, &detailed_poly, &handle_line](const Line& line) { + const std::function handle_line = [slope_max_segment_length, &detailed_poly, &handle_line](const Line &line) { if (line.length() <= slope_max_segment_length) { detailed_poly.append(line.b); } else { @@ -432,13 +431,10 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths, } }; - for (const auto& l : poly.lines()) { - handle_line(l); - } + for (const auto &l : poly.lines()) { handle_line(l); } } - starts.emplace_back(detailed_poly, path, ExtrusionPathSloped::Slope{ratio_begin, ratio_begin}, - ExtrusionPathSloped::Slope{ratio_end, ratio_end}); + starts.emplace_back(detailed_poly, path, ExtrusionPathSloped::Slope{ratio_begin, ratio_begin}, ExtrusionPathSloped::Slope{ratio_end, ratio_end}); if (is_approx(ratio_end, 1.) && seam_gap > 0) { // Remove the segments that has no extrusion @@ -456,10 +452,8 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths, detailed_poly.clear(); } } - if (!detailed_poly.empty()) { - ends.emplace_back(detailed_poly, path, ExtrusionPathSloped::Slope{1., 1. - ratio_begin}, - ExtrusionPathSloped::Slope{1., 1. - ratio_end}); - } + if (!detailed_poly.empty()) { ends.emplace_back(detailed_poly, path, ExtrusionPathSloped::Slope{1., 1. - ratio_begin}, ExtrusionPathSloped::Slope{1., 1. - ratio_end}); } + }; double remaining_length = slope_min_length; @@ -509,6 +503,61 @@ std::vector ExtrusionLoopSloped::get_all_paths() const { return r; } +void ExtrusionLoopSloped::clip_slope(double distance, bool inter_perimeter) +{ + + this->clip_end(distance); + this->clip_front(distance*2); +} + +void ExtrusionLoopSloped::clip_end(const double distance) +{ + double clip_dist = distance; + std::vector &ends_slope = this->ends; + while (clip_dist > 0 && !ends_slope.empty()) { + ExtrusionPathSloped &last_path = ends_slope.back(); + double len = last_path.length(); + if (len <= clip_dist) { + ends_slope.pop_back(); + clip_dist -= len; + } else { + last_path.polyline.clip_end(clip_dist); + break; + } + } +} + +void ExtrusionLoopSloped::clip_front(const double distance) +{ + double clip_dist = distance; + if (this->role() == erPerimeter) + clip_dist = scale_(this->slope_path_length()) * slope_inner_outer_wall_gap; + + std::vector &start_slope = this->starts; + + Polyline front_inward; + while (distance > 0 && !start_slope.empty()) { + ExtrusionPathSloped &first_path = start_slope.front(); + double len = first_path.length(); + if (len <= clip_dist) { + start_slope.erase(start_slope.begin()); + clip_dist -= len; + } else { + first_path.polyline.reverse(); + first_path.polyline.clip_end(clip_dist); + first_path.polyline.reverse(); + break; + } + } +} + +double ExtrusionLoopSloped::slope_path_length() { + double total_length = 0.0; + for (ExtrusionPathSloped start_ep : this->starts) { + total_length += unscale_(start_ep.length()); + } + return total_length; +} std::string ExtrusionEntity::role_to_string(ExtrusionRole role) { diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 0f6a37779a..4394d00264 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -151,7 +151,7 @@ class ExtrusionPath : public ExtrusionEntity { public: Polyline polyline; - int overhang_degree = 0; + double overhang_degree = 0; int curve_degree = 0; // Volumetric velocity. mm^3 of plastic per mm of linear head motion. Used by the G-code generator. double mm3_per_mm; @@ -163,7 +163,8 @@ public: ExtrusionPath() : mm3_per_mm(-1), width(-1), height(-1), m_role(erNone), m_no_extrusion(false) {} ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {} ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height, bool no_extrusion = false) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role), m_no_extrusion(no_extrusion) {} - ExtrusionPath(int overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {} + ExtrusionPath(double overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {} + ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline) , overhang_degree(rhs.overhang_degree) @@ -277,8 +278,8 @@ public: }; int get_overhang_degree() const { // only perimeter has overhang degree. Other return 0; - if (is_perimeter(m_role) || is_bridge(m_role)) - return overhang_degree; + if (is_perimeter(m_role)) + return (int)overhang_degree; return 0; }; void set_curve_degree(int curve) { @@ -513,6 +514,10 @@ public: ExtrusionLoopRole role = elrDefault); [[nodiscard]] std::vector get_all_paths() const; + void clip_slope(double distance, bool inter_perimeter = false ); + void clip_end(const double distance); + void clip_front(const double distance); + double slope_path_length(); }; inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) @@ -525,7 +530,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, Ex } } -inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, int overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) +inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); for (Polyline &polyline : polylines) @@ -546,7 +551,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E polylines.clear(); } -inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, int overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) +inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); for (Polyline &polyline : polylines) @@ -557,6 +562,16 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, i polylines.clear(); } +inline void extrusion_paths_append(ExtrusionPaths &dst, Polyline &&polyline, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) +{ + dst.reserve(dst.size() + 1); + if (polyline.is_valid()) { + dst.push_back(ExtrusionPath(overhang_degree, curva_degree, role, mm3_per_mm, width, height)); + dst.back().polyline = std::move(polyline); + } + polyline.clear(); +} + inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height, bool can_reverse = true) { dst.reserve(dst.size() + polylines.size()); diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index d68c14ce51..d87588c6d9 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -65,7 +65,10 @@ struct SurfaceFillParams // Index of this entry in a linear vector. size_t idx = 0; - + // infill speed settings + float sparse_infill_speed = 0; + float top_surface_speed = 0; + float solid_infill_speed = 0; bool operator<(const SurfaceFillParams &rhs) const { #define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false; @@ -89,6 +92,10 @@ struct SurfaceFillParams RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter()); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, bridge); RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, extrusion_role); + RETURN_COMPARE_NON_EQUAL(sparse_infill_speed); + RETURN_COMPARE_NON_EQUAL(top_surface_speed); + RETURN_COMPARE_NON_EQUAL(solid_infill_speed); + return false; } @@ -105,7 +112,10 @@ struct SurfaceFillParams this->anchor_length == rhs.anchor_length && this->anchor_length_max == rhs.anchor_length_max && this->flow == rhs.flow && - this->extrusion_role == rhs.extrusion_role; + this->extrusion_role == rhs.extrusion_role && + this->sparse_infill_speed == rhs.sparse_infill_speed && + this->top_surface_speed == rhs.top_surface_speed && + this->solid_infill_speed == rhs.solid_infill_speed; } }; @@ -490,7 +500,15 @@ std::vector group_fills(const Layer &layer) //Orca: enable thick bridge based on config layerm.bridging_flow(extrusion_role, is_thick_bridge) : layerm.flow(extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness); - + // record speed params + if (!params.bridge) { + if (params.extrusion_role == erInternalInfill) + params.sparse_infill_speed = region_config.sparse_infill_speed; + else if (params.extrusion_role == erTopSolidInfill) + params.top_surface_speed = region_config.top_surface_speed; + else if (params.extrusion_role == erSolidInfill) + params.solid_infill_speed = region_config.internal_solid_infill_speed; + } // Calculate flow spacing for infill pattern generation. if (surface.is_solid() || is_bridge) { params.spacing = params.flow.spacing(); diff --git a/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/src/libslic3r/Fill/Fill3DHoneycomb.cpp index 6c8c099c4c..7b7a3b8878 100644 --- a/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -186,15 +186,18 @@ static Polylines makeGrid(coordf_t z, coordf_t gridSize, coordf_t boundWidth, co // dont_adjust [avoid filling space evenly] // monotonic [fill strictly left to right] // complete [complete each loop] - + void Fill3DHoneycomb::_fill_surface_single( - const FillParams ¶ms, + const FillParams ¶ms, unsigned int thickness_layers, - const std::pair &direction, + const std::pair &direction, ExPolygon expolygon, Polylines &polylines_out) { // no rotation is supported for this infill pattern + // Support infill angle + auto infill_angle = float(this->angle); + if (std::abs(infill_angle) >= EPSILON) expolygon.rotate(-infill_angle); BoundingBox bb = expolygon.contour.bounding_box(); // Note: with equally-scaled X/Y/Z, the pattern will create a vertically-stretched @@ -216,7 +219,7 @@ void Fill3DHoneycomb::_fill_surface_single( // Z scale is adjusted to make the layer patterns consistent / symmetric // This means that the resultant infill won't be an ideal truncated octahedron, // but it should look better than the equivalent quantised version - + coordf_t layerHeight = scale_(thickness_layers); // ceiling to an integer value of layers per Z // (with a little nudge in case it's close to perfect) @@ -248,7 +251,7 @@ void Fill3DHoneycomb::_fill_surface_single( // (a module is 2*$gridSize since one $gridSize half-module is // growing while the other $gridSize half-module is shrinking) bb.merge(align_to_grid(bb.min, Point(gridSize*4, gridSize*4))); - + // generate pattern Polylines polylines = makeGrid( @@ -257,7 +260,7 @@ void Fill3DHoneycomb::_fill_surface_single( bb.size()(0), bb.size()(1), !params.dont_adjust); - + // move pattern in place for (Polyline &pl : polylines){ pl.translate(bb.min); @@ -266,11 +269,21 @@ void Fill3DHoneycomb::_fill_surface_single( // clip pattern to boundaries, chain the clipped polylines polylines = intersection_pl(polylines, to_polygons(expolygon)); - // connect lines if needed - if (params.dont_connect() || polylines.size() <= 1) + // copy from fliplines + if (!polylines.empty()) { + int infill_start_idx = polylines_out.size(); // only rotate what belongs to us. + // connect lines + if (params.dont_connect() || polylines.size() <= 1) append(polylines_out, chain_polylines(std::move(polylines))); - else + else this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params); + + // rotate back + if (std::abs(infill_angle) >= EPSILON) { + for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it) + it->rotate(infill_angle); + } + } } } // namespace Slic3r \ No newline at end of file diff --git a/src/libslic3r/Format/STL.cpp b/src/libslic3r/Format/STL.cpp index 133a7a5056..1888f5cd18 100644 --- a/src/libslic3r/Format/STL.cpp +++ b/src/libslic3r/Format/STL.cpp @@ -14,13 +14,13 @@ namespace Slic3r { -bool load_stl(const char *path, Model *model, const char *object_name_in, ImportstlProgressFn stlFn) +bool load_stl(const char *path, Model *model, const char *object_name_in, ImportstlProgressFn stlFn, int custom_header_length) { TriangleMesh mesh; std::string design_id; - if (! mesh.ReadSTLFile(path, true, stlFn)) { -// die "Failed to open $file\n" if !-e $path; + if (!mesh.ReadSTLFile(path, true, stlFn, custom_header_length)) { + // die "Failed to open $file\n" if !-e $path; return false; } if (mesh.empty()) { diff --git a/src/libslic3r/Format/STL.hpp b/src/libslic3r/Format/STL.hpp index 5f2f838bfe..e545e1c6d0 100644 --- a/src/libslic3r/Format/STL.hpp +++ b/src/libslic3r/Format/STL.hpp @@ -10,7 +10,7 @@ class TriangleMesh; class ModelObject; // Load an STL file into a provided model. -extern bool load_stl(const char *path, Model *model, const char *object_name = nullptr, ImportstlProgressFn stlFn = nullptr); +extern bool load_stl(const char *path, Model *model, const char *object_name = nullptr, ImportstlProgressFn stlFn = nullptr, int custom_header_length = 80); extern bool store_stl(const char *path, TriangleMesh *mesh, bool binary); extern bool store_stl(const char *path, ModelObject *model_object, bool binary); diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp index a451c08492..8275cf7c5f 100644 --- a/src/libslic3r/Format/bbs_3mf.cpp +++ b/src/libslic3r/Format/bbs_3mf.cpp @@ -291,6 +291,8 @@ static constexpr const char* LOCK_ATTR = "locked"; static constexpr const char* BED_TYPE_ATTR = "bed_type"; static constexpr const char* PRINT_SEQUENCE_ATTR = "print_sequence"; static constexpr const char* FIRST_LAYER_PRINT_SEQUENCE_ATTR = "first_layer_print_sequence"; +static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_ATTR = "other_layers_print_sequence"; +static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_NUMS_ATTR = "other_layers_print_sequence_nums"; static constexpr const char* SPIRAL_VASE_MODE = "spiral_mode"; static constexpr const char* GCODE_FILE_ATTR = "gcode_file"; static constexpr const char* THUMBNAIL_FILE_ATTR = "thumbnail_file"; @@ -1491,6 +1493,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) plate->is_label_object_enabled = it->second->is_label_object_enabled; plate->skipped_objects = it->second->skipped_objects; plate->slice_filaments_info = it->second->slice_filaments_info; + plate->printer_model_id = it->second->printer_model_id; + plate->nozzle_diameters = it->second->nozzle_diameters; plate->warnings = it->second->warnings; plate->thumbnail_file = it->second->thumbnail_file; if (plate->thumbnail_file.empty()) { @@ -4096,6 +4100,19 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) }; m_curr_plater->config.set_key_value("first_layer_print_sequence", new ConfigOptionInts(get_vector_from_string(value))); } + else if (key == OTHER_LAYERS_PRINT_SEQUENCE_ATTR) { + auto get_vector_from_string = [](const std::string &str) -> std::vector { + std::stringstream stream(str); + int value; + std::vector results; + while (stream >> value) { results.push_back(value); } + return results; + }; + m_curr_plater->config.set_key_value("other_layers_print_sequence", new ConfigOptionInts(get_vector_from_string(value))); + } + else if (key == OTHER_LAYERS_PRINT_SEQUENCE_NUMS_ATTR) { + m_curr_plater->config.set_key_value("other_layers_print_sequence_nums", new ConfigOptionInt(stoi(value))); + } else if (key == SPIRAL_VASE_MODE) { bool spiral_mode = false; std::istringstream(value) >> std::boolalpha >> spiral_mode; @@ -4185,6 +4202,16 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) if (m_curr_plater) std::istringstream(value) >> std::boolalpha >> m_curr_plater->is_label_object_enabled; } + else if (key == PRINTER_MODEL_ID_ATTR) + { + if (m_curr_plater) + m_curr_plater->printer_model_id = value; + } + else if (key == NOZZLE_DIAMETERS_ATTR) + { + if (m_curr_plater) + m_curr_plater->nozzle_diameters = value; + } } return true; @@ -7415,6 +7442,24 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) stream << "\"/>\n"; } + + ConfigOptionInts *other_layers_print_sequence_opt = plate_data->config.option("other_layers_print_sequence"); + if (other_layers_print_sequence_opt != nullptr) { + stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OTHER_LAYERS_PRINT_SEQUENCE_ATTR << "\" " << VALUE_ATTR << "=\""; + const std::vector &values = other_layers_print_sequence_opt->values; + for (int i = 0; i < values.size(); ++i) { + stream << values[i]; + if (i != (values.size() - 1)) + stream << " "; + } + stream << "\"/>\n"; + } + + const ConfigOptionInt *sequence_nums_opt = dynamic_cast(plate_data->config.option("other_layers_print_sequence_nums")); + if (sequence_nums_opt != nullptr) { + stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OTHER_LAYERS_PRINT_SEQUENCE_NUMS_ATTR << "\" " << VALUE_ATTR << "=\"" << sequence_nums_opt->getInt() << "\"/>\n"; + } + ConfigOption* spiral_mode_opt = plate_data->config.option("spiral_mode"); if (spiral_mode_opt) stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SPIRAL_VASE_MODE << "\" " << VALUE_ATTR << "=\"" << spiral_mode_opt->getBool() << "\"/>\n"; @@ -7780,18 +7825,22 @@ bool _BBS_3MF_Exporter::_add_auxiliary_dir_to_archive(mz_zip_archive &archive, c int root_dir_len = dir.string().length() + 1; //boost file access while (!directories.empty()) { - boost::filesystem::directory_iterator iterator(directories.front()); + boost::system::error_code ec; + boost::filesystem::directory_iterator iterator(directories.front(), ec); directories.pop_front(); - for (auto &dir_entry : iterator) + if (ec) continue; + for (; iterator != end(iterator); iterator.increment(ec)) { + if (ec) break; + auto dir_entry = *iterator; std::string src_file; std::string dst_in_3mf; - if (boost::filesystem::is_directory(dir_entry.path())) + if (boost::filesystem::is_directory(dir_entry.path(), ec)) { directories.push_back(dir_entry.path()); continue; } - if (boost::filesystem::is_regular_file(dir_entry.path()) && !m_skip_auxiliary) + if (boost::filesystem::is_regular_file(dir_entry.path(), ec) && !m_skip_auxiliary) { src_file = dir_entry.path().string(); dst_in_3mf = dir_entry.path().string(); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 6664294962..467ec4bbeb 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -639,6 +639,8 @@ static std::vector get_path_of_change_filament(const Print& print) } gcodegen.placeholder_parser().set("current_extruder", new_extruder_id); + gcodegen.placeholder_parser().set("retraction_distance_when_cut", gcodegen.m_config.retraction_distances_when_cut.get_at(new_extruder_id)); + gcodegen.placeholder_parser().set("long_retraction_when_cut", gcodegen.m_config.long_retractions_when_cut.get_at(new_extruder_id)); // Process the start filament gcode. std::string start_filament_gcode_str; @@ -1425,8 +1427,21 @@ namespace DoExport { total_cost += weight * extruder->filament_cost() * 0.001; } - total_cost += config.time_cost.getFloat() * (normal_print_time/3600.0); - + for (auto volume : result.print_statistics.support_volumes_per_extruder) { + total_extruded_volume += volume.second; + + size_t extruder_id = volume.first; + auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) {return extr.id() == extruder_id; }); + if (extruder == extruders.end()) + continue; + + double s = PI * sqr(0.5* extruder->filament_diameter()); + double weight = volume.second * extruder->filament_density() * 0.001; + total_used_filament += volume.second/s; + total_weight += weight; + total_cost += weight * extruder->filament_cost() * 0.001; + } + print_statistics.total_extruded_volume = total_extruded_volume; print_statistics.total_used_filament = total_used_filament; print_statistics.total_weight = total_weight; @@ -1613,6 +1628,15 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu m_processor.result().timelapse_warning_code = m_timelapse_warning_code; m_processor.result().support_traditional_timelapse = m_support_traditional_timelapse; + bool activate_long_retraction_when_cut = false; + for (const auto& extruder : m_writer.extruders()) + activate_long_retraction_when_cut |= ( + m_config.long_retractions_when_cut.get_at(extruder.id()) + && m_config.retraction_distances_when_cut.get_at(extruder.id()) > 0 + ); + + m_processor.result().long_retraction_when_cut = activate_long_retraction_when_cut; + { //BBS:check bed and filament compatible const ConfigOptionDef *bed_type_def = print_config_def.get("curr_bed_type"); assert(bed_type_def != nullptr); @@ -2275,6 +2299,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato this->placeholder_parser().set("initial_no_support_tool", initial_non_support_extruder_id); this->placeholder_parser().set("initial_no_support_extruder", initial_non_support_extruder_id); this->placeholder_parser().set("current_extruder", initial_extruder_id); + //set the key for compatibilty + this->placeholder_parser().set("retraction_distance_when_cut", m_config.retraction_distances_when_cut.get_at(initial_extruder_id)); + this->placeholder_parser().set("long_retraction_when_cut", m_config.long_retractions_when_cut.get_at(initial_extruder_id)); + + this->placeholder_parser().set("retraction_distances_when_cut", new ConfigOptionFloats(m_config.retraction_distances_when_cut)); + this->placeholder_parser().set("long_retractions_when_cut",new ConfigOptionBools(m_config.long_retractions_when_cut)); //Set variable for total layer count so it can be used in custom gcode. this->placeholder_parser().set("total_layer_count", m_layer_count); // Useful for sequential prints. @@ -2295,6 +2325,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato { BoundingBoxf bbox_bed(print.config().printable_area.values); + Vec2f plate_offset = m_writer.get_xy_offset(); this->placeholder_parser().set("print_bed_min", new ConfigOptionFloats({ bbox_bed.min.x(), bbox_bed.min.y()})); this->placeholder_parser().set("print_bed_max", new ConfigOptionFloats({ bbox_bed.max.x(), bbox_bed.max.y()})); this->placeholder_parser().set("print_bed_size", new ConfigOptionFloats({ bbox_bed.size().x(), bbox_bed.size().y() })); @@ -2322,12 +2353,37 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato pts->values.emplace_back(print.translate_to_print_space(pt)); bbox = BoundingBoxf((pts->values)); } - BoundingBoxf bbox_head_wrap_zone (print.config().head_wrap_detect_zone.values); this->placeholder_parser().set("first_layer_print_convex_hull", pts.release()); this->placeholder_parser().set("first_layer_print_min", new ConfigOptionFloats({bbox.min.x(), bbox.min.y()})); this->placeholder_parser().set("first_layer_print_max", new ConfigOptionFloats({bbox.max.x(), bbox.max.y()})); this->placeholder_parser().set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() })); - this->placeholder_parser().set("in_head_wrap_detect_zone",bbox_head_wrap_zone.overlap(bbox)); + + { + // use first layer convex_hull union with each object's bbox to check whether in head detect zone + Polygons object_projections; + for (auto& obj : print.objects()) { + for (auto& instance : obj->instances()) { + const auto& bbox = instance.get_bounding_box(); + Point min_p{ coord_t(scale_(bbox.min.x())),coord_t(scale_(bbox.min.y())) }; + Point max_p{ coord_t(scale_(bbox.max.x())),coord_t(scale_(bbox.max.y())) }; + Polygon instance_projection = { + {min_p.x(),min_p.y()}, + {max_p.x(),min_p.y()}, + {max_p.x(),max_p.y()}, + {min_p.x(),max_p.y()} + }; + object_projections.emplace_back(std::move(instance_projection)); + } + } + object_projections.emplace_back(print.first_layer_convex_hull()); + + Polygons project_polys = union_(object_projections); + Polygon head_wrap_detect_zone; + for (auto& point : print.config().head_wrap_detect_zone.values) + head_wrap_detect_zone.append(scale_(point).cast() + scale_(plate_offset).cast()); + + this->placeholder_parser().set("in_head_wrap_detect_zone", !intersection_pl(project_polys, {head_wrap_detect_zone}).empty()); + } BoundingBoxf mesh_bbox(m_config.bed_mesh_min, m_config.bed_mesh_max); auto mesh_margin = m_config.adaptive_bed_mesh_margin.value; @@ -4705,6 +4761,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // Calculate the sloped loop ExtrusionLoopSloped new_loop(paths, seam_gap, slope_min_length, slope_max_segment_length, start_slope_ratio, loop.loop_role()); + new_loop.clip_slope(seam_gap); // Then extrude it for (const auto& p : new_loop.get_all_paths()) { @@ -4985,6 +5042,30 @@ static std::map overhang_speed_key_map = {5, "bridge_speed"}, }; +double GCode::get_overhang_degree_corr_speed(float normal_speed, double path_degree) { + + //BBS: protection: overhang degree is float, make sure it not excess degree range + if (path_degree <= 0) + return normal_speed; + + if (path_degree >= 5 ) + return m_config.get_abs_value(overhang_speed_key_map[5].c_str()); + + int lower_degree_bound = int(path_degree); + if (path_degree==lower_degree_bound) + return m_config.get_abs_value(overhang_speed_key_map[lower_degree_bound].c_str()); + int upper_degree_bound = lower_degree_bound + 1; + + double lower_speed_bound = lower_degree_bound == 0 ? normal_speed : m_config.get_abs_value(overhang_speed_key_map[lower_degree_bound].c_str()); + double upper_speed_bound = upper_degree_bound == 0 ? normal_speed : m_config.get_abs_value(overhang_speed_key_map[upper_degree_bound].c_str()); + + lower_speed_bound = lower_speed_bound == 0 ? normal_speed : lower_speed_bound; + upper_speed_bound = upper_speed_bound == 0 ? normal_speed : upper_speed_bound; + + double speed_out = lower_speed_bound + (upper_speed_bound - lower_speed_bound) * (path_degree - lower_degree_bound); + return speed_out; +} + std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed) { std::string gcode; @@ -5092,12 +5173,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // set speed if (speed == -1) { - int overhang_degree = path.get_overhang_degree(); if (path.role() == erPerimeter) { speed = m_config.get_abs_value("inner_wall_speed"); - if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value && overhang_degree > 0 && - overhang_degree <= 5) { - double new_speed = m_config.get_abs_value(overhang_speed_key_map[overhang_degree].c_str()); + if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value) { + double new_speed = 0; + new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree); speed = new_speed == 0.0 ? speed : new_speed; } @@ -5106,9 +5186,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } } else if (path.role() == erExternalPerimeter) { speed = m_config.get_abs_value("outer_wall_speed"); - if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value && - overhang_degree > 0 && overhang_degree <= 5) { - double new_speed = m_config.get_abs_value(overhang_speed_key_map[overhang_degree].c_str()); + if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value ) { + double new_speed = 0; + new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree); speed = new_speed == 0.0 ? speed : new_speed; } if (sloped) { @@ -5405,6 +5485,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, for (const Line& line : path.polyline.lines()) { std::string tempDescription = description; const double line_length = line.length() * SCALING_FACTOR; + if (line_length < EPSILON) + continue; path_length += line_length; auto dE = e_per_mm * line_length; if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { @@ -5444,6 +5526,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, for (size_t point_index = start_index + 1; point_index < end_index + 1; point_index++) { const Line line = Line(path.polyline.points[point_index - 1], path.polyline.points[point_index]); const double line_length = line.length() * SCALING_FACTOR; + if (line_length < EPSILON) + continue; auto dE = e_per_mm * line_length; if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { auto oldE = dE; @@ -5464,6 +5548,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, case EMovePathType::Arc_move_ccw: { const ArcSegment& arc = fitting_result[fitting_index].arc_data; const double arc_length = fitting_result[fitting_index].arc_data.length * SCALING_FACTOR; + if (arc_length < EPSILON) + continue; const Vec2d center_offset = this->point_to_gcode(arc.center) - this->point_to_gcode(arc.start_point); auto dE = e_per_mm * arc_length; if (m_small_area_infill_flow_compensator && m_config.small_area_infill_flow_compensation.value) { @@ -5545,6 +5631,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } const double line_length = (p - prev).norm(); + if(line_length < EPSILON) + continue; path_length += line_length; double new_speed = pre_processed_point.speed * 60.0; if (last_set_speed != new_speed) { @@ -5971,6 +6059,8 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool b // if we are running a single-extruder setup, just set the extruder and return nothing if (!m_writer.multiple_extruders) { this->placeholder_parser().set("current_extruder", extruder_id); + this->placeholder_parser().set("retraction_distance_when_cut", m_config.retraction_distances_when_cut.get_at(extruder_id)); + this->placeholder_parser().set("long_retraction_when_cut", m_config.long_retractions_when_cut.get_at(extruder_id)); std::string gcode; // Append the filament start G-code. @@ -6162,6 +6252,8 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool b } this->placeholder_parser().set("current_extruder", extruder_id); + this->placeholder_parser().set("retraction_distance_when_cut", m_config.retraction_distances_when_cut.get_at(extruder_id)); + this->placeholder_parser().set("long_retraction_when_cut", m_config.long_retractions_when_cut.get_at(extruder_id)); // Append the filament start G-code. const std::string &filament_start_gcode = m_config.filament_start_gcode.get_at(extruder_id); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 03ba079fae..18ea653546 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -577,6 +577,7 @@ private: int get_bed_temperature(const int extruder_id, const bool is_first_layer, const BedType bed_type) const; std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1); + double get_overhang_degree_corr_speed(float speed, double path_degree); void print_machine_envelope(GCodeOutputStream &file, Print &print); void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 2ae00168d7..9258c6bf5d 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -762,6 +762,15 @@ void GCodeProcessor::UsedFilaments::reset() wipe_tower_cache = 0.0f; wipe_tower_volume_per_extruder.clear(); + + support_volume_cache = 0.0f; + support_volume_per_extruder.clear(); +} + +void GCodeProcessor::UsedFilaments::increase_support_caches(double extruded_volume) +{ + support_volume_cache += extruded_volume; + role_cache += extruded_volume; } void GCodeProcessor::UsedFilaments::increase_model_caches(double extruded_volume) @@ -774,6 +783,7 @@ void GCodeProcessor::UsedFilaments::increase_model_caches(double extruded_volume void GCodeProcessor::UsedFilaments::increase_wipe_tower_caches(double extruded_volume) { wipe_tower_cache += extruded_volume; + role_cache += extruded_volume; } void GCodeProcessor::UsedFilaments::process_color_change_cache() @@ -808,6 +818,18 @@ void GCodeProcessor::UsedFilaments::process_wipe_tower_cache(GCodeProcessor* pro } } +void GCodeProcessor::UsedFilaments::process_support_cache(GCodeProcessor* processor) +{ + size_t active_extruder_id = processor->m_extruder_id; + if (support_volume_cache != 0.0f){ + if (support_volume_per_extruder.find(active_extruder_id) != support_volume_per_extruder.end()) + support_volume_per_extruder[active_extruder_id] += support_volume_cache; + else + support_volume_per_extruder[active_extruder_id] = support_volume_cache; + support_volume_cache = 0.0f; + } +} + void GCodeProcessor::UsedFilaments::update_flush_per_filament(size_t extrude_id, float flush_volume) { if (flush_per_filament.find(extrude_id) != flush_per_filament.end()) @@ -842,6 +864,7 @@ void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor) process_model_cache(processor); process_role_cache(processor); process_wipe_tower_cache(processor); + process_support_cache(processor); } #if ENABLE_GCODE_VIEWER_STATISTICS @@ -885,6 +908,7 @@ void GCodeProcessorResult::reset() { toolpath_outside = false; //BBS: add label_object_enabled label_object_enabled = false; + long_retraction_when_cut = false; timelapse_warning_code = 0; printable_height = 0.0f; settings_ids.reset(); @@ -2932,7 +2956,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; - if (m_wipe_tower) { + + if(m_extrusion_role == ExtrusionRole::erSupportMaterial || m_extrusion_role == ExtrusionRole::erSupportMaterialInterface || m_extrusion_role ==ExtrusionRole::erSupportTransition) + m_used_filaments.increase_support_caches(volume_extruded_filament); + else if (m_extrusion_role==ExtrusionRole::erWipeTower) { m_used_filaments.increase_wipe_tower_caches(volume_extruded_filament); } else { @@ -3406,7 +3433,10 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line) if (type == EMoveType::Extrude) { float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; - if (m_wipe_tower) { + + if(m_extrusion_role == ExtrusionRole::erSupportMaterial || m_extrusion_role == ExtrusionRole::erSupportMaterialInterface || m_extrusion_role ==ExtrusionRole::erSupportTransition) + m_used_filaments.increase_support_caches(volume_extruded_filament); + else if (m_extrusion_role == ExtrusionRole::erWipeTower) { //BBS: save wipe tower volume to the cache m_used_filaments.increase_wipe_tower_caches(volume_extruded_filament); } @@ -4511,6 +4541,7 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code) if (code == CustomGCode::ToolChange) { m_used_filaments.process_model_cache(this); + m_used_filaments.process_support_cache(this); //BBS: reset remaining filament m_remaining_volume = m_nozzle_volume; } @@ -4544,6 +4575,7 @@ void GCodeProcessor::update_estimated_times_stats() m_result.print_statistics.volumes_per_color_change = m_used_filaments.volumes_per_color_change; m_result.print_statistics.volumes_per_extruder = m_used_filaments.volumes_per_extruder; m_result.print_statistics.wipe_tower_volumes_per_extruder = m_used_filaments.wipe_tower_volume_per_extruder; + m_result.print_statistics.support_volumes_per_extruder = m_used_filaments.support_volume_per_extruder; m_result.print_statistics.flush_per_filament = m_used_filaments.flush_per_filament; m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role; } diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 2b3a46206a..ed38b2af37 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -22,6 +22,7 @@ namespace Slic3r { #define BED_TEMP_TOO_HIGH_THAN_FILAMENT "bed_temperature_too_high_than_filament" #define NOT_SUPPORT_TRADITIONAL_TIMELAPSE "not_support_traditional_timelapse" #define NOT_GENERATE_TIMELAPSE "not_generate_timelapse" +#define LONG_RETRACTION_WHEN_CUT "activate_long_retraction_when_cut" enum class EMoveType : unsigned char { @@ -74,6 +75,7 @@ namespace Slic3r { std::vector volumes_per_color_change; std::map volumes_per_extruder; std::map wipe_tower_volumes_per_extruder; + std::map support_volumes_per_extruder; //BBS: the flush amount of every filament std::map flush_per_filament; std::map> used_filaments_per_role; @@ -195,6 +197,8 @@ namespace Slic3r { bool toolpath_outside; //BBS: add object_label_enabled bool label_object_enabled; + //BBS : extra retraction when change filament,experiment func + bool long_retraction_when_cut {0}; int timelapse_warning_code {0}; bool support_traditional_timelapse{true}; float printable_height; @@ -231,6 +235,7 @@ namespace Slic3r { bed_exclude_area = other.bed_exclude_area; toolpath_outside = other.toolpath_outside; label_object_enabled = other.label_object_enabled; + long_retraction_when_cut = other.long_retraction_when_cut; timelapse_warning_code = other.timelapse_warning_code; printable_height = other.printable_height; settings_ids = other.settings_ids; @@ -500,6 +505,9 @@ namespace Slic3r { double wipe_tower_cache; std::mapwipe_tower_volume_per_extruder; + double support_volume_cache; + std::mapsupport_volume_per_extruder; + //BBS: the flush amount of every filament std::map flush_per_filament; @@ -508,12 +516,15 @@ namespace Slic3r { void reset(); + void increase_support_caches(double extruded_volume); void increase_model_caches(double extruded_volume); void increase_wipe_tower_caches(double extruded_volume); void process_color_change_cache(); void process_model_cache(GCodeProcessor* processor); void process_wipe_tower_cache(GCodeProcessor* processor); + void process_support_cache(GCodeProcessor* processor); + void update_flush_per_filament(size_t extrude_id, float flush_length); void process_role_cache(GCodeProcessor* processor); void process_caches(GCodeProcessor* processor); diff --git a/src/libslic3r/GCode/SpiralVase.cpp b/src/libslic3r/GCode/SpiralVase.cpp index e1440bc7db..8462e73111 100644 --- a/src/libslic3r/GCode/SpiralVase.cpp +++ b/src/libslic3r/GCode/SpiralVase.cpp @@ -164,13 +164,19 @@ std::string SpiralVase::process_layer(const std::string &gcode, bool last_layer) if (found && dist < max_xy_dist_for_smoothing) { // Interpolate between the point on this layer and the point on the previous layer SpiralVase::SpiralPoint target = SpiralVaseHelpers::add(SpiralVaseHelpers::scale(nearestp, 1 - factor), SpiralVaseHelpers::scale(p, factor)); - line.set(reader, X, target.x); - line.set(reader, Y, target.y); + + // Remove tiny movement // We need to figure out the distance of this new line! float modified_dist_XY = SpiralVaseHelpers::distance(last_point, target); - // Scale the extrusion amount according to change in length - line.set(reader, E, line.e() * modified_dist_XY / dist_XY, 5 /*decimal_digits*/); - last_point = target; + if (modified_dist_XY < 0.001) + line.clear(); + else { + line.set(reader, X, target.x); + line.set(reader, Y, target.y); + // Scale the extrusion amount according to change in length + line.set(reader, E, line.e() * modified_dist_XY / dist_XY, 5 /*decimal_digits*/); + last_point = target; + } } else { last_point = p; } diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index a5aaf4e00b..dc272e9464 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -1,6 +1,8 @@ #include "Print.hpp" #include "ToolOrdering.hpp" #include "Layer.hpp" +#include "ClipperUtils.hpp" +#include "ParameterUtils.hpp" // #define SLIC3R_DEBUG @@ -21,9 +23,74 @@ namespace Slic3r { const static bool g_wipe_into_objects = false; + +// Shortest hamilton path problem +static std::vector solve_extruder_order(const std::vector>& wipe_volumes, std::vector all_extruders, unsigned int start_extruder_id) +{ + auto start_iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id); + bool add_start_extruder_flag = false; + if (start_iter == all_extruders.end()) + all_extruders.insert(all_extruders.begin(), start_extruder_id), add_start_extruder_flag = true; + else + std::swap(*all_extruders.begin(), *start_iter); + + unsigned int iterations = (1 << all_extruders.size()); + unsigned int final_state = iterations - 1; + std::vector>cache(iterations, std::vector(all_extruders.size(),0x7fffffff)); + std::vector>prev(iterations, std::vector(all_extruders.size(), -1)); + cache[1][0] = 0.; + for (unsigned int state = 0; state < iterations; ++state) { + if (state & 1) { + for (unsigned int target = 0; target < all_extruders.size(); ++target) { + if (state >> target & 1) { + for (unsigned int mid_point = 0; mid_point < all_extruders.size(); ++mid_point) { + if(state>>mid_point&1){ + auto tmp = cache[state - (1 << target)][mid_point] + wipe_volumes[all_extruders[mid_point]][all_extruders[target]]; + if (cache[state][target] >tmp) { + cache[state][target] = tmp; + prev[state][target] = mid_point; + } + } + } + } + } + } + } + + //get res + float cost = std::numeric_limits::max(); + int final_dst =0; + for (unsigned int dst = 0; dst < all_extruders.size(); ++dst) { + if (all_extruders[dst] != start_extruder_id && cost > cache[final_state][dst]) { + cost = cache[final_state][dst]; + final_dst = dst; + } + } + + std::vectorpath; + unsigned int curr_state = final_state; + int curr_point = final_dst; + while (curr_point != -1) { + path.emplace_back(all_extruders[curr_point]); + auto mid_point = prev[curr_state][curr_point]; + curr_state -= (1 << curr_point); + curr_point = mid_point; + }; + + if (add_start_extruder_flag) + path.pop_back(); + + std::reverse(path.begin(), path.end()); + return path; +} + std::vector get_extruders_order(const std::vector> &wipe_volumes, std::vector all_extruders, unsigned int start_extruder_id) { - if (all_extruders.size() > 1) { +#define USE_DP_OPTIMIZE +#ifdef USE_DP_OPTIMIZE + return solve_extruder_order(wipe_volumes, all_extruders, start_extruder_id); +#else +if (all_extruders.size() > 1) { int begin_index = 0; auto iter = std::find(all_extruders.begin(), all_extruders.end(), start_extruder_id); if (iter != all_extruders.end()) { @@ -52,6 +119,8 @@ std::vector get_extruders_order(const std::vector(number_of_extruders, print_config->prime_volume)); } + auto extruders_to_hash_key = [](const std::vector& extruders, unsigned int initial_extruder_id)->uint32_t { + uint32_t hash_key = 0; + // high 16 bit define initial extruder ,low 16 bit define extruder set + hash_key |= (1 << (16 + initial_extruder_id)); + for (auto item : extruders) + hash_key |= (1 << item); + return hash_key; + }; + + std::vector other_layers_seqs; + const ConfigOptionInts *other_layers_print_sequence_op = print_config->option("other_layers_print_sequence"); + const ConfigOptionInt *other_layers_print_sequence_nums_op = print_config->option("other_layers_print_sequence_nums"); + if (other_layers_print_sequence_op && other_layers_print_sequence_nums_op) { + const std::vector &print_sequence = other_layers_print_sequence_op->values; + int sequence_nums = other_layers_print_sequence_nums_op->value; + other_layers_seqs = get_other_layers_print_sequence(sequence_nums, print_sequence); + } + + // other_layers_seq: the layer_idx and extruder_idx are base on 1 + auto get_custom_seq = [&other_layers_seqs](int layer_idx, std::vector& out_seq) -> bool { + for (size_t idx = other_layers_seqs.size() - 1; idx != size_t(-1); --idx) { + const auto &other_layers_seq = other_layers_seqs[idx]; + if (layer_idx + 1 >= other_layers_seq.first.first && layer_idx + 1 <= other_layers_seq.first.second) { + out_seq = other_layers_seq.second; + return true; + } + } + return false; + }; + unsigned int current_extruder_id = -1; for (int i = 0; i < m_layer_tools.size(); ++i) { LayerTools& lt = m_layer_tools[i]; if (lt.extruders.empty()) continue; - // todo: The algorithm complexity is too high(o(n2)), currently only 12 colors are supported - if (i != 0 && lt.extruders.size() <= 12) { - lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id); + + std::vector custom_extruder_seq; + if (get_custom_seq(i, custom_extruder_seq) && !custom_extruder_seq.empty()) { + std::vector unsign_custom_extruder_seq; + for (int extruder : custom_extruder_seq) { + unsigned int unsign_extruder = static_cast(extruder) - 1; + auto it = std::find(lt.extruders.begin(), lt.extruders.end(), unsign_extruder); + if (it != lt.extruders.end()) { + unsign_custom_extruder_seq.emplace_back(unsign_extruder); + } + } + assert(lt.extruders.size() == unsign_custom_extruder_seq.size()); + lt.extruders = unsign_custom_extruder_seq; + current_extruder_id = lt.extruders.back(); + continue; + } + + // The algorithm complexity is O(n2*2^n) + if (i != 0) { + auto hash_key = extruders_to_hash_key(lt.extruders, current_extruder_id); + auto iter = m_tool_order_cache.find(hash_key); + if (iter == m_tool_order_cache.end()) { + lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id); + std::vector hash_val; + hash_val.reserve(lt.extruders.size()); + for (auto item : lt.extruders) + hash_val.emplace_back(static_cast(item)); + m_tool_order_cache[hash_key] = hash_val; + } + else { + std::vectorextruder_order; + extruder_order.reserve(iter->second.size()); + for (auto item : iter->second) + extruder_order.emplace_back(static_cast(item)); + lt.extruders = std::move(extruder_order); + } } current_extruder_id = lt.extruders.back(); } diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 1cc6f74c8a..d9a93131a7 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -156,7 +156,9 @@ public: // (print->config().print_sequence == PrintSequence::ByObject is false). ToolOrdering(const Print& print, unsigned int first_extruder, bool prime_multi_material = false); - void clear() { m_layer_tools.clear(); } + void clear() { + m_layer_tools.clear(); m_tool_order_cache.clear(); + } // Only valid for non-sequential print: // Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools. @@ -207,7 +209,7 @@ private: unsigned int m_last_printing_extruder = (unsigned int)-1; // All extruders, which extrude some material over m_layer_tools. std::vector m_all_printing_extruders; - + std::unordered_map> m_tool_order_cache; const PrintConfig* m_print_config_ptr = nullptr; const PrintObject* m_print_object_ptr = nullptr; bool m_is_BBL_printer = false; diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index ea0df3dd70..52a37dde55 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -26,6 +26,7 @@ public: const std::string_view comment() const { size_t pos = m_raw.find(';'); return (pos == std::string::npos) ? std::string_view() : std::string_view(m_raw).substr(pos + 1); } + void clear() { m_raw.clear(); } bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; } float value(Axis axis) const { return m_axis[axis]; } bool has(char axis) const; diff --git a/src/libslic3r/Geometry/MedialAxis.cpp b/src/libslic3r/Geometry/MedialAxis.cpp index 39677c9285..44eccd9851 100644 --- a/src/libslic3r/Geometry/MedialAxis.cpp +++ b/src/libslic3r/Geometry/MedialAxis.cpp @@ -448,7 +448,7 @@ MedialAxis::MedialAxis(double min_width, double max_width, const ExPolygon &expo void MedialAxis::build(ThickPolylines* polylines) { - construct_voronoi(m_lines.begin(), m_lines.end(), &m_vd); + m_vd.construct_voronoi(m_lines.begin(), m_lines.end()); Slic3r::Voronoi::annotate_inside_outside(m_vd, m_lines); // static constexpr double threshold_alpha = M_PI / 12.; // 30 degrees // std::vector skeleton_edges = Slic3r::Voronoi::skeleton_edges_rough(vd, lines, threshold_alpha); diff --git a/src/libslic3r/Geometry/Voronoi.cpp b/src/libslic3r/Geometry/Voronoi.cpp new file mode 100644 index 0000000000..e1df7322a4 --- /dev/null +++ b/src/libslic3r/Geometry/Voronoi.cpp @@ -0,0 +1,354 @@ +#include "Voronoi.hpp" + +#include "libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp" +#include "libslic3r/Geometry/VoronoiUtils.hpp" +#include "libslic3r/Geometry/VoronoiUtilsCgal.hpp" +#include "libslic3r/MultiMaterialSegmentation.hpp" + +#include + +namespace Slic3r::Geometry { + +using PolygonsSegmentIndexConstIt = std::vector::const_iterator; +using LinesIt = Lines::iterator; +using ColoredLinesConstIt = ColoredLines::const_iterator; + +// Explicit template instantiation. +template void VoronoiDiagram::construct_voronoi(LinesIt, LinesIt, bool); +template void VoronoiDiagram::construct_voronoi(ColoredLinesConstIt, ColoredLinesConstIt, bool); +template void VoronoiDiagram::construct_voronoi(PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt, bool); + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + void>::type +VoronoiDiagram::construct_voronoi(const SegmentIterator segment_begin, const SegmentIterator segment_end, const bool try_to_repair_if_needed) { + boost::polygon::construct_voronoi(segment_begin, segment_end, &m_voronoi_diagram); + if (try_to_repair_if_needed) { + if (m_issue_type = detect_known_issues(*this, segment_begin, segment_end); m_issue_type != IssueType::NO_ISSUE_DETECTED) { + if (m_issue_type == IssueType::MISSING_VORONOI_VERTEX) { + BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth."; + } else if (m_issue_type == IssueType::NON_PLANAR_VORONOI_DIAGRAM) { + BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth."; + } else if (m_issue_type == IssueType::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT) { + BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth."; + } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { + BOOST_LOG_TRIVIAL(warning) << "Detected finite Voronoi vertex with non finite vertex, input polygons will be rotated back and forth."; + } else { + BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue, input polygons will be rotated back and forth."; + } + + if (m_issue_type = try_to_repair_degenerated_voronoi_diagram(segment_begin, segment_end); m_issue_type != IssueType::NO_ISSUE_DETECTED) { + if (m_issue_type == IssueType::MISSING_VORONOI_VERTEX) { + BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input."; + } else if (m_issue_type == IssueType::NON_PLANAR_VORONOI_DIAGRAM) { + BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input."; + } else if (m_issue_type == IssueType::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT) { + BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input."; + } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { + BOOST_LOG_TRIVIAL(error) << "Detected finite Voronoi vertex with non finite vertex even after the rotation of input."; + } else { + BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue even after the rotation of input."; + } + + m_state = State::REPAIR_UNSUCCESSFUL; + } else { + m_state = State::REPAIR_SUCCESSFUL; + } + } else { + m_state = State::REPAIR_NOT_NEEDED; + m_issue_type = IssueType::NO_ISSUE_DETECTED; + } + } else { + m_state = State::UNKNOWN; + m_issue_type = IssueType::UNKNOWN; + } +} + +void VoronoiDiagram::clear() +{ + if (m_is_modified) { + m_vertices.clear(); + m_edges.clear(); + m_cells.clear(); + m_is_modified = false; + } else { + m_voronoi_diagram.clear(); + } + + m_state = State::UNKNOWN; + m_issue_type = IssueType::UNKNOWN; +} + +void VoronoiDiagram::copy_to_local(voronoi_diagram_type &voronoi_diagram) { + m_edges.clear(); + m_cells.clear(); + m_vertices.clear(); + + // Copy Voronoi edges. + m_edges.reserve(voronoi_diagram.num_edges()); + for (const edge_type &edge : voronoi_diagram.edges()) { + m_edges.emplace_back(edge.is_linear(), edge.is_primary()); + m_edges.back().color(edge.color()); + } + + // Copy Voronoi cells. + m_cells.reserve(voronoi_diagram.num_cells()); + for (const cell_type &cell : voronoi_diagram.cells()) { + m_cells.emplace_back(cell.source_index(), cell.source_category()); + m_cells.back().color(cell.color()); + + if (cell.incident_edge()) { + size_t incident_edge_idx = cell.incident_edge() - voronoi_diagram.edges().data(); + m_cells.back().incident_edge(&m_edges[incident_edge_idx]); + } + } + + // Copy Voronoi vertices. + m_vertices.reserve(voronoi_diagram.num_vertices()); + for (const vertex_type &vertex : voronoi_diagram.vertices()) { + m_vertices.emplace_back(vertex.x(), vertex.y()); + m_vertices.back().color(vertex.color()); + + if (vertex.incident_edge()) { + size_t incident_edge_idx = vertex.incident_edge() - voronoi_diagram.edges().data(); + m_vertices.back().incident_edge(&m_edges[incident_edge_idx]); + } + } + + // Assign all pointers for each Voronoi edge. + for (const edge_type &old_edge : voronoi_diagram.edges()) { + size_t edge_idx = &old_edge - voronoi_diagram.edges().data(); + edge_type &new_edge = m_edges[edge_idx]; + + if (old_edge.cell()) { + size_t cell_idx = old_edge.cell() - voronoi_diagram.cells().data(); + new_edge.cell(&m_cells[cell_idx]); + } + + if (old_edge.vertex0()) { + size_t vertex0_idx = old_edge.vertex0() - voronoi_diagram.vertices().data(); + new_edge.vertex0(&m_vertices[vertex0_idx]); + } + + if (old_edge.twin()) { + size_t twin_edge_idx = old_edge.twin() - voronoi_diagram.edges().data(); + new_edge.twin(&m_edges[twin_edge_idx]); + } + + if (old_edge.next()) { + size_t next_edge_idx = old_edge.next() - voronoi_diagram.edges().data(); + new_edge.next(&m_edges[next_edge_idx]); + } + + if (old_edge.prev()) { + size_t prev_edge_idx = old_edge.prev() - voronoi_diagram.edges().data(); + new_edge.prev(&m_edges[prev_edge_idx]); + } + } +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type +VoronoiDiagram::detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end) +{ + if (has_finite_edge_with_non_finite_vertex(voronoi_diagram)) { + return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX; + } else if (const IssueType cell_issue_type = detect_known_voronoi_cell_issues(voronoi_diagram, segment_begin, segment_end); cell_issue_type != IssueType::NO_ISSUE_DETECTED) { + return cell_issue_type; + } else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) { + // Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446. + return IssueType::NON_PLANAR_VORONOI_DIAGRAM; + } + + return IssueType::NO_ISSUE_DETECTED; +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type +VoronoiDiagram::detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, + const SegmentIterator segment_begin, + const SegmentIterator segment_end) +{ + using Segment = typename std::iterator_traits::value_type; + using Point = typename boost::polygon::segment_point_type::type; + using SegmentCellRange = SegmentCellRange; + + for (VD::cell_type cell : voronoi_diagram.cells()) { + if (cell.is_degenerate() || !cell.contains_segment()) + continue; // Skip degenerated cell that has no spoon. Also, skip a cell that doesn't contain a segment. + + if (const SegmentCellRange cell_range = VoronoiUtils::compute_segment_cell_range(cell, segment_begin, segment_end); cell_range.is_valid()) { + // Detection if Voronoi edge is intersecting input segment. + // It detects this type of issue at least in GH issues #8446, #8474 and #8514. + + const Segment &source_segment = Geometry::VoronoiUtils::get_source_segment(cell, segment_begin, segment_end); + const Vec2d source_segment_from = boost::polygon::segment_traits::get(source_segment, boost::polygon::LOW).template cast(); + const Vec2d source_segment_to = boost::polygon::segment_traits::get(source_segment, boost::polygon::HIGH).template cast(); + const Vec2d source_segment_vec = source_segment_to - source_segment_from; + + // All Voronoi vertices must be on the left side of the source segment, otherwise the Voronoi diagram is invalid. + for (const VD::edge_type *edge = cell_range.edge_begin; edge != cell_range.edge_end; edge = edge->next()) { + if (edge->is_infinite()) { + // When there is a missing Voronoi vertex, we may encounter an infinite Voronoi edge. + // This happens, for example, in GH issue #8846. + return IssueType::MISSING_VORONOI_VERTEX; + } else if (const Vec2d edge_v1(edge->vertex1()->x(), edge->vertex1()->y()); Slic3r::cross2(source_segment_vec, edge_v1 - source_segment_from) < 0) { + return IssueType::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT; + } + } + } else { + // When there is a missing Voronoi vertex (especially at one of the endpoints of the input segment), + // the returned cell_range is marked as invalid. + // It detects this type of issue at least in GH issue #8846. + return IssueType::MISSING_VORONOI_VERTEX; + } + } + + return IssueType::NO_ISSUE_DETECTED; +} + +bool VoronoiDiagram::has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram) +{ + for (const voronoi_diagram_type::edge_type &edge : voronoi_diagram.edges()) { + if (edge.is_finite()) { + assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr); + if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || !VoronoiUtils::is_finite(*edge.vertex1())) + return true; + } + } + return false; +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type +VoronoiDiagram::try_to_repair_degenerated_voronoi_diagram(const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + IssueType issue_type = m_issue_type; + + const std::vector fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11}; + for (const double fix_angle : fix_angles) { + issue_type = try_to_repair_degenerated_voronoi_diagram_by_rotation(segment_begin, segment_end, fix_angle); + if (issue_type == IssueType::NO_ISSUE_DETECTED) { + return issue_type; + } + } + + return issue_type; +} + +inline VD::vertex_type::color_type encode_input_segment_endpoint(const VD::cell_type::source_index_type cell_source_index, const boost::polygon::direction_1d dir) +{ + return (cell_source_index + 1) << 1 | (dir.to_int() ? 1 : 0); +} + +template +inline typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename boost::polygon::segment_point_type::value_type>::type>::type +decode_input_segment_endpoint(const VD::vertex_type::color_type color, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + using SegmentType = typename std::iterator_traits::value_type; + using PointType = typename boost::polygon::segment_traits::point_type; + + const size_t segment_idx = (color >> 1) - 1; + const SegmentIterator segment_it = segment_begin + segment_idx; + const PointType source_point = boost::polygon::segment_traits::get(*segment_it, ((color & 1) ? boost::polygon::HIGH : + boost::polygon::LOW)); + return source_point; +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type +VoronoiDiagram::try_to_repair_degenerated_voronoi_diagram_by_rotation(const SegmentIterator segment_begin, + const SegmentIterator segment_end, + const double fix_angle) +{ + using SegmentType = typename std::iterator_traits::value_type; + using PointType = typename boost::polygon::segment_traits::point_type; + + // Copy all segments and rotate their vertices. + std::vector segments_rotated; + segments_rotated.reserve(std::distance(segment_begin, segment_end)); + for (auto segment_it = segment_begin; segment_it != segment_end; ++segment_it) { + PointType from = boost::polygon::segment_traits::get(*segment_it, boost::polygon::LOW); + PointType to = boost::polygon::segment_traits::get(*segment_it, boost::polygon::HIGH); + segments_rotated.emplace_back(from.rotated(fix_angle), to.rotated(fix_angle)); + } + + VoronoiDiagram::voronoi_diagram_type voronoi_diagram_rotated; + boost::polygon::construct_voronoi(segments_rotated.begin(), segments_rotated.end(), &voronoi_diagram_rotated); + + this->copy_to_local(voronoi_diagram_rotated); + const IssueType issue_type = detect_known_issues(*this, segments_rotated.begin(), segments_rotated.end()); + + // We want to remap all Voronoi vertices at the endpoints of input segments + // to ensure that Voronoi vertices at endpoints will be preserved after rotation. + // So we assign every Voronoi vertices color to map this Vertex into input segments. + for (cell_type cell : m_cells) { + if (cell.is_degenerate()) + continue; + + if (cell.contains_segment()) { + if (const SegmentCellRange cell_range = VoronoiUtils::compute_segment_cell_range(cell, segments_rotated.begin(), segments_rotated.end()); cell_range.is_valid()) { + if (cell_range.edge_end->vertex1()->color() == 0) { + // Vertex 1 of edge_end points to the starting endpoint of the input segment (from() or line.a). + VD::vertex_type::color_type color = encode_input_segment_endpoint(cell.source_index(), boost::polygon::LOW); + cell_range.edge_end->vertex1()->color(color); + } + + if (cell_range.edge_begin->vertex0()->color() == 0) { + // Vertex 0 of edge_end points to the ending endpoint of the input segment (to() or line.b). + VD::vertex_type::color_type color = encode_input_segment_endpoint(cell.source_index(), boost::polygon::HIGH); + cell_range.edge_begin->vertex0()->color(color); + } + } else { + // This could happen when there is a missing Voronoi vertex even after rotation. + assert(cell_range.is_valid()); + } + } + + // FIXME @hejllukas: Implement mapping also for source points and not just for source segments. + } + + // Rotate all Voronoi vertices back. + // When a Voronoi vertex can be mapped to the input segment endpoint, then we don't need to do rotation back. + for (vertex_type &vertex : m_vertices) { + if (vertex.color() == 0) { + // This vertex isn't mapped to any vertex, so we rotate it back. + vertex = VoronoiUtils::make_rotated_vertex(vertex, -fix_angle); + } else { + // This vertex can be mapped to the input segment endpoint. + PointType endpoint = decode_input_segment_endpoint(vertex.color(), segment_begin, segment_end); + vertex_type endpoint_vertex{double(endpoint.x()), double(endpoint.y())}; + endpoint_vertex.incident_edge(vertex.incident_edge()); + endpoint_vertex.color(vertex.color()); + vertex = endpoint_vertex; + } + } + + // We have to clear all marked vertices because some algorithms expect that all vertices have a color equal to 0. + for (vertex_type &vertex : m_vertices) + vertex.color(0); + + m_voronoi_diagram.clear(); + m_is_modified = true; + + return issue_type; +} + +} // namespace Slic3r::Geometry diff --git a/src/libslic3r/Geometry/Voronoi.hpp b/src/libslic3r/Geometry/Voronoi.hpp index 5529750f3b..ef1c622769 100644 --- a/src/libslic3r/Geometry/Voronoi.hpp +++ b/src/libslic3r/Geometry/Voronoi.hpp @@ -4,10 +4,8 @@ #include "../Line.hpp" #include "../Polyline.hpp" -#define BOOST_VORONOI_USE_GMP 1 - #ifdef _MSC_VER -// Suppress warning C4146 in OpenVDB: unary minus operator applied to unsigned type, result still unsigned +// Suppress warning C4146 in OpenVDB: unary minus operator applied to unsigned type, result still unsigned #pragma warning(push) #pragma warning(disable : 4146) #endif // _MSC_VER @@ -16,18 +14,182 @@ #pragma warning(pop) #endif // _MSC_VER -namespace Slic3r { +namespace Slic3r::Geometry { -namespace Geometry { - -class VoronoiDiagram : public boost::polygon::voronoi_diagram { +class VoronoiDiagram +{ public: - typedef double coord_type; - typedef boost::polygon::point_data point_type; - typedef boost::polygon::segment_data segment_type; - typedef boost::polygon::rectangle_data rect_type; + using coord_type = double; + using voronoi_diagram_type = boost::polygon::voronoi_diagram; + using point_type = boost::polygon::point_data; + using segment_type = boost::polygon::segment_data; + using rect_type = boost::polygon::rectangle_data; + + using coordinate_type = voronoi_diagram_type::coordinate_type; + using vertex_type = voronoi_diagram_type::vertex_type; + using edge_type = voronoi_diagram_type::edge_type; + using cell_type = voronoi_diagram_type::cell_type; + + using const_vertex_iterator = voronoi_diagram_type::const_vertex_iterator; + using const_edge_iterator = voronoi_diagram_type::const_edge_iterator; + using const_cell_iterator = voronoi_diagram_type::const_cell_iterator; + + using vertex_container_type = voronoi_diagram_type::vertex_container_type; + using edge_container_type = voronoi_diagram_type::edge_container_type; + using cell_container_type = voronoi_diagram_type::cell_container_type; + + enum class IssueType { + NO_ISSUE_DETECTED, + FINITE_EDGE_WITH_NON_FINITE_VERTEX, + MISSING_VORONOI_VERTEX, + NON_PLANAR_VORONOI_DIAGRAM, + VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT, + UNKNOWN // Repairs are disabled in the constructor. + }; + + enum class State { + REPAIR_NOT_NEEDED, // The original Voronoi diagram doesn't have any issue. + REPAIR_SUCCESSFUL, // The original Voronoi diagram has some issues, but it was repaired. + REPAIR_UNSUCCESSFUL, // The original Voronoi diagram has some issues, but it wasn't repaired. + UNKNOWN // Repairs are disabled in the constructor. + }; + + VoronoiDiagram() = default; + + virtual ~VoronoiDiagram() = default; + + IssueType get_issue_type() const { return m_issue_type; } + + State get_state() const { return m_state; } + + bool is_valid() const { return m_state != State::REPAIR_UNSUCCESSFUL; } + + void clear(); + + const vertex_container_type &vertices() const { return m_is_modified ? m_vertices : m_voronoi_diagram.vertices(); } + + const edge_container_type &edges() const { return m_is_modified ? m_edges : m_voronoi_diagram.edges(); } + + const cell_container_type &cells() const { return m_is_modified ? m_cells : m_voronoi_diagram.cells(); } + + std::size_t num_vertices() const { return m_is_modified ? m_vertices.size() : m_voronoi_diagram.num_vertices(); } + + std::size_t num_edges() const { return m_is_modified ? m_edges.size() : m_voronoi_diagram.num_edges(); } + + std::size_t num_cells() const { return m_is_modified ? m_cells.size() : m_voronoi_diagram.num_cells(); } + + template + typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + void>::type + construct_voronoi(SegmentIterator segment_begin, SegmentIterator segment_end, bool try_to_repair_if_needed = true); + + template + typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + void>::type + construct_voronoi(const PointIterator first, const PointIterator last) + { + boost::polygon::construct_voronoi(first, last, &m_voronoi_diagram); + m_state = State::UNKNOWN; + m_issue_type = IssueType::UNKNOWN; + } + + template + typename boost::polygon::enable_if< + typename boost::polygon::gtl_and< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename boost::polygon::gtl_if::value_type>::type>::type>::type>::type, + void>::type + construct_voronoi(const PointIterator p_first, const PointIterator p_last, const SegmentIterator s_first, const SegmentIterator s_last) + { + boost::polygon::construct_voronoi(p_first, p_last, s_first, s_last, &m_voronoi_diagram); + m_state = State::UNKNOWN; + m_issue_type = IssueType::UNKNOWN; + } + + // Try to detect cases when some Voronoi vertex is missing, when the Voronoi diagram + // is not planar or some Voronoi edge is intersecting input segment. + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + IssueType>::type + detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end); + + template + typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type + try_to_repair_degenerated_voronoi_diagram_by_rotation(SegmentIterator segment_begin, SegmentIterator segment_end, double fix_angle); + + template + typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + VoronoiDiagram::IssueType>::type + try_to_repair_degenerated_voronoi_diagram(SegmentIterator segment_begin, SegmentIterator segment_end); + +private: + struct Segment + { + Point from; + Point to; + + Segment() = delete; + explicit Segment(const Point &from, const Point &to) : from(from), to(to) {} + }; + + void copy_to_local(voronoi_diagram_type &voronoi_diagram); + + // Detect issues related to Voronoi cells, or that can be detected by iterating over Voronoi cells. + // The first type of issue that can be detected is a missing Voronoi vertex, especially when it is + // missing at one of the endpoints of the input segment. + // The second type of issue that can be detected is a Voronoi edge that intersects the input segment. + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + IssueType>::type + detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end); + + static bool has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram); + + voronoi_diagram_type m_voronoi_diagram; + vertex_container_type m_vertices; + edge_container_type m_edges; + cell_container_type m_cells; + bool m_is_modified = false; + State m_state = State::UNKNOWN; + IssueType m_issue_type = IssueType::UNKNOWN; + +public: + using SegmentIt = std::vector::iterator; + + friend struct boost::polygon::segment_traits; }; -} } // namespace Slicer::Geometry +} // namespace Slic3r::Geometry + +namespace boost::polygon { +template<> struct geometry_concept +{ + typedef segment_concept type; +}; + +template<> struct segment_traits +{ + using coordinate_type = coord_t; + using point_type = Slic3r::Point; + using segment_type = Slic3r::Geometry::VoronoiDiagram::Segment; + + static inline point_type get(const segment_type &segment, direction_1d dir) { return dir.to_int() ? segment.to : segment.from; } +}; +} // namespace boost::polygon #endif // slic3r_Geometry_Voronoi_hpp_ diff --git a/src/libslic3r/Geometry/VoronoiOffset.cpp b/src/libslic3r/Geometry/VoronoiOffset.cpp index ed8d9c2b18..46105220a4 100644 --- a/src/libslic3r/Geometry/VoronoiOffset.cpp +++ b/src/libslic3r/Geometry/VoronoiOffset.cpp @@ -782,9 +782,6 @@ void annotate_inside_outside(VD &vd, const Lines &lines) for (const VD::edge_type &edge : vd.edges()) if (edge.vertex1() == nullptr) { - if (edge.vertex0() == nullptr) - continue; - // Infinite Voronoi edge separating two Point sites or a Point site and a Segment site. // Infinite edge is always outside and it references at least one valid vertex. assert(edge.is_infinite()); @@ -891,9 +888,6 @@ void annotate_inside_outside(VD &vd, const Lines &lines) for (const VD::edge_type &edge : vd.edges()) { assert((edge_category(edge) == EdgeCategory::Unknown) == (edge_category(edge.twin()) == EdgeCategory::Unknown)); if (edge_category(edge) == EdgeCategory::Unknown) { - if (!edge.is_finite()) - continue; - assert(edge.is_finite()); const VD::cell_type &cell = *edge.cell(); const VD::cell_type &cell2 = *edge.twin()->cell(); diff --git a/src/libslic3r/Geometry/VoronoiUtils.cpp b/src/libslic3r/Geometry/VoronoiUtils.cpp new file mode 100644 index 0000000000..1e9436325f --- /dev/null +++ b/src/libslic3r/Geometry/VoronoiUtils.cpp @@ -0,0 +1,283 @@ +#include + +#include +#include + +#include "VoronoiUtils.hpp" + +namespace Slic3r::Geometry { + +using PolygonsSegmentIndexConstIt = std::vector::const_iterator; +using LinesIt = Lines::iterator; +using ColoredLinesIt = ColoredLines::iterator; +using ColoredLinesConstIt = ColoredLines::const_iterator; + +// Explicit template instantiation. +template LinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, LinesIt, LinesIt); +template VD::SegmentIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt); +template ColoredLinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt); +template ColoredLinesConstIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt); +template PolygonsSegmentIndexConstIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt); +template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, LinesIt, LinesIt); +template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt); +template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt); +template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt); +template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt); +template SegmentCellRange VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, LinesIt, LinesIt); +template SegmentCellRange VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt); +template SegmentCellRange VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt); +template SegmentCellRange VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt); +template Points VoronoiUtils::discretize_parabola(const Point &, const Arachne::PolygonsSegmentIndex &, const Point &, const Point &, coord_t, float); +template Arachne::PolygonsPointIndex VoronoiUtils::get_source_point_index(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt); + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename std::iterator_traits::reference>::type +VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &cell, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + if (!cell.contains_segment()) + throw Slic3r::InvalidArgument("Voronoi cell doesn't contain a source segment!"); + + if (cell.source_index() >= size_t(std::distance(segment_begin, segment_end))) + throw Slic3r::OutOfRange("Voronoi cell source index is out of range!"); + + return *(segment_begin + cell.source_index()); +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename boost::polygon::segment_point_type::value_type>::type>::type +VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &cell, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + using Segment = typename std::iterator_traits::value_type; + + if (!cell.contains_point()) + throw Slic3r::InvalidArgument("Voronoi cell doesn't contain a source point!"); + + if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + assert(int(cell.source_index()) < std::distance(segment_begin, segment_end)); + const SegmentIterator segment_it = segment_begin + cell.source_index(); + return boost::polygon::segment_traits::get(*segment_it, boost::polygon::LOW); + } else if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT) { + assert(int(cell.source_index()) < std::distance(segment_begin, segment_end)); + const SegmentIterator segment_it = segment_begin + cell.source_index(); + return boost::polygon::segment_traits::get(*segment_it, boost::polygon::HIGH); + } else if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + throw Slic3r::RuntimeError("Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!"); + } else { + throw Slic3r::InvalidArgument("Function get_source_point() should only be called on point cells!"); + } +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + Arachne::PolygonsPointIndex>::type +VoronoiUtils::get_source_point_index(const VD::cell_type &cell, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + if (!cell.contains_point()) + throw Slic3r::InvalidArgument("Voronoi cell doesn't contain a source point!"); + + if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + assert(int(cell.source_index()) < std::distance(segment_begin, segment_end)); + const SegmentIterator segment_it = segment_begin + cell.source_index(); + return (*segment_it); + } else if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT) { + assert(int(cell.source_index()) < std::distance(segment_begin, segment_end)); + const SegmentIterator segment_it = segment_begin + cell.source_index(); + return (*segment_it).next(); + } else if (cell.source_category() == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + throw Slic3r::RuntimeError("Voronoi diagram is always constructed using segments, so cell.source_category() shouldn't be SOURCE_CATEGORY_SINGLE_POINT!"); + } else { + throw Slic3r::InvalidArgument("Function get_source_point_index() should only be called on point cells!"); + } +} + +template +typename boost::polygon::enable_if::type>::type>::type, + Points>::type +VoronoiUtils::discretize_parabola(const Point &source_point, const Segment &source_segment, const Point &start, const Point &end, const coord_t approximate_step_size, float transitioning_angle) +{ + Points discretized; + // x is distance of point projected on the segment ab + // xx is point projected on the segment ab + const Point a = source_segment.from(); + const Point b = source_segment.to(); + const Point ab = b - a; + const Point as = start - a; + const Point ae = end - a; + const coord_t ab_size = ab.cast().norm(); + const coord_t sx = as.cast().dot(ab.cast()) / ab_size; + const coord_t ex = ae.cast().dot(ab.cast()) / ab_size; + const coord_t sxex = ex - sx; + + const Point ap = source_point - a; + const coord_t px = ap.cast().dot(ab.cast()) / ab_size; + + Point pxx; + Line(a, b).distance_to_infinite_squared(source_point, &pxx); + const Point ppxx = pxx - source_point; + const coord_t d = ppxx.cast().norm(); + + const Vec2d rot = perp(ppxx).cast().normalized(); + const double rot_cos_theta = rot.x(); + const double rot_sin_theta = rot.y(); + + if (d == 0) { + discretized.emplace_back(start); + discretized.emplace_back(end); + return discretized; + } + + const double marking_bound = atan(transitioning_angle * 0.5); + int64_t msx = -marking_bound * int64_t(d); // projected marking_start + int64_t mex = marking_bound * int64_t(d); // projected marking_end + + const coord_t marking_start_end_h = msx * msx / (2 * d) + d / 2; + Point marking_start = Point(coord_t(msx), marking_start_end_h).rotated(rot_cos_theta, rot_sin_theta) + pxx; + Point marking_end = Point(coord_t(mex), marking_start_end_h).rotated(rot_cos_theta, rot_sin_theta) + pxx; + const int dir = (sx > ex) ? -1 : 1; + if (dir < 0) { + std::swap(marking_start, marking_end); + std::swap(msx, mex); + } + + bool add_marking_start = msx * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && msx * int64_t(dir) < int64_t(ex - px) * int64_t(dir); + bool add_marking_end = mex * int64_t(dir) > int64_t(sx - px) * int64_t(dir) && mex * int64_t(dir) < int64_t(ex - px) * int64_t(dir); + + const Point apex = Point(0, d / 2).rotated(rot_cos_theta, rot_sin_theta) + pxx; + bool add_apex = int64_t(sx - px) * int64_t(dir) < 0 && int64_t(ex - px) * int64_t(dir) > 0; + + assert(!add_marking_start || !add_marking_end || add_apex); + if (add_marking_start && add_marking_end && !add_apex) + BOOST_LOG_TRIVIAL(warning) << "Failing to discretize parabola! Must add an apex or one of the endpoints."; + + const coord_t step_count = lround(static_cast(std::abs(ex - sx)) / approximate_step_size); + discretized.emplace_back(start); + for (coord_t step = 1; step < step_count; ++step) { + const int64_t x = int64_t(sx) + int64_t(sxex) * int64_t(step) / int64_t(step_count) - int64_t(px); + const int64_t y = int64_t(x) * int64_t(x) / int64_t(2 * d) + int64_t(d / 2); + + if (add_marking_start && msx * int64_t(dir) < int64_t(x) * int64_t(dir)) { + discretized.emplace_back(marking_start); + add_marking_start = false; + } + + if (add_apex && int64_t(x) * int64_t(dir) > 0) { + discretized.emplace_back(apex); + add_apex = false; // only add the apex just before the + } + + if (add_marking_end && mex * int64_t(dir) < int64_t(x) * int64_t(dir)) { + discretized.emplace_back(marking_end); + add_marking_end = false; + } + + assert(is_in_range(x) && is_in_range(y)); + const Point result = Point(x, y).rotated(rot_cos_theta, rot_sin_theta) + pxx; + discretized.emplace_back(result); + } + + if (add_apex) + discretized.emplace_back(apex); + + if (add_marking_end) + discretized.emplace_back(marking_end); + + discretized.emplace_back(end); + return discretized; +} + +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + Geometry::SegmentCellRange< + typename boost::polygon::segment_point_type::value_type>::type>>::type +VoronoiUtils::compute_segment_cell_range(const VD::cell_type &cell, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + using Segment = typename std::iterator_traits::value_type; + using Point = typename boost::polygon::segment_point_type::type; + using SegmentCellRange = SegmentCellRange; + + const Segment &source_segment = Geometry::VoronoiUtils::get_source_segment(cell, segment_begin, segment_end); + const Point from = boost::polygon::segment_traits::get(source_segment, boost::polygon::LOW); + const Point to = boost::polygon::segment_traits::get(source_segment, boost::polygon::HIGH); + const Vec2i64 from_i64 = from.template cast(); + const Vec2i64 to_i64 = to.template cast(); + + // FIXME @hejllukas: Ensure that there is no infinite edge during iteration between edge_begin and edge_end. + SegmentCellRange cell_range(to, from); + + // Find starting edge and end edge + bool seen_possible_start = false; + bool after_start = false; + bool ending_edge_is_set_before_start = false; + const VD::edge_type *edge = cell.incident_edge(); + do { + if (edge->is_infinite()) + continue; + + Vec2i64 v0 = Geometry::VoronoiUtils::to_point(edge->vertex0()); + Vec2i64 v1 = Geometry::VoronoiUtils::to_point(edge->vertex1()); + assert(v0 != to_i64 || v1 != from_i64); + + if (v0 == to_i64 && !after_start) { // Use the last edge which starts in source_segment.to + cell_range.edge_begin = edge; + seen_possible_start = true; + } else if (seen_possible_start) { + after_start = true; + } + + if (v1 == from_i64 && (!cell_range.edge_end || ending_edge_is_set_before_start)) { + ending_edge_is_set_before_start = !after_start; + cell_range.edge_end = edge; + } + } while (edge = edge->next(), edge != cell.incident_edge()); + + return cell_range; +} + +Vec2i64 VoronoiUtils::to_point(const VD::vertex_type *vertex) +{ + assert(vertex != nullptr); + return VoronoiUtils::to_point(*vertex); +} + +Vec2i64 VoronoiUtils::to_point(const VD::vertex_type &vertex) +{ + const double x = vertex.x(), y = vertex.y(); + + assert(std::isfinite(x) && std::isfinite(y)); + assert(is_in_range(x) && is_in_range(y)); + + return {std::llround(x), std::llround(y)}; +} + +bool VoronoiUtils::is_finite(const VD::vertex_type &vertex) +{ + return std::isfinite(vertex.x()) && std::isfinite(vertex.y()); +} + +VD::vertex_type VoronoiUtils::make_rotated_vertex(VD::vertex_type &vertex, const double angle) +{ + const double cos_a = std::cos(angle); + const double sin_a = std::sin(angle); + + const double rotated_x = (cos_a * vertex.x() - sin_a * vertex.y()); + const double rotated_y = (cos_a * vertex.y() + sin_a * vertex.x()); + + VD::vertex_type rotated_vertex{rotated_x, rotated_y}; + rotated_vertex.incident_edge(vertex.incident_edge()); + rotated_vertex.color(vertex.color()); + + return rotated_vertex; +} + +} // namespace Slic3r::Geometry diff --git a/src/libslic3r/Geometry/VoronoiUtils.hpp b/src/libslic3r/Geometry/VoronoiUtils.hpp new file mode 100644 index 0000000000..bf63914677 --- /dev/null +++ b/src/libslic3r/Geometry/VoronoiUtils.hpp @@ -0,0 +1,120 @@ +#ifndef slic3r_VoronoiUtils_hpp_ +#define slic3r_VoronoiUtils_hpp_ + +#include "libslic3r/Geometry/Voronoi.hpp" +#include "libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp" + +using VD = Slic3r::Geometry::VoronoiDiagram; + +namespace Slic3r::Geometry { + +// Represent trapezoid Voronoi cell around segment. +template struct SegmentCellRange +{ + const PT segment_start_point; // The start point of the source segment of this cell. + const PT segment_end_point; // The end point of the source segment of this cell. + const VD::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts. + const VD::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends. + + SegmentCellRange() = delete; + explicit SegmentCellRange(const PT &segment_start_point, const PT &segment_end_point) + : segment_start_point(segment_start_point), segment_end_point(segment_end_point) + {} + + bool is_valid() const { return edge_begin && edge_end && edge_begin != edge_end; } +}; + +class VoronoiUtils +{ +public: + static Vec2i64 to_point(const VD::vertex_type *vertex); + + static Vec2i64 to_point(const VD::vertex_type &vertex); + + static bool is_finite(const VD::vertex_type &vertex); + + static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle); + + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename std::iterator_traits::reference>::type + get_source_segment(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); + + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + typename boost::polygon::segment_point_type::value_type>::type>::type + get_source_point(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); + + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + Arachne::PolygonsPointIndex>::type + get_source_point_index(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); + + /** + * Discretize a parabola based on (approximate) step size. + * + * Adapted from CuraEngine VoronoiUtils::discretizeParabola by Tim Kuipers @BagelOrb and @Ghostkeeper. + * + * @param approximate_step_size is measured parallel to the source_segment, not along the parabola. + */ + template + static typename boost::polygon::enable_if::type>::type>::type, + Points>::type + discretize_parabola(const Point &source_point, const Segment &source_segment, const Point &start, const Point &end, coord_t approximate_step_size, float transitioning_angle); + + /** + * Compute the range of line segments that surround a cell of the skeletal + * graph that belongs to a line segment of the medial axis. + * + * This should only be used on cells that belong to a central line segment + * of the skeletal graph, e.g. trapezoid cells, not triangular cells. + * + * The resulting line segments is just the first and the last segment. They + * are linked to the neighboring segments, so you can iterate over the + * segments until you reach the last segment. + * + * Adapted from CuraEngine VoronoiUtils::computePointCellRange by Tim Kuipers @BagelOrb, + * Jaime van Kessel @nallath, Remco Burema @rburema and @Ghostkeeper. + * + * @param cell The cell to compute the range of line segments for. + * @param segment_begin Begin iterator for all edges of the input Polygons. + * @param segment_end End iterator for all edges of the input Polygons. + * @return Range of line segments that surround the cell. + */ + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + Geometry::SegmentCellRange< + typename boost::polygon::segment_point_type::value_type>::type>>::type + compute_segment_cell_range(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); + + template static bool is_in_range(double value) + { + return double(std::numeric_limits::lowest()) <= value && value <= double(std::numeric_limits::max()); + } + + template static bool is_in_range(const VD::vertex_type &vertex) + { + return VoronoiUtils::is_finite(vertex) && is_in_range(vertex.x()) && is_in_range(vertex.y()); + } + + template static bool is_in_range(const VD::edge_type &edge) + { + if (edge.vertex0() == nullptr || edge.vertex1() == nullptr) + return false; + + return is_in_range(*edge.vertex0()) && is_in_range(*edge.vertex1()); + } +}; + +} // namespace Slic3r::Geometry + +#endif // slic3r_VoronoiUtils_hpp_ diff --git a/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp b/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp index e76decf5f1..a0e2191af5 100644 --- a/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp +++ b/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp @@ -4,7 +4,9 @@ #include #include "libslic3r/Geometry/Voronoi.hpp" -#include "libslic3r/Arachne/utils/VoronoiUtils.hpp" +#include "libslic3r/Geometry/VoronoiUtils.hpp" +#include "libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp" +#include "libslic3r/MultiMaterialSegmentation.hpp" #include "VoronoiUtilsCgal.hpp" @@ -12,18 +14,145 @@ using VD = Slic3r::Geometry::VoronoiDiagram; namespace Slic3r::Geometry { -using CGAL_Point = CGAL::Exact_predicates_exact_constructions_kernel::Point_2; -using CGAL_Segment = CGAL::Arr_segment_traits_2::Curve_2; +using PolygonsSegmentIndexConstIt = std::vector::const_iterator; +using LinesIt = Lines::iterator; +using ColoredLinesConstIt = ColoredLines::const_iterator; -inline static CGAL_Point to_cgal_point(const VD::vertex_type &pt) { return {pt.x(), pt.y()}; } +// Explicit template instantiation. +template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, LinesIt, LinesIt); +template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, VD::SegmentIt, VD::SegmentIt); +template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, ColoredLinesConstIt, ColoredLinesConstIt); +template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt); + +// The tangent vector of the parabola is computed based on the Proof of the reflective property. +// https://en.wikipedia.org/wiki/Parabola#Proof_of_the_reflective_property +// https://math.stackexchange.com/q/2439647/2439663#comment5039739_2439663 +namespace impl { + using K = CGAL::Simple_cartesian; + using FK = CGAL::Simple_cartesian; + using EK = CGAL::Simple_cartesian; + using C2E = CGAL::Cartesian_converter; + using C2F = CGAL::Cartesian_converter; + class Epick : public CGAL::Filtered_kernel_adaptor::Type, Epick>, true> {}; + + template + inline typename K::Vector_2 calculate_parabolic_tangent_vector( + // Test point on the parabola, where the tangent will be calculated. + const typename K::Point_2 &p, + // Focus point of the parabola. + const typename K::Point_2 &f, + // Points of a directrix of the parabola. + const typename K::Point_2 &u, + const typename K::Point_2 &v, + // On which side of the parabolic segment endpoints the focus point is, which determines the orientation of the tangent. + const typename K::Orientation &tangent_orientation) + { + using RT = typename K::RT; + using Vector_2 = typename K::Vector_2; + + const Vector_2 directrix_vec = v - u; + const RT directrix_vec_sqr_length = CGAL::scalar_product(directrix_vec, directrix_vec); + Vector_2 focus_vec = (f - u) * directrix_vec_sqr_length - directrix_vec * CGAL::scalar_product(directrix_vec, p - u); + Vector_2 tangent_vec = focus_vec.perpendicular(tangent_orientation); + return tangent_vec; + } + + template struct ParabolicTangentToSegmentOrientationPredicate + { + using Point_2 = typename K::Point_2; + using Vector_2 = typename K::Vector_2; + using Orientation = typename K::Orientation; + using result_type = typename K::Orientation; + + result_type operator()( + // Test point on the parabola, where the tangent will be calculated. + const Point_2 &p, + // End of the linear segment (p, q), for which orientation towards the tangent to parabola will be evaluated. + const Point_2 &q, + // Focus point of the parabola. + const Point_2 &f, + // Points of a directrix of the parabola. + const Point_2 &u, + const Point_2 &v, + // On which side of the parabolic segment endpoints the focus point is, which determines the orientation of the tangent. + const Orientation &tangent_orientation) const + { + assert(tangent_orientation == CGAL::Orientation::LEFT_TURN || tangent_orientation == CGAL::Orientation::RIGHT_TURN); + + Vector_2 tangent_vec = calculate_parabolic_tangent_vector(p, f, u, v, tangent_orientation); + Vector_2 linear_vec = q - p; + + return CGAL::sign(tangent_vec.x() * linear_vec.y() - tangent_vec.y() * linear_vec.x()); + } + }; + + template struct ParabolicTangentToParabolicTangentOrientationPredicate + { + using Point_2 = typename K::Point_2; + using Vector_2 = typename K::Vector_2; + using Orientation = typename K::Orientation; + using result_type = typename K::Orientation; + + result_type operator()( + // Common point on both parabolas, where the tangent will be calculated. + const Point_2 &p, + // Focus point of the first parabola. + const Point_2 &f_0, + // Points of a directrix of the first parabola. + const Point_2 &u_0, + const Point_2 &v_0, + // On which side of the parabolic segment endpoints the focus point is, which determines the orientation of the tangent. + const Orientation &tangent_orientation_0, + // Focus point of the second parabola. + const Point_2 &f_1, + // Points of a directrix of the second parabola. + const Point_2 &u_1, + const Point_2 &v_1, + // On which side of the parabolic segment endpoints the focus point is, which determines the orientation of the tangent. + const Orientation &tangent_orientation_1) const + { + assert(tangent_orientation_0 == CGAL::Orientation::LEFT_TURN || tangent_orientation_0 == CGAL::Orientation::RIGHT_TURN); + assert(tangent_orientation_1 == CGAL::Orientation::LEFT_TURN || tangent_orientation_1 == CGAL::Orientation::RIGHT_TURN); + + Vector_2 tangent_vec_0 = calculate_parabolic_tangent_vector(p, f_0, u_0, v_0, tangent_orientation_0); + Vector_2 tangent_vec_1 = calculate_parabolic_tangent_vector(p, f_1, u_1, v_1, tangent_orientation_1); + + return CGAL::sign(tangent_vec_0.x() * tangent_vec_1.y() - tangent_vec_0.y() * tangent_vec_1.x()); + } + }; + + using ParabolicTangentToSegmentOrientationPredicateFiltered = CGAL::Filtered_predicate, ParabolicTangentToSegmentOrientationPredicate, C2E, C2F>; + using ParabolicTangentToParabolicTangentOrientationPredicateFiltered = CGAL::Filtered_predicate, ParabolicTangentToParabolicTangentOrientationPredicate, C2E, C2F>; +} // namespace impl + +using ParabolicTangentToSegmentOrientation = impl::ParabolicTangentToSegmentOrientationPredicateFiltered; +using ParabolicTangentToParabolicTangentOrientation = impl::ParabolicTangentToParabolicTangentOrientationPredicateFiltered; +using CGAL_Point = impl::K::Point_2; + +inline CGAL_Point to_cgal_point(const VD::vertex_type *pt) { return {pt->x(), pt->y()}; } +inline CGAL_Point to_cgal_point(const Point &pt) { return {pt.x(), pt.y()}; } +inline CGAL_Point to_cgal_point(const Vec2d &pt) { return {pt.x(), pt.y()}; } + +inline Linef make_linef(const VD::edge_type &edge) +{ + const VD::vertex_type *v0 = edge.vertex0(); + const VD::vertex_type *v1 = edge.vertex1(); + return {Vec2d(v0->x(), v0->y()), Vec2d(v1->x(), v1->y())}; +} + +[[maybe_unused]] inline bool is_equal(const VD::vertex_type &vertex_first, const VD::vertex_type &vertex_second) { return vertex_first.x() == vertex_second.x() && vertex_first.y() == vertex_second.y(); } // FIXME Lukas H.: Also includes parabolic segments. bool VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(const VD &voronoi_diagram) { + using CGAL_E_Point = CGAL::Exact_predicates_exact_constructions_kernel::Point_2; + using CGAL_E_Segment = CGAL::Arr_segment_traits_2::Curve_2; + auto to_cgal_point = [](const VD::vertex_type &pt) -> CGAL_E_Point { return {pt.x(), pt.y()}; }; + assert(std::all_of(voronoi_diagram.edges().cbegin(), voronoi_diagram.edges().cend(), [](const VD::edge_type &edge) { return edge.color() == 0; })); - std::vector segments; + std::vector segments; segments.reserve(voronoi_diagram.num_edges()); for (const VD::edge_type &edge : voronoi_diagram.edges()) { @@ -31,7 +160,7 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(const VD &voronoi_ continue; if (edge.is_finite() && edge.is_linear() && edge.vertex0() != nullptr && edge.vertex1() != nullptr && - Arachne::VoronoiUtils::is_finite(*edge.vertex0()) && Arachne::VoronoiUtils::is_finite(*edge.vertex1())) { + VoronoiUtils::is_finite(*edge.vertex0()) && VoronoiUtils::is_finite(*edge.vertex1())) { segments.emplace_back(to_cgal_point(*edge.vertex0()), to_cgal_point(*edge.vertex1())); edge.color(1); assert(edge.twin() != nullptr); @@ -42,42 +171,136 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(const VD &voronoi_ for (const VD::edge_type &edge : voronoi_diagram.edges()) edge.color(0); - std::vector intersections_pt; + std::vector intersections_pt; CGAL::compute_intersection_points(segments.begin(), segments.end(), std::back_inserter(intersections_pt)); return intersections_pt.empty(); } -static bool check_if_three_vectors_are_ccw(const CGAL_Point &common_pt, const CGAL_Point &pt_1, const CGAL_Point &pt_2, const CGAL_Point &test_pt) { - CGAL::Orientation orientation = CGAL::orientation(common_pt, pt_1, pt_2); +struct ParabolicSegment +{ + const Point focus; + const Line directrix; + // Two points on the parabola; + const Linef segment; + // Indicate if focus point is on the left side or right side relative to parabolic segment endpoints. + const CGAL::Orientation is_focus_on_left; +}; + +template +inline static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + ParabolicSegment>::type +get_parabolic_segment(const VD::edge_type &edge, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + using Segment = typename std::iterator_traits::value_type; + assert(edge.is_curved()); + + const VD::cell_type *left_cell = edge.cell(); + const VD::cell_type *right_cell = edge.twin()->cell(); + + const Point focus_pt = VoronoiUtils::get_source_point(*(left_cell->contains_point() ? left_cell : right_cell), segment_begin, segment_end); + const Segment &directrix = VoronoiUtils::get_source_segment(*(left_cell->contains_point() ? right_cell : left_cell), segment_begin, segment_end); + CGAL::Orientation focus_side = CGAL::opposite(CGAL::orientation(to_cgal_point(edge.vertex0()), to_cgal_point(edge.vertex1()), to_cgal_point(focus_pt))); + + assert(focus_side == CGAL::Orientation::LEFT_TURN || focus_side == CGAL::Orientation::RIGHT_TURN); + + const Point directrix_from = boost::polygon::segment_traits::get(directrix, boost::polygon::LOW); + const Point directrix_to = boost::polygon::segment_traits::get(directrix, boost::polygon::HIGH); + return {focus_pt, Line(directrix_from, directrix_to), make_linef(edge), focus_side}; +} + +template +inline static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + CGAL::Orientation>::type +orientation_of_two_edges(const VD::edge_type &edge_a, const VD::edge_type &edge_b, const SegmentIterator segment_begin, const SegmentIterator segment_end) +{ + assert(is_equal(*edge_a.vertex0(), *edge_b.vertex0())); + CGAL::Orientation orientation; + if (edge_a.is_linear() && edge_b.is_linear()) { + orientation = CGAL::orientation(to_cgal_point(edge_a.vertex0()), to_cgal_point(edge_a.vertex1()), to_cgal_point(edge_b.vertex1())); + } else if (edge_a.is_curved() && edge_b.is_curved()) { + const ParabolicSegment parabolic_a = get_parabolic_segment(edge_a, segment_begin, segment_end); + const ParabolicSegment parabolic_b = get_parabolic_segment(edge_b, segment_begin, segment_end); + orientation = ParabolicTangentToParabolicTangentOrientation{}(to_cgal_point(parabolic_a.segment.a), + to_cgal_point(parabolic_a.focus), + to_cgal_point(parabolic_a.directrix.a), + to_cgal_point(parabolic_a.directrix.b), + parabolic_a.is_focus_on_left, + to_cgal_point(parabolic_b.focus), + to_cgal_point(parabolic_b.directrix.a), + to_cgal_point(parabolic_b.directrix.b), + parabolic_b.is_focus_on_left); + return orientation; + } else { + assert(edge_a.is_curved() != edge_b.is_curved()); + + const VD::edge_type &linear_edge = edge_a.is_curved() ? edge_b : edge_a; + const VD::edge_type ¶bolic_edge = edge_a.is_curved() ? edge_a : edge_b; + const ParabolicSegment parabolic = get_parabolic_segment(parabolic_edge, segment_begin, segment_end); + orientation = ParabolicTangentToSegmentOrientation{}(to_cgal_point(parabolic.segment.a), to_cgal_point(linear_edge.vertex1()), + to_cgal_point(parabolic.focus), + to_cgal_point(parabolic.directrix.a), + to_cgal_point(parabolic.directrix.b), + parabolic.is_focus_on_left); + + if (edge_b.is_curved()) + orientation = CGAL::opposite(orientation); + } + + return orientation; +} + +template +static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + bool>::type +check_if_three_edges_are_ccw(const VD::edge_type &edge_first, + const VD::edge_type &edge_second, + const VD::edge_type &edge_third, + const SegmentIterator segment_begin, + const SegmentIterator segment_end) +{ + assert(is_equal(*edge_first.vertex0(), *edge_second.vertex0()) && is_equal(*edge_second.vertex0(), *edge_third.vertex0())); + + CGAL::Orientation orientation = orientation_of_two_edges(edge_first, edge_second, segment_begin, segment_end); if (orientation == CGAL::Orientation::COLLINEAR) { // The first two edges are collinear, so the third edge must be on the right side on the first of them. - return CGAL::orientation(common_pt, pt_1, test_pt) == CGAL::Orientation::RIGHT_TURN; + return orientation_of_two_edges(edge_first, edge_third, segment_begin, segment_end) == CGAL::Orientation::RIGHT_TURN; } else if (orientation == CGAL::Orientation::LEFT_TURN) { // CCW oriented angle between vectors (common_pt, pt1) and (common_pt, pt2) is bellow PI. // So we need to check if test_pt isn't between them. - CGAL::Orientation orientation1 = CGAL::orientation(common_pt, pt_1, test_pt); - CGAL::Orientation orientation2 = CGAL::orientation(common_pt, pt_2, test_pt); + CGAL::Orientation orientation1 = orientation_of_two_edges(edge_first, edge_third, segment_begin, segment_end); + CGAL::Orientation orientation2 = orientation_of_two_edges(edge_second, edge_third, segment_begin, segment_end); return (orientation1 != CGAL::Orientation::LEFT_TURN || orientation2 != CGAL::Orientation::RIGHT_TURN); } else { assert(orientation == CGAL::Orientation::RIGHT_TURN); // CCW oriented angle between vectors (common_pt, pt1) and (common_pt, pt2) is upper PI. // So we need to check if test_pt is between them. - CGAL::Orientation orientation1 = CGAL::orientation(common_pt, pt_1, test_pt); - CGAL::Orientation orientation2 = CGAL::orientation(common_pt, pt_2, test_pt); + CGAL::Orientation orientation1 = orientation_of_two_edges(edge_first, edge_third, segment_begin, segment_end); + CGAL::Orientation orientation2 = orientation_of_two_edges(edge_second, edge_third, segment_begin, segment_end); return (orientation1 == CGAL::Orientation::RIGHT_TURN || orientation2 == CGAL::Orientation::LEFT_TURN); } } -bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &voronoi_diagram) +template +typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + bool>::type +VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &voronoi_diagram, + const SegmentIterator segment_begin, + const SegmentIterator segment_end) { for (const VD::vertex_type &vertex : voronoi_diagram.vertices()) { std::vector edges; const VD::edge_type *edge = vertex.incident_edge(); do { - // FIXME Lukas H.: Also process parabolic segments. - if (edge->is_finite() && edge->is_linear() && edge->vertex0() != nullptr && edge->vertex1() != nullptr && - Arachne::VoronoiUtils::is_finite(*edge->vertex0()) && Arachne::VoronoiUtils::is_finite(*edge->vertex1())) + if (edge->is_finite() && edge->vertex0() != nullptr && edge->vertex1() != nullptr && VoronoiUtils::is_finite(*edge->vertex0()) && VoronoiUtils::is_finite(*edge->vertex1())) edges.emplace_back(edge); edge = edge->rot_next(); @@ -86,12 +309,11 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &vor // Checking for CCW make sense for three and more edges. if (edges.size() > 2) { for (auto edge_it = edges.begin() ; edge_it != edges.end(); ++edge_it) { - const Geometry::VoronoiDiagram::edge_type *prev_edge = edge_it == edges.begin() ? edges.back() : *std::prev(edge_it); - const Geometry::VoronoiDiagram::edge_type *curr_edge = *edge_it; - const Geometry::VoronoiDiagram::edge_type *next_edge = std::next(edge_it) == edges.end() ? edges.front() : *std::next(edge_it); + const VD::edge_type *prev_edge = edge_it == edges.begin() ? edges.back() : *std::prev(edge_it); + const VD::edge_type *curr_edge = *edge_it; + const VD::edge_type *next_edge = std::next(edge_it) == edges.end() ? edges.front() : *std::next(edge_it); - if (!check_if_three_vectors_are_ccw(to_cgal_point(*prev_edge->vertex0()), to_cgal_point(*prev_edge->vertex1()), - to_cgal_point(*curr_edge->vertex1()), to_cgal_point(*next_edge->vertex1()))) + if (!check_if_three_edges_are_ccw(*prev_edge, *curr_edge, *next_edge, segment_begin, segment_end)) return false; } } @@ -100,5 +322,4 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &vor return true; } - } // namespace Slic3r::Geometry diff --git a/src/libslic3r/Geometry/VoronoiUtilsCgal.hpp b/src/libslic3r/Geometry/VoronoiUtilsCgal.hpp index 897891bd93..33ae847802 100644 --- a/src/libslic3r/Geometry/VoronoiUtilsCgal.hpp +++ b/src/libslic3r/Geometry/VoronoiUtilsCgal.hpp @@ -2,6 +2,7 @@ #define slic3r_VoronoiUtilsCgal_hpp_ #include "Voronoi.hpp" +#include "../Arachne/utils/PolygonsSegmentIndex.hpp" namespace Slic3r::Geometry { class VoronoiDiagram; @@ -13,8 +14,12 @@ public: static bool is_voronoi_diagram_planar_intersection(const VoronoiDiagram &voronoi_diagram); // Check if the Voronoi diagram is planar using verification that all neighboring edges are ordered CCW for each vertex. - static bool is_voronoi_diagram_planar_angle(const VoronoiDiagram &voronoi_diagram); - + template + static typename boost::polygon::enable_if< + typename boost::polygon::gtl_if::value_type>::type>::type>::type, + bool>::type + is_voronoi_diagram_planar_angle(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end); }; } // namespace Slic3r::Geometry diff --git a/src/libslic3r/MeshBoolean.cpp b/src/libslic3r/MeshBoolean.cpp index f9e66e9ebb..f6dd46e9ee 100644 --- a/src/libslic3r/MeshBoolean.cpp +++ b/src/libslic3r/MeshBoolean.cpp @@ -201,12 +201,12 @@ indexed_triangle_set cgal_to_indexed_triangle_set(const _Mesh &cgalmesh) const auto &vertices = cgalmesh.vertices(); int vsize = int(vertices.size()); - for (const auto &vi : vertices) { + for (auto &vi : vertices) { auto &v = cgalmesh.point(vi); // Don't ask... its.vertices.emplace_back(to_vec3f(v)); } - for (const auto &face : faces) { + for (auto &face : faces) { auto vtc = cgalmesh.vertices_around_face(cgalmesh.halfedge(face)); int i = 0; @@ -782,7 +782,7 @@ void do_boolean(McutMesh& srcMesh, const McutMesh& cutMesh, const std::string& b auto src_part = triangle_mesh_to_mcut(src_parts[i]); for (size_t j = 0; j < cut_parts.size(); j++) { auto cut_part = triangle_mesh_to_mcut(cut_parts[j]); - bool success = do_boolean_single(*src_part, *cut_part, boolean_opts); + do_boolean_single(*src_part, *cut_part, boolean_opts); } TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part); its_merge(all_its, tri_part.its); @@ -811,7 +811,9 @@ void make_boolean(const TriangleMesh &src_mesh, const TriangleMesh &cut_mesh, st triangle_mesh_to_mcut(cut_mesh, cutMesh); //dst_mesh = make_boolean(srcMesh, cutMesh, boolean_opts); do_boolean(srcMesh, cutMesh, boolean_opts); - dst_mesh.push_back(mcut_to_triangle_mesh(srcMesh)); + TriangleMesh tri_src = mcut_to_triangle_mesh(srcMesh); + if (!tri_src.empty()) + dst_mesh.push_back(std::move(tri_src)); } } // namespace mcut diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8d475cefbb..66aef84a3d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -104,6 +104,7 @@ Model& Model::assign_copy(const Model &rhs) this->design_info = rhs.design_info; this->model_info = rhs.model_info; this->stl_design_id = rhs.stl_design_id; + this->stl_design_country = rhs.stl_design_country; this->profile_info = rhs.profile_info; this->mk_name = rhs.mk_name; @@ -138,6 +139,7 @@ Model& Model::assign_copy(Model &&rhs) //BBS: add auxiliary path logic // BBS: backup, all in one temp dir this->stl_design_id = rhs.stl_design_id; + this->stl_design_country = rhs.stl_design_country; this->mk_name = rhs.mk_name; this->mk_version = rhs.mk_version; this->backup_path = std::move(rhs.backup_path); @@ -217,6 +219,8 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c result = load_step(input_file.c_str(), &model, is_cb_cancel, stepFn, stepIsUtf8Fn); else if (boost::algorithm::iends_with(input_file, ".stl")) result = load_stl(input_file.c_str(), &model, nullptr, stlFn); + else if (boost::algorithm::iends_with(input_file, ".oltp")) + result = load_stl(input_file.c_str(), &model, nullptr, stlFn,256); else if (boost::algorithm::iends_with(input_file, ".obj")) result = load_obj(input_file.c_str(), &model, message); else if (boost::algorithm::iends_with(input_file, ".svg")) @@ -954,6 +958,7 @@ void Model::load_from(Model& model) next_object_backup_id = model.next_object_backup_id; design_info = model.design_info; stl_design_id = model.stl_design_id; + stl_design_country = model.stl_design_country; model_info = model.model_info; profile_info = model.profile_info; mk_name = model.mk_name; @@ -1508,13 +1513,16 @@ BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance &instance, //BBS: add convex bounding box BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const +{ + return instance_convex_hull_bounding_box(this->instances[instance_idx], dont_translate); +} + +BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(const ModelInstance* instance, bool dont_translate) const { BoundingBoxf3 bb; - const Transform3d& inst_matrix = dont_translate ? - this->instances[instance_idx]->get_transformation().get_matrix_no_offset() : - this->instances[instance_idx]->get_transformation().get_matrix(); - for (ModelVolume *v : this->volumes) - { + const Transform3d inst_matrix = dont_translate ? instance->get_transformation().get_matrix_no_offset() : + instance->get_transformation().get_matrix(); + for (ModelVolume* v : this->volumes) { if (v->is_model_part()) bb.merge(v->get_convex_hull().transformed_bounding_box(inst_matrix * v->get_matrix())); } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ecab5a1296..03b25b810e 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -482,6 +482,7 @@ public: //BBS: add instance convex hull bounding box BoundingBoxf3 instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate = false) const; + BoundingBoxf3 instance_convex_hull_bounding_box(const ModelInstance* instance, bool dont_translate = false) const; // Calculate 2D convex hull of of a projection of the transformed printable volumes into the XY plane. // This method is cheap in that it does not make any unnecessary copy of the volume meshes. @@ -1510,6 +1511,7 @@ public: // DesignInfo of Model std::string stl_design_id; + std::string stl_design_country; std::shared_ptr design_info = nullptr; std::shared_ptr model_info = nullptr; std::shared_ptr profile_info = nullptr; diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 92ac77b191..477509e69e 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -176,7 +176,8 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r:: ap.has_tree_support = true; } - ap.height = obj->bounding_box_exact().size().z(); + auto size = obj->instance_convex_hull_bounding_box(instance).size(); + ap.height = size.z(); ap.name = obj->name; return ap; } diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 596fc56db4..148fdc9921 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -4,11 +4,11 @@ #include "Layer.hpp" #include "Print.hpp" #include "Geometry/VoronoiVisualUtils.hpp" +#include "Geometry/VoronoiUtils.hpp" #include "MutablePolygon.hpp" #include "format.hpp" #include -#include #include #include @@ -16,36 +16,19 @@ #include #include -namespace Slic3r { -struct ColoredLine { - Line line; - int color; - int poly_idx = -1; - int local_line_idx = -1; -}; -} +//#define MM_SEGMENTATION_DEBUG_GRAPH +//#define MM_SEGMENTATION_DEBUG_REGIONS +//#define MM_SEGMENTATION_DEBUG_INPUT +//#define MM_SEGMENTATION_DEBUG_PAINTED_LINES +//#define MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS -#include -namespace boost::polygon { -template <> -struct geometry_concept { typedef segment_concept type; }; +#if defined(MM_SEGMENTATION_DEBUG_GRAPH) || defined(MM_SEGMENTATION_DEBUG_REGIONS) || \ + defined(MM_SEGMENTATION_DEBUG_INPUT) || defined(MM_SEGMENTATION_DEBUG_PAINTED_LINES) || \ + defined(MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS) +#define MM_SEGMENTATION_DEBUG +#endif -template <> -struct segment_traits { - typedef coord_t coordinate_type; - typedef Slic3r::Point point_type; - - static inline point_type get(const Slic3r::ColoredLine& line, const direction_1d& dir) { - return dir.to_int() ? line.line.b : line.line.a; - } -}; -} - -//#define MMU_SEGMENTATION_DEBUG_GRAPH -//#define MMU_SEGMENTATION_DEBUG_REGIONS -//#define MMU_SEGMENTATION_DEBUG_INPUT -//#define MMU_SEGMENTATION_DEBUG_PAINTED_LINES -//#define MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS +//#define MM_SEGMENTATION_DEBUG_TOP_BOTTOM namespace Slic3r { bool is_equal(float left, float right, float eps = 1e-3) { @@ -156,55 +139,31 @@ struct PaintedLineVisitor static inline const double append_threshold2 = Slic3r::sqr(append_threshold); }; -static Polygon colored_points_to_polygon(const std::vector &lines) -{ - Polygon out; - out.points.reserve(lines.size()); - for (const ColoredLine &l : lines) - out.points.emplace_back(l.line.a); - return out; -} - -static Polygons colored_points_to_polygon(const std::vector> &lines) -{ - Polygons out; - out.reserve(lines.size()); - for (const std::vector &l : lines) - out.emplace_back(colored_points_to_polygon(l)); - return out; +BoundingBox get_extents(const std::vector &colored_polygons) { + BoundingBox bbox; + for (const ColoredLines &colored_lines : colored_polygons) { + for (const ColoredLine &colored_line : colored_lines) { + bbox.merge(colored_line.line.a); + bbox.merge(colored_line.line.b); + } + } + return bbox; } // Flatten the vector of vectors into a vector. -static inline std::vector to_lines(const std::vector> &c_lines) +static inline ColoredLines to_lines(const std::vector &c_lines) { size_t n_lines = 0; for (const auto &c_line : c_lines) n_lines += c_line.size(); - std::vector lines; + ColoredLines lines; lines.reserve(n_lines); for (const auto &c_line : c_lines) lines.insert(lines.end(), c_line.begin(), c_line.end()); return lines; } -static bool vertex_equal_to_point(const Voronoi::VD::vertex_type &vertex, const Vec2d &ipt) -{ - // Convert ipt to doubles, force the 80bit FPU temporary to 64bit and then compare. - // This should work with any settings of math compiler switches and the C++ compiler - // shall understand the memcpies as type punning and it shall optimize them out. - using ulp_cmp_type = boost::polygon::detail::ulp_comparison; - ulp_cmp_type ulp_cmp; - static constexpr int ULPS = boost::polygon::voronoi_diagram_traits::vertex_equality_predicate_type::ULPS; - return ulp_cmp(vertex.x(), ipt.x(), ULPS) == ulp_cmp_type::EQUAL && - ulp_cmp(vertex.y(), ipt.y(), ULPS) == ulp_cmp_type::EQUAL; -} - -static inline bool vertex_equal_to_point(const Voronoi::VD::vertex_type *vertex, const Vec2d &ipt) -{ - return vertex_equal_to_point(*vertex, ipt); -} - -static std::vector> get_segments(const std::vector &polygon) +static std::vector> get_segments(const ColoredLines &polygon) { std::vector> segments; @@ -229,16 +188,6 @@ static std::vector> get_segments(const std::vector>> get_all_segments(const std::vector> &color_poly) -{ - std::vector>> all_segments(color_poly.size()); - for (size_t poly_idx = 0; poly_idx < color_poly.size(); ++poly_idx) { - const std::vector &c_polygon = color_poly[poly_idx]; - all_segments[poly_idx] = get_segments(c_polygon); - } - return all_segments; -} - static std::vector filter_painted_lines(const Line &line_to_process, const size_t start_idx, const size_t end_idx, const std::vector &painted_lines) { const int filter_eps_value = scale_(0.1f); @@ -319,7 +268,7 @@ static std::vector> post_process_painted_lines(const st } #ifndef NDEBUG -static bool are_lines_connected(const std::vector &colored_lines) +static bool are_lines_connected(const ColoredLines &colored_lines) { for (size_t line_idx = 1; line_idx < colored_lines.size(); ++line_idx) if (colored_lines[line_idx - 1].line.b != colored_lines[line_idx].line.a) @@ -328,7 +277,7 @@ static bool are_lines_connected(const std::vector &colored_lines) } #endif -static std::vector colorize_line(const Line &line_to_process, +static ColoredLines colorize_line(const Line &line_to_process, const size_t start_idx, const size_t end_idx, const std::vector &painted_contour) @@ -336,9 +285,9 @@ static std::vector colorize_line(const Line &line_to_process, assert(start_idx < painted_contour.size() && end_idx < painted_contour.size() && start_idx <= end_idx); assert(std::all_of(painted_contour.begin() + start_idx, painted_contour.begin() + end_idx + 1, [&painted_contour, &start_idx](const auto &p_line) { return painted_contour[start_idx].line_idx == p_line.line_idx; })); - const int filter_eps_value = scale_(0.1f); - std::vector final_lines; - const PaintedLine &first_line = painted_contour[start_idx]; + const int filter_eps_value = scale_(0.1f); + ColoredLines final_lines; + const PaintedLine &first_line = painted_contour[start_idx]; if (double dist_to_start = (first_line.projected_line.a - line_to_process.a).cast().norm(); dist_to_start > filter_eps_value) final_lines.push_back({Line(line_to_process.a, first_line.projected_line.a), 0}); final_lines.push_back({first_line.projected_line, first_line.color}); @@ -377,7 +326,7 @@ static std::vector colorize_line(const Line &line_to_process, if (line_1.line.length() <= scale_(0.2)) line_1.color = line_0.color; } - std::vector colored_lines_simple; + ColoredLines colored_lines_simple; colored_lines_simple.emplace_back(final_lines.front()); for (size_t line_idx = 1; line_idx < final_lines.size(); ++line_idx) { const ColoredLine &line_0 = final_lines[line_idx]; @@ -405,7 +354,7 @@ static std::vector colorize_line(const Line &line_to_process, return final_lines; } -static std::vector filter_colorized_polygon(std::vector &&new_lines) { +static ColoredLines filter_colorized_polygon(ColoredLines &&new_lines) { for (size_t line_idx = 2; line_idx < new_lines.size(); ++line_idx) { const ColoredLine &line_0 = new_lines[line_idx - 2]; ColoredLine &line_1 = new_lines[line_idx - 1]; @@ -494,10 +443,10 @@ static std::vector filter_colorized_polygon(std::vector colorize_contour(const EdgeGrid::Contour &contour, const std::vector &painted_contour) { +static ColoredLines colorize_contour(const EdgeGrid::Contour &contour, const std::vector &painted_contour) { assert(painted_contour.empty() || std::all_of(painted_contour.begin(), painted_contour.end(), [&painted_contour](const auto &p_line) { return painted_contour.front().contour_idx == p_line.contour_idx; })); - std::vector colorized_contour; + ColoredLines colorized_contour; if (painted_contour.empty()) { // Appends contour with default color for lines before the first PaintedLine. colorized_contour.reserve(contour.num_segments()); @@ -534,297 +483,33 @@ static std::vector colorize_contour(const EdgeGrid::Contour &contou return filter_colorized_polygon(std::move(colorized_contour)); } -static std::vector> colorize_contours(const std::vector &contours, const std::vector> &painted_contours) +static std::vector colorize_contours(const std::vector &contours, const std::vector> &painted_contours) { assert(contours.size() == painted_contours.size()); - std::vector> colorized_contours(contours.size()); + std::vector colorized_contours(contours.size()); for (const std::vector &painted_contour : painted_contours) { size_t contour_idx = &painted_contour - &painted_contours.front(); colorized_contours[contour_idx] = colorize_contour(contours[contour_idx], painted_contours[contour_idx]); } + + size_t poly_idx = 0; + for (ColoredLines &color_lines : colorized_contours) { + size_t line_idx = 0; + for (size_t color_line_idx = 0; color_line_idx < color_lines.size(); ++color_line_idx) { + color_lines[color_line_idx].poly_idx = int(poly_idx); + color_lines[color_line_idx].local_line_idx = int(line_idx); + ++line_idx; + } + ++poly_idx; + } + return colorized_contours; } -using boost::polygon::voronoi_diagram; - -static inline Point mk_point(const Voronoi::VD::vertex_type *point) { return {coord_t(point->x()), coord_t(point->y())}; } - -static inline Point mk_point(const Voronoi::Internal::point_type &point) { return {coord_t(point.x()), coord_t(point.y())}; } - -static inline Point mk_point(const voronoi_diagram::vertex_type &point) { return {coord_t(point.x()), coord_t(point.y())}; } - -static inline Point mk_point(const Vec2d &point) { return {coord_t(std::round(point.x())), coord_t(std::round(point.y()))}; } - -static inline Vec2d mk_vec2(const voronoi_diagram::vertex_type *point) { return {point->x(), point->y()}; } - -struct MMU_Graph -{ - enum class ARC_TYPE { BORDER, NON_BORDER }; - - struct Arc - { - size_t from_idx; - size_t to_idx; - int color; - ARC_TYPE type; - - bool operator==(const Arc &rhs) const { return (from_idx == rhs.from_idx) && (to_idx == rhs.to_idx) && (color == rhs.color) && (type == rhs.type); } - bool operator!=(const Arc &rhs) const { return !operator==(rhs); } - }; - - struct Node - { - Vec2d point; - std::list arc_idxs; - - void remove_edge(const size_t to_idx, MMU_Graph &graph) - { - for (auto arc_it = this->arc_idxs.begin(); arc_it != this->arc_idxs.end(); ++arc_it) { - MMU_Graph::Arc &arc = graph.arcs[*arc_it]; - if (arc.to_idx == to_idx) { - assert(arc.type != ARC_TYPE::BORDER); - this->arc_idxs.erase(arc_it); - break; - } - } - } - }; - - std::vector nodes; - std::vector arcs; - size_t all_border_points{}; - - std::vector polygon_idx_offset; - std::vector polygon_sizes; - - void remove_edge(const size_t from_idx, const size_t to_idx) - { - nodes[from_idx].remove_edge(to_idx, *this); - nodes[to_idx].remove_edge(from_idx, *this); - } - - [[nodiscard]] size_t get_global_index(const size_t poly_idx, const size_t point_idx) const { return polygon_idx_offset[poly_idx] + point_idx; } - - void append_edge(const size_t &from_idx, const size_t &to_idx, int color = -1, ARC_TYPE type = ARC_TYPE::NON_BORDER) - { - // Don't append duplicate edges between the same nodes. - for (const size_t &arc_idx : this->nodes[from_idx].arc_idxs) - if (arcs[arc_idx].to_idx == to_idx) - return; - for (const size_t &arc_idx : this->nodes[to_idx].arc_idxs) - if (arcs[arc_idx].to_idx == from_idx) - return; - - this->nodes[from_idx].arc_idxs.push_back(this->arcs.size()); - this->arcs.push_back({from_idx, to_idx, color, type}); - - // Always insert only one directed arc for the input polygons. - // Two directed arcs in both directions are inserted if arcs aren't between points of the input polygons. - if (type == ARC_TYPE::NON_BORDER) { - this->nodes[to_idx].arc_idxs.push_back(this->arcs.size()); - this->arcs.push_back({to_idx, from_idx, color, type}); - } - } - - // It assumes that between points of the input polygons is always only one directed arc, - // with the same direction as lines of the input polygon. - [[nodiscard]] MMU_Graph::Arc get_border_arc(size_t idx) const { - assert(idx < this->all_border_points); - return this->arcs[idx]; - } - - [[nodiscard]] size_t nodes_count() const { return this->nodes.size(); } - - void remove_nodes_with_one_arc() - { - std::queue update_queue; - for (const MMU_Graph::Node &node : this->nodes) { - size_t node_idx = &node - &this->nodes.front(); - // Skip nodes that represent points of input polygons. - if (node.arc_idxs.size() == 1 && node_idx >= this->all_border_points) - update_queue.emplace(&node - &this->nodes.front()); - } - - while (!update_queue.empty()) { - size_t node_from_idx = update_queue.front(); - MMU_Graph::Node &node_from = this->nodes[update_queue.front()]; - update_queue.pop(); - if (node_from.arc_idxs.empty()) - continue; - - assert(node_from.arc_idxs.size() == 1); - size_t node_to_idx = arcs[node_from.arc_idxs.front()].to_idx; - MMU_Graph::Node &node_to = this->nodes[node_to_idx]; - this->remove_edge(node_from_idx, node_to_idx); - if (node_to.arc_idxs.size() == 1 && node_to_idx >= this->all_border_points) - update_queue.emplace(node_to_idx); - } - } - - void add_contours(const std::vector> &color_poly) - { - this->all_border_points = nodes.size(); - this->polygon_sizes = std::vector(color_poly.size()); - for (size_t polygon_idx = 0; polygon_idx < color_poly.size(); ++polygon_idx) - this->polygon_sizes[polygon_idx] = color_poly[polygon_idx].size(); - this->polygon_idx_offset = std::vector(color_poly.size()); - this->polygon_idx_offset[0] = 0; - for (size_t polygon_idx = 1; polygon_idx < color_poly.size(); ++polygon_idx) { - this->polygon_idx_offset[polygon_idx] = this->polygon_idx_offset[polygon_idx - 1] + color_poly[polygon_idx - 1].size(); - } - - size_t poly_idx = 0; - for (const std::vector &color_lines : color_poly) { - size_t line_idx = 0; - for (const ColoredLine &color_line : color_lines) { - size_t from_idx = this->get_global_index(poly_idx, line_idx); - size_t to_idx = this->get_global_index(poly_idx, (line_idx + 1) % color_lines.size()); - this->append_edge(from_idx, to_idx, color_line.color, ARC_TYPE::BORDER); - ++line_idx; - } - ++poly_idx; - } - } - - // Nodes 0..all_border_points are only one with are on countour. Other vertexis are consider as not on coouter. So we check if base on attach index - inline bool is_vertex_on_contour(const Voronoi::VD::vertex_type *vertex) const - { - assert(vertex != nullptr); - return vertex->color() < this->all_border_points; - } - - [[nodiscard]] inline bool is_edge_attach_to_contour(const voronoi_diagram::const_edge_iterator &edge_iterator) const - { - return this->is_vertex_on_contour(edge_iterator->vertex0()) || this->is_vertex_on_contour(edge_iterator->vertex1()); - } - - [[nodiscard]] inline bool is_edge_connecting_two_contour_vertices(const voronoi_diagram::const_edge_iterator &edge_iterator) const - { - return this->is_vertex_on_contour(edge_iterator->vertex0()) && this->is_vertex_on_contour(edge_iterator->vertex1()); - } - - // All Voronoi vertices are post-processes to merge very close vertices to single. Witch eliminates issues with intersection edges. - // Also, Voronoi vertices outside of the bounding of input polygons are throw away by marking them. - void append_voronoi_vertices(const Geometry::VoronoiDiagram &vd, const Polygons &color_poly_tmp, BoundingBox bbox) { - bbox.offset(SCALED_EPSILON); - - struct CPoint - { - CPoint() = delete; - CPoint(const Vec2d &point, size_t contour_idx, size_t point_idx) : m_point_double(point), m_point(mk_point(point)), m_point_idx(point_idx), m_contour_idx(contour_idx) {} - CPoint(const Vec2d &point, size_t point_idx) : m_point_double(point), m_point(mk_point(point)), m_point_idx(point_idx), m_contour_idx(0) {} - const Vec2d m_point_double; - const Point m_point; - size_t m_point_idx; - size_t m_contour_idx; - - [[nodiscard]] const Vec2d &point_double() const { return m_point_double; } - [[nodiscard]] const Point &point() const { return m_point; } - bool operator==(const CPoint &rhs) const { return this->m_point_double == rhs.m_point_double && this->m_contour_idx == rhs.m_contour_idx && this->m_point_idx == rhs.m_point_idx; } - }; - struct CPointAccessor { const Point* operator()(const CPoint &pt) const { return &pt.point(); }}; - typedef ClosestPointInRadiusLookup CPointLookupType; - - CPointLookupType closest_voronoi_point(coord_t(SCALED_EPSILON)); - CPointLookupType closest_contour_point(3 * coord_t(SCALED_EPSILON)); - for (const Polygon &polygon : color_poly_tmp) - for (const Point &pt : polygon.points) - closest_contour_point.insert(CPoint(Vec2d(pt.x(), pt.y()), &polygon - &color_poly_tmp.front(), &pt - &polygon.points.front())); - - for (const voronoi_diagram::vertex_type &vertex : vd.vertices()) { - vertex.color(-1); - Vec2d vertex_point_double = Vec2d(vertex.x(), vertex.y()); - Point vertex_point = mk_point(vertex); - - const Vec2d &first_point_double = this->nodes[this->get_border_arc(vertex.incident_edge()->cell()->source_index()).from_idx].point; - const Vec2d &second_point_double = this->nodes[this->get_border_arc(vertex.incident_edge()->twin()->cell()->source_index()).from_idx].point; - - if (vertex_equal_to_point(&vertex, first_point_double)) { - assert(vertex.color() != vertex.incident_edge()->cell()->source_index()); - assert(vertex.color() != vertex.incident_edge()->twin()->cell()->source_index()); - vertex.color(this->get_border_arc(vertex.incident_edge()->cell()->source_index()).from_idx); - } else if (vertex_equal_to_point(&vertex, second_point_double)) { - assert(vertex.color() != vertex.incident_edge()->cell()->source_index()); - assert(vertex.color() != vertex.incident_edge()->twin()->cell()->source_index()); - vertex.color(this->get_border_arc(vertex.incident_edge()->twin()->cell()->source_index()).from_idx); - } else if (bbox.contains(vertex_point)) { - if (auto [contour_pt, c_dist_sqr] = closest_contour_point.find(vertex_point); contour_pt != nullptr && c_dist_sqr < Slic3r::sqr(3 * SCALED_EPSILON)) { - vertex.color(this->get_global_index(contour_pt->m_contour_idx, contour_pt->m_point_idx)); - } else if (auto [voronoi_pt, v_dist_sqr] = closest_voronoi_point.find(vertex_point); voronoi_pt == nullptr || v_dist_sqr >= Slic3r::sqr(SCALED_EPSILON / 10.0)) { - closest_voronoi_point.insert(CPoint(vertex_point_double, this->nodes_count())); - vertex.color(this->nodes_count()); - this->nodes.push_back({vertex_point_double}); - } else { - // Boost Voronoi diagram generator sometimes creates two very closed points instead of one point. - // For the example points (146872.99999999997, -146872.99999999997) and (146873, -146873), this example also included in Voronoi generator test cases. - std::vector> all_closes_c_points = closest_voronoi_point.find_all(vertex_point); - int merge_to_point = -1; - for (const std::pair &c_point : all_closes_c_points) - if ((vertex_point_double - c_point.first->point_double()).squaredNorm() <= Slic3r::sqr(EPSILON)) { - merge_to_point = int(c_point.first->m_point_idx); - break; - } - - if (merge_to_point != -1) { - vertex.color(merge_to_point); - } else { - closest_voronoi_point.insert(CPoint(vertex_point_double, this->nodes_count())); - vertex.color(this->nodes_count()); - this->nodes.push_back({vertex_point_double}); - } - } - } - } - } - - void garbage_collect() - { - std::vector nodes_map(this->nodes.size(), -1); - int nodes_count = 0; - size_t arcs_count = 0; - for (const MMU_Graph::Node &node : this->nodes) - if (size_t node_idx = &node - &this->nodes.front(); !node.arc_idxs.empty()) { - nodes_map[node_idx] = nodes_count++; - arcs_count += node.arc_idxs.size(); - } - - std::vector new_nodes; - std::vector new_arcs; - new_nodes.reserve(nodes_count); - new_arcs.reserve(arcs_count); - for (const MMU_Graph::Node &node : this->nodes) - if (size_t node_idx = &node - &this->nodes.front(); nodes_map[node_idx] >= 0) { - new_nodes.push_back({node.point}); - for (const size_t &arc_idx : node.arc_idxs) { - const Arc &arc = this->arcs[arc_idx]; - new_nodes.back().arc_idxs.emplace_back(new_arcs.size()); - new_arcs.push_back({size_t(nodes_map[arc.from_idx]), size_t(nodes_map[arc.to_idx]), arc.color, arc.type}); - } - } - - this->nodes = std::move(new_nodes); - this->arcs = std::move(new_arcs); - } -}; - -static inline void mark_processed(const voronoi_diagram::const_edge_iterator &edge_iterator) -{ - edge_iterator->color(true); - edge_iterator->twin()->color(true); -} - -// Return true, if "p" is closer to line.a, then line.b -static inline bool is_point_closer_to_beginning_of_line(const Line &line, const Point &p) -{ - return (p - line.a).cast().squaredNorm() < (p - line.b).cast().squaredNorm(); -} - -static inline bool has_same_color(const ColoredLine &cl1, const ColoredLine &cl2) { return cl1.color == cl2.color; } - // Determines if the line points from the point between two contour lines is pointing inside polygon or outside. static inline bool points_inside(const Line &contour_first, const Line &contour_second, const Point &new_point) { - // Used in points_inside for decision if line leading thought the common point of two lines is pointing inside polygon or outside + // TODO: Used in points_inside for decision if line leading thought the common point of two lines is pointing inside polygon or outside auto three_points_inward_normal = [](const Point &left, const Point &middle, const Point &right) -> Vec2d { assert(left != middle); assert(middle != right); @@ -839,534 +524,309 @@ static inline bool points_inside(const Line &contour_first, const Line &contour_ return side > 0.; } -static inline bool line_intersection_with_epsilon(const Line &line_to_extend, const Line &other, Point *intersection) -{ - Line extended_line = line_to_extend; - extended_line.extend(15 * SCALED_EPSILON); - return extended_line.intersection(other, intersection); +enum VD_ANNOTATION : Voronoi::VD::cell_type::color_type { + VERTEX_ON_CONTOUR = 1, + DELETED = 2 +}; + +#ifdef MM_SEGMENTATION_DEBUG_GRAPH +static void export_graph_to_svg(const std::string &path, const Voronoi::VD& vd, const std::vector& colored_polygons) { + const coordf_t stroke_width = scaled(0.05f); + const BoundingBox bbox = get_extents(colored_polygons); + + SVG svg(path.c_str(), bbox); + for (const ColoredLines &colored_lines : colored_polygons) + for (const ColoredLine &colored_line : colored_lines) + svg.draw(colored_line.line, "black", stroke_width); + + for (const Voronoi::VD::vertex_type &vertex : vd.vertices()) { + if (Geometry::VoronoiUtils::is_in_range(vertex)) { + if (const Point pt = Geometry::VoronoiUtils::to_point(&vertex).cast(); vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR) { + svg.draw(pt, "blue", coord_t(stroke_width)); + } else if (vertex.color() != VD_ANNOTATION::DELETED) { + svg.draw(pt, "green", coord_t(stroke_width)); + } + } + } + + for (const Voronoi::VD::edge_type &edge : vd.edges()) { + if (edge.is_infinite() || !Geometry::VoronoiUtils::is_in_range(edge)) + continue; + + const Point from = Geometry::VoronoiUtils::to_point(edge.vertex0()).cast(); + const Point to = Geometry::VoronoiUtils::to_point(edge.vertex1()).cast(); + + if (edge.color() != VD_ANNOTATION::DELETED) + svg.draw(Line(from, to), "red", stroke_width); + } +} +#endif // MM_SEGMENTATION_DEBUG_GRAPH + +static size_t non_deleted_edge_count(const VD::vertex_type &vertex) { + size_t non_deleted_edge_cnt = 0; + const VD::edge_type *edge = vertex.incident_edge(); + do { + if (edge->color() != VD_ANNOTATION::DELETED) + ++non_deleted_edge_cnt; + } while (edge = edge->prev()->twin(), edge != vertex.incident_edge()); + + return non_deleted_edge_cnt; } -// For every ColoredLine in lines_colored_out, assign the index of the polygon to which belongs and also the index of this line inside of the polygon. -static inline void init_polygon_indices(const MMU_Graph &graph, - const std::vector> &color_poly, - std::vector &lines_colored_out) -{ - size_t poly_idx = 0; - for (const std::vector &color_lines : color_poly) { - size_t line_idx = 0; - for (size_t color_line_idx = 0; color_line_idx < color_lines.size(); ++color_line_idx) { - size_t from_idx = graph.get_global_index(poly_idx, line_idx); - lines_colored_out[from_idx].poly_idx = int(poly_idx); - lines_colored_out[from_idx].local_line_idx = int(line_idx); - ++line_idx; - } - ++poly_idx; +static bool can_vertex_be_deleted(const VD::vertex_type &vertex) { + if (vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR || vertex.color() == VD_ANNOTATION::DELETED) + return false; + + return non_deleted_edge_count(vertex) <= 1; +} + +static void delete_vertex_deep(const VD::vertex_type &vertex) { + std::queue vertices_to_delete; + vertices_to_delete.emplace(&vertex); + + while (!vertices_to_delete.empty()) { + const VD::vertex_type &vertex_to_delete = *vertices_to_delete.front(); + vertices_to_delete.pop(); + vertex_to_delete.color(VD_ANNOTATION::DELETED); + + const VD::edge_type *edge = vertex_to_delete.incident_edge(); + do { + edge->color(VD_ANNOTATION::DELETED); + edge->twin()->color(VD_ANNOTATION::DELETED); + + if (edge->is_finite() && can_vertex_be_deleted(*edge->vertex1())) + vertices_to_delete.emplace(edge->vertex1()); + } while (edge = edge->prev()->twin(), edge != vertex_to_delete.incident_edge()); } } -// Voronoi edges produced by Voronoi generator cloud have coordinates that don't fit inside coord_t (int32_t). -// Because of that, this function tries to clip edges that have one endpoint of the edge inside the BoundingBox. -static inline Line clip_finite_voronoi_edge(const Voronoi::VD::edge_type &edge, const BoundingBoxf &bbox) -{ +static inline Vec2d mk_point_vec2d(const VD::vertex_type *point) { + assert(point != nullptr); + return {point->x(), point->y()}; +} + +static inline Vec2d mk_vector_vec2d(const VD::edge_type *edge) { + assert(edge != nullptr); + return mk_point_vec2d(edge->vertex1()) - mk_point_vec2d(edge->vertex0()); +} + +static inline Vec2d mk_flipped_vector_vec2d(const VD::edge_type *edge) { + assert(edge != nullptr); + return mk_point_vec2d(edge->vertex0()) - mk_point_vec2d(edge->vertex1()); +} + +static double edge_length(const VD::edge_type &edge) { assert(edge.is_finite()); - Vec2d v0 = mk_vec2(edge.vertex0()); - Vec2d v1 = mk_vec2(edge.vertex1()); - bool contains_v0 = bbox.contains(v0); - bool contains_v1 = bbox.contains(v1); - if ((contains_v0 && contains_v1) || (!contains_v0 && !contains_v1)) - return {mk_point(edge.vertex0()), mk_point(edge.vertex1())}; - - Vec2d vector = (v1 - v0).normalized() * bbox.size().norm(); - if (!contains_v0) - v0 = (v1 - vector); - else - v1 = (v0 + vector); - - return {v0.cast(), v1.cast()}; -} - -static MMU_Graph build_graph(size_t layer_idx, const std::vector> &color_poly) -{ - Geometry::VoronoiDiagram vd; - std::vector lines_colored = to_lines(color_poly); - const Polygons color_poly_tmp = colored_points_to_polygon(color_poly); - const Points points = to_points(color_poly_tmp); - const Lines lines = to_lines(color_poly_tmp); - - // The algorithm adds edges to the graph that are between two different colors. - // If a polygon is colored entirely with one color, we need to add at least one edge from that polygon artificially. - // Adding this edge is necessary for cases where the expolygon has an outer contour colored whole with one color - // and a hole colored with a different color. If an edge wasn't added to the graph, - // the entire expolygon would be colored with single random color instead of two different. - std::vector force_edge_adding(color_poly.size()); - - // For each polygon, check if it is all colored with the same color. If it is, we need to force adding one edge to it. - for (const std::vector &c_poly : color_poly) { - bool force_edge = true; - for (const ColoredLine &c_line : c_poly) - if (c_line.color != c_poly.front().color) { - force_edge = false; - break; - } - force_edge_adding[&c_poly - &color_poly.front()] = force_edge; - } - - boost::polygon::construct_voronoi(lines_colored.begin(), lines_colored.end(), &vd); - MMU_Graph graph; - graph.nodes.reserve(points.size() + vd.vertices().size()); - for (const Point &point : points) - graph.nodes.push_back({Vec2d(double(point.x()), double(point.y()))}); - - graph.add_contours(color_poly); - init_polygon_indices(graph, color_poly, lines_colored); - - assert(graph.nodes.size() == lines_colored.size()); - BoundingBox bbox = get_extents(color_poly_tmp); - graph.append_voronoi_vertices(vd, color_poly_tmp, bbox); - - auto get_prev_contour_line = [&lines_colored, &color_poly, &graph](const voronoi_diagram::const_edge_iterator &edge_it) -> ColoredLine { - size_t contour_line_local_idx = lines_colored[edge_it->cell()->source_index()].local_line_idx; - size_t contour_line_size = color_poly[lines_colored[edge_it->cell()->source_index()].poly_idx].size(); - size_t contour_prev_idx = graph.get_global_index(lines_colored[edge_it->cell()->source_index()].poly_idx, - (contour_line_local_idx > 0) ? contour_line_local_idx - 1 : contour_line_size - 1); - return lines_colored[contour_prev_idx]; - }; - - auto get_next_contour_line = [&lines_colored, &color_poly, &graph](const voronoi_diagram::const_edge_iterator &edge_it) -> ColoredLine { - size_t contour_line_local_idx = lines_colored[edge_it->cell()->source_index()].local_line_idx; - size_t contour_line_size = color_poly[lines_colored[edge_it->cell()->source_index()].poly_idx].size(); - size_t contour_next_idx = graph.get_global_index(lines_colored[edge_it->cell()->source_index()].poly_idx, - (contour_line_local_idx + 1) % contour_line_size); - return lines_colored[contour_next_idx]; - }; - - bbox.offset(scale_(10.)); - const BoundingBoxf bbox_clip(bbox.min.cast(), bbox.max.cast()); - const double bbox_dim_max = double(std::max(bbox.size().x(), bbox.size().y())); - - // Make a copy of the input segments with the double type. - std::vector segments; - for (const Line &line : lines) - segments.emplace_back(Voronoi::Internal::point_type(double(line.a(0)), double(line.a(1))), - Voronoi::Internal::point_type(double(line.b(0)), double(line.b(1)))); - - for (auto edge_it = vd.edges().begin(); edge_it != vd.edges().end(); ++edge_it) { - // Skip second half-edge - if (edge_it->cell()->source_index() > edge_it->twin()->cell()->source_index() || edge_it->color()) - continue; - - if (edge_it->is_infinite() && (edge_it->vertex0() != nullptr || edge_it->vertex1() != nullptr)) { - // Infinite edge is leading through a point on the counter, but there are no Voronoi vertices. - // So we could fix this case by computing the intersection between the contour line and infinity edge. - std::vector samples; - Voronoi::Internal::clip_infinite_edge(points, segments, *edge_it, bbox_dim_max, &samples); - if (samples.empty()) - continue; - - const Line edge_line(mk_point(samples[0]), mk_point(samples[1])); - const ColoredLine &contour_line = lines_colored[edge_it->cell()->source_index()]; - Point contour_intersection; - - if (line_intersection_with_epsilon(contour_line.line, edge_line, &contour_intersection)) { - const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_it->cell()->source_index()); - const size_t from_idx = (edge_it->vertex1() != nullptr) ? edge_it->vertex1()->color() : edge_it->vertex0()->color(); - size_t to_idx = ((contour_line.line.a - contour_intersection).cast().squaredNorm() < - (contour_line.line.b - contour_intersection).cast().squaredNorm()) ? - graph_arc.from_idx : - graph_arc.to_idx; - if (from_idx != to_idx && from_idx < graph.nodes_count() && to_idx < graph.nodes_count()) { - graph.append_edge(from_idx, to_idx); - mark_processed(edge_it); - } - } - } else if (edge_it->is_finite()) { - // Both points are on contour, so skip them. In cases of duplicate Voronoi vertices, skip edges between the same two points. - if (graph.is_edge_connecting_two_contour_vertices(edge_it) || (edge_it->vertex0()->color() == edge_it->vertex1()->color())) - continue; - - const Line edge_line = clip_finite_voronoi_edge(*edge_it, bbox_clip); - const Line contour_line = lines_colored[edge_it->cell()->source_index()].line; - const ColoredLine colored_line = lines_colored[edge_it->cell()->source_index()]; - const ColoredLine contour_line_prev = get_prev_contour_line(edge_it); - const ColoredLine contour_line_next = get_next_contour_line(edge_it); - - if (edge_it->vertex0()->color() >= graph.nodes_count() || edge_it->vertex1()->color() >= graph.nodes_count()) { - enum class Vertex { VERTEX0, VERTEX1 }; - auto append_edge_if_intersects_with_contour = [&graph, &lines_colored, &edge_line, &contour_line](const voronoi_diagram::const_edge_iterator &edge_iterator, const Vertex vertex) { - Point intersection; - Line contour_line_twin = lines_colored[edge_iterator->twin()->cell()->source_index()].line; - if (line_intersection_with_epsilon(contour_line_twin, edge_line, &intersection)) { - const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_iterator->twin()->cell()->source_index()); - const size_t to_idx_l = is_point_closer_to_beginning_of_line(contour_line_twin, intersection) ? graph_arc.from_idx : - graph_arc.to_idx; - graph.append_edge(vertex == Vertex::VERTEX0 ? edge_iterator->vertex0()->color() : edge_iterator->vertex1()->color(), to_idx_l); - } else if (line_intersection_with_epsilon(contour_line, edge_line, &intersection)) { - const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_iterator->cell()->source_index()); - const size_t to_idx_l = is_point_closer_to_beginning_of_line(contour_line, intersection) ? graph_arc.from_idx : graph_arc.to_idx; - graph.append_edge(vertex == Vertex::VERTEX0 ? edge_iterator->vertex0()->color() : edge_iterator->vertex1()->color(), to_idx_l); - } - mark_processed(edge_iterator); - }; - - if (edge_it->vertex0()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex0())) - append_edge_if_intersects_with_contour(edge_it, Vertex::VERTEX0); - - if (edge_it->vertex1()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex1())) - append_edge_if_intersects_with_contour(edge_it, Vertex::VERTEX1); - } else if (graph.is_edge_attach_to_contour(edge_it)) { - mark_processed(edge_it); - // Skip edges witch connection two points on a contour - if (graph.is_edge_connecting_two_contour_vertices(edge_it)) - continue; - - const size_t from_idx = edge_it->vertex0()->color(); - const size_t to_idx = edge_it->vertex1()->color(); - if (graph.is_vertex_on_contour(edge_it->vertex0())) { - if (is_point_closer_to_beginning_of_line(contour_line, edge_line.a)) { - if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, edge_line.b)) { - graph.append_edge(from_idx, to_idx); - force_edge_adding[colored_line.poly_idx] = false; - } - } else { - if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, edge_line.b)) { - graph.append_edge(from_idx, to_idx); - force_edge_adding[colored_line.poly_idx] = false; - } - } - } else { - assert(graph.is_vertex_on_contour(edge_it->vertex1())); - if (is_point_closer_to_beginning_of_line(contour_line, edge_line.b)) { - if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, edge_line.a)) { - graph.append_edge(from_idx, to_idx); - force_edge_adding[colored_line.poly_idx] = false; - } - } else { - if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, edge_line.a)) { - graph.append_edge(from_idx, to_idx); - force_edge_adding[colored_line.poly_idx] = false; - } - } - } - } else if (Point intersection; line_intersection_with_epsilon(contour_line, edge_line, &intersection)) { - mark_processed(edge_it); - Vec2d real_v0_double = graph.nodes[edge_it->vertex0()->color()].point; - Vec2d real_v1_double = graph.nodes[edge_it->vertex1()->color()].point; - Point real_v0 = Point(coord_t(real_v0_double.x()), coord_t(real_v0_double.y())); - Point real_v1 = Point(coord_t(real_v1_double.x()), coord_t(real_v1_double.y())); - - if (is_point_closer_to_beginning_of_line(contour_line, intersection)) { - Line first_part(intersection, real_v0); - Line second_part(intersection, real_v1); - - if (!has_same_color(contour_line_prev, colored_line)) { - if (points_inside(contour_line_prev.line, contour_line, first_part.b)) - graph.append_edge(edge_it->vertex0()->color(), graph.get_border_arc(edge_it->cell()->source_index()).from_idx); - - if (points_inside(contour_line_prev.line, contour_line, second_part.b)) - graph.append_edge(edge_it->vertex1()->color(), graph.get_border_arc(edge_it->cell()->source_index()).from_idx); - } - } else { - const size_t int_point_idx = graph.get_border_arc(edge_it->cell()->source_index()).to_idx; - const Vec2d int_point_double = graph.nodes[int_point_idx].point; - const Point int_point = Point(coord_t(int_point_double.x()), coord_t(int_point_double.y())); - - const Line first_part(int_point, real_v0); - const Line second_part(int_point, real_v1); - - if (!has_same_color(contour_line_next, colored_line)) { - if (points_inside(contour_line, contour_line_next.line, first_part.b)) - graph.append_edge(edge_it->vertex0()->color(), int_point_idx); - - if (points_inside(contour_line, contour_line_next.line, second_part.b)) - graph.append_edge(edge_it->vertex1()->color(), int_point_idx); - } - } - } - } - } - - for (auto edge_it = vd.edges().begin(); edge_it != vd.edges().end(); ++edge_it) { - // Skip second half-edge and processed edges - if (edge_it->cell()->source_index() > edge_it->twin()->cell()->source_index() || edge_it->color()) - continue; - - if (edge_it->is_finite() && !bool(edge_it->color()) && edge_it->vertex0()->color() < graph.nodes_count() && - edge_it->vertex1()->color() < graph.nodes_count()) { - // Skip cases, when the edge is between two same vertices, which is in cases two near vertices were merged together. - if (edge_it->vertex0()->color() == edge_it->vertex1()->color()) - continue; - - size_t from_idx = edge_it->vertex0()->color(); - size_t to_idx = edge_it->vertex1()->color(); - graph.append_edge(from_idx, to_idx); - } - mark_processed(edge_it); - } - - graph.remove_nodes_with_one_arc(); - return graph; -} - -static inline Polygon to_polygon(const std::vector> &id_to_lines) -{ - std::vector lines; - for (auto id_to_line : id_to_lines) - lines.emplace_back(id_to_line.second); - - Polygon poly_out; - poly_out.points.reserve(lines.size()); - for (const Linef &line : lines) - poly_out.points.emplace_back(mk_point(line.a)); - return poly_out; -} - - -static std::vector> get_all_next_arcs( - const MMU_Graph &graph, - std::vector &used_arcs, - const Linef &process_line, - const MMU_Graph::Arc &original_arc, - const int color) -{ - std::vector> all_next_arcs; - for (const size_t &arc_idx : graph.nodes[original_arc.to_idx].arc_idxs) { - std::vector next_continue_arc; - - const MMU_Graph::Arc & arc = graph.arcs[arc_idx]; - if (graph.nodes[arc.to_idx].point == process_line.a || used_arcs[arc_idx]) - continue; - - if (original_arc.type == MMU_Graph::ARC_TYPE::BORDER && original_arc.color != color) - continue; - - if (arc.type == MMU_Graph::ARC_TYPE::BORDER && arc.color != color) - continue; - - Vec2d arc_line = graph.nodes[arc.to_idx].point - graph.nodes[arc.from_idx].point; - next_continue_arc.emplace_back(&arc); - all_next_arcs.emplace_back(next_continue_arc); - } - return all_next_arcs; -} - -// two points that are very close are considered as one point -// std::vector contain the close points -static std::vector get_next_arc( - const MMU_Graph &graph, - std::vector &used_arcs, - const Linef &process_line, - const MMU_Graph::Arc &original_arc, - const int color) -{ - std::vector res; - - std::vector> all_next_arcs = get_all_next_arcs(graph, used_arcs, process_line, original_arc, color); - if (all_next_arcs.empty()) { - res.emplace_back(&original_arc); - return res; - } - - std::vector, double>> sorted_arcs; - for (auto next_arc : all_next_arcs) { - if (next_arc.empty()) - continue; - - Vec2d process_line_vec_n = (process_line.a - process_line.b).normalized(); - Vec2d neighbour_line_vec_n = (graph.nodes[next_arc.back()->to_idx].point - graph.nodes[next_arc.back()->from_idx].point).normalized(); - - double angle = ::acos(std::clamp(neighbour_line_vec_n.dot(process_line_vec_n), -1.0, 1.0)); - if (Slic3r::cross2(neighbour_line_vec_n, process_line_vec_n) < 0.0) - angle = 2.0 * (double) PI - angle; - - sorted_arcs.emplace_back(next_arc, angle); - } - - std::sort(sorted_arcs.begin(), sorted_arcs.end(), - [](std::pair, double> &l, std::pair, double> &r) -> bool { - return l.second < r.second; - }); - - // Try to return left most edge witch is unused - for (auto &sorted_arc : sorted_arcs) { - if (size_t arc_idx = sorted_arc.first.back() - &graph.arcs.front(); !used_arcs[arc_idx]) - return sorted_arc.first; - } - - if (sorted_arcs.empty()) { - res.emplace_back(&original_arc); - return res; - } - - return sorted_arcs.front().first; -} - -static bool is_profile_self_interaction(Polygon poly) -{ - auto lines = poly.lines(); - Point intersection; - for (int i = 0; i < lines.size(); ++i) { - for (int j = i + 2; j < std::min(lines.size(), lines.size() + i - 1); ++j) { - if (lines[i].intersection(lines[j], &intersection)) - return true; - } - } - return false; -} - -// Returns list of polygons and assigned colors. -// It iterates through all nodes on the border between two different colors, and from this point, -// start selection always left most edges for every node to construct CCW polygons. -// Assumes that graph is planar (without self-intersection edges) -static std::vector extract_colored_segments(const MMU_Graph &graph, const size_t num_extruders) -{ - std::vector used_arcs(graph.arcs.size(), false); - - auto all_arc_used = [&used_arcs](const MMU_Graph::Node &node) -> bool { - return std::all_of(node.arc_idxs.cbegin(), node.arc_idxs.cend(), [&used_arcs](const size_t &arc_idx) -> bool { return used_arcs[arc_idx]; }); - }; - - std::vector expolygons_segments(num_extruders + 1); - for (size_t node_idx = 0; node_idx < graph.all_border_points; ++node_idx) { - const MMU_Graph::Node &node = graph.nodes[node_idx]; - - for (const size_t &arc_idx : node.arc_idxs) { - const MMU_Graph::Arc &arc = graph.arcs[arc_idx]; - if (arc.type == MMU_Graph::ARC_TYPE::NON_BORDER || used_arcs[arc_idx]) - continue; - - Linef process_line(graph.nodes[arc.from_idx].point, graph.nodes[arc.to_idx].point); - used_arcs[arc_idx] = true; - - std::vector> arc_id_to_face_lines; - arc_id_to_face_lines.emplace_back(std::make_pair(arc_idx, process_line)); - Vec2d start_p = process_line.a; - - Linef p_vec = process_line; - const MMU_Graph::Arc *p_arc = &arc; - bool flag = false; - do { - std::vector nexts = get_next_arc(graph, used_arcs, p_vec, *p_arc, arc.color); - for (auto next : nexts) { - size_t next_arc_idx = next - &graph.arcs.front(); - if (used_arcs[next_arc_idx]) { - flag = true; - break; - } - } - - if (flag) - break; - - for (auto next : nexts) { - size_t next_arc_idx = next - &graph.arcs.front(); - arc_id_to_face_lines.emplace_back(std::make_pair(next_arc_idx, Linef(graph.nodes[next->from_idx].point, graph.nodes[next->to_idx].point))); - used_arcs[next_arc_idx] = true; - } - - p_vec = Linef(graph.nodes[nexts.back()->from_idx].point, graph.nodes[nexts.back()->to_idx].point); - p_arc = nexts.back(); - - } while (graph.nodes[p_arc->to_idx].point != start_p || !all_arc_used(graph.nodes[p_arc->to_idx])); - - if (Polygon poly = to_polygon(arc_id_to_face_lines); poly.is_counter_clockwise() && poly.is_valid()) { - expolygons_segments[arc.color].emplace_back(std::move(poly)); - } else{ - while (arc_id_to_face_lines.size() > 1) - { - auto id_to_line = arc_id_to_face_lines.back(); - used_arcs[id_to_line.first] = false; - arc_id_to_face_lines.pop_back(); - Linef add_line(arc_id_to_face_lines.back().second.b, arc_id_to_face_lines.front().second.a); - arc_id_to_face_lines.emplace_back(std::make_pair(-1, add_line)); - Polygon poly = to_polygon(arc_id_to_face_lines); - if (!is_profile_self_interaction(poly) && poly.is_counter_clockwise() && poly.is_valid()) { - expolygons_segments[arc.color].emplace_back(std::move(poly)); - break; - } - arc_id_to_face_lines.pop_back(); - } - } - } - } - return expolygons_segments; + return mk_vector_vec2d(&edge).norm(); } // Used in remove_multiple_edges_in_vertices() // Returns length of edge with is connected to contour. To this length is include other edges with follows it if they are almost straight (with the // tolerance of 15) And also if node between two subsequent edges is connected only to these two edges. -static inline double compute_edge_length(const MMU_Graph &graph, const size_t start_idx, const size_t &start_arc_idx) +static inline double calc_total_edge_length(const VD::edge_type &starting_edge) { - assert(start_arc_idx < graph.arcs.size()); - std::vector used_arcs(graph.arcs.size(), false); - - used_arcs[start_arc_idx] = true; - const MMU_Graph::Arc *arc = &graph.arcs[start_arc_idx]; - size_t idx = start_idx; - double line_total_length = (graph.nodes[arc->to_idx].point - graph.nodes[idx].point).norm(); - while (graph.nodes[arc->to_idx].arc_idxs.size() == 2) { - bool found = false; - for (const size_t &arc_idx : graph.nodes[arc->to_idx].arc_idxs) { - if (const MMU_Graph::Arc &arc_n = graph.arcs[arc_idx]; arc_n.type == MMU_Graph::ARC_TYPE::NON_BORDER && !used_arcs[arc_idx] && arc_n.to_idx != idx) { - Linef first_line(graph.nodes[idx].point, graph.nodes[arc->to_idx].point); - Linef second_line(graph.nodes[arc->to_idx].point, graph.nodes[arc_n.to_idx].point); - - Vec2d first_line_vec = (first_line.a - first_line.b); - Vec2d second_line_vec = (second_line.b - second_line.a); - Vec2d first_line_vec_n = first_line_vec.normalized(); - Vec2d second_line_vec_n = second_line_vec.normalized(); - double angle = ::acos(std::clamp(first_line_vec_n.dot(second_line_vec_n), -1.0, 1.0)); - if (Slic3r::cross2(first_line_vec_n, second_line_vec_n) < 0.0) - angle = 2.0 * (double) PI - angle; - - if (std::abs(angle - PI) >= (PI / 12)) - continue; - - idx = arc->to_idx; - arc = &arc_n; - - line_total_length += (graph.nodes[arc->to_idx].point - graph.nodes[idx].point).norm(); - used_arcs[arc_idx] = true; - found = true; - break; - } - } - if (!found) + double total_edge_length = edge_length(starting_edge); + const VD::edge_type *prev = &starting_edge; + do { + if (prev->is_finite() && non_deleted_edge_count(*prev->vertex1()) > 2) break; - } - return line_total_length; + bool found_next_edge = false; + const VD::edge_type *current = prev->next(); + do { + if (current->color() == VD_ANNOTATION::DELETED) + continue; + + Vec2d first_line_vec_n = mk_flipped_vector_vec2d(prev).normalized(); + Vec2d second_line_vec_n = mk_vector_vec2d(current).normalized(); + double angle = ::acos(std::clamp(first_line_vec_n.dot(second_line_vec_n), -1.0, 1.0)); + if (Slic3r::cross2(first_line_vec_n, second_line_vec_n) < 0.0) + angle = 2.0 * (double) PI - angle; + + if (std::abs(angle - PI) >= (PI / 12)) + continue; + + prev = current; + found_next_edge = true; + total_edge_length += edge_length(*current); + + break; + } while (current = current->prev()->twin(), current != prev->next()); + + if (!found_next_edge) + break; + + } while (prev != &starting_edge); + + return total_edge_length; } -// Used for fixing double Voronoi edges for concave parts of the polygon. -static void remove_multiple_edges_in_vertices(MMU_Graph &graph, const std::vector> &color_poly) +// When a Voronoi vertex has more than one Voronoi edge (for example, in concave parts of a polygon), +// we leave just one Voronoi edge in the Voronoi vertex. +// This Voronoi edge is selected based on a heuristic. +static void remove_multiple_edges_in_vertex(const VD::vertex_type &vertex) { + if (non_deleted_edge_count(vertex) <= 1) + return; + + std::vector> edges_to_check; + const VD::edge_type *edge = vertex.incident_edge(); + do { + if (edge->color() == VD_ANNOTATION::DELETED) + continue; + + edges_to_check.emplace_back(edge, calc_total_edge_length(*edge)); + } while (edge = edge->prev()->twin(), edge != vertex.incident_edge()); + + std::sort(edges_to_check.begin(), edges_to_check.end(), [](const auto &l, const auto &r) -> bool { + return l.second > r.second; + }); + + while (edges_to_check.size() > 1) { + const VD::edge_type &edge_to_check = *edges_to_check.back().first; + edge_to_check.color(VD_ANNOTATION::DELETED); + edge_to_check.twin()->color(VD_ANNOTATION::DELETED); + + if (const VD::vertex_type &vertex_to_delete = *edge_to_check.vertex1(); can_vertex_be_deleted(vertex_to_delete)) + delete_vertex_deep(vertex_to_delete); + + edges_to_check.pop_back(); + } +} + +// Returns list of ExPolygons for each extruder + 1 for default unpainted regions. +// It iterates through all nodes on the border between two different colors, and from this point, +// start selection always left most edges for every node to construct CCW polygons. +static std::vector extract_colored_segments(const std::vector &colored_polygons, + const size_t num_extruders, + const size_t layer_idx) { - std::vector>> colored_segments = get_all_segments(color_poly); - for (const std::vector> &colored_segment_p : colored_segments) { - size_t poly_idx = &colored_segment_p - &colored_segments.front(); - for (const std::pair &colored_segment : colored_segment_p) { - size_t first_idx = graph.get_global_index(poly_idx, colored_segment.first); - size_t second_idx = graph.get_global_index(poly_idx, (colored_segment.second + 1) % graph.polygon_sizes[poly_idx]); - Linef seg_line(graph.nodes[first_idx].point, graph.nodes[second_idx].point); + const ColoredLines colored_lines = to_lines(colored_polygons); + const BoundingBox bbox = get_extents(colored_polygons); - if (graph.nodes[first_idx].arc_idxs.size() >= 3) { - std::vector> arc_to_check; - for (const size_t &arc_idx : graph.nodes[first_idx].arc_idxs) { - MMU_Graph::Arc &n_arc = graph.arcs[arc_idx]; - if (n_arc.type == MMU_Graph::ARC_TYPE::NON_BORDER) { - double total_len = compute_edge_length(graph, first_idx, arc_idx); - arc_to_check.emplace_back(&n_arc, total_len); - } - } - std::sort(arc_to_check.begin(), arc_to_check.end(), - [](std::pair &l, std::pair &r) -> bool { return l.second > r.second; }); + auto get_next_contour_line = [&colored_polygons](const ColoredLine &line) -> const ColoredLine & { + size_t contour_line_size = colored_polygons[line.poly_idx].size(); + size_t contour_next_idx = (line.local_line_idx + 1) % contour_line_size; + return colored_polygons[line.poly_idx][contour_next_idx]; + }; - while (arc_to_check.size() > 1) { - graph.remove_edge(first_idx, arc_to_check.back().first->to_idx); - arc_to_check.pop_back(); - } - } + Voronoi::VD vd; + vd.construct_voronoi(colored_lines.begin(), colored_lines.end()); + + // First, mark each Voronoi vertex on the input polygon to prevent it from being deleted later. + for (const Voronoi::VD::cell_type &cell : vd.cells()) { + if (cell.is_degenerate() || !cell.contains_segment()) + continue; + + if (const Geometry::SegmentCellRange cell_range = Geometry::VoronoiUtils::compute_segment_cell_range(cell, colored_lines.begin(), colored_lines.end()); cell_range.is_valid()) + cell_range.edge_begin->vertex0()->color(VD_ANNOTATION::VERTEX_ON_CONTOUR); + } + + // Second, remove all Voronoi vertices that are outside the bounding box of input polygons. + // Such Voronoi vertices are definitely not inside of input polygons, so we don't care about them. + for (const Voronoi::VD::vertex_type &vertex : vd.vertices()) { + if (vertex.color() == VD_ANNOTATION::DELETED || vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR) + continue; + + if (!Geometry::VoronoiUtils::is_in_range(vertex) || !bbox.contains(Geometry::VoronoiUtils::to_point(vertex).cast())) + delete_vertex_deep(vertex); + } + + // Third, remove all Voronoi edges that are infinite. + for (const Voronoi::VD::edge_type &edge : vd.edges()) { + if (edge.color() != VD_ANNOTATION::DELETED && edge.is_infinite()) { + edge.color(VD_ANNOTATION::DELETED); + edge.twin()->color(VD_ANNOTATION::DELETED); + + if (edge.vertex0() != nullptr && can_vertex_be_deleted(*edge.vertex0())) + delete_vertex_deep(*edge.vertex0()); + + if (edge.vertex1() != nullptr && can_vertex_be_deleted(*edge.vertex1())) + delete_vertex_deep(*edge.vertex1()); } } + + // Fourth, remove all edges that point outward from the input polygon. + for (Voronoi::VD::cell_type cell : vd.cells()) { + if (cell.is_degenerate() || !cell.contains_segment()) + continue; + + if (const Geometry::SegmentCellRange cell_range = Geometry::VoronoiUtils::compute_segment_cell_range(cell, colored_lines.begin(), colored_lines.end()); cell_range.is_valid()) { + const ColoredLine ¤t_line = Geometry::VoronoiUtils::get_source_segment(cell, colored_lines.begin(), colored_lines.end()); + const ColoredLine &next_line = get_next_contour_line(current_line); + + const VD::edge_type *edge = cell_range.edge_begin; + do { + if (edge->color() == VD_ANNOTATION::DELETED) + continue; + + if (!points_inside(current_line.line, next_line.line, Geometry::VoronoiUtils::to_point(edge->vertex1()).cast())) { + edge->color(VD_ANNOTATION::DELETED); + edge->twin()->color(VD_ANNOTATION::DELETED); + delete_vertex_deep(*edge->vertex1()); + } + } while (edge = edge->prev()->twin(), edge != cell_range.edge_begin); + } + } + + // Fifth, if a Voronoi vertex has more than one Voronoi edge, remove all but one of them based on heuristics. + for (const Voronoi::VD::vertex_type &vertex : vd.vertices()) { + if (vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR) + remove_multiple_edges_in_vertex(vertex); + } + +#ifdef MM_SEGMENTATION_DEBUG_GRAPH + { + static int iRun = 0; + export_graph_to_svg(debug_out_path("mm-graph-%d-%d.svg", layer_idx, iRun++), vd, colored_polygons); + } +#endif // MM_SEGMENTATION_DEBUG_GRAPH + + // Sixth, extract the colored segments from the annotated Voronoi diagram. + std::vector segmented_expolygons_per_extruder(num_extruders + 1); + for (const Voronoi::VD::cell_type &cell : vd.cells()) { + if (cell.is_degenerate() || !cell.contains_segment()) + continue; + + if (const Geometry::SegmentCellRange cell_range = Geometry::VoronoiUtils::compute_segment_cell_range(cell, colored_lines.begin(), colored_lines.end()); cell_range.is_valid()) { + if (cell_range.edge_begin->vertex0()->color() != VD_ANNOTATION::VERTEX_ON_CONTOUR) + continue; + + const ColoredLine source_segment = Geometry::VoronoiUtils::get_source_segment(cell, colored_lines.begin(), colored_lines.end()); + + Polygon segmented_polygon; + segmented_polygon.points.emplace_back(source_segment.line.b); + + // We have ensured that each segmented_polygon have to start at edge_begin->vertex0() and end at edge_end->vertex1(). + const VD::edge_type *edge = cell_range.edge_begin; + do { + if (edge->color() == VD_ANNOTATION::DELETED) + continue; + + const VD::vertex_type &next_vertex = *edge->vertex1(); + segmented_polygon.points.emplace_back(Geometry::VoronoiUtils::to_point(next_vertex).cast()); + edge->color(VD_ANNOTATION::DELETED); + + if (next_vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR || next_vertex.color() == VD_ANNOTATION::DELETED) { + assert(next_vertex.color() == VD_ANNOTATION::VERTEX_ON_CONTOUR); + break; + } + + edge = edge->twin(); + } while (edge = edge->twin()->next(), edge != cell_range.edge_begin); + + if (edge->vertex1() != cell_range.edge_end->vertex1()) + continue; + + cell_range.edge_begin->vertex0()->color(VD_ANNOTATION::DELETED); + segmented_expolygons_per_extruder[source_segment.color].emplace_back(std::move(segmented_polygon)); + } + } + + // Merge all polygons together for each extruder + for (auto &segmented_expolygons : segmented_expolygons_per_extruder) + segmented_expolygons = union_ex(segmented_expolygons); + + return segmented_expolygons_per_extruder; } static void cut_segmented_layers(const std::vector &input_expolygons, @@ -1375,12 +835,12 @@ static void cut_segmented_layers(const std::vector &input_exp const float interlocking_depth, const std::function &throw_on_cancel_callback) { - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin"; - tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()), - [&segmented_regions, &input_expolygons, &cut_width, &interlocking_depth, &throw_on_cancel_callback](const tbb::blocked_range &range) { + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - cutting segmented layers in parallel - begin"; + const float interlocking_cut_width = interlocking_depth > 0.f ? std::max(cut_width - interlocking_depth, 0.f) : 0.f; + tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &interlocking_cut_width, &throw_on_cancel_callback](const tbb::blocked_range& range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); - const float region_cut_width = ((layer_idx % 2 == 0) && (interlocking_depth != 0.f)) ? interlocking_depth : cut_width; + const float region_cut_width = (layer_idx % 2 == 0 && interlocking_cut_width > 0.f) ? interlocking_cut_width : cut_width; const size_t num_extruders_plus_one = segmented_regions[layer_idx].size(); if (region_cut_width > 0.f) { std::vector segmented_regions_cuts(num_extruders_plus_one); // Indexed by extruder_id @@ -1391,7 +851,7 @@ static void cut_segmented_layers(const std::vector &input_exp } } }); // end of parallel_for - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - cutting segmented layers in parallel - end"; } static bool is_volume_sinking(const indexed_triangle_set &its, const Transform3d &trafo) @@ -1431,9 +891,9 @@ static inline std::vector> mmu_segmentation_top_and_bott std::vector zs = zs_from_layers(layers); Transform3d object_trafo = print_object.trafo_centered(); -#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM +#ifdef MM_SEGMENTATION_DEBUG_TOP_BOTTOM static int iRun = 0; -#endif // NDEBUG +#endif // MM_SEGMENTATION_DEBUG_TOP_BOTTOM if (max_top_layers > 0 || max_bottom_layers > 0) { for (const ModelVolume *mv : print_object.model_object()->volumes) @@ -1441,12 +901,12 @@ static inline std::vector> mmu_segmentation_top_and_bott const Transform3d volume_trafo = object_trafo * mv->get_matrix(); for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++ extruder_idx) { const indexed_triangle_set painted = mv->mmu_segmentation_facets.get_facets_strict(*mv, EnforcerBlockerType(extruder_idx)); -#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM +#ifdef MM_SEGMENTATION_DEBUG_TOP_BOTTOM { static int iRun = 0; its_write_obj(painted, debug_out_path("mm-painted-patch-%d-%d.obj", iRun ++, extruder_idx).c_str()); } -#endif // MMU_SEGMENTATION_DEBUG_TOP_BOTTOM +#endif // MM_SEGMENTATION_DEBUG_TOP_BOTTOM if (! painted.indices.empty()) { std::vector top, bottom; if (!zs.empty() && is_volume_sinking(painted, volume_trafo)) { @@ -1501,7 +961,7 @@ static inline std::vector> mmu_segmentation_top_and_bott filter_out_small_polygons(top_raw, Slic3r::sqr(scale_(0.1f))); filter_out_small_polygons(bottom_raw, Slic3r::sqr(scale_(0.1f))); -#ifdef MMU_SEGMENTATION_DEBUG_TOP_BOTTOM +#ifdef MM_SEGMENTATION_DEBUG_TOP_BOTTOM { const char* colors[] = { "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "purple", "red", "silver", "teal", "yellow" }; static int iRun = 0; @@ -1523,7 +983,21 @@ static inline std::vector> mmu_segmentation_top_and_bott } ++ iRun; } -#endif // MMU_SEGMENTATION_DEBUG_TOP_BOTTOM +#endif // MM_SEGMENTATION_DEBUG_TOP_BOTTOM + + // When the upper surface of an object is occluded, it should no longer be considered the upper surface + { + for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++extruder_idx) { + for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { + if (!top_raw[extruder_idx].empty() && !top_raw[extruder_idx][layer_idx].empty() && layer_idx + 1 < layers.size()) { + top_raw[extruder_idx][layer_idx] = diff(top_raw[extruder_idx][layer_idx], input_expolygons[layer_idx + 1]); + } + if (!bottom_raw[extruder_idx].empty() && !bottom_raw[extruder_idx][layer_idx].empty() && layer_idx > 0) { + bottom_raw[extruder_idx][layer_idx] = diff(bottom_raw[extruder_idx][layer_idx], input_expolygons[layer_idx - 1]); + } + } + } + } std::vector> triangles_by_color_bottom(num_extruders); std::vector> triangles_by_color_top(num_extruders); @@ -1692,7 +1166,7 @@ static std::vector> merge_segmented_layers( segmented_regions_merged.assign(num_layers, std::vector(num_extruders)); assert(num_extruders + 1 == top_and_bottom_layers.size()); - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - merging segmented layers in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, num_layers), [&segmented_regions, &top_and_bottom_layers, &segmented_regions_merged, &num_extruders, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { assert(segmented_regions[layer_idx].size() == num_extruders + 1); @@ -1719,12 +1193,12 @@ static std::vector> merge_segmented_layers( } } }); // end of parallel_for - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - merging segmented layers in parallel - end"; return segmented_regions_merged; } -#ifdef MMU_SEGMENTATION_DEBUG_REGIONS +#ifdef MM_SEGMENTATION_DEBUG_REGIONS static void export_regions_to_svg(const std::string &path, const std::vector ®ions, const ExPolygons &lslices) { const std::vector colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "yellow"}; @@ -1736,35 +1210,15 @@ static void export_regions_to_svg(const std::string &path, const std::vector= 0 && extrude_idx < int(colors.size())) - svg.draw(by_extruder, colors[extrude_idx], stroke_width); + if (extrude_idx < int(colors.size())) + svg.draw(by_extruder, colors[extrude_idx]); else - svg.draw(by_extruder, "black", stroke_width); + svg.draw(by_extruder, "black"); } } -#endif // MMU_SEGMENTATION_DEBUG_REGIONS +#endif // MM_SEGMENTATION_DEBUG_REGIONS -#ifdef MMU_SEGMENTATION_DEBUG_GRAPH -static void export_graph_to_svg(const std::string &path, const MMU_Graph &graph, const ExPolygons &lslices) -{ - const std::vector colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "green", "yellow"}; - coordf_t stroke_width = scale_(0.05); - BoundingBox bbox = get_extents(lslices); - bbox.offset(scale_(1.)); - ::Slic3r::SVG svg(path.c_str(), bbox); - for (const MMU_Graph::Node &node : graph.nodes) - for (const size_t &arc_idx : node.arc_idxs) { - const MMU_Graph::Arc &arc = graph.arcs[arc_idx]; - Line arc_line(mk_point(node.point), mk_point(graph.nodes[arc.to_idx].point)); - if (arc.type == MMU_Graph::ARC_TYPE::BORDER && arc.color >= 0 && arc.color < int(colors.size())) - svg.draw(arc_line, colors[arc.color], stroke_width); - else - svg.draw(arc_line, "black", stroke_width); - } -} -#endif // MMU_SEGMENTATION_DEBUG_GRAPH - -#ifdef MMU_SEGMENTATION_DEBUG_INPUT +#ifdef MM_SEGMENTATION_DEBUG_INPUT void export_processed_input_expolygons_to_svg(const std::string &path, const LayerRegionPtrs ®ions, const ExPolygons &processed_input_expolygons) { coordf_t stroke_width = scale_(0.05); @@ -1774,13 +1228,14 @@ void export_processed_input_expolygons_to_svg(const std::string &path, const Lay ::Slic3r::SVG svg(path.c_str(), bbox); for (LayerRegion *region : regions) - svg.draw_outline(region->slices.surfaces, "blue", "cyan", stroke_width); + for (const Surface &surface : region->slices.surfaces) + svg.draw_outline(surface, "blue", "cyan", stroke_width); svg.draw_outline(processed_input_expolygons, "red", "pink", stroke_width); } -#endif // MMU_SEGMENTATION_DEBUG_INPUT +#endif // MM_SEGMENTATION_DEBUG_INPUT -#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES +#ifdef MM_SEGMENTATION_DEBUG_PAINTED_LINES static void export_painted_lines_to_svg(const std::string &path, const std::vector> &all_painted_lines, const ExPolygons &lslices) { const std::vector colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "yellow"}; @@ -1796,10 +1251,10 @@ static void export_painted_lines_to_svg(const std::string &path, const std::vect for (const PaintedLine &painted_line : painted_lines) svg.draw(painted_line.projected_line, painted_line.color < int(colors.size()) ? colors[painted_line.color] : "black", stroke_width); } -#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES +#endif // MM_SEGMENTATION_DEBUG_PAINTED_LINES -#ifdef MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS -static void export_colorized_polygons_to_svg(const std::string &path, const std::vector> &colorized_polygons, const ExPolygons &lslices) +#ifdef MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS +static void export_colorized_polygons_to_svg(const std::string &path, const std::vector &colorized_polygons, const ExPolygons &lslices) { const std::vector colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "green", "yellow"}; coordf_t stroke_width = scale_(0.05); @@ -1807,19 +1262,19 @@ static void export_colorized_polygons_to_svg(const std::string &path, const std: bbox.offset(scale_(1.)); ::Slic3r::SVG svg(path.c_str(), bbox); - for (const std::vector &colorized_polygon : colorized_polygons) + for (const ColoredLines &colorized_polygon : colorized_polygons) for (const ColoredLine &colorized_line : colorized_polygon) svg.draw(colorized_line.line, colorized_line.color < int(colors.size())? colors[colorized_line.color] : "black", stroke_width); } -#endif // MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS +#endif // MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS // Check if all ColoredLine representing a single layer uses the same color. -static bool has_layer_only_one_color(const std::vector> &colored_polygons) +static bool has_layer_only_one_color(const std::vector &colored_polygons) { assert(!colored_polygons.empty()); assert(!colored_polygons.front().empty()); int first_line_color = colored_polygons.front().front().color; - for (const std::vector &colored_polygon : colored_polygons) + for (const ColoredLines &colored_polygon : colored_polygons) for (const ColoredLine &colored_line : colored_polygon) if (first_line_color != colored_line.color) return false; @@ -1841,8 +1296,12 @@ std::vector> multi_material_segmentation_by_painting(con throw_on_cancel_callback(); +#ifdef MM_SEGMENTATION_DEBUG + static int iRun = 0; +#endif // MM_SEGMENTATION_DEBUG + // Merge all regions and remove small holes - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - slices preparation in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, num_layers), [&layers, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); @@ -1862,17 +1321,14 @@ std::vector> multi_material_segmentation_by_painting(con // Such close points sometimes caused that the Voronoi diagram has self-intersecting edges around these vertices. // This consequently leads to issues with the extraction of colored segments by function extract_colored_segments. // Calling expolygons_simplify fixed these issues. - input_expolygons[layer_idx] = remove_duplicates(expolygons_simplify(offset_ex(ex_polygons, -10.f * float(SCALED_EPSILON)), 5 * SCALED_EPSILON), scaled(0.01), PI / 6); + input_expolygons[layer_idx] = remove_duplicates(expolygons_simplify(offset_ex(ex_polygons, -10.f * float(SCALED_EPSILON)), 5 * SCALED_EPSILON), scaled(0.01), PI/6); -#ifdef MMU_SEGMENTATION_DEBUG_INPUT - { - static int iRun = 0; - export_processed_input_expolygons_to_svg(debug_out_path("mm-input-%d-%d.svg", layer_idx, iRun++), layers[layer_idx]->regions(), input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_INPUT +#ifdef MM_SEGMENTATION_DEBUG_INPUT + export_processed_input_expolygons_to_svg(debug_out_path("mm-input-%d-%d.svg", layer_idx, iRun), layers[layer_idx]->regions(), input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_INPUT } }); // end of parallel_for - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - slices preparation in parallel - end"; std::vector layer_bboxes(num_layers); for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) { @@ -1895,7 +1351,7 @@ std::vector> multi_material_segmentation_by_painting(con edge_grids[layer_idx].create(input_expolygons[layer_idx], coord_t(scale_(10.))); } - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - projection of painted triangles - begin"; for (const ModelVolume *mv : print_object.model_object()->volumes) { tbb::parallel_for(tbb::blocked_range(1, num_extruders + 1), [&mv, &print_object, &layers, &edge_grids, &painted_lines, &painted_lines_mutex, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) { @@ -1917,6 +1373,9 @@ std::vector> multi_material_segmentation_by_painting(con min_z = std::min(min_z, facet[p_idx].z()); } + if (is_equal(min_z, max_z)) + continue; + // Sort the vertices by z-axis for simplification of projected_facet on slices std::sort(facet.begin(), facet.end(), [](const Vec3f &p1, const Vec3f &p2) { return p1.z() < p2.z(); }); @@ -1961,7 +1420,9 @@ std::vector> multi_material_segmentation_by_painting(con // be outside EdgeGrid's BoundingBox, for example, when the negative volume is used on the painted area (GH #7618). // To ensure that the painted line is always inside EdgeGrid's BoundingBox, it is clipped by EdgeGrid's BoundingBox in cases // when any of the endpoints of the line are outside the EdgeGrid's BoundingBox. - if (const BoundingBox &edge_grid_bbox = edge_grids[layer_idx].bbox(); !edge_grid_bbox.contains(line_to_test.a) || !edge_grid_bbox.contains(line_to_test.b)) { + BoundingBox edge_grid_bbox = edge_grids[layer_idx].bbox(); + edge_grid_bbox.offset(10 * scale_(EPSILON)); + if (!edge_grid_bbox.contains(line_to_test.a) || !edge_grid_bbox.contains(line_to_test.b)) { // If the painted line (line_to_test) is entirely outside EdgeGrid's BoundingBox, skip this painted line. if (!edge_grid_bbox.overlap(BoundingBox(Points{line_to_test.a, line_to_test.b})) || !line_to_test.clip_with_bbox(edge_grid_bbox)) @@ -1981,39 +1442,30 @@ std::vector> multi_material_segmentation_by_painting(con } }); // end of parallel_for } - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - end"; - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - painted layers count: " + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - projection of painted triangles - end"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - painted layers count: " << std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector &pl) { return !pl.empty(); }); - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - layers segmentation in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, num_layers), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &num_extruders, &throw_on_cancel_callback](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); if (!painted_lines[layer_idx].empty()) { -#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES - { - static int iRun = 0; - export_painted_lines_to_svg(debug_out_path("mm-painted-lines-%d-%d.svg", layer_idx, iRun++), {painted_lines[layer_idx]}, input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES +#ifdef MM_SEGMENTATION_DEBUG_PAINTED_LINES + export_painted_lines_to_svg(debug_out_path("0-mm-painted-lines-%d-%d.svg", layer_idx, iRun), {painted_lines[layer_idx]}, input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_PAINTED_LINES std::vector> post_processed_painted_lines = post_process_painted_lines(edge_grids[layer_idx].contours(), std::move(painted_lines[layer_idx])); -#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES - { - static int iRun = 0; - export_painted_lines_to_svg(debug_out_path("mm-painted-lines-post-processed-%d-%d.svg", layer_idx, iRun++), post_processed_painted_lines, input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES +#ifdef MM_SEGMENTATION_DEBUG_PAINTED_LINES + export_painted_lines_to_svg(debug_out_path("1-mm-painted-lines-post-processed-%d-%d.svg", layer_idx, iRun), post_processed_painted_lines, input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_PAINTED_LINES - std::vector> color_poly = colorize_contours(edge_grids[layer_idx].contours(), post_processed_painted_lines); + std::vector color_poly = colorize_contours(edge_grids[layer_idx].contours(), post_processed_painted_lines); -#ifdef MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS - { - static int iRun = 0; - export_colorized_polygons_to_svg(debug_out_path("mm-colorized_polygons-%d-%d.svg", layer_idx, iRun++), color_poly, input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS +#ifdef MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS + export_colorized_polygons_to_svg(debug_out_path("2-mm-colorized_polygons-%d-%d.svg", layer_idx, iRun), color_poly, input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_COLORIZED_POLYGONS assert(!color_poly.empty()); assert(!color_poly.front().empty()); @@ -2021,33 +1473,19 @@ std::vector> multi_material_segmentation_by_painting(con // If the whole layer is painted using the same color, it is not needed to construct a Voronoi diagram for the segmentation of this layer. segmented_regions[layer_idx][size_t(color_poly.front().front().color)] = input_expolygons[layer_idx]; } else { - MMU_Graph graph = build_graph(layer_idx, color_poly); - remove_multiple_edges_in_vertices(graph, color_poly); - graph.remove_nodes_with_one_arc(); - -#ifdef MMU_SEGMENTATION_DEBUG_GRAPH - { - static int iRun = 0; - export_graph_to_svg(debug_out_path("mm-graph-final-%d-%d.svg", layer_idx, iRun++), graph, input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_GRAPH - - segmented_regions[layer_idx] = extract_colored_segments(graph, num_extruders); + segmented_regions[layer_idx] = extract_colored_segments(color_poly, num_extruders, layer_idx); } -#ifdef MMU_SEGMENTATION_DEBUG_REGIONS - { - static int iRun = 0; - export_regions_to_svg(debug_out_path("mm-regions-sides-%d-%d.svg", layer_idx, iRun++), segmented_regions[layer_idx], input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_REGIONS +#ifdef MM_SEGMENTATION_DEBUG_REGIONS + export_regions_to_svg(debug_out_path("3-mm-regions-sides-%d-%d.svg", layer_idx, iRun), segmented_regions[layer_idx], input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_REGIONS } } }); // end of parallel_for - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - end"; + BOOST_LOG_TRIVIAL(debug) << "MM segmentation - layers segmentation in parallel - end"; throw_on_cancel_callback(); - if (auto max_width = print_object.config().mmu_segmented_region_max_width, interlocking_depth = print_object.config().mmu_segmented_region_interlocking_depth; max_width > 0.f || interlocking_depth > 0.f) { + if (auto max_width = print_object.config().mmu_segmented_region_max_width, interlocking_depth = print_object.config().mmu_segmented_region_interlocking_depth; max_width > 0.f) { cut_segmented_layers(input_expolygons, segmented_regions, float(scale_(max_width)), float(scale_(interlocking_depth)), throw_on_cancel_callback); throw_on_cancel_callback(); } @@ -2059,13 +1497,14 @@ std::vector> multi_material_segmentation_by_painting(con std::vector> segmented_regions_merged = merge_segmented_layers(segmented_regions, std::move(top_and_bottom_layers), num_extruders, throw_on_cancel_callback); throw_on_cancel_callback(); -#ifdef MMU_SEGMENTATION_DEBUG_REGIONS - { - static int iRun = 0; - for (size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) - export_regions_to_svg(debug_out_path("mm-regions-merged-%d-%d.svg", layer_idx, iRun++), segmented_regions_merged[layer_idx], input_expolygons[layer_idx]); - } -#endif // MMU_SEGMENTATION_DEBUG_REGIONS +#ifdef MM_SEGMENTATION_DEBUG_REGIONS + for (size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) + export_regions_to_svg(debug_out_path("4-mm-regions-merged-%d-%d.svg", layer_idx, iRun), segmented_regions_merged[layer_idx], input_expolygons[layer_idx]); +#endif // MM_SEGMENTATION_DEBUG_REGIONS + +#ifdef MM_SEGMENTATION_DEBUG + ++iRun; +#endif // MM_SEGMENTATION_DEBUG return segmented_regions_merged; } diff --git a/src/libslic3r/MultiMaterialSegmentation.hpp b/src/libslic3r/MultiMaterialSegmentation.hpp index 4efdc69514..91d0f298bc 100644 --- a/src/libslic3r/MultiMaterialSegmentation.hpp +++ b/src/libslic3r/MultiMaterialSegmentation.hpp @@ -6,13 +6,41 @@ namespace Slic3r { - class PrintObject; class ExPolygon; +using ExPolygons = std::vector; + +struct ColoredLine +{ + Line line; + int color; + int poly_idx = -1; + int local_line_idx = -1; +}; + +using ColoredLines = std::vector; // Returns MMU segmentation based on painting in MMU segmentation gizmo std::vector> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function &throw_on_cancel_callback); } // namespace Slic3r +namespace boost::polygon { +template<> struct geometry_concept +{ + typedef segment_concept type; +}; + +template<> struct segment_traits +{ + typedef coord_t coordinate_type; + typedef Slic3r::Point point_type; + + static inline point_type get(const Slic3r::ColoredLine &line, const direction_1d &dir) + { + return dir.to_int() ? line.line.b : line.line.a; + } +}; +} // namespace boost::polygon + #endif // slic3r_MultiMaterialSegmentation_hpp_ diff --git a/src/libslic3r/ParameterUtils.cpp b/src/libslic3r/ParameterUtils.cpp new file mode 100644 index 0000000000..4e5fed7e6b --- /dev/null +++ b/src/libslic3r/ParameterUtils.cpp @@ -0,0 +1,45 @@ +#include "ParameterUtils.hpp" + +namespace Slic3r { + +std::vector get_other_layers_print_sequence(int sequence_nums, const std::vector &sequence) +{ + std::vector res; + if (sequence_nums == 0 || sequence.empty()) + return res; + + assert(sequence.size() % sequence_nums == 0); + + res.reserve(sequence_nums); + size_t item_nums = sequence.size() / sequence_nums; + + for (int i = 0; i < sequence_nums; ++i) { + std::vector item; + item.assign(sequence.begin() + i * item_nums, sequence.begin() + ((i + 1) * item_nums)); + + assert(item.size() > 2); + std::pair, std::vector> res_item; + res_item.first.first = item[0]; + res_item.first.second = item[1]; + res_item.second.assign(item.begin() + 2, item.end()); + res.emplace_back(std::move(res_item)); + } + + return res; +} + +void get_other_layers_print_sequence(const std::vector &customize_sequences, int &sequence_nums, std::vector &sequence) +{ + sequence_nums = 0; + sequence.clear(); + if (customize_sequences.empty()) { return; } + + sequence_nums = (int) customize_sequences.size(); + for (const auto &customize_sequence : customize_sequences) { + sequence.push_back(customize_sequence.first.first); + sequence.push_back(customize_sequence.first.second); + sequence.insert(sequence.end(), customize_sequence.second.begin(), customize_sequence.second.end()); + } +} + +}; // namespace Slic3r diff --git a/src/libslic3r/ParameterUtils.hpp b/src/libslic3r/ParameterUtils.hpp new file mode 100644 index 0000000000..090fd8d803 --- /dev/null +++ b/src/libslic3r/ParameterUtils.hpp @@ -0,0 +1,14 @@ +#ifndef slic3r_Parameter_Utils_hpp_ +#define slic3r_Parameter_Utils_hpp_ + +#include +#include + +namespace Slic3r { +using LayerPrintSequence = std::pair, std::vector>; +std::vector get_other_layers_print_sequence(int sequence_nums, const std::vector &sequence); +void get_other_layers_print_sequence(const std::vector &customize_sequences, int &sequence_nums, std::vector &sequence); + +} // namespace Slic3r + +#endif // slic3r_Parameter_Utils_hpp_ diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index c708e5620d..86f9f5ceac 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -20,13 +20,15 @@ #include "Geometry/ConvexHull.hpp" #include "ExPolygonCollection.hpp" #include "Geometry.hpp" - +#include "Line.hpp" #include #include #include - +#include "libslic3r/AABBTreeLines.hpp" static const int overhang_sampling_number = 6; static const double narrow_loop_length_threshold = 10; +static const double min_degree_gap = 0.1; +static const int max_overhang_degree = overhang_sampling_number - 1; //BBS: when the width of expolygon is smaller than //ext_perimeter_width + ext_perimeter_spacing * (1 - SMALLER_EXT_INSET_OVERLAP_TOLERANCE), //we think it's small detail area and will generate smaller line width for it @@ -222,6 +224,188 @@ static void lowpass_filter_by_paths_overhang_degree(ExtrusionPaths& paths) { } } +struct PolylineWithDegree +{ + PolylineWithDegree(Polyline polyline, double overhang_degree) : polyline(polyline), overhang_degree(overhang_degree){}; + Polyline polyline; + double overhang_degree = 0; +}; + +static std::deque split_polyline_by_degree(const Polyline &polyline_with_insert_points, const std::deque &points_overhang) +{ + std::deque out; + Polyline left; + Polyline right; + Polyline temp_copy = polyline_with_insert_points; + + size_t poly_size = polyline_with_insert_points.size(); + // BBS: merge degree in limited range + //find first degee base + double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap) * min_degree_gap + min_degree_gap; + degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base; + double short_poly_len = 0; + for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) { + + double degree = points_overhang[point_idx]; + + if ( degree <= degree_base && degree >= degree_base - min_degree_gap ) + continue; + + temp_copy.split_at_index(point_idx, &left, &right); + + temp_copy = std::move(left); + out.push_back(PolylineWithDegree(right, degree_base)); + + degree_base = int(degree / min_degree_gap) * min_degree_gap + min_degree_gap; + degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base; + } + + if (!temp_copy.empty()) { + out.push_back(PolylineWithDegree(temp_copy, degree_base)); + } + + return out; + +} +static void insert_point_to_line( double left_point_degree, + Point left_point, + double right_point_degree, + Point right_point, + std::deque &points_overhang, + Polyline& polyline, + double mini_length) +{ + Line line_temp(left_point, right_point); + double line_length = line_temp.length(); + if (std::abs(left_point_degree - right_point_degree) <= 0.5 * min_degree_gap || line_length left_points_overhang; + std::deque right_points_overhang; + + double middle_degree = (left_point_degree + right_point_degree) / 2; + Polyline left_polyline; + Polyline right_polyline; + + insert_point_to_line(left_point_degree, left_point, middle_degree, middle_pt, left_points_overhang, left_polyline, mini_length); + insert_point_to_line(middle_degree, middle_pt, right_point_degree, right_point, right_points_overhang, right_polyline, mini_length); + + if (!left_polyline.empty()) { + polyline.points.insert(polyline.points.end(), std::make_move_iterator(left_polyline.points.begin()), std::make_move_iterator(left_polyline.points.end())); + points_overhang.insert(points_overhang.end(), std::make_move_iterator(left_points_overhang.begin()), std::make_move_iterator(left_points_overhang.end())); + } + + polyline.append(middle_pt); + points_overhang.emplace_back(middle_degree); + + if (!right_polyline.empty()) { + polyline.points.insert(polyline.points.end(), std::make_move_iterator(right_polyline.points.begin()), std::make_move_iterator(right_polyline.points.end())); + points_overhang.insert(points_overhang.end(), std::make_move_iterator(right_points_overhang.begin()), std::make_move_iterator(right_points_overhang.end())); + } +} + +class OverhangDistancer +{ + std::vector lines; + AABBTreeIndirect::Tree<2, double> tree; + +public: + OverhangDistancer(const Polygons layer_polygons) + { + for (const Polygon &island : layer_polygons) { + for (const auto &line : island.lines()) { + lines.emplace_back(line.a.cast(), line.b.cast()); + } + } + tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines); + } + + float distance_from_perimeter(const Vec2f &point) const + { + Vec2d p = point.cast(); + size_t hit_idx_out{}; + Vec2d hit_point_out = Vec2d::Zero(); + auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out); + if (distance < 0) { return std::numeric_limits::max(); } + + distance = sqrt(distance); + return distance; + } +}; + +static std::deque detect_overahng_degree(Polygons lower_polygons, + Polylines middle_overhang_polyines, + const double &lower_bound, + const double &upper_bound, + Polylines &too_short_polylines) +{ + // BBS: collect lower_polygons points + //Polylines; + Points lower_polygon_points; + std::vector polygons_bound; + + std::unique_ptr prev_layer_distancer; + prev_layer_distancer = std::make_unique(lower_polygons); + std::deque out; + std::deque points_overhang; + //BBS: get overhang degree and split path + for (size_t polyline_idx = 0; polyline_idx < middle_overhang_polyines.size(); ++polyline_idx) { + //filter too short polyline + Polyline middle_poly = middle_overhang_polyines[polyline_idx]; + if (middle_poly.length() < scale_(1.0)) { + too_short_polylines.push_back(middle_poly); + continue; + } + + Polyline polyline_with_insert_points; + points_overhang.clear(); + double last_degree = 0; + // BBS : calculate overhang dist + for (size_t point_idx = 0; point_idx < middle_poly.points.size(); ++point_idx) { + Point pt = middle_poly.points[point_idx]; + + float overhang_dist = prev_layer_distancer->distance_from_perimeter(pt.cast()); + overhang_dist = overhang_dist > upper_bound ? upper_bound : overhang_dist; + // BBS : calculate overhang degree + int max_overhang = max_overhang_degree; + int min_overhang = 0; + double t = (overhang_dist - lower_bound) / (upper_bound - lower_bound); + t = t > 1.0 ? 1: t; + t = t < EPSILON ? 0 : t; + double this_degree = (1.0 - t) * min_overhang + t * max_overhang; + // BBS: intert points + if (point_idx > 0) { + insert_point_to_line(last_degree, middle_poly.points[point_idx - 1], this_degree, pt, points_overhang, polyline_with_insert_points, + upper_bound - lower_bound); + } + points_overhang.push_back(this_degree); + + polyline_with_insert_points.append(pt); + last_degree = this_degree; + + } + + // BBS : split path by degree + std::deque polyline_with_merged_degree = split_polyline_by_degree(polyline_with_insert_points, points_overhang); + out.insert(out.end(), std::make_move_iterator(polyline_with_merged_degree.begin()), std::make_move_iterator(polyline_with_merged_degree.end())); + } + + return out; +} + +std::pair PerimeterGenerator::dist_boundary(double width) +{ + std::pair out; + float nozzle_diameter = print_config->nozzle_diameter.get_at(config->wall_filament - 1); + float start_offset = -0.5 * width; + float end_offset = 0.5 * nozzle_diameter; + double degree_0 = scale_(start_offset + 0.5 * (end_offset - start_offset) / (overhang_sampling_number - 1)); + out.first = 0; + out.second = scale_(end_offset) - degree_0; + return out; +} + template static bool detect_steep_overhang(const PrintRegionConfig *config, bool is_contour, @@ -297,24 +481,28 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime ExtrusionPaths paths; // BBS: get lower polygons series, width, mm3_per_mm - const std::map *lower_polygons_series; + const std::vector *lower_polygons_series; + const std::pair *overhang_dist_boundary; double extrusion_mm3_per_mm; double extrusion_width; if (is_external) { if (is_small_width) { //BBS: smaller width external perimeter lower_polygons_series = &perimeter_generator.m_smaller_external_lower_polygons_series; + overhang_dist_boundary = &perimeter_generator.m_smaller_external_overhang_dist_boundary; extrusion_mm3_per_mm = perimeter_generator.smaller_width_ext_mm3_per_mm(); extrusion_width = perimeter_generator.smaller_ext_perimeter_flow.width(); } else { //BBS: normal external perimeter lower_polygons_series = &perimeter_generator.m_external_lower_polygons_series; + overhang_dist_boundary = &perimeter_generator.m_external_overhang_dist_boundary; extrusion_mm3_per_mm = perimeter_generator.ext_mm3_per_mm(); extrusion_width = perimeter_generator.ext_perimeter_flow.width(); } } else { //BBS: normal perimeter lower_polygons_series = &perimeter_generator.m_lower_polygons_series; + overhang_dist_boundary = &perimeter_generator.m_lower_overhang_dist_boundary; extrusion_mm3_per_mm = perimeter_generator.mm3_per_mm(); extrusion_width = perimeter_generator.perimeter_flow.width(); } @@ -349,50 +537,72 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime Polylines remain_polines; - //BBS: don't calculate overhang degree when enable fuzzy skin. It's unmeaning - if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) { - for (auto it = lower_polygons_series->begin(); - it != lower_polygons_series->end(); it++) - { - Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(it->second, bbox); + Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_polygons_series->back(), bbox); - Polylines inside_polines = (it == lower_polygons_series->begin()) ? intersection_pl({polygon}, lower_polygons_series_clipped) : - intersection_pl(remain_polines, lower_polygons_series_clipped); + Polylines inside_polines = intersection_pl({polygon}, lower_polygons_series_clipped); + + + remain_polines = diff_pl({polygon}, lower_polygons_series_clipped); + + bool detect_overhang_degree = perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None; + + if (!detect_overhang_degree) { + if (!inside_polines.empty()) extrusion_paths_append( paths, std::move(inside_polines), - it->first, + 0, int(0), role, extrusion_mm3_per_mm, extrusion_width, (float)perimeter_generator.layer_height); - - remain_polines = (it == lower_polygons_series->begin()) ? diff_pl({polygon}, lower_polygons_series_clipped) : - diff_pl(remain_polines, lower_polygons_series_clipped); - - if (remain_polines.size() == 0) - break; - } } else { - auto it = lower_polygons_series->end(); - it--; - Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(it->second, bbox); + Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_polygons_series->front(), bbox); - Polylines inside_polines = intersection_pl({polygon}, lower_polygons_series_clipped); - extrusion_paths_append( - paths, - std::move(inside_polines), - int(0), - int(0), - role, - extrusion_mm3_per_mm, - extrusion_width, - (float)perimeter_generator.layer_height); + Polylines middle_overhang_polyines = diff_pl({inside_polines}, lower_polygons_series_clipped); + //BBS: add zero_degree_path + Polylines zero_degree_polines = intersection_pl({inside_polines}, lower_polygons_series_clipped); + if (!zero_degree_polines.empty()) + extrusion_paths_append( + paths, + std::move(zero_degree_polines), + 0, + int(0), + role, + extrusion_mm3_per_mm, + extrusion_width, + (float)perimeter_generator.layer_height); + //BBS: detect middle line overhang + if (!middle_overhang_polyines.empty()) { + Polylines too_short_polylines; + std::deque polylines_degree_collection = detect_overahng_degree(lower_polygons_series->front(), + middle_overhang_polyines, + overhang_dist_boundary->first, + overhang_dist_boundary->second, + too_short_polylines); + if (!too_short_polylines.empty()) + extrusion_paths_append(paths, + std::move(too_short_polylines), + 0, + int(0), + role, + extrusion_mm3_per_mm, + extrusion_width, + (float) perimeter_generator.layer_height); + // BBS: add path with overhang degree + for (PolylineWithDegree polylines_collection : polylines_degree_collection) { + extrusion_paths_append(paths, + std::move(polylines_collection.polyline), + polylines_collection.overhang_degree, + int(0), + role, + extrusion_mm3_per_mm, + extrusion_width, (float) perimeter_generator.layer_height); + } + } - remain_polines = diff_pl({polygon}, lower_polygons_series_clipped); } - // get 100% overhang paths by checking what parts of this loop fall // outside the grown lower slices (thus where the distance between // the loop centerline and original lower slices is >= half nozzle diameter @@ -407,9 +617,6 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. if(paths.empty()) continue; chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); - // smothing the overhang degree - // merge small path between paths which have same overhang degree - lowpass_filter_by_paths_overhang_degree(paths); } else { ExtrusionPath path(role); //BBS. @@ -1489,12 +1696,16 @@ void PerimeterGenerator::process_classic() // prepare grown lower layer slices for overhang detection m_lower_polygons_series = generate_lower_polygons_series(this->perimeter_flow.width()); - if (ext_perimeter_width == perimeter_width) + m_lower_overhang_dist_boundary = dist_boundary(this->perimeter_flow.width()); + if (ext_perimeter_width == perimeter_width){ m_external_lower_polygons_series = m_lower_polygons_series; - else + m_external_overhang_dist_boundary=m_lower_overhang_dist_boundary; + } else { m_external_lower_polygons_series = generate_lower_polygons_series(this->ext_perimeter_flow.width()); + m_external_overhang_dist_boundary = dist_boundary(this->ext_perimeter_flow.width()); + } m_smaller_external_lower_polygons_series = generate_lower_polygons_series(this->smaller_ext_perimeter_flow.width()); - + m_smaller_external_overhang_dist_boundary = dist_boundary(this->smaller_ext_perimeter_flow.width()); // we need to process each island separately because we might have different // extra perimeters for each one Surfaces all_surfaces = this->slices->surfaces; @@ -2702,7 +2913,7 @@ bool PerimeterGeneratorLoop::is_internal_contour() const return true; } -std::map PerimeterGenerator::generate_lower_polygons_series(float width) +std::vector PerimeterGenerator::generate_lower_polygons_series(float width) { float nozzle_diameter = print_config->nozzle_diameter.get_at(config->wall_filament - 1); float start_offset = -0.5 * width; @@ -2711,23 +2922,18 @@ std::map PerimeterGenerator::generate_lower_polygons_series(float assert(overhang_sampling_number >= 3); // generate offsets std::vector offset_series; - offset_series.reserve(overhang_sampling_number - 1); - for (int i = 0; i < overhang_sampling_number - 1; i++) { - offset_series.push_back(start_offset + (i + 0.5) * (end_offset - start_offset) / (overhang_sampling_number - 1)); - } - // BBS: increase start_offset a little to avoid to calculate 90 degree as overhang - offset_series[0] = start_offset + 0.5 * (end_offset - start_offset) / (overhang_sampling_number - 1); - offset_series[overhang_sampling_number - 2] = end_offset; - offset_series.back() = 0.1 * nozzle_diameter; + offset_series.reserve(2); - std::map lower_polygons_series; + offset_series.push_back(start_offset + 0.5 * (end_offset - start_offset) / (overhang_sampling_number - 1)); + offset_series.push_back(end_offset); + std::vector lower_polygons_series; if (this->lower_slices == NULL) { return lower_polygons_series; } // offset expolygon to generate series of polygons for (int i = 0; i < offset_series.size(); i++) { - lower_polygons_series.insert(std::pair(i, offset(*this->lower_slices, float(scale_(offset_series[i]))))); + lower_polygons_series.emplace_back(offset(*this->lower_slices, float(scale_(offset_series[i])))); } return lower_polygons_series; } diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index e9da632386..c50f3b7faa 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -34,9 +34,13 @@ public: //BBS Flow smaller_ext_perimeter_flow; - std::map m_lower_polygons_series; - std::map m_external_lower_polygons_series; - std::map m_smaller_external_lower_polygons_series; + std::vector m_lower_polygons_series; + std::vector m_external_lower_polygons_series; + std::vector m_smaller_external_lower_polygons_series; + std::pair m_lower_overhang_dist_boundary; + std::pair m_external_overhang_dist_boundary; + std::pair m_smaller_external_overhang_dist_boundary; + PerimeterGenerator( // Input: @@ -79,10 +83,11 @@ public: Polygons lower_slices_polygons() const { return m_lower_slices_polygons; } private: - std::map generate_lower_polygons_series(float width); + std::vector generate_lower_polygons_series(float width); void split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills, ExPolygons &non_top_polygons, ExPolygons &fill_clip) const; void apply_extra_perimeters(ExPolygons& infill_area); void process_no_bridge(Surfaces& all_surfaces, coord_t perimeter_spacing, coord_t ext_perimeter_width); + std::pair dist_boundary(double width); private: bool m_spiral_vase; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index a9995c15d6..20cf79206d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -801,7 +801,7 @@ static std::vector s_Preset_print_options { "tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter", "tree_support_branch_diameter", "tree_support_branch_diameter_angle", "tree_support_branch_diameter_double_wall", "detect_narrow_internal_solid_infill", - "gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/ + "gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination", /*"adaptive_layer_height",*/ "support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed", "initial_layer_infill_speed", "only_one_wall_top", "timelapse_type", @@ -850,7 +850,8 @@ static std::vector s_Preset_filament_options { "filament_loading_speed", "filament_loading_speed_start", "filament_load_time", "filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", - "filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control" + "filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control", + "filament_long_retractions_when_cut","filament_retraction_distances_when_cut" }; static std::vector s_Preset_machine_limits_options { @@ -867,6 +868,7 @@ static std::vector s_Preset_printer_options { "fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs", "single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "change_extrusion_role_gcode", "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", + "nozzle_height", "default_print_profile", "inherits", "silent_mode", // BBS @@ -882,7 +884,7 @@ static std::vector s_Preset_printer_options { "cooling_tube_retraction", "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming", "z_offset", - "disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "support_multi_bed_types","bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin" + "disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "support_multi_bed_types","bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "enable_long_retraction_when_cut","long_retractions_when_cut","retraction_distances_when_cut" }; static std::vector s_Preset_sla_print_options { @@ -1184,6 +1186,8 @@ void PresetCollection::load_presets( preset.setting_id.clear(); //BBS: add config related logs BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", preset type %1%, name %2%, path %3%, is_system %4%, is_default %5% is_visible %6%")%Preset::get_type_string(m_type) %preset.name %preset.file %preset.is_system %preset.is_default %preset.is_visible; + // add alias for custom filament preset + set_custom_preset_alias(preset); } catch (const std::ifstream::failure &err) { ++m_errors; BOOST_LOG_TRIVIAL(error) << boost::format("The user-config cannot be loaded: %1%. Reason: %2%")%preset.file %err.what(); @@ -2139,6 +2143,7 @@ bool PresetCollection::clone_presets(std::vector const &presets, auto old_name = this->get_edited_preset().name; for (auto preset : new_presets) { preset.alias.clear(); + set_custom_preset_alias(preset); preset.base_id.clear(); auto it = this->find_preset_internal(preset.name); assert((it == m_presets.end() || it->name != preset.name) || force_rewritten); @@ -2200,6 +2205,10 @@ std::map> PresetCollection::get_filamen { std::map> filament_presets; for (auto &preset : m_presets) { + if (preset.is_user()) { + if (preset.inherits() == "") { filament_presets[preset.filament_id].push_back(&preset); } + continue; + } if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); } } return filament_presets; @@ -2456,10 +2465,13 @@ const std::string& PresetCollection::get_preset_name_by_alias(const std::string& auto it = Slic3r::lower_bound_by_predicate(m_map_alias_to_profile_name.begin(), m_map_alias_to_profile_name.end(), [&alias](auto &l){ return l.first < alias; }); // Continue over all profile names with the same alias. it != m_map_alias_to_profile_name.end() && it->first == alias; ++ it) - if (auto it_preset = this->find_preset_internal(it->second); - it_preset != m_presets.end() && it_preset->name == it->second && + for (const std::string &preset_name : it->second) { + if (auto it_preset = this->find_preset_internal(preset_name); + it_preset != m_presets.end() && it_preset->name == preset_name && it_preset->is_visible && (it_preset->is_compatible || size_t(it_preset - m_presets.begin()) == m_idx_selected)) return it_preset->name; + } + return alias; } @@ -2471,6 +2483,28 @@ const std::string* PresetCollection::get_preset_name_renamed(const std::string & return nullptr; } +bool PresetCollection::is_alias_exist(const std::string &alias, Preset* preset) +{ + auto it = m_map_alias_to_profile_name.find(alias); + if (m_map_alias_to_profile_name.end() == it) return false; + if (!preset) return true; + + auto compatible_printers = dynamic_cast(preset->config.option("compatible_printers")); + if (compatible_printers == nullptr) return true; + + for (const std::string &printer_name : compatible_printers->values) { + auto printer_iter = m_printer_hold_alias.find(printer_name); + if (m_printer_hold_alias.end() != printer_iter) { + auto alias_iter = m_printer_hold_alias[printer_name].find(alias); + if (m_printer_hold_alias[printer_name].end() != alias_iter) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << " The alias already exists: " << alias << " and the preset name: " << preset->name; + return true; + } + } + } + return false; +} + const std::string& PresetCollection::get_suffix_modified() { return g_suffix_modified; } @@ -2803,9 +2837,11 @@ void PresetCollection::update_vendor_ptrs_after_copy(const VendorMap &new_vendor void PresetCollection::update_map_alias_to_profile_name() { m_map_alias_to_profile_name.clear(); - for (const Preset &preset : m_presets) - m_map_alias_to_profile_name.emplace_back(preset.alias, preset.name); - std::sort(m_map_alias_to_profile_name.begin(), m_map_alias_to_profile_name.end(), [](auto &l, auto &r) { return l.first < r.first; }); + for (const Preset &preset : m_presets) { + m_map_alias_to_profile_name[preset.alias].push_back(preset.name); + } + // now m_map_alias_to_profile_name is map, not need sort + //std::sort(m_map_alias_to_profile_name.begin(), m_map_alias_to_profile_name.end(), [](auto &l, auto &r) { return l.first < r.first; }); } void PresetCollection::update_map_system_profile_renamed() @@ -2823,6 +2859,47 @@ void PresetCollection::update_map_system_profile_renamed() } } +void PresetCollection::set_custom_preset_alias(Preset &preset) +{ + if (m_type == Preset::Type::TYPE_FILAMENT && preset.config.has(BBL_JSON_KEY_INHERITS) && preset.config.option(BBL_JSON_KEY_INHERITS)->value.empty()) { + std::string alias_name; + std::string preset_name = preset.name; + if (alias_name.empty()) { + size_t end_pos = preset_name.find_first_of("@"); + if (end_pos != std::string::npos) { + alias_name = preset_name.substr(0, end_pos); + boost::trim_right(alias_name); + } + } + if (alias_name.empty() || is_alias_exist(alias_name, &preset)) + preset.alias = ""; + else { + preset.alias = std::move(alias_name); + m_map_alias_to_profile_name[preset.alias].push_back(preset.name); + set_printer_hold_alias(preset.alias, preset); + } + } +} + +void PresetCollection::set_printer_hold_alias(const std::string &alias, Preset &preset) +{ + auto compatible_printers = dynamic_cast(preset.config.option("compatible_printers")); + if (compatible_printers == nullptr) return; + for (const std::string &printer_name : compatible_printers->values) { + auto printer_iter = m_printer_hold_alias.find(printer_name); + if (m_printer_hold_alias.end() == printer_iter) { + m_printer_hold_alias[printer_name].insert(alias); + } else { + auto alias_iter = m_printer_hold_alias[printer_name].find(alias); + if (m_printer_hold_alias[printer_name].end() == alias_iter) { + m_printer_hold_alias[printer_name].insert(alias); + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << printer_name << "already has alias: " << alias << " and the preset name: " << preset.name; + } + } + } +} + std::string PresetCollection::name() const { switch (this->type()) { diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index b03ce605e3..4922f12eb1 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -554,6 +555,8 @@ public: const std::string& get_preset_name_by_alias(const std::string& alias) const; const std::string* get_preset_name_renamed(const std::string &old_name) const; + bool is_alias_exist(const std::string &alias, Preset* preset = nullptr); + void set_printer_hold_alias(const std::string &alias, Preset &preset); // used to update preset_choice from Tab const std::deque& get_presets() const { return m_presets; } @@ -705,6 +708,8 @@ protected: // Update m_map_system_profile_renamed from loaded system profiles. void update_map_system_profile_renamed(); + void set_custom_preset_alias(Preset &preset); + private: // Find a preset position in the sorted list of presets. // The "-- default -- " preset is always the first, so it needs @@ -748,7 +753,8 @@ private: // so that the addresses of the presets don't change during resizing of the container. std::deque m_presets; // System profiles may have aliases. Map to the full profile name. - std::vector> m_map_alias_to_profile_name; + std::map> m_map_alias_to_profile_name; + std::unordered_map> m_printer_hold_alias; // Map from old system profile name to a current system profile name. std::map m_map_system_profile_renamed; // Initially this preset contains a copy of the selected preset. Later on, this copy may be modified by the user. diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index f46e0aebcb..e1503604bb 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1895,7 +1895,6 @@ unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns) if (filament_presets.size() < this->filament_presets.size()) { filament_presets.push_back(this->filament_presets[filament_presets.size()]); filament_colors.push_back(filament_color); - ams_multi_color_filment.push_back(filament_multi_color); ++unknowns; continue; } @@ -1945,6 +1944,96 @@ void PresetBundle::set_calibrate_printer(std::string name) } } +std::set PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str) +{ + std::set printer_names; + if ("0.0" == nozzle_diameter_str || nozzle_diameter_str.empty()) { + nozzle_diameter_str = "0.4"; + } + std::ostringstream stream; + + for (auto printer_it = this->printers.begin(); printer_it != this->printers.end(); printer_it++) { + if (!printer_it->is_system) continue; + + ConfigOption * printer_model_opt = printer_it->config.option("printer_model"); + ConfigOptionString *printer_model_str = dynamic_cast(printer_model_opt); + if (!printer_model_str) continue; + + // use printer_model as printer type + if (printer_model_str->value != printer_type) continue; + + if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) printer_names.insert(printer_it->name); + } + assert(printer_names.size() == 1); + + for (auto& printer_name : printer_names) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " printer name: " << printer_name; + } + + return printer_names; +} + +bool PresetBundle::check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray( + const std::string &printer_type, std::string& nozzle_diameter_str, std::string &setting_id, std::string &tag_uid, std::string &nozzle_temp_min, std::string &nozzle_temp_max, std::string& preset_setting_id) +{ + bool is_equation = true; + + std::map> filament_list = filaments.get_filament_presets(); + std::set printer_names = get_printer_names_by_printer_type_and_nozzle(printer_type, nozzle_diameter_str); + + for (const Preset *preset : filament_list.find(setting_id)->second) { + if (tag_uid == "0" || (tag_uid.size() == 16 && tag_uid.substr(12, 2) == "01")) continue; + if (preset && !preset->is_user()) continue; + ConfigOption * printer_opt = const_cast(preset)->config.option("compatible_printers"); + ConfigOptionStrings *printer_strs = dynamic_cast(printer_opt); + bool compared = false; + for (const std::string &printer_str : printer_strs->values) { + if (printer_names.find(printer_str) != printer_names.end()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "nozzle temp matching: preset name: " << preset->name << " printer name: " << printer_str; + // Compare only once + if (!compared) { + compared = true; + bool min_temp_equation = false, max_temp_equation = false; + int min_nozzle_temp = std::stoi(nozzle_temp_min); + int max_nozzle_temp = std::stoi(nozzle_temp_max); + ConfigOption *opt_min = const_cast(preset)->config.option("nozzle_temperature_range_low"); + if (opt_min) { + ConfigOptionInts *opt_min_ints = dynamic_cast(opt_min); + min_nozzle_temp = opt_min_ints->get_at(0); + if (std::to_string(min_nozzle_temp) == nozzle_temp_min) + min_temp_equation = true; + else { + BOOST_LOG_TRIVIAL(info) << "tray min temp: " << nozzle_temp_min << " preset min temp: " << min_nozzle_temp; + nozzle_temp_min = std::to_string(min_nozzle_temp); + } + } + ConfigOption *opt_max = const_cast(preset)->config.option("nozzle_temperature_range_high"); + if (opt_max) { + ConfigOptionInts *opt_max_ints = dynamic_cast(opt_max); + max_nozzle_temp = opt_max_ints->get_at(0); + if (std::to_string(max_nozzle_temp) == nozzle_temp_max) + max_temp_equation = true; + else { + BOOST_LOG_TRIVIAL(info) << "tray max temp: " << nozzle_temp_max << " preset min temp: " << max_nozzle_temp; + nozzle_temp_max = std::to_string(max_nozzle_temp); + } + } + if (min_temp_equation && max_temp_equation) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "Determine if the temperature has changed: no changed"; + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "Determine if the temperature has changed: has changed"; + preset_setting_id = preset->setting_id; + is_equation = false; + } + } else { + assert(false); + } + } + } + } + return is_equation; +} + //BBS: check whether this is the only edited filament bool PresetBundle::is_the_only_edited_filament(unsigned int filament_index) { @@ -3544,8 +3633,10 @@ std::pair PresetBundle::load_vendor_configs_ } if (alias_name.empty()) loaded.alias = preset_name; - else + else { loaded.alias = std::move(alias_name); + filaments.set_printer_hold_alias(loaded.alias, loaded); + } loaded.renamed_from = std::move(renamed_from); if (! substitution_context.empty()) substitutions.push_back({ diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index c54ddda576..4cc62a3ed9 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -125,6 +125,15 @@ public: void set_is_validation_mode(bool mode) { validation_mode = mode; } void set_vendor_to_validate(std::string vendor) { vendor_to_validate = vendor; } + std::set get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str); + bool check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray(const std::string &printer_type, + std::string & nozzle_diameter_str, + std::string & setting_id, + std::string & tag_uid, + std::string & nozzle_temp_min, + std::string & nozzle_temp_max, + std::string & preset_setting_id); + PresetCollection prints; PresetCollection sla_prints; PresetCollection filaments; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a4756a6e38..9dfe1f9659 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -125,6 +125,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid", "extruder_clearance_radius", + "nozzle_height", "extruder_colour", "extruder_offset", "filament_flow_ratio", @@ -213,6 +214,12 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "activate_chamber_temp_control", "manual_filament_change", "disable_m73", + "use_firmware_retraction", + "enable_long_retraction_when_cut", + "long_retractions_when_cut", + "retraction_distances_when_cut", + "filament_long_retractions_when_cut", + "filament_retraction_distances_when_cut" }; static std::unordered_set steps_ignore; @@ -244,6 +251,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "nozzle_diameter" || opt_key == "filament_shrink" || opt_key == "resolution" + || opt_key == "precise_z_height" // Spiral Vase forces different kind of slicing than the normal model: // In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer. // Therefore toggling the Spiral Vase on / off requires complete reslicing. @@ -280,6 +288,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "prime_tower_width" || opt_key == "prime_tower_brim_width" || opt_key == "first_layer_print_sequence" + || opt_key == "other_layers_print_sequence" + || opt_key == "other_layers_print_sequence_nums" || opt_key == "wipe_tower_bridging" || opt_key == "wipe_tower_no_sparse_layers" || opt_key == "flush_volumes_matrix" @@ -460,8 +470,8 @@ std::vector Print::extruders(bool conside_custom_gcode) const if (conside_custom_gcode) { //BBS int num_extruders = m_config.filament_colour.size(); - for (auto plate_data : m_model.plates_custom_gcodes) { - for (auto item : plate_data.second.gcodes) { + if (m_model.plates_custom_gcodes.find(m_model.curr_plate_index) != m_model.plates_custom_gcodes.end()) { + for (auto item : m_model.plates_custom_gcodes.at(m_model.curr_plate_index).gcodes) { if (item.type == CustomGCode::Type::ToolChange && item.extruder <= num_extruders) extruders.push_back((unsigned int)(item.extruder - 1)); } @@ -576,6 +586,11 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print polygons->clear(); std::vector intersecting_idxs; + bool all_objects_are_short = print.is_all_objects_are_short(); + // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects + // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. + float obj_distance = all_objects_are_short ? scale_(0.5*MAX_OUTER_NOZZLE_DIAMETER-0.1) : scale_(0.5*print.config().extruder_clearance_radius.value-0.1); + for (const PrintObject *print_object : print.objects()) { assert(! print_object->model_object()->instances.empty()); assert(! print_object->instances().empty()); @@ -601,11 +616,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print // Now we check that no instance of convex_hull intersects any of the previously checked object instances. for (const PrintInstance &instance : print_object->instances()) { Polygon convex_hull_no_offset = convex_hull0, convex_hull; - auto tmp = offset(convex_hull_no_offset, - // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects - // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - float(scale_(0.5 * print.config().extruder_clearance_radius.value - 0.1)), - jtRound, scale_(0.1)); + auto tmp = offset(convex_hull_no_offset, obj_distance, jtRound, scale_(0.1)); if (!tmp.empty()) { // tmp may be empty due to clipper's bug, see STUDIO-2452 convex_hull = tmp.front(); // instance.shift is a position of a centered object, while model object may not be centered. @@ -840,7 +851,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print break; } } - if (height < inst->print_object->height()) + if (height < inst->print_object->max_z()) too_tall_instances[inst] = std::make_pair(print_instance_with_bounding_box[k].hull_polygon, unscaled(height)); } @@ -1088,7 +1099,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* if (m_config.spiral_mode) { size_t total_copies_count = 0; - for (const PrintObject *object : m_objects) + for (const PrintObject* object : m_objects) total_copies_count += object->instances().size(); // #4043 if (total_copies_count > 1 && m_config.print_sequence != PrintSequence::ByObject) @@ -1117,7 +1128,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) { const PrintObject &print_object = *m_objects[print_object_idx]; //FIXME It is quite expensive to generate object layers just to get the print height! - if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx)); + if (auto layers = generate_object_layers(print_object.slicing_parameters(), layer_height_profile(print_object_idx), print_object.config().precise_z_height.value); ! layers.empty() && layers.back() > this->config().printable_height + EPSILON) { return // Test whether the last slicing plane is below or above the print volume. @@ -1220,6 +1231,13 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* // BBS: remove obsolete logics and _L() if (has_custom_layering) { + std::vector> layer_z_series; + layer_z_series.assign(m_objects.size(), std::vector()); + + for (size_t idx_object = 0; idx_object < m_objects.size(); ++idx_object) { + layer_z_series[idx_object] = generate_object_layers(m_objects[idx_object]->slicing_parameters(), layer_height_profiles[idx_object], m_objects[idx_object]->config().precise_z_height.value); + } + for (size_t idx_object = 0; idx_object < m_objects.size(); ++idx_object) { if (idx_object == tallest_object_idx) continue; // Check that the layer height profiles are equal. This will happen when one object is @@ -2472,7 +2490,8 @@ int Print::get_hrc_by_nozzle_type(const NozzleType&type) static std::mapnozzle_type_to_hrc; if (nozzle_type_to_hrc.empty()) { fs::path file_path = fs::path(resources_dir()) / "info" / "nozzle_info.json"; - std::ifstream in(file_path.string()); + boost::nowide::ifstream in(file_path.string()); + //std::ifstream in(file_path.string()); json j; try { j = json::parse(in); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 231761f957..f48466e575 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -38,6 +38,8 @@ class SupportLayer; class TreeSupportData; class TreeSupport; +#define MARGIN_HEIGHT 1.5 +#define MAX_OUTER_NOZZLE_DIAMETER 4 // BBS: move from PrintObjectSlice.cpp struct VolumeSlices { @@ -331,6 +333,7 @@ public: // Height is used for slicing, for sorting the objects by height for sequential printing and for checking vertical clearence in sequential print mode. // The height is snug. coord_t height() const { return m_size.z(); } + double max_z() const { return m_max_z; } // Centering offset of the sliced mesh from the scaled and rotated mesh of the model. const Point& center_offset() const { return m_center_offset; } @@ -505,6 +508,7 @@ private: // XYZ in scaled coordinates Vec3crd m_size; + double m_max_z; PrintObjectConfig m_config; // Translation in Z + Rotation + Scaling / Mirroring. Transform3d m_trafo = Transform3d::Identity(); @@ -954,7 +958,11 @@ public: // Unset types are just ignored. static int get_compatible_filament_type(const std::set& types); - protected: + bool is_all_objects_are_short() const { + return std::all_of(this->objects().begin(), this->objects().end(), [&](PrintObject* obj) { return obj->height() < scale_(this->config().nozzle_height.value); }); + } + +protected: // Invalidates the step, and its depending steps in Print. bool invalidate_step(PrintStep step); diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 50fdee7cb9..b6fd173c03 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -235,11 +235,16 @@ static t_config_option_keys print_config_diffs( bool overriden = opt_new->overriden_by(opt_new_filament); if (overriden || *opt_old != *opt_new) { auto opt_copy = opt_new->clone(); - opt_copy->apply_override(opt_new_filament); + if (!((opt_key == "long_retractions_when_cut" || opt_key == "retraction_distances_when_cut") + && new_full_config.option("enable_long_retraction_when_cut")->value != LongRectrationLevel::EnableFilament)) // ugly code, remove it later if firmware supports + opt_copy->apply_override(opt_new_filament); bool changed = *opt_old != *opt_copy; if (changed) print_diff.emplace_back(opt_key); if (changed || overriden) { + if ((opt_key == "long_retractions_when_cut" || opt_key == "retraction_distances_when_cut") + && new_full_config.option("enable_long_retraction_when_cut")->value != LongRectrationLevel::EnableFilament) + continue; // filament_overrides will be applied to the placeholder parser, which layers these parameters over full_print_config. filament_overrides.set_key_value(opt_key, opt_copy); } else diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 2edde94c42..ff7722c739 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -370,11 +370,11 @@ static const t_config_enum_values s_keys_map_BedType = { CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BedType) // BBS -static const t_config_enum_values s_keys_map_FirstLayerSeq = { +static const t_config_enum_values s_keys_map_LayerSeq = { { "Auto", flsAuto }, { "Customize", flsCutomize }, }; -CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(FirstLayerSeq) +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(LayerSeq) static t_config_enum_values s_keys_map_NozzleType { { "undefine", int(NozzleType::ntUndefine) }, @@ -770,16 +770,37 @@ void PrintConfigDef::init_fff_params() def->max = 16; def->set_default_value(new ConfigOptionInts{0}); + def = this->add("other_layers_print_sequence", coInts); + def->label = L("Other layers print sequence"); + def->min = 0; + def->max = 16; + def->set_default_value(new ConfigOptionInts{0}); + + def = this->add("other_layers_print_sequence_nums", coInt); + def->label = L("The number of other layers print sequence"); + def->set_default_value(new ConfigOptionInt{0}); + def = this->add("first_layer_sequence_choice", coEnum); def->category = L("Quality"); def->label = L("First layer filament sequence"); - def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("Auto"); def->enum_values.push_back("Customize"); def->enum_labels.push_back(L("Auto")); def->enum_labels.push_back(L("Customize")); def->mode = comSimple; - def->set_default_value(new ConfigOptionEnum(flsAuto)); + def->set_default_value(new ConfigOptionEnum(flsAuto)); + + def = this->add("other_layers_sequence_choice", coEnum); + def->category = L("Quality"); + def->label = L("Other layers filament sequence"); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("Auto"); + def->enum_values.push_back("Customize"); + def->enum_labels.push_back(L("Auto")); + def->enum_labels.push_back(L("Customize")); + def->mode = comSimple; + def->set_default_value(new ConfigOptionEnum(flsAuto)); def = this->add("before_layer_change_gcode", coString); def->label = L("Before layer change G-code"); @@ -1580,6 +1601,14 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(40)); + def = this->add("nozzle_height", coFloat); + def->label = L("Nozzle height"); + def->tooltip = L("The height of nozzle tip."); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comDevelop; + def->set_default_value(new ConfigOptionFloat(4)); + def = this->add("bed_mesh_min", coPoint); def->label = L("Bed mesh min"); def->tooltip = L( @@ -2390,6 +2419,15 @@ def = this->add("filament_loading_speed", coFloats); def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(30)); + // BBS + def = this->add("precise_z_height", coBool); + def->label = L("Precise Z height"); + def->tooltip = L("Enable this to get precise z height of object after slicing. " + "It will get the precise object height by fine-tuning the layer heights of the last few layers. " + "Note that this is an experimental parameter."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(0)); + // BBS def = this->add("enable_arc_fitting", coBool); def->label = L("Arc fitting"); @@ -3393,6 +3431,25 @@ def = this->add("filament_loading_speed", coFloats); def->mode = comSimple; def->set_default_value(new ConfigOptionFloats { 0.8 }); + def = this->add("enable_long_retraction_when_cut",coInt); + def->mode = comDevelop; + def->set_default_value(new ConfigOptionInt {0}); + + def = this->add("long_retractions_when_cut", coBools); + def->label = L("Long retraction when cut(experimental)"); + def->tooltip = L("Experimental feature.Retracting and cutting off the filament at a longer distance during changes to minimize purge." + "While this reduces flush significantly, it may also raise the risk of nozzle clogs or other printing problems."); + def->mode = comDevelop; + def->set_default_value(new ConfigOptionBools {false}); + + def = this->add("retraction_distances_when_cut",coFloats); + def->label = L("Retraction distance when cut"); + def->tooltip = L("Experimental feature.Retraction length before cutting off during filament change"); + def->mode = comDevelop; + def->min = 10; + def->max = 18; + def->set_default_value(new ConfigOptionFloats {18}); + def = this->add("retract_length_toolchange", coFloats); def->label = L("Length"); //def->full_label = L("Retraction Length (Toolchange)"); @@ -4929,7 +4986,10 @@ def = this->add("filament_loading_speed", coFloats); // bools "retract_when_changing_layer", "wipe", // percents - "retract_before_wipe"}) { + "retract_before_wipe", + "long_retractions_when_cut", + "retraction_distances_when_cut" + }) { auto it_opt = options.find(opt_key); assert(it_opt != options.end()); def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type); @@ -4940,9 +5000,13 @@ def = this->add("filament_loading_speed", coFloats); def->enum_keys_map = it_opt->second.enum_keys_map; def->enum_labels = it_opt->second.enum_labels; def->enum_values = it_opt->second.enum_values; + def->min = it_opt->second.min; + def->max = it_opt->second.max; //BBS: shown specific filament retract config because we hide the machine retract into comDevelop mode if ((strcmp(opt_key, "retraction_length") == 0) || - (strcmp(opt_key, "z_hop") == 0)) + (strcmp(opt_key, "z_hop") == 0)|| + (strcmp(opt_key, "long_retractions_when_cut") == 0)|| + (strcmp(opt_key, "retraction_distances_when_cut") == 0)) def->mode = comSimple; else def->mode = comAdvanced; @@ -4973,17 +5037,19 @@ void PrintConfigDef::init_extruder_option_keys() "retraction_length", "z_hop", "z_hop_types", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retraction_speed", "deretraction_speed", "retract_before_wipe", "retract_restart_extra", "retraction_minimum_travel", "wipe", "wipe_distance", "retract_when_changing_layer", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour", - "default_filament_profile" + "default_filament_profile","retraction_distances_when_cut","long_retractions_when_cut" }; m_extruder_retract_keys = { "deretraction_speed", + "long_retractions_when_cut", "retract_before_wipe", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retract_restart_extra", "retract_when_changing_layer", + "retraction_distances_when_cut", "retraction_length", "retraction_minimum_travel", "retraction_speed", @@ -5002,17 +5068,19 @@ void PrintConfigDef::init_filament_option_keys() "retraction_length", "z_hop", "z_hop_types", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retraction_speed", "deretraction_speed", "retract_before_wipe", "retract_restart_extra", "retraction_minimum_travel", "wipe", "wipe_distance", "retract_when_changing_layer", "retract_length_toolchange", "retract_restart_extra_toolchange", "filament_colour", - "default_filament_profile"/*,"filament_seam_gap"*/ + "default_filament_profile","retraction_distances_when_cut","long_retractions_when_cut"/*,"filament_seam_gap"*/ }; m_filament_retract_keys = { "deretraction_speed", + "long_retractions_when_cut", "retract_before_wipe", "retract_lift_above", "retract_lift_below", "retract_lift_enforce", "retract_restart_extra", "retract_when_changing_layer", + "retraction_distances_when_cut", "retraction_length", "retraction_minimum_travel", "retraction_speed", @@ -5792,7 +5860,8 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va "remove_freq_sweep", "remove_bed_leveling", "remove_extrusion_calibration", "support_transition_line_width", "support_transition_speed", "bed_temperature", "bed_temperature_initial_layer", "can_switch_nozzle_type", "can_add_auxiliary_fan", "extra_flush_volume", "spaghetti_detector", "adaptive_layer_height", - "z_hop_type", "z_lift_type", "bed_temperature_difference", + "z_hop_type", "z_lift_type", "bed_temperature_difference","long_retraction_when_cut", + "retraction_distance_when_cut", "extruder_type", "internal_bridge_support_thickness","extruder_clearance_max_radius", "top_area_threshold", "reduce_wall_solid_infill" }; @@ -6287,6 +6356,8 @@ std::map validate(const FullPrintConfig &cfg, bool und if (cfg.extruder_clearance_height_to_lid <= 0) { error_message.emplace("extruder_clearance_height_to_lid", L("invalid value ") + std::to_string(cfg.extruder_clearance_height_to_lid)); } + if (cfg.nozzle_height <= 0) + error_message.emplace("nozzle_height", L("invalid value ") + std::to_string(cfg.nozzle_height)); // --extrusion-multiplier for (double em : cfg.filament_flow_ratio.values) @@ -6848,6 +6919,12 @@ CLIMiscConfigDef::CLIMiscConfigDef() def->tooltip = "MakerLab version to generate this 3mf"; def->cli_params = "version"; def->set_default_value(new ConfigOptionString()); + + def = this->add("allow_newer_file", coBool); + def->label = "Allow 3mf with newer version to be sliced"; + def->tooltip = "Allow 3mf with newer version to be sliced"; + def->cli_params = "option"; + def->set_default_value(new ConfigOptionBool(false)); } const CLIActionsConfigDef cli_actions_config_def; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 28e9d00923..be3edef9a3 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -144,6 +144,13 @@ enum SupportMaterialStyle { smsDefault, smsGrid, smsSnug, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsOrganic, }; +enum LongRectrationLevel +{ + Disabled=0, + EnableMachine, + EnableFilament +}; + enum SupportMaterialInterfacePattern { smipAuto, smipRectilinear, smipConcentric, smipRectilinearInterlaced, smipGrid }; @@ -268,7 +275,7 @@ enum BedType { }; // BBS -enum FirstLayerSeq { +enum LayerSeq { flsAuto, flsCutomize }; @@ -854,6 +861,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, top_surface_jerk)) ((ConfigOptionFloat, initial_layer_jerk)) ((ConfigOptionFloat, travel_jerk)) + ((ConfigOptionBool, precise_z_height)) ) // This object is mapped to Perl as Slic3r::Config::PrintRegion. @@ -1051,6 +1059,9 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionPercents, retract_before_wipe)) ((ConfigOptionFloats, retraction_length)) ((ConfigOptionFloats, retract_length_toolchange)) + ((ConfigOptionInt, enable_long_retraction_when_cut)) + ((ConfigOptionFloats, retraction_distances_when_cut)) + ((ConfigOptionBools, long_retractions_when_cut)) ((ConfigOptionFloats, z_hop)) // BBS ((ConfigOptionEnumsGeneric, z_hop_types)) @@ -1156,12 +1167,15 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionEnum,print_sequence)) ((ConfigOptionEnum, print_order)) ((ConfigOptionInts, first_layer_print_sequence)) + ((ConfigOptionInts, other_layers_print_sequence)) + ((ConfigOptionInt, other_layers_print_sequence_nums)) ((ConfigOptionBools, slow_down_for_layer_cooling)) ((ConfigOptionInts, close_fan_the_first_x_layers)) ((ConfigOptionEnum, draft_shield)) ((ConfigOptionFloat, extruder_clearance_height_to_rod))//BBs ((ConfigOptionFloat, extruder_clearance_height_to_lid))//BBS ((ConfigOptionFloat, extruder_clearance_radius)) + ((ConfigOptionFloat, nozzle_height)) ((ConfigOptionStrings, extruder_colour)) ((ConfigOptionPoints, extruder_offset)) ((ConfigOptionBools, reduce_fan_stop_start_freq)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 077b226668..c78e7de4b5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -97,6 +97,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor // snug height and an approximate bounding box in XY. BoundingBoxf3 bbox = model_object->raw_bounding_box(); Vec3d bbox_center = bbox.center(); + // We may need to rotate the bbox / bbox_center from the original instance to the current instance. double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_rotation(), instances.front().model_instance->get_rotation()); if (std::abs(z_diff) > EPSILON) { @@ -109,7 +110,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor m_center_offset = Point::new_scale(bbox_center.x(), bbox_center.y()); // Size of the transformed mesh. This bounding may not be snug in XY plane, but it is snug in Z. m_size = (bbox.size() * (1. / SCALING_FACTOR)).cast(); - m_size.z() = coord_t(model_object->max_z() * (1. / SCALING_FACTOR)); + m_max_z = scaled(model_object->instance_bounding_box(0).max(2)); this->set_instances(std::move(instances)); } diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 78dd620eba..53c875555b 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -810,7 +810,7 @@ void PrintObject::slice() m_print->throw_if_canceled(); m_typed_slices = false; this->clear_layers(); - m_layers = new_layers(this, generate_object_layers(m_slicing_params, layer_height_profile)); + m_layers = new_layers(this, generate_object_layers(m_slicing_params, layer_height_profile, m_config.precise_z_height.value)); this->slice_volumes(); m_print->throw_if_canceled(); int firstLayerReplacedBy = 0; diff --git a/src/libslic3r/ProjectTask.hpp b/src/libslic3r/ProjectTask.hpp index 103d82073f..05f39f9b2c 100644 --- a/src/libslic3r/ProjectTask.hpp +++ b/src/libslic3r/ProjectTask.hpp @@ -46,6 +46,8 @@ struct FilamentInfo float used_g; int tray_id; // start with 0 float distance; + int ctype = 0; + std::vector colors = std::vector(); int mapping_result = 0; }; diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 72e231c314..97a8700d83 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -631,10 +631,104 @@ void adjust_layer_height_profile( #endif /* _DEBUG */ } +bool adjust_layer_series_to_align_object_height(const SlicingParameters &slicing_params, std::vector& layer_series) +{ + coordf_t object_height = slicing_params.object_print_z_height(); + if (is_approx(layer_series.back(), object_height)) + return true; + + // need at least 5 + 1(first_layer) layers to adjust the height + size_t layer_size = layer_series.size(); + if (layer_size < 12) + return false; + + std::vector last_5_layers_heght; + for (size_t i = 0; i < 5; ++i) { + last_5_layers_heght.emplace_back(layer_series[layer_size - 10 + 2 * i + 1] - layer_series[layer_size - 10 + 2 * i]); + } + + coordf_t gap = abs(layer_series.back() - object_height); + std::vector can_adjust(5, true); // to record whether every layer can adjust layer height + bool taller_than_object = layer_series.back() < object_height; + + auto get_valid_size = [&can_adjust]() -> int { + int valid_size = 0; + for (auto b_adjust : can_adjust) { + valid_size += b_adjust ? 1 : 0; + } + return valid_size; + }; + + auto adjust_layer_height = [&slicing_params, &last_5_layers_heght, &can_adjust, &get_valid_size, &taller_than_object](coordf_t gap) -> coordf_t { + coordf_t delta_gap = gap / get_valid_size(); + coordf_t remain_gap = 0; + for (size_t i = 0; i < last_5_layers_heght.size(); ++i) { + coordf_t& l_height = last_5_layers_heght[i]; + if (taller_than_object) { + if (can_adjust[i] && is_approx(l_height, slicing_params.max_layer_height)) { + remain_gap += delta_gap; + can_adjust[i] = false; + continue; + } + + if (can_adjust[i] && l_height + delta_gap > slicing_params.max_layer_height) { + remain_gap += l_height + delta_gap - slicing_params.max_layer_height; + l_height = slicing_params.max_layer_height; + can_adjust[i] = false; + } + else { + l_height += delta_gap; + } + } + else { + if (can_adjust[i] && is_approx(l_height, slicing_params.min_layer_height)) { + remain_gap += delta_gap; + can_adjust[i] = false; + continue; + } + + if (can_adjust[i] && l_height - delta_gap < slicing_params.min_layer_height) { + remain_gap += slicing_params.min_layer_height + delta_gap - l_height; + l_height = slicing_params.min_layer_height; + can_adjust[i] = false; + } + else { + l_height -= delta_gap; + } + } + } + return remain_gap; + }; + + while (gap > 0) { + int valid_size = get_valid_size(); + if (valid_size == 0) { + // 5 layers can not adjust z within valid layer height + return false; + } + + gap = adjust_layer_height(gap); + if (is_approx(gap, 0.0)) { + // adjust succeed + break; + } + } + + for (size_t i = 0; i < last_5_layers_heght.size(); ++i) { + if (i > 0) { + layer_series[layer_size - 10 + 2 * i] = layer_series[layer_size - 10 + 2 * i - 1]; + } + layer_series[layer_size - 10 + 2 * i + 1] = layer_series[layer_size - 10 + 2 * i] + last_5_layers_heght[i]; + } + + return true; +} + // Produce object layers as pairs of low / high layer boundaries, stored into a linear vector. std::vector generate_object_layers( const SlicingParameters &slicing_params, - const std::vector &layer_height_profile) + const std::vector &layer_height_profile, + bool is_precise_z_height) { assert(! layer_height_profile.empty()); @@ -683,7 +777,8 @@ std::vector generate_object_layers( out.push_back(print_z); } - //FIXME Adjust the last layer to align with the top object layer exactly? + if (is_precise_z_height) + adjust_layer_series_to_align_object_height(slicing_params, out); return out; } diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 464a05ba44..74b99eb8df 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -177,7 +177,8 @@ void adjust_layer_height_profile( // The object layers are based at z=0, ignoring the raft layers. std::vector generate_object_layers( const SlicingParameters &slicing_params, - const std::vector &layer_height_profile); + const std::vector &layer_height_profile, + bool is_precise_z_height); // Check whether the layer height profile describes a fixed layer height profile. bool check_object_layers_fixed( diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 973d6c6d33..1ad9c03bd8 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -224,21 +224,21 @@ bool TriangleMesh::from_stl(stl_file& stl, bool repair) return true; } -bool TriangleMesh::ReadSTLFile(const char* input_file, bool repair, ImportstlProgressFn stlFn) -{ +bool TriangleMesh::ReadSTLFile(const char *input_file, bool repair, ImportstlProgressFn stlFn, int custom_header_length) +{ stl_file stl; - if (! stl_open(&stl, input_file, stlFn)) + if (!stl_open(&stl, input_file, stlFn, custom_header_length)) return false; return from_stl(stl, repair); } bool TriangleMesh::write_ascii(const char* output_file) -{ +{ return its_write_stl_ascii(output_file, "", this->its); } bool TriangleMesh::write_binary(const char* output_file) -{ +{ return its_write_stl_binary(output_file, "", this->its); } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index fb6951c1df..54b2d45f88 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -105,7 +105,7 @@ public: explicit TriangleMesh(indexed_triangle_set &&M, const RepairedMeshErrors& repaired_errors = RepairedMeshErrors()); void clear() { this->its.clear(); this->m_stats.clear(); } bool from_stl(stl_file& stl, bool repair = true); - bool ReadSTLFile(const char* input_file, bool repair = true, ImportstlProgressFn stlFn = nullptr); + bool ReadSTLFile(const char *input_file, bool repair = true, ImportstlProgressFn stlFn = nullptr, int custom_header_length = 80); bool write_ascii(const char* output_file); bool write_binary(const char* output_file); float volume(); diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index b03f27d187..43daedb5bb 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -50,6 +50,7 @@ #define CLI_OBJECT_ARRANGE_FAILED -21 #define CLI_OBJECT_ORIENT_FAILED -22 #define CLI_MODIFIED_PARAMS_TO_PRINTER -23 +#define CLI_FILE_VERSION_NOT_SUPPORTED -24 #define CLI_NO_SUITABLE_OBJECTS -50 diff --git a/src/libslic3r/calib.hpp b/src/libslic3r/calib.hpp index 3d0146e2b8..af5bbb81d5 100644 --- a/src/libslic3r/calib.hpp +++ b/src/libslic3r/calib.hpp @@ -34,6 +34,11 @@ struct Calib_Params CalibMode mode; }; +enum FlowRatioCalibrationType { + COMPLETE_CALIBRATION = 0, + FINE_CALIBRATION, +}; + class X1CCalibInfos { public: @@ -78,6 +83,7 @@ struct PrinterCaliInfo bool cali_finished = true; float cache_flow_ratio; std::vector selected_presets; + FlowRatioCalibrationType cache_flow_rate_calibration_type = FlowRatioCalibrationType::COMPLETE_CALIBRATION; }; class PACalibResult diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index ddbf120b21..e91b01730d 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -251,8 +251,11 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent) m_panel_SN->Fit(); wxBoxSizer* m_tip_sizer = new wxBoxSizer(wxHORIZONTAL); - m_tip_readonly = new wxStaticText(parent, wxID_ANY, _L("Setting AMS slot information while printing is not supported"), wxDefaultPosition, wxSize(-1, AMS_MATERIALS_SETTING_INPUT_SIZE.y)); + m_tip_readonly = new Label(parent, _L("Setting AMS slot information while printing is not supported")); m_tip_readonly->SetForegroundColour(*wxBLACK); + m_tip_readonly->SetBackgroundColour(*wxWHITE); + m_tip_readonly->SetMinSize(wxSize(FromDIP(380), -1)); + m_tip_readonly->SetMaxSize(wxSize(FromDIP(380), -1)); m_tip_readonly->Hide(); m_tip_sizer->Add(m_tip_readonly, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(20)); @@ -409,6 +412,7 @@ void AMSMaterialsSetting::enable_confirm_button(bool en) else { m_tip_readonly->SetLabelText(_L("Setting Virtual slot information while printing is not supported")); } + m_tip_readonly->Wrap(FromDIP(380)); m_tip_readonly->Show(!en); } } @@ -443,7 +447,7 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) { } // set k / n value - if (obj->get_printer_series() != PrinterSeries::SERIES_X1) { + if (obj->cali_version <= -1 && obj->get_printer_series() == PrinterSeries::SERIES_P1P) { // set extrusion cali ratio int cali_tray_id = ams_id * 4 + tray_id; @@ -561,7 +565,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) wxString k_text = m_input_k_val->GetTextCtrl()->GetValue(); wxString n_text = m_input_n_val->GetTextCtrl()->GetValue(); - if ((obj->get_printer_series() != PrinterSeries::SERIES_X1) && !ExtrusionCalibration::check_k_validation(k_text)) { + if (obj->cali_version <= -1 && (obj->get_printer_series() != PrinterSeries::SERIES_X1) && !ExtrusionCalibration::check_k_validation(k_text)) { wxString k_tips = _L("Please input a valid value (K in 0~0.3)"); wxString kn_tips = _L("Please input a valid value (K in 0~0.3, N in 0.6~2.0)"); MessageDialog msg_dlg(nullptr, k_tips, wxEmptyString, wxICON_WARNING | wxOK); @@ -586,7 +590,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) ; } - if (obj->get_printer_series() == PrinterSeries::SERIES_X1) { + if (obj->cali_version >= 0) { PACalibIndexInfo select_index_info; select_index_info.tray_id = tray_id; select_index_info.nozzle_diameter = obj->nozzle_diameter; @@ -625,7 +629,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) ; } - if (obj->get_printer_series() == PrinterSeries::SERIES_X1) { + if (obj->cali_version >= 0) { PACalibIndexInfo select_index_info; select_index_info.tray_id = cali_tray_id; select_index_info.nozzle_diameter = obj->nozzle_diameter; @@ -728,7 +732,7 @@ void AMSMaterialsSetting::update_widgets() else m_panel_normal->Hide(); m_panel_kn->Show(); - } else if (obj && (obj->ams_support_virtual_tray || (obj->get_printer_series() == PrinterSeries::SERIES_X1))) { + } else if (obj && (obj->ams_support_virtual_tray || obj->cali_version >= 0)) { m_panel_normal->Show(); m_panel_kn->Show(); } else { @@ -774,8 +778,12 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi std::set filament_id_set; - - PresetBundle* preset_bundle = wxGetApp().preset_bundle; + PresetBundle * preset_bundle = wxGetApp().preset_bundle; + std::ostringstream stream; + stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter; + std::string nozzle_diameter_str = stream.str(); + std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), nozzle_diameter_str); + if (preset_bundle) { BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size(); for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) { @@ -787,79 +795,64 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) { continue; } + + ConfigOption * printer_opt = filament_it->config.option("compatible_printers"); + ConfigOptionStrings *printer_strs = dynamic_cast(printer_opt); + for (auto printer_str : printer_strs->values) { + if (printer_names.find(printer_str) != printer_names.end()) { + if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) { + continue; + } else { + filament_id_set.insert(filament_it->filament_id); + // name matched + if (filament_it->is_system) { + filament_items.push_back(filament_it->alias); + FilamentInfos filament_infos; + filament_infos.filament_id = filament_it->filament_id; + filament_infos.setting_id = filament_it->setting_id; + map_filament_items[filament_it->alias] = filament_infos; + } else { + char target = '@'; + size_t pos = filament_it->name.find(target); + if (pos != std::string::npos) { + std::string user_preset_alias = filament_it->name.substr(0, pos - 1); + wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8); + user_preset_alias = wx_user_preset_alias.ToStdString(); - for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) { - // filter by system preset - if (!printer_it->is_system) continue; - // get printer_model - ConfigOption* printer_model_opt = printer_it->config.option("printer_model"); - ConfigOptionString* printer_model_str = dynamic_cast(printer_model_opt); - if (!printer_model_str ) - continue; - - // use printer_model as printer type - if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type)) - continue; - ConfigOption* printer_opt = filament_it->config.option("compatible_printers"); - ConfigOptionStrings* printer_strs = dynamic_cast(printer_opt); - for (auto printer_str : printer_strs->values) { - if (printer_it->name == printer_str) { - if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) { - continue; - } - else { - filament_id_set.insert(filament_it->filament_id); - // name matched - if (filament_it->is_system) { - filament_items.push_back(filament_it->alias); + filament_items.push_back(user_preset_alias); FilamentInfos filament_infos; - filament_infos.filament_id = filament_it->filament_id; - filament_infos.setting_id = filament_it->setting_id; - map_filament_items[filament_it->alias] = filament_infos; + filament_infos.filament_id = filament_it->filament_id; + filament_infos.setting_id = filament_it->setting_id; + map_filament_items[user_preset_alias] = filament_infos; } - else { - char target = '@'; - size_t pos = filament_it->name.find(target); - if (pos != std::string::npos) { - std::string user_preset_alias = filament_it->name.substr(0, pos-1); - wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8); - user_preset_alias = wx_user_preset_alias.ToStdString(); - - filament_items.push_back(user_preset_alias); - FilamentInfos filament_infos; - filament_infos.filament_id = filament_it->filament_id; - filament_infos.setting_id = filament_it->setting_id; - map_filament_items[user_preset_alias] = filament_infos; - } - - } - - if (filament_it->filament_id == ams_filament_id) { - selection_idx = idx; - - // update if nozzle_temperature_range is found - ConfigOption* opt_min = filament_it->config.option("nozzle_temperature_range_low"); - if (opt_min) { - ConfigOptionInts* opt_min_ints = dynamic_cast(opt_min); - if (opt_min_ints) { - wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0)); - m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min); - } - } - ConfigOption* opt_max = filament_it->config.option("nozzle_temperature_range_high"); - if (opt_max) { - ConfigOptionInts* opt_max_ints = dynamic_cast(opt_max); - if (opt_max_ints) { - wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0)); - m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max); - } - } - } - idx++; } + + if (filament_it->filament_id == ams_filament_id) { + selection_idx = idx; + + // update if nozzle_temperature_range is found + ConfigOption *opt_min = filament_it->config.option("nozzle_temperature_range_low"); + if (opt_min) { + ConfigOptionInts *opt_min_ints = dynamic_cast(opt_min); + if (opt_min_ints) { + wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0)); + m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min); + } + } + ConfigOption *opt_max = filament_it->config.option("nozzle_temperature_range_high"); + if (opt_max) { + ConfigOptionInts *opt_max_ints = dynamic_cast(opt_max); + if (opt_max_ints) { + wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0)); + m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max); + } + } + } + idx++; } } } + } } @@ -884,7 +877,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi m_readonly_filament->Hide(); } - if (obj->get_printer_series() == PrinterSeries::SERIES_X1) { + if (obj->cali_version >= 0) { m_title_pa_profile->Show(); m_comboBox_cali_result->Show(); m_input_k_val->Disable(); @@ -943,12 +936,26 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) m_filament_type = ""; PresetBundle* preset_bundle = wxGetApp().preset_bundle; if (preset_bundle) { + std::ostringstream stream; + if (obj) + stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter; + std::string nozzle_diameter_str = stream.str(); + std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), + nozzle_diameter_str); for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) { if (!m_comboBox_filament->GetValue().IsEmpty()) { auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()]; std::string filament_id = filament_item.filament_id; if (it->filament_id.compare(filament_id) == 0) { - + bool has_compatible_printer = false; + std::string preset_name = it->name; + for (std::string printer_name : printer_names) { + if (preset_name.find(printer_name) != std::string::npos) { + has_compatible_printer = true; + break; + } + } + if (!it->is_system && !has_compatible_printer) continue; // ) if nozzle_temperature_range is found ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low"); if (opt_min) { @@ -1039,7 +1046,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) m_pa_profile_items.clear(); m_comboBox_cali_result->SetValue(wxEmptyString); - if (obj->get_printer_series() == PrinterSeries::SERIES_X1) { + if (obj->cali_version >= 0) { m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString); std::vector cali_history = this->obj->pa_calib_tab; for (auto cali_item : cali_history) { @@ -1442,7 +1449,7 @@ void ColorPickerPopup::on_custom_clr_picker(wxMouseEvent& event) m_clrData->GetColour().Red(), m_clrData->GetColour().Green(), m_clrData->GetColour().Blue(), - 254 + 255 ); if (picker_color.Alpha() == 0) { diff --git a/src/slic3r/GUI/AMSMaterialsSetting.hpp b/src/slic3r/GUI/AMSMaterialsSetting.hpp index c66052a077..6a10255d28 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.hpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.hpp @@ -166,7 +166,7 @@ protected: wxStaticBitmap * bitmap_min_degree; Button * m_button_reset; Button * m_button_confirm; - wxStaticText* m_tip_readonly; + Label* m_tip_readonly; Button * m_button_close; wxColourData * m_clrData; diff --git a/src/slic3r/GUI/AMSSetting.cpp b/src/slic3r/GUI/AMSSetting.cpp index ac62d1ebaf..b2ef34e620 100644 --- a/src/slic3r/GUI/AMSSetting.cpp +++ b/src/slic3r/GUI/AMSSetting.cpp @@ -21,29 +21,31 @@ void AMSSetting::create() auto m_static_ams_settings = new wxStaticText(this, wxID_ANY, _L("AMS Settings"), wxDefaultPosition, wxDefaultSize, 0); m_static_ams_settings->SetFont(::Label::Head_14); m_static_ams_settings->SetForegroundColour(AMS_SETTING_GREY800); - m_sizer_main->Add(0,0,0,wxTOP,FromDIP(10)); - m_sizer_main->Add(m_static_ams_settings, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(24)); + m_panel_body = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxTAB_TRAVERSAL); m_panel_body->SetBackgroundColour(*wxWHITE); wxBoxSizer *m_sizerl_body = new wxBoxSizer(wxVERTICAL); + m_panel_Insert_material = new wxPanel(m_panel_body, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxTAB_TRAVERSAL); + m_panel_Insert_material->SetBackgroundColour(*wxWHITE); + wxBoxSizer* m_sizer_main_Insert_material = new wxBoxSizer(wxVERTICAL); // checkbox area 1 wxBoxSizer *m_sizer_Insert_material = new wxBoxSizer(wxHORIZONTAL); - m_checkbox_Insert_material_auto_read = new ::CheckBox(m_panel_body); + m_checkbox_Insert_material_auto_read = new ::CheckBox(m_panel_Insert_material); m_checkbox_Insert_material_auto_read->Bind(wxEVT_TOGGLEBUTTON, &AMSSetting::on_insert_material_read, this); m_sizer_Insert_material->Add(m_checkbox_Insert_material_auto_read, 0, wxTOP, 1); m_sizer_Insert_material->Add(0, 0, 0, wxLEFT, 12); - m_title_Insert_material_auto_read = new wxStaticText(m_panel_body, wxID_ANY, _L("Insertion update"), + m_title_Insert_material_auto_read = new wxStaticText(m_panel_Insert_material, wxID_ANY, _L("Insertion update"), wxDefaultPosition, wxDefaultSize, 0); m_title_Insert_material_auto_read->SetFont(::Label::Head_13); m_title_Insert_material_auto_read->SetForegroundColour(AMS_SETTING_GREY800); m_title_Insert_material_auto_read->Wrap(AMS_SETTING_BODY_WIDTH); - m_sizer_Insert_material->Add(m_title_Insert_material_auto_read, 1, wxALL | wxEXPAND, 0); + m_sizer_Insert_material->Add(m_title_Insert_material_auto_read, 0, wxALL | wxEXPAND, 0); @@ -53,7 +55,7 @@ void AMSSetting::create() m_sizer_Insert_material_tip->Add(0, 0, 0, wxLEFT, 10); // tip line1 - m_tip_Insert_material_line1 = new Label(m_panel_body, + m_tip_Insert_material_line1 = new Label(m_panel_Insert_material, _L("The AMS will automatically read the filament information when inserting a new Bambu Lab filament. This takes about 20 seconds.") ); m_tip_Insert_material_line1->SetFont(::Label::Body_13); @@ -64,8 +66,8 @@ void AMSSetting::create() m_sizer_Insert_material_tip_inline->Add(m_tip_Insert_material_line1, 0, wxEXPAND, 0); // tip line2 - m_tip_Insert_material_line2 = new Label(m_panel_body, - _L("Note: if new filament is inserted during printing, the AMS will not automatically read any information until printing is completed.") + m_tip_Insert_material_line2 = new Label(m_panel_Insert_material, + _L("Note: if a new filament is inserted during printing, the AMS will not automatically read any information until printing is completed.") ); m_tip_Insert_material_line2->SetFont(::Label::Body_13); m_tip_Insert_material_line2->SetForegroundColour(AMS_SETTING_GREY700); @@ -74,8 +76,8 @@ void AMSSetting::create() m_tip_Insert_material_line2->Hide(); m_sizer_Insert_material_tip_inline->Add(m_tip_Insert_material_line2, 0, wxEXPAND | wxTOP, 8); - // tip line2 - m_tip_Insert_material_line3 = new Label(m_panel_body, + // tip line3 + m_tip_Insert_material_line3 = new Label(m_panel_Insert_material, _L("When inserting a new filament, the AMS will not automatically read its information, leaving it blank for you to enter manually.") ); m_tip_Insert_material_line3->SetFont(::Label::Body_13); @@ -87,7 +89,10 @@ void AMSSetting::create() m_sizer_Insert_material_tip->Add(m_sizer_Insert_material_tip_inline, 1, wxALIGN_CENTER, 0); - + m_sizer_main_Insert_material->Add(m_sizer_Insert_material, 0, wxEXPAND | wxTOP, FromDIP(4)); + m_sizer_main_Insert_material->Add(m_sizer_Insert_material_tip, 0, wxEXPAND | wxLEFT | wxTOP, 18); + m_panel_Insert_material->SetSizer(m_sizer_main_Insert_material); + // checkbox area 2 wxBoxSizer *m_sizer_starting = new wxBoxSizer(wxHORIZONTAL); m_checkbox_starting_auto_read = new ::CheckBox(m_panel_body); @@ -205,10 +210,7 @@ void AMSSetting::create() m_sizer_remain_block->Add(m_sizer_remain_tip, 0, wxLEFT, 18); m_sizer_remain_block->Add(0, 0, 0, wxTOP, 15); - m_sizerl_body->Add(m_sizer_Insert_material, 0, wxEXPAND, 0); - m_sizerl_body->Add(0, 0, 0, wxTOP, 8); - m_sizerl_body->Add(m_sizer_Insert_material_tip, 0, wxEXPAND | wxLEFT, 18); - m_sizerl_body->Add(0, 0, 0, wxTOP, 15); + m_sizerl_body->Add(m_panel_Insert_material, 0, 0, 0); m_sizerl_body->Add(m_sizer_starting, 0, wxEXPAND | wxTOP, FromDIP(8)); m_sizerl_body->Add(0, 0, 0, wxTOP, 8); m_sizerl_body->Add(m_sizer_starting_tip, 0, wxLEFT, 18); @@ -224,7 +226,10 @@ void AMSSetting::create() m_panel_body->SetSizer(m_sizerl_body); m_panel_body->Layout(); m_sizerl_body->Fit(m_panel_body); - m_sizer_main->Add(m_panel_body, 1, wxALL | wxEXPAND, FromDIP(24)); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10)); + m_sizer_main->Add(m_static_ams_settings, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(24)); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10)); + m_sizer_main->Add(m_panel_body, 1, wxBottom | wxLEFT | wxRIGHT | wxEXPAND, FromDIP(24)); this->SetSizer(m_sizer_main); this->Layout(); @@ -245,18 +250,34 @@ void AMSSetting::create() }); } -void AMSSetting::update_insert_material_read_mode(bool selected) +void AMSSetting::update_insert_material_read_mode(bool selected, std::string version) { - m_checkbox_Insert_material_auto_read->SetValue(selected); - if (selected) { - m_tip_Insert_material_line1->Show(); - m_tip_Insert_material_line2->Show(); - m_tip_Insert_material_line3->Hide(); - } else { + if (!version.empty() && version >= AMS_F1_SUPPORT_INSERTION_UPDATE_DEFAULT) { + m_checkbox_Insert_material_auto_read->SetValue(true); + m_checkbox_Insert_material_auto_read->Hide(); + m_title_Insert_material_auto_read->Hide(); m_tip_Insert_material_line1->Hide(); m_tip_Insert_material_line2->Hide(); - m_tip_Insert_material_line3->Show(); + m_tip_Insert_material_line3->Hide(); + m_panel_Insert_material->Hide(); } + else { + m_panel_Insert_material->Show(); + m_checkbox_Insert_material_auto_read->SetValue(selected); + m_checkbox_Insert_material_auto_read->Show(); + m_title_Insert_material_auto_read->Show(); + if (selected) { + m_tip_Insert_material_line1->Show(); + m_tip_Insert_material_line2->Show(); + m_tip_Insert_material_line3->Hide(); + } + else { + m_tip_Insert_material_line1->Hide(); + m_tip_Insert_material_line2->Hide(); + m_tip_Insert_material_line3->Show(); + } + } + m_panel_Insert_material->Layout(); m_sizer_Insert_material_tip_inline->Layout(); Layout(); Fit(); diff --git a/src/slic3r/GUI/AMSSetting.hpp b/src/slic3r/GUI/AMSSetting.hpp index 4fddf47660..f87479f034 100644 --- a/src/slic3r/GUI/AMSSetting.hpp +++ b/src/slic3r/GUI/AMSSetting.hpp @@ -17,6 +17,7 @@ #define AMS_SETTING_GREY200 wxColour(248, 248, 248) #define AMS_SETTING_BODY_WIDTH FromDIP(380) #define AMS_SETTING_BUTTON_SIZE wxSize(FromDIP(150), FromDIP(24)) +#define AMS_F1_SUPPORT_INSERTION_UPDATE_DEFAULT std::string("00.00.07.89") namespace Slic3r { namespace GUI { @@ -27,7 +28,7 @@ public: ~AMSSetting(); void create(); - void update_insert_material_read_mode(bool selected); + void update_insert_material_read_mode(bool selected, std::string version); void update_ams_img(std::string ams_icon_str); void update_starting_read_mode(bool selected); void update_remain_mode(bool selected); @@ -49,6 +50,7 @@ protected: protected: wxPanel * m_panel_body; + wxPanel* m_panel_Insert_material; CheckBox * m_checkbox_Insert_material_auto_read; wxStaticText *m_title_Insert_material_auto_read; Label* m_tip_Insert_material_line1; diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index 1c4c186816..f1308efec5 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -58,11 +58,13 @@ void MaterialItem::msw_rescale() { m_transparent_mitem = ScalableBitmap(this, "transparent_material_item", FromDIP(32)); } -void MaterialItem::set_ams_info(wxColour col, wxString txt) +void MaterialItem::set_ams_info(wxColour col, wxString txt, int ctype, std::vector cols) { auto need_refresh = false; + if (m_ams_cols != cols) { m_ams_cols = cols; need_refresh = true; } + if (m_ams_ctype != ctype) { m_ams_ctype = ctype; need_refresh = true; } if (m_ams_coloul != col) { m_ams_coloul = col; need_refresh = true;} - if (m_ams_name != txt) {m_ams_name = txt;need_refresh = true;} + if (m_ams_name != txt) { m_ams_name = txt; need_refresh = true; } if (need_refresh) { Refresh();} } @@ -140,14 +142,11 @@ void MaterialItem::render(wxDC &dc) auto mcolor = m_material_coloul; auto acolor = m_ams_coloul; + change_the_opacity(acolor); if (!IsEnabled()) { mcolor = wxColour(0x90, 0x90, 0x90); acolor = wxColour(0x90, 0x90, 0x90); } - else { - mcolor = m_material_coloul; - acolor = m_ams_coloul; - } // materials name dc.SetFont(::Label::Body_13); @@ -183,8 +182,10 @@ void MaterialItem::render(wxDC &dc) void MaterialItem::doRender(wxDC &dc) { + wxSize size = GetSize(); auto mcolor = m_material_coloul; auto acolor = m_ams_coloul; + change_the_opacity(acolor); if (mcolor.Alpha() == 0 || acolor.Alpha() == 0) { dc.DrawBitmap(m_transparent_mitem.bmp(), FromDIP(1), FromDIP(1)); @@ -194,10 +195,6 @@ void MaterialItem::doRender(wxDC &dc) mcolor = wxColour(0x90, 0x90, 0x90); acolor = wxColour(0x90, 0x90, 0x90); } - else { - mcolor = m_material_coloul; - acolor = m_ams_coloul; - } //top dc.SetPen(*wxTRANSPARENT_PEN); @@ -205,18 +202,48 @@ void MaterialItem::doRender(wxDC &dc) dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(18), 5); //bottom - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(wxColour(acolor))); - dc.DrawRoundedRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16), 5); + if (m_ams_cols.size() > 1) { + int left = FromDIP(1); + int gwidth = std::round(MATERIAL_ITEM_REAL_SIZE.x / (m_ams_cols.size() - 1)); + //gradient + if (m_ams_ctype == 0) { + for (int i = 0; i < m_ams_cols.size() - 1; i++) { + auto rect = wxRect(left, FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16)); + dc.GradientFillLinear(rect, m_ams_cols[i], m_ams_cols[i + 1], wxEAST); + left += gwidth; + } + } + else { + int cols_size = m_ams_cols.size(); + for (int i = 0; i < cols_size; i++) { + dc.SetBrush(wxBrush(m_ams_cols[i])); + float x = left + ((float)MATERIAL_ITEM_REAL_SIZE.x) * i / cols_size; + if (i != cols_size - 1) { + dc.DrawRoundedRectangle(x, FromDIP(18), ((float)MATERIAL_ITEM_REAL_SIZE.x) / cols_size + FromDIP(3), FromDIP(16), 3); + } + else { + dc.DrawRoundedRectangle(x, FromDIP(18), ((float)MATERIAL_ITEM_REAL_SIZE.x) / cols_size , FromDIP(16), 3); + } + } + + } + } + else { + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(wxColour(acolor))); + dc.DrawRoundedRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16), 5); + ////middle - ////middle + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(acolor)); + dc.DrawRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8)); + } dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxBrush(mcolor)); dc.DrawRectangle(FromDIP(1), FromDIP(11), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8)); - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(acolor)); - dc.DrawRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8)); + ////border #if __APPLE__ @@ -247,10 +274,10 @@ void MaterialItem::doRender(wxDC &dc) //arrow if ( (acolor.Red() > 160 && acolor.Green() > 160 && acolor.Blue() > 160) && (acolor.Red() < 180 && acolor.Green() < 180 && acolor.Blue() < 180)) { - dc.DrawBitmap(m_arraw_bitmap_white.bmp(), GetSize().x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(7), GetSize().y - m_arraw_bitmap_white.GetBmpSize().y); + dc.DrawBitmap(m_arraw_bitmap_white.bmp(), size.x - m_arraw_bitmap_white.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_white.GetBmpSize().y); } else { - dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), GetSize().x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(7), GetSize().y - m_arraw_bitmap_gray.GetBmpSize().y); + dc.DrawBitmap(m_arraw_bitmap_gray.bmp(), size.x - m_arraw_bitmap_gray.GetBmpSize().x - FromDIP(7), size.y - m_arraw_bitmap_gray.GetBmpSize().y); } @@ -437,6 +464,10 @@ void AmsMapingPopup::update_ams_data(std::map amsList) td.colour = AmsTray::decode_color(tray_data->color); td.name = tray_data->get_display_filament_type(); td.filament_type = tray_data->get_filament_type(); + td.ctype = tray_data->ctype; + for (auto col : tray_data->cols) { + td.material_cols.push_back(AmsTray::decode_color(col)); + } } } @@ -518,7 +549,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector tray_data, wxWindow* m_mapping_item_list.push_back(m_mapping_item); if (tray_data[i].type == NORMAL) { - if (is_match_material(tray_data[i].filament_type)) { + if (is_match_material(tray_data[i].filament_type)) { m_mapping_item->set_data(tray_data[i].colour, tray_data[i].name, tray_data[i]); } else { m_mapping_item->set_data(wxColour(0xEE,0xEE,0xEE), tray_data[i].name, tray_data[i], true); @@ -673,14 +704,38 @@ void MappingItem::set_data(wxColour colour, wxString name, TrayData data, bool u void MappingItem::doRender(wxDC &dc) { - dc.SetPen(m_coloul); - dc.SetBrush(wxBrush(m_coloul)); + wxSize size = GetSize(); + wxColour color = m_coloul; + change_the_opacity(color); - if (m_coloul.Alpha() == 0) { - dc.DrawBitmap( m_transparent_mapping_item.bmp(), 0, (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2); + dc.SetPen(color); + dc.SetBrush(wxBrush(color)); + + if (m_tray_data.material_cols.size() > 1) { + int left = 0; + int gwidth = std::round(MAPPING_ITEM_REAL_SIZE.x / (m_tray_data.material_cols.size() - 1)); + //gradient + if (m_tray_data.ctype == 0) { + for (int i = 0; i < m_tray_data.material_cols.size() - 1; i++) { + auto rect = wxRect(left, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2, MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y); + dc.GradientFillLinear(rect, m_tray_data.material_cols[i], m_tray_data.material_cols[i + 1], wxEAST); + left += gwidth; + } + } + else { + int cols_size = m_tray_data.material_cols.size(); + for (int i = 0; i < cols_size; i++) { + dc.SetBrush(wxBrush(m_tray_data.material_cols[i])); + float x = (float)MAPPING_ITEM_REAL_SIZE.x * i / cols_size; + dc.DrawRectangle(x, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2, (float)MAPPING_ITEM_REAL_SIZE.x / cols_size, MAPPING_ITEM_REAL_SIZE.y); + } + } + } + else if (color.Alpha() == 0) { + dc.DrawBitmap( m_transparent_mapping_item.bmp(), 0, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2); } else { - dc.DrawRectangle(0, (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2, MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y); + dc.DrawRectangle(0, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2, MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y); } @@ -689,11 +744,11 @@ void MappingItem::doRender(wxDC &dc) dc.SetPen(side_colour); dc.SetBrush(wxBrush(side_colour)); #ifdef __APPLE__ - dc.DrawRectangle(0, 0, FromDIP(4), GetSize().y); - dc.DrawRectangle(GetSize().x - FromDIP(4), 0, FromDIP(4), GetSize().y); + dc.DrawRectangle(0, 0, FromDIP(4), size.y); + dc.DrawRectangle(size.x - FromDIP(4), 0, FromDIP(4), size.y); #else - dc.DrawRectangle(0, 0, FromDIP(4), GetSize().y); - dc.DrawRectangle(GetSize().x - FromDIP(4), 0, FromDIP(4), GetSize().y); + dc.DrawRectangle(0, 0, FromDIP(4), size.y); + dc.DrawRectangle(size.x - FromDIP(4), 0, FromDIP(4), size.y); #endif // __APPLE__ } @@ -806,98 +861,52 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent) { SetBackgroundColour(*wxWHITE); - wxBoxSizer* main_sizer; - main_sizer = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + close_img = ScalableBitmap(this, "hum_popup_close", 24); - main_sizer->Add(0, 0, 0, wxTOP, 28); + m_staticText = new Label(this, _L("Current Cabin humidity")); + m_staticText->SetFont(::Label::Head_24); - wxBoxSizer* m_sizer_body; - m_sizer_body = new wxBoxSizer(wxHORIZONTAL); + humidity_level_list = new AmsHumidityLevelList(this); + curr_humidity_img = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("hum_level1_light", this, 132), wxDefaultPosition, wxSize(FromDIP(132), FromDIP(132)), 0); - m_img = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("ams_humidity_tips", this, 125), wxDefaultPosition, wxSize(FromDIP(125), FromDIP(145)), 0); - - m_sizer_body->Add(m_img, 0, wxEXPAND | wxALL, 2); - - - m_sizer_body->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18)); - - wxBoxSizer* m_sizer_tips = new wxBoxSizer(wxVERTICAL); - - m_staticText1 = new Label(this, _L("Cabin humidity")); - m_staticText1->SetFont(::Label::Head_13); + m_staticText_note = new Label(this, _L("Please change the desiccant when it is too wet. The indicator may not represent accurately in following cases : when the lid is open or the desiccant pack is changed. it take hours to absorb the moisture, low temperatures also slow down the process.")); + m_staticText_note->SetMinSize(wxSize(FromDIP(680), -1)); + m_staticText_note->SetMaxSize(wxSize(FromDIP(680), -1)); + m_staticText_note->Wrap(FromDIP(680)); - m_staticText2 = new Label(this, _L("Green means that AMS humidity is normal, orange represent humidity is high, red represent humidity is too high.(Hygrometer: lower the better.)")); - m_staticText2->SetFont(::Label::Body_13); - m_staticText2->SetSize(wxSize(FromDIP(357), -1)); - m_staticText2->SetMinSize(wxSize(FromDIP(357), -1)); - m_staticText2->SetMaxSize(wxSize(FromDIP(357), -1)); - m_staticText2->Wrap(FromDIP(357)); - - - m_staticText3 = new Label(this, _L("Desiccant status")); - m_staticText3->SetFont(::Label::Head_13); - - - m_staticText4 = new Label(this, _L("A desiccant status lower than two bars indicates that desiccant may be inactive. Please change the desiccant.(The bars: higher the better.)")); - m_staticText4->SetFont(::Label::Body_13); - m_staticText4->SetSize(wxSize(FromDIP(357), -1)); - m_staticText4->SetMinSize(wxSize(FromDIP(357), -1)); - m_staticText4->SetMaxSize(wxSize(FromDIP(357), -1)); - m_staticText4->Wrap(FromDIP(357)); - - m_sizer_tips->Add(m_staticText1, 0, wxLEFT|wxRIGHT, 3); - m_sizer_tips->Add(0,0,0,wxTOP,2); - m_sizer_tips->Add(m_staticText2, 0, wxLEFT|wxRIGHT, 3); - m_sizer_tips->Add(0,0,0,wxTOP,8); - m_sizer_tips->Add(m_staticText3, 0, wxLEFT|wxRIGHT, 3); - m_sizer_tips->Add(0,0,0,wxTOP,2); - m_sizer_tips->Add(m_staticText4, 0, wxLEFT|wxRIGHT, 3); - - - m_sizer_body->Add(m_sizer_tips, 0, wxEXPAND, 0); - - - main_sizer->Add(m_sizer_body, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20)); - - m_staticText_note = new Label(this, _L("Note: When the lid is open or the desiccant pack is changed, it can take hours or a night to absorb the moisture. Low temperatures also slow down the process. During this time, the indicator may not represent the chamber accurately.")); - m_staticText4->SetFont(::Label::Body_13); - m_staticText_note->SetMinSize(wxSize(FromDIP(523), -1)); - m_staticText_note->SetMaxSize(wxSize(FromDIP(523), -1)); - m_staticText_note->Wrap(FromDIP(523)); - main_sizer->Add(m_staticText_note, 0, wxALL | wxLEFT | wxRIGHT, 22); - - m_button_confirm = new Button(this, _L("OK")); - StateColor btn_bg_green(std::pair(wxColour(0, 150, 136), StateColor::Pressed), std::pair(wxColour(0, 150, 136), StateColor::Normal)); - m_button_confirm->SetBackgroundColor(btn_bg_green); - m_button_confirm->SetBorderColor(wxColour(0, 150, 136)); - m_button_confirm->SetTextColor(wxColour(0xFFFFFE)); - m_button_confirm->SetSize(wxSize(FromDIP(72), FromDIP(24))); - m_button_confirm->SetMinSize(wxSize(FromDIP(72), FromDIP(24))); - m_button_confirm->SetCornerRadius(FromDIP(12)); - - - m_button_confirm->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { - Dismiss(); - }); - Bind(wxEVT_LEFT_UP, [this](auto& e) { + + auto rect = ClientToScreen(wxPoint(0, 0)); + + auto close_left = rect.x + GetSize().x - close_img.GetBmpWidth() - FromDIP(38); + auto close_right = close_left + close_img.GetBmpWidth(); + auto close_top = rect.y + FromDIP(24); + auto close_bottom = close_top + close_img.GetBmpHeight(); + auto mouse_pos = ClientToScreen(e.GetPosition()); - auto rect = m_button_confirm->ClientToScreen(wxPoint(0, 0)); - if (mouse_pos.x > rect.x && mouse_pos.y > rect.y - && mouse_pos.x < (rect.x + m_button_confirm->GetSize().x) - && mouse_pos.y < (rect.y + m_button_confirm->GetSize().y)) + if (mouse_pos.x > close_left + && mouse_pos.y > close_top + && mouse_pos.x < close_right + && mouse_pos.y < close_bottom + ) { Dismiss(); } - }); - main_sizer->Add(m_button_confirm, 0, wxALIGN_CENTER | wxALL, 0); - - - main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, 18); - + }); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(24)); + main_sizer->Add(m_staticText, 0, wxALIGN_CENTER, 0); + main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(28)); + main_sizer->Add(curr_humidity_img, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(35)); + main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(15)); + main_sizer->Add(humidity_level_list, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(35)); + main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(6)); + main_sizer->Add(m_staticText_note, 0, wxALIGN_CENTER, 0); + main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(5)); + main_sizer->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(25)); SetSizer(main_sizer); Layout(); Fit(); @@ -909,9 +918,7 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent) void AmsHumidityTipPopup::paintEvent(wxPaintEvent& evt) { wxPaintDC dc(this); - dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); + render(dc); } void AmsHumidityTipPopup::OnDismiss() {} @@ -920,6 +927,50 @@ bool AmsHumidityTipPopup::ProcessLeftDown(wxMouseEvent& event) { return PopupWindow::ProcessLeftDown(event); } +void AmsHumidityTipPopup::set_humidity_level(int level) +{ + current_humidity_level = level; + if (current_humidity_level<= 0) {return;} + + std::string mode_string = wxGetApp().dark_mode()?"_dark":"_light"; + + curr_humidity_img->SetBitmap(create_scaled_bitmap("hum_level" + std::to_string(current_humidity_level) + mode_string, this, 132)); + curr_humidity_img->Refresh(); + curr_humidity_img->Update(); +} + +void AmsHumidityTipPopup::render(wxDC& dc) +{ +#ifdef __WXMSW__ + wxSize size = GetSize(); + wxMemoryDC memdc; + wxBitmap bmp(size.x, size.y); + memdc.SelectObject(bmp); + memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 }); + + { + wxGCDC dc2(memdc); + doRender(dc2); + } + + memdc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#else + doRender(dc); +#endif +} + +void AmsHumidityTipPopup::doRender(wxDC& dc) +{ + //close + dc.DrawBitmap(close_img.bmp(), GetSize().x - close_img.GetBmpWidth() - FromDIP(38), FromDIP(24)); + + //background + dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); +} + AmsTutorialPopup::AmsTutorialPopup(wxWindow* parent) :PopupWindow(parent, wxBORDER_NONE) { @@ -1507,7 +1558,11 @@ void AmsRMGroup::doRender(wxDC& dc) int x = size.x / 2; int y = size.y / 2; - int radius = size.x / 2 - FromDIP(2); + int radius; + if (wxGetApp().dark_mode()) + radius = size.x / 2 - int(size.x * 0.02); + else + radius = size.x / 2; endAngle += ev_angle; @@ -1589,4 +1644,90 @@ void AmsRMGroup::doRender(wxDC& dc) dc.DrawText(m_group_index, (size.x - text_size.x) / 2, (size.y - text_size.y) / 2 + FromDIP(10)); } +AmsHumidityLevelList::AmsHumidityLevelList(wxWindow* parent) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) +{ +#ifdef __WINDOWS__ + SetDoubleBuffered(true); +#endif //__WINDOWS__ + + SetSize(wxSize(FromDIP(680), FromDIP(104))); + SetMinSize(wxSize(FromDIP(680), FromDIP(104))); + SetMaxSize(wxSize(FromDIP(680), FromDIP(104))); + SetBackgroundColour(*wxWHITE); + + background_img = ScalableBitmap(this, "humidity_list_background", 104); + + for (int i = 5; i > 0; i--) { + hum_level_img_light.push_back(ScalableBitmap(this, ("hum_level" + std::to_string(i) + "_light"), 54)); + hum_level_img_dark.push_back(ScalableBitmap(this, ("hum_level" + std::to_string(i) + "_dark"), 54)); + } + + Bind(wxEVT_PAINT, &AmsHumidityLevelList::paintEvent, this); + wxGetApp().UpdateDarkUI(this); +} + +void AmsHumidityLevelList::msw_rescale() +{ + +} + +void AmsHumidityLevelList::paintEvent(wxPaintEvent& evt) +{ + wxPaintDC dc(this); + render(dc); +} + +void AmsHumidityLevelList::render(wxDC& dc) +{ +#ifdef __WXMSW__ + wxSize size = GetSize(); + wxMemoryDC memdc; + wxBitmap bmp(size.x, size.y); + memdc.SelectObject(bmp); + memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 }); + + { + wxGCDC dc2(memdc); + doRender(dc2); + } + + memdc.SelectObject(wxNullBitmap); + dc.DrawBitmap(bmp, 0, 0); +#else + doRender(dc); +#endif +} + +void AmsHumidityLevelList::doRender(wxDC& dc) +{ + dc.DrawBitmap(background_img.bmp(), 0,0); + + auto width_center = GetSize().x / 2; + auto left = width_center - FromDIP(27) - FromDIP(46) * 2 - FromDIP(54) * 2; + + + //dry / wet + dc.SetTextForeground(wxColour(0x989898)); + dc.SetFont(::Label::Head_20); + + auto font_top = GetSize().y - dc.GetTextExtent(_L("DRY")).GetHeight(); + dc.DrawText(_L("DRY"), wxPoint(FromDIP(38), font_top / 2)); + dc.DrawText(_L("WET"), wxPoint(( GetSize().x - FromDIP(38) - dc.GetTextExtent(_L("DRY")).GetWidth()), font_top / 2)); + + + //level list + + for (int i = 0; i < hum_level_img_light.size(); i++) { + if (wxGetApp().dark_mode()) { + dc.DrawBitmap(hum_level_img_dark[i].bmp(), left, (GetSize().y - FromDIP(54)) / 2); + } + else { + dc.DrawBitmap(hum_level_img_light[i].bmp(), left, (GetSize().y - FromDIP(54)) / 2); + } + + left += FromDIP(46) + FromDIP(54); + } +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/AmsMappingPopup.hpp b/src/slic3r/GUI/AmsMappingPopup.hpp index acfc8cd3e9..e8e78b2578 100644 --- a/src/slic3r/GUI/AmsMappingPopup.hpp +++ b/src/slic3r/GUI/AmsMappingPopup.hpp @@ -55,9 +55,11 @@ struct TrayData { TrayType type; int id; + int ctype = 0; std::string name; std::string filament_type; wxColour colour; + std::vector material_cols = std::vector(); }; class MaterialItem: public wxPanel @@ -72,6 +74,8 @@ public: wxColour m_ams_coloul; wxString m_ams_name; + int m_ams_ctype = 0; + std::vector m_ams_cols = std::vector(); ScalableBitmap m_arraw_bitmap_gray; ScalableBitmap m_arraw_bitmap_white; @@ -81,7 +85,7 @@ public: bool m_warning{false}; void msw_rescale(); - void set_ams_info(wxColour col, wxString txt); + void set_ams_info(wxColour col, wxString txt, int ctype=0, std::vector cols= std::vector()); void disable(); void enable(); @@ -185,6 +189,33 @@ public: wxStaticText * m_tip_disable_ams; }; +class AmsHumidityLevelList : public wxPanel +{ +public: + AmsHumidityLevelList(wxWindow* parent); + ~AmsHumidityLevelList() {}; + + ScalableBitmap background_img; + ScalableBitmap hum_level1_img; + ScalableBitmap hum_level2_img; + ScalableBitmap hum_level3_img; + ScalableBitmap hum_level4_img; + + std::vector hum_level_img_light; + std::vector hum_level_img_dark; + + wxStaticBitmap* hum_level1_bitmap; + wxStaticBitmap* hum_level2_bitmap; + wxStaticBitmap* hum_level3_bitmap; + wxStaticBitmap* hum_level4_bitmap; + wxStaticBitmap* hum_level5_bitmap; + + void msw_rescale(); + void paintEvent(wxPaintEvent& evt); + void render(wxDC& dc); + void doRender(wxDC& dc); +}; + class AmsHumidityTipPopup : public PopupWindow { public: @@ -195,14 +226,19 @@ public: virtual void OnDismiss() wxOVERRIDE; virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE; + void set_humidity_level(int level); + void render(wxDC& dc); + void doRender(wxDC& dc); + public: + int current_humidity_level; + + ScalableBitmap close_img; + wxStaticBitmap* curr_humidity_img; + AmsHumidityLevelList* humidity_level_list{nullptr}; wxStaticBitmap* m_img; - Label* m_staticText1; - Label* m_staticText2; - Label* m_staticText3; - Label* m_staticText4; + Label* m_staticText;; Label* m_staticText_note; - Button* m_button_confirm; }; class AmsTutorialPopup : public PopupWindow diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 0ae0ef4ce8..b9347b9c1a 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -238,12 +238,13 @@ void BackgroundSlicingProcess::process_fff() //BBS: add plate index into render params m_temp_output_path = this->get_current_plate()->get_tmp_gcode_path(); m_fff_print->export_gcode(m_temp_output_path, m_gcode_result, [this](const ThumbnailsParams& params) { return this->render_thumbnails(params); }); + finalize_gcode(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": export gcode finished"); } if (this->set_step_started(bspsGCodeFinalize)) { if (! m_export_path.empty()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); - finalize_gcode(); + export_gcode(); } else if (! m_upload_job.empty()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); prepare_upload(); @@ -767,44 +768,34 @@ bool BackgroundSlicingProcess::invalidate_all_steps() return m_step_state.invalidate_all([this](){ this->stop_internal(); }); } +//Call post-processing script for the last step during slicing +void BackgroundSlicingProcess::finalize_gcode() +{ + m_print->set_status(95, _utf8(L("Running post-processing scripts"))); + + run_post_process_scripts(m_temp_output_path, false, "File", m_temp_output_path, m_fff_print->full_print_config()); + + m_print->set_status(100, _utf8(L("Successfully executed post-processing script"))); +} + // G-code is generated in m_temp_output_path. // Optionally run a post-processing script on a copy of m_temp_output_path. // Copy the final G-code to target location (possibly a SD card, if it is a removable media, then verify that the file was written without an error). -void BackgroundSlicingProcess::finalize_gcode() +void BackgroundSlicingProcess::export_gcode() { - //BBS: don't support running user-defined post-processing scripts - //m_print->set_status(95, _utf8(L("Running post-processing scripts"))); - // Perform the final post-processing of the export path by applying the print statistics over the file name. std::string export_path = m_fff_print->print_statistics().finalize_output_path(m_export_path); std::string output_path = m_temp_output_path; - // Both output_path and export_path ar in-out parameters. - // If post processed, output_path will differ from m_temp_output_path as run_post_process_scripts() will make a copy of the G-code to not - // collide with the G-code viewer memory mapping of the unprocessed G-code. G-code viewer maps unprocessed G-code, because m_gcode_result - // is calculated for the unprocessed G-code and it references lines in the memory mapped G-code file by line numbers. - // export_path may be changed by the post-processing script as well if the post processing script decides so, see GH #6042. - bool post_processed = run_post_process_scripts(output_path, true, "File", export_path, m_fff_print->full_print_config()); - auto remove_post_processed_temp_file = [post_processed, &output_path]() { - if (post_processed) - try { - boost::filesystem::remove(output_path); - } catch (const std::exception &ex) { - BOOST_LOG_TRIVIAL(error) << "Failed to remove temp file " << output_path << ": " << ex.what(); - } - }; - //FIXME localize the messages std::string error_message; int copy_ret_val = CopyFileResult::SUCCESS; try { copy_ret_val = copy_file(output_path, export_path, error_message, m_export_path_on_removable_media); - remove_post_processed_temp_file(); } catch (...) { - remove_post_processed_temp_file(); throw Slic3r::ExportError(_utf8(L("Unknown error when export G-code."))); } switch (copy_ret_val) { @@ -840,7 +831,6 @@ void BackgroundSlicingProcess::finalize_gcode() // BBS: to be checked. Whether use export_path or output_path. gcode_add_line_number(export_path, m_fff_print->full_print_config()); - m_print->set_status(100, (boost::format(_utf8(L("Succeed to export G-code to %1%"))) % export_path).str()); } // A print host upload job has been scheduled, enqueue it to the printhost job queue diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index b5b8ffcd7a..78e8971869 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -287,6 +287,7 @@ private: // If the background processing stop was requested, throw CanceledException. void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); } void finalize_gcode(); + void export_gcode(); void prepare_upload(); // To be executed at the background thread. ThumbnailsList render_thumbnails(const ThumbnailsParams ¶ms); diff --git a/src/slic3r/GUI/CaliHistoryDialog.cpp b/src/slic3r/GUI/CaliHistoryDialog.cpp index e1d0d8e073..ec3d76ecb9 100644 --- a/src/slic3r/GUI/CaliHistoryDialog.cpp +++ b/src/slic3r/GUI/CaliHistoryDialog.cpp @@ -14,6 +14,7 @@ namespace GUI { #define HISTORY_WINDOW_SIZE wxSize(FromDIP(700), FromDIP(600)) #define EDIT_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(160), FromDIP(24)) +#define NEW_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(250), FromDIP(24)) #define HISTORY_WINDOW_ITEMS_COUNT 5 static const wxString k_tips = "Please input a valid value (K in 0~0.3)"; @@ -71,6 +72,21 @@ HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector& auto scroll_sizer = new wxBoxSizer(wxVERTICAL); scroll_window->SetSizer(scroll_sizer); + Button * mew_btn = new Button(scroll_window, _L("New")); + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(wxColour(0, 174, 66), StateColor::Normal)); + mew_btn->SetBackgroundColour(*wxWHITE); + mew_btn->SetBackgroundColor(btn_bg_green); + mew_btn->SetBorderColor(wxColour(0, 174, 66)); + mew_btn->SetTextColor(wxColour("#FFFFFE")); + mew_btn->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + mew_btn->SetMaxSize(wxSize(FromDIP(100), FromDIP(24))); + mew_btn->SetCornerRadius(FromDIP(12)); + mew_btn->Bind(wxEVT_BUTTON, &HistoryWindow::on_click_new_button, this); + + scroll_sizer->Add(mew_btn, 0, wxLEFT, FromDIP(20)); + scroll_sizer->AddSpacer(FromDIP(15)); + wxPanel* comboBox_panel = new wxPanel(scroll_window); comboBox_panel->SetBackgroundColour(wxColour(238, 238, 238)); auto comboBox_sizer = new wxBoxSizer(wxVERTICAL); @@ -346,6 +362,11 @@ float HistoryWindow::get_nozzle_value() return nozzle_value; } +void HistoryWindow::on_click_new_button(wxCommandEvent& event) +{ + NewCalibrationHistoryDialog dlg(this, m_calib_results_history); + dlg.ShowModal(); +} EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow* parent, const PACalibResult& result) : DPIDialog(parent, wxID_ANY, _L("Edit Flow Dynamics Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) @@ -434,13 +455,9 @@ PACalibResult EditCalibrationHistoryDialog::get_result() { void EditCalibrationHistoryDialog::on_save(wxCommandEvent& event) { wxString name = m_name_value->GetTextCtrl()->GetValue(); - if (name.IsEmpty()) + if (!CalibUtils::validate_input_name(name)) return; - if (name.Length() > 40) { - MessageDialog msg_dlg(nullptr, _L("The name cannot exceed 40 characters."), wxEmptyString, wxICON_WARNING | wxOK); - msg_dlg.ShowModal(); - return; - } + m_new_result.name = m_name_value->GetTextCtrl()->GetValue().ToUTF8().data(); float k = 0.0f; @@ -465,5 +482,255 @@ void EditCalibrationHistoryDialog::on_dpi_changed(const wxRect& suggested_rect) { } +wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject *obj) +{ + PresetBundle *preset_bundle = wxGetApp().preset_bundle; + + wxArrayString filament_items; + std::set filament_id_set; + std::set printer_names; + std::ostringstream stream; + stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter; + std::string nozzle_diameter_str = stream.str(); + + for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) { + // filter by system preset + if (!printer_it->is_system) + continue; + // get printer_model + ConfigOption * printer_model_opt = printer_it->config.option("printer_model"); + ConfigOptionString *printer_model_str = dynamic_cast(printer_model_opt); + if (!printer_model_str) + continue; + + // use printer_model as printer type + if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type)) + continue; + + if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) + printer_names.insert(printer_it->name); + } + + if (preset_bundle) { + BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size(); + for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) { + // filter by system preset + Preset &preset = *filament_it; + /*The situation where the user preset is not displayed is as follows: + 1. Not a root preset + 2. Not system preset and the printer firmware does not support user preset */ + if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && ! obj->is_support_user_preset)) { continue; } + + ConfigOption * printer_opt = filament_it->config.option("compatible_printers"); + ConfigOptionStrings *printer_strs = dynamic_cast(printer_opt); + for (auto printer_str : printer_strs->values) { + if (printer_names.find(printer_str) != printer_names.end()) { + if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) { + continue; + } else { + filament_id_set.insert(filament_it->filament_id); + // name matched + if (filament_it->is_system) { + filament_items.push_back(filament_it->alias); + FilamentInfos filament_infos; + filament_infos.filament_id = filament_it->filament_id; + filament_infos.setting_id = filament_it->setting_id; + map_filament_items[filament_it->alias] = filament_infos; + } else { + char target = '@'; + size_t pos = filament_it->name.find(target); + if (pos != std::string::npos) { + std::string user_preset_alias = filament_it->name.substr(0, pos - 1); + wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8); + user_preset_alias = wx_user_preset_alias.ToStdString(); + + filament_items.push_back(user_preset_alias); + FilamentInfos filament_infos; + filament_infos.filament_id = filament_it->filament_id; + filament_infos.setting_id = filament_it->setting_id; + map_filament_items[user_preset_alias] = filament_infos; + } + } + } + } + } + } + } + return filament_items; +} + +NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const std::vector history_results) + : DPIDialog(parent, wxID_ANY, _L("New Flow Dynamics Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) + , m_history_results(history_results) +{ + Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) + return; + MachineObject *obj = dev->get_selected_machine(); + if (!obj) + return; + + this->SetBackgroundColour(*wxWHITE); + auto main_sizer = new wxBoxSizer(wxVERTICAL); + + auto top_panel = new wxPanel(this); + top_panel->SetBackgroundColour(*wxWHITE); + auto panel_sizer = new wxBoxSizer(wxVERTICAL); + top_panel->SetSizer(panel_sizer); + + auto flex_sizer = new wxFlexGridSizer(0, 2, FromDIP(15), FromDIP(30)); + flex_sizer->SetFlexibleDirection(wxBOTH); + flex_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + + Label *name_title = new Label(top_panel, _L("Name")); + m_name_value = new TextInput(top_panel, "", "", "", wxDefaultPosition, NEW_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER); + + // Name + flex_sizer->Add(name_title); + flex_sizer->Add(m_name_value); + + Label * preset_name_title = new Label(top_panel, _L("Filament")); + m_comboBox_filament = new ::ComboBox(top_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, NEW_HISTORY_DIALOG_INPUT_SIZE, 0, nullptr, wxCB_READONLY); + + wxArrayString filament_items = get_all_filaments(obj); + m_comboBox_filament->Set(filament_items); + m_comboBox_filament->SetSelection(-1); + + // Filament + flex_sizer->Add(preset_name_title); + flex_sizer->Add(m_comboBox_filament); + + Label *nozzle_diameter_title = new Label(top_panel, _L("Nozzle Diameter")); + m_comboBox_nozzle_diameter = new ::ComboBox(top_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, NEW_HISTORY_DIALOG_INPUT_SIZE, 0, nullptr, wxCB_READONLY); + static std::array nozzle_diameter_list = {0.2f, 0.4f, 0.6f, 0.8f}; + for (int i = 0; i < nozzle_diameter_list.size(); i++) { + m_comboBox_nozzle_diameter->AppendString(wxString::Format("%1.1f mm", nozzle_diameter_list[i])); + if (abs(obj->nozzle_diameter - nozzle_diameter_list[i]) < 1e-3) { + m_comboBox_nozzle_diameter->SetSelection(i); + } + } + + // Nozzle Diameter + flex_sizer->Add(nozzle_diameter_title); + flex_sizer->Add(m_comboBox_nozzle_diameter); + + Label *k_title = new Label(top_panel, _L("Factor K")); + auto k_str = wxString::Format("%.3f", m_new_result.k_value); + m_k_value = new TextInput(top_panel, k_str, "", "", wxDefaultPosition, NEW_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER); + + // Factor K + flex_sizer->Add(k_title); + flex_sizer->Add(m_k_value); + + panel_sizer->Add(flex_sizer); + + panel_sizer->AddSpacer(FromDIP(25)); + + auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); + Button * ok_btn = new Button(top_panel, _L("Ok")); + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(wxColour(0, 174, 66), StateColor::Normal)); + ok_btn->SetBackgroundColour(*wxWHITE); + ok_btn->SetBackgroundColor(btn_bg_green); + ok_btn->SetBorderColor(wxColour(0, 174, 66)); + ok_btn->SetTextColor(wxColour("#FFFFFE")); + ok_btn->SetMinSize(wxSize(-1, FromDIP(24))); + ok_btn->SetCornerRadius(FromDIP(12)); + Button *cancel_btn = new Button(top_panel, _L("Cancel")); + cancel_btn->SetBackgroundColour(*wxWHITE); + cancel_btn->SetMinSize(wxSize(-1, FromDIP(24))); + cancel_btn->SetCornerRadius(FromDIP(12)); + ok_btn->Bind(wxEVT_BUTTON, &NewCalibrationHistoryDialog::on_ok, this); + cancel_btn->Bind(wxEVT_BUTTON, &NewCalibrationHistoryDialog::on_cancel, this); + btn_sizer->AddStretchSpacer(); + btn_sizer->Add(ok_btn); + btn_sizer->AddSpacer(FromDIP(20)); + btn_sizer->Add(cancel_btn); + panel_sizer->Add(btn_sizer, 0, wxEXPAND, 0); + + main_sizer->Add(top_panel, 1, wxEXPAND | wxALL, FromDIP(20)); + + SetSizer(main_sizer); + Layout(); + Fit(); + CenterOnParent(); + + wxGetApp().UpdateDlgDarkUI(this); +} + +void NewCalibrationHistoryDialog::on_ok(wxCommandEvent &event) +{ + wxString name = m_name_value->GetTextCtrl()->GetValue(); + if (!CalibUtils::validate_input_name(name)) + return; + + float k = 0.0f; + if (!CalibUtils::validate_input_k_value(m_k_value->GetTextCtrl()->GetValue(), &k)) { + MessageDialog msg_dlg(nullptr, _L(k_tips), wxEmptyString, wxICON_WARNING | wxOK); + msg_dlg.ShowModal(); + return; + } + wxString k_str = wxString::Format("%.3f", k); + m_k_value->GetTextCtrl()->SetValue(k_str); + + double nozzle_value = 0.0; + wxString nozzle_value_str = m_comboBox_nozzle_diameter->GetValue(); + nozzle_value_str.ToDouble(&nozzle_value); + + std::string filament_name = m_comboBox_filament->GetValue().ToStdString(); + if (filament_name.empty()) { + MessageDialog msg_dlg(nullptr, _L("The filament must be selected."), wxEmptyString, wxICON_WARNING | wxOK); + msg_dlg.ShowModal(); + return; + } + + auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()]; + std::string filament_id = filament_item.filament_id; + std::string setting_id = filament_item.setting_id; + + m_new_result.name = name.ToUTF8().data(); + m_new_result.k_value = k; + m_new_result.tray_id = -1; + m_new_result.cali_idx = -1; + + m_new_result.nozzle_diameter = nozzle_value; + m_new_result.filament_id = filament_id; + m_new_result.setting_id = setting_id; + + // Check for duplicate names from history + { + struct PACalibResult + { + size_t operator()(const std::pair &item) const + { + return std::hash()(item.first) * std::hash()(item.second); + } + }; + std::unordered_set, PACalibResult> set; + set.insert({m_new_result.name, m_new_result.filament_id}); + + for (auto &result : m_history_results) { + if (!set.insert({result.name, result.filament_id}).second) { + MessageDialog msg_dlg(nullptr, + wxString::Format(_L("There is already a historical calibration result with the same name: %s. Only one of the results with the same name " + "is saved. Are you sure you want to override the historical result?"), + result.name), + wxEmptyString, wxICON_WARNING | wxYES_NO); + if (msg_dlg.ShowModal() != wxID_YES) + return; + } + } + } + + CalibUtils::set_PA_calib_result({m_new_result}, true); + + EndModal(wxID_OK); +} + +void NewCalibrationHistoryDialog::on_cancel(wxCommandEvent &event) +{ + EndModal(wxID_CANCEL); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/CaliHistoryDialog.hpp b/src/slic3r/GUI/CaliHistoryDialog.hpp index c44d4399e5..94b3a874aa 100644 --- a/src/slic3r/GUI/CaliHistoryDialog.hpp +++ b/src/slic3r/GUI/CaliHistoryDialog.hpp @@ -25,6 +25,8 @@ protected: void enbale_action_buttons(bool enable); float get_nozzle_value(); + void on_click_new_button(wxCommandEvent &event); + wxPanel* m_history_data_panel; ComboBox* m_comboBox_nozzle_dia; Label* m_tips; @@ -55,6 +57,38 @@ protected: TextInput* m_k_value{ nullptr }; }; +class NewCalibrationHistoryDialog : public DPIDialog +{ +public: + NewCalibrationHistoryDialog(wxWindow *parent, const std::vector history_results); + ~NewCalibrationHistoryDialog(){}; + void on_dpi_changed(const wxRect &suggested_rect) override{}; + +protected: + virtual void on_ok(wxCommandEvent &event); + virtual void on_cancel(wxCommandEvent &event); + + + wxArrayString get_all_filaments(const MachineObject *obj); + +protected: + PACalibResult m_new_result; + std::vector m_history_results; + + TextInput *m_name_value{nullptr}; + TextInput *m_k_value{nullptr}; + + ComboBox *m_comboBox_nozzle_diameter; + ComboBox *m_comboBox_filament; + + struct FilamentInfos + { + std::string filament_id; + std::string setting_id; + }; + std::map map_filament_items; +}; + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/CalibrationWizard.cpp b/src/slic3r/GUI/CalibrationWizard.cpp index a96cc93f1d..cbeabeb3cd 100644 --- a/src/slic3r/GUI/CalibrationWizard.cpp +++ b/src/slic3r/GUI/CalibrationWizard.cpp @@ -19,21 +19,6 @@ static const float MIN_PA_K_VALUE = 0.0; static const float MAX_PA_K_VALUE = 0.3; static const float MIN_PA_K_VALUE_STEP = 0.001; -bool check_preset_name_valid(const wxString& name) { - wxString error_message; - if (name.IsEmpty()) { - error_message = _L("Please enter the name you want to save to printer."); - } else if (name.Length() > 40) { - error_message = _L("The name cannot exceed 40 characters."); - } - if (!error_message.IsEmpty()) { - MessageDialog error_msg_dlg(nullptr, error_message, wxEmptyString, wxICON_WARNING | wxOK); - error_msg_dlg.ShowModal(); - return false; - } - return true; -} - std::map get_cached_selected_filament(MachineObject* obj) { std::map selected_filament_map; if (!obj) return selected_filament_map; @@ -90,6 +75,28 @@ CalibrationWizard::CalibrationWizard(wxWindow* parent, CalibMode mode, wxWindowI main_sizer->Fit(this); Bind(EVT_CALIBRATION_JOB_FINISHED, &CalibrationWizard::on_cali_job_finished, this); + +#if !BBL_RELEASE_TO_PUBLIC + this->Bind(wxEVT_CHAR_HOOK, [this](auto& evt) { + const int keyCode = evt.GetKeyCode(); + switch (keyCode) + { + case WXK_PAGEUP: + { + show_step(m_curr_step->prev); + break; + } + case WXK_PAGEDOWN: + { + show_step(m_curr_step->next); + break; + } + default: + evt.Skip(); + break; + } + }); +#endif } CalibrationWizard::~CalibrationWizard() @@ -295,6 +302,7 @@ void CalibrationWizard::recover_preset_info(MachineObject *obj) obj->cali_finished = back_info.cali_finished; obj->cache_flow_ratio = back_info.cache_flow_ratio; obj->selected_cali_preset = back_info.selected_presets; + obj->flow_ratio_calibration_type = back_info.cache_flow_rate_calibration_type; } } } @@ -306,6 +314,7 @@ void CalibrationWizard::back_preset_info(MachineObject *obj, bool cali_finish, b printer_cali_info.cali_finished = cali_finish; printer_cali_info.cache_flow_ratio = obj->cache_flow_ratio; printer_cali_info.selected_presets = obj->selected_cali_preset; + printer_cali_info.cache_flow_rate_calibration_type = obj->flow_ratio_calibration_type; wxGetApp().app_config->save_printer_cali_infos(printer_cali_info, back_cali_flag); } @@ -698,34 +707,44 @@ void PressureAdvanceWizard::on_cali_save() msg_dlg.ShowModal(); } else if (curr_obj->get_printer_series() == PrinterSeries::SERIES_P1P) { - auto save_page = static_cast(save_step->page); - float new_k_value = 0.0f; - float new_n_value = 0.0f; - if (!save_page->get_p1p_result(&new_k_value, &new_n_value)) { - return; - } + if (curr_obj->cali_version >= 0) { + PACalibResult new_pa_cali_result; + auto save_page = static_cast(save_step->page); + if (!save_page->get_manual_result(new_pa_cali_result)) { + return; + } + CalibUtils::set_PA_calib_result({new_pa_cali_result}, false); + } else { + auto save_page = static_cast(save_step->page); + float new_k_value = 0.0f; + float new_n_value = 0.0f; + if (!save_page->get_p1p_result(&new_k_value, &new_n_value)) { + return; + } - float nozzle_dia = 0.4; - BedType plate_type = BedType::btDefault; - CalibrationPresetPage* preset_page = (static_cast(preset_step->page)); - preset_page->get_preset_info(nozzle_dia, plate_type); - std::map selected_filaments = get_cached_selected_filament(curr_obj); - if (selected_filaments.empty()) { - BOOST_LOG_TRIVIAL(error) << "CaliPreset: get selected filaments error"; - return; - } - int tray_id = selected_filaments.begin()->first; - std::string setting_id = selected_filaments.begin()->second->setting_id; + float nozzle_dia = 0.4; + BedType plate_type = BedType::btDefault; + CalibrationPresetPage *preset_page = (static_cast(preset_step->page)); + preset_page->get_preset_info(nozzle_dia, plate_type); + std::map selected_filaments = get_cached_selected_filament(curr_obj); + if (selected_filaments.empty()) { + BOOST_LOG_TRIVIAL(error) << "CaliPreset: get selected filaments error"; + return; + } + int tray_id = selected_filaments.begin()->first; + std::string setting_id = selected_filaments.begin()->second->setting_id; - int nozzle_temp = -1; - int bed_temp = -1; - float max_volumetric_speed = -1; - if (!get_preset_info(selected_filaments.begin()->second->config, plate_type, nozzle_temp, bed_temp, max_volumetric_speed)) { - BOOST_LOG_TRIVIAL(error) << "CaliPreset: get preset info error"; - return; - } + int nozzle_temp = -1; + int bed_temp = -1; + float max_volumetric_speed = -1; + if (!get_preset_info(selected_filaments.begin()->second->config, plate_type, nozzle_temp, bed_temp, max_volumetric_speed)) { + BOOST_LOG_TRIVIAL(error) << "CaliPreset: get preset info error"; + return; + } - curr_obj->command_extrusion_cali_set(tray_id, setting_id, "", new_k_value, new_n_value, bed_temp, nozzle_temp, max_volumetric_speed); + curr_obj->command_extrusion_cali_set(tray_id, setting_id, "", new_k_value, new_n_value, bed_temp, nozzle_temp, max_volumetric_speed); + + } MessageDialog msg_dlg(nullptr, _L("Flow Dynamics Calibration result has been saved to the printer"), wxEmptyString, wxOK); msg_dlg.ShowModal(); @@ -1098,7 +1117,7 @@ void FlowRateWizard::on_cali_save() return; } - if (!check_preset_name_valid(new_preset_name)) + if (!CalibUtils::validate_input_name(new_preset_name)) return; std::string old_preset_name; @@ -1385,7 +1404,7 @@ void MaxVolumetricSpeedWizard::on_cali_save() return; } - if (!check_preset_name_valid(new_preset_name)) + if (!CalibUtils::validate_input_name(new_preset_name)) return; std::map key_value_map; diff --git a/src/slic3r/GUI/CalibrationWizardCaliPage.cpp b/src/slic3r/GUI/CalibrationWizardCaliPage.cpp index 6279cc6048..d412146741 100644 --- a/src/slic3r/GUI/CalibrationWizardCaliPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardCaliPage.cpp @@ -21,6 +21,7 @@ CalibrationCaliPage::CalibrationCaliPage(wxWindow* parent, CalibMode cali_mode, create_page(this); this->SetSizer(m_top_sizer); + Layout(); m_top_sizer->Fit(this); } @@ -63,8 +64,6 @@ void CalibrationCaliPage::create_page(wxWindow* parent) m_printing_panel->get_pause_resume_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CalibrationCaliPage::on_subtask_pause_resume), NULL, this); m_printing_panel->get_abort_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CalibrationCaliPage::on_subtask_abort), NULL, this); - - Layout(); } void CalibrationCaliPage::on_subtask_pause_resume(wxCommandEvent& event) @@ -395,6 +394,7 @@ void CalibrationCaliPage::update_subtask(MachineObject* obj) } this->Layout(); + this->Fit(); } void CalibrationCaliPage::update_basic_print_data(bool def, float weight, int prediction) @@ -424,6 +424,7 @@ void CalibrationCaliPage::reset_printing_values() m_printing_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR)); update_basic_print_data(false); this->Layout(); + this->Fit(); } void CalibrationCaliPage::on_device_connected(MachineObject* obj) diff --git a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp index b428110c75..e6941066c2 100644 --- a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp @@ -35,16 +35,16 @@ void CaliPresetCaliStagePanel::create_panel(wxWindow* parent) m_complete_radioBox = new wxRadioButton(parent, wxID_ANY, _L("Complete Calibration")); m_complete_radioBox->SetForegroundColour(*wxBLACK); + m_complete_radioBox->SetValue(true); m_stage = CALI_MANUAL_STAGE_1; m_top_sizer->Add(m_complete_radioBox); m_top_sizer->AddSpacer(FromDIP(10)); - m_fine_radioBox = new wxRadioButton(parent, wxID_ANY, _L("Fine Calibration based on flow ratio")); m_fine_radioBox->SetForegroundColour(*wxBLACK); m_top_sizer->Add(m_fine_radioBox); - auto input_panel = new wxPanel(parent); + input_panel = new wxPanel(parent); input_panel->Hide(); auto input_sizer = new wxBoxSizer(wxHORIZONTAL); input_panel->SetSizer(input_sizer); @@ -58,15 +58,16 @@ void CaliPresetCaliStagePanel::create_panel(wxWindow* parent) m_top_sizer->Add(input_panel); m_top_sizer->AddSpacer(PRESET_GAP); - // events - m_complete_radioBox->Bind(wxEVT_RADIOBUTTON, [this, input_panel](auto& e) { + m_complete_radioBox->Bind(wxEVT_RADIOBUTTON, [this](auto& e) { + m_stage_panel_parent->get_current_object()->flow_ratio_calibration_type = COMPLETE_CALIBRATION; input_panel->Show(false); m_stage = CALI_MANUAL_STAGE_1; GetParent()->Layout(); GetParent()->Fit(); }); - m_fine_radioBox->Bind(wxEVT_RADIOBUTTON, [this, input_panel](auto& e) { + m_fine_radioBox->Bind(wxEVT_RADIOBUTTON, [this](auto& e) { + m_stage_panel_parent->get_current_object()->flow_ratio_calibration_type = FINE_CALIBRATION; input_panel->Show(); m_stage = CALI_MANUAL_STAGE_2; GetParent()->Layout(); @@ -127,6 +128,21 @@ void CaliPresetCaliStagePanel::set_flow_ratio_value(float flow_ratio) m_flow_ratio_value = flow_ratio; } +void CaliPresetCaliStagePanel::set_flow_ratio_calibration_type(FlowRatioCalibrationType type) { + if (type == COMPLETE_CALIBRATION) { + m_complete_radioBox->SetValue(true); + m_stage = CaliPresetStage::CALI_MANUAL_STAGE_1; + input_panel->Hide(); + } + else if (type == FINE_CALIBRATION) { + m_fine_radioBox->SetValue(true); + m_stage = CaliPresetStage::CALI_MANUAL_STAGE_2; + input_panel->Show(); + } + GetParent()->Layout(); + GetParent()->Fit(); +} + CaliComboBox::CaliComboBox(wxWindow* parent, wxString title, wxArrayString values, @@ -285,7 +301,6 @@ void CaliPresetCustomRangePanel::create_panel(wxWindow* parent) { wxBoxSizer* horiz_sizer; horiz_sizer = new wxBoxSizer(wxHORIZONTAL); - for (size_t i = 0; i < m_input_value_nums; ++i) { if (i > 0) { horiz_sizer->Add(FromDIP(10), 0, 0, wxEXPAND, 0); @@ -299,6 +314,38 @@ void CaliPresetCustomRangePanel::create_panel(wxWindow* parent) item_sizer->Add(m_title_texts[i], 0, wxALL, 0); m_value_inputs[i] = new TextInput(parent, wxEmptyString, _L("\u2103"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, 0); m_value_inputs[i]->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); + m_value_inputs[i]->GetTextCtrl()->Bind(wxEVT_TEXT, [this, i](wxCommandEvent& event) { + std::string number = m_value_inputs[i]->GetTextCtrl()->GetValue().ToStdString(); + std::string decimal_point; + std::string expression = "^[-+]?[0-9]+([,.][0-9]+)?$"; + std::regex decimalRegex(expression); + int decimal_number; + if (std::regex_match(number, decimalRegex)) { + std::smatch match; + if (std::regex_search(number, match, decimalRegex)) { + std::string decimalPart = match[1].str(); + if (decimalPart != "") + decimal_number = decimalPart.length() - 1; + else + decimal_number = 0; + } + int max_decimal_length; + if (i <= 1) + max_decimal_length = 3; + else if (i >= 2) + max_decimal_length = 4; + if (decimal_number > max_decimal_length) { + int allowed_length = number.length() - decimal_number + max_decimal_length; + number = number.substr(0, allowed_length); + m_value_inputs[i]->GetTextCtrl()->SetValue(number); + m_value_inputs[i]->GetTextCtrl()->SetInsertionPointEnd(); + } + } + // input is not a number, invalid. + else + BOOST_LOG_TRIVIAL(trace) << "The K input string is not a valid number when calibrating. "; + + }); item_sizer->Add(m_value_inputs[i], 0, wxALL, 0); horiz_sizer->Add(item_sizer, 0, wxEXPAND, 0); } @@ -390,10 +437,8 @@ void CaliPresetTipsPanel::set_params(int nozzle_temp, int bed_temp, float max_vo wxString text_nozzle_temp = wxString::Format("%d", nozzle_temp); m_nozzle_temp->GetTextCtrl()->SetValue(text_nozzle_temp); - wxString bed_temp_text = wxString::Format("%d", bed_temp); - if (bed_temp == 0) - bed_temp_text = "-"; - m_bed_temp->SetLabel(bed_temp_text + _L(" \u2103")); + std::string bed_temp_text = bed_temp==0 ? "-": std::to_string(bed_temp); + m_bed_temp->SetLabel(wxString::FromUTF8(bed_temp_text + "°C")); wxString flow_val_text = wxString::Format("%0.2f", max_volumetric); m_max_volumetric_speed->GetTextCtrl()->SetValue(flow_val_text); @@ -676,6 +721,7 @@ void CalibrationPresetPage::create_page(wxWindow* parent) m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0); m_cali_stage_panel = new CaliPresetCaliStagePanel(parent); + m_cali_stage_panel->set_parent(this); m_top_sizer->Add(m_cali_stage_panel, 0); m_selection_panel = new wxPanel(parent); @@ -1040,11 +1086,6 @@ void CalibrationPresetPage::update_plate_type_collection(CalibrationMethod metho const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type"); if (bed_type_def && bed_type_def->enum_keys_map) { for (int i = 0; i < bed_type_def->enum_labels.size(); i++) { - if(btDefault + 1 + i == btPTE) { - if (method == CalibrationMethod::CALI_METHOD_AUTO) { - continue; - } - } m_comboBox_bed_type->AppendString(_L(bed_type_def->enum_labels[i])); } m_comboBox_bed_type->SetSelection(0); @@ -1458,6 +1499,8 @@ void CalibrationPresetPage::init_with_machine(MachineObject* obj) { if (!obj) return; + //set flow ratio calibration type + m_cali_stage_panel->set_flow_ratio_calibration_type(obj->flow_ratio_calibration_type); // set nozzle value from machine bool nozzle_is_set = false; for (int i = 0; i < NOZZLE_LIST_COUNT; i++) { @@ -1482,8 +1525,8 @@ void CalibrationPresetPage::init_with_machine(MachineObject* obj) } // set bed type collection from machine - if (m_cali_mode == CalibMode::Calib_PA_Line) - update_plate_type_collection(m_cali_method); + //if (m_cali_mode == CalibMode::Calib_PA_Line) + // update_plate_type_collection(m_cali_method); // init default for filament source // TODO if user change ams/ext, need to update diff --git a/src/slic3r/GUI/CalibrationWizardPresetPage.hpp b/src/slic3r/GUI/CalibrationWizardPresetPage.hpp index 9096c7a34a..4adcd858f3 100644 --- a/src/slic3r/GUI/CalibrationWizardPresetPage.hpp +++ b/src/slic3r/GUI/CalibrationWizardPresetPage.hpp @@ -16,6 +16,8 @@ enum FlowRatioCaliSource { FROM_COARSE_PAGE, }; +class CalibrationPresetPage; + class CaliPresetCaliStagePanel : public wxPanel { public: @@ -30,14 +32,17 @@ public: void get_cali_stage(CaliPresetStage& stage, float& value); void set_flow_ratio_value(float flow_ratio); - + void set_parent(CalibrationPresetPage* parent) { m_stage_panel_parent = parent; } + void set_flow_ratio_calibration_type(FlowRatioCalibrationType type); protected: CaliPresetStage m_stage; wxBoxSizer* m_top_sizer; wxRadioButton* m_complete_radioBox; wxRadioButton* m_fine_radioBox; TextInput * flow_ratio_input; + wxPanel* input_panel; float m_flow_ratio_value; + CalibrationPresetPage* m_stage_panel_parent; }; class CaliComboBox : public wxPanel @@ -162,6 +167,7 @@ public: void stripWhiteSpace(std::string& str); void update_priner_status_msg(wxString msg, bool is_warning); void update(MachineObject* obj) override; + void update_flow_ratio_type(FlowRatioCalibrationType type) { curr_obj->flow_ratio_calibration_type = type; } void on_device_connected(MachineObject* obj) override; @@ -206,7 +212,7 @@ public: CalibMode get_pa_cali_method(); CaliPresetPageStatus get_page_status() { return m_page_status; } - + MachineObject* get_current_object() { return curr_obj; } void msw_rescale() override; void on_sys_color_changed() override; @@ -306,4 +312,4 @@ public: }} // namespace Slic3r::GUI -#endif \ No newline at end of file +#endif diff --git a/src/slic3r/GUI/CalibrationWizardSavePage.cpp b/src/slic3r/GUI/CalibrationWizardSavePage.cpp index 77637bc10d..287fa61361 100644 --- a/src/slic3r/GUI/CalibrationWizardSavePage.cpp +++ b/src/slic3r/GUI/CalibrationWizardSavePage.cpp @@ -552,16 +552,8 @@ bool CaliPASaveManualPanel::get_result(PACalibResult& out_result) { } wxString name = m_save_name_input->GetTextCtrl()->GetValue(); - if (name.IsEmpty()) { - MessageDialog msg_dlg(nullptr, _L("Please enter the name you want to save to printer."), wxEmptyString, wxICON_WARNING | wxOK); - msg_dlg.ShowModal(); + if (!CalibUtils::validate_input_name(name)) return false; - } - else if (name.Length() > 40) { - MessageDialog msg_dlg(nullptr, _L("The name cannot exceed 40 characters."), wxEmptyString, wxICON_WARNING | wxOK); - msg_dlg.ShowModal(); - return false; - } out_result.k_value = k; out_result.name = into_u8(name); @@ -874,11 +866,11 @@ void CalibrationPASavePage::show_panels(CalibrationMethod method, const PrinterS } m_p1p_panel->Show(false); } - else if (printer_ser == PrinterSeries::SERIES_P1P) { + else if (curr_obj->cali_version >= 0) { m_auto_panel->Show(false); - m_manual_panel->Show(false); - m_p1p_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method); - m_p1p_panel->Show(); + m_manual_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method); + m_manual_panel->Show(); + m_p1p_panel->Show(false); } else { m_auto_panel->Show(false); m_manual_panel->Show(false); diff --git a/src/slic3r/GUI/CalibrationWizardStartPage.cpp b/src/slic3r/GUI/CalibrationWizardStartPage.cpp index 3857d0983e..c65ddb72ac 100644 --- a/src/slic3r/GUI/CalibrationWizardStartPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardStartPage.cpp @@ -161,19 +161,24 @@ void CalibrationPAStartPage::on_device_connected(MachineObject* obj) m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false); m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false); } + + // is support auto cali + bool is_support_pa_auto = (obj->home_flag >> 16 & 1) == 1; + if (!is_support_pa_auto) { + m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false); + } } else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P || obj->get_printer_arch() == PrinterArch::ARCH_I3) { - m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false); + if (obj->cali_version >= 0) { + m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, true); + m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false); + } + else + m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false); m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false); m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true); m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false); } - - //is support auto cali - bool is_support_pa_auto = (obj->home_flag >> 16 & 1) == 1; - if (!is_support_pa_auto) { - m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false); - } } void CalibrationPAStartPage::msw_rescale() diff --git a/src/slic3r/GUI/CameraPopup.cpp b/src/slic3r/GUI/CameraPopup.cpp index 08e4801372..6ee0711137 100644 --- a/src/slic3r/GUI/CameraPopup.cpp +++ b/src/slic3r/GUI/CameraPopup.cpp @@ -8,6 +8,7 @@ #include #include #include "GUI_App.hpp" +#include namespace Slic3r { namespace GUI { @@ -65,6 +66,24 @@ CameraPopup::CameraPopup(wxWindow *parent) top_sizer->Add(m_text_vcamera, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); top_sizer->Add(m_switch_vcamera, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5)); +#if !BBL_RELEASE_TO_PUBLIC + m_text_liveview_retry = new wxStaticText(m_panel, wxID_ANY, _L("Liveview Retry")); + m_text_liveview_retry->Wrap(-1); + m_text_liveview_retry->SetFont(Label::Head_14); + m_text_liveview_retry->SetForegroundColour(TEXT_COL); + m_switch_liveview_retry = new SwitchButton(m_panel); + bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false"; + m_switch_liveview_retry->SetValue(auto_retry); + + top_sizer->Add(m_text_liveview_retry, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + top_sizer->Add(m_switch_liveview_retry, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5)); + + m_switch_liveview_retry->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent &e) { + wxGetApp().app_config->set("liveview", "auto_retry", e.IsChecked()); + e.Skip(); + }); +#endif + //resolution m_text_resolution = new wxStaticText(m_panel, wxID_ANY, _L("Resolution")); m_text_resolution->Wrap(-1); diff --git a/src/slic3r/GUI/CameraPopup.hpp b/src/slic3r/GUI/CameraPopup.hpp index 8135f41fa4..dbdb81a9cb 100644 --- a/src/slic3r/GUI/CameraPopup.hpp +++ b/src/slic3r/GUI/CameraPopup.hpp @@ -72,6 +72,8 @@ private: SwitchButton* m_switch_recording; wxStaticText* m_text_vcamera; SwitchButton* m_switch_vcamera; + wxStaticText* m_text_liveview_retry; + SwitchButton* m_switch_liveview_retry; wxStaticText* m_custom_camera_hint; TextInput* m_custom_camera_input; Button* m_custom_camera_input_confirm; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index d9405e76b8..ddc9877cdf 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -56,24 +56,42 @@ void ConfigManipulation::toggle_line(const std::string& opt_key, const bool togg cb_toggle_line(opt_key, toggle); } +void ConfigManipulation::check_nozzle_recommended_temperature_range(DynamicPrintConfig *config) { + if (is_msg_dlg_already_exist) + return; + + int temperature_range_low, temperature_range_high; + if (!get_temperature_range(config, temperature_range_low, temperature_range_high)) return; + + wxString msg_text; + bool need_check = false; + if (temperature_range_low < 190 || temperature_range_high > 300) { + msg_text += _L("The recommended minimum temperature is less than 190 degree or the recommended maximum temperature is greater than 300 degree.\n"); + need_check = true; + } + if (temperature_range_low > temperature_range_high) { + msg_text += _L("The recommended minimum temperature cannot be higher than the recommended maximum temperature.\n"); + need_check = true; + } + if (need_check) { + msg_text += _L("Please check.\n"); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); + is_msg_dlg_already_exist = true; + dialog.ShowModal(); + is_msg_dlg_already_exist = false; + } +} + void ConfigManipulation::check_nozzle_temperature_range(DynamicPrintConfig *config) { if (is_msg_dlg_already_exist) return; - int temperature_range_low = config->has("nozzle_temperature_range_low") ? - config->opt_int("nozzle_temperature_range_low", (unsigned int)0) : - 0; - int temperature_range_high = config->has("nozzle_temperature_range_high") ? - config->opt_int("nozzle_temperature_range_high", (unsigned int)0) : - 0; + int temperature_range_low, temperature_range_high; + if (!get_temperature_range(config, temperature_range_low, temperature_range_high)) return; - if (temperature_range_low != 0 && - temperature_range_high != 0 && - config->has("nozzle_temperature")) { - if (config->opt_int("nozzle_temperature", 0) < temperature_range_low || - config->opt_int("nozzle_temperature", 0) > temperature_range_high) - { + if (config->has("nozzle_temperature")) { + if (config->opt_int("nozzle_temperature", 0) < temperature_range_low || config->opt_int("nozzle_temperature", 0) > temperature_range_high) { wxString msg_text = _(L("Nozzle may be blocked when the temperature is out of recommended range.\n" "Please make sure whether to use the temperature to print.\n\n")); msg_text += wxString::Format(_L("Recommended nozzle temperature of this filament type is [%d, %d] degree centigrade"), temperature_range_low, temperature_range_high); @@ -90,16 +108,10 @@ void ConfigManipulation::check_nozzle_temperature_initial_layer_range(DynamicPri if (is_msg_dlg_already_exist) return; - int temperature_range_low = config->has("nozzle_temperature_range_low") ? - config->opt_int("nozzle_temperature_range_low", (unsigned int)0) : - 0; - int temperature_range_high = config->has("nozzle_temperature_range_high") ? - config->opt_int("nozzle_temperature_range_high", (unsigned int)0) : - 0; + int temperature_range_low, temperature_range_high; + if (!get_temperature_range(config, temperature_range_low, temperature_range_high)) return; - if (temperature_range_low != 0 && - temperature_range_high != 0 && - config->has("nozzle_temperature_initial_layer")) { + if (config->has("nozzle_temperature_initial_layer")) { if (config->opt_int("nozzle_temperature_initial_layer", 0) < temperature_range_low || config->opt_int("nozzle_temperature_initial_layer", 0) > temperature_range_high) { @@ -161,7 +173,7 @@ void ConfigManipulation::check_chamber_temperature(DynamicPrintConfig* config) } } -void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config) +void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config, const bool is_plate_config) { // #ys_FIXME_to_delete //! Temporary workaround for the correct updates of the TextCtrl (like "layer_height"): @@ -171,6 +183,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (is_msg_dlg_already_exist) return; + bool is_object_config = (!is_global_config && !is_plate_config); + // layer_height shouldn't be equal to zero auto layer_height = config->opt_float("layer_height"); auto gpreset = GUI::wxGetApp().preset_bundle->printers.get_edited_preset(); @@ -273,7 +287,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con double sparse_infill_density = config->option("sparse_infill_density")->value; auto timelapse_type = config->opt_enum("timelapse_type"); - if (config->opt_bool("spiral_mode") && + if (!is_plate_config && + config->opt_bool("spiral_mode") && ! (config->opt_int("wall_loops") == 1 && config->opt_int("top_shell_layers") == 0 && sparse_infill_density == 0 && @@ -284,24 +299,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con config->opt_enum("wall_direction") == WallDirection::Auto && config->opt_enum("timelapse_type") == TimelapseType::tlTraditional)) { - wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional.")); - - auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option>("printer_structure"); - if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) { - msg_text += _(L(" But machines with I3 structure will not generate timelapse videos.")); - } - - if (is_global_config) - msg_text += "\n\n" + _(L("Change these settings automatically? \n" - "Yes - Change these settings and enable spiral mode automatically\n" - "No - Give up using spiral mode this time")); - MessageDialog dialog(m_msg_dlg_parent, msg_text, "", - wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); DynamicPrintConfig new_conf = *config; - is_msg_dlg_already_exist = true; - auto answer = dialog.ShowModal(); + auto answer = show_spiral_mode_settings_dialog(is_object_config); bool support = true; - if (!is_global_config || answer == wxID_YES) { + if (answer == wxID_YES) { new_conf.set_key_value("wall_loops", new ConfigOptionInt(1)); new_conf.set_key_value("top_shell_layers", new ConfigOptionInt(0)); new_conf.set_key_value("sparse_infill_density", new ConfigOptionPercent(0)); @@ -843,5 +844,42 @@ void ConfigManipulation::toggle_print_sla_options(DynamicPrintConfig* config) toggle_field("pad_object_connector_penetration", zero_elev); } +int ConfigManipulation::show_spiral_mode_settings_dialog(bool is_object_config) +{ + wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional.")); + auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option>("printer_structure"); + if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) { + msg_text += _(L(" But machines with I3 structure will not generate timelapse videos.")); + } + if (!is_object_config) + msg_text += "\n\n" + _(L("Change these settings automatically? \n" + "Yes - Change these settings and enable spiral mode automatically\n" + "No - Give up using spiral mode this time")); + + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", + wxICON_WARNING | (!is_object_config ? wxYES | wxNO : wxOK)); + is_msg_dlg_already_exist = true; + auto answer = dialog.ShowModal(); + is_msg_dlg_already_exist = false; + if (is_object_config) + answer = wxID_YES; + return answer; +} + +bool ConfigManipulation::get_temperature_range(DynamicPrintConfig *config, int &range_low, int &range_high) +{ + bool range_low_exist = false, range_high_exist = false; + if (config->has("nozzle_temperature_range_low")) { + range_low = config->opt_int("nozzle_temperature_range_low", (unsigned int) 0); + range_low_exist = true; + } + if (config->has("nozzle_temperature_range_high")) { + range_high = config->opt_int("nozzle_temperature_range_high", (unsigned int) 0); + range_high_exist = true; + } + return range_low_exist && range_high_exist; +} + + } // GUI } // Slic3r diff --git a/src/slic3r/GUI/ConfigManipulation.hpp b/src/slic3r/GUI/ConfigManipulation.hpp index da856c416e..fec8d08f4d 100644 --- a/src/slic3r/GUI/ConfigManipulation.hpp +++ b/src/slic3r/GUI/ConfigManipulation.hpp @@ -69,11 +69,12 @@ public: void toggle_line(const std::string& field_key, const bool toggle); // FFF print - void update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config = false); + void update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config = false, const bool is_plate_config = false); void toggle_print_fff_options(DynamicPrintConfig* config, const bool is_global_config = false); void apply_null_fff_config(DynamicPrintConfig *config, std::vector const &keys, std::map const & configs); //BBS: FFF filament nozzle temperature range + void check_nozzle_recommended_temperature_range(DynamicPrintConfig *config); void check_nozzle_temperature_range(DynamicPrintConfig* config); void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config); void check_filament_max_volumetric_speed(DynamicPrintConfig *config); @@ -89,10 +90,10 @@ public: m_is_initialized_support_material_overhangs_queried = true; m_support_material_overhangs_queried = queried; } + int show_spiral_mode_settings_dialog(bool is_object_config = false); private: - std::vector get_temperature_range_by_filament_type(const std::string &filament_type); - + bool get_temperature_range(DynamicPrintConfig *config, int &range_low, int &range_high); }; } // GUI diff --git a/src/slic3r/GUI/CreatePresetsDialog.cpp b/src/slic3r/GUI/CreatePresetsDialog.cpp index 91a0a62108..85bee59d5f 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.cpp +++ b/src/slic3r/GUI/CreatePresetsDialog.cpp @@ -46,17 +46,6 @@ static const std::vector filament_types = {"PLA", "PLA+", "PLA "PETGCF", "PTBA", "PTBA90A", "PEEK", "TPU93A", "TPU75D", "TPU", "TPU92A", "TPU98A", "Misc", "TPE", "GLAZE", "Nylon", "CPE", "METAL", "ABST", "Carbon Fiber"}; -static const std::vector system_filament_types = {"PLA", "ABS", "TPU", "PC", "ASA", "PA-CF", "PA6-CF", "PET-CF", "PETG", "PETG-CF", - "PLA Aero", "PLA-CF", "PPA-CF", "PPA-GF", "PA", "HIPS", "PPS", "PPS-CF", "PVA"}; - -static std::unordered_map system_filament_types_map = {{"PLA", "PLA"}, {"ABS", "ABS"}, {"TPU", "TPU"}, - {"PC", "PC"}, {"ASA", "ASA"}, {"PA-CF", "PA-CF"}, - {"PA6-CF", "PA6-CF"}, {"PET-CF", "PET-CF"}, {"PETG", "PETG"}, - {"PETG-CF", "PETG-CF"}, {"PLA Aero", "PLA-AERO"}, {"PLA-CF", "PLA-CF"}, - {"PPA-CF", "PPA-CF"}, {"PPA-GF", "PPA-GF"}, {"PA", "PA"}, - {"HIPS", "HIPS"}, {"PPS", "PPS"}, {"PPS-CF", "PPS-CF"}, - {"PVA", "PVA"}}; - static const std::vector printer_vendors = {"Anycubic", "Artillery", "BIBO", "BIQU", "Creality ENDER", "Creality CR", "Creality SERMOON", "FLSun", "gCreate", "Geeetech", "INAT", "Infinity3D", "Jubilee", "LNL3D", "LulzBot", "MakerGear", "Original Prusa", "Papapiu", "Print4Taste", "RatRig", "Rigid3D", @@ -520,6 +509,20 @@ static char* read_json_file(const std::string &preset_path) return json_contents; } +static std::string get_printer_nozzle_diameter(std::string printer_name) { + + size_t index = printer_name.find(" nozzle"); + if (std::string::npos == index) { + return ""; + } + std::string nozzle = printer_name.substr(0, index); + size_t last_space_index = nozzle.find_last_of(" "); + if (std::string::npos == index) { + return ""; + } + return nozzle.substr(last_space_index + 1); +} + static void adjust_dialog_in_screen(DPIDialog* dialog) { wxSize screen_size = wxGetDisplaySize(); int pos_x, pos_y, size_x, size_y, screen_width, screen_height, dialog_x, dialog_y; @@ -547,6 +550,7 @@ CreateFilamentPresetDialog::CreateFilamentPresetDialog(wxWindow *parent) { m_create_type.base_filament = _L("Create Based on Current Filament"); m_create_type.base_filament_preset = _L("Copy Current Filament Preset "); + get_all_filament_presets(); this->SetBackgroundColour(*wxWHITE); this->SetSize(wxSize(FromDIP(600), FromDIP(480))); @@ -595,7 +599,6 @@ CreateFilamentPresetDialog::CreateFilamentPresetDialog(wxWindow *parent) m_main_sizer->Add(m_scrolled_preset_panel, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(10)); m_main_sizer->Add(create_button_item(), 0, wxEXPAND | wxALL, FromDIP(10)); - get_all_filament_presets(); get_all_visible_printer_name(); select_curr_radiobox(m_create_type_btns, 0); @@ -748,7 +751,7 @@ wxBoxSizer *CreateFilamentPresetDialog::create_type_item() horizontal_sizer->Add(optionSizer, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); wxArrayString filament_type; - for (const wxString &filament : system_filament_types) { + for (const wxString &filament : m_system_filament_types_set) { filament_type.Add(filament); } @@ -851,13 +854,13 @@ wxBoxSizer *CreateFilamentPresetDialog::create_filament_preset_item() continue; } for (std::string &compatible_printer_name : compatible_printers->values) { - if (m_visible_printers.find(compatible_printer_name) == m_visible_printers.end()) continue; - size_t index = compatible_printer_name.find("nozzle"); - if (index < 4) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " compatible printer name encounter exception and name is: " << compatible_printer_name; + if (m_visible_printers.find(compatible_printer_name) == m_visible_printers.end()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "there is a comppatible printer no exist: " << compatible_printer_name + << "and the preset name is: " << preset->name; continue; } - if (nozzle_diameter[compatible_printer_name.substr(index - 4, 3)] == 0) { + std::string nozzle = get_printer_nozzle_diameter(compatible_printer_name); + if (nozzle_diameter[nozzle] == 0) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " compatible printer nozzle encounter exception and name is: " << compatible_printer_name; continue; } @@ -1005,11 +1008,21 @@ wxBoxSizer *CreateFilamentPresetDialog::create_button_item() return; } - std::string filament_preset_name = vendor_name + " " + type_name + " " + serial_name; + std::string filament_preset_name = vendor_name + " " + (type_name == "PLA-AERO" ? "PLA Aero" : type_name) + " " + serial_name; + PresetBundle *preset_bundle = wxGetApp().preset_bundle; + if (preset_bundle->filaments.is_alias_exist(filament_preset_name)) { + MessageDialog dlg(this, + wxString::Format(_L("The Filament name %s you created already exists. \nIf you continue creating, the preset created will be displayed with its " + "full name. Do you want to continue?"), + from_u8(filament_preset_name)), + wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Info"), wxYES_NO | wxYES_DEFAULT | wxCENTRE); + if (wxID_YES != dlg.ShowModal()) { return; } + } + std::string user_filament_id = get_filament_id(filament_preset_name); const wxString &curr_create_type = curr_create_filament_type(); - PresetBundle * preset_bundle = wxGetApp().preset_bundle; + if (curr_create_type == m_create_type.base_filament) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":clone filament create type filament "; for (const std::pair<::CheckBox *, std::pair> &checkbox_preset : m_filament_preset) { @@ -1106,10 +1119,14 @@ wxArrayString CreateFilamentPresetDialog::get_filament_preset_choices() for (std::pair filament_presets : m_all_presets_map) { Preset *preset = filament_presets.second; auto inherit = preset->config.option("inherits"); - if (inherit && !inherit->value.empty()) continue; + if (inherit && !inherit->value.empty()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " inherit user preset is:" << preset->name << " and inherits is: " << inherit->value; + continue; + } auto fila_type = preset->config.option("filament_type"); - if (!fila_type || fila_type->values.empty() || system_filament_types_map[type_name] != fila_type->values[0]) continue; + if (!fila_type || fila_type->values.empty() || type_name != fila_type->values[0]) continue; m_filament_choice_map[preset->filament_id].push_back(preset); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " base user preset is:" << preset->name; } int suffix = 0; @@ -1119,10 +1136,10 @@ wxArrayString CreateFilamentPresetDialog::get_filament_preset_choices() for (Preset* filament_preset : preset.second) { std::string preset_name = filament_preset->name; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " filament_id: " << filament_preset->filament_id << " preset name: " << filament_preset->name; - size_t index_at = preset_name.find("@"); + size_t index_at = preset_name.find(" @"); if (std::string::npos != index_at) { - std::string cur_preset_name = preset_name.substr(0, index_at - 1); - preset_name_set.insert(wxString::FromUTF8(cur_preset_name)); + std::string cur_preset_name = preset_name.substr(0, index_at); + preset_name_set.insert(from_u8(cur_preset_name)); } } assert(1 == preset_name_set.size()); @@ -1261,12 +1278,8 @@ void CreateFilamentPresetDialog::get_filament_presets_by_machine() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " preset type is not selected type and preset name is: " << preset->name; continue; } - size_t index = compatible_printer_name.find("nozzle"); - if (index < 4) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " compatible printer name encounter exception and name is: " << compatible_printer_name; - continue; - } - if (nozzle_diameter[compatible_printer_name.substr(index - 4, 3)] == 0) { + std::string nozzle = get_printer_nozzle_diameter(compatible_printer_name); + if (nozzle_diameter[nozzle] == 0) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " compatible printer nozzle encounter exception and name is: " << compatible_printer_name; continue; } @@ -1310,8 +1323,11 @@ void CreateFilamentPresetDialog::get_all_filament_presets() const std::deque &temp_filament_presets = preset_bundle->filaments.get_presets(); for (const Preset& preset : temp_filament_presets) { if (preset.filament_id.empty() || "null" == preset.filament_id) continue; - std::string filament_preset_name = preset.name; + auto filament_type = preset.config.option("filament_type"); + if (filament_type && filament_type->values.size()) + m_system_filament_types_set.insert(filament_type->values[0]); if (!preset.is_visible) continue; + std::string filament_preset_name = preset.name; Preset *filament_preset = new Preset(preset); m_all_presets_map[filament_preset_name] = filament_preset; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " loaded preset name is: " << filament_preset->name; @@ -1352,14 +1368,18 @@ void CreateFilamentPresetDialog::sort_printer_by_nozzle(std::vector nozzle_diameter = nozzle_diameter_map; std::sort(printer_name_to_filament_preset.begin(), printer_name_to_filament_preset.end(), [&nozzle_diameter](const std::pair &a, const std::pair &b) { - size_t nozzle_index_a = a.first.find("nozzle"); - size_t nozzle_index_b = b.first.find("nozzle"); + size_t nozzle_index_a = a.first.find(" nozzle"); + size_t nozzle_index_b = b.first.find(" nozzle"); if (nozzle_index_a == std::string::npos || nozzle_index_b == std::string::npos) return a.first < b.first; std::string nozzle_str_a; std::string nozzle_str_b; try { - nozzle_str_a = a.first.substr(nozzle_index_a - 4, 3); - nozzle_str_b = b.first.substr(nozzle_index_b - 4, 3); + nozzle_str_a = a.first.substr(0, nozzle_index_a); + nozzle_str_b = b.first.substr(0, nozzle_index_b); + size_t last_space_index = nozzle_str_a.find_last_of(" "); + nozzle_str_a = nozzle_str_a.substr(last_space_index + 1); + last_space_index = nozzle_str_b.find_last_of(" "); + nozzle_str_b = nozzle_str_b.substr(last_space_index + 1); } catch (...) { BOOST_LOG_TRIVIAL(info) << "substr filed, and printer name is: " << a.first << " and " << b.first; return a.first < b.first; @@ -2854,6 +2874,8 @@ bool CreatePrinterPresetDialog::data_init() void CreatePrinterPresetDialog::set_current_visible_printer() { + //The entire process of creating a custom printer only needs to be done once + if (m_printer_name_to_preset.size() > 0) return; PresetBundle *preset_bundle = wxGetApp().preset_bundle; const std::deque &printer_presets = preset_bundle->printers.get_presets(); wxArrayString printer_choice; @@ -2861,7 +2883,7 @@ void CreatePrinterPresetDialog::set_current_visible_printer() for (const Preset &printer_preset : printer_presets) { if (printer_preset.is_system || !printer_preset.is_visible) continue; if (preset_bundle->printers.get_preset_base(printer_preset)->name != printer_preset.name) continue; - printer_choice.push_back(wxString::FromUTF8(printer_preset.name)); + printer_choice.push_back(from_u8(printer_preset.name)); m_printer_name_to_preset[printer_preset.name] = std::make_shared(printer_preset); } m_select_printer->Set(printer_choice); @@ -3189,6 +3211,7 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con wxBoxSizer *success_text_sizer = new wxBoxSizer(wxVERTICAL); wxStaticText *success_text; wxStaticText *next_step_text; + bool sync_user_preset_need_enabled = wxGetApp().getAgent() && wxGetApp().app_config->get("sync_user_preset") == "false"; switch (create_success_type) { case PRINTER: success_text = new wxStaticText(this, wxID_ANY, _L("Printer Created")); @@ -3196,11 +3219,14 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con break; case FILAMENT: success_text = new wxStaticText(this, wxID_ANY, _L("Filament Created")); - next_step_text = new wxStaticText(this, wxID_ANY, _L("Please go to filament setting to edit your presets if you need.\nPlease note that nozzle temperature, hot bed temperature, and maximum volumetric speed have a significant impact on printing quality. Please set them carefully.")); + wxString prompt_text = _L("Please go to filament setting to edit your presets if you need.\nPlease note that nozzle temperature, hot bed temperature, and maximum " + "volumetric speed has a significant impact on printing quality. Please set them carefully."); + wxString sync_text = sync_user_preset_need_enabled ? _L("\n\nStudio has detected that your user presets synchronization function is not enabled, which may result in unsuccessful Filament settings on " + "the Device page. \nClick \"Sync user presets\" to enable the synchronization function.") : ""; + next_step_text = new wxStaticText(this, wxID_ANY, prompt_text + sync_text); break; } success_text->SetFont(Label::Head_18); - //next_step_text->SetFont(Label::Body_14); success_text_sizer->Add(success_text, 0, wxEXPAND, 0); success_text_sizer->Add(next_step_text, 0, wxEXPAND | wxTOP, FromDIP(5)); horizontal_sizer->Add(success_text_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); @@ -3214,8 +3240,7 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con case PRINTER: m_button_ok = new Button(this, _L("Printer Setting")); break; - case FILAMENT: - m_button_ok = new Button(this, _L("OK")); + case FILAMENT: m_button_ok = sync_user_preset_need_enabled ? new Button(this, _L("Sync user presets")) : new Button(this, _L("OK")); break; } StateColor btn_bg_green(std::pair(wxColour(0, 137, 123), StateColor::Pressed), std::pair(wxColour(38, 166, 154), StateColor::Hovered), @@ -3232,9 +3257,15 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con m_button_ok->SetCornerRadius(FromDIP(12)); btn_sizer->Add(m_button_ok, 0, wxRIGHT, FromDIP(10)); - m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_OK); }); + m_button_ok->Bind(wxEVT_LEFT_DOWN, [this, sync_user_preset_need_enabled](wxMouseEvent &e) { + if (sync_user_preset_need_enabled) { + wxGetApp().app_config->set("sync_user_preset", "true"); + wxGetApp().start_sync_user_preset(); + } + EndModal(wxID_OK); + }); - if (PRINTER == create_success_type) { + if (PRINTER == create_success_type || sync_user_preset_need_enabled) { m_button_cancel = new Button(this, _L("Cancel")); m_button_cancel->SetBackgroundColor(btn_bg_white); m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); @@ -3339,6 +3370,10 @@ ExportConfigsDialog::~ExportConfigsDialog() } } } + + // Delete the Temp folder + boost::filesystem::path temp_folder(data_dir() + "/" + PRESET_USER_DIR + "/" + "Temp"); + if (boost::filesystem::exists(temp_folder)) boost::filesystem::remove_all(temp_folder); } void ExportConfigsDialog::on_dpi_changed(const wxRect &suggested_rect) { @@ -3394,6 +3429,26 @@ bool ExportConfigsDialog::has_check_box_selected() return false; } +bool ExportConfigsDialog::earse_preset_fields_for_safe(Preset *preset) +{ + if (preset->type != Preset::Type::TYPE_PRINTER) return true; + + boost::filesystem::path file_path(data_dir() + "/" + PRESET_USER_DIR + "/" + "Temp" + "/" + (preset->name + ".json")); + preset->file = file_path.make_preferred().string(); + + DynamicPrintConfig &config = preset->config; + config.erase("print_host"); + config.erase("print_host_webui"); + config.erase("printhost_apikey"); + config.erase("printhost_cafile"); + config.erase("printhost_user"); + config.erase("printhost_password"); + config.erase("printhost_port"); + + preset->save(nullptr); + return true; +} + std::string ExportConfigsDialog::initial_file_path(const wxString &path, const std::string &sub_file_path) { std::string export_path = into_u8(path); @@ -3655,11 +3710,15 @@ ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_preset_bundle_to_fi std::string printer_preset_name_ = printer_preset->name; json bundle_structure; + NetworkAgent *agent = wxGetApp().getAgent(); std::string clock = get_curr_timestmp(); - bundle_structure["user_name"] = ""; - bundle_structure["user_id"] = ""; - bundle_structure["version"] = SoftFever_VERSION; - bundle_structure["bundle_id"] = printer_preset_name_ + "_" + clock; + if (agent) { + bundle_structure["version"] = agent->get_version(); + bundle_structure["bundle_id"] = agent->get_user_id() + "_" + printer_preset_name_ + "_" + clock; + } else { + bundle_structure["version"] = ""; + bundle_structure["bundle_id"] = "offline_" + printer_preset_name_ + "_" + clock; + } bundle_structure["bundle_type"] = "printer config bundle"; bundle_structure["printer_preset_name"] = printer_preset_name_; json printer_config = json::array(); @@ -3770,11 +3829,15 @@ ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_filament_bundle_to_ std::string filament_name = checkbox_filament_name.second; json bundle_structure; + NetworkAgent *agent = wxGetApp().getAgent(); std::string clock = get_curr_timestmp(); - bundle_structure["user_name"] = ""; - bundle_structure["user_id"] = ""; - bundle_structure["version"] = SoftFever_VERSION; - bundle_structure["bundle_id"] = filament_name + "_" + clock; + if (agent) { + bundle_structure["version"] = agent->get_version(); + bundle_structure["bundle_id"] = agent->get_user_id() + "_" + filament_name + "_" + clock; + } else { + bundle_structure["version"] = ""; + bundle_structure["bundle_id"] = "offline_" + filament_name + "_" + clock; + } bundle_structure["bundle_type"] = "filament config bundle"; bundle_structure["filament_name"] = filament_name; std::unordered_map vendor_structure; @@ -4068,19 +4131,45 @@ wxBoxSizer *ExportConfigsDialog::create_select_printer(wxWindow *parent) void ExportConfigsDialog::data_init() { + // Delete the Temp folder + boost::filesystem::path folder(data_dir() + "/" + PRESET_USER_DIR + "/" + "Temp"); + if (boost::filesystem::exists(folder)) boost::filesystem::remove_all(folder); + + boost::system::error_code ec; + boost::filesystem::path user_folder(data_dir() + "/" + PRESET_USER_DIR); + bool temp_folder_exist = true; + if (!boost::filesystem::exists(user_folder)) { + if (!boost::filesystem::create_directories(user_folder, ec)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << user_folder << " "< & printer_presets = preset_bundle.printers.get_presets(); for (const Preset &printer_preset : printer_presets) { std::string preset_name = printer_preset.name; - if (!printer_preset.is_visible || "Default Printer" == preset_name) continue; + if (!printer_preset.is_visible || printer_preset.is_default || printer_preset.is_project_embedded) continue; if (preset_bundle.printers.select_preset_by_name(preset_name, false)) { preset_bundle.update_compatible(PresetSelectCompatibleType::Always); const std::deque &filament_presets = preset_bundle.filaments.get_presets(); for (const Preset &filament_preset : filament_presets) { - if (filament_preset.is_system || filament_preset.is_default) continue; + if (filament_preset.is_system || filament_preset.is_default || filament_preset.is_project_embedded) continue; if (filament_preset.is_compatible) { Preset *new_filament_preset = new Preset(filament_preset); m_filament_presets[preset_name].push_back(new_filament_preset); @@ -4089,7 +4178,7 @@ void ExportConfigsDialog::data_init() const std::deque &process_presets = preset_bundle.prints.get_presets(); for (const Preset &process_preset : process_presets) { - if (process_preset.is_system || process_preset.is_default) continue; + if (process_preset.is_system || process_preset.is_default || process_preset.is_project_embedded) continue; if (process_preset.is_compatible) { Preset *new_prpcess_preset = new Preset(process_preset); m_process_presets[preset_name].push_back(new_prpcess_preset); @@ -4097,6 +4186,7 @@ void ExportConfigsDialog::data_init() } Preset *new_printer_preset = new Preset(printer_preset); + earse_preset_fields_for_safe(new_printer_preset); m_printer_presets[preset_name] = new_printer_preset; } } @@ -4159,9 +4249,10 @@ EditFilamentPresetDialog::EditFilamentPresetDialog(wxWindow *parent, FilamentInf if (vendor_names && !vendor_names->values.empty()) m_vendor_name = vendor_names->values[0]; auto filament_types = dynamic_cast(preset->config.option("filament_type")); if (filament_types && !filament_types->values.empty()) m_filament_type = filament_types->values[0]; - size_t index = m_filament_name.find(m_filament_type); - if (std::string::npos != index && index + m_filament_type.size() < m_filament_name.size()) { - m_filament_serial = m_filament_name.substr(index + m_filament_type.size()); + std::string filament_type = m_filament_type == "PLA-AERO" ? "PLA Aero" : m_filament_type; + size_t index = m_filament_name.find(filament_type); + if (std::string::npos != index && index + filament_type.size() < m_filament_name.size()) { + m_filament_serial = m_filament_name.substr(index + filament_type.size()); if (m_filament_serial.size() > 2 && m_filament_serial[0] == ' ') { m_filament_serial = m_filament_serial.substr(1); } @@ -4639,8 +4730,7 @@ void CreatePresetForPrinterDialog::get_visible_printer_and_compatible_filament_p if (filament_types && filament_types->values.empty()) continue; const std::string filament_type = filament_types->values[0]; - std::string filament_type_ = system_filament_types_map[m_filament_type]; - if (filament_type_.empty()) filament_type_ = m_filament_type; + std::string filament_type_ = m_filament_type == "PLA Aero" ? "PLA-AERO" : m_filament_type; if (filament_type == filament_type_) { m_printer_compatible_filament_presets[printer_preset.name].push_back(std::make_shared(filament_preset)); } diff --git a/src/slic3r/GUI/CreatePresetsDialog.hpp b/src/slic3r/GUI/CreatePresetsDialog.hpp index 9c79bc71f3..911caca5e1 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.hpp +++ b/src/slic3r/GUI/CreatePresetsDialog.hpp @@ -70,12 +70,13 @@ private: std::unordered_map> m_filament_choice_map; std::unordered_map m_public_name_to_filament_id_map; std::unordered_map m_all_presets_map; + std::unordered_set m_system_filament_types_set; std::set m_visible_printers; CreateType m_create_type; Button * m_button_create = nullptr; Button * m_button_cancel = nullptr; ComboBox * m_filament_vendor_combobox = nullptr; - ::CheckBox * m_can_not_find_vendor_checkbox = nullptr; + ::CheckBox * m_can_not_find_vendor_checkbox = nullptr; ComboBox * m_filament_type_combobox = nullptr; ComboBox * m_exist_vendor_combobox = nullptr; ComboBox * m_filament_preset_combobox = nullptr; @@ -262,6 +263,7 @@ private: void on_dpi_changed(const wxRect &suggested_rect) override; void show_export_result(const ExportCase &export_case); bool has_check_box_selected(); + bool earse_preset_fields_for_safe(Preset *preset); std::string initial_file_path(const wxString &path, const std::string &sub_file_path); std::string initial_file_name(const wxString &path, const std::string file_name); wxBoxSizer *create_export_config_item(wxWindow *parent); @@ -314,7 +316,6 @@ private: std::string m_filament_vendor; std::string m_filament_type; std::shared_ptr m_preset_bundle; - std::string m_filamnt_type; ComboBox * m_selected_printer = nullptr; ComboBox * m_selected_filament = nullptr; Button * m_ok_btn = nullptr; diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index f3ffa85bdc..b9a6b758b6 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -807,7 +807,9 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std info.color = tray->second->color; info.type = tray->second->get_filament_type(); info.id = tray_index; - info.filament_id=tray->second->setting_id; + info.filament_id = tray->second->setting_id; + info.ctype = tray->second->ctype; + info.colors = tray->second->cols; tray_filaments.emplace(std::make_pair(tray_index, info)); } } @@ -824,6 +826,8 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std info.tray_id = atoi(tray_it->first.c_str()) + atoi(it->first.c_str()) * 4; info.color = tray_it->second->color; info.type = tray_it->second->get_filament_type(); + info.ctype = tray_it->second->ctype; + info.colors = tray_it->second->cols; } else { info.id = -1; @@ -857,6 +861,9 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std if (filaments[i].type == tray_it->second->get_filament_type()) { info.color = tray_it->second->color; info.type = tray_it->second->get_filament_type(); + info.ctype = tray_it->second->ctype; + std::vector cols; + info.colors = tray_it->second->cols; } else { info.tray_id = -1; info.mapping_result = (int)MappingResult::MAPPING_RESULT_TYPE_MISMATCH; @@ -944,7 +951,8 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std picked_src_idx = i; picked_tar_idx = j; } - else if (min_val == distance_map[i][j].distance && filaments[i].filament_id == tray_filaments[j].filament_id) { + else if (min_val == distance_map[i][j].distance&& filaments[picked_src_idx].filament_id!= tray_filaments[picked_tar_idx].filament_id && filaments[i].filament_id == tray_filaments[j].filament_id) { + picked_src_idx = i; picked_tar_idx = j; } @@ -959,6 +967,8 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std result[picked_src_idx].type = tray->second.type; result[picked_src_idx].distance = tray->second.distance; result[picked_src_idx].filament_id = tray->second.filament_id; + result[picked_src_idx].ctype = tray->second.ctype; + result[picked_src_idx].colors = tray->second.colors; } else { FilamentInfo info; @@ -998,6 +1008,8 @@ int MachineObject::ams_filament_mapping(std::vector filaments, std result[i].tray_id = tray_info_list[i].tray_id; result[i].color = tray_info_list[i].color; result[i].type = tray_info_list[i].type; + result[i].ctype = tray_info_list[i].ctype; + result[i].colors = tray_info_list[i].colors; } } } @@ -1132,24 +1144,26 @@ MachineObject::LIGHT_EFFECT MachineObject::light_effect_parse(std::string effect std::string MachineObject::get_firmware_type_str() { - if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) + /*if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) return "engineer"; else if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) - return "product"; + return "product";*/ - // return engineer by default; - return "engineer"; + // return product by default; + // always return product, printer do not push this field + return "product"; } std::string MachineObject::get_lifecycle_type_str() { - if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) + /*if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) return "engineer"; else if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) - return "product"; + return "product";*/ - // return engineer by default; - return "engineer"; + // return product by default; + // always return product, printer do not push this field + return "product"; } bool MachineObject::is_in_upgrading() @@ -1806,7 +1820,7 @@ int MachineObject::command_ams_calibrate(int ams_id) int MachineObject::command_ams_filament_settings(int ams_id, int tray_id, std::string filament_id, std::string setting_id, std::string tray_color, std::string tray_type, int nozzle_temp_min, int nozzle_temp_max) { BOOST_LOG_TRIVIAL(info) << "command_ams_filament_settings, ams_id = " << ams_id << ", tray_id = " << tray_id << ", tray_color = " << tray_color - << ", tray_type = " << tray_type << ", setting_id = " << setting_id; + << ", tray_type = " << tray_type << ", setting_id = " << setting_id << ", temp_min: = " << nozzle_temp_min << ", temp_max: = " << nozzle_temp_max; json j; j["print"]["command"] = "ams_filament_setting"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -1869,6 +1883,7 @@ int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, i int MachineObject::command_set_printer_nozzle(std::string nozzle_type, float diameter) { + nozzle_setting_hold_count = HOLD_COUNT_MAX * 2; BOOST_LOG_TRIVIAL(info) << "command_set_printer_nozzle, nozzle_type = " << nozzle_type << " diameter = " << diameter; json j; j["system"]["command"] = "set_accessories"; @@ -2069,33 +2084,45 @@ int MachineObject::command_start_pa_calibration(const X1CCalibInfos &pa_data, in CNumericLocalesSetter locales_setter; pa_calib_results.clear(); - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "extrusion_cali"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_data.calib_datas[0].nozzle_diameter); - j["print"]["mode"] = mode; + json j; + j["print"]["command"] = "extrusion_cali"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_data.calib_datas[0].nozzle_diameter); + j["print"]["mode"] = mode; - for (int i = 0; i < pa_data.calib_datas.size(); ++i) { - j["print"]["filaments"][i]["tray_id"] = pa_data.calib_datas[i].tray_id; - j["print"]["filaments"][i]["bed_temp"] = pa_data.calib_datas[i].bed_temp; - j["print"]["filaments"][i]["filament_id"] = pa_data.calib_datas[i].filament_id; - j["print"]["filaments"][i]["setting_id"] = pa_data.calib_datas[i].setting_id; - j["print"]["filaments"][i]["nozzle_temp"] = pa_data.calib_datas[i].nozzle_temp; - j["print"]["filaments"][i]["max_volumetric_speed"] = std::to_string(pa_data.calib_datas[i].max_volumetric_speed); - } + std::string filament_ids; + for (int i = 0; i < pa_data.calib_datas.size(); ++i) { + j["print"]["filaments"][i]["tray_id"] = pa_data.calib_datas[i].tray_id; + j["print"]["filaments"][i]["bed_temp"] = pa_data.calib_datas[i].bed_temp; + j["print"]["filaments"][i]["filament_id"] = pa_data.calib_datas[i].filament_id; + j["print"]["filaments"][i]["setting_id"] = pa_data.calib_datas[i].setting_id; + j["print"]["filaments"][i]["nozzle_temp"] = pa_data.calib_datas[i].nozzle_temp; + j["print"]["filaments"][i]["max_volumetric_speed"] = std::to_string(pa_data.calib_datas[i].max_volumetric_speed); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: " << j.dump(); - return this->publish_json(j.dump()); + if (i > 0) filament_ids += ","; + filament_ids += pa_data.calib_datas[i].filament_id; } - return -1; + + BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: " << j.dump(); + + try { + json js; + js["cali_type"] = "cali_pa_auto"; + js["nozzle_diameter"] = pa_data.calib_datas[0].nozzle_diameter; + js["filament_id"] = filament_ids; + js["printer_type"] = this->printer_type; + NetworkAgent *agent = GUI::wxGetApp().getAgent(); + if (agent) agent->track_event("cali", js.dump()); + } catch (...) {} + + return this->publish_json(j.dump()); } int MachineObject::command_set_pa_calibration(const std::vector &pa_calib_values, bool is_auto_cali) { CNumericLocalesSetter locales_setter; - if (get_printer_series() == PrinterSeries::SERIES_X1 && pa_calib_values.size() > 0) { + if (pa_calib_values.size() > 0) { json j; j["print"]["command"] = "extrusion_cali_set"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2126,73 +2153,61 @@ int MachineObject::command_set_pa_calibration(const std::vector & int MachineObject::command_delete_pa_calibration(const PACalibIndexInfo& pa_calib) { - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "extrusion_cali_del"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["filament_id"] = pa_calib.filament_id; - j["print"]["cali_idx"] = pa_calib.cali_idx; - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib.nozzle_diameter); + json j; + j["print"]["command"] = "extrusion_cali_del"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["filament_id"] = pa_calib.filament_id; + j["print"]["cali_idx"] = pa_calib.cali_idx; + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib.nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_del: " << j.dump(); - return this->publish_json(j.dump()); - } - return -1; + BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_del: " << j.dump(); + return this->publish_json(j.dump()); } int MachineObject::command_get_pa_calibration_tab(float nozzle_diameter, const std::string &filament_id) { reset_pa_cali_history_result(); - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "extrusion_cali_get"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["filament_id"] = filament_id; - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); + json j; + j["print"]["command"] = "extrusion_cali_get"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["filament_id"] = filament_id; + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_get: " << j.dump(); - return this->publish_json(j.dump()); - } - return -1; + BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_get: " << j.dump(); + return this->publish_json(j.dump()); } int MachineObject::command_get_pa_calibration_result(float nozzle_diameter) { - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "extrusion_cali_get_result"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); + json j; + j["print"]["command"] = "extrusion_cali_get_result"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_get_result: " << j.dump(); - return this->publish_json(j.dump()); - } - return -1; + BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_get_result: " << j.dump(); + return this->publish_json(j.dump()); } int MachineObject::commnad_select_pa_calibration(const PACalibIndexInfo& pa_calib_info) { - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "extrusion_cali_sel"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["tray_id"] = pa_calib_info.tray_id; - j["print"]["cali_idx"] = pa_calib_info.cali_idx; - j["print"]["filament_id"] = pa_calib_info.filament_id; - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib_info.nozzle_diameter); + json j; + j["print"]["command"] = "extrusion_cali_sel"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["tray_id"] = pa_calib_info.tray_id; + j["print"]["cali_idx"] = pa_calib_info.cali_idx; + j["print"]["filament_id"] = pa_calib_info.filament_id; + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib_info.nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_sel: " << j.dump(); - return this->publish_json(j.dump()); - } - return -1; + BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_sel: " << j.dump(); + return this->publish_json(j.dump()); } int MachineObject::command_start_flow_ratio_calibration(const X1CCalibInfos& calib_data) { CNumericLocalesSetter locales_setter; - if (get_printer_series() == PrinterSeries::SERIES_X1 && calib_data.calib_datas.size() > 0) { + if (calib_data.calib_datas.size() > 0) { json j; j["print"]["command"] = "flowrate_cali"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2217,16 +2232,13 @@ int MachineObject::command_start_flow_ratio_calibration(const X1CCalibInfos& cal int MachineObject::command_get_flow_ratio_calibration_result(float nozzle_diameter) { - if (get_printer_series() == PrinterSeries::SERIES_X1) { - json j; - j["print"]["command"] = "flowrate_get_result"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); + json j; + j["print"]["command"] = "flowrate_get_result"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "flowrate_get_result: " << j.dump(); - return this->publish_json(j.dump()); - } - return -1; + BOOST_LOG_TRIVIAL(trace) << "flowrate_get_result: " << j.dump(); + return this->publish_json(j.dump()); } int MachineObject::command_ipcam_record(bool on_off) @@ -2678,6 +2690,7 @@ int MachineObject::parse_json(std::string payload) std::string access_code = j_pre["system"]["access_code"].get(); if (!access_code.empty()) { set_access_code(access_code); + set_user_access_code(access_code); } } } @@ -2690,6 +2703,8 @@ int MachineObject::parse_json(std::string payload) uint64_t t_utc = j.value("t_utc", 0ULL); if (t_utc > 0) last_utc_time = std::chrono::system_clock::time_point(t_utc * 1ms); + else + last_utc_time = last_update_time; BOOST_LOG_TRIVIAL(trace) << "parse_json: dev_id=" << dev_id << ", playload=" << j.dump(4); @@ -3341,14 +3356,21 @@ int MachineObject::parse_json(std::string payload) ; } #pragma endregion - try { if (jj.contains("nozzle_diameter")) { - if (jj["nozzle_diameter"].is_number_float()) { - nozzle_diameter = jj["nozzle_diameter"].get(); - } else if (jj["nozzle_diameter"].is_string()) { - nozzle_diameter = string_to_float(jj["nozzle_diameter"].get()); + + if (nozzle_setting_hold_count > 0) { + nozzle_setting_hold_count--; + } else { + if (jj["nozzle_diameter"].is_number_float()) { + nozzle_diameter = jj["nozzle_diameter"].get(); + } + else if (jj["nozzle_diameter"].is_string()) { + nozzle_diameter = string_to_float(jj["nozzle_diameter"].get()); + } } + + } } catch(...) { @@ -3357,8 +3379,14 @@ int MachineObject::parse_json(std::string payload) try { if (jj.contains("nozzle_type")) { - if (jj["nozzle_type"].is_string()) { - nozzle_type = jj["nozzle_type"].get(); + + if (nozzle_setting_hold_count > 0) { + nozzle_setting_hold_count--; + } + else { + if (jj["nozzle_type"].is_string()) { + nozzle_type = jj["nozzle_type"].get(); + } } } } @@ -3513,8 +3541,8 @@ int MachineObject::parse_json(std::string payload) camera_resolution_supported.swap(resolution_supported); } if (ipcam.contains("liveview")) { - char const *local_protos[] = { "none", "local", "rtsps", "rtsp" }; - liveview_local = enum_index_of(ipcam["liveview"].value("local", "none").c_str(), local_protos, 4, LiveviewLocal::LVL_None); + char const *local_protos[] = {"none", "disabled", "local", "rtsps", "rtsp"}; + liveview_local = enum_index_of(ipcam["liveview"].value("local", "none").c_str(), local_protos, 5, LiveviewLocal::LVL_None); liveview_remote = ipcam["liveview"].value("remote", "disabled") == "enabled"; } if (ipcam.contains("file")) { @@ -3526,7 +3554,7 @@ int MachineObject::parse_json(std::string payload) if (ipcam.contains("rtsp_url")) { local_rtsp_url = ipcam["rtsp_url"].get(); liveview_local = local_rtsp_url.empty() ? LVL_None : local_rtsp_url == "disable" - ? LVL_None : boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? LVL_Rtsps : LVL_Rtsp; + ? LVL_Disable : boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? LVL_Rtsps : LVL_Rtsp; } if (ipcam.contains("tutk_server")) { tutk_state = ipcam["tutk_server"].get(); @@ -3620,11 +3648,19 @@ int MachineObject::parse_json(std::string payload) if (jj.contains("cali_version")) { cali_version = jj["cali_version"].get(); } + else { + cali_version = -1; + } std::string str = jj.dump(); } catch (...) { ; } + PresetBundle *preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle; + std::map> filament_list = preset_bundle->filaments.get_filament_presets(); + std::ostringstream stream; + stream << std::fixed << std::setprecision(1) << nozzle_diameter; + std::string nozzle_diameter_str = stream.str(); if (jj.contains("ams")) { if (jj["ams"].contains("ams")) { @@ -3701,6 +3737,7 @@ int MachineObject::parse_json(std::string payload) json j_ams = jj["ams"]["ams"]; std::set ams_id_set; + for (auto it = amsList.begin(); it != amsList.end(); it++) { ams_id_set.insert(it->first); } @@ -3785,6 +3822,17 @@ int MachineObject::parse_json(std::string payload) } else { curr_tray->type = type; } + if (filament_list.find(curr_tray->setting_id) == filament_list.end()) { + wxColour color = *wxWHITE; + char col_buf[10]; + sprintf(col_buf, "%02X%02X%02XFF", (int) color.Red(), (int) color.Green(), (int) color.Blue()); + try { + this->command_ams_filament_settings(std::stoi(ams_id), std::stoi(tray_id), "", "", std::string(col_buf), "", 0, 0); + continue; + } catch (...) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " stoi error and ams_id: " << ams_id << " tray_id" << tray_id; + } + } } else { curr_tray->setting_id = ""; curr_tray->type = ""; @@ -3817,14 +3865,37 @@ int MachineObject::parse_json(std::string payload) curr_tray->bed_temp = (*tray_it)["bed_temp"].get(); else curr_tray->bed_temp = ""; - if (tray_it->contains("nozzle_temp_max")) + if (tray_it->contains("tray_color")) { + auto color = (*tray_it)["tray_color"].get(); + curr_tray->update_color_from_str(color); + } else { + curr_tray->color = ""; + } + if (tray_it->contains("nozzle_temp_max")) { curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get(); + } else curr_tray->nozzle_temp_max = ""; if (tray_it->contains("nozzle_temp_min")) curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get(); else curr_tray->nozzle_temp_min = ""; + if (curr_tray->nozzle_temp_min != "" && curr_tray->nozzle_temp_max != "") { + try { + std::string preset_setting_id; + bool is_equation = preset_bundle->check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray( + MachineObject::get_preset_printer_model_name(this->printer_type), nozzle_diameter_str, curr_tray->setting_id, + curr_tray->tag_uid, curr_tray->nozzle_temp_min, curr_tray->nozzle_temp_max, preset_setting_id); + if (!is_equation) { + command_ams_filament_settings(std::stoi(ams_id), std::stoi(tray_id), curr_tray->setting_id, preset_setting_id, + curr_tray->color, curr_tray->type, + std::stoi(curr_tray->nozzle_temp_min), + std::stoi(curr_tray->nozzle_temp_max)); + } + } catch (...) { + BOOST_LOG_TRIVIAL(info) << "check fail and curr_tray ams_id" << ams_id << " curr_tray tray_id"<contains("xcam_info")) curr_tray->xcam_info = (*tray_it)["xcam_info"].get(); else @@ -3833,12 +3904,6 @@ int MachineObject::parse_json(std::string payload) curr_tray->uuid = (*tray_it)["tray_uuid"].get(); else curr_tray->uuid = "0"; - if (tray_it->contains("tray_color")) { - auto color = (*tray_it)["tray_color"].get(); - curr_tray->update_color_from_str(color); - } else { - curr_tray->color = ""; - } if (tray_it->contains("ctype")) curr_tray->ctype = (*tray_it)["ctype"].get(); @@ -3952,6 +4017,17 @@ int MachineObject::parse_json(std::string payload) else { vt_tray.type = type; } + if (filament_list.find(vt_tray.setting_id) == filament_list.end()) { + wxColour color = *wxWHITE; + char col_buf[10]; + sprintf(col_buf, "%02X%02X%02XFF", (int) color.Red(), (int) color.Green(), (int) color.Blue()); + try { + BOOST_LOG_TRIVIAL(info) << "no filament_id in filament_list and reset vt_tray and the filament_id is: " << vt_tray.setting_id; + this->command_ams_filament_settings(255, std::stoi(vt_tray.id), "", "", std::string(col_buf), "", 0, 0); + } catch (...) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " stoi error and tray_id" << vt_tray.id; + } + } } else { vt_tray.setting_id = ""; @@ -3985,6 +4061,12 @@ int MachineObject::parse_json(std::string payload) vt_tray.bed_temp = jj["vt_tray"]["bed_temp"].get(); else vt_tray.bed_temp = ""; + if (jj["vt_tray"].contains("tray_color")) { + auto color = jj["vt_tray"]["tray_color"].get(); + vt_tray.update_color_from_str(color); + } else { + vt_tray.color = ""; + } if (jj["vt_tray"].contains("nozzle_temp_max")) vt_tray.nozzle_temp_max = jj["vt_tray"]["nozzle_temp_max"].get(); else @@ -3993,6 +4075,22 @@ int MachineObject::parse_json(std::string payload) vt_tray.nozzle_temp_min = jj["vt_tray"]["nozzle_temp_min"].get(); else vt_tray.nozzle_temp_min = ""; + if (vt_tray.nozzle_temp_min != "" && vt_tray.nozzle_temp_max != "") { + try { + std::string preset_setting_id; + bool is_equation = preset_bundle->check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray( + MachineObject::get_preset_printer_model_name(this->printer_type), nozzle_diameter_str, vt_tray.setting_id, vt_tray.tag_uid, + vt_tray.nozzle_temp_min, vt_tray.nozzle_temp_max, preset_setting_id); + if (!is_equation) { + command_ams_filament_settings(255, std::stoi(vt_tray.id), vt_tray.setting_id, preset_setting_id, vt_tray.color, vt_tray.type, + std::stoi(vt_tray.nozzle_temp_min), std::stoi(vt_tray.nozzle_temp_max)); + } + } + catch(...) { + BOOST_LOG_TRIVIAL(info) << "check fail and vt_tray.id" << vt_tray.id; + } + + } if (jj["vt_tray"].contains("xcam_info")) vt_tray.xcam_info = jj["vt_tray"]["xcam_info"].get(); else @@ -4001,13 +4099,6 @@ int MachineObject::parse_json(std::string payload) vt_tray.uuid = jj["vt_tray"]["tray_uuid"].get(); else vt_tray.uuid = "0"; - if (jj["vt_tray"].contains("tray_color")) { - auto color = jj["vt_tray"]["tray_color"].get(); - vt_tray.update_color_from_str(color); - } - else { - vt_tray.color = ""; - } if (jj["vt_tray"].contains("cali_idx")) vt_tray.cali_idx = jj["vt_tray"]["cali_idx"].get(); @@ -5450,7 +5541,7 @@ std::vector DeviceManager::get_resolution_supported(std::string typ std::vector resolution_supported; std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json"; - std::ifstream json_file(config_file.c_str()); + boost::nowide::ifstream json_file(config_file.c_str()); try { json jj; if (json_file.is_open()) { @@ -5472,7 +5563,7 @@ std::vector DeviceManager::get_compatible_machine(std::string type_ { std::vector compatible_machine; std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json"; - std::ifstream json_file(config_file.c_str()); + boost::nowide::ifstream json_file(config_file.c_str()); try { json jj; if (json_file.is_open()) { @@ -5491,10 +5582,12 @@ std::vector DeviceManager::get_compatible_machine(std::string type_ } -bool DeviceManager::load_filaments_blacklist_config(std::string config_file) +bool DeviceManager::load_filaments_blacklist_config() { filaments_blacklist = json::object(); - std::ifstream json_file(config_file.c_str()); + + std::string config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json"; + boost::nowide::ifstream json_file(config_file.c_str()); try { if (json_file.is_open()) { @@ -5593,4 +5686,10 @@ std::string DeviceManager::load_gcode(std::string type_str, std::string gcode_fi return ""; } +void change_the_opacity(wxColour& colour) +{ + if (colour.Alpha() == 255) { + colour = wxColour(colour.Red(), colour.Green(), colour.Blue(), 254); + } +} } // namespace Slic3r diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 1c3c5881b9..b8e7f3d451 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -133,6 +133,7 @@ enum ManualPaCaliMethod { PA_PATTERN, }; + struct RatingInfo { bool request_successful; int http_code; @@ -289,6 +290,7 @@ public: unsigned reserved; HMSMessageLevel msg_level = HMS_UNKNOWN; int msg_code = 0; + bool already_read = false; bool parse_hms_info(unsigned attr, unsigned code); std::string get_long_error_code(); @@ -622,6 +624,7 @@ public: std::vector selected_cali_preset; float cache_flow_ratio { 0.0 }; bool cali_finished = true; + FlowRatioCalibrationType flow_ratio_calibration_type = FlowRatioCalibrationType::COMPLETE_CALIBRATION; ManualPaCaliMethod manual_pa_cali_method = ManualPaCaliMethod::PA_LINE; bool has_get_pa_calib_tab{ false }; @@ -694,6 +697,7 @@ public: std::string tutk_state; enum LiveviewLocal { LVL_None, + LVL_Disable, LVL_Local, LVL_Rtsps, LVL_Rtsp @@ -704,6 +708,8 @@ public: bool file_model_download{false}; bool virtual_camera{false}; + int nozzle_setting_hold_count = 0; + bool xcam_ai_monitoring{ false }; int xcam_ai_monitoring_hold_count = 0; std::string xcam_ai_monitoring_sensitivity; @@ -1026,11 +1032,13 @@ public: static bool get_printer_is_enclosed(std::string type_str); static std::vector get_resolution_supported(std::string type_str); static std::vector get_compatible_machine(std::string type_str); - static bool load_filaments_blacklist_config(std::string config_file); + static bool load_filaments_blacklist_config(); static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info); static std::string load_gcode(std::string type_str, std::string gcode_file); }; +// change the opacity +void change_the_opacity(wxColour& colour); } // namespace Slic3r #endif // slic3r_DeviceManager_hpp_ diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index aa366e20ec..0cbda20b45 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -82,7 +82,6 @@ wxString get_thumbnails_string(const std::vector& values) return ret_str; } - Field::~Field() { if (m_on_kill_focus) @@ -93,11 +92,6 @@ Field::~Field() m_back_to_initial_value = nullptr; if (m_back_to_sys_value) m_back_to_sys_value = nullptr; - if (getWindow()) { - wxWindow* win = getWindow(); - win->Destroy(); - win = nullptr; - } } void Field::PostInitialize() @@ -133,6 +127,8 @@ void Field::PostInitialize() if (getWindow()) { if (m_opt.readonly) { this->disable(); + } else { + this->enable(); } getWindow()->Bind(wxEVT_KEY_UP, [](wxKeyEvent& evt) { if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) { @@ -161,7 +157,7 @@ void Field::PostInitialize() } evt.Skip(); - }); + }, getWindow()->GetId()); } } @@ -302,6 +298,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true m_value.clear(); break; } + std::string opt_key_without_idx = m_opt_id.substr(0, m_opt_id.find('#')); if (m_opt_id == "filament_flow_ratio") { if (m_value.empty() || boost::any_cast(m_value) != val) { wxString msg_text = format_wxstr(_L("Value %s is out of range, continue?"), str); @@ -318,6 +315,21 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true } } } + else if(m_opt_id == "filament_retraction_distances_when_cut" || opt_key_without_idx == "retraction_distances_when_cut"){ + if (m_value.empty() || boost::any_cast(m_value) != val) { + wxString msg_text = format_wxstr(_L("Value %s is out of range. The valid range is from %d to %d."), str, m_opt.min, m_opt.max); + WarningDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxYES); + if (dialog.ShowModal()) { + if (m_value.empty()) { + if (m_opt.min > val) val = m_opt.min; + if (val > m_opt.max) val = m_opt.max; + } + else + val = boost::any_cast(m_value); + set_value(double_to_string(val), true); + } + } + } else { show_error(m_parent, _L("Value is out of range.")); if (m_opt.min > val) val = m_opt.min; @@ -490,6 +502,101 @@ void Field::sys_color_changed() #endif } +std::vector**> spools; +std::vector*> spools2; + +void switch_window_pools() +{ + for (auto p : spools) { + spools2.push_back(*p); + *p = new std::deque; + } +} + +void release_window_pools() +{ + for (auto p : spools2) { + delete p; + } + spools2.clear(); +} + +template +struct Builder +{ + Builder() + { + pool_ = new std::deque; + spools.push_back(&pool_); + } + + template + T *build(wxWindow * p, Args ...args) + { + if (pool_->empty()) { + auto t = new T(p, args...); + t->SetClientData(pool_); + return t; + } + auto t = dynamic_cast(pool_->front()); + pool_->pop_front(); + t->Reparent(p); + t->Enable(); + t->Show(); + return t; + } + std::deque* pool_; +}; + +struct wxEventFunctorRef +{ + wxEventFunctor * func; +}; + +wxEventFunctor & wxMakeEventFunctor(const int, wxEventFunctorRef func) +{ + return *func.func; +} + +struct myEvtHandler : wxEvtHandler +{ + void UnbindAll() + { + size_t cookie; + for (wxDynamicEventTableEntry *entry = GetFirstDynamicEntry(cookie); + entry; + entry = GetNextDynamicEntry(cookie)) { + // In Field, All Bind has id, but for TextInput, ComboBox, SpinInput, all not + if (entry->m_id != wxID_ANY && entry->m_lastId == wxID_ANY) + Unbind(entry->m_eventType, + wxEventFunctorRef{entry->m_fn}, + entry->m_id, + entry->m_lastId, + entry->m_callbackUserData); + //DoUnbind(entry->m_id, entry->m_lastId, entry->m_eventType, *entry->m_fn, entry->m_callbackUserData); + } + } +}; + +static void unbind_events(wxEvtHandler *h) +{ + static_cast(h)->UnbindAll(); +} + +void free_window(wxWindow *win) +{ + unbind_events(win); + for (auto c : win->GetChildren()) + if (dynamic_cast(c)) + unbind_events(c); + win->Hide(); + if (auto sizer = win->GetContainingSizer()) + sizer->Clear(); + win->Reparent(wxGetApp().mainframe); + if (win->GetClientData()) + reinterpret_cast*>(win->GetClientData())->push_back(win); +} + template bool is_defined_input_value(wxWindow* win, const ConfigOptionType& type) { @@ -554,10 +661,15 @@ void TextCtrl::BUILD() { // BBS: new param ui style // const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/; + static Builder builder1; + static Builder<::TextInput> builder2; auto temp = m_opt.multiline - ? (wxWindow *) new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_MULTILINE) - : new ::TextInput(m_parent, text_value, _L(m_opt.sidetext), "", wxDefaultPosition, size, wxTE_PROCESS_ENTER); + ? (wxWindow*)builder1.build(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE) + : builder2.build(m_parent, "", "", "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); + temp->SetLabel(_L(m_opt.sidetext)); auto text_ctrl = m_opt.multiline ? (wxTextCtrl *)temp : ((TextInput *) temp)->GetTextCtrl(); + text_ctrl->SetLabel(text_value); + temp->SetSize(size); m_combine_side_text = !m_opt.multiline; if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double) text_ctrl->GetSize().GetHeight() / m_em_unit; @@ -620,7 +732,7 @@ void TextCtrl::BUILD() { if (!bEnterPressed) propagate_value(); }), temp->GetId()); -/* + /* // select all text using Ctrl+A temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) { @@ -789,7 +901,8 @@ void CheckBox::BUILD() { m_last_meaningful_value = static_cast(check_value); // BBS: use ::CheckBox - auto temp = new ::CheckBox(m_parent); + static Builder<::CheckBox> builder; + auto temp = builder.build(m_parent); if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); //temp->SetBackgroundColour(*wxWHITE); temp->SetValue(check_value); @@ -908,8 +1021,14 @@ void SpinCtrl::BUILD() { ? 0 : m_opt.min; const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; - auto temp = new SpinInput(m_parent, text_value, _L(m_opt.sidetext), wxDefaultPosition, size, - wxSP_ARROW_KEYS, min_val, max_val, default_value); + static Builder builder; + auto temp = builder.build(m_parent, "", "", wxDefaultPosition, wxDefaultSize, + wxSP_ARROW_KEYS); + temp->SetSize(size); + temp->SetLabel(_L(m_opt.sidetext)); + temp->GetTextCtrl()->SetLabel(text_value); + temp->SetRange(min_val, max_val); + temp->SetValue(default_value); m_combine_side_text = true; #ifdef __WXGTK3__ wxSize best_sz = temp->GetBestSize(); @@ -932,7 +1051,7 @@ void SpinCtrl::BUILD() { } propagate_value(); - })); + }), temp->GetId()); temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { propagate_value(); }), temp->GetId()); @@ -1084,14 +1203,15 @@ void Choice::BUILD() if (m_opt.nullable) m_last_meaningful_value = dynamic_cast(m_opt.default_value.get())->get_at(0); - choice_ctrl* temp; + choice_ctrl * temp; auto dynamic_list = dynamic_lists.find(m_opt.opt_key); if (dynamic_list != dynamic_lists.end()) m_list = dynamic_list->second; if (m_opt.gui_type != ConfigOptionDef::GUIType::undefined && m_opt.gui_type != ConfigOptionDef::GUIType::select_open && m_list == nullptr) { m_is_editable = true; - temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxTE_PROCESS_ENTER); + static Builder builder1; + temp = builder1.build(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxTE_PROCESS_ENTER); } else { #ifdef UNDEIFNED__WXOSX__ // __WXOSX__ // BBS @@ -1103,9 +1223,12 @@ void Choice::BUILD() temp->SetTextCtrlStyle(wxTE_READONLY); temp->Create(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr); #else - temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY); + static Builder builder2; + temp = builder2.build(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY); #endif //__WXOSX__ } + temp->SetSize(size); + temp->Clear(); temp->GetDropDown().SetUseContentWidth(true); if (parent_is_custom_ctrl && m_opt.height < 0) opt_height = (double) temp->GetTextCtrl()->GetSize().GetHeight() / m_em_unit; @@ -1158,9 +1281,9 @@ void Choice::BUILD() e.StopPropagation(); else e.Skip(); - }); - temp->Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_is_dropped = true; }); - temp->Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_is_dropped = false; }); + }, temp->GetId()); + temp->Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_is_dropped = true; }, temp->GetId()); + temp->Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_is_dropped = false; }, temp->GetId()); temp->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { on_change_field(); }, temp->GetId()); @@ -1169,12 +1292,12 @@ void Choice::BUILD() e.Skip(); if (!bEnterPressed) propagate_value(); - } ); + }, temp->GetId() ); temp->Bind(wxEVT_TEXT_ENTER, [this](wxEvent& e) { EnterPressed enter(this); propagate_value(); - } ); + }, temp->GetId() ); } temp->SetToolTip(get_tooltip_text(temp->GetValue())); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index cec2f1e405..1661eb003e 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4080,16 +4080,19 @@ void GCodeViewer::render_all_plates_stats(const std::vectorget("use_inches") == "1"; float window_padding = 4.0f * m_scale; const float icon_size = ImGui::GetTextLineHeight() * 0.7; - std::vector offsets; + std::map offsets; std::map model_volume_of_extruders_all_plates; // map std::map flushed_volume_of_extruders_all_plates; // map std::map wipe_tower_volume_of_extruders_all_plates; // map + std::map support_volume_of_extruders_all_plates; // map std::vector model_used_filaments_m_all_plates; std::vector model_used_filaments_g_all_plates; std::vector flushed_filaments_m_all_plates; std::vector flushed_filaments_g_all_plates; std::vector wipe_tower_used_filaments_m_all_plates; std::vector wipe_tower_used_filaments_g_all_plates; + std::vector support_used_filaments_m_all_plates; + std::vector support_used_filaments_g_all_plates; float total_time_all_plates = 0.0f; float total_cost_all_plates = 0.0f; bool show_detailed_statistics_page = false; @@ -4098,6 +4101,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector(m_time_estimate_mode)]; total_time_all_plates += plate_time_mode.time; @@ -4227,6 +4237,13 @@ void GCodeViewer::render_all_plates_stats(const std::vectorsecond, it->first); + if (support_filament_m != 0.0 || support_filament_g != 0.0) + displayed_columns |= ColumnData::Support; + support_used_filaments_m_all_plates.push_back(support_filament_m); + support_used_filaments_g_all_plates.push_back(support_filament_g); + } char buff[64]; double longest_str = 0.0; @@ -4236,21 +4253,30 @@ void GCodeViewer::render_all_plates_stats(const std::vector>> title_columns; + if (displayed_columns & ColumnData::Model) { + title_columns.push_back({ _u8L("Filament"), {""} }); + title_columns.push_back({ _u8L("Model"), {buff} }); } - else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) { - offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Total"), {buff}} }, icon_size); - append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} }); + if (displayed_columns & ColumnData::Support) { + title_columns.push_back({ _u8L("Support"), {buff} }); } - else { - if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) - displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower); - - offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Tower"), {buff}}, {_u8L("Total"), {buff}} }, icon_size); - append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} }); + if (displayed_columns & ColumnData::Flushed) { + title_columns.push_back({ _u8L("Flushed"), {buff} }); } + if (displayed_columns & ColumnData::WipeTower) { + title_columns.push_back({ _u8L("Tower"), {buff} }); + } + if ((displayed_columns & ~ColumnData::Model) > 0) { + title_columns.push_back({ _u8L("Total"), {buff} }); + } + auto offsets_ = calculate_offsets(title_columns, icon_size); + std::vector> title_offsets; + for (int i = 0; i < offsets_.size(); i++) { + title_offsets.push_back({ title_columns[i].first, offsets_[i] }); + offsets[title_columns[i].first] = offsets_[i]; + } + append_headers(title_offsets); } // item @@ -4259,39 +4285,43 @@ void GCodeViewer::render_all_plates_stats(const std::vector> columns_offsets; - columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] }); + columns_offsets.push_back({ std::to_string(it->first + 1), offsets[_u8L("Filament")]}); char buf[64]; double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0; - if (displayed_columns == ColumnData::Model) { - char buf[64]; - ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); + + float column_sum_m = 0.0f; + float column_sum_g = 0.0f; + if (displayed_columns & ColumnData::Model) { + if ((displayed_columns & ~ColumnData::Model) > 0) + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver); + else + ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver); + columns_offsets.push_back({ buf, offsets[_u8L("Model")] }); + column_sum_m += model_used_filaments_m_all_plates[i]; + column_sum_g += model_used_filaments_g_all_plates[i]; } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i]), - (model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); + if (displayed_columns & ColumnData::Support) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", support_used_filaments_m_all_plates[i], support_used_filaments_g_all_plates[i] / unit_conver); + columns_offsets.push_back({ buf, offsets[_u8L("Support")] }); + column_sum_m += support_used_filaments_m_all_plates[i]; + column_sum_g += support_used_filaments_g_all_plates[i]; } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - + if (displayed_columns & ColumnData::Flushed) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - + columns_offsets.push_back({ buf, offsets[_u8L("Flushed")] }); + column_sum_m += flushed_filaments_m_all_plates[i]; + column_sum_g += flushed_filaments_g_all_plates[i]; + } + if (displayed_columns & ColumnData::WipeTower) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", wipe_tower_used_filaments_m_all_plates[i], wipe_tower_used_filaments_g_all_plates[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i] + wipe_tower_used_filaments_m_all_plates[i]), - (model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i] + wipe_tower_used_filaments_g_all_plates[i]) / unit_conver); - columns_offsets.push_back({ buf, offsets[4] }); + columns_offsets.push_back({ buf, offsets[_u8L("Tower")] }); + column_sum_m += wipe_tower_used_filaments_m_all_plates[i]; + column_sum_g += wipe_tower_used_filaments_g_all_plates[i]; + } + if ((displayed_columns & ~ColumnData::Model) > 0) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", column_sum_m, column_sum_g / unit_conver); + columns_offsets.push_back({ buf, offsets[_u8L("Total")] }); } append_item(filament_colors[it->first], columns_offsets); @@ -4686,19 +4716,90 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv std::vector wipe_tower_used_filaments_m; std::vector wipe_tower_used_filaments_g; double total_wipe_tower_used_filament_m = 0, total_wipe_tower_used_filament_g = 0; + std::vector support_used_filaments_m; + std::vector support_used_filaments_g; + double total_support_used_filament_m = 0, total_support_used_filament_g = 0; struct ColumnData { enum { Model = 1, Flushed = 2, WipeTower = 4, + Support = 1 << 3, }; }; int displayed_columns = 0; + std::map color_print_offsets; const PrintStatistics& ps = wxGetApp().plater()->get_partplate_list().get_current_fff_print().print_statistics(); double koef = imperial_units ? GizmoObjectManipulation::in_to_mm : 1000.0; double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1; + // used filament statistics + 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()) { + model_used_filaments_m.push_back(0.0); + model_used_filaments_g.push_back(0.0); + } + else { + double volume = m_print_statistics.volumes_per_extruder.at(extruder_id); + auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id); + model_used_filaments_m.push_back(model_used_filament_m); + model_used_filaments_g.push_back(model_used_filament_g); + total_model_used_filament_m += model_used_filament_m; + total_model_used_filament_g += model_used_filament_g; + displayed_columns |= ColumnData::Model; + } + } + + for (size_t extruder_id : m_extruder_ids) { + if (m_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == m_print_statistics.wipe_tower_volumes_per_extruder.end()) { + wipe_tower_used_filaments_m.push_back(0.0); + wipe_tower_used_filaments_g.push_back(0.0); + } + else { + double volume = m_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id); + auto [wipe_tower_used_filament_m, wipe_tower_used_filament_g] = get_used_filament_from_volume(volume, extruder_id); + wipe_tower_used_filaments_m.push_back(wipe_tower_used_filament_m); + wipe_tower_used_filaments_g.push_back(wipe_tower_used_filament_g); + total_wipe_tower_used_filament_m += wipe_tower_used_filament_m; + total_wipe_tower_used_filament_g += wipe_tower_used_filament_g; + displayed_columns |= ColumnData::WipeTower; + } + } + + for (size_t extruder_id : m_extruder_ids) { + if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) { + flushed_filaments_m.push_back(0.0); + flushed_filaments_g.push_back(0.0); + } + else { + double volume = m_print_statistics.flush_per_filament.at(extruder_id); + auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, extruder_id); + flushed_filaments_m.push_back(flushed_filament_m); + flushed_filaments_g.push_back(flushed_filament_g); + total_flushed_filament_m += flushed_filament_m; + total_flushed_filament_g += flushed_filament_g; + displayed_columns |= ColumnData::Flushed; + } + } + + for (size_t extruder_id : m_extruder_ids) { + if (m_print_statistics.support_volumes_per_extruder.find(extruder_id) == m_print_statistics.support_volumes_per_extruder.end()) { + support_used_filaments_m.push_back(0.0); + support_used_filaments_g.push_back(0.0); + } + else { + double volume = m_print_statistics.support_volumes_per_extruder.at(extruder_id); + auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id); + support_used_filaments_m.push_back(used_filament_m); + support_used_filaments_g.push_back(used_filament_g); + total_support_used_filament_m += used_filament_m; + total_support_used_filament_g += used_filament_g; + displayed_columns |= ColumnData::Support; + } + } + + // extrusion paths section -> title ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); @@ -4776,76 +4877,36 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } case EViewType::ColorPrint: { - 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()) { - model_used_filaments_m.push_back(0.0); - model_used_filaments_g.push_back(0.0); - } - else { - double volume = m_print_statistics.volumes_per_extruder.at(extruder_id); - auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id); - model_used_filaments_m.push_back(model_used_filament_m); - model_used_filaments_g.push_back(model_used_filament_g); - total_model_used_filament_m += model_used_filament_m; - total_model_used_filament_g += model_used_filament_g; - displayed_columns |= ColumnData::Model; - } - } - - for (size_t extruder_id : m_extruder_ids) { - if (m_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == m_print_statistics.wipe_tower_volumes_per_extruder.end()) { - wipe_tower_used_filaments_m.push_back(0.0); - wipe_tower_used_filaments_g.push_back(0.0); - } - else { - double volume = m_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id); - auto [wipe_tower_used_filament_m, wipe_tower_used_filament_g] = get_used_filament_from_volume(volume, extruder_id); - wipe_tower_used_filaments_m.push_back(wipe_tower_used_filament_m); - wipe_tower_used_filaments_g.push_back(wipe_tower_used_filament_g); - total_wipe_tower_used_filament_m += wipe_tower_used_filament_m; - total_wipe_tower_used_filament_g += wipe_tower_used_filament_g; - displayed_columns |= ColumnData::WipeTower; - } - } - - for (size_t extruder_id : m_extruder_ids) { - if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) { - flushed_filaments_m.push_back(0.0); - flushed_filaments_g.push_back(0.0); - } - else { - double volume = m_print_statistics.flush_per_filament.at(extruder_id); - auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, extruder_id); - flushed_filaments_m.push_back(flushed_filament_m); - flushed_filaments_g.push_back(flushed_filament_g); - total_flushed_filament_m += flushed_filament_m; - total_flushed_filament_g += flushed_filament_g; - displayed_columns |= ColumnData::Flushed; - } - } - std::vector total_filaments; char buffer[64]; ::sprintf(buffer, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", ps.total_used_filament / /*1000*/koef, ps.total_weight / unit_conver); total_filaments.push_back(buffer); - if (displayed_columns == ColumnData::Model) { - offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size); - append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]}}); + std::vector>> title_columns; + if (displayed_columns & ColumnData::Model) { + title_columns.push_back({ _u8L("Filament"), {""} }); + title_columns.push_back({ _u8L("Model"), total_filaments }); } - else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) { - offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size); - append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} }); + if (displayed_columns & ColumnData::Support) { + title_columns.push_back({ _u8L("Support"), total_filaments }); } - else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "displayed_columns: " << displayed_columns; - if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) - displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower); - - offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Tower"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size); - append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} }); + if (displayed_columns & ColumnData::Flushed) { + title_columns.push_back({ _u8L("Flushed"), total_filaments }); } + if (displayed_columns & ColumnData::WipeTower) { + title_columns.push_back({ _u8L("Tower"), total_filaments }); + } + if ((displayed_columns & ~ColumnData::Model) > 0) { + title_columns.push_back({ _u8L("Total"), total_filaments }); + } + auto offsets_ = calculate_offsets(title_columns, icon_size); + std::vector> title_offsets; + for (int i = 0; i < offsets_.size(); i++) { + title_offsets.push_back({ title_columns[i].first, offsets_[i] }); + color_print_offsets[title_columns[i].first] = offsets_[i]; + } + append_headers(title_offsets); break; } @@ -4986,40 +5047,42 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv const bool filament_visible = m_tools.m_tool_visibles[extruder_idx]; if (i < model_used_filaments_m.size() && i < model_used_filaments_g.size()) { std::vector> columns_offsets; - columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] }); + columns_offsets.push_back({ std::to_string(extruder_idx + 1), color_print_offsets[_u8L("Filament")]}); char buf[64]; - if (displayed_columns == ColumnData::Model) { - char buf[64]; - ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); + float column_sum_m = 0.0f; + float column_sum_g = 0.0f; + if (displayed_columns & ColumnData::Model) { + if ((displayed_columns & ~ColumnData::Model) > 0) + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver); + else + ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Model")] }); + column_sum_m += model_used_filaments_m[i]; + column_sum_g += model_used_filaments_g[i]; } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i]), - (model_used_filaments_g[i] + flushed_filaments_g[i]) / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); + if (displayed_columns & ColumnData::Support) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", support_used_filaments_m[i], support_used_filaments_g[i] / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Support")] }); + column_sum_m += support_used_filaments_m[i]; + column_sum_g += support_used_filaments_g[i]; } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - + if (displayed_columns & ColumnData::Flushed) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Flushed")]}); + column_sum_m += flushed_filaments_m[i]; + column_sum_g += flushed_filaments_g[i]; + } + if (displayed_columns & ColumnData::WipeTower) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", wipe_tower_used_filaments_m[i], wipe_tower_used_filaments_g[i] / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i] + wipe_tower_used_filaments_m[i]), - (model_used_filaments_g[i] + flushed_filaments_g[i] + wipe_tower_used_filaments_g[i]) / unit_conver); - columns_offsets.push_back({ buf, offsets[4] }); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Tower")] }); + column_sum_m += wipe_tower_used_filaments_m[i]; + column_sum_g += wipe_tower_used_filaments_g[i]; + } + if ((displayed_columns & ~ColumnData::Model) > 0) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", column_sum_m, column_sum_g / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Total")] }); } - append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false, filament_visible, [this, extruder_idx]() { m_tools.m_tool_visibles[extruder_idx] = !m_tools.m_tool_visibles[extruder_idx]; @@ -5035,6 +5098,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv if (need_scrollable) ImGui::EndChild(); + // Sum of all rows char buf[64]; if (m_extruder_ids.size() > 1) { // Separator @@ -5045,42 +5109,32 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv window->DrawList->AddLine(separator.Min, ImVec2(separator.Max.x, separator.Min.y), ImGui::GetColorU32(ImGuiCol_Separator)); std::vector> columns_offsets; - columns_offsets.push_back({ _u8L("Total"), offsets[0] }); - if (displayed_columns == ColumnData::Model) { - ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - - append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets); + columns_offsets.push_back({ _u8L("Total"), color_print_offsets[_u8L("Filament")]}); + if (displayed_columns & ColumnData::Model) { + if ((displayed_columns & ~ColumnData::Model) > 0) + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); + else + ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Model")] }); } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - - bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m , (total_model_used_filament_g + total_flushed_filament_g) / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); - - append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets); + if (displayed_columns & ColumnData::Support) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_support_used_filament_m, total_support_used_filament_g / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Support")] }); } - if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) { - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[1] }); - + if (displayed_columns & ColumnData::Flushed) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[2] }); - + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Flushed")] }); + } + if (displayed_columns & ColumnData::WipeTower) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_wipe_tower_used_filament_m, total_wipe_tower_used_filament_g / unit_conver); - columns_offsets.push_back({ buf, offsets[3] }); - - bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m, (total_model_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g) / unit_conver); - columns_offsets.push_back({ buf, offsets[4] }); - - append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Tower")] }); } + if ((displayed_columns & ~ColumnData::Model) > 0) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_support_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m, + (total_model_used_filament_g + total_support_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g) / unit_conver); + columns_offsets.push_back({ buf, color_print_offsets[_u8L("Total")] }); + } + append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets); } //BBS display filament change times @@ -5521,7 +5575,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.title(time_title); - std::string filament_str = _u8L("Filament"); + std::string total_filament_str = _u8L("Total Filament"); + std::string model_filament_str = _u8L("Model Filament"); std::string cost_str = _u8L("Cost"); std::string prepare_str = _u8L("Prepare time"); std::string print_str = _u8L("Model printing time"); @@ -5535,7 +5590,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv max_len += std::max(ImGui::CalcTextSize(cost_str.c_str()).x, std::max(ImGui::CalcTextSize(print_str.c_str()).x, std::max(std::max(ImGui::CalcTextSize(prepare_str.c_str()).x, ImGui::CalcTextSize(total_str.c_str()).x), - ImGui::CalcTextSize(filament_str.c_str()).x))); + std::max(ImGui::CalcTextSize(total_filament_str.c_str()).x, ImGui::CalcTextSize(model_filament_str.c_str()).x)))); else max_len += std::max(ImGui::CalcTextSize(print_str.c_str()).x, (std::max(ImGui::CalcTextSize(prepare_str.c_str()).x, ImGui::CalcTextSize(total_str.c_str()).x))); @@ -5545,24 +5600,34 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv //BBS display filament cost ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); - imgui.text(filament_str + ":"); + imgui.text(total_filament_str + ":"); ImGui::SameLine(max_len); - //BBS: use current plater's print statistics bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; char buf[64]; - ::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", ps.total_used_filament / /*1000*/koef); + ::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", ps.total_used_filament / koef); imgui.text(buf); ImGui::SameLine(); ::sprintf(buf, imperial_units ? " %.2f oz" : " %.2f g", ps.total_weight / unit_conver); imgui.text(buf); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); + imgui.text(model_filament_str + ":"); + ImGui::SameLine(max_len); + auto exlude_m = total_support_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m; + auto exlude_g = total_support_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g; + ::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", ps.total_used_filament / koef - exlude_m); + imgui.text(buf); + ImGui::SameLine(); + ::sprintf(buf, imperial_units ? " %.2f oz" : " %.2f g", (ps.total_weight - exlude_g) / unit_conver); + imgui.text(buf); + //BBS: display cost of filaments ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.text(cost_str + ":"); ImGui::SameLine(max_len); - ::sprintf(buf, "%.2f", ps.total_cost); imgui.text(buf); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 26486c6259..29addc6738 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -657,7 +657,7 @@ void GLCanvas3D::LayersEditing::generate_layer_height_texture() bool level_of_detail_2nd_level = true; m_layers_texture.cells = Slic3r::generate_layer_height_texture( *m_slicing_parameters, - Slic3r::generate_object_layers(*m_slicing_parameters, m_layer_height_profile), + Slic3r::generate_object_layers(*m_slicing_parameters, m_layer_height_profile, false), m_layers_texture.data.data(), m_layers_texture.height, m_layers_texture.width, level_of_detail_2nd_level); m_layers_texture.valid = true; } @@ -1024,6 +1024,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_SWITCH_TO_OBJECT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_SWITCH_TO_GLOBAL, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/); @@ -1096,6 +1098,25 @@ void GLCanvas3D::load_arrange_settings() m_arrange_settings_fff_seq_print.is_seq_print = true; } +GLCanvas3D::ArrangeSettings& GLCanvas3D::get_arrange_settings() +{ + PrinterTechnology ptech = current_printer_technology(); + + auto* ptr = &m_arrange_settings_fff; + + if (ptech == ptSLA) { + ptr = &m_arrange_settings_sla; + } + else if (ptech == ptFFF) { + if (wxGetApp().global_print_sequence() == PrintSequence::ByObject) + ptr = &m_arrange_settings_fff_seq_print; + else + ptr = &m_arrange_settings_fff; + } + + return *ptr; +} + int GLCanvas3D::GetHoverId() { if (m_hover_plate_idxs.size() == 0) { @@ -1152,7 +1173,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed) m_retina_helper.reset(new RetinaHelper(canvas)); #endif // ENABLE_RETINA_GL } - + m_timer_set_color.Bind(wxEVT_TIMER, &GLCanvas3D::on_set_color_timer, this); load_arrange_settings(); m_selection.set_volumes(&m_volumes.volumes); @@ -1347,7 +1368,36 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const return state; } -void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) +void GLCanvas3D::toggle_selected_volume_visibility(bool selected_visible) +{ + m_render_sla_auxiliaries = !selected_visible; + if (selected_visible) { + const Selection::IndicesList &idxs = m_selection.get_volume_idxs(); + if (idxs.size() > 0) { + for (GLVolume *vol : m_volumes.volumes) { + if (vol->composite_id.object_id >= 1000 && vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count()) + continue; // the wipe tower + if (vol->composite_id.volume_id >= 0) { + vol->is_active = false; + } + } + for (unsigned int idx : idxs) { + GLVolume *v = const_cast(m_selection.get_volume(idx)); + v->is_active = true; + } + } + } else { // show all + for (GLVolume *vol : m_volumes.volumes) { + if (vol->composite_id.object_id >= 1000 && vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count()) + continue; // the wipe tower + if (vol->composite_id.volume_id >= 0) { + vol->is_active = true; + } + } + } +} + +void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject *mo, int instance_idx) { if (current_printer_technology() != ptSLA) return; @@ -1771,7 +1821,9 @@ void GLCanvas3D::render(bool only_init) if (!is_initialized() && !init()) return; - + if (m_canvas_type == ECanvasType::CanvasView3D && m_gizmos.get_current_type() == GLGizmosManager::Undefined) { + enable_return_toolbar(false); + } if (!m_main_toolbar.is_enabled()) m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle); @@ -3170,15 +3222,25 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) } // BBS: use keypad to change extruder - case '1': + case '1': { + if (!m_timer_set_color.IsRunning()) { + m_timer_set_color.StartOnce(500); + break; + } + } + case '0': //Color logic for material 10 case '2': case '3': case '4': case '5': - case '6': + case '6': case '7': case '8': case '9': { + if (m_timer_set_color.IsRunning()) { + if (keyCode < '7') keyCode += 10; + m_timer_set_color.Stop(); + } if (m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) obj_list->set_extruder_for_selected_items(keyCode - '0'); break; @@ -3720,6 +3782,14 @@ void GLCanvas3D::on_render_timer(wxTimerEvent& evt) // wxWakeUpIdle(); } +void GLCanvas3D::on_set_color_timer(wxTimerEvent& evt) +{ + auto obj_list = wxGetApp().obj_list(); + if (m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) + obj_list->set_extruder_for_selected_items(1); + m_timer_set_color.Stop(); +} + void GLCanvas3D::schedule_extra_frame(int miliseconds) { @@ -4026,6 +4096,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.position = Vec2d(-1.0, -1.0); m_dirty = true; } + else if (evt.LeftDClick()) { + // switch to object panel if double click on object, otherwise switch to global panel if double click on background + if (selected_object_idx >= 0) + post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_OBJECT)); + else + post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_GLOBAL)); + } else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) { //BBS: add orient deactivate logic if (!m_gizmos.on_mouse(evt)) { @@ -4988,8 +5065,10 @@ std::vector GLCanvas3D::get_empty_cells(const Vec2f start_point, const Ve Vec2d vmin(build_volume.min.x(), build_volume.min.y()), vmax(build_volume.max.x(), build_volume.max.y()); BoundingBoxf bbox(vmin, vmax); std::vector cells; - for (float x = bbox.min.x()+step(0)/2; x < bbox.max.x()-step(0)/2; x += step(0)) - for (float y = bbox.min.y()+step(1)/2; y < bbox.max.y()-step(1)/2; y += step(1)) + auto min_x = start_point.x() - step(0) * int((start_point.x() - bbox.min.x()) / step(0)); + auto min_y = start_point.y() - step(1) * int((start_point.y() - bbox.min.y()) / step(1)); + for (float x = min_x; x < bbox.max.x() - step(0) / 2; x += step(0)) + for (float y = min_y; y < bbox.max.y() - step(1) / 2; y += step(1)) { cells.emplace_back(x, y); } @@ -5125,7 +5204,14 @@ void GLCanvas3D::update_sequential_clearance() // the results are then cached for following displacements if (m_sequential_print_clearance_first_displacement) { m_sequential_print_clearance.m_hull_2d_cache.clear(); - float shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON)); + bool all_objects_are_short = std::all_of(fff_print()->objects().begin(), fff_print()->objects().end(), \ + [&](PrintObject* obj) { return obj->height() < scale_(fff_print()->config().nozzle_height.value - MARGIN_HEIGHT); }); + float shrink_factor; + if (all_objects_are_short) + shrink_factor = scale_(0.5 * MAX_OUTER_NOZZLE_DIAMETER - 0.1); + else + shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON)); + double mitter_limit = scale_(0.1); m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size()); for (size_t i = 0; i < m_model->objects.size(); ++i) { @@ -5435,7 +5521,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo PrinterTechnology ptech = current_printer_technology(); bool settings_changed = false; - float dist_min = 0.1f; // should be larger than 0 so objects won't touch + float dist_min = 0.f; // 0 means auto std::string dist_key = "min_object_distance", rot_key = "enable_rotation"; std::string bed_shrink_x_key = "bed_shrink_x", bed_shrink_y_key = "bed_shrink_y"; std::string multi_material_key = "allow_multi_materials_on_same_plate"; @@ -5446,17 +5532,12 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo bool seq_print = false; if (ptech == ptSLA) { - dist_min = 0.1f; postfix = "_sla"; } else if (ptech == ptFFF) { - auto co_opt = m_config->option>("print_sequence"); - if (co_opt && (co_opt->value == PrintSequence::ByObject)) { - dist_min = float(min_object_distance(*m_config)); + seq_print = &settings == &m_arrange_settings_fff_seq_print; + if (seq_print) { postfix = "_fff_seq_print"; - //BBS: - seq_print = true; } else { - dist_min = 0.0f; postfix = "_fff"; } } @@ -5481,6 +5562,8 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance)); settings_changed = true; } + imgui->text(_L("0 means auto spacing.")); + ImGui::Separator(); if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings.enable_rotation)) { settings_out.enable_rotation = settings.enable_rotation; @@ -6346,7 +6429,7 @@ void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) { bool GLCanvas3D::_update_imgui_select_plate_toolbar() { bool result = true; - if (!m_sel_plate_toolbar.is_enabled()) return false; + if (!m_sel_plate_toolbar.is_enabled() || m_sel_plate_toolbar.is_render_finish) return false; _update_select_plate_toolbar_stats_item(); @@ -7926,6 +8009,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() } imgui.end(); + m_sel_plate_toolbar.is_render_finish = true; } //BBS: GUI refactor: GLToolbar adjust diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index bed5ac3ae1..5af8ee8aa9 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -187,6 +187,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_SWITCH_TO_OBJECT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_SWITCH_TO_GLOBAL, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/); @@ -515,6 +517,7 @@ private: unsigned int m_last_w, m_last_h; bool m_in_render; wxTimer m_timer; + wxTimer m_timer_set_color; LayersEditing m_layers_editing; Mouse m_mouse; GLGizmosManager m_gizmos; @@ -607,25 +610,6 @@ private: PrinterTechnology current_printer_technology() const; - template - static auto & get_arrange_settings(Self *self) { - PrinterTechnology ptech = self->current_printer_technology(); - - auto *ptr = &self->m_arrange_settings_fff; - - if (ptech == ptSLA) { - ptr = &self->m_arrange_settings_sla; - } else if (ptech == ptFFF) { - auto co_opt = self->m_config->template option>("print_sequence"); - if (co_opt && (co_opt->value == PrintSequence::ByObject)) - ptr = &self->m_arrange_settings_fff_seq_print; - else - ptr = &self->m_arrange_settings_fff; - } - - return *ptr; - } - //BBS:record key botton frequency @@ -651,7 +635,11 @@ public: } void load_arrange_settings(); - ArrangeSettings& get_arrange_settings() { return get_arrange_settings(this); } + ArrangeSettings& get_arrange_settings();// { return get_arrange_settings(this); } + ArrangeSettings& get_arrange_settings(PrintSequence print_seq) { + return (print_seq == PrintSequence::ByObject) ? m_arrange_settings_fff_seq_print + : m_arrange_settings_fff; + } class SequentialPrintClearance { @@ -774,6 +762,7 @@ public: const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); } + void toggle_selected_volume_visibility(bool selected_visible); void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1, const ModelVolume* mv = nullptr); void update_instance_printable_state_for_object(size_t obj_idx); @@ -960,6 +949,7 @@ public: void on_mouse_wheel(wxMouseEvent& evt); void on_timer(wxTimerEvent& evt); void on_render_timer(wxTimerEvent& evt); + void on_set_color_timer(wxTimerEvent& evt); void on_mouse(wxMouseEvent& evt); void on_gesture(wxGestureEvent& evt); void on_paint(wxPaintEvent& evt); @@ -1068,6 +1058,17 @@ public: void highlight_toolbar_item(const std::string& item_name); void highlight_gizmo(const std::string& gizmo_name); + ArrangeSettings get_arrange_settings() const { + const ArrangeSettings &settings = get_arrange_settings(); + ArrangeSettings ret = settings; + if (&settings == &m_arrange_settings_fff_seq_print) { + ret.distance = std::max(ret.distance, + float(min_object_distance(*m_config))); + } + + return ret; + } + // Timestamp for FPS calculation and notification fade-outs. static int64_t timestamp_now() { #ifdef _WIN32 diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 5284595e0b..1d9c558b6b 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -149,6 +149,40 @@ namespace GUI { class MainFrame; +void start_ping_test() +{ + wxArrayString output; + wxExecute("ping www.amazon.com", output, wxEXEC_NODISABLE); + + wxString output_i; + std::string output_temp; + + for (int i = 0; i < output.size(); i++) { + output_i = output[i].To8BitData(); + output_temp = output_i.ToStdString(wxConvUTF8); + BOOST_LOG_TRIVIAL(info) << "ping amazon:" << output_temp; + + } + wxExecute("ping www.apple.com", output, wxEXEC_NODISABLE); + for (int i = 0; i < output.size(); i++) { + output_i = output[i].To8BitData(); + output_temp = output_i.ToStdString(wxConvUTF8); + BOOST_LOG_TRIVIAL(info) << "ping www.apple.com:" << output_temp; + } + wxExecute("ping www.bambulab.com", output, wxEXEC_NODISABLE); + for (int i = 0; i < output.size(); i++) { + output_i = output[i].To8BitData(); + output_temp = output_i.ToStdString(wxConvUTF8); + BOOST_LOG_TRIVIAL(info) << "ping bambulab:" << output_temp; + } + //Get GateWay IP + wxExecute("ping 192.168.0.1", output, wxEXEC_NODISABLE); + for (int i = 0; i < output.size(); i++) { + output_i = output[i].To8BitData(); + output_temp = output_i.ToStdString(wxConvUTF8); + BOOST_LOG_TRIVIAL(info) << "ping 192.168.0.1:" << output_temp; + } +} std::string VersionInfo::convert_full_version(std::string short_version) { @@ -474,9 +508,11 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = { /* FT_3MF */ { "3MF files"sv, { ".3mf"sv } }, /* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".3mf"sv } }, #ifdef __APPLE__ - /* FT_MODEL */ { "Supported files"sv, { ".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv , ".usd"sv, ".usda"sv, ".usdc"sv, ".usdz"sv, ".abc"sv, ".ply"sv} }, + /* FT_MODEL */ + {"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv, ".usd"sv, ".usda"sv, ".usdc"sv, ".usdz"sv, ".abc"sv, ".ply"sv}}, #else - /* FT_MODEL */ {"Supported files"sv, {".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv }}, + /* FT_MODEL */ + {"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv}}, #endif /* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} }, /* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } }, @@ -993,8 +1029,7 @@ void GUI_App::post_init() }); - std::string filaments_blacklist_config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json"; - DeviceManager::load_filaments_blacklist_config(encode_path(filaments_blacklist_config_file.c_str())); + DeviceManager::load_filaments_blacklist_config(); // remove old log files over LOG_FILES_MAX_NUM std::string log_addr = data_dir(); @@ -1935,7 +1970,7 @@ std::map GUI_App::get_extra_header() extra_headers.insert(std::make_pair("X-BBL-OS-Version", os_version)); if (app_config) extra_headers.insert(std::make_pair("X-BBL-Device-ID", app_config->get("slicer_uuid"))); - extra_headers.insert(std::make_pair("X-BBL-Language", convert_studio_language_to_api(app_config->get("language")))); + extra_headers.insert(std::make_pair("X-BBL-Language", convert_studio_language_to_api(into_u8(current_language_code_safe())))); return extra_headers; } @@ -2114,9 +2149,6 @@ bool GUI_App::on_init_inner() d->EndModal(wxID_ABORT); }); - std::map extra_headers = get_extra_header(); - Slic3r::Http::set_extra_headers(extra_headers); - // Verify resources path const wxString resources_dir = from_u8(Slic3r::resources_dir()); wxCHECK_MSG(wxDirExists(resources_dir), false, @@ -2379,6 +2411,10 @@ bool GUI_App::on_init_inner() Bind(EVT_SHOW_IP_DIALOG, &GUI_App::show_ip_address_enter_dialog_handler, this); + + std::map extra_headers = get_extra_header(); + Slic3r::Http::set_extra_headers(extra_headers); + copy_network_if_available(); on_init_network(); @@ -2555,7 +2591,7 @@ void GUI_App::copy_network_if_available() { if (app_config->get("update_network_plugin") != "true") return; - std::string network_library, player_library, network_library_dst, player_library_dst; + std::string network_library, player_library, live555_library, network_library_dst, player_library_dst, live555_library_dst; std::string data_dir_str = data_dir(); boost::filesystem::path data_dir_path(data_dir_str); auto plugin_folder = data_dir_path / "plugins"; @@ -2563,19 +2599,25 @@ void GUI_App::copy_network_if_available() std::string changelog_file = cache_folder.string() + "/network_plugins.json"; #if defined(_MSC_VER) || defined(_WIN32) network_library = cache_folder.string() + "/bambu_networking.dll"; - player_library = cache_folder.string() + "/BambuSource.dll"; + player_library = cache_folder.string() + "/BambuSource.dll"; + live555_library = cache_folder.string() + "/live555.dll"; network_library_dst = plugin_folder.string() + "/bambu_networking.dll"; - player_library_dst = plugin_folder.string() + "/BambuSource.dll"; + player_library_dst = plugin_folder.string() + "/BambuSource.dll"; + live555_library_dst = plugin_folder.string() + "/live555.dll"; #elif defined(__WXMAC__) network_library = cache_folder.string() + "/libbambu_networking.dylib"; player_library = cache_folder.string() + "/libBambuSource.dylib"; + live555_library = cache_folder.string() + "/liblive555.dylib"; network_library_dst = plugin_folder.string() + "/libbambu_networking.dylib"; player_library_dst = plugin_folder.string() + "/libBambuSource.dylib"; + live555_library_dst = plugin_folder.string() + "/liblive555.dylib"; #else network_library = cache_folder.string() + "/libbambu_networking.so"; - player_library = cache_folder.string() + "/libBambuSource.so"; + player_library = cache_folder.string() + "/libBambuSource.so"; + live555_library = cache_folder.string() + "/liblive555.so"; network_library_dst = plugin_folder.string() + "/libbambu_networking.so"; - player_library_dst = plugin_folder.string() + "/libBambuSource.so"; + player_library_dst = plugin_folder.string() + "/libBambuSource.so"; + live555_library_dst = plugin_folder.string() + "/liblive555.so"; #endif BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": checking network_library " << network_library << ", player_library " << player_library; @@ -2609,6 +2651,19 @@ void GUI_App::copy_network_if_available() fs::remove(player_library); BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": Copying player library from" << player_library << " to " << player_library_dst<<" successfully."; } + + if (boost::filesystem::exists(live555_library)) { + CopyFileResult cfr = copy_file(live555_library, live555_library_dst, error_message, false); + if (cfr != CopyFileResult::SUCCESS) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": Copying failed(" << cfr << "): " << error_message; + return; + } + + static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; + fs::permissions(live555_library_dst, perms); + fs::remove(live555_library); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": Copying live555 library from" << live555_library << " to " << live555_library_dst<<" successfully."; + } if (boost::filesystem::exists(changelog_file)) fs::remove(changelog_file); app_config->set("update_network_plugin", "false"); @@ -3136,7 +3191,10 @@ void GUI_App::check_printer_presets() #endif } -void GUI_App::recreate_GUI(const wxString& msg_name) +void switch_window_pools(); +void release_window_pools(); + +void GUI_App::recreate_GUI(const wxString &msg_name) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "recreate_GUI enter"; m_is_recreating_gui = true; @@ -3144,12 +3202,18 @@ void GUI_App::recreate_GUI(const wxString& msg_name) update_http_extra_header(); mainframe->shutdown(); - ProgressDialog dlg(msg_name, msg_name, 100, nullptr, wxPD_AUTO_HIDE); dlg.Pulse(); dlg.Update(10, _L("Rebuild") + dots); MainFrame *old_main_frame = mainframe; + struct ClientData : wxClientData + { + ~ClientData() { release_window_pools(); } + }; + old_main_frame->SetClientObject(new ClientData); + + switch_window_pools(); mainframe = new MainFrame(); if (is_editor()) // hide settings tabs after first Layout @@ -3218,6 +3282,7 @@ void GUI_App::ShowUserGuide() { if (res) { load_current_presets(); update_publish_status(); + mainframe->refresh_plugin_tips(); // BBS: remove SLA related message } } catch (std::exception &e) { @@ -5934,6 +5999,15 @@ int GUI_App::filaments_cnt() const return preset_bundle->filament_presets.size(); } +PrintSequence GUI_App::global_print_sequence() const +{ + PrintSequence global_print_seq = PrintSequence::ByDefault; + auto curr_preset_config = preset_bundle->prints.get_edited_preset().config; + if (curr_preset_config.has("print_sequence")) + global_print_seq = curr_preset_config.option>("print_sequence")->value; + return global_print_seq; +} + wxString GUI_App::current_language_code_safe() const { // Translate the language code to a code, for which Prusa Research maintains translations. @@ -6007,6 +6081,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage if (res) { load_current_presets(); update_publish_status(); + mainframe->refresh_plugin_tips(); // BBS: remove SLA related message } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index f7606c8a07..21a38862fb 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -587,6 +587,7 @@ private: // BBS int filaments_cnt() const; + PrintSequence global_print_sequence() const; std::vector tabs_list; std::vector model_tabs_list; diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 386e36d469..14fa20763b 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -87,7 +87,9 @@ std::map> SettingsFactory::OBJECT_C {"seam_position", "",2}, {"slice_closing_radius", "",3}, {"resolution", "",4}, {"xy_hole_compensation", "",5}, {"xy_contour_compensation", "",6}, {"elefant_foot_compensation", "",7}, - {"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}, {"wall_sequence","",10} + {"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}, {"wall_sequence","",10}, + {"precise_z_height", "",10} + }}, { L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3}, {"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7}, diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0f1f753acb..1f3ae959eb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -699,6 +699,9 @@ void ObjectList::update_filament_values_for_items(const size_t filaments_count) void ObjectList::update_plate_values_for_items() { +#ifdef __WXOSX__ + AssociateModel(nullptr); +#endif PartPlateList& list = wxGetApp().plater()->get_partplate_list(); for (size_t i = 0; i < m_objects->size(); ++i) { @@ -724,6 +727,9 @@ void ObjectList::update_plate_values_for_items() Expand(item); Select(item); } +#ifdef __WXOSX__ + AssociateModel(m_objects_model); +#endif } // BBS @@ -3627,7 +3633,7 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, //BBS start add obj_idx for debug PartPlateList& list = wxGetApp().plater()->get_partplate_list(); if (notify_partplate) { - list.notify_instance_update(obj_idx, 0); + list.notify_instance_update(obj_idx, 0, true); } //int plate_idx = list.find_instance_belongs(obj_idx, 0); //std::string item_name_str = (boost::format("[P%1%][O%2%]%3%") % plate_idx % std::to_string(obj_idx) % model_object->name).str(); @@ -3869,16 +3875,10 @@ void ObjectList::update_lock_icons_for_model() void ObjectList::delete_all_objects_from_list() { -#ifdef __WXOSX__ - AssociateModel(nullptr); -#endif m_prevent_list_events = true; reload_all_plates(); m_prevent_list_events = false; part_selection_changed(); -#ifdef __WXOSX__ - AssociateModel(m_objects_model); -#endif } void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num) @@ -5697,6 +5697,9 @@ void ObjectList::on_plate_deleted(int plate_idx) void ObjectList::reload_all_plates(bool notify_partplate) { m_prevent_canvas_selection_update = true; +#ifdef __WXOSX__ + AssociateModel(nullptr); +#endif // Unselect all objects before deleting them, so that no change of selection is emitted during deletion. @@ -5726,6 +5729,9 @@ void ObjectList::reload_all_plates(bool notify_partplate) update_selections(); +#ifdef __WXOSX__ + AssociateModel(m_objects_model); +#endif m_prevent_canvas_selection_update = false; // update scene @@ -5853,6 +5859,7 @@ void ObjectList::toggle_printable_state() // update scene wxGetApp().plater()->update(); + wxGetApp().plater()->reload_paint_after_background_process_apply(); } ModelObject* ObjectList::object(const int obj_idx) const diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index ff9521b584..09ca8c64a8 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -209,36 +209,36 @@ bool ObjectSettings::update_settings_list() ModelObject * parent_object = nullptr; for (auto item : items) { auto type = objects_model->GetItemType(item); - if (type == itPlate) { - is_plate_settings = true; - - int plate_id = objects_model->GetPlateIdByItem(item); - - static ModelConfig cfg; - PartPlateList& ppl = wxGetApp().plater()->get_partplate_list(); - - if (plate_id < 0 || plate_id >= ppl.get_plate_count()) { - plate_id = ppl.get_curr_plate_index(); - } - assert(plate_id >= 0 && plate_id < ppl.get_plate_count()); - - cfg.assign_config(*ppl.get_plate(plate_id)->config()); - plate_configs.emplace(ppl.get_plate(plate_id), &cfg); - } - if (type != itObject && type != itVolume && type != itLayerRoot && type != itLayer) { + if (type != itPlate && type != itObject && type != itVolume && type != itLayerRoot && type != itLayer) { continue; } + int plate_id = objects_model->GetPlateIdByItem(item); + PartPlateList& ppl = wxGetApp().plater()->get_partplate_list(); + if (plate_id < 0 || plate_id >= ppl.get_plate_count()) { + plate_id = ppl.get_curr_plate_index(); + } + assert(plate_id >= 0 && plate_id < ppl.get_plate_count()); + static ModelConfig cfg; + cfg.assign_config(*ppl.get_plate(plate_id)->config()); + if (type == itPlate) { + is_plate_settings = true; + plate_configs.emplace(ppl.get_plate(plate_id), &cfg); + break; + } + const int obj_idx = objects_model->GetObjectIdByItem(item); assert(obj_idx >= 0); auto object = wxGetApp().model().objects[obj_idx]; if (type == itObject) { is_object_settings = true; + plate_configs.emplace(ppl.get_plate(plate_id), &cfg); object_configs.emplace(object, &object->config); } else if(type == itVolume){ is_volume_settings = true; if (parent_object && parent_object != object) return false; + plate_configs.emplace(ppl.get_plate(plate_id), &cfg); parent_object = object; const int vol_idx = objects_model->GetVolumeIdByItem(item); assert(vol_idx >= 0); @@ -249,6 +249,7 @@ bool ObjectSettings::update_settings_list() is_layer_range_settings = true; if (parent_object && parent_object != object) return false; + plate_configs.emplace(ppl.get_plate(plate_id), &cfg); parent_object = object; t_layer_height_range height_range = objects_model->GetLayerRangeByItem(item); @@ -265,38 +266,38 @@ bool ObjectSettings::update_settings_list() auto tab_layer = dynamic_cast(wxGetApp().get_layer_tab()); if (is_plate_settings) { + tab_plate->set_model_config(plate_configs); tab_object->set_model_config({}); tab_volume->set_model_config({}); tab_layer->set_model_config({}); - tab_plate->set_model_config(plate_configs); ;// m_tab_active = tab_plate; } else if (is_object_settings) { + tab_plate->set_model_config(plate_configs); tab_object->set_model_config(object_configs); tab_volume->set_model_config({}); tab_layer->set_model_config({}); - tab_plate->set_model_config({}); //m_tab_active = tab_object; } else if (is_volume_settings) { + tab_plate->set_model_config(plate_configs); tab_object->set_model_config({ {parent_object, &parent_object->config} }); tab_volume->set_model_config(object_configs); tab_layer->set_model_config({}); - tab_plate->set_model_config({}); //m_tab_active = tab_volume; } else if (is_layer_range_settings) { + tab_plate->set_model_config(plate_configs); tab_object->set_model_config({ {parent_object, &parent_object->config} }); tab_volume->set_model_config({}); tab_layer->set_model_config(object_configs); - tab_plate->set_model_config({}); //m_tab_active = tab_layer; } else { + tab_plate->set_model_config({}); tab_object->set_model_config({}); tab_volume->set_model_config({}); tab_layer->set_model_config({}); - tab_plate->set_model_config({}); //m_tab_active = nullptr; } ((ParamsPanel*) tab_object->GetParent())->set_active_tab(nullptr); diff --git a/src/slic3r/GUI/GUI_ObjectTable.cpp b/src/slic3r/GUI/GUI_ObjectTable.cpp index dd2e90b84d..56c1550c46 100644 --- a/src/slic3r/GUI/GUI_ObjectTable.cpp +++ b/src/slic3r/GUI/GUI_ObjectTable.cpp @@ -345,10 +345,16 @@ void GridCellFilamentsRenderer::Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &d dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxBrush(attr.GetBackgroundColour())); dc.DrawRectangle(rect); - if ( grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) { + if ((grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) && \ + (grid_row->model_volume_type != ModelVolumeType::SUPPORT_BLOCKER) && \ + (grid_row->model_volume_type != ModelVolumeType::SUPPORT_ENFORCER) && \ + (grid_row->model_volume_type != ModelVolumeType::PARAMETER_MODIFIER)) { dc.DrawBitmap(*bitmap, wxPoint(rect.x + offset_x, rect.y + offset_y)); } - + else if (grid_row->model_volume_type == ModelVolumeType::PARAMETER_MODIFIER){ + dc.DrawText("Default", wxPoint(rect.x + offset_x, rect.y + offset_y)); + } + text_rect.x += bitmap_width + grid_cell_border_width * 2; text_rect.width -= (bitmap_width + grid_cell_border_width * 2); } @@ -693,40 +699,44 @@ void GridCellSupportRenderer::Draw(wxGrid& grid, auto width = grid.GetColSize(col); wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); - if (cur_option.value) { + wxString value = table->GetValue(row, col); + if (grid_row->row_type != table->GridRowType::row_volume || col != table->GridColType::col_printable) { + if (cur_option.value) { - auto check_on = create_scaled_bitmap("check_on", nullptr, 18); - dc.SetPen(*wxTRANSPARENT_PEN); + auto check_on = create_scaled_bitmap("check_on", nullptr, 18); + dc.SetPen(*wxTRANSPARENT_PEN); - auto offsetx = 0; - auto offsety = 0; + auto offsetx = 0; + auto offsety = 0; - #ifdef __WXOSX_MAC__ - offsetx = (width - 18) / 2; - offsety = (height - 18) / 2; - #else - offsetx = (width - check_on.GetSize().x) / 2; - offsety = (height - check_on.GetSize().y) / 2; - #endif // __WXOSX_MAC__ + #ifdef __WXOSX_MAC__ + offsetx = (width - 18) / 2; + offsety = (height - 18) / 2; + #else + offsetx = (width - check_on.GetSize().x) / 2; + offsety = (height - check_on.GetSize().y) / 2; + #endif // __WXOSX_MAC__ - dc.DrawBitmap(check_on, rect.x + offsetx, rect.y + offsety); + dc.DrawBitmap(check_on, rect.x + offsetx, rect.y + offsety); } else { - auto check_off = create_scaled_bitmap("check_off_focused", nullptr, 18); - dc.SetPen(*wxTRANSPARENT_PEN); + auto check_off = create_scaled_bitmap("check_off_focused", nullptr, 18); + dc.SetPen(*wxTRANSPARENT_PEN); - auto offsetx = 0; - auto offsety = 0; + auto offsetx = 0; + auto offsety = 0; - #ifdef __WXOSX_MAC__ - offsetx = (width - 18) / 2; - offsety = (height - 18) / 2; - #else - offsetx = (width - check_off.GetSize().x) / 2; - offsety = (height - check_off.GetSize().y) / 2; - #endif // __WXOSX_MAC__ + #ifdef __WXOSX_MAC__ + offsetx = (width - 18) / 2; + offsety = (height - 18) / 2; + #else + offsetx = (width - check_off.GetSize().x) / 2; + offsety = (height - check_off.GetSize().y) / 2; + #endif // __WXOSX_MAC__ - dc.DrawBitmap(check_off, rect.x + offsetx, rect.y + offsety); + dc.DrawBitmap(check_off, rect.x + offsetx, rect.y + offsety); + } } + } wxSize GridCellSupportRenderer::GetBestSize(wxGrid& grid, @@ -2764,6 +2774,10 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi m_object_settings->Hide(); //m_page_sizer->Add(m_page_top_sizer, 0, wxALIGN_CENTER_HORIZONTAL, 0); m_page_sizer->Add(m_object_settings->get_sizer(), 1, wxEXPAND | wxALL, 2 ); + m_side_window->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& evt) { + m_object_grid->SetFocus(); + evt.Skip(); + }); auto m_line_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(2, -1), wxTAB_TRAVERSAL); m_line_left->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA)); @@ -2962,7 +2976,9 @@ void ObjectTablePanel::load_data() break; case coEnum: if (col == ObjectGridTable::col_filaments) { - if (grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) { + if ((grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) && \ + (grid_row->model_volume_type != ModelVolumeType::SUPPORT_BLOCKER) && \ + (grid_row->model_volume_type != ModelVolumeType::SUPPORT_ENFORCER)) { GridCellFilamentsEditor* filament_editor = new GridCellFilamentsEditor(grid_col->choices, false, &m_color_bitmaps); m_object_grid->SetCellEditor(row, col, filament_editor); m_object_grid->SetCellRenderer(row, col, new GridCellFilamentsRenderer()); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 2ce7e67ec1..9cb20f6573 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -107,6 +107,7 @@ class Preview : public wxPanel const Slic3r::PrintBase* m_loaded_print { nullptr }; //BBS: add only gcode mode bool m_only_gcode { false }; + bool m_reload_paint_after_background_process_apply{false}; public: enum class OptionType : unsigned int @@ -160,6 +161,8 @@ public: void show_sliders(bool show = true); void show_moves_sliders(bool show = true); void show_layers_sliders(bool show = true); + void set_reload_paint_after_background_process_apply(bool flag) { m_reload_paint_after_background_process_apply = flag; } + bool get_reload_paint_after_background_process_apply() { return m_reload_paint_after_background_process_apply; } private: bool init(wxWindow* parent, Bed3D& bed, Model* model); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 81c6e8710c..35cc3c7700 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -1862,10 +1862,13 @@ bool GLGizmoAdvancedCut::render_slider_double_input(const std::string &label, fl // slider_with + item_in_gap + first_input_width + item_out_gap + slider_with + item_in_gap + second_input_width double slider_with = 0.24 * m_editing_window_width; // m_control_width * 0.35; double item_in_gap = 0.01 * m_editing_window_width; - double item_out_gap = 0.01 * m_editing_window_width; - double first_input_width = 0.29 * m_editing_window_width; - double second_input_width = 0.29 * m_editing_window_width; - + double item_out_gap = 0.04 * m_editing_window_width; + double first_input_width = 0.37 * m_editing_window_width; + double second_input_width = 0.37 * m_editing_window_width; +#ifdef __APPLE__ + first_input_width = 0.5 * m_editing_window_width; + second_input_width = 0.5 * m_editing_window_width; +#endif ImGui::AlignTextToFramePadding(); m_imgui->text(label); ImGui::SameLine(m_label_width); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 0471d02358..3a57a895d6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -248,6 +248,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l const float on_overhangs_only_width = m_imgui->calc_text_size(m_desc["on_overhangs_only"]).x + m_imgui->scaled(1.5f); const float remove_btn_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.5f); const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform")).x + m_imgui->scaled(1.5f); + const float gap_area_txt_width = m_imgui->calc_text_size(m_desc.at("gap_area")).x + m_imgui->scaled(1.5f); + const float smart_fill_angle_txt_width = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f); const float buttons_width = remove_btn_width + filter_btn_width + m_imgui->scaled(1.5f); const float empty_button_width = m_imgui->calc_button_size("").x; @@ -263,7 +265,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l total_text_max += caption_max + m_imgui->scaled(1.f); caption_max += m_imgui->scaled(1.f); - const float sliders_left_width = std::max(reset_button_slider_left, std::max(std::max(cursor_slider_left, clipping_slider_left), std::max(highlight_slider_left, gap_fill_slider_left))); + const float sliders_left_width = std::max(gap_area_txt_width, std::max(smart_fill_angle_txt_width, std::max(reset_button_slider_left, std::max(std::max(cursor_slider_left, clipping_slider_left), std::max(highlight_slider_left, gap_fill_slider_left))))); const float slider_icon_width = m_imgui->get_slider_icon_size().x; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; @@ -374,7 +376,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l m_cursor_type = TriangleSelector::CursorType::POINTER; ImGui::AlignTextToFramePadding(); - m_imgui->text(m_desc["gap_area"] + ":"); + m_imgui->text(m_desc["gap_area"]); ImGui::SameLine(sliders_left_width); ImGui::PushItemWidth(sliders_width); std::string format_str = std::string("%.2f") + I18N::translate_utf8("", "Triangle patch area threshold,""triangle patch will be merged to neighbor if its area is less than threshold"); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 11886c142a..bd91482f65 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -250,7 +250,7 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const bool GLGizmoMmuSegmentation::on_number_key_down(int number) { int extruder_idx = number - 1; - if (extruder_idx < m_extruders_colors.size()) + if (extruder_idx < m_extruders_colors.size() && extruder_idx >= 0) m_selected_extruder_idx = extruder_idx; return true; @@ -487,7 +487,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott color_button_high = ImGui::GetCursorPos().y - color_button - 2.0; if (color_picked) { m_selected_extruder_idx = extruder_idx; } - if (extruder_idx < 9 && ImGui::IsItemHovered()) m_imgui->tooltip(_L("Shortcut Key ") + std::to_string(extruder_idx + 1), max_tooltip_width); + if (extruder_idx < 16 && ImGui::IsItemHovered()) m_imgui->tooltip(_L("Shortcut Key ") + std::to_string(extruder_idx + 1), max_tooltip_width); // draw filament id float gray = 0.299 * extruder_color.r() + 0.587 * extruder_color.g() + 0.114 * extruder_color.b(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index e653829bee..9df780d720 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -298,6 +298,12 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co const Selection& selection = m_parent.get_selection(); const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()]; const ModelInstance* mi = model_object->instances[selection.get_instance_idx()]; + + int volumes_count = model_object->volumes.size(); + if (m_cut_contours.size() != volumes_count * 2) { + m_cut_contours.resize(volumes_count * 2); + } + m_volumes_index = 0; for (const ModelVolume* mv : model_object->volumes) { TriangleMesh vol_mesh = mv->mesh(); if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { @@ -310,15 +316,16 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co } for (int i = 0; i < zs.size(); i++) { - update_contours(vol_mesh, zs[i], max_z, min_z); + update_contours(m_volumes_index, vol_mesh, zs[i], max_z, min_z); const Camera& camera = wxGetApp().plater()->get_camera(); - Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_cut_contours.shift); + Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_cut_contours[m_volumes_index].shift); shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); glsafe(::glLineWidth(2.0f)); - m_cut_contours.contours.render(); + m_cut_contours[m_volumes_index].contours.render(); + m_volumes_index++; } } @@ -339,7 +346,7 @@ BoundingBoxf3 GLGizmoPainterBase::bounding_box() const return ret; } -void GLGizmoPainterBase::update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const +void GLGizmoPainterBase::update_contours(int i, const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const { const Selection& selection = m_parent.get_selection(); const GLVolume* first_glvolume = selection.get_first_volume(); @@ -349,31 +356,31 @@ void GLGizmoPainterBase::update_contours(const TriangleMesh& vol_mesh, float cur const int instance_idx = selection.get_instance_idx(); if (min_z < cursor_z && cursor_z < max_z) { - if (m_cut_contours.cut_z != cursor_z || m_cut_contours.object_id != model_object->id() || m_cut_contours.instance_idx != instance_idx) { - m_cut_contours.cut_z = cursor_z; + if (m_cut_contours[i].cut_z != cursor_z || m_cut_contours[i].object_id != model_object->id() || m_cut_contours[i].instance_idx != instance_idx) { + m_cut_contours[i].cut_z = cursor_z; - m_cut_contours.mesh = vol_mesh; + m_cut_contours[i].mesh = vol_mesh; - m_cut_contours.position = box.center(); - m_cut_contours.shift = Vec3d::Zero(); - m_cut_contours.object_id = model_object->id(); - m_cut_contours.instance_idx = instance_idx; - m_cut_contours.contours.reset(); + m_cut_contours[i].position = box.center(); + m_cut_contours[i].shift = Vec3d::Zero(); + m_cut_contours[i].object_id = model_object->id(); + m_cut_contours[i].instance_idx = instance_idx; + m_cut_contours[i].contours.reset(); MeshSlicingParams slicing_params; slicing_params.trafo = Transform3d::Identity().matrix(); - const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params); + const Polygons polys = slice_mesh(m_cut_contours[i].mesh.its, cursor_z, slicing_params); if (!polys.empty()) { - m_cut_contours.contours.init_from(polys, static_cast(cursor_z)); - m_cut_contours.contours.set_color({ 1.0f, 1.0f, 1.0f, 1.0f }); + m_cut_contours[i].contours.init_from(polys, static_cast(cursor_z)); + m_cut_contours[i].contours.set_color({ 1.0f, 1.0f, 1.0f, 1.0f }); } } - else if (box.center() != m_cut_contours.position) { - m_cut_contours.shift = box.center() - m_cut_contours.position; + else if (box.center() != m_cut_contours[i].position) { + m_cut_contours[i].shift = box.center() - m_cut_contours[i].position; } } else - m_cut_contours.contours.reset(); + m_cut_contours[i].contours.reset(); } bool GLGizmoPainterBase::is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index da05fcfab4..2644c10098 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -355,10 +355,15 @@ private: ObjectID object_id; int instance_idx{ -1 }; }; - mutable CutContours m_cut_contours; - + mutable std::vector m_cut_contours; + mutable int m_volumes_index = 0; + mutable float m_cursor_z{0}; + mutable double m_height_start_z_in_imgui{0}; + mutable bool m_is_set_height_start_z_by_imgui{false}; + mutable Vec2i m_height_start_pos{0, 0}; + mutable bool m_is_cursor_in_imgui{false}; BoundingBoxf3 bounding_box() const; - void update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const; + void update_contours(int i, const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const; protected: void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 7034b0eb27..271368d9e6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -1123,10 +1123,8 @@ bool GLGizmoText::update_text_positions(const std::vector& texts) Polygons polys = union_(temp_polys); auto point_in_line_rectange = [](const Line &line, const Point &point, double& distance) { - distance = abs((point.x() - line.a.x()) * (line.b.y() - line.a.y()) - (line.b.x() - line.a.x()) * (point.y() - line.a.y())); - bool in_rectange = (std::min(line.a.x(), line.b.x()) - 1000) <= point.x() && point.x() <= (std::max(line.a.x(), line.b.x()) + 1000) && - (std::min(line.a.y(), line.b.y()) - 1000) <= point.y() && point.y() <= (std::max(line.a.y(), line.b.y()) + 1000); - return in_rectange; + distance = line.distance_to(point); + return distance < line.length() / 2; }; int index = 0; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 4a747ad963..a9d83df5ae 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -57,6 +57,7 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) //BBS: GUI refactor: add object manipulation in gizmo , m_object_manipulation(parent) { + m_timer_set_color.Bind(wxEVT_TIMER, &GLGizmosManager::on_set_color_timer, this); } std::vector GLGizmosManager::get_selectable_idxs() const @@ -805,7 +806,7 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt) bool GLGizmosManager::on_key(wxKeyEvent& evt) { - const int keyCode = evt.GetKeyCode(); + int keyCode = evt.GetKeyCode(); bool processed = false; if (evt.GetEventType() == wxEVT_KEY_UP) { @@ -887,8 +888,21 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) else if (m_current == MmuSegmentation) { GLGizmoMmuSegmentation* mmu_seg = dynamic_cast(get_current()); if (mmu_seg != nullptr) { - if (keyCode > '0' && keyCode <= '9') { - processed = mmu_seg->on_number_key_down(keyCode - '0'); + if (keyCode >= WXK_NUMPAD0 && keyCode <= WXK_NUMPAD9) { + keyCode = keyCode- WXK_NUMPAD0+'0'; + } + if (keyCode >= '0' && keyCode <= '9') { + if (keyCode == '1' && !m_timer_set_color.IsRunning()) { + m_timer_set_color.StartOnce(500); + processed = true; + } + else if (keyCode < '7' && m_timer_set_color.IsRunning()) { + processed = mmu_seg->on_number_key_down(keyCode - '0'+10); + m_timer_set_color.Stop(); + } + else { + processed = mmu_seg->on_number_key_down(keyCode - '0'); + } } else if (keyCode == 'F' || keyCode == 'T' || keyCode == 'S' || keyCode == 'C' || keyCode == 'H' || keyCode == 'G') { processed = mmu_seg->on_key_down_select_tool_type(keyCode); @@ -933,6 +947,15 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) return processed; } +void GLGizmosManager::on_set_color_timer(wxTimerEvent& evt) +{ + if (m_current == MmuSegmentation) { + GLGizmoMmuSegmentation* mmu_seg = dynamic_cast(get_current()); + mmu_seg->on_number_key_down(1); + m_parent.set_as_dirty(); + } +} + void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot) { update_data(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 19cf11a8ca..687b8de27c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -142,6 +142,10 @@ private: bool m_serializing; std::unique_ptr m_common_gizmos_data; + //When there are more than 9 colors, shortcut key coloring + wxTimer m_timer_set_color; + void on_set_color_timer(wxTimerEvent& evt); + // key MENU_ICON_NAME, value = ImtextureID std::map icon_list; diff --git a/src/slic3r/GUI/HMSPanel.cpp b/src/slic3r/GUI/HMSPanel.cpp index 9992e37af4..88afb2a456 100644 --- a/src/slic3r/GUI/HMSPanel.cpp +++ b/src/slic3r/GUI/HMSPanel.cpp @@ -5,6 +5,8 @@ #include #include "GUI.hpp" #include "GUI_App.hpp" +#include "MainFrame.hpp" +#include "Monitor.hpp" namespace Slic3r { namespace GUI { @@ -12,9 +14,12 @@ namespace GUI { #define HMS_NOTIFY_ITEM_TEXT_SIZE wxSize(FromDIP(730), -1) #define HMS_NOTIFY_ITEM_SIZE wxSize(-1, FromDIP(80)) +wxDEFINE_EVENT(EVT_ALREADY_READ_HMS, wxCommandEvent); + HMSNotifyItem::HMSNotifyItem(wxWindow *parent, HMSItem& item) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL) , m_hms_item(item) + , long_error_code(item.get_long_error_code()) , m_url(get_hms_wiki_url(item.get_long_error_code())) { init_bitmaps(); @@ -114,6 +119,9 @@ HMSNotifyItem::HMSNotifyItem(wxWindow *parent, HMSItem& item) }); m_hms_content->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) { if (!m_url.empty()) wxLaunchDefaultBrowser(m_url); + wxCommandEvent evt(EVT_ALREADY_READ_HMS); + evt.SetString(long_error_code); + wxPostEvent(wxGetApp().mainframe->m_monitor, evt); }); #endif } @@ -193,6 +201,11 @@ void HMSPanel::delete_hms_panels() { m_scrolledWindow->DestroyChildren(); } +void HMSPanel::clear_hms_tag() +{ + temp_hms_list.clear(); +} + void HMSPanel::update(MachineObject *obj) { if (obj) { @@ -201,9 +214,35 @@ void HMSPanel::update(MachineObject *obj) wxString hms_text; for (auto item : obj->hms_list) { if (wxGetApp().get_hms_query()) { + + auto key = item.get_long_error_code(); + auto iter = temp_hms_list.find(key); + if (iter == temp_hms_list.end()) { + temp_hms_list[key] = item; + } + append_hms_panel(item); } } + + for (auto it = temp_hms_list.begin(); it != temp_hms_list.end(); ) { + auto key = it->second.get_long_error_code(); + bool inr = false; + for (auto hms : obj->hms_list) { + if (hms.get_long_error_code() == key) { + inr = true; + break; + } + } + + if (!inr) { + it = temp_hms_list.erase(it); + } + else { + ++it; + } + } + Layout(); this->Thaw(); } else { diff --git a/src/slic3r/GUI/HMSPanel.hpp b/src/slic3r/GUI/HMSPanel.hpp index f6fe003382..bafa043a69 100644 --- a/src/slic3r/GUI/HMSPanel.hpp +++ b/src/slic3r/GUI/HMSPanel.hpp @@ -16,6 +16,7 @@ class HMSNotifyItem : public wxPanel { HMSItem & m_hms_item; std::string m_url; + std::string long_error_code; wxPanel * m_panel_hms; wxStaticBitmap *m_bitmap_notify; @@ -39,6 +40,7 @@ public: void msw_rescale() {} }; + class HMSPanel : public wxPanel { protected: @@ -50,6 +52,7 @@ protected: void append_hms_panel(HMSItem &item); void delete_hms_panels(); + public: HMSPanel(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxTAB_TRAVERSAL); ~HMSPanel(); @@ -62,9 +65,14 @@ public: void show_status(int status); + void clear_hms_tag(); + MachineObject *obj { nullptr }; + std::map temp_hms_list; }; +wxDECLARE_EVENT(EVT_ALREADY_READ_HMS, wxCommandEvent); + } } diff --git a/src/slic3r/GUI/IMToolbar.cpp b/src/slic3r/GUI/IMToolbar.cpp index e14cdb2ffc..1dbfc9e613 100644 --- a/src/slic3r/GUI/IMToolbar.cpp +++ b/src/slic3r/GUI/IMToolbar.cpp @@ -58,6 +58,13 @@ void IMToolbar::del_stats_item() m_all_plates_stats_item = nullptr; } +void IMToolbar::set_enabled(bool enable) +{ + m_enabled = enable; + if (!m_enabled) + is_render_finish = false; +} + bool IMReturnToolbar::init() { bool compress = false; diff --git a/src/slic3r/GUI/IMToolbar.hpp b/src/slic3r/GUI/IMToolbar.hpp index 681045fdb8..add067d83a 100644 --- a/src/slic3r/GUI/IMToolbar.hpp +++ b/src/slic3r/GUI/IMToolbar.hpp @@ -49,7 +49,7 @@ public: float icon_height; bool is_display_scrollbar; bool show_stats_item{ false }; - + bool is_render_finish{false}; IMToolbar() { icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH; icon_height = DEFAULT_TOOLBAR_BUTTON_HEIGHT; @@ -63,7 +63,7 @@ public: float fontScale; bool is_enabled() const { return m_enabled; } - void set_enabled(bool enable) { m_enabled = enable; } + void set_enabled(bool enable); void set_icon_size(float width, float height) { icon_width = width; diff --git a/src/slic3r/GUI/ImageGrid.cpp b/src/slic3r/GUI/ImageGrid.cpp index 770d46ec00..15adf8c8ca 100644 --- a/src/slic3r/GUI/ImageGrid.cpp +++ b/src/slic3r/GUI/ImageGrid.cpp @@ -46,6 +46,8 @@ ImageGrid::ImageGrid(wxWindow * parent) , m_model_time_icon(this, "model_time", 14) , m_model_weight_icon(this, "model_weight", 14) { + m_cell_size.Set(396, 228); + SetBackgroundStyle(wxBG_STYLE_PAINT); SetBackgroundColour(0xEEEEEE); SetFont(Label::Head_20); @@ -293,9 +295,16 @@ void ImageGrid::mouseMoved(wxMouseEvent& event) if (hit != std::make_pair(m_hit_type, m_hit_item)) { m_hit_type = hit.first; m_hit_item = hit.second; - if (hit.first == HIT_ITEM) - SetToolTip(from_u8(m_file_sys->GetFile(hit.second).Title())); - else + if (hit.first == HIT_ITEM) { + SetToolTip({}); + auto & file = m_file_sys->GetFile(hit.second); + if (auto title = file.Title(); !title.empty()) { + auto tip = wxString::Format(_L("File: %s\nTitle: %s\n"), from_u8(file.name), from_u8(title)); + SetToolTip(tip); + } else { + SetToolTip(from_u8(file.name)); + } + } else SetToolTip({}); Refresh(); } @@ -732,7 +741,17 @@ void Slic3r::GUI::ImageGrid::renderText(wxDC &dc, wxString const &text, wxRect c dc.SetTextForeground(m_buttonTextColor.colorForStatesNoDark(states)); wxRect rc({0, 0}, dc.GetTextExtent(text)); rc = rc.CenterIn(rect); - dc.DrawText(text, rc.GetTopLeft()); + float fontScale = float(rect.width - 8) / rc.width; + if (fontScale < 1) { + auto font = dc.GetFont(); + dc.SetFont(font.Scaled(fontScale)); + wxRect rc({0, 0}, dc.GetTextExtent(text)); + rc = rc.CenterIn(rect); + dc.DrawText(text, rc.GetTopLeft()); + dc.SetFont(font); + } else { + dc.DrawText(text, rc.GetTopLeft()); + } } void Slic3r::GUI::ImageGrid::renderText2(wxDC &dc, wxString text, wxRect const &rect) diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 538ffc4fa5..c7a9a016c8 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -96,6 +96,7 @@ void ArrangeJob::clear_input() m_unprintable.clear(); m_locked.clear(); m_unarranged.clear(); + m_uncompatible_plates.clear(); m_selected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */); m_unprintable.reserve(cunprint /* for optional wti */); @@ -189,10 +190,20 @@ void ArrangeJob::prepare_selected() { } void ArrangeJob::prepare_all() { - PartPlateList& plate_list = m_plater->get_partplate_list(); - clear_input(); + PartPlateList& plate_list = m_plater->get_partplate_list(); + for (size_t i = 0; i < plate_list.get_plate_count(); i++) { + PartPlate* plate = plate_list.get_plate(i); + bool same_as_global_print_seq = true; + plate->get_real_print_seq(&same_as_global_print_seq); + if (plate->is_locked() == false && !same_as_global_print_seq) { + plate->lock(true); + m_uncompatible_plates.push_back(i); + } + } + + Model &model = m_plater->model(); bool selected_is_locked = false; @@ -492,20 +503,21 @@ void ArrangeJob::prepare() void ArrangeJob::check_unprintable() { for (auto it = m_selected.begin(); it != m_selected.end();) { - if (it->poly.area() < 0.001) + if (it->poly.area() < 0.001 || it->height>params.printable_height) { #if SAVE_ARRANGE_POLY - SVG svg("SVG/arrange_unprintable_"+it->name+".svg", get_extents(it->poly)); + SVG svg(data_dir() + "/SVG/arrange_unprintable_"+it->name+".svg", get_extents(it->poly)); if (svg.is_opened()) svg.draw_outline(it->poly); #endif - + if (it->poly.area() < 0.001) { + auto msg = (boost::format( + _utf8("Object %s has zero size and can't be arranged.")) + % _utf8(it->name)).str(); + m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo, + NotificationManager::NotificationLevel::WarningNotificationLevel, msg); + } m_unprintable.push_back(*it); - auto msg = (boost::format( - _utf8("Object %s has zero size and can't be arranged.")) - % _utf8(it->name)).str(); - m_plater->get_notification_manager()->push_notification(NotificationType::BBLPlateInfo, - NotificationManager::NotificationLevel::WarningNotificationLevel, msg); it = m_selected.erase(it); } else @@ -572,8 +584,6 @@ void ArrangeJob::process(Ctl &ctl) BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose(); } - arrangement::arrange(m_unprintable, {}, bedpts, params); - // put unpackable items to m_unprintable so they goes outside bool we_have_unpackable_items = false; for (auto item : m_selected) { @@ -717,6 +727,10 @@ void ArrangeJob::finalize(bool canceled, std::exception_ptr &eptr) { plate_list.rebuild_plates_after_arrangement(!only_on_partplate, true); } + // unlock the plates we just locked + for (int i : m_uncompatible_plates) + plate_list.get_plate(i)->lock(false); + // BBS: update slice context and gcode result. m_plater->update_slicing_context_to_current_partplate(); @@ -761,6 +775,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) params.cleareance_radius = print_config.extruder_clearance_radius.value; params.printable_height = print_config.printable_height.value; params.allow_rotations = settings.enable_rotation; + params.nozzle_height = print.config().nozzle_height.value; params.align_center = print_config.best_object_pos.value; params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate; params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; @@ -780,7 +795,6 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) } if (params.is_seq_print) { - params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error params.bed_shrink_x = BED_SHRINK_SEQ_PRINT; params.bed_shrink_y = BED_SHRINK_SEQ_PRINT; } diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index 6b3364236d..005d386fee 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -28,6 +28,8 @@ class ArrangeJob : public Job ArrangePolygons m_selected, m_unselected, m_unprintable, m_locked; std::vector m_unarranged; std::map m_selected_groups; // groups of selected items for sequential printing + std::vector m_uncompatible_plates; // plate indices with different printing sequence than global + arrangement::ArrangeParams params; int current_plate_index = 0; Polygon bed_poly; diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index efcb556456..d671a70c91 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -239,7 +239,21 @@ void FillBedJob::process(Ctl &ctl) // final align用的是凸包,在有fixed item的情况下可能找到的参考点位置是错的,这里就不做了。见STUDIO-3265 params.do_final_align = !is_bbl; - arrangement::arrange(m_selected, m_unselected, m_bedpts, params); + if (m_selected.size() > 100){ + // too many items, just find grid empty cells to put them + Vec2f step = unscaled(get_extents(m_selected.front().poly).size()) + Vec2f(m_selected.front().brim_width, m_selected.front().brim_width); + std::vector empty_cells = Plater::get_empty_cells(step); + size_t n=std::min(m_selected.size(), empty_cells.size()); + for (size_t i = 0; i < n; i++) { + m_selected[i].translation = scaled(empty_cells[i]); + m_selected[i].bed_idx= 0; + } + for (size_t i = n; i < m_selected.size(); i++) { + m_selected[i].bed_idx = -1; + } + } + else + arrangement::arrange(m_selected, m_unselected, m_bedpts, params); // finalize just here. ctl.update_status(100, ctl.was_canceled() ? @@ -285,10 +299,12 @@ void FillBedJob::finalize(bool canceled, std::exception_ptr &eptr) else ap.bed_idx = cur_plate; - ap.row = ap.bed_idx / plate_cols; - ap.col = ap.bed_idx % plate_cols; - ap.translation(X) += bed_stride_x(m_plater) * ap.col; - ap.translation(Y) -= bed_stride_y(m_plater) * ap.row; + if (m_selected.size() <= 100) { + ap.row = ap.bed_idx / plate_cols; + ap.col = ap.bed_idx % plate_cols; + ap.translation(X) += bed_stride_x(m_plater) * ap.col; + ap.translation(Y) -= bed_stride_y(m_plater) * ap.row; + } ap.apply(); diff --git a/src/slic3r/GUI/Jobs/PrintJob.cpp b/src/slic3r/GUI/Jobs/PrintJob.cpp index 8ff354e7c7..0e7af93f36 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.cpp +++ b/src/slic3r/GUI/Jobs/PrintJob.cpp @@ -281,15 +281,42 @@ void PrintJob::process(Ctl &ctl) } } + params.stl_design_id = 0; if (!wxGetApp().model().stl_design_id.empty()) { - int stl_design_id = 0; - try { - stl_design_id = std::stoi(wxGetApp().model().stl_design_id); + + auto country_code = wxGetApp().app_config->get_country_code(); + bool match_code = false; + + if (wxGetApp().model().stl_design_country == "DEV" && (country_code == "ENV_CN_DEV" || country_code == "NEW_ENV_DEV_HOST")) { + match_code = true; } - catch (const std::exception& e) { - stl_design_id = 0; + + if (wxGetApp().model().stl_design_country == "QA" && (country_code == "ENV_CN_QA" || country_code == "NEW_ENV_QAT_HOST")) { + match_code = true; + } + + if (wxGetApp().model().stl_design_country == "CN_PRE" && (country_code == "ENV_CN_PRE" || country_code == "NEW_ENV_PRE_HOST")) { + match_code = true; + } + + if (wxGetApp().model().stl_design_country == "US_PRE" && country_code == "ENV_US_PRE") { + match_code = true; + } + + if (country_code == wxGetApp().model().stl_design_country) { + match_code = true; + } + + if (match_code) { + int stl_design_id = 0; + try { + stl_design_id = std::stoi(wxGetApp().model().stl_design_id); + } + catch (const std::exception& e) { + stl_design_id = 0; + } + params.stl_design_id = stl_design_id; } - params.stl_design_id = stl_design_id; } if (params.preset_name.empty() && m_print_type == "from_normal") { params.preset_name = wxString::Format("%s_plate_%d", m_project_name, curr_plate_idx).ToStdString(); } diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index 3b23ee7632..944006f3c4 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -27,6 +27,7 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent) , m_bmp_loading(this, "media_loading", 0) , m_bmp_failed(this, "media_failed", 0) , m_bmp_empty(this, "media_empty", 0) + , m_machine("") { SetBackgroundColour(0xEEEEEE); Hide(); @@ -104,7 +105,9 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent) m_button_download->SetToolTip(_L("Download selected files from printer.")); m_button_management = new ::Button(m_manage_panel, _L("Select")); m_button_management->SetToolTip(_L("Batch manage files.")); - for (auto b : {m_button_delete, m_button_download, m_button_management}) { + m_button_refresh = new ::Button(m_manage_panel, _L("Refresh")); + m_button_refresh->SetToolTip(_L("Reload file list from printer.")); + for (auto b : {m_button_delete, m_button_download, m_button_refresh, m_button_management}) { b->SetFont(Label::Body_12); b->SetCornerRadius(12); b->SetPaddingSize({10, 6}); @@ -116,11 +119,16 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent) m_button_management->SetBackgroundColorNormal(wxColor("#009688")); m_button_management->SetTextColorNormal(*wxWHITE); m_button_management->Enable(false); + m_button_refresh->SetBorderWidth(0); + m_button_refresh->SetBackgroundColorNormal(wxColor("#00AE42")); + m_button_refresh->SetTextColorNormal(*wxWHITE); + m_button_refresh->Enable(false); wxBoxSizer *manage_sizer = new wxBoxSizer(wxHORIZONTAL); manage_sizer->AddStretchSpacer(1); manage_sizer->Add(m_button_download, 0, wxALIGN_CENTER_VERTICAL)->Show(false); manage_sizer->Add(m_button_delete, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24)->Show(false); + manage_sizer->Add(m_button_refresh, 0, wxALIGN_CENTER_VERTICAL); manage_sizer->Add(m_button_management, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24); m_manage_panel->SetSizer(manage_sizer); top_sizer->Add(m_manage_panel, 1, wxEXPAND); @@ -171,6 +179,11 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent) e.Skip(); SetSelecting(!m_image_grid->IsSelecting()); }); + m_button_refresh->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { + e.Skip(); + if (auto fs = m_image_grid->GetFileSystem()) + fs->ListAllFiles(); + }); m_button_download->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { m_image_grid->DoActionOnSelection(1); SetSelecting(false); @@ -198,9 +211,7 @@ MediaFilePanel::~MediaFilePanel() SetMachineObject(nullptr); } -wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1); - - void MediaFilePanel::SetMachineObject(MachineObject* obj) +void MediaFilePanel::SetMachineObject(MachineObject* obj) { std::string machine = obj ? obj->dev_id : ""; if (obj) { @@ -208,6 +219,8 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le m_lan_ip = obj->dev_ip; m_lan_passwd = obj->get_access_code(); m_dev_ver = obj->get_ota_version(); + m_device_busy = obj->is_camera_busy_off(); + m_sdcard_exist = obj->has_sdcard(); m_local_support = obj->file_local; m_remote_support = obj->file_remote; m_model_download_support = obj->file_model_download; @@ -216,18 +229,21 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le m_lan_ip.clear(); m_lan_passwd.clear(); m_dev_ver.clear(); + m_sdcard_exist = false; + m_device_busy = false; m_local_support = false; m_remote_support = false; m_model_download_support = false; } - if (machine == m_machine && m_image_grid->GetFileSystem()) { - if (m_waiting_enable && IsEnabled()) { + Enable(obj && obj->is_connected() && obj->m_push_count > 0); + if (machine == m_machine) { + if ((m_waiting_enable && IsEnabled()) || (m_waiting_support && (m_local_support || m_remote_support))) { auto fs = m_image_grid->GetFileSystem(); if (fs) fs->Retry(); } return; } - m_machine = machine; + m_machine.swap(machine); m_last_errors.clear(); auto fs = m_image_grid->GetFileSystem(); if (fs) { @@ -235,12 +251,11 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le fs->Unbind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this); fs->Stop(true); } + m_button_refresh->Enable(false); m_button_management->Enable(false); SetSelecting(false); if (m_machine.empty()) { m_image_grid->SetStatus(m_bmp_failed, _L("No printers.")); - } else if (!m_local_support && !m_remote_support) { - m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not supported on the current printer version)!")); } else { boost::shared_ptr fs(new PrinterFileSystem); fs->Attached(); @@ -253,6 +268,7 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le return; m_time_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL); //m_manage_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL); + m_button_refresh->Enable(fs->GetStatus() == PrinterFileSystem::ListReady); m_button_management->Enable(fs->GetCount() > 0); bool download_support = fs->GetFileType() < PrinterFileSystem::F_MODEL || m_model_download_support; m_image_grid->ShowDownload(download_support); @@ -282,27 +298,21 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le case PrinterFileSystem::Connecting: icon = m_bmp_loading; msg = _L("Connecting..."); break; case PrinterFileSystem::Failed: icon = m_bmp_failed; if (extra != 1) msg = _L("Connect failed [%d]!"); break; case PrinterFileSystem::ListSyncing: icon = m_bmp_loading; msg = _L("Loading file list..."); break; - case PrinterFileSystem::ListReady: icon = extra == 0 ? m_bmp_empty : m_bmp_failed; msg = extra == 0 ? _L("No files [%d]") : _L("Load failed [%d]"); break; + case PrinterFileSystem::ListReady: icon = extra == 0 ? m_bmp_empty : m_bmp_failed; msg = extra == 0 ? _L("No files") : _L("Load failed"); break; } - if (!e.GetString().IsEmpty()) msg = e.GetString(); + int err = fs->GetLastError(); + if (!e.GetString().IsEmpty()) + msg = e.GetString(); + if (err != 0) + msg += " [%d]"; if (fs->GetCount() == 0 && !msg.empty()) m_image_grid->SetStatus(icon, msg); if (e.GetInt() == PrinterFileSystem::Initializing) fetchUrl(boost::weak_ptr(fs)); - int err = fs->GetLastError(); + err = fs->GetLastError(); if ((status == PrinterFileSystem::Failed && m_last_errors.find(err) == m_last_errors.end()) || status == PrinterFileSystem::ListReady) { - json j; - j["code"] = err; - j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; - NetworkAgent* agent = wxGetApp().getAgent(); - if (status == PrinterFileSystem::Failed && err != 0) { - j["result"] = "failed"; - } else if (status == PrinterFileSystem::ListReady) { - j["result"] = "success"; - } m_last_errors.insert(fs->GetLastError()); } }); @@ -314,7 +324,9 @@ wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t le int result = e.GetExtraLong(); if (result > 1 && !e.GetString().IsEmpty()) - MessageDialog(this, e.GetString(), _L("Download failed"), wxOK | wxICON_ERROR).ShowModal(); + CallAfter([this, m = e.GetString()] { + MessageDialog(this, m, _L("Download failed"), wxOK | wxICON_ERROR).ShowModal(); + }); NetworkAgent* agent = wxGetApp().getAgent(); if (result > 1 || result == 0) { @@ -373,6 +385,7 @@ void MediaFilePanel::Rescale() m_button_download->Rescale(); m_button_delete->Rescale(); + m_button_refresh->Rescale(); m_button_management->Rescale(); m_image_grid->Rescale(); @@ -386,6 +399,7 @@ void MediaFilePanel::SetSelecting(bool selecting) bool download_support = fs && fs->GetFileType() < PrinterFileSystem::F_MODEL || m_model_download_support; m_manage_panel->GetSizer()->Show(m_button_download, selecting && download_support); m_manage_panel->GetSizer()->Show(m_button_delete, selecting); + m_manage_panel->GetSizer()->Show(m_button_refresh, !selecting); m_manage_panel->Layout(); } @@ -420,31 +434,60 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr wfs) } m_waiting_enable = false; if (!m_local_support && !m_remote_support) { - m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not supported on the current printer version)!")); + m_waiting_support = true; + m_image_grid->SetStatus(m_bmp_failed, _L("Browsing file in SD card is not supported in current firmware. Please update the printer firmware.")); fs->SetUrl("0"); return; } + if (!m_sdcard_exist) { + m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Storage unavailable, insert SD card.)!")); + fs->SetUrl("0"); + return; + } + if (m_device_busy) { + m_image_grid->SetStatus(m_bmp_failed, _L("The printer is currently busy downloading. Please try again after it finishes.")); + fs->SetUrl("0"); + return; + } + m_waiting_support = false; + NetworkAgent *agent = wxGetApp().getAgent(); + std::string agent_version = agent ? agent->get_version() : ""; if ((m_lan_mode || !m_remote_support) && m_local_support && !m_lan_ip.empty()) { - std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + - "&device=" + m_machine + "&dev_ver=" + m_dev_ver; + std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd; + url += "&device=" + m_machine; + url += "&net_ver=" + agent_version; + url += "&dev_ver=" + m_dev_ver; + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); fs->SetUrl(url); return; } + if (!m_remote_support && m_local_support) { // not support tutk + m_image_grid->SetStatus(m_bmp_failed, _L("Please enter the IP of printer to connect.")); + fs->SetUrl("0"); + fs.reset(); + if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to view sdcard)"))) { + if (auto fs = wfs.lock()) + fs->Retry(); + } + return; + } if (m_lan_mode) { - m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not accessible in LAN-only mode)!")); + m_image_grid->SetStatus(m_bmp_failed, _L("Browsing file in SD card is not supported in LAN Only Mode.")); fs->SetUrl("0"); return; } - if (!m_remote_support && m_local_support) { // not support tutk - m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Missing LAN ip of printer)!")); - fs->SetUrl("1"); - return; - } - NetworkAgent *agent = wxGetApp().getAgent(); if (agent) { agent->get_camera_url(m_machine, - [this, wfs, m = m_machine, v = m_dev_ver](std::string url) { - BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << hide_id_middle_string(hide_passwd(url, {"authkey=", "passwd="}), 9, 20); + [this, wfs, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) { + if (boost::algorithm::starts_with(url, "bambu:///")) { + url += "&device=" + m; + url += "&net_ver=" + v; + url += "&dev_ver=" + dv; + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); + } + BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="}); CallAfter([=] { boost::shared_ptr fs(wfs.lock()); if (!fs || fs != m_image_grid->GetFileSystem()) return; @@ -498,9 +541,11 @@ void MediaFilePanel::doAction(size_t index, int action) if (result == PrinterFileSystem::ERROR_CANCEL) return; if (result != 0) { - MessageDialog(this, - _L("Failed to fetching model infomations from printer."), - _L("Error"), wxOK).ShowModal(); + wxString msg = data.empty() ? _L("Failed to fetch model information from printer.") : + from_u8(data); + CallAfter([this, msg] { + MessageDialog(this, msg, _L("Print"), wxOK).ShowModal(); + }); return; } Slic3r::DynamicPrintConfig config; @@ -511,8 +556,8 @@ void MediaFilePanel::doAction(size_t index, int action) if (!Slic3r::load_gcode_3mf_from_stream(is, &config, &model, &plate_data_list, &file_version) || plate_data_list.empty()) { MessageDialog(this, - _L("Failed to parse model infomations."), - _L("Error"), wxOK).ShowModal(); + _L("Failed to parse model information."), + _L("Print"), wxOK).ShowModal(); return; } diff --git a/src/slic3r/GUI/MediaFilePanel.h b/src/slic3r/GUI/MediaFilePanel.h index 1ae5df7916..0b64cdb5d6 100644 --- a/src/slic3r/GUI/MediaFilePanel.h +++ b/src/slic3r/GUI/MediaFilePanel.h @@ -69,6 +69,7 @@ private: ::StaticBox *m_manage_panel = nullptr; ::Button * m_button_delete = nullptr; ::Button *m_button_download = nullptr; + ::Button *m_button_refresh = nullptr; ::Button *m_button_management = nullptr; ImageGrid * m_image_grid = nullptr; @@ -81,10 +82,13 @@ private: std::string m_lan_passwd; std::string m_dev_ver; bool m_lan_mode = false; + bool m_sdcard_exist = false; bool m_local_support = false; bool m_remote_support = false; bool m_model_download_support = false; + bool m_device_busy = false; bool m_waiting_enable = false; + bool m_waiting_support = false; int m_last_mode = 0; int m_last_type = 0; diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index b5ab46647e..bdc3de924e 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -22,6 +22,16 @@ #endif #include +#include "wx/evtloop.h" + +static std::map error_messages = { + {1, L("The device cannot handle more conversations. Please retry later.")}, + {2, L("Player is malfunctioning. Please reinstall the system player.")}, + {100, L("The player is not loaded, please click \"play\" button to retry.")}, + {101, L("The player is not loaded, please click \"play\" button to retry.")}, + {102, L("The player is not loaded, please click \"play\" button to retry.")}, + {103, L("The player is not loaded, please click \"play\" button to retry.")} +}; namespace Slic3r { namespace GUI { @@ -30,6 +40,7 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w : wxPanel(parent, wxID_ANY, pos, size) , m_media_ctrl(media_ctrl) { + SetLabel("MediaPlayCtrl"); SetBackgroundColour(*wxWHITE); m_media_ctrl->Bind(wxEVT_MEDIA_STATECHANGED, &MediaPlayCtrl::onStateChanged, this); @@ -39,6 +50,39 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w m_label_status = new Label(this, ""); m_label_status->SetForegroundColour(wxColour("#323A3C")); + m_label_stat = new Label(this, ""); + m_label_stat->SetForegroundColour(wxColour("#323A3C")); + m_media_ctrl->Bind(EVT_MEDIA_CTRL_STAT, [this](auto & e) { +#if !BBL_RELEASE_TO_PUBLIC + wxSize size = m_media_ctrl->GetVideoSize(); + m_label_stat->SetLabel(e.GetString() + wxString::Format(" VS:%ix%i", size.x, size.y)); +#endif + wxString str = e.GetString(); + m_stat.clear(); + for (auto k : {"FPS:", "BPS:", "T:", "B:"}) { + auto ik = str.Find(k); + double value = 0; + if (ik != wxString::npos) { + ik += strlen(k); + auto ip = str.find(' ', ik); + if (ip == wxString::npos) ip = str.Length(); + auto v = str.Mid(ik, ip - ik); + if (k == "T:" && v.Length() == 8) { + long h = 0,m = 0,s = 0; + v.Left(2).ToLong(&h); + v.Mid(3, 2).ToLong(&m); + v.Mid(6, 2).ToLong(&s); + value = h * 3600. + m * 60 + s; + } else { + v.ToDouble(&value); + if (v.Right(1) == "K") value *= 1024; + else if (v.Right(1) == "%") value *= 0.01; + } + } + m_stat.push_back(value); + } + }); + m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); }); m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) { m_media_ctrl->Play(); }); // m_label_status->Bind(wxEVT_LEFT_UP, [this](auto &e) { @@ -66,6 +110,7 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_button_play, 0, wxEXPAND | wxALL, 0); + sizer->Add(m_label_stat, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(25)); sizer->AddStretchSpacer(1); sizer->Add(m_label_status, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(25)); SetSizer(sizer); @@ -92,16 +137,9 @@ MediaPlayCtrl::~MediaPlayCtrl() m_tasks.push_back(""); m_cond.notify_all(); } - m_thread.join(); -} - -wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1) -{ - if (length == size_t(-1)) - length = str.Length() - offset; - if (length <= 8) - return str; - return str.Left(offset + 4) + wxString(length - 8, '*') + str.Mid(offset + length - 4); + while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) { + wxEventLoopBase::GetActive()->Yield(); + } } void MediaPlayCtrl::SetMachineObject(MachineObject* obj) @@ -128,13 +166,21 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj) m_remote_support = true; m_device_busy = false; } + Enable(obj && obj->is_connected() && obj->m_push_count > 0); if (machine == m_machine) { if (m_last_state == MEDIASTATE_IDLE && IsEnabled()) Play(); + else if (m_last_state == MEDIASTATE_LOADING && m_tutk_state == "disable" + && m_last_user_play + wxTimeSpan::Seconds(3) < wxDateTime::Now()) { + // resend ttcode to printer + if (auto agent = wxGetApp().getAgent()) + agent->get_camera_url(machine, [](auto) {}); + m_last_user_play = wxDateTime::Now(); + } return; } m_machine = machine; - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << hide_id_middle_string(m_machine); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine; m_disable_lan = false; m_failed_retry = 0; m_last_failed_codes.clear(); @@ -153,6 +199,17 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj) SetStatus("", false); } +wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1) +{ +#if BBL_RELEASE_TO_PUBLIC + if (length == size_t(-1)) length = str.Length() - offset; + if (length <= 8) return str; + return str.Left(offset + 4) + wxString(length - 8, '*') + str.Mid(offset + length - 4); +#else + return str; +#endif +} + wxString hide_passwd(wxString url, std::vector const &passwords) { for (auto &p : passwords) { @@ -166,7 +223,9 @@ wxString hide_passwd(wxString url, std::vector const &passwords) if (j == wxString::npos) j = url.length(); } auto l = size_t(j - i); - if (j == url.length() || url[j] == '@' || url[j] == '&') + if (p[0] == '?' || p[0] == '&') + url = hide_id_middle_string(url, i, l); + else if (j == url.length() || url[j] == '@' || url[j] == '&') url.replace(i, l, l, wxUniChar('*')); } return url; @@ -183,83 +242,98 @@ void MediaPlayCtrl::Play() } m_failed_code = 0; if (m_machine.empty()) { - Stop(_L("Initialize failed (No Device)!")); + Stop(_L("Please confirm if the printer is connected.")); return; } if (!IsEnabled()) { - Stop(_L("Initialize failed (Device connection not ready)!")); - return; - } - if (!m_camera_exists) { - Stop(_L("Initialize failed (No Camera Device)!")); + Stop(_L("Please confirm if the printer is connected.")); return; } if (m_device_busy) { - Stop(_L("Printer is busy downloading, Please wait for the downloading to finish.")); + Stop(_L("The printer is currently busy downloading. Please try again after it finishes.")); m_failed_retry = 0; return; } + if (!m_camera_exists) { + Stop(_L("Printer camera is malfunctioning.")); + return; + } - m_last_state = MEDIASTATE_INITIALIZING; m_button_play->SetIcon("media_stop"); NetworkAgent *agent = wxGetApp().getAgent(); std::string agent_version = agent ? agent->get_version() : ""; - if (m_lan_proto > MachineObject::LVL_None && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) { + if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) { m_disable_lan = m_remote_support && !m_lan_mode; // try remote next time + std::string url; if (m_lan_proto == MachineObject::LVL_Local) - m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd; + url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd; else if (m_lan_proto == MachineObject::LVL_Rtsps) - m_url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps"; + url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps"; else if (m_lan_proto == MachineObject::LVL_Rtsp) - m_url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp"; - m_url += "&device=" + hide_id_middle_string(m_machine); - m_url += "&version=" + agent_version; - m_url += "&dev_ver=" + m_dev_ver; - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(m_url, {m_lan_passwd} ); + url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp"; + url += "&device=" + m_machine; + url += "&net_ver=" + agent_version; + url += "&dev_ver=" + m_dev_ver; + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd}); + m_url = url; load(); return; } - m_disable_lan = false; - if (m_lan_ip.empty()) - m_failed_code = -1; + // m_lan_mode && m_lan_proto > LVL_Disable (use local tunnel) + // m_lan_mode && m_lan_proto == LVL_Disable (*) + // m_lan_mode && m_lan_proto == LVL_None (x) + // !m_lan_mode && m_remote_support (go on) + // !m_lan_mode && !m_remote_support && m_lan_proto > LVL_None (use local tunnel) + // !m_lan_mode && !m_remote_support && m_lan_proto == LVL_Disable (*) + // !m_lan_mode && !m_remote_support && m_lan_proto == LVL_None (x) - if (m_lan_mode) { - Stop(m_lan_proto < 0 - ? _L("Initialize failed (Not supported on the current printer version)!") - : _L("Initialize failed (Not accessible in LAN-only mode)!")); + if (m_lan_proto <= MachineObject::LVL_Disable && (m_lan_mode || !m_remote_support)) { + Stop(m_lan_proto == MachineObject::LVL_None + ? _L("Problem occured. Please update the printer firmware and try again.") + : _L("LAN Only Liveview is off. Please turn on the liveview on printer screen.")); return; } + + m_disable_lan = false; + m_failed_code = 0; + m_last_state = MEDIASTATE_INITIALIZING; if (!m_remote_support) { // not support tutk - Stop(m_lan_ip.empty() - ? _L("Initialize failed (Missing LAN ip of printer)!") - : _L("Initialize failed (Not supported on the current printer version)!")); + m_failed_code = -1; + m_url = "bambu:///local/"; + Stop(_L("Please enter the IP of printer to connect.")); return; } - m_failed_code = 0; + m_label_stat->SetLabel({}); SetStatus(_L("Initializing...")); if (agent) { - agent->get_camera_url(m_machine, [this, m = m_machine, v = agent_version, dv = m_dev_ver](std::string url) { + agent->get_camera_url(m_machine, + [this, m = m_machine, v = agent_version, dv = m_dev_ver](std::string url) { if (boost::algorithm::starts_with(url, "bambu:///")) { - url += "&device=" + into_u8(hide_id_middle_string(m)); - url += "&version=" + v; + url += "&device=" + into_u8(m); + url += "&net_ver=" + v; url += "&dev_ver=" + dv; + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); } - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_id_middle_string(hide_passwd(url, {"authkey=", "passwd="}), 9, 20); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url, + {"?uid=", "authkey=", "passwd=", "license=", "token="}); CallAfter([this, m, url] { if (m != m_machine) { BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m; return; } - m_url = url; if (m_last_state == MEDIASTATE_INITIALIZING) { if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) { m_failed_code = 3; - Stop(wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url))); + Stop(_L("Connection Failed. Please check the network and try again")); } else { + m_url = url; load(); } } else { @@ -270,6 +344,8 @@ void MediaPlayCtrl::Play() } } +void start_ping_test(); + void MediaPlayCtrl::Stop(wxString const &msg) { int last_state = m_last_state; @@ -280,23 +356,41 @@ void MediaPlayCtrl::Stop(wxString const &msg) boost::unique_lock lock(m_mutex); m_tasks.push_back(""); m_cond.notify_all(); - m_last_state = MEDIASTATE_IDLE; if (!msg.IsEmpty()) - SetStatus(msg, false); - else if (m_failed_code) - SetStatus(_L("Stopped [%d]!"), true); - else + SetStatus(msg); + else if (m_failed_code) { + auto iter = error_messages.find(m_failed_code); + auto msg2 = iter == error_messages.end() + ? _L("Please check the network and try again, You can restart or update the printer if the issue persists.") + : _L(iter->second.c_str()); + if (m_failed_code == 1) { + if (m_last_state == wxMEDIASTATE_PLAYING) + msg2 = _L("The printer has been logged out and cannot connect."); + } +#if !BBL_RELEASE_TO_PUBLIC && defined(__WINDOWS__) + if (m_failed_code < 0) + boost::thread ping_thread = Slic3r::create_thread([] { + start_ping_test(); + }); +#endif + SetStatus(msg2); + } else SetStatus(_L("Stopped."), false); - if (m_failed_code >= 100) // not keep retry on local error + m_last_state = MEDIASTATE_IDLE; + bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false"; + if (!auto_retry || m_failed_code >= 100 || m_failed_code == 1) // not keep retry on local error or EOS m_next_retry = wxDateTime(); } else if (!msg.IsEmpty()) { SetStatus(msg, false); + return; } else { m_failed_code = 0; + return; } - - bool remote = m_url.find("/local/") == wxString::npos && m_url.find("/rtsp") == wxString::npos; + auto tunnel = m_url.empty() ? "" : into_u8(wxURI(m_url).GetPath()).substr(1); + if (auto n = tunnel.find_first_of('/_'); n != std::string::npos) + tunnel = tunnel.substr(0, n); if (last_state != wxMEDIASTATE_PLAYING && m_failed_code != 0 && m_last_failed_codes.find(m_failed_code) == m_last_failed_codes.end() && (m_user_triggered || m_failed_retry > 3)) { @@ -305,7 +399,9 @@ void MediaPlayCtrl::Stop(wxString const &msg) m_url.clear(); ++m_failed_retry; - if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && !remote && (m_failed_retry > 1 || m_user_triggered)) { + bool local = tunnel == "local" || tunnel == "rtsp" || + tunnel == "rtsps"; + if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && local && (m_failed_retry > 1 || m_user_triggered)) { m_next_retry = wxDateTime(); // stop retry if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to start liveview)"))) { m_failed_retry = 0; @@ -369,13 +465,13 @@ void MediaPlayCtrl::ToggleStream() DownloadProgressDialog2(MediaPlayCtrl *ctrl) : DownloadProgressDialog(_L("Downloading Virtual Camera Tools")), ctrl(ctrl) {} struct UpgradeNetworkJob2 : UpgradeNetworkJob { - UpgradeNetworkJob2() { + UpgradeNetworkJob2(std::shared_ptr pri) : UpgradeNetworkJob() { name = "cameratools"; package_name = "camera_tools.zip"; } }; - std::unique_ptr make_job() override - { return std::make_unique(); } + std::shared_ptr make_job(std::shared_ptr pri) + { return std::make_shared(pri); } void on_finish() override { ctrl->CallAfter([ctrl = this->ctrl] { ctrl->ToggleStream(); }); @@ -397,7 +493,7 @@ void MediaPlayCtrl::ToggleStream() wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1"); if (res == wxID_CANCEL) return; } - if (m_lan_proto > MachineObject::LVL_None && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) { + if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) { std::string url; if (m_lan_proto == MachineObject::LVL_Local) url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd; @@ -405,9 +501,9 @@ void MediaPlayCtrl::ToggleStream() url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps"; else if (m_lan_proto == MachineObject::LVL_Rtsp) url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp"; - url += "&device=" + into_u8(hide_id_middle_string(m_machine)); + url += "&device=" + into_u8(m_machine); url += "&dev_ver=" + m_dev_ver; - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url, {m_lan_passwd}); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd}); std::string file_url = data_dir() + "/cameratools/url.txt"; boost::nowide::ofstream file(file_url); auto url2 = encode_path(url.c_str()); @@ -421,10 +517,13 @@ void MediaPlayCtrl::ToggleStream() agent->get_camera_url(m_machine, [this, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) { if (boost::algorithm::starts_with(url, "bambu:///")) { url += "&device=" + m; - url += "&version=" + v; + url += "&net_ver=" + v; url += "&dev_ver=" + dv; + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); } - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_id_middle_string(hide_passwd(url, {"authkey=", "passwd="}), 9, 20); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url, + {"?uid=", "authkey=", "passwd=", "license=", "token="}); CallAfter([this, m, url] { if (m != m_machine) return; if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) { @@ -484,7 +583,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) } else if (event.GetId()) { if (m_failed_code == 0) m_failed_code = 2; - Stop(_L("Load failed [%d]!")); + Stop(); } } else { m_last_state = state; @@ -493,14 +592,20 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) void MediaPlayCtrl::SetStatus(wxString const &msg2, bool hyperlink) { - auto msg = wxString::Format(msg2, m_failed_code); - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data(); + auto msg = msg2; + if (m_failed_code != 0) { + int state2 = m_last_state >= MEDIASTATE_IDLE ? m_last_state - MEDIASTATE_IDLE : + m_last_state + MEDIASTATE_BUFFERING - MEDIASTATE_IDLE; + msg += wxString::Format(" [%d:%d]", state2, m_failed_code); + } + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data() << " tutk_state: " << m_tutk_state; #ifdef __WXMSW__ OutputDebugStringA("MediaPlayCtrl::SetStatus: "); OutputDebugStringA(msg.ToUTF8().data()); OutputDebugStringA("\n"); #endif // __WXMSW__ m_label_status->SetLabel(msg); + m_label_status->Wrap(GetSize().GetWidth() - 120 - m_label_stat->GetSize().GetWidth()); long style = m_label_status->GetWindowStyle() & ~LB_HYPERLINK; if (hyperlink) { style |= LB_HYPERLINK; @@ -550,7 +655,7 @@ void MediaPlayCtrl::media_proc() } wxString url = m_tasks.front(); if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "") { - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: busy skip url: " << hide_id_middle_string(hide_passwd(url, {"authkey=", "passwd=", m_lan_passwd}), 9, 20); + BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << url; m_tasks.pop_front(); m_tasks.pop_front(); continue; @@ -586,13 +691,15 @@ void MediaPlayCtrl::media_proc() bool MediaPlayCtrl::start_stream_service(bool *need_install) { #ifdef __WIN32__ - std::string file_source = data_dir() + "\\cameratools\\bambu_source.exe"; - std::string file_ffmpeg = data_dir() + "\\cameratools\\ffmpeg.exe"; - std::string file_ff_cfg = data_dir() + "\\cameratools\\ffmpeg.cfg"; + auto tools_dir = boost::nowide::widen(data_dir()) + L"\\cameratools\\"; + auto file_source = tools_dir + L"bambu_source.exe"; + auto file_ffmpeg = tools_dir + L"ffmpeg.exe"; + auto file_ff_cfg = tools_dir + L"ffmpeg.cfg"; #else - std::string file_source = data_dir() + "/cameratools/bambu_source"; - std::string file_ffmpeg = data_dir() + "/cameratools/ffmpeg"; - std::string file_ff_cfg = data_dir() + "/cameratools/ffmpeg.cfg"; + auto tools_dir = data_dir() + "/cameratools/"; + auto file_source = tools_dir + "bambu_source"; + auto file_ffmpeg = tools_dir + "ffmpeg"; + auto file_ff_cfg = tools_dir + "ffmpeg.cfg"; #endif if (!boost::filesystem::exists(file_source) || !boost::filesystem::exists(file_ffmpeg) || !boost::filesystem::exists(file_ff_cfg)) { if (need_install) *need_install = true; @@ -615,14 +722,15 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install) boost::process::pipe intermediate; boost::filesystem::path start_dir(boost::filesystem::path(data_dir()) / "plugins"); #ifdef __WXMSW__ - start_dir = boost::filesystem::path(data_dir()) / "cameratools"; - std::string file_dll = data_dir() + "/cameratools/BambuSource.dll"; - std::string file_dll2 = data_dir() + "/plugins/BambuSource.dll"; - if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2)) - boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists); - static std::locale tmp = std::locale(std::locale(), new boost::nowide::utf8_codecvt()); - boost::process::imbue(tmp); - boost::process::child process_source(file_source, into_u8(file_url2), boost::process::start_dir(start_dir), boost::process::windows::create_no_window, + auto plugins_dir = boost::nowide::widen(data_dir()) + L"\\plugins\\"; + for (auto dll : {L"BambuSource.dll", L"live555.dll"}) { + auto file_dll = tools_dir + dll; + auto file_dll2 = plugins_dir + dll; + if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2)) + boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists); + } + boost::process::child process_source(file_source, file_url2.ToStdWstring(), boost::process::start_dir(tools_dir), + boost::process::windows::create_no_window, boost::process::std_out > intermediate, boost::process::limit_handles); boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window, boost::process::std_in < intermediate, boost::process::limit_handles); @@ -636,7 +744,7 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install) process_source.detach(); process_ffmpeg.detach(); } catch (std::exception &e) { - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl failed to start camera stream: " << e.what(); + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl failed to start camera stream: " << decode_path(e.what()); return false; } return true; @@ -687,20 +795,18 @@ void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags) #else wxMediaCtrl::DoSetSize(x, y, width, height, sizeFlags); #endif - //if (sizeFlags & wxSIZE_USE_EXISTING) return; - //wxSize size = GetVideoSize(); - //if (size.GetWidth() <= 0) - // size = wxSize{16, 9}; - //int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth(); - //if (maxHeight != GetMaxHeight()) { - // // BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight; - // SetMaxSize({-1, maxHeight}); - // CallAfter([this] { - // if (auto p = GetParent()) { - // p->Layout(); - // p->Refresh(); - // } - // }); - //} + if (sizeFlags & wxSIZE_USE_EXISTING) return; + wxSize size = m_video_size; + int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth(); + if (maxHeight != GetMaxHeight()) { + // BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight; + SetMaxSize({-1, maxHeight}); + CallAfter([this] { + if (auto p = GetParent()) { + p->Layout(); + p->Refresh(); + } + }); + } } diff --git a/src/slic3r/GUI/MediaPlayCtrl.h b/src/slic3r/GUI/MediaPlayCtrl.h index 79ce3a4b9c..c4e088876c 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.h +++ b/src/slic3r/GUI/MediaPlayCtrl.h @@ -95,11 +95,13 @@ private: bool m_user_triggered = false; int m_failed_retry = 0; int m_failed_code = 0; + std::vector m_stat; std::set m_last_failed_codes; wxDateTime m_last_user_play; wxDateTime m_next_retry; ::Button *m_button_play; + ::Label * m_label_stat; ::Label * m_label_status; }; diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index 8985e0d3a4..dfb3ef974c 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -121,6 +121,17 @@ AddMachinePanel::~AddMachinePanel() { m_select_machine.Bind(EVT_FINISHED_UPDATE_MACHINE_LIST, [this](wxCommandEvent& e) { m_side_tools->start_interval(); }); + + Bind(EVT_ALREADY_READ_HMS, [this](wxCommandEvent& e) { + auto key = e.GetString().ToStdString(); + auto iter = m_hms_panel->temp_hms_list.find(key); + if (iter != m_hms_panel->temp_hms_list.end()) { + m_hms_panel->temp_hms_list[key].already_read = true; + } + + update_hms_tag(); + e.Skip(); + }); } MonitorPanel::~MonitorPanel() @@ -252,17 +263,20 @@ void MonitorPanel::select_machine(std::string machine_sn) void MonitorPanel::on_update_all(wxMouseEvent &event) { - update_all(); - Layout(); - Refresh(); + if (update_flag) { + update_all(); + Layout(); + Refresh(); + } } void MonitorPanel::on_timer(wxTimerEvent& event) { - update_all(); - - Layout(); - Refresh(); + if (update_flag) { + update_all(); + Layout(); + Refresh(); + } } void MonitorPanel::on_select_printer(wxCommandEvent& event) @@ -270,6 +284,10 @@ void MonitorPanel::on_update_all(wxMouseEvent &event) Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; + if ( dev->get_selected_machine() && (dev->get_selected_machine()->dev_id != event.GetString().ToStdString()) && m_hms_panel) { + m_hms_panel->clear_hms_tag(); + } + if (!dev->set_selected_machine(event.GetString().ToStdString())) return; @@ -348,13 +366,15 @@ void MonitorPanel::update_all() } m_status_info_panel->obj = obj; - m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj); m_upgrade_panel->update(obj); + m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj); m_media_file_panel->SetMachineObject(obj); m_side_tools->update_status(obj); if (!obj) { show_status((int)MONITOR_NO_PRINTER); + m_hms_panel->clear_hms_tag(); + m_tabpanel->GetBtnsListCtrl()->showNewTag(3, false); return; } @@ -380,7 +400,7 @@ void MonitorPanel::update_all() m_status_info_panel->update(obj); } - if (m_hms_panel->IsShown()) { + if (m_hms_panel->IsShown() || (obj->hms_list.size() != m_hms_panel->temp_hms_list.size())) { m_hms_panel->update(obj); } @@ -389,6 +409,21 @@ void MonitorPanel::update_all() m_upgrade_panel->update(obj); } #endif + + update_hms_tag(); +} + +void MonitorPanel::update_hms_tag() +{ + for (auto hmsitem : m_hms_panel->temp_hms_list) { + if (!hmsitem.second.already_read) { + //show HMS new tag + m_tabpanel->GetBtnsListCtrl()->showNewTag(3, true); + return; + } + } + + m_tabpanel->GetBtnsListCtrl()->showNewTag(3, false); } bool MonitorPanel::Show(bool show) @@ -400,6 +435,8 @@ bool MonitorPanel::Show(bool show) NetworkAgent* m_agent = wxGetApp().getAgent(); DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (show) { + start_update(); + m_refresh_timer->Stop(); m_refresh_timer->SetOwner(this); m_refresh_timer->Start(REFRESH_INTERVAL); @@ -418,6 +455,7 @@ bool MonitorPanel::Show(bool show) } } } else { + stop_update(); m_refresh_timer->Stop(); } return wxPanel::Show(show); @@ -470,7 +508,6 @@ Freeze(); m_status_info_panel->show_status(status); m_hms_panel->show_status(status); m_upgrade_panel->show_status(status); - m_media_file_panel->Enable(status == MonitorStatus::MONITOR_NORMAL); if ((status & (int)MonitorStatus::MONITOR_NO_PRINTER) != 0) { set_default(); diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index cb5615b044..715e3e0c17 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -104,6 +104,7 @@ private: int last_wifi_signal = -1; int last_status; bool m_initialized { false }; + bool update_flag{false}; wxTimer* m_refresh_timer = nullptr; public: @@ -141,6 +142,7 @@ public: //void update_ams(MachineObject* obj); void update_all(); + void update_hms_tag(); bool Show(bool show); void update_side_panel(); @@ -148,6 +150,9 @@ public: MachineObject *obj { nullptr }; std::string last_conn_type = "undedefined"; + + void stop_update() {update_flag = false;}; + void start_update() {update_flag = true;}; }; diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp index c8efc1b9eb..c5e0881ec8 100644 --- a/src/slic3r/GUI/Mouse3DController.cpp +++ b/src/slic3r/GUI/Mouse3DController.cpp @@ -146,11 +146,13 @@ static std::string format_device_string(int vid, int pid) static std::string detect_attached_device() { std::string ret; - // Initialize the hidapi library int res = hid_init(); if (res != 0) BOOST_LOG_TRIVIAL(error) << "Unable to initialize hidapi library"; + else if (wxGetApp().app_config->get("skip_3dmouse_detect") == "true") { + BOOST_LOG_TRIVIAL(info) << "do not detect 3d Mouse"; + } else { // Enumerates devices hid_device_info* devices = hid_enumerate(0, 0); @@ -927,7 +929,7 @@ void Mouse3DController::run() bool Mouse3DController::connect_device() { - if (m_stop) + if (m_stop || wxGetApp().app_config->get("skip_3dmouse_detect") == "true") return false; { diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index ed323417aa..daac8b18c8 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -543,6 +543,126 @@ DeleteConfirmDialog::~DeleteConfirmDialog() {} void DeleteConfirmDialog::on_dpi_changed(const wxRect &suggested_rect) {} +Newer3mfVersionDialog::Newer3mfVersionDialog(wxWindow *parent, const Semver *file_version, const Semver *cloud_version, wxString new_keys) + : DPIDialog(parent ? parent : nullptr, wxID_ANY, wxString(SLIC3R_APP_FULL_NAME " - ") + _L("Newer 3mf version"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) + , m_file_version(file_version) + , m_cloud_version(cloud_version) + , m_new_keys(new_keys) +{ + this->SetBackgroundColour(*wxWHITE); + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + // top line + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA)); + main_sizer->Add(m_line_top, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5)); + + wxBoxSizer * content_sizer = new wxBoxSizer(wxHORIZONTAL); + wxStaticBitmap *info_bitmap = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("info", nullptr, 60), wxDefaultPosition, wxSize(FromDIP(70), FromDIP(70)), 0); + wxBoxSizer * msg_sizer = get_msg_sizer(); + content_sizer->Add(info_bitmap, 0, wxEXPAND | wxALL, FromDIP(5)); + content_sizer->Add(msg_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); + main_sizer->Add(content_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); + main_sizer->Add(get_btn_sizer(), 0, wxEXPAND | wxALL, FromDIP(5)); + + this->SetSizer(main_sizer); + Layout(); + Fit(); + wxGetApp().UpdateDlgDarkUI(this); +} + +wxBoxSizer *Newer3mfVersionDialog::get_msg_sizer() +{ + wxBoxSizer *vertical_sizer = new wxBoxSizer(wxVERTICAL); + bool file_version_newer = (*m_file_version) > (*m_cloud_version); + wxStaticText *text1; + wxBoxSizer * horizontal_sizer = new wxBoxSizer(wxHORIZONTAL); + wxString msg_str; + if (file_version_newer) { + text1 = new wxStaticText(this, wxID_ANY, _L("The 3mf file version is in Beta and it is newer than the current Bambu Studio version.")); + wxStaticText * text2 = new wxStaticText(this, wxID_ANY, _L("If you would like to try Bambu Studio Beta, you may click to")); + wxHyperlinkCtrl *github_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Download Beta Version"), "https://github.com/bambulab/BambuStudio/releases"); + horizontal_sizer->Add(text2, 0, wxEXPAND, 0); + horizontal_sizer->Add(github_link, 0, wxEXPAND | wxLEFT, 5); + + } else { + text1 = new wxStaticText(this, wxID_ANY, _L("The 3mf file version is newer than the current Bambu Studio version.")); + wxStaticText *text2 = new wxStaticText(this, wxID_ANY, _L("Update your Bambu Studio could enable all functionality in the 3mf file.")); + horizontal_sizer->Add(text2, 0, wxEXPAND, 0); + } + Semver app_version = *(Semver::parse(SLIC3R_VERSION)); + wxStaticText *cur_version = new wxStaticText(this, wxID_ANY, _L("Current Version: ") + app_version.to_string()); + + vertical_sizer->Add(text1, 0, wxEXPAND | wxTOP, FromDIP(5)); + vertical_sizer->Add(horizontal_sizer, 0, wxEXPAND | wxTOP, FromDIP(5)); + vertical_sizer->Add(cur_version, 0, wxEXPAND | wxTOP, FromDIP(5)); + if (!file_version_newer) { + wxStaticText *latest_version = new wxStaticText(this, wxID_ANY, _L("Latest Version: ") + m_cloud_version->to_string()); + vertical_sizer->Add(latest_version, 0, wxEXPAND | wxTOP, FromDIP(5)); + } + + wxStaticText *unrecognized_keys = new wxStaticText(this, wxID_ANY, m_new_keys); + vertical_sizer->Add(unrecognized_keys, 0, wxEXPAND | wxTOP, FromDIP(10)); + + return vertical_sizer; +} + +wxBoxSizer *Newer3mfVersionDialog::get_btn_sizer() +{ + wxBoxSizer *horizontal_sizer = new wxBoxSizer(wxHORIZONTAL); + horizontal_sizer->Add(0, 0, 1, wxEXPAND, 0); + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(wxColour(0, 174, 66), StateColor::Normal)); + StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + bool file_version_newer = (*m_file_version) > (*m_cloud_version); + if (!file_version_newer) { + m_update_btn = new Button(this, _L("Update")); + m_update_btn->SetBackgroundColor(btn_bg_green); + m_update_btn->SetBorderColor(*wxWHITE); + m_update_btn->SetTextColor(wxColour(0xFFFFFE)); + m_update_btn->SetFont(Label::Body_12); + m_update_btn->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_update_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_update_btn->SetCornerRadius(FromDIP(12)); + horizontal_sizer->Add(m_update_btn, 0, wxRIGHT, FromDIP(10)); + + m_update_btn->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { + EndModal(wxID_OK); + if (wxGetApp().app_config->has("app", "cloud_software_url")) { + std::string download_url = wxGetApp().app_config->get("app", "cloud_software_url"); + wxLaunchDefaultBrowser(download_url); + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "Bambu Studio conf has no cloud_software_url and file_version: " << m_file_version->to_string() + << " and cloud_version: " << m_cloud_version->to_string(); + } + }); + } + + if (!file_version_newer) { + m_later_btn = new Button(this, _L("Not for now")); + m_later_btn->SetBackgroundColor(btn_bg_white); + m_later_btn->SetBorderColor(wxColour(38, 46, 48)); + } else { + m_later_btn = new Button(this, _L("OK")); + m_later_btn->SetBackgroundColor(btn_bg_green); + m_later_btn->SetBorderColor(*wxWHITE); + m_later_btn->SetTextColor(wxColour(0xFFFFFE)); + } + m_later_btn->SetFont(Label::Body_12); + m_later_btn->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_later_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_later_btn->SetCornerRadius(FromDIP(12)); + horizontal_sizer->Add(m_later_btn, 0, wxRIGHT, FromDIP(10)); + m_later_btn->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { + EndModal(wxID_OK); + }); + return horizontal_sizer; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index 58e113acbe..a7acc42de2 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -1,7 +1,3 @@ -///|/ Copyright (c) Prusa Research 2018 - 2022 Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral -///|/ -///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher -///|/ #ifndef slic3r_MsgDialog_hpp_ #define slic3r_MsgDialog_hpp_ @@ -20,6 +16,7 @@ #include "Widgets/TextInput.hpp" #include "BBLStatusBar.hpp" #include "BBLStatusBarSend.hpp" +#include "libslic3r/Semver.hpp" class wxBoxSizer; class wxCheckBox; @@ -392,6 +389,27 @@ private: wxStaticText *m_msg_text = nullptr; }; +class Newer3mfVersionDialog : public DPIDialog +{ +public: + Newer3mfVersionDialog(wxWindow *parent, const Semver* file_version, const Semver* cloud_version, wxString new_keys); + ~Newer3mfVersionDialog(){}; + virtual void on_dpi_changed(const wxRect &suggested_rect){}; + +private: + wxBoxSizer *get_msg_sizer(); + wxBoxSizer *get_btn_sizer(); + + +private: + const Semver *m_file_version; + const Semver *m_cloud_version; + wxString m_new_keys; + Button * m_update_btn = nullptr; + Button * m_later_btn = nullptr; + wxStaticText *m_msg_text = nullptr; +}; + } } diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index b320ea4f4a..fdf4f765b8 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -1532,7 +1532,10 @@ void ObjectDataViewModel::assembly_name(ObjectDataViewModelNode* item, wxString auto type = this->GetItemType(wxDataViewItem(item)); if (type != itPlate) { wxString str = name + ":" + item->GetName(); - assembly_name_list.push_back(std::make_pair(item, str)); + assembly_name_list.push_back(std::make_tuple(item, str, str)); + } + else { + assembly_name_list.push_back(std::make_tuple(item, name, name)); } for (size_t i = 0; i < item->GetChildCount(); ++i) { wxString str_name = name + ":" + item->GetName(); @@ -1552,18 +1555,27 @@ void ObjectDataViewModel::search_object(wxString search_text) search_found_list.clear(); search_text = search_text.MakeLower(); - for (auto pair : assembly_name_list) { - wxString need_str = pair.second.AfterFirst(':'); - need_str = need_str.MakeLower(); - size_t pos = need_str.find(search_text); - if ( pos != wxString::npos) { - size_t len = search_text.length(); - size_t before_size = pair.second.BeforeFirst(':').length(); - wxString new_search_str = "" + pair.second.Mid(before_size + pos + 1, len) + ""; - wxString new_str = pair.second.Mid(0, before_size + pos + 1) + new_search_str + pair.second.Mid(before_size + pos + len + 1, wxString::npos); + for (const auto& [model_node, name, tip] : assembly_name_list) { + wxString sub_str = name; + sub_str = sub_str.MakeLower(); - search_found_list.push_back(std::make_pair(pair.first, new_str)); + wxString new_str = ""; + size_t search_text_len = search_text.length(); + size_t curr_str_len = 0; + size_t pos = sub_str.find(search_text); + while (pos != wxString::npos) { + wxString new_search_str = "" + name.Mid(curr_str_len + pos, search_text_len) + ""; + new_str += name.Mid(curr_str_len, pos) + new_search_str; + curr_str_len += search_text_len + pos; + sub_str = sub_str.substr(pos + search_text_len); + pos = sub_str.find(search_text); } + + if (curr_str_len > 0 && curr_str_len < name.length()) { + new_str += name.substr(curr_str_len); + } + if (!new_str.empty()) + search_found_list.push_back(std::tuple(model_node, new_str, tip)); } } } diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index 47ac80d3d3..83131dc5e0 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -341,8 +341,8 @@ class ObjectDataViewModel :public wxDataViewModel ObjectDataViewModelNode* m_plate_outside; wxDataViewCtrl* m_ctrl { nullptr }; - std::vector> assembly_name_list; - std::vector> search_found_list; + std::vector> assembly_name_list; + std::vector> search_found_list; std::map m_ui_and_3d_volume_map; public: @@ -518,9 +518,9 @@ public: void assembly_name(ObjectDataViewModelNode* item, wxString name); void assembly_name(); - std::vector> get_assembly_name_list() { return assembly_name_list; } + std::vector> get_assembly_name_list() const { return assembly_name_list; } void search_object(wxString search_text); - std::vector> get_found_list() { return search_found_list; } + std::vector> get_found_list() const { return search_found_list; } void sys_color_changed(); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index eb25999cc8..110d91d9ce 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -289,7 +289,7 @@ void OptionsGroup::activate_line(Line& line) // Set sidetext width for a better alignment of options in line // "m_show_modified_btns==true" means that options groups are in tabs if (option_set.size() > 1 && m_use_custom_ctrl) { - // sublabel_width = Field::def_width(); + sublabel_width = Field::def_width() + 1; sidetext_width = Field::def_width_thinner(); } @@ -532,6 +532,9 @@ bool OptionsGroup::activate(std::function throw_if_canceled/* = [](){}*/ return true; } + +void free_window(wxWindow *win); + // delete all controls from the option group void OptionsGroup::clear(bool destroy_custom_ctrl) { @@ -560,8 +563,10 @@ void OptionsGroup::clear(bool destroy_custom_ctrl) if (custom_ctrl) { for (auto const &item : m_fields) { wxWindow* win = item.second.get()->getWindow(); - if (win) + if (win) { + free_window(win); win = nullptr; + } } //BBS: custom_ctrl already destroyed from sizer->clear(), no need to destroy here anymore if (destroy_custom_ctrl) @@ -1048,6 +1053,11 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config ret = 0; break; } + if (!config.has("other_layers_sequence_choice") && opt_key == "other_layers_sequence_choice") { + // reset to Auto value + ret = 0; + break; + } if (!config.has("curr_bed_type") && opt_key == "curr_bed_type") { // reset to global value DynamicConfig& global_cfg = wxGetApp().preset_bundle->project_config; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 61480e49af..119e3394ef 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -282,11 +282,7 @@ PrintSequence PartPlate::get_print_seq() const PrintSequence PartPlate::get_real_print_seq(bool* plate_same_as_global) const { - PrintSequence global_print_seq = PrintSequence::ByDefault; - auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; - if (curr_preset_config.has("print_sequence")) - global_print_seq = curr_preset_config.option>("print_sequence")->value; - + PrintSequence global_print_seq = wxGetApp().global_print_sequence(); PrintSequence curr_plate_seq = get_print_seq(); if (curr_plate_seq == PrintSequence::ByDefault) { curr_plate_seq = global_print_seq; @@ -323,8 +319,20 @@ void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global) std::string key = "spiral_mode"; if (as_global) m_config.erase(key); - else - m_config.set_key_value(key, new ConfigOptionBool(spiral_mode)); + else { + if (spiral_mode) { + if (get_spiral_vase_mode()) + return; + // Secondary confirmation + auto answer = static_cast(wxGetApp().plate_tab)->show_spiral_mode_settings_dialog(false); + if (answer == wxID_YES) { + m_config.set_key_value(key, new ConfigOptionBool(true)); + set_vase_mode_related_object_config(); + } + } + else + m_config.set_key_value(key, new ConfigOptionBool(false)); + } } bool PartPlate::valid_instance(int obj_id, int instance_id) @@ -1020,16 +1028,17 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id) else render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_texture); - if (m_partplate_list->render_plate_settings) { + if (m_partplate_list->render_plate_settings) { + bool has_plate_settings = get_bed_type() != BedType::btDefault || get_print_seq() != PrintSequence::ByDefault || !get_first_layer_print_sequence().empty() || !get_other_layers_print_sequence().empty() || has_spiral_mode_config(); if (hover_id == 5) { - if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault && get_first_layer_print_sequence().empty()) + if (!has_plate_settings) render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_hovered_texture); else render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_changed_hovered_texture); show_tooltip(_u8L("Customize current plate")); } else { - if (get_bed_type() == BedType::btDefault && get_print_seq() == PrintSequence::ByDefault && get_first_layer_print_sequence().empty()) + if (!has_plate_settings) render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_texture); else render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_changed_texture); @@ -1569,11 +1578,19 @@ std::vector PartPlate::get_used_extruders() if (!result) return used_extruders; + std::set used_extruders_set; PrintEstimatedStatistics& ps = result->print_statistics; - for (auto it = ps.volumes_per_extruder.begin(); it != ps.volumes_per_extruder.end(); it++) { - used_extruders.push_back(it->first + 1); - } - return used_extruders; + // model usage + for (const auto&item:ps.volumes_per_extruder) + used_extruders_set.emplace(item.first + 1); + // support usage + for (const auto&item:ps.support_volumes_per_extruder) + used_extruders_set.emplace(item.first + 1); + // wipe tower usage + for (const auto&item:ps.wipe_tower_volumes_per_extruder) + used_extruders_set.emplace(item.first + 1); + + return std::vector(used_extruders_set.begin(), used_extruders_set.end()); } Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double d, int plate_extruder_size, bool use_global_objects) const @@ -1900,6 +1917,16 @@ bool PartPlate::is_valid_gcode_file() return true; } +ModelObjectPtrs PartPlate::get_objects_on_this_plate() { + ModelObjectPtrs objects_ptr; + int obj_id; + for (auto it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); it++) { + obj_id = it->first; + objects_ptr.push_back(m_model->objects[obj_id]); + } + return objects_ptr; +} + ModelInstance* PartPlate::get_instance(int obj_id, int instance_id) { if (!contain_instance(obj_id, instance_id)) @@ -1969,13 +1996,10 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi ModelInstance* instance = object->instances[instance_id]; BoundingBoxf3 instance_box = bounding_box? *bounding_box: object->instance_convex_hull_bounding_box(instance_id); - Vec3d up_point = m_bounding_box.max + Vec3d(Slic3r::BuildVolume::SceneEpsilon, Slic3r::BuildVolume::SceneEpsilon, - m_origin.z() + m_height + Slic3r::BuildVolume::SceneEpsilon); - Vec3d low_point = m_bounding_box.min + Vec3d(-Slic3r::BuildVolume::SceneEpsilon, -Slic3r::BuildVolume::SceneEpsilon, - m_origin.z() - Slic3r::BuildVolume::SceneEpsilon); - Polygon hull = instance->convex_hull_2d(); - if (instance_box.max.z() > low_point.z()) low_point.z() += instance_box.min.z(); // not considering outsize if sinking - BoundingBoxf3 plate_box(low_point, up_point); + Polygon hull = instance->convex_hull_2d(); + BoundingBoxf3 plate_box = get_plate_box(); + if (instance_box.max.z() > plate_box.min.z()) + plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking if (plate_box.contains(instance_box)) { @@ -2018,15 +2042,7 @@ bool PartPlate::intersect_instance(int obj_id, int instance_id, BoundingBoxf3* b ModelObject* object = m_model->objects[obj_id]; ModelInstance* instance = object->instances[instance_id]; BoundingBoxf3 instance_box = bounding_box? *bounding_box: object->instance_convex_hull_bounding_box(instance_id); - Vec3d up_point = - m_bounding_box.max + Vec3d(Slic3r::BuildVolume::SceneEpsilon, Slic3r::BuildVolume::SceneEpsilon, - m_origin.z() + m_height + Slic3r::BuildVolume::SceneEpsilon); - Vec3d low_point = - m_bounding_box.min + Vec3d(-Slic3r::BuildVolume::SceneEpsilon, -Slic3r::BuildVolume::SceneEpsilon, - m_origin.z() - Slic3r::BuildVolume::SceneEpsilon); - BoundingBoxf3 plate_box(low_point, up_point); - - result = plate_box.intersects(instance_box); + result = get_plate_box().intersects(instance_box); } else { @@ -2069,7 +2085,7 @@ int PartPlate::add_instance(int obj_id, int instance_id, bool move_position, Bou ModelInstance* instance = object->instances[instance_id]; std::pair pair(obj_id, instance_id); - obj_to_instance_set.insert(pair); + obj_to_instance_set.insert(pair); BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id %1%, add instance obj_id %2%, instance_id %3%, move_position %4%") % m_plate_index % obj_id % instance_id % move_position; @@ -2267,6 +2283,43 @@ void PartPlate::update_object_index(int obj_idx_removed, int obj_idx_max) } +void PartPlate::set_vase_mode_related_object_config(int obj_id) { + ModelObjectPtrs obj_ptrs; + if (obj_id != -1) { + ModelObject* object = m_model->objects[obj_id]; + obj_ptrs.push_back(object); + } + else + obj_ptrs = get_objects_on_this_plate(); + + DynamicPrintConfig* global_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; + DynamicPrintConfig new_conf; + new_conf.set_key_value("wall_loops", new ConfigOptionInt(1)); + new_conf.set_key_value("top_shell_layers", new ConfigOptionInt(0)); + new_conf.set_key_value("sparse_infill_density", new ConfigOptionPercent(0)); + new_conf.set_key_value("enable_support", new ConfigOptionBool(false)); + new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0)); + new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); + new_conf.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); + new_conf.set_key_value("overhang_reverse", new ConfigOptionBool(false)); + new_conf.set_key_value("wall_direction", new ConfigOptionEnum(WallDirection::Auto)); + auto applying_keys = global_config->diff(new_conf); + + for (ModelObject* object : obj_ptrs) { + ModelConfigObject& config = object->config; + + for (auto opt_key : applying_keys) { + config.set_key_value(opt_key, new_conf.option(opt_key)->clone()); + } + + applying_keys = config.get().diff(new_conf); + for (auto opt_key : applying_keys) { + config.set_key_value(opt_key, new_conf.option(opt_key)->clone()); + } + } + //wxGetApp().obj_list()->update_selections(); +} + int PartPlate::printable_instance_size() { int size = 0; @@ -2512,7 +2565,7 @@ void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon) bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod) { Pointfs new_shape, new_exclude_areas; - + m_raw_shape = shape; for (const Vec2d& p : shape) { new_shape.push_back(Vec2d(p.x() + position.x(), p.y() + position.y())); } @@ -2889,6 +2942,20 @@ std::vector PartPlate::get_first_layer_print_sequence() const return std::vector(); } +std::vector PartPlate::get_other_layers_print_sequence() const +{ + const ConfigOptionInts* other_layers_print_sequence_op = m_config.option("other_layers_print_sequence"); + const ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option("other_layers_print_sequence_nums"); + if (other_layers_print_sequence_op && other_layers_print_sequence_nums_op) { + const std::vector& print_sequence = other_layers_print_sequence_op->values; + int sequence_nums = other_layers_print_sequence_nums_op->value; + auto other_layers_seqs = Slic3r::get_other_layers_print_sequence(sequence_nums, print_sequence); + return other_layers_seqs; + } + else + return {}; +} + void PartPlate::set_first_layer_print_sequence(const std::vector& sorted_filaments) { if (sorted_filaments.size() > 0) { @@ -2908,8 +2975,52 @@ void PartPlate::set_first_layer_print_sequence(const std::vector& sorted_fi } } +void PartPlate::set_other_layers_print_sequence(const std::vector& layer_seq_list) +{ + if (layer_seq_list.empty()) { + m_config.erase("other_layers_print_sequence"); + m_config.erase("other_layers_print_sequence_nums"); + return; + } + + int sequence_nums; + std::vector other_layers_seqs; + Slic3r::get_other_layers_print_sequence(layer_seq_list, sequence_nums, other_layers_seqs); + ConfigOptionInts* other_layers_print_sequence_op = m_config.option("other_layers_print_sequence"); + ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option("other_layers_print_sequence_nums"); + if (other_layers_print_sequence_op) + other_layers_print_sequence_op->values = other_layers_seqs; + else + m_config.set_key_value("other_layers_print_sequence", new ConfigOptionInts(other_layers_seqs)); + if (other_layers_print_sequence_nums_op) + other_layers_print_sequence_nums_op->value = sequence_nums; + else + m_config.set_key_value("other_layers_print_sequence_nums", new ConfigOptionInt(sequence_nums)); +} + void PartPlate::update_first_layer_print_sequence(size_t filament_nums) { + auto other_layers_seqs = get_other_layers_print_sequence(); + if (!other_layers_seqs.empty()) { + bool need_update_data = false; + for (auto& other_layers_seq : other_layers_seqs) { + std::vector& orders = other_layers_seq.second; + if (orders.size() > filament_nums) { + orders.erase(std::remove_if(orders.begin(), orders.end(), [filament_nums](int n) { return n > filament_nums; }), orders.end()); + need_update_data = true; + } + if (orders.size() < filament_nums) { + for (size_t extruder_id = orders.size(); extruder_id < filament_nums; ++extruder_id) { + orders.push_back(extruder_id + 1); + need_update_data = true; + } + } + } + if (need_update_data) + set_other_layers_print_sequence(other_layers_seqs); + } + + ConfigOptionInts * op_print_sequence_1st = m_config.option("first_layer_print_sequence"); if (!op_print_sequence_1st) { return; @@ -3957,7 +4068,7 @@ int PartPlateList::find_instance_belongs(int obj_id, int instance_id) //notify instance's update, need to refresh the instance in plates //newly added or modified -int PartPlateList::notify_instance_update(int obj_id, int instance_id) +int PartPlateList::notify_instance_update(int obj_id, int instance_id, bool is_new) { int ret = 0, index; PartPlate* plate = NULL; @@ -4028,6 +4139,21 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id) } } + auto is_object_config_compatible_with_spiral_vase = [](ModelObject* object) { + const DynamicPrintConfig& config = object->config.get(); + if (config.has("wall_loops") && config.opt_int("wall_loops") == 1 && + config.has("top_shell_layers") && config.opt_int("top_shell_layers") == 0 && + config.has("sparse_infill_density") && config.option("sparse_infill_density")->value == 0 && + config.has("enable_support") && !config.opt_bool("enable_support") && + config.has("enforce_support_layers") && config.opt_int("enforce_support_layers") == 0 && + config.has("ensure_vertical_shell_thickness") && config.opt_bool("ensure_vertical_shell_thickness") && + config.has("detect_thin_wall") && !config.opt_bool("detect_thin_wall") && + config.has("timelapse_type") && config.opt_enum("timelapse_type") == TimelapseType::tlTraditional) + return true; + else + return false; + }; + //try to find a new plate for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i) { @@ -4038,6 +4164,20 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id) { //found a new plate, add it to plate plate->add_instance(obj_id, instance_id, false, &boundingbox); + + // spiral mode, update object setting + if (plate->config()->has("spiral_mode") && plate->config()->opt_bool("spiral_mode") && !is_object_config_compatible_with_spiral_vase(object)) { + if (!is_new) { + auto answer = static_cast(wxGetApp().plate_tab)->show_spiral_mode_settings_dialog(true); + if (answer == wxID_YES) { + plate->set_vase_mode_related_object_config(obj_id); + } + } + else { + plate->set_vase_mode_related_object_config(obj_id); + } + } + plate->update_slice_result_valid_state(); plate->thumbnail_data.reset(); plate->top_thumbnail_data.reset(); diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index b6c5d430ff..8a9f9436b7 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -22,6 +22,7 @@ #include "GLModel.hpp" #include "3DBed.hpp" #include "MeshUtils.hpp" +#include "libslic3r/ParameterUtils.hpp" class GLUquadric; typedef class GLUquadric GLUquadricObject; @@ -116,6 +117,7 @@ private: friend class PartPlateList; + Pointfs m_raw_shape; Pointfs m_shape; Pointfs m_exclude_area; BoundingBoxf3 m_bounding_box; @@ -291,6 +293,7 @@ public: // BBS Vec2d get_size() const { return Vec2d(m_width, m_depth); } ModelObjectPtrs get_objects() { return m_model->objects; } + ModelObjectPtrs get_objects_on_this_plate(); ModelInstance* get_instance(int obj_id, int instance_id); Vec3d get_origin() { return m_origin; } @@ -335,6 +338,9 @@ public: //update object's index caused by original object deleted void update_object_index(int obj_idx_removed, int obj_idx_max); + // set objects configs when enabling spiral vase mode. + void set_vase_mode_related_object_config(int obj_id = -1); + //whether it is empty bool empty() { return obj_to_instance_set.empty(); } @@ -362,10 +368,18 @@ public: void set_hover_id(int id) { m_hover_id = id; } const BoundingBoxf3& get_bounding_box(bool extended = false) { return extended ? m_extended_bounding_box : m_bounding_box; } const BoundingBox get_bounding_box_crd(); + BoundingBoxf3 get_plate_box() {return get_build_volume();} BoundingBoxf3 get_build_volume() { - Vec3d up_point = m_bounding_box.max + Vec3d(0, 0, m_origin.z() + m_height); - Vec3d low_point = m_bounding_box.min + Vec3d(0, 0, m_origin.z()); + auto eps=Slic3r::BuildVolume::SceneEpsilon; + Vec3d up_point = Vec3d(m_origin.x() + m_width + eps, m_origin.y() + m_depth + eps, m_origin.z() + m_height + eps); + Vec3d low_point = Vec3d(m_origin.x() - eps, m_origin.y() - eps, m_origin.z() - eps); + if (m_raw_shape.size() > 0) { + up_point.x() += m_raw_shape[0].x(); + up_point.y() += m_raw_shape[0].y(); + low_point.x() += m_raw_shape[0].x(); + low_point.y() += m_raw_shape[0].y(); + } BoundingBoxf3 plate_box(low_point, up_point); return plate_box; } @@ -460,7 +474,9 @@ public: int load_pattern_box_data(std::string filename); std::vector get_first_layer_print_sequence() const; + std::vector get_other_layers_print_sequence() const; void set_first_layer_print_sequence(const std::vector &sorted_filaments); + void set_other_layers_print_sequence(const std::vector& layer_seq_list); void update_first_layer_print_sequence(size_t filament_nums); void print() const; @@ -733,7 +749,7 @@ public: int find_instance_belongs(int obj_id, int instance_id); //notify instance's update, need to refresh the instance in plates - int notify_instance_update(int obj_id, int instance_id); + int notify_instance_update(int obj_id, int instance_id, bool is_new = false); //notify instance is removed int notify_instance_removed(int obj_id, int instance_id); diff --git a/src/slic3r/GUI/PlateSettingsDialog.cpp b/src/slic3r/GUI/PlateSettingsDialog.cpp index d45c93091d..88f9391773 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.cpp +++ b/src/slic3r/GUI/PlateSettingsDialog.cpp @@ -1,11 +1,368 @@ #include "PlateSettingsDialog.hpp" - +#include "MsgDialog.hpp" namespace Slic3r { namespace GUI { +static constexpr int MIN_LAYER_VALUE = 2; +static constexpr int MAX_LAYER_VALUE = INT_MAX - 1; wxDEFINE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent); +wxDEFINE_EVENT(EVT_NEED_RESORT_LAYERS, wxCommandEvent); -PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title, bool only_first_layer_seq, const wxPoint& pos, const wxSize& size, long style) +bool LayerSeqInfo::operator<(const LayerSeqInfo& another) const +{ + if (this->begin_layer_number < MIN_LAYER_VALUE) + return false; + if (another.begin_layer_number < MIN_LAYER_VALUE) + return true; + if (this->begin_layer_number == another.begin_layer_number) { + if (this->end_layer_number < MIN_LAYER_VALUE) + return false; + if (another.end_layer_number < MIN_LAYER_VALUE) + return true; + return this->end_layer_number < another.end_layer_number; + } + return this->begin_layer_number < another.begin_layer_number; +} + +LayerNumberTextInput::LayerNumberTextInput(wxWindow* parent, int layer_number, wxSize size, Type type, ValueType value_type) + :ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, NULL) + , m_layer_number(layer_number) + , m_type(type) + , m_value_type(value_type) +{ + GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_DIGITS)); + GetTextCtrl()->SetFont(::Label::Body_14); + Append(_L("End")); + Append(_L("Customize")); + if (m_value_type == ValueType::End) + SetSelection(0); + if (m_value_type == ValueType::Custom) { + SetSelection(1); + update_label(); + } + + Bind(wxEVT_TEXT, [this](auto& evt) { + if (m_value_type == ValueType::End) { + // TextCtrl->SetValue() will generate a wxEVT_TEXT event + GetTextCtrl()->ChangeValue(_L("End")); + return; + } + evt.Skip(); + }); + + auto validate_input_value = [this](int gui_value) { + // value should not be less than MIN_LAYER_VALUE, and should not be greater than MAX_LAYER_VALUE + gui_value = std::clamp(gui_value, MIN_LAYER_VALUE, MAX_LAYER_VALUE); + + int begin_value; + int end_value; + LayerNumberTextInput* end_layer_input = nullptr; + if (this->m_type == Type::Begin) { + begin_value = gui_value; + end_value = m_another_layer_input->get_layer_number(); + end_layer_input = m_another_layer_input; + } + if (this->m_type == Type::End) { + begin_value = m_another_layer_input->get_layer_number(); + end_value = gui_value; + end_layer_input = this; + } + + // end value should not be less than begin value + if (begin_value > end_value) { + // set new value for end_layer_input + if (this->m_type == Type::Begin) { + if (end_layer_input->is_layer_number_valid()) { + end_layer_input->set_layer_number(begin_value); + } + } + if (this->m_type == Type::End) { + if (!this->is_layer_number_valid()) { + this->set_layer_number(begin_value); + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + } + else { + // do nothing + // reset to the last value for end_layer_input + } + return; + } + } + m_layer_number = gui_value; + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + }; + auto commit_layer_number_from_gui = [this, validate_input_value]() { + if (m_value_type == ValueType::End) + return; + + auto gui_str = GetTextCtrl()->GetValue().ToStdString(); + if (gui_str.empty()) { + m_layer_number = -1; + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + } + if (!gui_str.empty()) { + int gui_value = atoi(gui_str.c_str()); + validate_input_value(gui_value); + } + update_label(); + }; + Bind(wxEVT_TEXT_ENTER, [commit_layer_number_from_gui](wxEvent& evt) { + commit_layer_number_from_gui(); + evt.Skip(); + }); + Bind(wxEVT_KILL_FOCUS, [commit_layer_number_from_gui](wxFocusEvent& evt) { + commit_layer_number_from_gui(); + evt.Skip(); + }); + + Bind(wxEVT_COMBOBOX, [this](auto& e) { + if (e.GetSelection() == 0) { + m_value_type = ValueType::End; + } + else if (e.GetSelection() == 1) { + m_value_type = ValueType::Custom; + m_layer_number = -1; + update_label(); + } + e.Skip(); + }); +} + +void LayerNumberTextInput::update_label() +{ + if (m_value_type == ValueType::End) + return; + + if (!is_layer_number_valid()) { + SetLabel(""); + } + else + SetLabel(std::to_string(m_layer_number)); +} + +void LayerNumberTextInput::set_layer_number(int layer_number) +{ + m_layer_number = layer_number; + if (layer_number == MAX_LAYER_VALUE) + m_value_type = ValueType::End; + else + m_value_type = ValueType::Custom; + + if (m_value_type == ValueType::End) + SetSelection(0); + if (m_value_type == ValueType::Custom) { + SetSelection(1); + update_label(); + } +} + +int LayerNumberTextInput::get_layer_number() +{ + return m_value_type == ValueType::End ? MAX_LAYER_VALUE : m_layer_number; +} + +bool LayerNumberTextInput::is_layer_number_valid() +{ + if (m_value_type == ValueType::End) + return true; + return m_layer_number >= MIN_LAYER_VALUE; +} + +OtherLayersSeqPanel::OtherLayersSeqPanel(wxWindow* parent) + :wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) +{ + m_bmp_delete = ScalableBitmap(this, "delete_filament"); + m_bmp_add = ScalableBitmap(this, "add_filament"); + + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL); + + wxBoxSizer* title_sizer = new wxBoxSizer(wxHORIZONTAL); + m_other_layer_print_seq_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); + m_other_layer_print_seq_choice->Append(_L("Auto")); + m_other_layer_print_seq_choice->Append(_L("Customize")); + m_other_layer_print_seq_choice->SetSelection(0); + wxStaticText* other_layer_txt = new wxStaticText(this, wxID_ANY, _L("Other layer filament sequence")); + other_layer_txt->SetFont(Label::Body_14); + title_sizer->Add(other_layer_txt, 0, wxALIGN_CENTER | wxALIGN_LEFT, 0); + title_sizer->AddStretchSpacer(); + title_sizer->Add(m_other_layer_print_seq_choice, 0, wxALIGN_CENTER | wxALIGN_RIGHT, 0); + + wxBoxSizer* buttons_sizer = new wxBoxSizer(wxHORIZONTAL); + ScalableButton* add_layers_btn = new ScalableButton(this, wxID_ANY, m_bmp_add); + add_layers_btn->SetBackgroundColour(GetBackgroundColour()); + ScalableButton* delete_layers_btn = new ScalableButton(this, wxID_ANY, m_bmp_delete); + delete_layers_btn->SetBackgroundColour(GetBackgroundColour()); + buttons_sizer->Add(add_layers_btn, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + buttons_sizer->Add(delete_layers_btn, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + buttons_sizer->Show(false); + + m_layer_input_panel = new wxPanel(this); + wxBoxSizer* layer_panel_sizer = new wxBoxSizer(wxVERTICAL); + m_layer_input_panel->SetSizer(layer_panel_sizer); + m_layer_input_panel->Hide(); + append_layer(); + + top_sizer->Add(title_sizer, 0, wxEXPAND, 0); + top_sizer->Add(buttons_sizer, 0, wxALIGN_CENTER, 0); + top_sizer->Add(m_layer_input_panel, 0, wxEXPAND, 0); + + SetSizer(top_sizer); + Layout(); + top_sizer->Fit(this); + + + m_other_layer_print_seq_choice->Bind(wxEVT_COMBOBOX, [this, buttons_sizer](auto& e) { + if (e.GetSelection() == 0) { + m_layer_input_panel->Show(false); + buttons_sizer->Show(false); + } + else if (e.GetSelection() == 1) { + m_layer_input_panel->Show(true); + buttons_sizer->Show(true); + } + m_parent->Layout(); + m_parent->Fit(); + }); + add_layers_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { + Freeze(); + append_layer(); + m_parent->Layout(); + m_parent->Fit(); + Thaw(); + }); + delete_layers_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { + popup_layer(); + m_parent->Layout(); + m_parent->Fit(); + }); + Bind(EVT_NEED_RESORT_LAYERS, [this](auto& evt) { + std::vector result; + for (int i = 0; i < m_layer_input_sizer_list.size(); i++) { + int begin_layer_number = m_begin_layer_input_list[i]->get_layer_number(); + int end_layer_number = m_end_layer_input_list[i]->get_layer_number(); + result.push_back({ begin_layer_number, end_layer_number, m_drag_canvas_list[i]->get_shape_list_order() }); + } + if (!std::is_sorted(result.begin(), result.end())) { + std::sort(result.begin(), result.end()); + sync_layers_print_seq(1, result); + } + result.swap(m_layer_seq_infos); + }); + Bind(EVT_SET_BED_TYPE_CONFIRM, [this](auto& evt) { + std::vector result; + for (int i = 0; i < m_layer_input_sizer_list.size(); i++) { + int begin_layer_number = m_begin_layer_input_list[i]->get_layer_number(); + int end_layer_number = m_end_layer_input_list[i]->get_layer_number(); + + if (!m_begin_layer_input_list[i]->is_layer_number_valid() || !m_end_layer_input_list[i]->is_layer_number_valid()) { + MessageDialog msg_dlg(nullptr, _L("Please input layer value (>= 2)."), wxEmptyString, wxICON_WARNING | wxOK); + msg_dlg.ShowModal(); + evt.SetString("Invalid"); + return; + } + + result.push_back({ begin_layer_number, end_layer_number, m_drag_canvas_list[i]->get_shape_list_order() }); + } + result.swap(m_layer_seq_infos); + }); +} + +void OtherLayersSeqPanel::append_layer(const LayerSeqInfo* layer_info) +{ + wxBoxSizer* layer_panel_sizer = static_cast(m_layer_input_panel->GetSizer()); + + wxStaticText* choose_layer_head_txt = new wxStaticText(m_layer_input_panel, wxID_ANY, _L("Layer")); + choose_layer_head_txt->SetFont(Label::Body_14); + + LayerNumberTextInput* begin_layer_input = new LayerNumberTextInput(m_layer_input_panel, -1, wxSize(FromDIP(100), -1), LayerNumberTextInput::Type::Begin, LayerNumberTextInput::ValueType::Custom); + + wxStaticText* choose_layer_to_txt = new wxStaticText(m_layer_input_panel, wxID_ANY, _L("to")); + choose_layer_to_txt->SetFont(Label::Body_14); + + LayerNumberTextInput* end_layer_input = new LayerNumberTextInput(m_layer_input_panel, -1, wxSize(FromDIP(100), -1), LayerNumberTextInput::Type::End, LayerNumberTextInput::ValueType::End); + + begin_layer_input->link(end_layer_input); + if (m_begin_layer_input_list.size() == 0) { + begin_layer_input->set_layer_number(MIN_LAYER_VALUE); + end_layer_input->set_layer_number(MAX_LAYER_VALUE); + } + + const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); + std::vector order(extruder_colours.size()); + for (int i = 0; i < order.size(); i++) { + order[i] = i + 1; + } + auto drag_canvas = new DragCanvas(m_layer_input_panel, extruder_colours, order); + + if (layer_info) { + begin_layer_input->set_layer_number(layer_info->begin_layer_number); + end_layer_input->set_layer_number(layer_info->end_layer_number); + drag_canvas->set_shape_list(extruder_colours, layer_info->print_sequence); + } + + wxBoxSizer* single_layer_input_sizer = new wxBoxSizer(wxHORIZONTAL); + single_layer_input_sizer->Add(choose_layer_head_txt, 0, wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->Add(begin_layer_input, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->Add(choose_layer_to_txt, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, 0); + single_layer_input_sizer->Add(end_layer_input, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->AddStretchSpacer(); + single_layer_input_sizer->Add(drag_canvas, 0, wxLEFT | wxALIGN_CENTER, FromDIP(5)); + layer_panel_sizer->Add(single_layer_input_sizer, 0, wxEXPAND | wxALIGN_CENTER | wxBOTTOM, FromDIP(10)); + m_layer_input_sizer_list.push_back(single_layer_input_sizer); + m_begin_layer_input_list.push_back(begin_layer_input); + m_end_layer_input_list.push_back(end_layer_input); + m_drag_canvas_list.push_back(drag_canvas); +} + +void OtherLayersSeqPanel::popup_layer() +{ + if (m_layer_input_sizer_list.size() > 1) { + m_layer_input_sizer_list.back()->Clear(true); + m_layer_input_sizer_list.pop_back(); + m_begin_layer_input_list.pop_back(); + m_end_layer_input_list.pop_back(); + m_drag_canvas_list.pop_back(); + } +} + +void OtherLayersSeqPanel::clear_all_layers() +{ + for (auto sizer : m_layer_input_sizer_list) { + sizer->Clear(true); + } + m_layer_input_sizer_list.clear(); + m_begin_layer_input_list.clear(); + m_end_layer_input_list.clear(); + m_drag_canvas_list.clear(); +} + +void OtherLayersSeqPanel::sync_layers_print_seq(int selection, const std::vector& seq) +{ + if (m_other_layer_print_seq_choice != nullptr) { + if (selection == 1) { + clear_all_layers(); + Freeze(); + for (int i = 0; i < seq.size(); i++) { + append_layer(&seq[i]); + } + Thaw(); + } + m_other_layer_print_seq_choice->SetSelection(selection); + + wxCommandEvent event(wxEVT_COMBOBOX); + event.SetInt(selection); + event.SetEventObject(m_other_layer_print_seq_choice); + wxPostEvent(m_other_layer_print_seq_choice, event); + } +} + + +PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title, bool only_layer_seq, const wxPoint& pos, const wxSize& size, long style) :DPIDialog(parent, wxID_ANY, title, pos, size, style) { std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str(); @@ -13,10 +370,9 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title SetBackgroundColour(*wxWHITE); wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL); - auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(400), -1)); + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(650), -1)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); - m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); wxFlexGridSizer* top_sizer = new wxFlexGridSizer(0, 2, FromDIP(5), 0); top_sizer->AddGrowableCol(0,1); @@ -40,10 +396,10 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title wxStaticText* m_bed_type_txt = new wxStaticText(this, wxID_ANY, _L("Bed type")); m_bed_type_txt->SetFont(Label::Body_14); - top_sizer->Add(m_bed_type_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); - top_sizer->Add(m_bed_type_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5)); + top_sizer->Add(m_bed_type_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_bed_type_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); - wxBoxSizer* m_sizer_selectbox = new wxBoxSizer(wxHORIZONTAL); + // Print Sequence m_print_seq_choice = new ComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240),-1), 0, NULL, wxCB_READONLY ); m_print_seq_choice->Append(_L("Same as Global Print Sequence")); for (auto i = PrintSequence::ByLayer; i < PrintSequence::ByDefault; i = PrintSequence(int(i) + 1)) { @@ -51,9 +407,21 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title } wxStaticText* m_print_seq_txt = new wxStaticText(this, wxID_ANY, _L("Print sequence")); m_print_seq_txt->SetFont(Label::Body_14); - top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT |wxALL, FromDIP(5)); - top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5)); + top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); + // Spiral mode + m_spiral_mode_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); + m_spiral_mode_choice->Append(_L("Same as Global")); + m_spiral_mode_choice->Append(_L("Enable")); + m_spiral_mode_choice->Append(_L("Disable")); + m_spiral_mode_choice->SetSelection(0); + wxStaticText* spiral_mode_txt = new wxStaticText(this, wxID_ANY, _L("Spiral vase")); + spiral_mode_txt->SetFont(Label::Body_14); + top_sizer->Add(spiral_mode_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_spiral_mode_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); + + // First layer filament sequence m_first_layer_print_seq_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); m_first_layer_print_seq_choice->Append(_L("Auto")); m_first_layer_print_seq_choice->Append(_L("Customize")); @@ -70,22 +438,26 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title }); wxStaticText* first_layer_txt = new wxStaticText(this, wxID_ANY, _L("First layer filament sequence")); first_layer_txt->SetFont(Label::Body_14); - top_sizer->Add(first_layer_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); - top_sizer->Add(m_first_layer_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5)); + top_sizer->Add(first_layer_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_first_layer_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); - std::vector order; - if (order.empty()) { - for (int i = 1; i <= extruder_colours.size(); i++) { - order.push_back(i); - } + std::vector order(extruder_colours.size()); + for (int i = 0; i < order.size(); i++) { + order[i] = i + 1; } m_drag_canvas = new DragCanvas(this, extruder_colours, order); m_drag_canvas->Hide(); - top_sizer->Add(0, 0, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); - top_sizer->Add(m_drag_canvas, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + top_sizer->Add(0, 0, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT, 0); + top_sizer->Add(m_drag_canvas, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxBOTTOM, FromDIP(10)); + + m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, FromDIP(30)); + + // Other layer filament sequence + m_other_layers_seq_panel = new OtherLayersSeqPanel(this); + m_sizer_main->AddSpacer(FromDIP(5)); + m_sizer_main->Add(m_other_layers_seq_panel, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); - m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxALL, FromDIP(30)); auto sizer_button = new wxBoxSizer(wxHORIZONTAL); StateColor btn_bg_green(std::pair(wxColour(0, 137, 123), StateColor::Pressed), std::pair(wxColour(38, 166, 154), StateColor::Hovered), @@ -102,10 +474,12 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetCornerRadius(FromDIP(12)); - m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + m_button_ok->Bind(wxEVT_BUTTON, [this](auto& e) { wxCommandEvent evt(EVT_SET_BED_TYPE_CONFIRM, GetId()); - e.SetEventObject(this); + static_cast(m_other_layers_seq_panel)->ProcessEvent(evt); GetEventHandler()->ProcessEvent(evt); + if (evt.GetString() == "Invalid") + return; if (this->IsModal()) EndModal(wxID_YES); else @@ -119,7 +493,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetCornerRadius(FromDIP(12)); - m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + m_button_cancel->Bind(wxEVT_BUTTON, [this](auto& e) { if (this->IsModal()) EndModal(wxID_NO); else @@ -131,7 +505,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5)); sizer_button->Add(FromDIP(30),0, 0, 0); - m_sizer_main->Add(sizer_button, 0, wxEXPAND, FromDIP(20)); + m_sizer_main->Add(sizer_button, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(20)); SetSizer(m_sizer_main); Layout(); @@ -141,7 +515,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title wxGetApp().UpdateDlgDarkUI(this); - if (only_first_layer_seq) { + if (only_layer_seq) { for (auto item : top_sizer->GetChildren()) { if (item->GetWindow()) item->GetWindow()->Show(false); @@ -149,6 +523,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title first_layer_txt->Show(); m_first_layer_print_seq_choice->Show(); m_drag_canvas->Show(); + m_other_layers_seq_panel->Show(); Layout(); Fit(); } @@ -189,6 +564,21 @@ void PlateSettingsDialog::sync_first_layer_print_seq(int selection, const std::v } } +void PlateSettingsDialog::sync_other_layers_print_seq(int selection, const std::vector& seq) { + if (selection == 1) { + std::vector sequences; + sequences.reserve(seq.size()); + for (int i = 0; i < seq.size(); i++) { + LayerSeqInfo info{ seq[i].first.first, seq[i].first.second, seq[i].second }; + sequences.push_back(info); + } + m_other_layers_seq_panel->sync_layers_print_seq(selection, sequences); + } + else { + m_other_layers_seq_panel->sync_layers_print_seq(selection, {}); + } +} + void PlateSettingsDialog::sync_spiral_mode(bool spiral_mode, bool as_global) { if (m_spiral_mode_choice) { @@ -349,4 +739,6 @@ void PlateNameEditDialog::set_plate_name(const wxString &name) { m_ti_plate_name->GetTextCtrl()->SetInsertionPointEnd(); } -}} // namespace Slic3r::GUI \ No newline at end of file + +} +} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/PlateSettingsDialog.hpp b/src/slic3r/GUI/PlateSettingsDialog.hpp index debad2a7f6..00dbbe4011 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.hpp +++ b/src/slic3r/GUI/PlateSettingsDialog.hpp @@ -7,10 +7,78 @@ #include "Widgets/RadioBox.hpp" #include "Widgets/ComboBox.hpp" #include "DragCanvas.hpp" +#include "libslic3r/ParameterUtils.hpp" namespace Slic3r { namespace GUI { wxDECLARE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent); +wxDECLARE_EVENT(EVT_NEED_RESORT_LAYERS, wxCommandEvent); + +struct LayerSeqInfo { + int begin_layer_number; + int end_layer_number; + std::vector print_sequence; + + bool operator<(const LayerSeqInfo& another) const; +}; + +class LayerNumberTextInput : public ComboBox { +public: + enum class Type { + Begin, + End + }; + enum class ValueType { + Custom, + End + }; + LayerNumberTextInput(wxWindow* parent, int layer_number, wxSize size, Type type, ValueType value_type = ValueType::Custom); + void link(LayerNumberTextInput* layer_input) { + if (m_another_layer_input) return; + m_another_layer_input = layer_input; + layer_input->link(this); } + void set_layer_number(int layer_number); + int get_layer_number(); + Type get_input_type() { return m_type; } + ValueType get_value_type() { return m_value_type; } + bool is_layer_number_valid(); + +protected: + void update_label(); + +private: + LayerNumberTextInput* m_another_layer_input{ nullptr }; + int m_layer_number; + Type m_type; + ValueType m_value_type; +}; + +class OtherLayersSeqPanel : public wxPanel { +public: + OtherLayersSeqPanel(wxWindow* parent); + + void sync_layers_print_seq(int selection, const std::vector& seq); + + int get_layers_print_seq_choice() { return m_other_layer_print_seq_choice->GetSelection(); }; + + std::vector get_layers_print_seq_infos() { return m_layer_seq_infos; } + +protected: + void append_layer(const LayerSeqInfo* layer_info = nullptr); + void popup_layer(); + void clear_all_layers(); + +private: + ScalableBitmap m_bmp_delete; + ScalableBitmap m_bmp_add; + ComboBox* m_other_layer_print_seq_choice{ nullptr }; + wxPanel* m_layer_input_panel{ nullptr }; + std::vector m_layer_input_sizer_list; + std::vector m_begin_layer_input_list; + std::vector m_end_layer_input_list; + std::vector m_drag_canvas_list; + std::vector m_layer_seq_infos; +}; class PlateSettingsDialog : public DPIDialog { @@ -23,7 +91,7 @@ public: PlateSettingsDialog( wxWindow* parent, const wxString& title = wxEmptyString, - bool only_first_layer_seq = false, + bool only_layer_seq = false, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCLOSE_BOX | wxCAPTION @@ -33,6 +101,7 @@ public: void sync_bed_type(BedType type); void sync_print_seq(int print_seq = 0); void sync_first_layer_print_seq(int selection, const std::vector& seq = std::vector()); + void sync_other_layers_print_seq(int selection, const std::vector& seq); void sync_spiral_mode(bool spiral_mode, bool as_global); wxString to_bed_type_name(BedType bed_type); wxString to_print_sequence_name(PrintSequence print_seq); @@ -62,8 +131,25 @@ public: return choice; }; + int get_other_layers_print_seq_choice() { + if (m_other_layers_seq_panel) + return m_other_layers_seq_panel->get_layers_print_seq_choice(); + return 0; + }; + std::vector get_first_layer_print_seq(); + std::vector get_other_layers_print_seq_infos() { + const std::vector& layer_seq_infos = m_other_layers_seq_panel->get_layers_print_seq_infos(); + std::vector result; + result.reserve(layer_seq_infos.size()); + for (int i = 0; i < layer_seq_infos.size(); i++) { + LayerPrintSequence item = std::make_pair(std::make_pair(layer_seq_infos[i].begin_layer_number, layer_seq_infos[i].end_layer_number), layer_seq_infos[i].print_sequence); + result.push_back(item); + } + return result; + } + int get_spiral_mode_choice() { int choice = 0; if (m_spiral_mode_choice != nullptr) @@ -76,11 +162,16 @@ public: } protected: - DragCanvas* m_drag_canvas; - ComboBox* m_first_layer_print_seq_choice { nullptr }; - ComboBox* m_print_seq_choice { nullptr }; + void add_layers(); + void delete_layers(); + +protected: ComboBox* m_bed_type_choice { nullptr }; + ComboBox* m_print_seq_choice { nullptr }; + ComboBox* m_first_layer_print_seq_choice { nullptr }; ComboBox* m_spiral_mode_choice { nullptr }; + DragCanvas* m_drag_canvas; + OtherLayersSeqPanel* m_other_layers_seq_panel; Button* m_button_ok; Button* m_button_cancel; TextInput *m_ti_plate_name; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 22868af0cb..384c6f0b74 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -491,6 +491,45 @@ void Sidebar::priv::hide_rich_tip(wxButton* btn) } #endif +std::vector get_min_flush_volumes() +{ + std::vectorextra_flush_volumes; + const auto& full_config = wxGetApp().preset_bundle->full_config(); + auto& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + + ConfigOption* nozzle_volume_opt = printer_config.option("nozzle_volume"); + int nozzle_volume_val = nozzle_volume_opt ? (int)nozzle_volume_opt->getFloat() : 0; + + int machine_enabled_level = printer_config.option("enable_long_retraction_when_cut")->value; + bool machine_activated = printer_config.option("long_retractions_when_cut")->values[0] == 1; + + auto filament_retraction_distance_when_cut = full_config.option("filament_retraction_distances_when_cut"); + auto printer_retraction_distance_when_cut = full_config.option("retraction_distances_when_cut"); + auto filament_long_retractions_when_cut = full_config.option("filament_long_retractions_when_cut"); + + size_t filament_size = filament_retraction_distance_when_cut->values.size(); + for (size_t idx = 0; idx < filament_size; ++idx) { + int extra_flush_volume = nozzle_volume_val; + int retract_length = machine_enabled_level && machine_activated ? printer_retraction_distance_when_cut->values[0] : 0; + + char filament_activated = filament_long_retractions_when_cut->values[idx]; + double filament_retract_length = filament_retraction_distance_when_cut->values[idx]; + + if (filament_activated == 0) + retract_length = 0; + else if (filament_activated == 1 && machine_enabled_level == LongRectrationLevel::EnableFilament) { + if (!std::isnan(filament_retract_length)) + retract_length = (int)filament_retraction_distance_when_cut->values[idx]; + else + retract_length = printer_retraction_distance_when_cut->values[0]; + } + + extra_flush_volume -= PI * 1.75 * 1.75 / 4 * retract_length; + extra_flush_volumes.emplace_back(extra_flush_volume); + } + return extra_flush_volumes; +} + // Sidebar / public static struct DynamicFilamentList : DynamicList @@ -804,18 +843,14 @@ Sidebar::Sidebar(Plater *parent) p->m_flushing_volume_btn->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent &e) { auto& project_config = wxGetApp().preset_bundle->project_config; - auto& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config; const std::vector& init_matrix = (project_config.option("flush_volumes_matrix"))->values; const std::vector& init_extruders = (project_config.option("flush_volumes_vector"))->values; - ConfigOption* extra_flush_volume_opt = printer_config.option("nozzle_volume"); - int extra_flush_volume = extra_flush_volume_opt ? (int)extra_flush_volume_opt->getFloat() : 0; ConfigOptionFloat* flush_multi_opt = project_config.option("flush_multiplier"); float flush_multiplier = flush_multi_opt ? flush_multi_opt->getFloat() : 1.f; const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); - - WipingDialog dlg(parent, cast(init_matrix), cast(init_extruders), extruder_colours, extra_flush_volume, flush_multiplier); - + const auto& extra_flush_volumes = get_min_flush_volumes(); + WipingDialog dlg(parent, cast(init_matrix), cast(init_extruders), extruder_colours, extra_flush_volumes, flush_multiplier); if (dlg.ShowModal() == wxID_OK) { std::vector matrix = dlg.get_matrix(); std::vector extruders = dlg.get_extruders(); @@ -1864,12 +1899,12 @@ void Sidebar::auto_calc_flushing_volumes(const int modify_id) const std::vector& init_matrix = (project_config.option("flush_volumes_matrix"))->values; const std::vector& init_extruders = (project_config.option("flush_volumes_vector"))->values; - ConfigOption* extra_flush_volume_opt = printer_config.option("nozzle_volume"); - int extra_flush_volume = extra_flush_volume_opt ? (int)extra_flush_volume_opt->getFloat() : 0; + + const std::vector& min_flush_volumes= get_min_flush_volumes(); + ConfigOptionFloat* flush_multi_opt = project_config.option("flush_multiplier"); float flush_multiplier = flush_multi_opt ? flush_multi_opt->getFloat() : 1.f; std::vector matrix = init_matrix; - int m_min_flush_volume = extra_flush_volume; int m_max_flush_volume = Slic3r::g_max_flush_volume; unsigned int m_number_of_extruders = (int)(sqrt(init_matrix.size()) + 0.001); @@ -1896,12 +1931,10 @@ void Sidebar::auto_calc_flushing_volumes(const int modify_id) if (modify_id >= 0 && modify_id < multi_colours.size()) { for (int i = 0; i < multi_colours.size(); ++i) { - - Slic3r::FlushVolCalculator calculator(m_min_flush_volume, m_max_flush_volume); - // from to modify int from_idx = i; if (from_idx != modify_id) { + Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], m_max_flush_volume); int flushing_volume = 0; bool is_from_support = is_support_filament(from_idx); bool is_to_support = is_support_filament(modify_id); @@ -1926,6 +1959,7 @@ void Sidebar::auto_calc_flushing_volumes(const int modify_id) // modify to to int to_idx = i; if (to_idx != modify_id) { + Slic3r::FlushVolCalculator calculator(min_flush_volumes[modify_id], m_max_flush_volume); bool is_from_support = is_support_filament(modify_id); bool is_to_support = is_support_filament(to_idx); int flushing_volume = 0; @@ -2592,7 +2626,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //BBS: add bed_exclude_area , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence", - "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_speed", "skirt_distance", + "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", + "nozzle_height", "skirt_loops", "skirt_speed", "skirt_distance", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume", "extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology", @@ -2855,6 +2890,16 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //preview_canvas->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this); //preview_canvas->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this); //review_canvas->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this); + view3D_canvas->Bind(EVT_GLCANVAS_SWITCH_TO_OBJECT, [main_frame](SimpleEvent&) { + if (main_frame->m_param_panel) { + main_frame->m_param_panel->switch_to_object(false); + } + }); + view3D_canvas->Bind(EVT_GLCANVAS_SWITCH_TO_GLOBAL, [main_frame](SimpleEvent&) { + if (main_frame->m_param_panel) { + main_frame->m_param_panel->switch_to_global(); + } + }); } view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); }); @@ -3349,53 +3394,70 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const return printable_area.bounding_box(); } -std::string read_binary_stl(const std::string& filename) { - std::string model_id; - std::ifstream file(filename, std::ios::binary); + +void read_binary_stl(const std::string& filename, std::string& model_id, std::string& code) { + std::ifstream file( encode_path(filename.c_str()), std::ios::binary); if (!file) { - return model_id; + return; } - try{ + try { // Read the first 80 bytes char data[80]; file.read(data, 80); if (!file) { file.close(); - return model_id; + return; } if (data[0] == '\0' || data[0] == ' ') { file.close(); - return model_id; + return; } char magic[2] = { data[0], data[1] }; if (magic[0] != 'M' || magic[1] != 'W') { file.close(); - return model_id; + return; } if (data[2] != ' ') { file.close(); - return model_id; + return; } char protocol_version[3] = { data[3], data[4], data[5] }; - //version - if (protocol_version[0] == '1' && protocol_version[1] == '.' && protocol_version[2] == '0') { - model_id = std::string(&data[7], &data[80]); + //version + if (protocol_version[0] != '1' || protocol_version[1] != '.' || protocol_version[2] != '0') { + file.close(); + return; } + std::vector tokens; + std::istringstream iss(data); + std::string token; + while (std::getline(iss, token, ' ')) { + char* tokenPtr = new char[token.length() + 1]; + std::strcpy(tokenPtr, token.c_str()); + tokens.push_back(tokenPtr); + } + + //model id + if (tokens.size() < 4) { + file.close(); + return; + } + + model_id = tokens[2]; + code = tokens[3]; file.close(); } - catch (...){ + catch (...) { } - return model_id; + return; } - // BBS: backup & restore std::vector Plater::priv::load_files(const std::vector& input_files, LoadStrategy strategy, bool ask_multi) { @@ -3438,6 +3500,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ std::vector obj_idxs; std::string designer_model_id; + std::string designer_country_code; int answer_convert_from_meters = wxOK_DEFAULT; int answer_convert_from_imperial_units = wxOK_DEFAULT; @@ -3881,9 +3944,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ model = Slic3r::Model::read_from_file( path.string(), nullptr, nullptr, strategy, &plate_data, &project_presets, &is_xxx, &file_version, nullptr, - [this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id](int current, int total, bool &cancel, std::string &mode_id) + [this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id, &designer_country_code](int current, int total, bool &cancel, std::string &mode_id, std::string &code) { designer_model_id = mode_id; + designer_country_code = code; + bool cont = true; float percent_float = (100.0f * (float)i / (float)total_files) + INPUT_FILES_RATIO * 100.0f * ((float)current / (float)total) / (float)total_files; BOOST_LOG_TRIVIAL(trace) << "load_stl_file: percent(float)=" << percent_float << ", curr = " << current << ", total = " << total; @@ -3910,7 +3975,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) { - designer_model_id = read_binary_stl(path.string()); + read_binary_stl(path.string(), designer_model_id, designer_country_code); } if (type_any_amf && is_xxx) imperial_units = true; @@ -4080,10 +4145,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ q->model().load_from(model); load_auxiliary_files(); } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", before load_model_objects, count %1%")%model.objects.size(); auto loaded_idxs = load_model_objects(model.objects, is_project_file); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n"); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", finished load_model_objects"); wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename)); dlg_cont = dlg.Update(progress_percent, msg); if (!dlg_cont) { @@ -4095,7 +4161,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ for (const ModelObject *model_object : model.objects) { new_model->add_object(*model_object); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_ADD_MODEL_OBJECTS \n"); + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":" << __LINE__ << boost::format(", added object %1%")%model_object->name; wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename)); dlg_cont = dlg.Update(progress_percent, msg); if (!dlg_cont) { @@ -4213,9 +4279,16 @@ std::vector Plater::priv::load_files(const std::vector& input_ obj_idxs, model.objects, *notification_manager); //set designer_model_id - if (!designer_model_id.empty() && q->model().stl_design_id.empty()) { - q->model().stl_design_id = designer_model_id; - } + q->model().stl_design_id = designer_model_id; + q->model().stl_design_country = designer_country_code; + //if (!designer_model_id.empty() && q->model().stl_design_id.empty() && !designer_country_code.empty()) { + // q->model().stl_design_id = designer_model_id; + // q->model().stl_design_country = designer_country_code; + //} + //else { + // q->model().stl_design_id = ""; + // q->model().stl_design_country = ""; + //} if (tolal_model_count <= 0 && !q->m_exported_file) { dlg.Hide(); @@ -4309,6 +4382,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& mode } } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", loaded objects, begin to auto placement"); #ifdef AUTOPLACEMENT_ON_LOAD #if 0 // FIXME distance should be a config value ///////////////////////////////// @@ -4353,9 +4427,19 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& mode // _L("Object too large?")); //} + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", finished auto placement, before add_objects_to_list"); notification_manager->close_notification_of_type(NotificationType::UpdatedItemsInfo); - wxGetApp().obj_list()->add_objects_to_list(obj_idxs); + if (obj_idxs.size() > 1) { + std::vector obj_idxs_1 (obj_idxs.begin(), obj_idxs.end() - 1); + + wxGetApp().obj_list()->add_objects_to_list(obj_idxs_1, false); + wxGetApp().obj_list()->add_object_to_list(obj_idxs[obj_idxs.size() - 1]); + } + else + wxGetApp().obj_list()->add_objects_to_list(obj_idxs); + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", after add_objects_to_list"); update(); // Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(), // which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call @@ -4388,7 +4472,14 @@ fs::path Plater::priv::get_export_file_path(GUI::FileType file_type) if (file_type == FT_3MF) // for 3mf take the path from the project filename, if any output_file = into_path(get_project_filename(".3mf")); - + else if (file_type == FT_STL) { + if (obj_idx > 0 && obj_idx < this->model.objects.size() && selection.is_single_full_object()) { + output_file = this->model.objects[obj_idx]->get_export_filename(); + } + else { + output_file = into_path(get_project_name()); + } + } //bbs name the project using the part name if (output_file.empty()) { if (get_project_name() != _L("Untitled")) { @@ -4540,7 +4631,11 @@ void Plater::priv::selection_changed() } // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears) - view3D->render(); + if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + assemble_view->render(); + } else { + view3D->render(); + } } void Plater::priv::object_list_changed() @@ -4965,6 +5060,12 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool notification_manager->set_slicing_progress_hidden(); } + else { + if (preview && preview->get_reload_paint_after_background_process_apply()) { + preview->set_reload_paint_after_background_process_apply(false); + preview->reload_print(); + } + } if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! background_process.empty()) { // The delayed error message is no more valid. @@ -5919,17 +6020,18 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) }; //BBS: add the collapse logic - if (panel == view3D || panel == preview) { - this->enable_sidebar(!q->only_gcode_mode()); - } - if (panel == preview && q->only_gcode_mode()) { - preview->get_canvas3d()->enable_select_plate_toolbar(false); - } - else if (panel == preview && q->using_exported_file() && (q->m_valid_plates_count <= 1)) { - preview->get_canvas3d()->enable_select_plate_toolbar(false); + if (panel == preview) { + if (q->only_gcode_mode()) { + this->sidebar->collapse(true); + preview->get_canvas3d()->enable_select_plate_toolbar(false); + } else if (q->using_exported_file() && (q->m_valid_plates_count <= 1)) { + preview->get_canvas3d()->enable_select_plate_toolbar(false); + } else { + preview->get_canvas3d()->enable_select_plate_toolbar(true); + } } else { - preview->get_canvas3d()->enable_select_plate_toolbar(true); + preview->get_canvas3d()->enable_select_plate_toolbar(false); } if (current_panel == panel) @@ -6002,6 +6104,18 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) else if (old_panel == assemble_view) assemble_view->get_canvas3d()->unbind_event_handlers(); + GLCanvas3D* assemble_canvas = assemble_view->get_canvas3d(); + Selection::IndicesList select_idxs = assemble_canvas->get_selection().get_volume_idxs(); + Selection& view3d_selection = view3D->get_canvas3d()->get_selection(); + view3d_selection.clear(); + for (unsigned int idx : select_idxs) { + auto v = assemble_canvas->get_selection().get_volume(idx); + auto real_idx = view3d_selection.query_real_volume_idx_from_other_view(v->object_idx(), v->instance_idx(), v->volume_idx()); + if (real_idx >= 0) { + view3d_selection.add(real_idx, false); + } + } + view3D->get_canvas3d()->bind_event_handlers(); if (view3D->is_reload_delayed()) { @@ -6080,6 +6194,20 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) assemble_view->get_canvas3d()->bind_event_handlers(); assemble_view->reload_scene(true); + if (old_panel == view3D) { + GLCanvas3D* view3D_canvas = view3D->get_canvas3d(); + Selection::IndicesList select_idxs = view3D_canvas->get_selection().get_volume_idxs(); + Selection& assemble_selection = assemble_view->get_canvas3d()->get_selection(); + assemble_selection.clear(); + for (unsigned int idx : select_idxs) { + auto v = view3D_canvas->get_selection().get_volume(idx); + auto real_idx = assemble_selection.query_real_volume_idx_from_other_view(v->object_idx(), v->instance_idx(), v->volume_idx()); + if (real_idx >= 0) { + assemble_selection.add(real_idx, false); + } + } + } + // BBS set default view and zoom if (first_enter_assemble) { wxGetApp().plater()->get_camera().requires_zoom_to_volumes = true; @@ -6260,6 +6388,12 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) view3D->deselect_all(); } +#if 0 // do not toggle auto calc when change printer + // update flush matrix + size_t filament_size = wxGetApp().plater()->get_extruder_colors_from_plater_config().size(); + for (size_t idx = 0; idx < filament_size; ++idx) + wxGetApp().plater()->sidebar().auto_calc_flushing_volumes(idx); +#endif } #ifdef __WXMSW__ @@ -6268,6 +6402,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // So, set the focus to the combobox explicitly combo->SetFocus(); #endif + if (preset_type == Preset::TYPE_FILAMENT && wxGetApp().app_config->get("auto_calculate_when_filament_change") == "true") { + wxGetApp().plater()->sidebar().auto_calc_flushing_volumes(idx); + } + // BBS: log modify of filament selection Slic3r::put_other_changes(); @@ -7007,13 +7145,14 @@ void Plater::priv::on_filament_color_changed(wxCommandEvent &event) //q->update_all_plate_thumbnails(true); //q->get_preview_canvas3D()->update_plate_thumbnails(); int modify_id = event.GetInt(); - if (wxGetApp().app_config->get("auto_calculate") == "true") { - sidebar->auto_calc_flushing_volumes(modify_id); - } auto& ams_multi_color_filment = wxGetApp().preset_bundle->ams_multi_color_filment; if (modify_id >= 0 && modify_id < ams_multi_color_filment.size()) ams_multi_color_filment[modify_id].clear(); + + if (wxGetApp().app_config->get("auto_calculate") == "true") { + sidebar->auto_calc_flushing_volumes(modify_id); + } } void Plater::priv::install_network_plugin(wxCommandEvent &event) @@ -10026,7 +10165,7 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect) //BBS: remove GCodeViewer as seperate APP logic bool Plater::load_files(const wxArrayString& filenames) { - const std::regex pattern_drop(".*[.](stp|step|stl|obj|amf|3mf|svg)", std::regex::icase); + const std::regex pattern_drop(".*[.](stp|step|stl|oltp|obj|amf|3mf|svg)", std::regex::icase); const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase); std::vector normal_paths; @@ -10342,6 +10481,10 @@ void Plater::select_view(const std::string& direction) { p->select_view(directio //BBS: add no_slice logic void Plater::select_view_3D(const std::string& name, bool no_slice) { p->select_view_3D(name, no_slice); } +void Plater::reload_paint_after_background_process_apply() { + p->preview->set_reload_paint_after_background_process_apply(true); +} + bool Plater::is_preview_shown() const { return p->is_preview_shown(); } bool Plater::is_preview_loaded() const { return p->is_preview_loaded(); } bool Plater::is_view3D_shown() const { return p->is_view3D_shown(); } @@ -10863,12 +11006,24 @@ TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, st csgmesh.reserve(2 * mo.volumes.size()); bool has_splitable_volume = csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh), csg::mpartsPositive | csg::mpartsNegative); - - if (csg::check_csgmesh_booleans(Range{ std::begin(csgmesh), std::end(csgmesh) }) == csgmesh.end()) { + + std::string fail_msg = _u8L("Unable to perform boolean operation on model meshes. " + "Only positive parts will be kept. You may fix the meshes and try agian."); + if (auto fail_reason_name = csg::check_csgmesh_booleans(Range{ std::begin(csgmesh), std::end(csgmesh) }); std::get<0>(fail_reason_name) != csg::BooleanFailReason::OK) { + std::string name = std::get<1>(fail_reason_name); + std::map fail_reasons = { + {csg::BooleanFailReason::OK, "OK"}, + {csg::BooleanFailReason::MeshEmpty, Slic3r::format( _u8L("Reason: part \"%1%\" is empty."), name)}, + {csg::BooleanFailReason::NotBoundAVolume, Slic3r::format(_u8L("Reason: part \"%1%\" does not bound a volume."), name)}, + {csg::BooleanFailReason::SelfIntersect, Slic3r::format(_u8L("Reason: part \"%1%\" has self intersection."), name)}, + {csg::BooleanFailReason::NoIntersection, Slic3r::format(_u8L("Reason: \"%1%\" and another part have no intersection."), name)} }; + fail_msg += " " + fail_reasons[std::get<0>(fail_reason_name)]; + } + else { try { MeshBoolean::mcut::McutMeshPtr meshPtr = csg::perform_csgmesh_booleans_mcut(Range{ std::begin(csgmesh), std::end(csgmesh) }); mesh = MeshBoolean::mcut::mcut_to_triangle_mesh(*meshPtr); - } + } catch (...) {} #if 0 // if mcut fails, try again with CGAL @@ -10884,8 +11039,7 @@ TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, st if (mesh.empty()) { if (notify_func) - notify_func(_u8L("Unable to perform boolean operation on model meshes. " - "Only positive parts will be exported.")); + notify_func(fail_msg); for (const ModelVolume* v : mo.volumes) if (v->is_model_part()) { @@ -12616,6 +12770,38 @@ void Plater::clone_selection() selection.clone(res); } +std::vector Plater::get_empty_cells(const Vec2f step) +{ + PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); + BoundingBoxf3 build_volume = plate->get_build_volume(); + Vec2d vmin(build_volume.min.x(), build_volume.min.y()), vmax(build_volume.max.x(), build_volume.max.y()); + BoundingBoxf bbox(vmin, vmax); + std::vector cells; + auto min_x = step(0)/2;// start_point.x() - step(0) * int((start_point.x() - bbox.min.x()) / step(0)); + auto min_y = step(1)/2;// start_point.y() - step(1) * int((start_point.y() - bbox.min.y()) / step(1)); + auto& exclude_box3s = plate->get_exclude_areas(); + std::vector exclude_boxs; + for (auto& box : exclude_box3s) { + Vec2d vmin(box.min.x(), box.min.y()), vmax(box.max.x(), box.max.y()); + exclude_boxs.emplace_back(vmin, vmax); + } + for (float x = min_x + bbox.min.x(); x < bbox.max.x() - step(0) / 2; x += step(0)) + for (float y = min_y + bbox.min.y(); y < bbox.max.y() - step(1) / 2; y += step(1)) { + bool in_exclude = false; + BoundingBoxf cell(Vec2d(x - step(0) / 2, y - step(1) / 2), Vec2d(x + step(0) / 2, y + step(1) / 2)); + for (auto& box : exclude_boxs) { + if (box.overlap(cell)) { + in_exclude = true; + break; + } + } + if(in_exclude) + continue; + cells.emplace_back(x, y); + } + return cells; +} + void Plater::search(bool plater_is_active, Preset::Type type, wxWindow *tag, TextInput *etag, wxWindow *stag) { if (plater_is_active) { @@ -12936,7 +13122,7 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error) void Plater::open_platesettings_dialog(wxCommandEvent& evt) { int plate_index = evt.GetInt(); - PlateSettingsDialog dlg(this, _L("Plate Settings"), evt.GetString() == "only_first_layer_sequence"); + PlateSettingsDialog dlg(this, _L("Plate Settings"), evt.GetString() == "only_layer_sequence"); PartPlate* curr_plate = p->partplate_list.get_curr_plate(); dlg.sync_bed_type(curr_plate->get_bed_type()); @@ -12953,6 +13139,13 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) { else dlg.sync_first_layer_print_seq(1, curr_plate->get_first_layer_print_sequence()); + auto other_layers_print_seq = curr_plate->get_other_layers_print_sequence(); + if (other_layers_print_seq.empty()) + dlg.sync_other_layers_print_seq(0, {}); + else { + dlg.sync_other_layers_print_seq(1, curr_plate->get_other_layers_print_sequence()); + } + dlg.sync_spiral_mode(curr_plate->get_spiral_vase_mode(), !curr_plate->has_spiral_mode_config()); dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index, &dlg](wxCommandEvent& e) { @@ -12971,6 +13164,11 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) { else curr_plate->set_first_layer_print_sequence({}); + if (dlg.get_other_layers_print_seq_choice() != 0) + curr_plate->set_other_layers_print_sequence(dlg.get_other_layers_print_seq_infos()); + else + curr_plate->set_other_layers_print_sequence({}); + int ps_sel = dlg.get_print_seq_choice(); if (ps_sel != 0) curr_plate->set_print_seq(PrintSequence(ps_sel - 1)); @@ -13348,13 +13546,13 @@ void Plater::post_process_string_object_exception(StringObjectException &err) filament_name = filament_it->alias; } else { auto preset = preset_bundle->filaments.get_preset_base(*filament_it); - if (!preset->alias.empty()) { + if (preset && !preset->alias.empty()) { filament_name = preset->alias; } else { char target = '@'; - size_t pos = preset->name.find(target); + size_t pos = filament_name.find(target); if (pos != std::string::npos) { - filament_name = preset->name.substr(0, pos - 1); + filament_name = filament_name.substr(0, pos - 1); } } } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 681db56703..acc896b07c 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -72,6 +72,7 @@ class Ams; using ModelInstancePtrs = std::vector; + namespace UndoRedo { class Stack; enum class SnapshotType : unsigned char; @@ -342,6 +343,7 @@ public: //BBS: add no_slice logic void select_view_3D(const std::string& name, bool no_slice = true); + void reload_paint_after_background_process_apply(); bool is_preview_shown() const; bool is_preview_loaded() const; bool is_view3D_shown() const; @@ -536,6 +538,8 @@ public: void split_object(); void split_volume(); void optimize_rotation(); + // find all empty cells on the plate and won't overlap with exclusion areas + static std::vector get_empty_cells(const Vec2f step); //BBS: void fill_color(int extruder_id); @@ -823,6 +827,7 @@ private: bool m_was_scheduled; }; +std::vector get_min_flush_volumes(); } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 919e79bd98..525686e770 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -866,6 +866,8 @@ PreferencesDialog::PreferencesDialog(wxWindow *parent, wxWindowID id, const wxSt std::string value; value = wxGetApp().app_config->get("auto_calculate"); j["auto_flushing"] = value; + value = wxGetApp().app_config->get("auto_calculate_when_filament_change"); + j["auto_calculate_when_filament_change"] = value; agent->track_event("preferences_changed", j.dump()); } } catch(...) {} @@ -1030,6 +1032,7 @@ wxWindow* PreferencesDialog::create_general_page() auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints"); auto item_calc_mode = create_item_checkbox(_L("Flushing volumes: Auto-calculate everytime the color changed."), page, _L("If enabled, auto-calculate everytime the color changed."), 50, "auto_calculate"); + auto item_calc_in_long_retract = create_item_checkbox(_L("Flushing volumes: Auto-calculate every time when the filament is changed."), page, _L("If enabled, auto-calculate every time when filament is changed"), 50, "auto_calculate_when_filament_change"); auto item_remember_printer_config = create_item_checkbox(_L("Remember printer configuration"), page, _L("If enabled, Orca will remember and switch filament/process configuration for each printer automatically."), 50, "remember_printer_config"); auto title_presets = create_item_title(_L("Presets"), page, _L("Presets")); auto title_network = create_item_title(_L("Network"), page, _L("Network")); @@ -1094,6 +1097,7 @@ wxWindow* PreferencesDialog::create_general_page() sizer_page->Add(reverse_mouse_zoom, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_show_splash_screen, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3)); + sizer_page->Add(item_calc_in_long_retract, 0, wxTOP, FromDIP(3)); sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20)); sizer_page->Add(item_calc_mode, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3)); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index d037a62394..4b53c0e359 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -625,6 +625,37 @@ bool PresetComboBox::selection_is_changed_according_to_physical_printers() return true; } +void PlaterPresetComboBox::save_custom_color_to_config(const std::vector& colors) +{ + auto set_colors = [](std::map &data, const std::vector &colors) { + for (size_t i = 0; i < colors.size(); i++) { + data[std::to_string(10 + i)] = colors[i]; //for map sort:10 begin + } + }; + if (colors.size() > 0) { + if (!wxGetApp().app_config->has_section("custom_color_list")) { + std::map data; + set_colors(data,colors); + wxGetApp().app_config->set_section("custom_color_list", data); + } else { + auto data = wxGetApp().app_config->get_section("custom_color_list"); + auto data_modify = const_cast *>(&data); + set_colors(*data_modify, colors); + wxGetApp().app_config->set_section("custom_color_list", *data_modify); + } + } +} + +std::vector PlaterPresetComboBox::get_custom_color_from_config() { + std::vector colors; + if (wxGetApp().app_config->has_section("custom_color_list")) { + auto data = wxGetApp().app_config->get_section("custom_color_list"); + for (auto iter : data) { + colors.push_back(iter.second); + } + } + return colors; +} // --------------------------------- // *** PlaterPresetComboBox *** // --------------------------------- @@ -673,13 +704,35 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset m_clrData.SetColour(clr_picker->GetBackgroundColour()); m_clrData.SetChooseFull(true); m_clrData.SetChooseAlpha(false); - + auto color_to_string = [](const wxColour& color) { + std::string str = std::to_string(color.Red()) + "," + std::to_string(color.Green()) + "," + std::to_string(color.Blue()) + "," + std::to_string(color.Alpha()); + return str; + }; + auto string_to_wxColor = [](const std::string& str) { + wxColour color; + std::vector result; + boost::split(result, str, boost::is_any_of(",")); + if (result.size() == 4) { + color = wxColour(std::stoi(result[0]), std::stoi(result[1]), std::stoi(result[2]), std::stoi(result[3])); + } + return color; + }; + std::vector colors=get_custom_color_from_config(); + for (int i = 0; i < colors.size(); i++) { + m_clrData.SetCustomColour(i, string_to_wxColor(colors[i])); + } wxColourDialog dialog(this, &m_clrData); dialog.SetTitle(_L("Please choose the filament colour")); if ( dialog.ShowModal() == wxID_OK ) { m_clrData = dialog.GetColourData(); - + const int custom_color_count = 15; + if (colors.size() != custom_color_count) { + colors.resize(custom_color_count); } + for (int i = 0; i < custom_color_count; i++) { + colors[i] = color_to_string(m_clrData.GetCustomColour(i)); + } + save_custom_color_to_config(colors); // get current color DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config; auto colors = static_cast(cfg->option("filament_colour")->clone()); diff --git a/src/slic3r/GUI/PresetComboBoxes.hpp b/src/slic3r/GUI/PresetComboBoxes.hpp index 954c06862f..6431354643 100644 --- a/src/slic3r/GUI/PresetComboBoxes.hpp +++ b/src/slic3r/GUI/PresetComboBoxes.hpp @@ -164,6 +164,8 @@ public: PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type); ~PlaterPresetComboBox(); + void save_custom_color_to_config(const std::vector &colors); + std::vector get_custom_color_from_config(); ScalableButton* edit_btn { nullptr }; // BBS diff --git a/src/slic3r/GUI/PrintOptionsDialog.cpp b/src/slic3r/GUI/PrintOptionsDialog.cpp index 67d8f4fd52..42667173c6 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.cpp +++ b/src/slic3r/GUI/PrintOptionsDialog.cpp @@ -385,4 +385,185 @@ bool PrintOptionsDialog::Show(bool show) return DPIDialog::Show(show); } +PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) +: DPIDialog(parent, wxID_ANY, _L("Printer Parts"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + nozzle_type_map[0] = "hardened_steel"; + nozzle_type_map[1] = "stainless_steel"; + + nozzle_stainless_diameter_map[0] = 0.2; + nozzle_stainless_diameter_map[1] = 0.4; + + nozzle_hard_diameter_map[0] = 0.4; + nozzle_hard_diameter_map[1] = 0.6; + nozzle_hard_diameter_map[2] = 0.8; + + SetBackgroundColour(*wxWHITE); + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + + + auto m_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line->SetBackgroundColour(wxColour(166, 169, 170)); + + //nozzle type + wxBoxSizer* line_sizer_nozzle_type = new wxBoxSizer(wxHORIZONTAL); + + auto nozzle_type = new Label(this, _L("Nozzle Type")); + nozzle_type->SetFont(Label::Body_14); + nozzle_type->SetMinSize(wxSize(FromDIP(180), -1)); + nozzle_type->SetMaxSize(wxSize(FromDIP(180), -1)); + nozzle_type->SetForegroundColour(STATIC_TEXT_CAPTION_COL); + nozzle_type->Wrap(-1); + + nozzle_type_checkbox = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(140), -1), 0, NULL, wxCB_READONLY); + nozzle_type_checkbox->Append(_L("Stainless Steel")); + nozzle_type_checkbox->Append(_L("Hardened Steel")); + nozzle_type_checkbox->SetSelection(0); + + + line_sizer_nozzle_type->Add(nozzle_type, 0, wxALIGN_CENTER, 5); + line_sizer_nozzle_type->Add(0, 0, 1, wxEXPAND, 5); + line_sizer_nozzle_type->Add(nozzle_type_checkbox, 0, wxALIGN_CENTER, 5); + + + //nozzle diameter + wxBoxSizer* line_sizer_nozzle_diameter = new wxBoxSizer(wxHORIZONTAL); + auto nozzle_diameter = new Label(this, _L("Nozzle Diameter")); + nozzle_diameter->SetFont(Label::Body_14); + nozzle_diameter->SetMinSize(wxSize(FromDIP(180), -1)); + nozzle_diameter->SetMaxSize(wxSize(FromDIP(180), -1)); + nozzle_diameter->SetForegroundColour(STATIC_TEXT_CAPTION_COL); + nozzle_diameter->Wrap(-1); + + nozzle_diameter_checkbox = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(140), -1), 0, NULL, wxCB_READONLY); + + + line_sizer_nozzle_diameter->Add(nozzle_diameter, 0, wxALIGN_CENTER, 5); + line_sizer_nozzle_diameter->Add(0, 0, 1, wxEXPAND, 5); + line_sizer_nozzle_diameter->Add(nozzle_diameter_checkbox, 0, wxALIGN_CENTER, 5); + + sizer->Add(m_line, 0, wxEXPAND, 0); + sizer->Add(0, 0, 0, wxTOP, FromDIP(24)); + sizer->Add(line_sizer_nozzle_type, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(18)); + sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + sizer->Add(line_sizer_nozzle_diameter, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(18)); + sizer->Add(0, 0, 0, wxTOP, FromDIP(24)); + + + nozzle_type_checkbox->Connect( wxEVT_COMBOBOX, wxCommandEventHandler(PrinterPartsDialog::set_nozzle_type), NULL, this ); + nozzle_diameter_checkbox->Connect( wxEVT_COMBOBOX, wxCommandEventHandler(PrinterPartsDialog::set_nozzle_diameter), NULL, this ); + + SetSizer(sizer); + Layout(); + Fit(); + wxGetApp().UpdateDlgDarkUI(this); +} + +PrinterPartsDialog::~PrinterPartsDialog() +{ + nozzle_type_checkbox->Disconnect(wxEVT_COMBOBOX, wxCommandEventHandler(PrinterPartsDialog::set_nozzle_type), NULL, this); + nozzle_diameter_checkbox->Disconnect(wxEVT_COMBOBOX, wxCommandEventHandler(PrinterPartsDialog::set_nozzle_diameter), NULL, this); +} + +void PrinterPartsDialog::set_nozzle_type(wxCommandEvent& evt) +{ + auto type = nozzle_type_map[nozzle_type_checkbox->GetSelection()]; + + if (type == last_nozzle_type) { + return; + } + + std::map diameter_list; + if (type == "hardened_steel") { + diameter_list = nozzle_hard_diameter_map; + } + else if (type == "stainless_steel") { + diameter_list = nozzle_stainless_diameter_map; + } + + nozzle_diameter_checkbox->Clear(); + for (int i = 0; i < diameter_list.size(); i++) + { + nozzle_diameter_checkbox->Append(wxString::Format(_L("%.1f"), diameter_list[i])); + } + nozzle_diameter_checkbox->SetSelection(0); + last_nozzle_type = type; + set_nozzle_diameter(evt); +} + +void PrinterPartsDialog::set_nozzle_diameter(wxCommandEvent& evt) +{ + if (obj) { + try + { + auto nozzle_type = nozzle_type_map[nozzle_type_checkbox->GetSelection()]; + auto nozzle_diameter = std::stof(nozzle_diameter_checkbox->GetStringSelection().ToStdString()); + nozzle_diameter = round(nozzle_diameter * 10) / 10; + + obj->nozzle_diameter = nozzle_diameter; + obj->nozzle_type = nozzle_type; + + obj->command_set_printer_nozzle(nozzle_type, nozzle_diameter); + } + catch (...) {} + } +} + +void PrinterPartsDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + Fit(); +} + +void PrinterPartsDialog::update_machine_obj(MachineObject* obj_) +{ + obj = obj_; +} + +bool PrinterPartsDialog::Show(bool show) +{ + if (show) { + wxGetApp().UpdateDlgDarkUI(this); + CentreOnParent(); + + auto type = obj->nozzle_type; + auto diameter = round(obj->nozzle_diameter * 10) / 10; + + nozzle_type_checkbox->Clear(); + nozzle_diameter_checkbox->Clear(); + + if (type.empty()) { + nozzle_type_checkbox->Disable(); + nozzle_diameter_checkbox->Disable(); + return DPIDialog::Show(show); + } + + last_nozzle_type = type; + + for (int i=0; i < nozzle_type_map.size(); i++) + { + nozzle_type_checkbox->Append( nozzle_type_map[i] ); + if (nozzle_type_map[i] == type) { + nozzle_type_checkbox->SetSelection(i); + } + } + + std::map diameter_list; + if (type == "hardened_steel") { + diameter_list = nozzle_hard_diameter_map; + } + else if (type == "stainless_steel") { + diameter_list = nozzle_stainless_diameter_map; + } + + for (int i = 0; i < diameter_list.size(); i++) + { + nozzle_diameter_checkbox->Append( wxString::Format(_L("%.1f"), diameter_list[i])); + if (diameter_list[i] == diameter) { + nozzle_diameter_checkbox->SetSelection(i); + } + } + } + return DPIDialog::Show(show); +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PrintOptionsDialog.hpp b/src/slic3r/GUI/PrintOptionsDialog.hpp index 21865bda3c..ce67b76720 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.hpp +++ b/src/slic3r/GUI/PrintOptionsDialog.hpp @@ -18,6 +18,27 @@ namespace Slic3r { namespace GUI { +class PrinterPartsDialog : public DPIDialog +{ +protected: + MachineObject* obj{ nullptr }; + ComboBox* nozzle_type_checkbox; + ComboBox* nozzle_diameter_checkbox; + std::string last_nozzle_type; + std::map nozzle_type_map; + std::map nozzle_stainless_diameter_map; + std::map nozzle_hard_diameter_map; +public: + PrinterPartsDialog(wxWindow* parent); + ~PrinterPartsDialog(); + void set_nozzle_type(wxCommandEvent& evt); + void set_nozzle_diameter(wxCommandEvent& evt); + void on_dpi_changed(const wxRect& suggested_rect) override; + void update_machine_obj(MachineObject* obj_); + bool Show(bool show) override; +}; + + class PrintOptionsDialog : public DPIDialog { protected: diff --git a/src/slic3r/GUI/Printer/BambuTunnel.h b/src/slic3r/GUI/Printer/BambuTunnel.h index bd00bdce9c..f578fa0cab 100644 --- a/src/slic3r/GUI/Printer/BambuTunnel.h +++ b/src/slic3r/GUI/Printer/BambuTunnel.h @@ -19,6 +19,8 @@ #ifdef __cplusplus extern "C" { +#else +#include #endif // __cplusplus #ifdef _WIN32 @@ -117,7 +119,9 @@ BAMBU_EXPORT void BAMBU_FUNC(Bambu_SetLogger)(Bambu_Tunnel tunnel, Logger logger BAMBU_EXPORT int BAMBU_FUNC(Bambu_Open)(Bambu_Tunnel tunnel); -BAMBU_EXPORT int BAMBU_FUNC(Bambu_StartStream)(Bambu_Tunnel tunnel, int video); +BAMBU_EXPORT int BAMBU_FUNC(Bambu_StartStream)(Bambu_Tunnel tunnel, bool video); + +BAMBU_EXPORT int BAMBU_FUNC(Bambu_StartStreamEx)(Bambu_Tunnel tunnel, int type); BAMBU_EXPORT int BAMBU_FUNC(Bambu_GetStreamCount)(Bambu_Tunnel tunnel); diff --git a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp index 886421c65f..2da83ed62d 100644 --- a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp +++ b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp @@ -45,9 +45,9 @@ wxDEFINE_EVENT(EVT_FILE_CALLBACK, wxCommandEvent); static wxBitmap default_thumbnail; static std::map error_messages = { - {PrinterFileSystem::ERROR_PIPE, L("Connection lost. Please retry.")}, - {PrinterFileSystem::ERROR_RES_BUSY, L("The device cannot handle more conversations. Please retry later.")}, - {PrinterFileSystem::FILE_NO_EXIST, L("File not exists.")}, + {PrinterFileSystem::ERROR_PIPE, L("Reconnecting the printer, the operation cannot be completed immediately, please try again later.")}, + {PrinterFileSystem::ERROR_RES_BUSY, L("Over 4 studio/handy are using remote access, you can close some and try again.")}, + {PrinterFileSystem::FILE_NO_EXIST, L("File does not exist.")}, {PrinterFileSystem::FILE_CHECK_ERR, L("File checksum error. Please retry.")}, {PrinterFileSystem::FILE_TYPE_ERR, L("Not supported on the current printer version.")}, {PrinterFileSystem::STORAGE_UNAVAILABLE, L("Storage unavailable, insert SD card.")} @@ -203,6 +203,7 @@ void PrinterFileSystem::ListAllFiles() } BuildGroups(); UpdateGroupSelect(); + m_last_error = 0; m_status = Status::ListReady; SendChangedEvent(EVT_STATUS_CHANGED, m_status); SendChangedEvent(EVT_FILE_CHANGED); @@ -357,6 +358,13 @@ void PrinterFileSystem::FetchModel(size_t index, std::functionsecond.c_str()); + else + file_data->clear(); + } callback(result, *file_data); }); } @@ -376,7 +384,7 @@ size_t PrinterFileSystem::GetCount() const int PrinterFileSystem::File::DownloadProgress() const { return download ? download->progress : !local_path.empty() ? 100 : -2; } -std::string PrinterFileSystem::File::Title() const { return Metadata("Title", name); } +std::string PrinterFileSystem::File::Title() const { return Metadata("Title", ""); } std::string PrinterFileSystem::File::Metadata(std::string const &key, std::string const &dflt) const { @@ -981,7 +989,7 @@ void PrinterFileSystem::FileRemoved(std::pair type, size_ m_group_flags.erase(m_group_flags.begin() + index2); } } - m_file_list.erase(file_index.first.begin() + index); + file_index.first.erase(file_index.first.begin() + index); } struct CallbackEvent : wxCommandEvent @@ -1025,10 +1033,7 @@ void PrinterFileSystem::DumpLog(void * thiz, int, tchar const *msg) boost::uint32_t PrinterFileSystem::SendRequest(int type, json const &req, callback_t2 const &callback) { if (m_session.tunnel == nullptr) { - { - boost::unique_lock l(m_mutex); - m_cond.notify_all(); - } + Retry(); callback(ERROR_PIPE, json(), nullptr); return 0; } @@ -1223,7 +1228,7 @@ void PrinterFileSystem::Reconnect(boost::unique_lock &l, int resul if (m_session.tunnel) { auto tunnel = m_session.tunnel; m_session.tunnel = nullptr; - wxLogMessage("PrinterFileSystem::Reconnect close"); + wxLogMessage("PrinterFileSystem::Reconnect close %d", result); l.unlock(); Bambu_Close(tunnel); Bambu_Destroy(tunnel); @@ -1258,6 +1263,8 @@ void PrinterFileSystem::Reconnect(boost::unique_lock &l, int resul if (url.size() < 2) { wxLogMessage("PrinterFileSystem::Reconnect Initialize failed: %s", wxString::FromUTF8(url)); m_last_error = atoi(url.c_str()); + if (m_last_error == 0) + m_stopped = true; } else { wxLogMessage("PrinterFileSystem::Reconnect Initialized: %s", Slic3r::GUI::hide_passwd(wxString::FromUTF8(url), {"authkey=", "passwd="})); l.unlock(); @@ -1271,7 +1278,11 @@ void PrinterFileSystem::Reconnect(boost::unique_lock &l, int resul ret = Bambu_Open(tunnel); } if (ret == 0) - ret = Bambu_StartStream(tunnel, false); + do { + ret = Bambu_StartStreamEx + ? Bambu_StartStreamEx(tunnel, CTRL_TYPE) + : Bambu_StartStream(tunnel, false); + } while (ret == Bambu_would_block); l.lock(); if (ret == 0) { m_session.tunnel = tunnel; @@ -1352,6 +1363,7 @@ StaticBambuLib &StaticBambuLib::get() GET_FUNC(Bambu_Create); GET_FUNC(Bambu_Open); GET_FUNC(Bambu_StartStream); + GET_FUNC(Bambu_StartStreamEx); GET_FUNC(Bambu_GetStreamCount); GET_FUNC(Bambu_GetStreamInfo); GET_FUNC(Bambu_SendMessage); diff --git a/src/slic3r/GUI/ReleaseNote.cpp b/src/slic3r/GUI/ReleaseNote.cpp index 539f9c08e9..85d1d276e1 100644 --- a/src/slic3r/GUI/ReleaseNote.cpp +++ b/src/slic3r/GUI/ReleaseNote.cpp @@ -30,6 +30,7 @@ namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CONFIRM, wxCommandEvent); wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CANCEL, wxCommandEvent); wxDEFINE_EVENT(EVT_SECONDARY_CHECK_DONE, wxCommandEvent); +wxDEFINE_EVENT(EVT_SECONDARY_CHECK_RESUME, wxCommandEvent); wxDEFINE_EVENT(EVT_CHECKBOX_CHANGE, wxCommandEvent); wxDEFINE_EVENT(EVT_ENTER_IP_ADDRESS, wxCommandEvent); wxDEFINE_EVENT(EVT_CLOSE_IPADDRESS_DLG, wxCommandEvent); @@ -649,6 +650,21 @@ SecondaryCheckDialog::SecondaryCheckDialog(wxWindow* parent, wxWindowID id, cons e.Skip(); }); + m_button_resume = new Button(this, _L("resume")); + m_button_resume->SetBackgroundColor(btn_bg_white); + m_button_resume->SetBorderColor(wxColour(38, 46, 48)); + m_button_resume->SetFont(Label::Body_12); + m_button_resume->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_resume->SetMinSize(wxSize(-1, FromDIP(24))); + m_button_resume->SetMaxSize(wxSize(-1, FromDIP(24))); + m_button_resume->SetCornerRadius(FromDIP(12)); + + m_button_resume->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + post_event(wxCommandEvent(EVT_SECONDARY_CHECK_RESUME)); + e.Skip(); + }); + m_button_resume->Hide(); + if (btn_style == CONFIRM_AND_CANCEL) { m_button_cancel->Show(); m_button_fn->Hide(); @@ -673,6 +689,7 @@ SecondaryCheckDialog::SecondaryCheckDialog(wxWindow* parent, wxWindowID id, cons } sizer_button->AddStretchSpacer(); + sizer_button->Add(m_button_resume, 0, wxALL, FromDIP(5)); sizer_button->Add(m_button_retry, 0, wxALL, FromDIP(5)); sizer_button->Add(m_button_fn, 0, wxALL, FromDIP(5)); sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5)); @@ -776,26 +793,39 @@ void SecondaryCheckDialog::update_title_style(wxString title, SecondaryCheckDial m_button_cancel->Show(); m_button_fn->Hide(); m_button_retry->Hide(); + m_button_resume->Hide(); } else if (style == CONFIRM_AND_DONE) { m_button_cancel->Hide(); m_button_fn->Show(); m_button_retry->Hide(); + m_button_resume->Hide(); } else if (style == CONFIRM_AND_RETRY) { m_button_retry->Show(); m_button_cancel->Hide(); m_button_fn->Hide(); + m_button_resume->Hide(); } else if (style == DONE_AND_RETRY) { m_button_retry->Show(); m_button_fn->Show(); m_button_cancel->Hide(); + m_button_resume->Hide(); + } + else if(style == CONFIRM_AND_RESUME) + { + m_button_retry->Hide(); + m_button_fn->Hide(); + m_button_cancel->Hide(); + m_button_resume->Show(); } else { m_button_retry->Hide(); m_button_cancel->Hide(); m_button_fn->Hide(); + m_button_resume->Hide(); + } @@ -965,16 +995,46 @@ void ConfirmBeforeSendDialog::update_text(wxString text) sizer_text_release_note->Add(bottom_blank_sizer, 0, wxALIGN_CENTER | wxALL, FromDIP(5)); m_vebview_release_note->SetSizer(sizer_text_release_note); } - m_staticText_release_note->SetMaxSize(wxSize(FromDIP(330), -1)); - m_staticText_release_note->SetMinSize(wxSize(FromDIP(330), -1)); + m_staticText_release_note->SetMaxSize(wxSize(FromDIP(380), -1)); + m_staticText_release_note->SetMinSize(wxSize(FromDIP(380), -1)); m_staticText_release_note->SetLabelText(text); m_vebview_release_note->Layout(); auto text_size = m_staticText_release_note->GetBestSize(); - if (text_size.y < FromDIP(360)) - m_vebview_release_note->SetMinSize(wxSize(FromDIP(360), text_size.y + FromDIP(25))); + if (text_size.y < FromDIP(380)) + m_vebview_release_note->SetMinSize(wxSize(FromDIP(400), text_size.y + FromDIP(25))); else { - m_vebview_release_note->SetMinSize(wxSize(FromDIP(360), FromDIP(360))); + m_vebview_release_note->SetMinSize(wxSize(FromDIP(400), FromDIP(380))); + } + + Layout(); + Fit(); +} + +void ConfirmBeforeSendDialog::update_text(std::vector texts) +{ + wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL); + m_vebview_release_note->SetSizer(sizer_text_release_note); + + auto height = 0; + for (auto text : texts) { + auto label_item = new Label(m_vebview_release_note, text.text, LB_AUTO_WRAP); + if (text.level == ConfirmBeforeSendInfo::InfoLevel::Warning) { + label_item->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00)); + } + label_item->SetMaxSize(wxSize(FromDIP(380), -1)); + label_item->SetMinSize(wxSize(FromDIP(380), -1)); + label_item->Wrap(FromDIP(380)); + label_item->Layout(); + sizer_text_release_note->Add(label_item, 0, wxALIGN_CENTER | wxALL, FromDIP(3)); + height += label_item->GetSize().y; + } + + m_vebview_release_note->Layout(); + if (height < FromDIP(380)) + m_vebview_release_note->SetMinSize(wxSize(FromDIP(400), height + FromDIP(25))); + else { + m_vebview_release_note->SetMinSize(wxSize(FromDIP(400), FromDIP(380))); } Layout(); @@ -1035,12 +1095,38 @@ void ConfirmBeforeSendDialog::on_dpi_changed(const wxRect& suggested_rect) rescale(); } -void ConfirmBeforeSendDialog::show_update_nozzle_button() +void ConfirmBeforeSendDialog::show_update_nozzle_button(bool show) { - m_button_update_nozzle->Show(true); + m_button_update_nozzle->Show(show); Layout(); } +void ConfirmBeforeSendDialog::hide_button_ok() +{ + m_button_ok->Hide(); +} + +void ConfirmBeforeSendDialog::edit_cancel_button_txt(wxString txt) +{ + m_button_cancel->SetLabel(txt); +} + +void ConfirmBeforeSendDialog::disable_button_ok() +{ + m_button_ok->Disable(); + m_button_ok->SetBackgroundColor(wxColour(0x90, 0x90, 0x90)); + m_button_ok->SetBorderColor(wxColour(0x90, 0x90, 0x90)); +} + +void ConfirmBeforeSendDialog::enable_button_ok() +{ + m_button_ok->Enable(); + StateColor btn_bg_green(std::pair(wxColour(61, 203, 115), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + m_button_ok->SetBackgroundColor(btn_bg_green); + m_button_ok->SetBorderColor(btn_bg_green); +} + void ConfirmBeforeSendDialog::rescale() { m_button_ok->Rescale(); diff --git a/src/slic3r/GUI/ReleaseNote.hpp b/src/slic3r/GUI/ReleaseNote.hpp index 98d42b964c..80727df552 100644 --- a/src/slic3r/GUI/ReleaseNote.hpp +++ b/src/slic3r/GUI/ReleaseNote.hpp @@ -46,6 +46,7 @@ wxDECLARE_EVENT(EVT_SECONDARY_CHECK_CONFIRM, wxCommandEvent); wxDECLARE_EVENT(EVT_SECONDARY_CHECK_CANCEL, wxCommandEvent); wxDECLARE_EVENT(EVT_SECONDARY_CHECK_RETRY, wxCommandEvent); wxDECLARE_EVENT(EVT_SECONDARY_CHECK_DONE, wxCommandEvent); +wxDECLARE_EVENT(EVT_SECONDARY_CHECK_RESUME, wxCommandEvent); wxDECLARE_EVENT(EVT_UPDATE_NOZZLE, wxCommandEvent); class ReleaseNoteDialog : public DPIDialog @@ -116,8 +117,9 @@ public: CONFIRM_AND_CANCEL = 1, CONFIRM_AND_DONE = 2, CONFIRM_AND_RETRY = 3, - DONE_AND_RETRY = 4, - MAX_STYLE_NUM = 5 + CONFIRM_AND_RESUME = 4, + DONE_AND_RETRY = 5, + MAX_STYLE_NUM = 6 }; SecondaryCheckDialog( wxWindow* parent, @@ -150,12 +152,25 @@ public: Button* m_button_retry { nullptr }; Button* m_button_cancel { nullptr }; Button* m_button_fn { nullptr }; + Button* m_button_resume { nullptr }; wxCheckBox* m_show_again_checkbox; ButtonStyle m_button_style; bool not_show_again = false; std::string show_again_config_text = ""; }; + +struct ConfirmBeforeSendInfo +{ + enum InfoLevel { + Normal = 0, + Warning = 1 + }; + InfoLevel level; + wxString text; + ConfirmBeforeSendInfo(wxString txt, InfoLevel lev = Normal) : text(txt), level(lev) {} +}; + class ConfirmBeforeSendDialog : public DPIDialog { public: @@ -175,12 +190,17 @@ public: bool not_show_again_check = false ); void update_text(wxString text); + void update_text(std::vector texts); void on_show(); void on_hide(); void update_btn_label(wxString ok_btn_text, wxString cancel_btn_text); void rescale(); void on_dpi_changed(const wxRect& suggested_rect); - void show_update_nozzle_button(); + void show_update_nozzle_button(bool show = false); + void hide_button_ok(); + void edit_cancel_button_txt(wxString txt); + void disable_button_ok(); + void enable_button_ok(); wxString format_text(wxString str, int warp); ~ConfirmBeforeSendDialog(); diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 6184086dc0..5579fb7bcf 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -395,7 +395,7 @@ void OptionsSearcher::add_key(const std::string &opt_key, Preset::Type type, con // SearchItem //------------------------------------------ -SearchItem::SearchItem(wxWindow *parent, wxString text, int index, SearchDialog* sdialog, SearchObjectDialog* search_dialog) +SearchItem::SearchItem(wxWindow *parent, wxString text, int index, SearchDialog* sdialog, SearchObjectDialog* search_dialog, wxString tooltip) : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(parent->GetSize().GetWidth(), 3 * GUI::wxGetApp().em_unit())) { m_sdialog = sdialog; @@ -403,6 +403,8 @@ SearchItem::SearchItem(wxWindow *parent, wxString text, int index, SearchDialog* m_text = text; m_index = index; + this->SetToolTip(tooltip); + SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#FFFFFF"))); Bind(wxEVT_ENTER_WINDOW, &SearchItem::on_mouse_enter, this); Bind(wxEVT_LEAVE_WINDOW, &SearchItem::on_mouse_leave, this); @@ -997,13 +999,11 @@ void SearchObjectDialog::update_list() m_listPanel->SetBackgroundColour(StateColor::darkModeColorFor(m_bg_color)); m_listPanel->SetSize(wxSize(m_scrolledWindow->GetSize().GetWidth(), -1)); - const std::vector>& found = m_object_list->GetModel()->get_found_list(); + const std::vector>& found = m_object_list->GetModel()->get_found_list(); auto index = 0; - for (const auto& item : found) { - GUI::ObjectDataViewModelNode* data_item = item.first; - wxString data_str = item.second; - auto tmp = new SearchItem(m_listPanel, data_str, index, nullptr, this); - tmp->m_item = data_item; + for (const auto& [model_node, name, tip] : found) { + auto tmp = new SearchItem(m_listPanel, name, index, nullptr, this, tip); + tmp->m_item = model_node; m_listsizer->Add(tmp, 0, wxEXPAND, 0); index++; } diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index 8d20a14e1c..31b83b8cf3 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -166,7 +166,7 @@ public: SearchObjectDialog* m_search_object_dialog{ nullptr }; GUI::ObjectDataViewModelNode* m_item{ nullptr }; - SearchItem(wxWindow *parent, wxString text, int index, SearchDialog *sdialog = nullptr, SearchObjectDialog* search_dialog = nullptr); + SearchItem(wxWindow *parent, wxString text, int index, SearchDialog *sdialog = nullptr, SearchObjectDialog* search_dialog = nullptr, wxString tooltip = ""); ~SearchItem(){}; wxSize DrawTextString(wxDC &dc, const wxString &text, const wxPoint &pt, bool bold); diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index 9c9bfb259a..62f602c27b 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -1800,8 +1800,11 @@ void SelectMachineDialog::sync_ams_mapping_result(std::vector &res // default color ams_col = wxColour(0xCE, 0xCE, 0xCE); } - - m->set_ams_info(ams_col, ams_id); + std::vector cols; + for (auto col : f->colors) { + cols.push_back(AmsTray::decode_color(col)); + } + m->set_ams_info(ams_col, ams_id,f->ctype, cols); break; } iter++; @@ -2141,9 +2144,39 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vectorget_selected_machine(); + if (obj_ == nullptr) return; + auto sourcet_print_name = obj_->get_printer_type_display_str(); + sourcet_print_name.Replace(wxT("Bambu Lab "), wxEmptyString); + + //target print + std::string target_model_id; + if (m_print_type == PrintFromType::FROM_NORMAL){ + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + target_model_id = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); + } + else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW) { + if (m_required_data_plate_data_list.size() > 0) { + target_model_id = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id; + } + } + + auto target_print_name = wxString(obj_->get_preset_printer_model_name(target_model_id)); + target_print_name.Replace(wxT("Bambu Lab "), wxEmptyString); + msg_text = wxString::Format(_L("The selected printer (%s) is incompatible with the chosen printer profile in the slicer (%s)."), sourcet_print_name, target_print_name); + + update_print_status_msg(msg_text, true, true); + } + catch (...){} + Enable_Send_Button(false); Enable_Refresh_Button(true); }else if (status == PrintDialogStatus::PrintStatusTimelapseNoSdcard) { @@ -2217,10 +2250,19 @@ bool SelectMachineDialog::is_blocking_printing(MachineObject* obj_) { DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return true; - - PresetBundle* preset_bundle = wxGetApp().preset_bundle; - auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); auto target_model = obj_->printer_type; + std::string source_model = ""; + + if (m_print_type == PrintFromType::FROM_NORMAL) { + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); + + + }else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW) { + if (m_required_data_plate_data_list.size() > 0) { + source_model = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id; + } + } if (source_model != target_model) { std::vector compatible_machine = dev->get_compatible_machine(target_model); @@ -2378,7 +2420,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) { bool has_slice_warnings = false; - bool has_update_nozzle = false; + bool is_printing_block = false; DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; @@ -2386,14 +2428,13 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) if (!obj_) return; - std::vector confirm_text; - confirm_text.push_back(_L("Please check the following:") + "\n\n"); + std::vector confirm_text; + confirm_text.push_back(ConfirmBeforeSendInfo(_L("Please check the following:"))); //Check Printer Model Id bool is_same_printer_type = is_same_printer_model(); if (!is_same_printer_type && (m_print_type == PrintFromType::FROM_NORMAL)) { - confirm_text.push_back(_L("The printer type selected when generating G-Code is not consistent with the currently selected printer. It is recommended that you use the same printer type for slicing.") + "\n"); - + confirm_text.push_back(ConfirmBeforeSendInfo(_L("The printer type selected when generating G-Code is not consistent with the currently selected printer. It is recommended that you use the same printer type for slicing."))); has_slice_warnings = true; } @@ -2421,7 +2462,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) if (in_blacklist && action == "warning") { wxString prohibited_error = wxString::FromUTF8(info); - confirm_text.push_back(prohibited_error + "\n"); + confirm_text.push_back(ConfirmBeforeSendInfo(prohibited_error)); has_slice_warnings = true; } } @@ -2437,20 +2478,20 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) } else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) { if (obj_->get_printer_arch() == PrinterArch::ARCH_I3 && m_checkbox_list["timelapse"]->GetValue()) { - confirm_text.push_back(Plater::get_slice_warning_string(warning) + "\n"); + confirm_text.push_back(ConfirmBeforeSendInfo(Plater::get_slice_warning_string(warning))); has_slice_warnings = true; } } else if (warning.msg == NOT_GENERATE_TIMELAPSE) { continue; } - else { + else if(warning.msg == NOZZLE_HRC_CHECKER){ wxString error_info = Plater::get_slice_warning_string(warning); if (error_info.IsEmpty()) { error_info = wxString::Format("%s\n", warning.msg); - confirm_text.push_back(error_info + "\n"); - } else - confirm_text.push_back(error_info + "\n"); + } + + confirm_text.push_back(ConfirmBeforeSendInfo(error_info)); has_slice_warnings = true; } } @@ -2508,7 +2549,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) if (has_unknown_filament) { has_slice_warnings = true; - confirm_text.push_back(_L("There are some unknown filaments in the AMS mappings. Please check whether they are the required filaments. If they are okay, press \"Confirm\" to start printing.") + "\n"); + confirm_text.push_back(ConfirmBeforeSendInfo(_L("There are some unknown filaments in the AMS mappings. Please check whether they are the required filaments. If they are okay, press \"Confirm\" to start printing."))); } std::string nozzle_diameter; @@ -2518,23 +2559,24 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) if (!obj_->nozzle_type.empty() && (m_print_type == PrintFromType::FROM_NORMAL)) { if (!is_same_nozzle_diameters(tag_nozzle_type, nozzle_diameter)) { has_slice_warnings = true; - has_update_nozzle = true; + is_printing_block = true; wxString nozzle_in_preset = wxString::Format(_L("nozzle in preset: %s %s"),nozzle_diameter, ""); wxString nozzle_in_printer = wxString::Format(_L("nozzle memorized: %.1f %s"), obj_->nozzle_diameter, ""); - confirm_text.push_back(_L("Your nozzle diameter in preset is not consistent with memorized nozzle diameter. Did you change your nozzle lately?") + confirm_text.push_back(ConfirmBeforeSendInfo(_L("Your nozzle diameter in sliced file is not consistent with memorized nozzle. If you changed your nozzle lately, please go to Device > Printer Parts to change settings.") + "\n " + nozzle_in_preset + "\n " + nozzle_in_printer - + "\n"); + + "\n", ConfirmBeforeSendInfo::InfoLevel::Warning)); } - else if (!is_same_nozzle_type(filament_type, tag_nozzle_type)){ + + if (!is_same_nozzle_type(filament_type, tag_nozzle_type)){ has_slice_warnings = true; - has_update_nozzle = true; + is_printing_block = true; nozzle_diameter = wxString::Format("%.1f", obj_->nozzle_diameter).ToStdString(); - wxString nozzle_in_preset = wxString::Format(_L("*Printing %s material with %s may cause nozzle damage"), filament_type, format_steel_name(obj_->nozzle_type)); - confirm_text.push_back(nozzle_in_preset + "\n"); + wxString nozzle_in_preset = wxString::Format(_L("Printing high temperature material(%s material) with %s may cause nozzle damage"), filament_type, format_steel_name(obj_->nozzle_type)); + confirm_text.push_back(ConfirmBeforeSendInfo(nozzle_in_preset, ConfirmBeforeSendInfo::InfoLevel::Warning)); } } @@ -2543,7 +2585,14 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) wxString confirm_title = _L("Warning"); ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, confirm_title); - if(has_update_nozzle){confirm_dlg.show_update_nozzle_button();} + if(is_printing_block){ + confirm_dlg.hide_button_ok(); + confirm_dlg.edit_cancel_button_txt(_L("Close")); + confirm_text.push_back(ConfirmBeforeSendInfo(_L("Please fix the error above, otherwise printing cannot continue."), ConfirmBeforeSendInfo::InfoLevel::Warning)); + } + else { + confirm_text.push_back(ConfirmBeforeSendInfo(_L("Please click the confirm button if you still want to proceed with printing."))); + } confirm_dlg.Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, &confirm_dlg](wxCommandEvent& e) { confirm_dlg.on_hide(); @@ -2555,34 +2604,34 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) } }); - confirm_dlg.Bind(EVT_UPDATE_NOZZLE, [this, obj_, tag_nozzle_type, nozzle_diameter, &confirm_dlg](wxCommandEvent& e) { - if (obj_ && !tag_nozzle_type.empty() && !nozzle_diameter.empty()) { - try - { - float diameter = std::stof(nozzle_diameter); - diameter = round(diameter * 10) / 10; - obj_->command_set_printer_nozzle(tag_nozzle_type, diameter); - } - catch (...) {} - } - }); + //confirm_dlg.Bind(EVT_UPDATE_NOZZLE, [this, obj_, tag_nozzle_type, nozzle_diameter, &confirm_dlg](wxCommandEvent& e) { + // if (obj_ && !tag_nozzle_type.empty() && !nozzle_diameter.empty()) { + // try + // { + // float diameter = std::stof(nozzle_diameter); + // diameter = round(diameter * 10) / 10; + // obj_->command_set_printer_nozzle(tag_nozzle_type, diameter); + // } + // catch (...) {} + // } + // }); - confirm_text.push_back(_L("Please click the confirm button if you still want to proceed with printing.") + "\n"); + wxString info_msg = wxEmptyString; for (auto i = 0; i < confirm_text.size(); i++) { if (i == 0) { - info_msg += confirm_text[i]; + //info_msg += confirm_text[i]; } else if (i == confirm_text.size() - 1) { - info_msg += confirm_text[i]; + //info_msg += confirm_text[i]; } else { - info_msg += wxString::Format("%d. %s\n",i, confirm_text[i]); + confirm_text[i].text = wxString::Format("%d. %s",i, confirm_text[i].text); } } - confirm_dlg.update_text(info_msg); + confirm_dlg.update_text(confirm_text); confirm_dlg.on_show(); } else { @@ -2882,15 +2931,32 @@ void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt) BOOST_LOG_TRIVIAL(info) << "The ams mapping selection result: data is " << selection_data; if (selection_data_arr.size() == 6) { - for (auto i = 0; i < m_ams_mapping_result.size(); i++) { + int ctype = 0; + std::vector material_cols; + std::vector tray_cols; + for (auto mapping_item : m_mapping_popup.m_mapping_item_list) { + if (mapping_item->m_tray_data.id == evt.GetInt()) { + ctype = mapping_item->m_tray_data.ctype; + material_cols = mapping_item->m_tray_data.material_cols; + for (auto col : mapping_item->m_tray_data.material_cols) { + wxString color = wxString::Format("#%02X%02X%02X%02X", col.Red(), col.Green(), col.Blue(), col.Alpha()); + tray_cols.push_back(color.ToStdString()); + } + break; + } + } + + for (auto i = 0; i < m_ams_mapping_result.size(); i++) { if (m_ams_mapping_result[i].id == wxAtoi(selection_data_arr[5])) { m_ams_mapping_result[i].tray_id = evt.GetInt(); - auto ams_colour = wxColour(wxAtoi(selection_data_arr[0]), wxAtoi(selection_data_arr[1]), wxAtoi(selection_data_arr[2]), wxAtoi(selection_data_arr[3])); - wxString color = wxString::Format("#%02X%02X%02X%02X", ams_colour.Red(), ams_colour.Green(), ams_colour.Blue(), ams_colour.Alpha()); - m_ams_mapping_result[i].color = color.ToStdString(); + auto ams_colour = wxColour(wxAtoi(selection_data_arr[0]), wxAtoi(selection_data_arr[1]), wxAtoi(selection_data_arr[2]), wxAtoi(selection_data_arr[3])); + wxString color = wxString::Format("#%02X%02X%02X%02X", ams_colour.Red(), ams_colour.Green(), ams_colour.Blue(), ams_colour.Alpha()); + m_ams_mapping_result[i].color = color.ToStdString(); + m_ams_mapping_result[i].ctype = ctype; + m_ams_mapping_result[i].colors = tray_cols; } BOOST_LOG_TRIVIAL(trace) << "The ams mapping result: id is " << m_ams_mapping_result[i].id << "tray_id is " << m_ams_mapping_result[i].tray_id; - } + } MaterialHash::iterator iter = m_materialList.begin(); while (iter != m_materialList.end()) { @@ -2898,7 +2964,7 @@ void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt) MaterialItem *m = item->item; if (item->id == m_current_filament_id) { auto ams_colour = wxColour(wxAtoi(selection_data_arr[0]), wxAtoi(selection_data_arr[1]), wxAtoi(selection_data_arr[2]), wxAtoi(selection_data_arr[3])); - m->set_ams_info(ams_colour, selection_data_arr[4]); + m->set_ams_info(ams_colour, selection_data_arr[4], ctype, material_cols); } iter++; } @@ -3157,7 +3223,7 @@ void SelectMachineDialog::on_rename_enter() m_current_project_name = new_file_name; m_rename_switch_panel->SetSelection(0); - m_rename_text->SetLabel(m_current_project_name); + m_rename_text->SetLabelText(m_current_project_name); m_rename_normal_panel->Layout(); } @@ -3282,12 +3348,7 @@ void SelectMachineDialog::update_flow_cali_check(MachineObject* obj) if (obj && obj->get_printer_arch() == PrinterArch::ARCH_I3) { show_cali_tips = false; } - if (bed_type == BedType::btPTE) { - set_flow_calibration_state(false, show_cali_tips); - } - else { - set_flow_calibration_state(true, show_cali_tips); - } + set_flow_calibration_state(true, show_cali_tips); } void SelectMachineDialog::update_ams_check(MachineObject* obj) @@ -3416,7 +3477,7 @@ void SelectMachineDialog::update_show_status() } } - if (m_print_type == PrintFromType::FROM_NORMAL && is_blocking_printing(obj_)) { + if (is_blocking_printing(obj_)) { show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter); return; } @@ -3774,7 +3835,23 @@ void SelectMachineDialog::set_default() } fs::path filename_path(filename.c_str()); - m_current_project_name = wxString::FromUTF8(filename_path.filename().string()); + std::string file_name = filename_path.filename().string(); + if (from_u8(file_name).find(_L("Untitled")) != wxString::npos) { + PartPlate *part_plate = m_plater->get_partplate_list().get_plate(m_print_plate_idx); + if (part_plate) { + if (std::vector objects = part_plate->get_objects_on_this_plate(); objects.size() > 0) { + file_name = objects[0]->name; + for (int i = 1; i < objects.size(); i++) { + file_name += (" + " + objects[i]->name); + } + } + if (file_name.size() > 100) { + file_name = file_name.substr(0, 97) + "..."; + } + } + } + m_current_project_name = wxString::FromUTF8(file_name); + //unsupported character filter m_current_project_name = from_u8(filter_characters(m_current_project_name.ToUTF8().data(), "<>[]:/\\|?*\"")); @@ -4051,10 +4128,13 @@ void SelectMachineDialog::set_default_from_sdcard() update_page_turn_state(true); ThumbnailData& data = m_required_data_plate_data_list[m_print_plate_idx]->plate_thumbnail; - wxMemoryInputStream mis((unsigned char*)data.pixels.data(), data.pixels.size()); - wxImage image = wxImage(mis); - image = image.Rescale(FromDIP(256), FromDIP(256)); - m_thumbnailPanel->set_thumbnail(image); + + if (data.pixels.size() > 0) { + wxMemoryInputStream mis((unsigned char*)data.pixels.data(), data.pixels.size()); + wxImage image = wxImage(mis); + image = image.Rescale(FromDIP(256), FromDIP(256)); + m_thumbnailPanel->set_thumbnail(image); + } //for black list std::vector materials; @@ -4158,14 +4238,7 @@ void SelectMachineDialog::set_default_from_sdcard() m_scrollable_view->SetMinSize(m_scrollable_region->GetSize()); m_scrollable_view->SetMaxSize(m_scrollable_region->GetSize()); - //disable pei bed - auto bed_type = m_plater->get_partplate_list().get_curr_plate()->get_bed_type(true); - if (bed_type == BedType::btPTE) { - set_flow_calibration_state(false); - } - else { - set_flow_calibration_state(true); - } + set_flow_calibration_state(true); wxSize screenSize = wxGetDisplaySize(); auto dialogSize = this->GetSize(); @@ -4479,7 +4552,7 @@ void EditDevNameDialog::on_edit_name(wxCommandEvent &e) dc.DrawBitmap(m_background_bitmap.bmp(), 0, 0); dc.DrawBitmap(m_bitmap, 0, 0); dc.SelectObject(wxNullBitmap); - + Refresh(); } void ThumbnailPanel::OnPaint(wxPaintEvent& event) { diff --git a/src/slic3r/GUI/SelectMachine.hpp b/src/slic3r/GUI/SelectMachine.hpp index 160c21592a..d9ea4cb8f4 100644 --- a/src/slic3r/GUI/SelectMachine.hpp +++ b/src/slic3r/GUI/SelectMachine.hpp @@ -64,6 +64,34 @@ enum PrintFromType { FROM_SDCARD_VIEW, }; +static int get_brightness_value(wxImage image) { + + wxImage grayImage = image.ConvertToGreyscale(); + + int width = grayImage.GetWidth(); + int height = grayImage.GetHeight(); + + int totalLuminance = 0; + unsigned char alpha; + int num_none_transparent = 0; + for (int y = 0; y < height; y += 2) { + + for (int x = 0; x < width; x += 2) { + + alpha = image.GetAlpha(x, y); + if (alpha != 0) { + wxColour pixelColor = grayImage.GetRed(x, y); + totalLuminance += pixelColor.Red(); + num_none_transparent = num_none_transparent + 1; + } + } + } + if (totalLuminance <= 0 || num_none_transparent <= 0) { + return 0; + } + return totalLuminance / num_none_transparent; +} + class Material { public: @@ -288,7 +316,7 @@ private: int m_print_plate_idx{0}; int m_print_plate_total{0}; int m_timeout_count{0}; - int m_print_error_code; + int m_print_error_code{0}; bool m_is_in_sending_mode{ false }; bool m_ams_mapping_res{ false }; bool m_ams_mapping_valid{ false }; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 01f1c06502..4b06c543b8 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -147,6 +147,17 @@ void Selection::set_model(Model* model) update_valid(); } +int Selection::query_real_volume_idx_from_other_view(unsigned int object_idx, unsigned int instance_idx, unsigned int model_volume_idx) +{ + for (int i = 0; i < m_volumes->size(); i++) { + auto v = (*m_volumes)[i]; + if (v->object_idx() == object_idx && instance_idx == v->instance_idx() && model_volume_idx == v->volume_idx()) { + return i; + } + } + return -1; +} + void Selection::add(unsigned int volume_idx, bool as_single_selection, bool check_for_already_contained) { if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx) @@ -1988,6 +1999,13 @@ void Selection::copy_to_clipboard() m_clipboard.reset(); + // sort as the object list order + std::vector selected_list; + selected_list.assign(m_list.begin(), m_list.end()); + std::sort(selected_list.begin(), selected_list.end(), [this](unsigned int left, unsigned int right) { + return (*m_volumes)[left]->volume_idx() < (*m_volumes)[right]->volume_idx(); + }); + for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) { ModelObject* src_object = m_model->objects[object.first]; ModelObject* dst_object = m_clipboard.add_object(); @@ -2005,7 +2023,7 @@ void Selection::copy_to_clipboard() dst_object->add_instance(*src_object->instances[i]); } - for (unsigned int i : m_list) { + for (unsigned int i : selected_list) { // Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance. const GLVolume* volume = (*m_volumes)[i]; if (volume->object_idx() == object.first && volume->instance_idx() == *object.second.begin()) { @@ -3078,7 +3096,7 @@ void Selection::paste_objects_from_clipboard() if (src_objects.size() > 1) { BoundingBoxf3 bbox_all; for (const ModelObject *src_object : src_objects) { - BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(0); + BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(size_t(0)); bbox_all.merge(bbox); } auto bsize = bbox_all.size(); @@ -3094,7 +3112,7 @@ void Selection::paste_objects_from_clipboard() ModelObject* dst_object = m_model->add_object(*src_object); // BBS: find an empty cell to put the copied object - BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(0); + BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(size_t(0)); Vec3d displacement; bool in_current = plate->intersects(bbox); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index c506a1a6fa..10954488df 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -212,6 +212,7 @@ public: EMode get_mode() const { return m_mode; } void set_mode(EMode mode) { m_mode = mode; } + int query_real_volume_idx_from_other_view(unsigned int object_idx, unsigned int instance_idx, unsigned int model_volume_idx); void add(unsigned int volume_idx, bool as_single_selection = true, bool check_for_already_contained = false); void remove(unsigned int volume_idx); diff --git a/src/slic3r/GUI/SendToPrinter.hpp b/src/slic3r/GUI/SendToPrinter.hpp index b084a382f3..9f477be993 100644 --- a/src/slic3r/GUI/SendToPrinter.hpp +++ b/src/slic3r/GUI/SendToPrinter.hpp @@ -50,7 +50,7 @@ private: int m_print_plate_idx; int m_current_filament_id; - int m_print_error_code; + int m_print_error_code = 0; int timeout_count = 0; bool m_is_in_sending_mode{ false }; bool m_is_rename_mode{ false }; diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 53394895f6..6c55a27b4f 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -85,7 +85,6 @@ static std::vector message_containing_retry{ "07FF 8012", "07FF 8013", "12FF 8007" - }; static std::vector message_containing_done{ @@ -93,6 +92,10 @@ static std::vector message_containing_done{ "12FF 8007" }; +static std::vector message_containing_resume{ + "0300 8013" +}; + static wxImage fail_image; @@ -492,7 +495,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent) static_score_sizer->Add(static_score_text, 1, wxEXPAND | wxALL, FromDIP(10)); m_has_rated_prompt = new wxStaticText(m_score_subtask_info, wxID_ANY, _L("(The model has already been rated. Your rating will overwrite the previous rating.)"), wxDefaultPosition, wxDefaultSize, 0); m_has_rated_prompt->Wrap(-1); - m_has_rated_prompt->SetForegroundColour(*wxRED); + m_has_rated_prompt->SetForegroundColour(*wxBLACK); m_has_rated_prompt->SetFont(::Label::Body_10); m_has_rated_prompt->Hide(); @@ -1093,6 +1096,13 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) std::pair(wxColour(38, 166, 154), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); StateColor btn_bd_green(std::pair(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Enabled)); + m_parts_btn = new Button(m_panel_control_title, _L("Printer Parts")); + m_parts_btn->SetBackgroundColor(btn_bg_green); + m_parts_btn->SetBorderColor(btn_bd_green); + m_parts_btn->SetTextColor(wxColour("#FFFFFE")); + m_parts_btn->SetSize(wxSize(FromDIP(128), FromDIP(26))); + m_parts_btn->SetMinSize(wxSize(-1, FromDIP(26))); + m_options_btn = new Button(m_panel_control_title, _L("Print Options")); m_options_btn->SetBackgroundColor(btn_bg_green); m_options_btn->SetBorderColor(btn_bd_green); @@ -1110,6 +1120,7 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) bSizer_control_title->Add(m_staticText_control, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, PAGE_TITLE_LEFT_MARGIN); bSizer_control_title->Add(0, 0, 1, wxEXPAND, 0); + bSizer_control_title->Add(m_parts_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); bSizer_control_title->Add(m_options_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); bSizer_control_title->Add(m_calibration_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); @@ -1767,10 +1778,12 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co Bind(EVT_AMS_RETRY, &StatusPanel::on_ams_retry, this); Bind(EVT_FAN_CHANGED, &StatusPanel::on_fan_changed, this); Bind(EVT_SECONDARY_CHECK_DONE, &StatusPanel::on_print_error_done, this); + Bind(EVT_SECONDARY_CHECK_RESUME, &StatusPanel::on_subtask_pause_resume, this); m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); m_options_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); + m_parts_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this); } StatusPanel::~StatusPanel() @@ -1803,6 +1816,7 @@ StatusPanel::~StatusPanel() m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); m_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); + m_parts_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this); m_button_unload->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_unload), NULL, this); // remove warning dialogs @@ -1917,6 +1931,10 @@ void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event) BOOST_LOG_TRIVIAL(info) << "monitor: pause current print task dev_id =" << obj->dev_id; obj->command_task_pause(); } + if (m_print_error_dlg) { + m_print_error_dlg->on_hide(); + } + } } @@ -1925,7 +1943,7 @@ void StatusPanel::on_subtask_abort(wxCommandEvent &event) if (abort_dlg == nullptr) { abort_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Cancel print")); abort_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this](wxCommandEvent &e) { - if (obj) { + if (obj) { BOOST_LOG_TRIVIAL(info) << "monitor: stop current print task dev_id =" << obj->dev_id; obj->command_task_abort(); } @@ -1956,10 +1974,12 @@ void StatusPanel::on_webrequest_state(wxWebRequestEvent &evt) BOOST_LOG_TRIVIAL(trace) << "monitor: monitor_panel web request state = " << evt.GetState(); switch (evt.GetState()) { case wxWebRequest::State_Completed: { - wxImage img(*evt.GetResponse().GetStream()); - img_list.insert(std::make_pair(m_request_url, img)); - wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y, wxIMAGE_QUALITY_HIGH); - m_project_task_panel->set_thumbnail_img(resize_img); + if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) { + wxImage img(*evt.GetResponse().GetStream()); + img_list.insert(std::make_pair(m_request_url, img)); + wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y, wxIMAGE_QUALITY_HIGH); + m_project_task_panel->set_thumbnail_img(resize_img); + } if (obj) { m_project_task_panel->set_plate_index(obj->m_plate_index); } else { @@ -2022,7 +2042,6 @@ bool StatusPanel::is_task_changed(MachineObject* obj) void StatusPanel::update(MachineObject *obj) { if (!obj) return; - m_project_task_panel->Freeze(); update_subtask(obj); m_project_task_panel->Thaw(); @@ -2080,6 +2099,8 @@ void StatusPanel::update(MachineObject *obj) m_options_btn->Hide(); } + m_parts_btn->Show(); + //support edit chamber temp if (obj->is_support_chamber_edit) { m_tempCtrl_chamber->SetReadOnly(false); @@ -2144,6 +2165,7 @@ void StatusPanel::show_error_message(MachineObject* obj, wxString msg, std::stri auto it_retry = std::find(message_containing_retry.begin(), message_containing_retry.end(), print_error_str); auto it_done = std::find(message_containing_done.begin(), message_containing_done.end(), print_error_str); + auto it_resume = std::find(message_containing_resume.begin(), message_containing_resume.end(), print_error_str); BOOST_LOG_TRIVIAL(info) << "show print error! error_msg = " << msg; if (m_print_error_dlg == nullptr) { @@ -2158,10 +2180,15 @@ void StatusPanel::show_error_message(MachineObject* obj, wxString msg, std::stri } else if (it_retry != message_containing_retry.end()) { m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RETRY, this); - }else { + } + else if (it_resume!= message_containing_resume.end()) { + m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RESUME, this); + } + else { m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::ONLY_CONFIRM, this); } m_print_error_dlg->update_text(msg); + m_print_error_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, obj](wxCommandEvent& e) { if (obj) { obj->command_clean_print_error(obj->subtask_id_, obj->print_error); @@ -2500,7 +2527,7 @@ void StatusPanel::update_ams(MachineObject *obj) m_ams_setting_dlg->obj = obj; if (obj && m_ams_setting_dlg->IsShown()) { - m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag); + update_ams_insert_material(obj); m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag); m_ams_setting_dlg->update_remain_mode(obj->ams_calibrate_remain_flag); m_ams_setting_dlg->update_switch_filament(obj->ams_auto_switch_filament_flag); @@ -2508,7 +2535,7 @@ void StatusPanel::update_ams(MachineObject *obj) } if (m_filament_setting_dlg) { m_filament_setting_dlg->obj = obj; } - if ( (obj->get_printer_series() == PrinterSeries::SERIES_X1) && last_cali_version != obj->cali_version) { + if (obj->cali_version != -1 && last_cali_version != obj->cali_version) { last_cali_version = obj->cali_version; CalibUtils::emit_get_PA_calib_info(obj->nozzle_diameter, ""); } @@ -2754,6 +2781,18 @@ void StatusPanel::update_ams(MachineObject *obj) update_ams_control_state(is_curr_tray_selected); } +void StatusPanel::update_ams_insert_material(MachineObject* obj) { + std::string extra_ams_str = (boost::format("ams_f1/%1%") % 0).str(); + auto extra_ams_it = obj->module_vers.find(extra_ams_str); + if (extra_ams_it != obj->module_vers.end()) { + m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag, extra_ams_it->second.sw_ver); + } + else { + m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag, ""); + } +} + + void StatusPanel::update_ams_control_state(bool is_curr_tray_selected) { // set default value to true @@ -2796,13 +2835,58 @@ void StatusPanel::update_ams_control_state(bool is_curr_tray_selected) } if (obj->ams_exist_bits == 0) { - if (obj->is_in_printing() && !obj->can_resume()) { - enable[ACTION_BTN_LOAD] = false; - enable[ACTION_BTN_UNLOAD] = false; + if (obj->is_in_printing()) { + if (!obj->can_resume()) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = false; + } + else{ + if (obj->m_tray_now == "255") { + enable[ACTION_BTN_LOAD] = true; + enable[ACTION_BTN_UNLOAD] = false; + } + else if (obj->m_tray_now == std::to_string(VIRTUAL_TRAY_ID)) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = true; + } + } } - else { - enable[ACTION_BTN_LOAD] = true; - enable[ACTION_BTN_UNLOAD] = true; + + } + else { + if (obj->is_in_printing() /*&& obj->can_resume() && obj->m_tray_now != std::to_string(VIRTUAL_TRAY_ID) */) { + + if (!obj->can_resume()) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = false; + } + else { + if (obj->m_tray_now == "255") { + + if ( m_ams_control->GetCurentAms() == std::to_string(VIRTUAL_TRAY_ID) ) { + enable[ACTION_BTN_LOAD] = true; + enable[ACTION_BTN_UNLOAD] = false; + } + else if (!m_ams_control->GetCurrentCan(m_ams_control->GetCurentAms()).empty()) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = false; + } + } + else if (obj->m_tray_now == std::to_string(VIRTUAL_TRAY_ID)) { + if (m_ams_control->GetCurentAms() == std::to_string(VIRTUAL_TRAY_ID)) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = true; + } + else if (!m_ams_control->GetCurrentCan(m_ams_control->GetCurentAms()).empty()) { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = false; + } + } + else { + enable[ACTION_BTN_LOAD] = false; + enable[ACTION_BTN_UNLOAD] = false; + } + } } } @@ -2836,6 +2920,14 @@ void StatusPanel::update_cali(MachineObject *obj) } } +void StatusPanel::update_calib_bitmap() { + m_current_print_mode = PrintingTaskType::NOT_CLEAR; //printing task might be changed when updating. + if (calib_bitmap != nullptr) { + delete calib_bitmap; + calib_bitmap = nullptr; + } +} + void StatusPanel::update_basic_print_data(bool def) { if (def) { @@ -2881,7 +2973,52 @@ void StatusPanel::update_model_info() void StatusPanel::update_subtask(MachineObject *obj) { if (!obj) return; + if (m_current_print_mode != PRINGINT) { + if (calib_bitmap == nullptr) { + m_calib_mode = get_obj_calibration_mode(obj, m_calib_method, cali_stage); + if (m_calib_mode == CalibMode::Calib_None) + m_current_print_mode = PRINGINT; + // the printing task is calibrattion, not normal printing. + else if (m_calib_mode != CalibMode::Calib_None) { + m_current_print_mode = CALIBRATION; + auto get_bitmap = [](wxString& png_path, int width, int height) { + wxImage image(width, height); + image.LoadFile(png_path, wxBITMAP_TYPE_PNG); + image = image.Scale(width, height, wxIMAGE_QUALITY_NORMAL); + return wxBitmap(image); + }; + wxString png_path = ""; + int width = m_project_task_panel->get_bitmap_thumbnail()->GetSize().x; + int height = m_project_task_panel->get_bitmap_thumbnail()->GetSize().y; + if (m_calib_method == CALI_METHOD_AUTO) { + if (m_calib_mode == CalibMode::Calib_PA_Line) { + png_path = (boost::format("%1%/images/fd_calibration_auto.png") % resources_dir()).str(); + } + else if (m_calib_mode == CalibMode::Calib_Flow_Rate) { + png_path = (boost::format("%1%/images/flow_rate_calibration_auto.png") % resources_dir()).str(); + } + } + else if (m_calib_method == CALI_METHOD_MANUAL) { + if (m_calib_mode== CalibMode::Calib_PA_Line) { + if (cali_stage == 0) { // Line mode + png_path = (boost::format("%1%/images/fd_calibration_manual.png") % resources_dir()).str(); + } + else if (cali_stage == 1) { // Pattern mode + png_path = (boost::format("%1%/images/fd_pattern_manual_device.png") % resources_dir()).str(); + } + } + } + if (png_path != "") { + calib_bitmap = new wxBitmap; + *calib_bitmap = get_bitmap(png_path, width, height); + } + } + } + if (calib_bitmap != nullptr) + m_project_task_panel->set_thumbnail_img(*calib_bitmap); + } + if (obj->is_support_layer_num) { m_project_task_panel->update_layers_num(true); } @@ -3039,15 +3176,18 @@ void StatusPanel::update_cloud_subtask(MachineObject *obj) } if (m_start_loading_thumbnail) { + update_calib_bitmap(); if (obj->slice_info) { m_request_url = wxString(obj->slice_info->thumbnail_url); if (!m_request_url.IsEmpty()) { wxImage img; std::map::iterator it = img_list.find(m_request_url); if (it != img_list.end()) { - img = it->second; - wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y); - m_project_task_panel->set_thumbnail_img(resize_img); + if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) { + img = it->second; + wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y); + m_project_task_panel->set_thumbnail_img(resize_img); + } if (this->obj) { m_project_task_panel->set_plate_index(obj->m_plate_index); } else { @@ -3071,7 +3211,10 @@ void StatusPanel::update_sdcard_subtask(MachineObject *obj) if (!obj) return; if (!m_load_sdcard_thumbnail) { - m_project_task_panel->get_bitmap_thumbnail()->SetBitmap(m_thumbnail_sdcard.bmp()); + update_calib_bitmap(); + if (m_current_print_mode != PrintingTaskType::CALIBRATION) { + m_project_task_panel->get_bitmap_thumbnail()->SetBitmap(m_thumbnail_sdcard.bmp()); + } task_thumbnail_state = ThumbnailState::SDCARD_THUMBNAIL; m_load_sdcard_thumbnail = true; } @@ -3092,7 +3235,7 @@ void StatusPanel::reset_printing_values() update_basic_print_data(false); m_project_task_panel->update_left_time(NA_STR); m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR)); - + update_calib_bitmap(); task_thumbnail_state = ThumbnailState::PLACE_HOLDER; m_start_loading_thumbnail = false; @@ -3245,6 +3388,7 @@ void StatusPanel::on_set_bed_temp() BOOST_LOG_TRIVIAL(info) << "can not set over limit = " << limit << ", set temp = " << bed_temp; bed_temp = limit; m_tempCtrl_bed->SetTagTemp(wxString::Format("%d", bed_temp)); + m_tempCtrl_bed->Warning(false); } obj->command_set_bed(bed_temp); } @@ -3260,6 +3404,11 @@ void StatusPanel::on_set_nozzle_temp() long nozzle_temp; if (str.ToLong(&nozzle_temp) && obj) { set_hold_count(m_temp_nozzle_timeout); + if (nozzle_temp > m_tempCtrl_nozzle->get_max_temp()) { + nozzle_temp = m_tempCtrl_nozzle->get_max_temp(); + m_tempCtrl_nozzle->SetTagTemp(wxString::Format("%d", nozzle_temp)); + m_tempCtrl_nozzle->Warning(false); + } obj->command_set_nozzle(nozzle_temp); } } catch (...) { @@ -3274,6 +3423,11 @@ void StatusPanel::on_set_chamber_temp() long chamber_temp; if (str.ToLong(&chamber_temp) && obj) { set_hold_count(m_temp_chamber_timeout); + if (chamber_temp > m_tempCtrl_chamber->get_max_temp()) { + chamber_temp = m_tempCtrl_chamber->get_max_temp(); + m_tempCtrl_chamber->SetTagTemp(wxString::Format("%d", chamber_temp)); + m_tempCtrl_chamber->Warning(false); + } obj->command_set_chamber(chamber_temp); } } @@ -3379,7 +3533,7 @@ void StatusPanel::on_ams_setting_click(SimpleEvent &event) { if (!m_ams_setting_dlg) m_ams_setting_dlg = new AMSSetting((wxWindow *) this, wxID_ANY); if (obj) { - m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag); + update_ams_insert_material(obj); m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag); m_ams_setting_dlg->update_ams_img(DeviceManager::get_printer_ams_img(obj->printer_type)); std::string ams_id = m_ams_control->GetCurentShowAms(); @@ -4016,7 +4170,8 @@ void StatusPanel::on_xyz_abs(wxCommandEvent &event) if (obj) obj->command_xyz_abs(); } -void StatusPanel::on_show_print_options(wxCommandEvent &event) + +void StatusPanel::on_show_print_options(wxCommandEvent& event) { if (obj) { if (print_options_dlg == nullptr) { @@ -4031,6 +4186,22 @@ void StatusPanel::on_show_print_options(wxCommandEvent &event) } } + +void StatusPanel::on_show_parts_options(wxCommandEvent &event) +{ + if (obj) { + if (print_parts_dlg == nullptr) { + print_parts_dlg = new PrinterPartsDialog(this); + print_parts_dlg->update_machine_obj(obj); + print_parts_dlg->ShowModal(); + } + else { + print_parts_dlg->update_machine_obj(obj); + print_parts_dlg->ShowModal(); + } + } +} + void StatusPanel::on_start_calibration(wxCommandEvent &event) { if (obj) { @@ -4084,12 +4255,14 @@ void StatusPanel::set_default() m_setting_button->Show(); m_tempCtrl_chamber->Show(); m_options_btn->Show(); + m_parts_btn->Show(); reset_temp_misc_control(); m_ams_control->Hide(); m_ams_control_box->Hide(); m_ams_control->Reset(); error_info_reset(); + SetFocus(); } void StatusPanel::show_status(int status) @@ -4105,14 +4278,14 @@ void StatusPanel::show_status(int status) show_printing_status(false, false); m_calibration_btn->Disable(); m_options_btn->Disable(); + m_parts_btn->Disable(); m_panel_monitoring_title->Disable(); - m_media_play_ctrl->Disable(); } else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) { show_printing_status(true, true); m_calibration_btn->Disable(); m_options_btn->Enable(); + m_parts_btn->Enable(); m_panel_monitoring_title->Enable(); - m_media_play_ctrl->Enable(); } } @@ -4236,7 +4409,10 @@ void StatusPanel::msw_rescale() m_calibration_btn->Rescale(); m_options_btn->SetMinSize(wxSize(-1, FromDIP(26))); - m_options_btn->Rescale(); + m_options_btn->Rescale(); + + m_parts_btn->SetMinSize(wxSize(-1, FromDIP(26))); + m_parts_btn->Rescale(); rescale_camera_icons(); diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 399566373b..d82c6371b6 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -17,6 +17,7 @@ #include "MediaPlayCtrl.h" #include "AMSSetting.hpp" #include "Calibration.hpp" +#include "CalibrationWizardPage.hpp" #include "PrintOptionsDialog.hpp" #include "AMSMaterialsSetting.hpp" #include "ExtrusionCalibration.hpp" @@ -58,6 +59,7 @@ enum CameraTimelapseStatus { enum PrintingTaskType { PRINGINT, CALIBRATION, + NOT_CLEAR }; struct ScoreData @@ -212,7 +214,7 @@ public: void show_error_msg(wxString msg); void reset_printing_value(); void msw_rescale(); - + public: void enable_pause_resume_button(bool enable, std::string type); void enable_abort_button(bool enable); @@ -390,6 +392,7 @@ protected: wxStaticText* m_staticText_calibration_caption; wxStaticText* m_staticText_calibration_caption_top; wxStaticText* m_calibration_text; + Button* m_parts_btn; Button* m_options_btn; Button* m_calibration_btn; StepIndicator* m_calibration_flow; @@ -463,6 +466,7 @@ protected: std::shared_ptr m_camera_popup; std::set rated_model_id; AMSSetting *m_ams_setting_dlg{nullptr}; + PrinterPartsDialog* print_parts_dlg { nullptr }; PrintOptionsDialog* print_options_dlg { nullptr }; CalibrationDialog* calibration_dlg {nullptr}; AMSMaterialsSetting *m_filament_setting_dlg{nullptr}; @@ -504,6 +508,11 @@ protected: std::vector