Merge remote-tracking branch 'BS/v1.7.2'

Signed-off-by: SoftFever <103989404+SoftFever@users.noreply.github.com>

# Conflicts:
#	.github/ISSUE_TEMPLATE/bug_report.md
#	.github/workflows/build_ubuntu.yml
#	.gitignore
#	Containerfile
#	Dockerfile
#	README.md
#	deps/Boost/Boost.cmake
#	deps/OpenEXR/OpenEXR.cmake
#	deps/OpenVDB/OpenVDB.cmake
#	doc/How to build - Mac OS.md
#	localization/i18n/OrcaSlicer.pot
#	localization/i18n/de/OrcaSlicer_de.po
#	localization/i18n/en/OrcaSlicer_en.po
#	localization/i18n/es/OrcaSlicer_es.po
#	localization/i18n/fr/OrcaSlicer_fr.po
#	localization/i18n/hu/OrcaSlicer_hu.po
#	localization/i18n/it/OrcaSlicer_it.po
#	localization/i18n/ja/OrcaSlicer_ja.po
#	localization/i18n/list.txt
#	localization/i18n/nl/OrcaSlicer_nl.po
#	localization/i18n/sv/OrcaSlicer_sv.po
#	localization/i18n/zh_cn/OrcaSlicer_zh_CN.po
#	resources/i18n/de/BambuStudio.mo
#	resources/i18n/en/BambuStudio.mo
#	resources/i18n/es/BambuStudio.mo
#	resources/i18n/fr/BambuStudio.mo
#	resources/i18n/hu/BambuStudio.mo
#	resources/i18n/it/BambuStudio.mo
#	resources/i18n/ja/BambuStudio.mo
#	resources/i18n/nl/BambuStudio.mo
#	resources/i18n/sv/BambuStudio.mo
#	resources/i18n/zh_cn/BambuStudio.mo
#	resources/images/im_all_plates_stats.svg
#	resources/profiles/Anker.json
#	resources/profiles/Anker/filament/Generic ASA @Anker.json
#	resources/profiles/Anker/filament/Generic PA @Anker.json
#	resources/profiles/Anker/filament/Generic PA-CF @Anker.json
#	resources/profiles/Anker/filament/Generic PC @Anker.json
#	resources/profiles/Anker/filament/Generic PETG @Anker.json
#	resources/profiles/Anker/filament/Generic PLA-CF @Anker.json
#	resources/profiles/Anker/filament/Generic PVA @Anker.json
#	resources/profiles/Anker/filament/Generic TPU @Anker.json
#	resources/profiles/Anker/machine/Anker M5 0.4 nozzle.json
#	resources/profiles/Anker/machine/Anker M5.json
#	resources/profiles/Anker/machine/Anker M5C 0.4 nozzle.json
#	resources/profiles/Anker/machine/Anker M5C.json
#	resources/profiles/Anker/machine/fdm_machine_common.json
#	resources/profiles/Anker/process/0.05mm Ultradetail @Anker.json
#	resources/profiles/Anker/process/0.15mm Fast @Anker.json
#	resources/profiles/Anker/process/0.20mm Fast @Anker.json
#	resources/profiles/Anker/process/0.20mm Standard @Anker.json
#	resources/profiles/Anker/process/0.25mm Fast @Anker.json
#	resources/profiles/Anker/process/fdm_process_common.json
#	resources/profiles/Anycubic.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro 2 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro 2.json
#	resources/profiles/Anycubic/machine/Anycubic 4Max Pro.json
#	resources/profiles/Anycubic/machine/Anycubic Chiron 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic Chiron.json
#	resources/profiles/Anycubic/machine/Anycubic Kobra 2 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic Kobra Max 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic Kobra Max.json
#	resources/profiles/Anycubic/machine/Anycubic Vyper 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic Vyper.json
#	resources/profiles/Anycubic/machine/Anycubic i3 Mega S 0.4 nozzle.json
#	resources/profiles/Anycubic/machine/Anycubic i3 Mega S.json
#	resources/profiles/Anycubic/machine/fdm_machine_common.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic 4MaxPro2.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic Chiron.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic Kobra2.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic KobraMax.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic Vyper.json
#	resources/profiles/Anycubic/process/0.15mm Optimal @Anycubic i3MegaS.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic 4MaxPro.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic 4MaxPro2.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic Chiron.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic Kobra2.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic KobraMax.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic Vyper.json
#	resources/profiles/Anycubic/process/0.20mm Standard @Anycubic i3MegaS.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic 4MaxPro2.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic Chiron.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic Kobra2.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic KobraMax.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic Vyper.json
#	resources/profiles/Anycubic/process/0.30mm Draft @Anycubic i3MegaS.json
#	resources/profiles/Anycubic/process/fdm_process_common.json
#	resources/profiles/BBL.json
#	resources/profiles/BBL/process/fdm_process_bbl_common.json
#	resources/profiles/Creality.json
#	resources/profiles/Creality/filament/fdm_filament_abs.json
#	resources/profiles/Creality/filament/fdm_filament_pla.json
#	resources/profiles/Creality/machine/Creality CR-10 Max 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality CR-10 Max.json
#	resources/profiles/Creality/machine/Creality CR-10 V2 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality CR-10 V2.json
#	resources/profiles/Creality/machine/Creality Ender-3 S1 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-3 S1 Pro 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-3 S1 Pro.json
#	resources/profiles/Creality/machine/Creality Ender-3 S1.json
#	resources/profiles/Creality/machine/Creality Ender-3 V2 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-3 V2.json
#	resources/profiles/Creality/machine/Creality Ender-5 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-5 Plus 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-5 Plus.json
#	resources/profiles/Creality/machine/Creality Ender-5 S1 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-5 S1.json
#	resources/profiles/Creality/machine/Creality Ender-5.json
#	resources/profiles/Creality/machine/Creality Ender-5S 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-5S.json
#	resources/profiles/Creality/machine/Creality Ender-6 0.4 nozzle.json
#	resources/profiles/Creality/machine/Creality Ender-6.json
#	resources/profiles/Creality/machine/fdm_creality_common.json
#	resources/profiles/Creality/machine/fdm_machine_common.json
#	resources/profiles/Creality/process/0.12mm Fine @Creality CR10Max.json
#	resources/profiles/Creality/process/0.12mm Fine @Creality Ender3V2.json
#	resources/profiles/Creality/process/0.15mm Optimal @Creality CR10Max.json
#	resources/profiles/Creality/process/0.15mm Optimal @Creality Ender3V2.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality CR10V2.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender3S1.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender3S1Pro.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender5.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender5Plus.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender5S.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender5S1.json
#	resources/profiles/Creality/process/0.16mm Optimal @Creality Ender6.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality CR10Max.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality CR10V2.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender3S1.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender3S1Pro.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender3V2.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender5.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender5Plus.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender5S.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender5S1.json
#	resources/profiles/Creality/process/0.20mm Standard @Creality Ender6.json
#	resources/profiles/Creality/process/0.24mm Draft @Creality CR10Max.json
#	resources/profiles/Creality/process/0.24mm Draft @Creality Ender3V2.json
#	resources/profiles/Creality/process/0.24mm Draft @Creality.json
#	resources/profiles/Creality/process/fdm_process_creality_common.json
#	resources/profiles/Custom/filament/My Generic PETG.json
#	resources/profiles/Custom/filament/My Generic PLA.json
#	resources/profiles/Elegoo.json
#	resources/profiles/Elegoo/filament/fdm_filament_common.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2D 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2D.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2S 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 2S.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Max 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Max.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Plus 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Plus.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Pro 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3 Pro.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune 3.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune X 0.4 nozzle.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune X.json
#	resources/profiles/Elegoo/machine/Elegoo Neptune.json
#	resources/profiles/Elegoo/machine/fdm_machine_common.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.08mm Extra Fine @Elegoo NeptuneX.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.12mm Fine @Elegoo NeptuneX.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.16mm Optimal @Elegoo NeptuneX.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.20mm Standard @Elegoo NeptuneX.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.24mm Draft @Elegoo NeptuneX.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune2.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune2D.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune2S.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune3.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune3Max.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune3Plus.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo Neptune3Pro.json
#	resources/profiles/Elegoo/process/0.28mm Extra Draft @Elegoo NeptuneX.json
#	resources/profiles/Prusa.json
#	resources/profiles/Prusa/filament/fdm_filament_common.json
#	resources/profiles/Prusa/machine/Prusa MINI 0.4 nozzle.json
#	resources/profiles/Prusa/machine/Prusa MINI.json
#	resources/profiles/Prusa/machine/Prusa MK3S 0.4 nozzle.json
#	resources/profiles/Prusa/machine/Prusa MK3S.json
#	resources/profiles/Prusa/machine/fdm_machine_common.json
#	resources/profiles/Prusa/process/0.20mm Standard @MINI.json
#	resources/profiles/Prusa/process/0.20mm Standard @MK3S.json
#	resources/profiles/Qidi.json
#	resources/profiles/Qidi/filament/fdm_filament_abs.json
#	resources/profiles/Qidi/filament/fdm_filament_asa.json
#	resources/profiles/Qidi/filament/fdm_filament_common.json
#	resources/profiles/Qidi/filament/fdm_filament_pa.json
#	resources/profiles/Qidi/filament/fdm_filament_pc.json
#	resources/profiles/Qidi/filament/fdm_filament_pet.json
#	resources/profiles/Qidi/filament/fdm_filament_pla.json
#	resources/profiles/Qidi/filament/fdm_filament_pva.json
#	resources/profiles/Qidi/filament/fdm_filament_tpu.json
#	resources/profiles/Qidi/machine/Qidi X-CF Pro 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-CF Pro.json
#	resources/profiles/Qidi/machine/Qidi X-Max 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-Max 3 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-Max 3.json
#	resources/profiles/Qidi/machine/Qidi X-Max.json
#	resources/profiles/Qidi/machine/Qidi X-Plus 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-Plus 3 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-Plus 3.json
#	resources/profiles/Qidi/machine/Qidi X-Plus.json
#	resources/profiles/Qidi/machine/Qidi X-Smart 3 0.4 nozzle.json
#	resources/profiles/Qidi/machine/Qidi X-Smart 3.json
#	resources/profiles/Qidi/machine/fdm_machine_common.json
#	resources/profiles/Qidi/machine/fdm_qidi_common.json
#	resources/profiles/Qidi/machine/fdm_qidi_x3_common.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XCFPro.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XMax.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XMax3.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XPlus.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XPlus3.json
#	resources/profiles/Qidi/process/0.12mm Fine @Qidi XSmart3.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XCFPro.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XMax.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XMax3.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XPlus.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XPlus3.json
#	resources/profiles/Qidi/process/0.16mm Optimal @Qidi XSmart3.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XCFPro.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XMax.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XMax3.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XPlus.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XPlus3.json
#	resources/profiles/Qidi/process/0.20mm Standard @Qidi XSmart3.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XCFPro.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XMax.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XMax3.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XPlus.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XPlus3.json
#	resources/profiles/Qidi/process/0.25mm Draft @Qidi XSmart3.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XCFPro.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XMax.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XMax3.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XPlus.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XPlus3.json
#	resources/profiles/Qidi/process/0.30mm Extra Draft @Qidi XSmart3.json
#	resources/profiles/Qidi/process/fdm_process_common.json
#	resources/profiles/Qidi/process/fdm_process_qidi_common.json
#	resources/profiles/Qidi/process/fdm_process_qidi_x3_common.json
#	resources/profiles/Tronxy/filament/Tronxy Generic ABS.json
#	resources/profiles/Tronxy/process/0.12mm Fine @Tronxy.json
#	resources/profiles/Tronxy/process/0.15mm Optimal @Tronxy.json
#	resources/profiles/Tronxy/process/0.20mm Standard @Tronxy.json
#	resources/profiles/Tronxy/process/0.24mm Draft @Tronxy.json
#	resources/profiles/Voron.json
#	resources/profiles/Voron/filament/Generic ABS @Voron.json
#	resources/profiles/Voron/filament/Generic ASA @Voron.json
#	resources/profiles/Voron/filament/Generic PA @Voron.json
#	resources/profiles/Voron/filament/Generic PETG @Voron.json
#	resources/profiles/Voron/filament/Generic PVA @Voron.json
#	resources/profiles/Voron/filament/Voron Generic PA-CF.json
#	resources/profiles/Voron/filament/Voron Generic PC.json
#	resources/profiles/Voron/filament/Voron Generic PLA-CF.json
#	resources/profiles/Voron/filament/Voron Generic PLA.json
#	resources/profiles/Voron/filament/Voron Generic TPU.json
#	resources/profiles/Voron/machine/Voron 0.1.json
#	resources/profiles/Voron/machine/Voron 2.4 250.json
#	resources/profiles/Voron/machine/Voron 2.4 300.json
#	resources/profiles/Voron/machine/Voron 2.4 350.json
#	resources/profiles/Voron/machine/Voron Trident 250.json
#	resources/profiles/Voron/machine/Voron Trident 300.json
#	resources/profiles/Voron/machine/Voron Trident 350.json
#	resources/profiles/Voron/process/fdm_process_voron_common.json
#	resources/profiles/Voxelab.json
#	resources/profiles/Voxelab/filament/Generic ABS @Voxelab.json
#	resources/profiles/Voxelab/filament/Generic PLA @Voxelab.json
#	resources/profiles/Voxelab/filament/fdm_filament_common.json
#	resources/profiles/Voxelab/machine/Voxelab Aquila X2 0.4 nozzle.json
#	resources/profiles/Voxelab/machine/Voxelab Aquila X2.json
#	resources/profiles/Voxelab/machine/fdm_machine_common.json
#	resources/profiles/Voxelab/process/0.16mm Optimal @Voxelab AquilaX2.json
#	resources/profiles/Voxelab/process/0.20mm Standard @Voxelab AquilaX2.json
#	resources/web/data/text.js
#	resources/web/guide/21/21.js
#	resources/web/guide/24/24.js
#	src/BaseException.cpp
#	src/OrcaSlicer.cpp
#	src/libslic3r/AppConfig.cpp
#	src/libslic3r/BoundingBox.hpp
#	src/libslic3r/Extruder.hpp
#	src/libslic3r/Fill/Fill.cpp
#	src/libslic3r/Format/bbs_3mf.cpp
#	src/libslic3r/GCode.cpp
#	src/libslic3r/GCode.hpp
#	src/libslic3r/GCode/CoolingBuffer.cpp
#	src/libslic3r/GCode/GCodeProcessor.cpp
#	src/libslic3r/GCode/GCodeProcessor.hpp
#	src/libslic3r/GCode/WipeTower.cpp
#	src/libslic3r/GCodeWriter.cpp
#	src/libslic3r/GCodeWriter.hpp
#	src/libslic3r/Model.cpp
#	src/libslic3r/PerimeterGenerator.cpp
#	src/libslic3r/Preset.cpp
#	src/libslic3r/Preset.hpp
#	src/libslic3r/PresetBundle.cpp
#	src/libslic3r/PresetBundle.hpp
#	src/libslic3r/Print.cpp
#	src/libslic3r/Print.hpp
#	src/libslic3r/PrintBase.hpp
#	src/libslic3r/PrintConfig.cpp
#	src/libslic3r/PrintConfig.hpp
#	src/libslic3r/PrintObject.cpp
#	src/libslic3r/TreeSupport.cpp
#	src/libslic3r/Utils.hpp
#	src/mcut/CMakeLists.txt
#	src/slic3r/CMakeLists.txt
#	src/slic3r/GUI/3DBed.cpp
#	src/slic3r/GUI/AMSMaterialsSetting.cpp
#	src/slic3r/GUI/AMSMaterialsSetting.hpp
#	src/slic3r/GUI/BBLTopbar.cpp
#	src/slic3r/GUI/BBLTopbar.hpp
#	src/slic3r/GUI/BackgroundSlicingProcess.hpp
#	src/slic3r/GUI/BindDialog.cpp
#	src/slic3r/GUI/ConfigManipulation.cpp
#	src/slic3r/GUI/DeviceManager.cpp
#	src/slic3r/GUI/Field.cpp
#	src/slic3r/GUI/GLCanvas3D.cpp
#	src/slic3r/GUI/GUI_App.cpp
#	src/slic3r/GUI/GUI_App.hpp
#	src/slic3r/GUI/GUI_Factories.cpp
#	src/slic3r/GUI/GUI_Factories.hpp
#	src/slic3r/GUI/GUI_ObjectList.cpp
#	src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp
#	src/slic3r/GUI/Jobs/ArrangeJob.cpp
#	src/slic3r/GUI/Jobs/FillBedJob.cpp
#	src/slic3r/GUI/MainFrame.cpp
#	src/slic3r/GUI/MediaPlayCtrl.cpp
#	src/slic3r/GUI/Monitor.cpp
#	src/slic3r/GUI/PartPlate.cpp
#	src/slic3r/GUI/PartPlate.hpp
#	src/slic3r/GUI/PlateSettingsDialog.cpp
#	src/slic3r/GUI/PlateSettingsDialog.hpp
#	src/slic3r/GUI/Plater.cpp
#	src/slic3r/GUI/Plater.hpp
#	src/slic3r/GUI/PresetComboBoxes.cpp
#	src/slic3r/GUI/ReleaseNote.cpp
#	src/slic3r/GUI/SelectMachine.cpp
#	src/slic3r/GUI/StatusPanel.cpp
#	src/slic3r/GUI/Tab.cpp
#	src/slic3r/GUI/Widgets/Label.cpp
#	src/slic3r/GUI/Widgets/Label.hpp
#	src/slic3r/GUI/Widgets/SideButton.cpp
#	src/slic3r/GUI/calib_dlg.cpp
#	src/slic3r/GUI/calib_dlg.hpp
#	src/slic3r/GUI/wxExtensions.hpp
#	src/slic3r/Utils/NetworkAgent.cpp
#	src/slic3r/Utils/bambu_networking.hpp
#	version.inc
This commit is contained in:
SoftFever 2023-08-26 16:13:57 +08:00
commit e65b11a831
734 changed files with 72573 additions and 47919 deletions

View file

@ -3,11 +3,14 @@
#include <string>
#include <sstream>
#include <iostream>
#include <mutex>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#include <mutex>
#define slic3r_Semver_hpp_
#define _libslic3r_h_
#include <libslic3r/Utils.hpp>
static std::string g_log_folder;
static std::atomic<int> g_crash_log_count = 0;
@ -105,127 +108,127 @@ void CBaseException::ShowExceptionResoult(DWORD dwExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
//OutputString(_T("ACCESS_VIOLATION(%s)\r\n"), _T("<EFBFBD><EFBFBD>д<EFBFBD>Ƿ<EFBFBD><EFBFBD>ڴ<EFBFBD>"));
//OutputString(_T("ACCESS_VIOLATION(%s)\r\n"), _T("读写非法内存"));
OutputString(_T("ACCESS_VIOLATION\r\n"));
}
return ;
case EXCEPTION_DATATYPE_MISALIGNMENT:
{
//OutputString(_T("DATATYPE_MISALIGNMENT(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>ڲ<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>дδ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
//OutputString(_T("DATATYPE_MISALIGNMENT(%s)\r\n"), _T("线程视图在不支持对齐的硬件上读写未对齐的数据"));
OutputString(_T("DATATYPE_MISALIGNMENT\r\n"));
}
return ;
case EXCEPTION_BREAKPOINT:
{
//OutputString(_T("BREAKPOINT(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>"));
//OutputString(_T("BREAKPOINT(%s)\r\n"), _T("遇到一个断点"));
OutputString(_T("BREAKPOINT\r\n"));
}
return ;
case EXCEPTION_SINGLE_STEP:
{
//OutputString(_T("SINGLE_STEP(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); //һ<><D2BB><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
//OutputString(_T("SINGLE_STEP(%s)\r\n"), _T("单步")); //一般是发生在调试事件中
OutputString(_T("SINGLE_STEP\r\n"));
}
return ;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
{
//OutputString(_T("ARRAY_BOUNDS_EXCEEDED(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>"));
//OutputString(_T("ARRAY_BOUNDS_EXCEEDED(%s)\r\n"), _T("数组访问越界"));
OutputString(_T("ARRAY_BOUNDS_EXCEEDED\r\n"));
}
return ;
case EXCEPTION_FLT_DENORMAL_OPERAND:
{
//OutputString(_T("FLT_DENORMAL_OPERAND(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ʾ")); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//OutputString(_T("FLT_DENORMAL_OPERAND(%s)\r\n"), _T("浮点操作的一个操作数不正规,给定的浮点数无法表示")); //操作数的问题
OutputString(_T("FLT_DENORMAL_OPERAND\r\n"));
}
return ;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
{
//OutputString(_T("FLT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
//OutputString(_T("FLT_DIVIDE_BY_ZERO(%s)\r\n"), _T("浮点数除0操作"));
OutputString(_T("FLT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_FLT_INEXACT_RESULT:
{
//OutputString(_T("FLT_INEXACT_RESULT(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ʾ")); //<2F>޷<EFBFBD><DEB7><EFBFBD>ʾһ<CABE><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̫С<CCAB><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ķ<EFBFBD>Χ, <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD>
//OutputString(_T("FLT_INEXACT_RESULT(%s)\r\n"), _T("浮点数操作的结果无法表示")); //无法表示一般是数据太小,超过浮点数表示的范围, 计算之后产生的结果异常
OutputString(_T("FLT_INEXACT_RESULT\r\n"));
}
return ;
case EXCEPTION_FLT_INVALID_OPERATION:
{
//OutputString(_T("FLT_INVALID_OPERATION(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
//OutputString(_T("FLT_INVALID_OPERATION(%s)\r\n"), _T("其他浮点数异常"));
OutputString(_T("FLT_INVALID_OPERATION\r\n"));
}
return ;
case EXCEPTION_FLT_OVERFLOW:
{
//OutputString(_T("FLT_OVERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ"));
//OutputString(_T("FLT_OVERFLOW(%s)\r\n"), _T("浮点操作的指数超过了相应类型的最大值"));
OutputString(_T("FLT_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_FLT_STACK_CHECK:
{
//OutputString(_T("STACK_CHECK(%s)\r\n"), _T("ջԽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
//OutputString(_T("STACK_CHECK(%s)\r\n"), _T("栈越界或者栈向下溢出"));
OutputString(_T("STACK_CHECK\r\n"));
}
return ;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
{
//OutputString(_T("INT_DIVIDE_BY_ZERO(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD>"));
//OutputString(_T("INT_DIVIDE_BY_ZERO(%s)\r\n"), _T("整数除0异常"));
OutputString(_T("INT_DIVIDE_BY_ZERO\r\n"));
}
return ;
case EXCEPTION_INVALID_HANDLE:
{
//OutputString(_T("INVALID_HANDLE(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч"));
//OutputString(_T("INVALID_HANDLE(%s)\r\n"), _T("句柄无效"));
OutputString(_T("INVALID_HANDLE\r\n"));
}
return ;
case EXCEPTION_PRIV_INSTRUCTION:
{
//OutputString(_T("PRIV_INSTRUCTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼִ<EFBFBD>е<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>ָ<EFBFBD><EFBFBD>"));
//OutputString(_T("PRIV_INSTRUCTION(%s)\r\n"), _T("线程试图执行当前机器模式不支持的指令"));
OutputString(_T("PRIV_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_IN_PAGE_ERROR:
{
//OutputString(_T("IN_PAGE_ERROR(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><EFBFBD>ܼ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ"));
//OutputString(_T("IN_PAGE_ERROR(%s)\r\n"), _T("线程视图访问未加载的虚拟内存页或者不能加载的虚拟内存页"));
OutputString(_T("IN_PAGE_ERROR\r\n"));
}
return ;
case EXCEPTION_ILLEGAL_INSTRUCTION:
{
//OutputString(_T("ILLEGAL_INSTRUCTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Чָ<EFBFBD><EFBFBD>"));
//OutputString(_T("ILLEGAL_INSTRUCTION(%s)\r\n"), _T("线程视图执行无效指令"));
OutputString(_T("ILLEGAL_INSTRUCTION\r\n"));
}
return ;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
{
//OutputString(_T("NONCONTINUABLE_EXCEPTION(%s)\r\n"), _T("<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>"));
//OutputString(_T("NONCONTINUABLE_EXCEPTION(%s)\r\n"), _T("线程试图在一个不可继续执行的异常发生后继续执行"));
OutputString(_T("NONCONTINUABLE_EXCEPTION\r\n"));
}
return ;
case EXCEPTION_STACK_OVERFLOW:
{
//OutputString(_T("STACK_OVERFLOW(%s)\r\n"), _T("ջ<EFBFBD><EFBFBD><EFBFBD>"));
//OutputString(_T("STACK_OVERFLOW(%s)\r\n"), _T("栈溢出"));
OutputString(_T("STACK_OVERFLOW\r\n"));
}
return ;
case EXCEPTION_INVALID_DISPOSITION:
{
//OutputString(_T("INVALID_DISPOSITION(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")); //ʹ<>ø߼<C3B8><DFBC><EFBFBD><EFBFBD>Ա<EFBFBD>д<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//OutputString(_T("INVALID_DISPOSITION(%s)\r\n"), _T("异常处理程序给异常调度器返回了一个无效配置")); //使用高级语言编写的程序永远不会遇到这个异常
OutputString(_T("INVALID_DISPOSITION\r\n"));
}
return ;
case EXCEPTION_FLT_UNDERFLOW:
{
//OutputString(_T("FLT_UNDERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Сֵ"));
//OutputString(_T("FLT_UNDERFLOW(%s)\r\n"), _T("浮点数操作的指数小于相应类型的最小值"));
OutputString(_T("FLT_UNDERFLOW\r\n"));
}
return ;
case EXCEPTION_INT_OVERFLOW:
{
//OutputString(_T("INT_OVERFLOW(%s)\r\n"), _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>"));
//OutputString(_T("INT_OVERFLOW(%s)\r\n"), _T("整数操作越界"));
OutputString(_T("INT_OVERFLOW\r\n"));
}
return ;
@ -254,6 +257,7 @@ LONG WINAPI CBaseException::UnhandledExceptionFilter(PEXCEPTION_POINTERS pExcept
//BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": got an ExceptionCode %1%, skip it!") % pExceptionInfo->ExceptionRecord->ExceptionCode;
return EXCEPTION_CONTINUE_SEARCH;
}
Slic3r::flush_logs();
g_dump_mutex.lock();
CBaseException base(GetCurrentProcess(), GetCurrentProcessId(), NULL, pExceptionInfo);
base.ShowExceptionInformation();
@ -292,7 +296,7 @@ BOOL CBaseException::GetLogicalAddress(
DWORD rva = (DWORD)addr - hMod;
//<EFBFBD><EFBFBD><EFBFBD>㵱ǰ<EFBFBD><EFBFBD>ַ<EFBFBD>ڵڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//计算当前地址在第几个节
for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
{
DWORD sectionStart = pSection->VirtualAddress;

View file

@ -248,6 +248,12 @@ else ()
COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${BIN_RESOURCES_DIR}"
COMMENT "Symlinking the resources directory into the build tree"
VERBATIM)
if (UNIX AND NOT APPLE)
add_custom_command(TARGET BambuStudio POST_BUILD
COMMAND ln -sfn "zh_cn" "${BIN_RESOURCES_DIR}/i18n/zh_CN"
COMMENT "Symlinking zh_CN language setting to zh_cn"
VERBATIM)
endif()
endif ()
# Slic3r binary install target. Default build type is release in case no CMAKE_BUILD_TYPE is provided.

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,7 @@ private:
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
std::string output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format) const;
};
}

View file

@ -84,6 +84,7 @@ public:
//BBS: virtual object to mark unprintable region on heatbed
bool is_virt_object{ false };
bool is_wipe_tower{ false };
bool has_tried_with_excluded{ false };
/// The type of the shape which was handed over as the template argument.
using ShapeType = RawShape;
@ -662,9 +663,21 @@ public:
/// Get the packed items.
inline ItemGroup getItems() { return impl_.getItems(); }
inline int getPackedSize()
{
int size = 0;
auto items = getItems();
for (const auto &itm : items) {
if (itm.get().isFixed() == false) { size++; }
}
return size;
}
/// Clear the packed items so a new session can be started.
inline void clearItems() { impl_.clearItems(); }
inline void clearItems(const std::function<bool(const Item &itm)> &func) { impl_.clearItems(func); }
inline double filledArea() const { return impl_.filledArea(); }
inline double score() const { return impl_.score(); }

View file

@ -555,6 +555,13 @@ public:
Base::clearItems();
}
//clearFunc: itm will be cleared if return ture
inline void clearItems(const std::function<bool(const Item &itm)> &clearFunc)
{
finalAlign(bin_);
Base::clearItems(clearFunc);
}
void preload(const ItemGroup& packeditems) {
Base::preload(packeditems);
if (config_.on_preload)

View file

@ -96,6 +96,17 @@ public:
farea_valid_ = false;
}
//clearFunc: will be cleared if return true
inline void clearItems(const std::function<bool(const Item &itm)> &clearFunc)
{
ItemGroup newGroup;
for (auto &i : items_) {
if (clearFunc(i.get()) == false) { newGroup.push_back(i); }
}
std::swap(newGroup, items_);
farea_valid_ = false;
}
inline double filledArea() const {
if(farea_valid_) return farea_;
else {

View file

@ -161,6 +161,24 @@ public:
makeProgress(placers[j], j);
}
if (was_packed && it->get().has_tried_with_excluded) {
placers[j].clearItems([](const Item &itm) { return itm.isFixed() && !itm.is_wipe_tower; });
placers[j].preload(fixed_bins[placers.size() - 1]);
}
bool placer_not_packed = !was_packed && !placers.empty() && j == placers.size() && placers[j - 1].getPackedSize() == 0; // large item is not placed into the bin
if (placer_not_packed) {
if (it->get().has_tried_with_excluded == false) {
it->get().has_tried_with_excluded = true;
placers[j - 1].clearItems([](const Item &itm) { return itm.isFixed()&&!itm.is_wipe_tower; });
placers[j - 1].preload(pconfig.m_excluded_items);
j = j - 1;
continue;
} else {
placers[j - 1].clearItems([](const Item &itm) { return itm.isFixed() && !itm.is_wipe_tower; });
placers[j - 1].preload(fixed_bins[placers.size() - 1]);
}
}
if(!was_packed){
if (this->unfitindicator_ && !placers.empty())
this->unfitindicator_(it->get().name + ", height=" +std::to_string(it->get().height)

View file

@ -37,7 +37,7 @@ protected:
// then it should be removed from the list
Placer p{ bin };
p.configure(pcfg);
//p.preload(pcfg.m_excluded_items);
p.preload(pcfg.m_excluded_items);
auto it = c.begin();
while (it != c.end() && !stopcond_()) {

View file

@ -38,7 +38,7 @@ using namespace nlohmann;
namespace Slic3r {
static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/softfever/OrcaSlicer/releases";
static const std::string VERSION_CHECK_URL = "";
static const std::string MODELS_STR = "models";
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
@ -65,19 +65,19 @@ std::string AppConfig::get_hms_host()
{
std::string sel = get("iot_environment");
std::string host = "";
// #if !BBL_RELEASE_TO_PUBLIC
// if (sel == ENV_DEV_HOST)
// host = "e-dev.bambu-lab.com";
// else if (sel == ENV_QAT_HOST)
// host = "e-qa.bambu-lab.com";
// else if (sel == ENV_PRE_HOST)
// host = "e-pre.bambu-lab.com";
// else if (sel == ENV_PRODUCT_HOST)
// host = "e.bambulab.com";
// return host;
// #else
#if !BBL_RELEASE_TO_PUBLIC
if (sel == ENV_DEV_HOST)
host = "e-dev.bambu-lab.com";
else if (sel == ENV_QAT_HOST)
host = "e-qa.bambu-lab.com";
else if (sel == ENV_PRE_HOST)
host = "e-pre.bambu-lab.com";
else if (sel == ENV_PRODUCT_HOST)
host = "e.bambulab.com";
return host;
#else
return "e.bambulab.com";
// #endif
#endif
}
void AppConfig::reset()
@ -178,9 +178,6 @@ void AppConfig::set_defaults()
set_bool("show_hints", true);
//#endif
if (get("show_gcode_window").empty())
set_bool("show_gcode_window", true);
#ifdef _WIN32
@ -229,10 +226,6 @@ void AppConfig::set_defaults()
set("slicer_uuid", to_string(uuid));
}
// Orca
if (get("stealth_mode").empty()) {
set_bool("stealth_mode", false);
}
if (get("show_model_mesh").empty()) {
set_bool("show_model_mesh", false);
}
@ -305,6 +298,10 @@ void AppConfig::set_defaults()
set("max_recent_count", "18");
}
if (get("staff_pick_switch").empty()) {
set_bool("staff_pick_switch", true);
}
if (get("sync_system_preset").empty()) {
set_bool("sync_system_preset", true);
}
@ -321,19 +318,15 @@ void AppConfig::set_defaults()
set("curr_bed_type", "1");
}
// #if BBL_RELEASE_TO_PUBLIC
#if BBL_RELEASE_TO_PUBLIC
if (get("iot_environment").empty()) {
set("iot_environment", "3");
}
// #else
// if (get("iot_environment").empty()) {
// set("iot_environment", "1");
// }
// #endif
if (get("presets", "filament_colors").empty()) {
set_str("presets", "filament_colors", "#F2754E");
#else
if (get("iot_environment").empty()) {
set("iot_environment", "1");
}
#endif
if (get("print", "bed_leveling").empty()) {
set_str("print", "bed_leveling", "1");
@ -515,11 +508,30 @@ std::string AppConfig::load()
m_storage[it.key()][iter.key()] = iter.value().get<std::string>();
}
}
} else if (it.key() == "orca_presets") {
for (auto& j_model : it.value()) {
m_printer_settings[j_model["machine"].get<std::string>()] = j_model;
} else if (it.key() == "calis") {
for (auto &calis_j : it.value()) {
PrinterCaliInfo cali_info;
if (calis_j.contains("dev_id"))
cali_info.dev_id = calis_j["dev_id"].get<std::string>();
if (calis_j.contains("cali_finished"))
cali_info.cali_finished = bool(calis_j["cali_finished"].get<int>());
if (calis_j.contains("flow_ratio"))
cali_info.cache_flow_ratio = calis_j["flow_ratio"].get<float>();
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++) {
CaliPresetInfo preset_info;
preset_info.tray_id = cali_it.value()["tray_id"].get<int>();
preset_info.nozzle_diameter = cali_it.value()["nozzle_diameter"].get<float>();
preset_info.filament_id = cali_it.value()["filament_id"].get<std::string>();
preset_info.setting_id = cali_it.value()["setting_id"].get<std::string>();
preset_info.name = cali_it.value()["name"].get<std::string>();
cali_info.selected_presets.push_back(preset_info);
}
}
m_printer_cali_infos.emplace_back(cali_info);
}
}else {
} else {
if (it.value().is_object()) {
for (auto iter = it.value().begin(); iter != it.value().end(); iter++) {
if (iter.value().is_boolean()) {
@ -618,6 +630,23 @@ void AppConfig::save()
j["app"]["filament_colors"].push_back(filament_color);
}
for (const auto &cali_info : m_printer_cali_infos) {
json cali_json;
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;
for (auto filament_preset : cali_info.selected_presets) {
json preset_json;
preset_json["tray_id"] = filament_preset.tray_id;
preset_json["nozzle_diameter"] = filament_preset.nozzle_diameter;
preset_json["filament_id"] = filament_preset.filament_id;
preset_json["setting_id"] = filament_preset.setting_id;
preset_json["name"] = filament_preset.name;
cali_json["presets"].push_back(preset_json);
}
j["calis"].push_back(cali_json);
}
// Write the other categories.
for (const auto& category : m_storage) {
if (category.first.empty())
@ -638,8 +667,7 @@ void AppConfig::save()
j[category.first][kvp.first] = kvp.second;
}
}
if(j_filament_array.size() > 0)
j["presets"]["filaments"] = j_filament_array;
j["presets"]["filaments"] = j_filament_array;
continue;
}
for (const auto& kvp : category.second) {
@ -674,10 +702,6 @@ void AppConfig::save()
}
}
// write machine settings
for (const auto& preset : m_printer_settings) {
j["orca_presets"].push_back(preset.second);
}
boost::nowide::ofstream c;
c.open(path_pid, std::ios::out | std::ios::trunc);
c << std::setw(4) << j << std::endl;
@ -945,6 +969,22 @@ void AppConfig::set_vendors(const AppConfig &from)
m_dirty = true;
}
void AppConfig::save_printer_cali_infos(const PrinterCaliInfo &cali_info)
{
auto iter = std::find_if(m_printer_cali_infos.begin(), m_printer_cali_infos.end(), [&cali_info](const PrinterCaliInfo &cali_info_item) {
return cali_info_item.dev_id == cali_info.dev_id;
});
if (iter == m_printer_cali_infos.end()) {
m_printer_cali_infos.emplace_back(cali_info);
} else {
(*iter).cali_finished = cali_info.cali_finished;
(*iter).cache_flow_ratio = cali_info.cache_flow_ratio;
(*iter).selected_presets = cali_info.selected_presets;
}
m_dirty = true;
}
std::string AppConfig::get_last_dir() const
{
const auto it = m_storage.find("recent");
@ -1088,29 +1128,29 @@ void AppConfig::update_last_backup_dir(const std::string& dir)
std::string AppConfig::get_region()
{
// #if BBL_RELEASE_TO_PUBLIC
#if BBL_RELEASE_TO_PUBLIC
return this->get("region");
// #else
// std::string sel = get("iot_environment");
// std::string region;
// if (sel == ENV_DEV_HOST)
// region = "ENV_CN_DEV";
// else if (sel == ENV_QAT_HOST)
// region = "ENV_CN_QA";
// else if (sel == ENV_PRE_HOST)
// region = "ENV_CN_PRE";
// if (region.empty())
// return this->get("region");
// return region;
// #endif
#else
std::string sel = get("iot_environment");
std::string region;
if (sel == ENV_DEV_HOST)
region = "ENV_CN_DEV";
else if (sel == ENV_QAT_HOST)
region = "ENV_CN_QA";
else if (sel == ENV_PRE_HOST)
region = "ENV_CN_PRE";
if (region.empty())
return this->get("region");
return region;
#endif
}
std::string AppConfig::get_country_code()
{
std::string region = get_region();
// #if !BBL_RELEASE_TO_PUBLIC
// if (is_engineering_region()) { return region; }
// #endif
#if !BBL_RELEASE_TO_PUBLIC
if (is_engineering_region()) { return region; }
#endif
if (region == "CHN" || region == "China")
return "CN";
else if (region == "USA")

View file

@ -9,6 +9,7 @@
#include "libslic3r/Config.hpp"
#include "libslic3r/Semver.hpp"
#include "Calib.hpp"
using namespace nlohmann;
@ -204,6 +205,9 @@ public:
m_dirty = true;
}
const std::vector<PrinterCaliInfo> &get_printer_cali_infos() const { return m_printer_cali_infos; }
void save_printer_cali_infos(const PrinterCaliInfo& cali_info);
// return recent/last_opened_folder or recent/settings_folder or empty string.
std::string get_last_dir() const;
void update_config_dir(const std::string &dir);
@ -305,6 +309,8 @@ private:
std::vector<std::string> m_filament_presets;
std::vector<std::string> m_filament_colors;
std::vector<PrinterCaliInfo> m_printer_cali_infos;
};
} // namespace Slic3r

View file

@ -268,13 +268,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr
{
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), SCALED_EPSILON));
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
}
}
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow)
{
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), SCALED_EPSILON));
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
}
} // namespace Slic3r

View file

@ -70,23 +70,14 @@ public:
return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) ||
this->max(1) < other.min(1) || this->min(1) > other.max(1));
}
PointClass operator[](size_t idx) const {
PointClass operator[](size_t idx) const
{
switch (idx) {
case 0:
return min;
break;
case 1:
return PointClass(max(0), min(1));
break;
case 2:
return max;
break;
case 3:
return PointClass(min(0), max(1));
break;
default:
return PointClass();
break;
case 0: return min; break;
case 1: return PointClass(max(0), min(1)); break;
case 2: return max; break;
case 3: return PointClass(min(0), max(1)); break;
default: return PointClass(); break;
}
return PointClass();
}

View file

@ -23,8 +23,8 @@ void make_brim(const Print& print, PrintTryCancel try_cancel,
std::vector<unsigned int>& printExtruders);
// BBS: automatically make brim
ExtrusionEntityCollection make_brim_auto(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area);
ExtrusionEntityCollection make_brim_auto(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area);
} // Slic3r
#endif // slic3r_Brim_hpp_

View file

@ -37,6 +37,8 @@ set(lisbslic3r_sources
Brim.hpp
BuildVolume.cpp
BuildVolume.hpp
Calib.cpp
Calib.hpp
Circle.cpp
Circle.hpp
clipper.cpp

748
src/libslic3r/Calib.cpp Normal file
View file

@ -0,0 +1,748 @@
#include "Calib.hpp"
#include "Config.hpp"
#include "Model.hpp"
#include "GCode.hpp"
#include <cmath>
namespace Slic3r {
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx)
{
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),
filament_max_volumetric_speed / pattern_line.mm3_per_mm());
return std::floor(pa_speed);
}
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::string comment)
{
std::stringstream gcode;
gcode << writer.retract();
gcode << writer.travel_to_xy(pt, comment);
gcode << writer.unretract();
m_last_pos = Vec3d(pt.x(), pt.y(), 0);
return gcode.str();
}
double CalibPressureAdvance::e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const
{
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const double filament_area = M_PI * std::pow(filament_diameter / 2, 2);
return line_flow.mm3_per_mm() / filament_area * print_flow_ratio;
}
std::string CalibPressureAdvance::convert_number_to_string(double num) const
{
auto sNumber = std::to_string(num);
sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos);
sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos);
return sNumber;
}
std::string CalibPressureAdvance::draw_digit(
double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer)
{
const double len = m_digit_segment_len;
const double gap = line_width / 2.0;
const auto dE = e_per_mm * len;
const auto two_dE = dE * 2;
Vec2d p0, p1, p2, p3, p4, p5;
Vec2d p0_5, p4_5;
Vec2d gap_p0_toward_p3, gap_p2_toward_p3;
Vec2d dot_direction;
if (mode == CalibPressureAdvance::DrawDigitMode::Bottom_To_Top) {
// 1-------2-------5
// | | |
// | | |
// 0-------3-------4
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx, starty + len / 2);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p4_5 = Vec2d(startx + len * 2, starty + len / 2);
p5 = Vec2d(startx + len * 2, starty + len);
gap_p0_toward_p3 = p0 + Vec2d(gap, 0);
gap_p2_toward_p3 = p2 + Vec2d(0, gap);
dot_direction = Vec2d(-len / 2, 0);
} else {
// 0-------1
// | |
// 3-------2
// | |
// 4-------5
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx + len / 2, starty);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p4_5 = Vec2d(startx + len / 2, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
gap_p0_toward_p3 = p0 - Vec2d(0, gap);
gap_p2_toward_p3 = p2 - Vec2d(gap, 0);
dot_direction = Vec2d(0, len / 2);
}
std::stringstream gcode;
switch (c) {
case '0':
gcode << move_to(p0, writer, "Glyph: 0");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(gap_p0_toward_p3, two_dE);
break;
case '1':
gcode << move_to(p0_5, writer, "Glyph: 1");
gcode << writer.extrude_to_xy(p4_5, two_dE);
break;
case '2':
gcode << move_to(p0, writer, "Glyph: 2");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(p5, dE);
break;
case '3':
gcode << move_to(p0, writer, "Glyph: 3");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << move_to(gap_p2_toward_p3, writer);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '4':
gcode << move_to(p0, writer, "Glyph: 4");
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << move_to(p1, writer);
gcode << writer.extrude_to_xy(p5, two_dE);
break;
case '5':
gcode << move_to(p1, writer, "Glyph: 5");
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p4, dE);
break;
case '6':
gcode << move_to(p1, writer, "Glyph: 6");
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p4, two_dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p2, dE);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '7':
gcode << move_to(p0, writer, "Glyph: 7");
gcode << writer.extrude_to_xy(p1, dE);
gcode << writer.extrude_to_xy(p5, two_dE);
break;
case '8':
gcode << move_to(p2, writer, "Glyph: 8");
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p4, dE);
gcode << writer.extrude_to_xy(p5, dE);
gcode << writer.extrude_to_xy(p1, two_dE);
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
break;
case '9':
gcode << move_to(p5, writer, "Glyph: 9");
gcode << writer.extrude_to_xy(p1, two_dE);
gcode << writer.extrude_to_xy(p0, dE);
gcode << writer.extrude_to_xy(p3, dE);
gcode << writer.extrude_to_xy(p2, dE);
break;
case '.':
gcode << move_to(p4_5, writer, "Glyph: .");
gcode << writer.extrude_to_xy(p4_5 + dot_direction, dE);
break;
default: break;
}
return gcode.str();
}
std::string CalibPressureAdvance::draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer)
{
auto sNumber = convert_number_to_string(value);
std::stringstream gcode;
gcode << writer.set_speed(speed);
for (std::string::size_type i = 0; i < sNumber.length(); ++i) {
if (i > m_max_number_len) { break; }
switch (mode) {
case DrawDigitMode::Bottom_To_Top: gcode << draw_digit(startx, starty + i * number_spacing(), sNumber[i], mode, line_width, e_per_mm, writer); break;
default: gcode << draw_digit(startx + i * number_spacing(), starty, sNumber[i], mode, line_width, e_per_mm, writer);
}
}
return gcode.str();
}
CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen)
: mp_gcodegen(gcodegen)
, m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{
}
std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, double step_pa /*= 0.002*/, int count /*= 10*/)
{
BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values);
if (is_delta()) { CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext); }
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
m_length_long = 40 + std::min(w - 120.0, 0.0);
auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2;
auto starty = (h - count * m_space_y) / 2;
if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); }
return print_pa_lines(startx, starty, start_pa, step_pa, count);
}
bool CalibPressureAdvanceLine::is_delta() const { return mp_gcodegen->config().printable_area.values.size() > 4; }
std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num)
{
auto & writer = mp_gcodegen->writer();
const auto &config = mp_gcodegen->config();
const auto filament_diameter = config.filament_diameter.get_at(0);
const auto print_flow_ratio = config.print_flow_ratio;
const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
std::stringstream gcode;
gcode << mp_gcodegen->writer().travel_to_z(m_height_layer);
double y_pos = start_y;
// prime line
auto prime_x = start_x - 2;
gcode << move_to(Vec2d(prime_x, y_pos + (num - 4) * m_space_y), writer);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos + 3 * m_space_y), e_per_mm * m_space_y * num * 1.1);
for (int i = 0; i < num; ++i) {
gcode << writer.set_pressure_advance(start_pa + i * step_pa);
gcode << move_to(Vec2d(start_x, y_pos + i * m_space_y), writer);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short);
gcode << writer.set_speed(fast);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + i * m_space_y), e_per_mm * m_length_long);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * m_space_y), e_per_mm * m_length_short);
}
gcode << writer.set_pressure_advance(0.0);
if (m_draw_numbers) {
// draw indicator lines
gcode << writer.set_speed(fast);
gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 2), writer);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), thin_e_per_mm * 7);
gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7), writer);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7);
for (int i = 0; i < num; i += 2) {
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode,
m_number_line_width, number_e_per_mm, 3600, writer);
}
}
return gcode.str();
}
void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty, int count)
{
startx = -startx;
starty = -(count * m_space_y) / 2;
}
CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
: m_params(params)
{
this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top;
refresh_setup(config, is_bbl_machine, model, origin);
};
void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
{
std::stringstream gcode;
gcode << "; start pressure advance pattern for layer\n";
refresh_setup(config, is_bbl_machine, model, origin);
gcode << move_to(Vec2d(m_starting_point.x(), m_starting_point.y()), m_writer, "Move to start XY position");
gcode << m_writer.travel_to_z(height_first_layer(), "Move to start Z position");
gcode << m_writer.set_pressure_advance(m_params.start);
const DrawBoxOptArgs default_box_opt_args(*this);
// create anchoring frame
gcode << draw_box(m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args);
// create tab for numbers
DrawBoxOptArgs draw_box_opt_args = default_box_opt_args;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.num_perimeters = wall_count();
gcode << draw_box(m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args);
std::vector<CustomGCode::Item> gcode_items;
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
// draw pressure advance pattern
for (int i = 0; i < m_num_layers; ++i) {
if (i > 0) {
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = height_first_layer() + (i - 1) * height_layer();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
gcode = std::stringstream(); // reset for next layer contents
gcode << "; start pressure advance pattern for layer\n";
const double layer_height = height_first_layer() + (i * height_layer());
gcode << m_writer.travel_to_z(layer_height, "Move to layer height");
}
// line numbering
if (i == 1) {
gcode << m_writer.set_pressure_advance(m_params.start);
double number_e_per_mm = e_per_mm(line_width(), height_layer(), m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
// glyph on every other line
for (int j = 0; j < num_patterns; j += 2) {
gcode << draw_number(glyph_start_x(j), m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(), m_params.start + (j * m_params.step),
m_draw_digit_mode, line_width(), number_e_per_mm, speed_first_layer(), m_writer);
}
}
DrawLineOptArgs draw_line_opt_args = default_line_opt_args;
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double side_length = m_wall_side_length;
// shrink first layer to fit inside frame
if (i == 0) {
double shrink = (line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment))) / std::sin(to_radians(m_corner_angle) / 2);
side_length = m_wall_side_length - shrink;
to_x += shrink * std::sin(to_radians(90) - to_radians(m_corner_angle) / 2);
to_y += line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment));
}
double initial_x = to_x;
double initial_y = to_y;
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to pattern start");
for (int j = 0; j < num_patterns; ++j) {
// increment pressure advance
gcode << m_writer.set_pressure_advance(m_params.start + (j * m_params.step));
for (int k = 0; k < wall_count(); ++k) {
to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_x -= std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_y = initial_y;
if (k != wall_count() - 1) {
// perimeters not done yet. move to next perimeter
to_x += line_spacing_angle();
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to start next pattern wall");
} else if (j != num_patterns - 1) {
// patterns not done yet. move to next pattern
to_x += m_pattern_spacing + line_width();
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move to next pattern");
} else if (i != m_num_layers - 1) {
// layers not done yet. move back to start
to_x = initial_x;
gcode << move_to(Vec2d(to_x, to_y), m_writer, "Move back to start position");
} else {
// everything done
}
}
}
}
gcode << m_writer.set_pressure_advance(m_params.start);
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = max_layer_z();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
CustomGCode::Info info;
info.mode = CustomGCode::Mode::SingleExtruder;
info.gcodes = gcode_items;
model.plates_custom_gcodes[model.curr_plate_index] = info;
}
void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
m_config = config;
m_config.apply(model.objects.front()->config.get(), true);
m_config.apply(model.objects.front()->volumes.front()->config.get(), true);
m_is_delta = (m_config.option<ConfigOptionPoints>("printable_area")->values.size() > 4);
_refresh_starting_point(model);
_refresh_writer(is_bbl_machine, model, origin);
}
void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
{
ModelObject * obj = model.objects.front();
BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false);
m_starting_point = Vec3d(bbox.min.x(), bbox.max.y(), 0);
m_starting_point.y() += m_handle_spacing;
if (m_is_delta) {
m_starting_point.x() *= -1;
m_starting_point.y() -= (frame_size_y() / 2);
}
}
void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
PrintConfig print_config;
print_config.apply(m_config, true);
m_writer.apply_print_config(print_config);
m_writer.set_xy_offset(origin(0), origin(1));
//m_writer.set_is_bbl_machine(is_bbl_machine);
const unsigned int extruder_id = model.objects.front()->volumes.front()->extruder_id();
m_writer.set_extruders({extruder_id});
m_writer.set_extruder(extruder_id);
}
std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs opt_args)
{
const double e_per_mm = CalibPressureAdvance::e_per_mm(opt_args.line_width, opt_args.height, m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt);
auto dE = e_per_mm * length;
std::stringstream gcode;
gcode << m_writer.set_speed(opt_args.speed);
gcode << m_writer.extrude_to_xy(to_pt, dE, opt_args.comment);
m_last_pos = Vec3d(to_pt.x(), to_pt.y(), 0);
return gcode.str();
}
std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args)
{
std::stringstream gcode;
double x = min_x;
double y = min_y;
const double max_x = min_x + size_x;
const double max_y = min_y + size_y;
const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4);
// if number of perims exceeds size of box, reduce it to max
const int max_perimeters = std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))));
opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters);
gcode << move_to(Vec2d(min_x, min_y), m_writer, "Move to box start");
DrawLineOptArgs line_opt_args(*this);
line_opt_args.height = opt_args.height;
line_opt_args.line_width = opt_args.line_width;
line_opt_args.speed = opt_args.speed;
for (int i = 0; i < opt_args.num_perimeters; ++i) {
if (i != 0) { // after first perimeter, step inwards to start next perimeter
x += spacing;
y += spacing;
gcode << move_to(Vec2d(x, y), m_writer, "Step inwards to print next perimeter");
}
y += size_y - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (up)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
x += size_x - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (right)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
y -= size_y - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (down)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
x -= size_x - i * spacing * 2;
line_opt_args.comment = "Draw perimeter (left)";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
if (!opt_args.is_filled) { return gcode.str(); }
// create box infill
const double spacing_45 = spacing / std::sin(to_radians(45));
const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment));
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45);
double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45);
x = x_min_bound;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Move to fill start");
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0);
++i) { // this isn't the most robust way, but less expensive than finding line intersections
if (i < std::min(x_count, y_count)) {
if (i % 2 == 0) {
x += spacing_45;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y += x - x_min_bound;
x = x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
y += spacing_45;
x = x_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x += y - y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
} else if (i < std::max(x_count, y_count)) {
if (x_count > y_count) {
// box is wider than tall
if (i % 2 == 0) {
x += spacing_45;
y = y_min_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x -= y_max_bound - y_min_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
if (i == y_count) {
x += spacing_45 - y_remainder;
y_remainder = 0;
} else {
x += spacing_45;
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x += y_max_bound - y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
} else {
// box is taller than wide
if (i % 2 == 0) {
x = x_max_bound;
if (i == x_count) {
y += spacing_45 - x_remainder;
x_remainder = 0;
} else {
y += spacing_45;
}
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x = x_min_bound;
y += x_max_bound - x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
x = x_min_bound;
y += spacing_45;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x = x_max_bound;
y -= x_max_bound - x_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
}
} else {
if (i % 2 == 0) {
x = x_max_bound;
if (i == x_count) {
y += spacing_45 - x_remainder;
} else {
y += spacing_45;
}
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x -= y_max_bound - y;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
if (i == y_count) {
x += spacing_45 - y_remainder;
} else {
x += spacing_45;
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y -= x_max_bound - x;
x = x_max_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
}
}
return gcode.str();
}
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); }
double CalibPressureAdvancePattern::object_size_x() const
{
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) + (get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length + line_spacing_first_layer() * wall_count();
}
double CalibPressureAdvancePattern::object_size_y() const
{
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) + max_numbering_height() + m_glyph_padding_vertical * 2 + line_width_first_layer();
}
double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
{
// note that pattern_i is zero-based!
// align glyph's start with first perimeter of specified pattern
double x =
// starting offset
m_starting_point.x() + pattern_shift() +
// width of pattern extrusions
pattern_i * (wall_count() - 1) * line_spacing_angle() + // center to center distance of extrusions
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
// space between each pattern
pattern_i * m_pattern_spacing;
// align to middle of pattern walls
x += wall_count() * line_spacing_angle() / 2;
// shift so glyph is centered on pattern
// m_digit_segment_len = half of X length of glyph
x -= (glyph_length_x() / 2);
return x;
}
double CalibPressureAdvancePattern::glyph_length_x() const
{
// half of line_width sticks out on each side
return line_width() + (2 * m_digit_segment_len);
}
double CalibPressureAdvancePattern::glyph_tab_max_x() const
{
// only every other glyph is shown, starting with 1
int num = get_num_patterns();
int max_num = (num % 2 == 0) ? num - 1 : num;
// padding at end should be same as padding at start
double padding = glyph_start_x(0) - m_starting_point.x();
return glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) + padding;
}
double CalibPressureAdvancePattern::max_numbering_height() const
{
std::string::size_type most_characters = 0;
const int num_patterns = get_num_patterns();
// note: only every other number is printed
for (std::string::size_type i = 0; i < num_patterns; i += 2) {
std::string sNumber = convert_number_to_string(m_params.start + (i * m_params.step));
if (sNumber.length() > most_characters) { most_characters = sNumber.length(); }
}
most_characters = std::min(most_characters, m_max_number_len);
return (most_characters * m_digit_segment_len) + ((most_characters - 1) * m_digit_gap_len);
}
double CalibPressureAdvancePattern::pattern_shift() const { return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; }
} // namespace Slic3r

307
src/libslic3r/Calib.hpp Normal file
View file

@ -0,0 +1,307 @@
#pragma once
#include "GCodeWriter.hpp"
#include "PrintConfig.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
class GCode;
class Model;
enum class CalibMode : int {
Calib_None = 0,
Calib_PA_Line,
Calib_PA_Pattern,
Calib_PA_Tower,
Calib_Flow_Rate,
Calib_Temp_Tower,
Calib_Vol_speed_Tower,
Calib_VFA_Tower,
Calib_Retraction_tower
};
enum class CalibState {
Start = 0,
Preset,
Calibration,
CoarseSave,
FineCalibration,
Save,
Finish
};
struct Calib_Params
{
Calib_Params() : mode(CalibMode::Calib_None){}
double start, end, step;
bool print_numbers;
CalibMode mode;
};
class X1CCalibInfos
{
public:
struct X1CCalibInfo
{
int tray_id;
int bed_temp;
int nozzle_temp;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float max_volumetric_speed;
float flow_rate = 0.98f; // for flow ratio
};
std::vector<X1CCalibInfo> calib_datas;
};
class CaliPresetInfo
{
public:
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
CaliPresetInfo &operator=(const CaliPresetInfo &other)
{
this->tray_id = other.tray_id;
this->nozzle_diameter = other.nozzle_diameter;
this->filament_id = other.filament_id;
this->setting_id = other.setting_id;
this->name = other.name;
return *this;
}
};
struct PrinterCaliInfo
{
std::string dev_id;
bool cali_finished = true;
float cache_flow_ratio;
std::vector<CaliPresetInfo> selected_presets;
};
class PACalibResult
{
public:
enum CalibResult {
CALI_RESULT_SUCCESS = 0,
CALI_RESULT_PROBLEM = 1,
CALI_RESULT_FAILED = 2,
};
int tray_id;
int cali_idx = -1;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
float k_value = 0.0;
float n_coef = 0.0;
int confidence = -1; // 0: success 1: uncertain 2: failed
};
struct PACalibIndexInfo
{
int tray_id;
int cali_idx;
float nozzle_diameter;
std::string filament_id;
};
class FlowRatioCalibResult
{
public:
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float flow_ratio;
int confidence; // 0: success 1: uncertain 2: failed
};
class CalibPressureAdvance
{
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0);
protected:
CalibPressureAdvance() = default;
~CalibPressureAdvance() = default;
enum class DrawDigitMode { Left_To_Right, Bottom_To_Top };
void delta_scale_bed_ext(BoundingBoxf &bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
std::string move_to(Vec2d pt, GCodeWriter &writer, std::string comment = std::string());
double e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const;
double speed_adjust(int speed) const { return speed * 60; };
std::string convert_number_to_string(double num) const;
double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; };
std::string draw_digit(double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer);
std::string draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer);
Vec3d m_last_pos;
DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right};
const double m_digit_segment_len{2};
const double m_digit_gap_len{1};
const std::string::size_type m_max_number_len{5};
};
class CalibPressureAdvanceLine : public CalibPressureAdvance
{
public:
CalibPressureAdvanceLine(GCode *gcodegen);
~CalibPressureAdvanceLine(){};
std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50);
void set_speed(double fast = 100.0, double slow = 20.0)
{
m_slow_speed = slow;
m_fast_speed = fast;
}
const double &line_width() { return m_line_width; };
bool is_delta() const;
bool & draw_numbers() { return m_draw_numbers; }
private:
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
void delta_modify_start(double &startx, double &starty, int count);
GCode *mp_gcodegen;
double m_nozzle_diameter;
double m_slow_speed, m_fast_speed;
const double m_height_layer{0.2};
const double m_line_width{0.6};
const double m_thin_line_width{0.44};
const double m_number_line_width{0.48};
const double m_space_y{3.5};
double m_length_short{20.0}, m_length_long{40.0};
bool m_draw_numbers{true};
};
struct SuggestedConfigCalibPAPattern
{
const std::vector<std::pair<std::string, double>> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
const std::vector<std::pair<std::string, int>> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}};
const std::pair<std::string, BrimType> brim_pair{"brim_type", BrimType::btNoBrim};
};
class CalibPressureAdvancePattern : public CalibPressureAdvance
{
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
public:
CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
double handle_xy_size() const { return m_handle_xy_size; };
double handle_spacing() const { return m_handle_spacing; };
double print_size_x() const { return object_size_x() + pattern_shift(); };
double print_size_y() const { return object_size_y(); };
double max_layer_z() const { return height_first_layer() + ((m_num_layers - 1) * height_layer()); };
void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
protected:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double line_width_first_layer() const { return m_config.get_abs_value("initial_layer_line_width"); };
double line_width() const { return m_config.get_abs_value("line_width"); };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
private:
struct DrawLineOptArgs
{
DrawLineOptArgs(const CalibPressureAdvancePattern &p) : height{p.height_layer()}, line_width{p.line_width()}, speed{p.speed_adjust(p.speed_perimeter())} {};
double height;
double line_width;
double speed;
std::string comment{"Print line"};
};
struct DrawBoxOptArgs
{
DrawBoxOptArgs(const CalibPressureAdvancePattern &p)
: num_perimeters{p.wall_count()}, height{p.height_first_layer()}, line_width{p.line_width_first_layer()}, speed{p.speed_adjust(p.speed_first_layer())} {};
bool is_filled{false};
int num_perimeters;
double height;
double line_width;
double speed;
};
void refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin);
void _refresh_starting_point(const Model &model);
void _refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin);
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const { return std::ceil((m_params.end - m_params.start) / m_params.step + 1); }
std::string draw_line(Vec2d to_pt, DrawLineOptArgs opt_args);
std::string draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args);
double to_radians(double degrees) const { return degrees * M_PI / 180; };
double get_distance(Vec2d from, Vec2d to) const;
/*
from slic3r documentation: spacing = extrusion_width - layer_height * (1 - PI/4)
"spacing" = center-to-center distance of adjacent extrusions, which partially overlap
https://manual.slic3r.org/advanced/flow-math
https://ellis3dp.com/Print-Tuning-Guide/articles/misconceptions.html#two-04mm-perimeters--08mm
*/
double line_spacing() const { return line_width() - height_layer() * (1 - M_PI / 4); };
double line_spacing_first_layer() const { return line_width_first_layer() - height_first_layer() * (1 - M_PI / 4); };
double line_spacing_angle() const { return line_spacing() / std::sin(to_radians(m_corner_angle) / 2); };
double object_size_x() const;
double object_size_y() const;
double frame_size_y() const { return std::sin(to_radians(double(m_corner_angle) / 2)) * m_wall_side_length * 2; };
double glyph_start_x(int pattern_i = 0) const;
double glyph_length_x() const;
double glyph_tab_max_x() const;
double max_numbering_height() const;
double pattern_shift() const;
const Calib_Params &m_params;
DynamicPrintConfig m_config;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
const double m_handle_xy_size{5};
const double m_handle_spacing{2};
const int m_num_layers{4};
const double m_wall_side_length{30.0};
const int m_corner_angle{90};
const int m_pattern_spacing{2};
const double m_encroachment{1. / 3.};
const double m_glyph_padding_horizontal{1};
const double m_glyph_padding_vertical{1};
};
} // namespace Slic3r

View file

@ -1660,7 +1660,7 @@ public:
ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; }
bool operator< (const ConfigOptionInts& rhs) const throw() { return this->values < rhs.values; }
bool operator==(const ConfigOptionInts& rhs) const throw()
bool operator==(const ConfigOptionInts& rhs) const
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnumsGeneric: Comparing incompatible types");

View file

@ -56,8 +56,6 @@ public:
double retract_length_toolchange() const;
double retract_restart_extra_toolchange() const;
bool use_firmware_retraction() const;
private:
// Private constructor to create a key for a search in std::set.
Extruder(unsigned int id) : m_id(id) {}
@ -66,7 +64,7 @@ private:
GCodeConfig *m_config;
// Print-wide global ID of this extruder.
unsigned int m_id;
// Current state of the extruder axis, may be resetted if use_relative_e_distances.
// Current state of the extruder axis, may be resetted if use_relative_e_distance.
double m_E;
// Current state of the extruder tachometer, used to output the extruded_volume() and used_filament() statistics.
double m_absolute_E;

View file

@ -95,7 +95,7 @@ struct SurfaceFillParams
this->overlap == rhs.overlap &&
this->angle == rhs.angle &&
this->bridge == rhs.bridge &&
this->bridge_angle == rhs.bridge_angle &&
// this->bridge_angle == rhs.bridge_angle &&
this->density == rhs.density &&
// this->dont_adjust == rhs.dont_adjust &&
this->anchor_length == rhs.anchor_length &&
@ -154,42 +154,26 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
//BBS
params.with_loop = surface.surface_type == stInternalWithLoop;
if (surface.is_solid()) {
if (surface.is_solid()) {
params.density = 100.f;
//FIXME for non-thick bridges, shall we allow a bottom surface pattern?
if (surface.is_solid_infill())
params.pattern = region_config.internal_solid_infill_pattern.value;
else if (surface.is_external() && ! is_bridge) {
if(surface.is_top())
params.pattern = region_config.top_surface_pattern.value;
else
params.pattern = region_config.bottom_surface_pattern.value;
}
else {
if(region_config.top_surface_pattern == ipMonotonic || region_config.top_surface_pattern == ipMonotonicLine)
params.pattern = ipMonotonic;
else
params.pattern = ipRectilinear;
}
else if (surface.is_external() && !is_bridge)
params.pattern = surface.is_top() ? region_config.top_surface_pattern.value : region_config.bottom_surface_pattern.value;
else
params.pattern = region_config.top_surface_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
} else if (params.density <= 0)
continue;
params.extrusion_role = erInternalInfill;
if (is_bridge) {
if (surface.is_internal_bridge())
params.extrusion_role = erInternalBridgeInfill;
else
params.extrusion_role = erBridgeInfill;
} else if (surface.is_solid()) {
if (surface.is_top()) {
params.extrusion_role = erTopSolidInfill;
} else if (surface.is_bottom()) {
params.extrusion_role = erBottomSurface;
} else {
params.extrusion_role = erSolidInfill;
}
}
params.bridge_angle = float(surface.bridge_angle);
params.extrusion_role =
is_bridge ?
erBridgeInfill :
(surface.is_solid() ?
(surface.is_top() ? erTopSolidInfill : (surface.is_bottom()? erBottomSurface : erSolidInfill)) :
erInternalInfill);
params.bridge_angle = float(surface.bridge_angle);
params.angle = float(Geometry::deg2rad(region_config.infill_direction.value));
// Calculate the actual flow we'll be using for this infill.
@ -210,11 +194,11 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
// so that internall infill will be aligned over all layers of the current region.
params.spacing = layerm.region().flow(*layer.object(), frInfill, layer.object()->config().layer_height, false).spacing();
// Anchor a sparse infill to inner perimeters with the following anchor length:
params.anchor_length = float(region_config.infill_anchor);
if (region_config.infill_anchor.percent)
params.anchor_length = float(region_config.sparse_infill_anchor);
if (region_config.sparse_infill_anchor.percent)
params.anchor_length = float(params.anchor_length * 0.01 * params.spacing);
params.anchor_length_max = float(region_config.infill_anchor_max);
if (region_config.infill_anchor_max.percent)
params.anchor_length_max = float(region_config.sparse_infill_anchor_max);
if (region_config.sparse_infill_anchor_max.percent)
params.anchor_length_max = float(params.anchor_length_max * 0.01 * params.spacing);
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
}
@ -331,11 +315,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
if (internal_solid_fill == nullptr) {
// Produce another solid fill.
params.extruder = layerm.region().extruder(frSolidInfill);
const auto top_pattern = layerm.region().config().top_surface_pattern;
if(top_pattern == ipMonotonic || top_pattern == ipMonotonicLine)
params.pattern = top_pattern;
else
params.pattern = ipRectilinear;
params.pattern = layerm.region().config().top_surface_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
params.density = 100.f;
params.extrusion_role = erInternalInfill;
params.angle = float(Geometry::deg2rad(layerm.region().config().infill_direction.value));
@ -479,12 +459,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
#endif
}
LayerRegion* layerm = this->m_regions[surface_fill.region_id];
// Maximum length of the perimeter segment linking two infill lines.
f->link_max_length = (coord_t)scale_(link_max_length);
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
f->loop_clipping = coord_t(scale_(layerm->region().config().seam_gap.get_abs_value(surface_fill.params.flow.nozzle_diameter())));
f->loop_clipping = coord_t(scale_(surface_fill.params.flow.nozzle_diameter()) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
// apply half spacing using this flow's own spacing and generate infill
FillParams params;
@ -502,19 +480,14 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.using_internal_flow = using_internal_flow;
params.no_extrusion_overlap = surface_fill.params.overlap;
params.with_loop = surface_fill.params.with_loop;
params.config = &layerm->region().config();
if (surface_fill.params.pattern == ipGrid)
params.can_reverse = false;
LayerRegion* layerm = this->m_regions[surface_fill.region_id];
for (ExPolygon& expoly : surface_fill.expolygons) {
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
f->spacing = surface_fill.params.spacing;
surface_fill.surface.expolygon = std::move(expoly);
if(surface_fill.params.bridge && surface_fill.surface.is_external() && surface_fill.params.density > 99.0){
params.density = layerm->region().config().bridge_density.get_abs_value(1.0);
params.dont_adjust = true;
}
// BBS: make fill
f->fill_surface_extrusion(&surface_fill.surface,
params,

View file

@ -28,11 +28,6 @@
namespace Slic3r {
//BBS: 0% of sparse_infill_line_width, no anchor at the start of sparse infill
float Fill::infill_anchor = 400;
//BBS: 20mm
float Fill::infill_anchor_max = 20;
Fill* Fill::new_from_type(const InfillPattern type)
{
switch (type) {

View file

@ -40,7 +40,7 @@ struct FillParams
bool full_infill() const { return density > 0.9999f; }
// Don't connect the fill lines around the inner perimeter.
bool dont_connect() const { return anchor_length_max < 0.05f; }
double filter_out_gap_fill { 0.0 };
// Fill density, fraction in <0, 1>
float density { 0.f };
@ -110,9 +110,6 @@ public:
// BBS: all no overlap expolygons in same layer
ExPolygons no_overlap_expolygons;
static float infill_anchor;
static float infill_anchor_max;
public:
virtual ~Fill() {}
virtual Fill* clone() const = 0;

View file

@ -3179,6 +3179,11 @@ void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, c
}), polylines.end());
ExtrusionEntityCollection gap_fill;
// OrcaSlicer: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [&](const ThickPolyline &p) {
return p.length() < scale_(params.filter_out_gap_fill);
}), polylines.end());
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
coll_nosort->append(std::move(gap_fill.entities));

View file

@ -277,7 +277,7 @@ static constexpr const char* OBJECT_ID_ATTR = "object_id";
static constexpr const char* INSTANCEID_ATTR = "instance_id";
static constexpr const char* IDENTIFYID_ATTR = "identify_id";
static constexpr const char* PLATERID_ATTR = "plater_id";
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
static constexpr const char* PLATE_IDX_ATTR = "index";
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
static constexpr const char* SLICE_WEIGHT_ATTR = "weight";
@ -910,7 +910,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool m_load_restore = false;
std::string m_backup_path;
std::string m_origin_file;
// Semantic version of Orca Slicer, that generated this 3MF.
// Semantic version of Bambu Studio, that generated this 3MF.
boost::optional<Semver> m_bambuslicer_generator_version;
unsigned int m_fdm_supports_painting_version = 0;
unsigned int m_seam_painting_version = 0;
@ -1769,7 +1769,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
lock.close();
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by OrcaSlicer and there is more than one instance,
// if the 3mf was not produced by BambuStudio and there is more than one instance,
// split the object in as many objects as instances
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", found 3mf from other vendor, split as instance");
for (const IdToModelObjectMap::value_type& object : m_objects) {
@ -2046,7 +2046,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
plate_data_list[it->first-1]->locked = it->second->locked;
plate_data_list[it->first-1]->plate_index = it->second->plate_index-1;
plate_data_list[it->first-1]->plate_name = it->second->plate_name;
plate_data_list[it->first-1]->plate_name = it->second->plate_name;
plate_data_list[it->first-1]->obj_inst_map = it->second->obj_inst_map;
plate_data_list[it->first-1]->gcode_file = (m_load_restore || it->second->gcode_file.empty()) ? it->second->gcode_file : m_backup_path + "/" + it->second->gcode_file;
plate_data_list[it->first-1]->gcode_prediction = it->second->gcode_prediction;
@ -2616,7 +2616,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
}
}
void _BBS_3MF_Importer::_extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, ConfigSubstitutionContext& config_substitutions)
{
if (stat.m_uncomp_size > 0) {
@ -3121,7 +3121,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by OrcaSlicer and there is only one object,
// if the 3mf was not produced by BambuStudio and there is only one object,
// set the object name to match the filename
if (m_model->objects.size() == 1)
m_model->objects.front()->name = m_name;
@ -3522,23 +3522,19 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_is_bbl_3mf = true;
m_bambuslicer_generator_version = Semver::parse(m_curr_characters.substr(12));
}
else if (boost::starts_with(m_curr_characters, "OrcaSlicer-")) {
m_is_bbl_3mf = true;
m_bambuslicer_generator_version = Semver::parse(m_curr_characters.substr(11));
}
//TODO: currently use version 0, no need to load&&save this string
/*} else if (m_curr_metadata_name == BBS_FDM_SUPPORTS_PAINTING_VERSION) {
m_fdm_supports_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_fdm_supports_painting_version, FDM_SUPPORTS_PAINTING_VERSION,
_(L("The selected 3MF contains FDM supports painted object using a newer version of OrcaSlicer and is not compatible.")));
_(L("The selected 3MF contains FDM supports painted object using a newer version of BambuStudio and is not compatible.")));
} else if (m_curr_metadata_name == BBS_SEAM_PAINTING_VERSION) {
m_seam_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_seam_painting_version, SEAM_PAINTING_VERSION,
_(L("The selected 3MF contains seam painted object using a newer version of OrcaSlicer and is not compatible.")));
_(L("The selected 3MF contains seam painted object using a newer version of BambuStudio and is not compatible.")));
} else if (m_curr_metadata_name == BBS_MM_PAINTING_VERSION) {
m_mm_painting_version = (unsigned int) atoi(m_curr_characters.c_str());
check_painting_version(m_mm_painting_version, MM_PAINTING_VERSION,
_(L("The selected 3MF contains multi-material painted object using a newer version of OrcaSlicer and is not compatible.")));*/
_(L("The selected 3MF contains multi-material painted object using a newer version of BambuStudio and is not compatible.")));*/
} else if (m_curr_metadata_name == BBL_MODEL_ID_TAG) {
m_model_id = xml_unescape(m_curr_characters);
} else if (m_curr_metadata_name == BBL_MODEL_NAME_TAG) {
@ -3838,9 +3834,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
m_curr_plater->plate_index = atoi(value.c_str());
}
else if(key == PLATER_NAME_ATTR)
{
m_curr_plater->plate_name = value.c_str();
else if (key == PLATER_NAME_ATTR) {
m_curr_plater->plate_name = xml_unescape(value.c_str());
}
else if (key == LOCK_ATTR)
{
@ -4548,7 +4543,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
TriangleMesh triangle_mesh(std::move(its), volume_data.mesh_stats);
if (!m_is_bbl_3mf) {
// if the 3mf was not produced by OrcaSlicer and there is only one instance,
// if the 3mf was not produced by BambuStudio and there is only one instance,
// bake the transformation into the geometry to allow the reload from disk command
// to work properly
if (object.instances.size() == 1) {
@ -5419,7 +5414,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
// Adds content types file ("[Content_Types].xml";).
// The content of this file is the same for each OrcaSlicer 3mf.
// The content of this file is the same for each BambuStudio 3mf.
if (!_add_content_types_file_to_archive(archive)) {
return false;
}
@ -5774,7 +5769,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
// Adds relationships file ("_rels/.rels").
// The content of this file is the same for each OrcaSlicer 3mf.
// The content of this file is the same for each BambuStudio 3mf.
// The relationshis file contains a reference to the geometry file "3D/3dmodel.model", the name was chosen to be compatible with CURA.
if (!_add_relationships_file_to_archive(archive, {}, {}, {}, temp_data, export_plate_idx)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", _add_relationships_file_to_archive failed\n");
@ -5939,7 +5934,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
int i = 0;
for (auto & path : targets) {
for (auto & type : types)
stream << " <Relationship Target=\"/" << xml_escape(path) << "\" Id=\"rel-" << std::to_string(++i) << "\" Type=\"" << type << "\"/>\n";
stream << " <Relationship Target=\"/" << xml_escape(path) << "\" Id=\"rel-" << boost::to_string(++i) << "\" Type=\"" << type << "\"/>\n";
}
}
stream << "</Relationships>";
@ -6074,8 +6069,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
date = date.substr(0, 10);
metadata_item_map[BBL_CREATION_DATE_TAG] = date;
metadata_item_map[BBL_MODIFICATION_TAG] = date;
//SoftFever: write BambuStudio tag to keep it compatible
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % "BambuStudio" % SLIC3R_VERSION).str();
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % SLIC3R_APP_KEY % SLIC3R_VERSION).str();
}
metadata_item_map[BBS_3MF_VERSION] = std::to_string(VERSION_BBS_3MF);
@ -7029,7 +7023,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " <" << PLATE_TAG << ">\n";
//plate index
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATERID_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->plate_index + 1 << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATER_NAME_ATTR << "\" " << VALUE_ATTR << "=\"" << xml_escape(plate_data->plate_name) << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATER_NAME_ATTR << "\" " << VALUE_ATTR << "=\"" << xml_escape(plate_data->plate_name.c_str()) << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << LOCK_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->locked<< "\"/>\n";
ConfigOption* bed_type_opt = plate_data->config.option("curr_bed_type");
t_config_enum_names bed_type_names = ConfigOptionEnum<BedType>::get_enum_names();

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,6 @@
#include "PrintConfig.hpp"
#include "GCode/AvoidCrossingPerimeters.hpp"
#include "GCode/CoolingBuffer.hpp"
#include "GCode/FanMover.hpp"
#include "GCode/RetractWhenCrossingPerimeters.hpp"
#include "GCode/SpiralVase.hpp"
#include "GCode/ToolOrdering.hpp"
@ -20,7 +19,6 @@
#include "EdgeGrid.hpp"
#include "GCode/ThumbnailData.hpp"
#include "libslic3r/ObjectID.hpp"
#include "GCode/ExtrusionProcessor.hpp"
#include <memory>
#include <map>
@ -181,7 +179,6 @@ public:
const Point& last_pos() const { return m_last_pos; }
Vec2d point_to_gcode(const Point &point) const;
Point gcode_to_point(const Vec2d &point) const;
Vec2d point_to_gcode_quantized(const Point& point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
@ -198,19 +195,19 @@ public:
void set_layer_count(unsigned int value) { m_layer_count = value; }
void apply_print_config(const PrintConfig &print_config);
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z);
bool is_BBL_Printer();
// SoftFever
// OrcaSlicer
std::string set_object_info(Print* print);
// append full config to the given string
static void append_full_config(const Print& print, std::string& str);
// BBS: detect lift type in needs_retraction
bool needs_retraction(const Polyline &travel, ExtrusionRole role, LiftType &lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
//BBS
bool is_BBL_Printer();
// Object and support extrusions of the same PrintObject at the same print_z.
// public, so that it could be accessed by free helper functions from GCode.cpp
struct LayerToPrint
@ -335,7 +332,7 @@ private:
void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::string preamble();
// BBS
std::string change_layer(coordf_t print_z, bool lazy_raise = false);
std::string change_layer(coordf_t print_z);
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1.);
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1.);
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
@ -406,21 +403,20 @@ private:
// For sequential print, the instance of the object to be printing has to be defined.
const size_t single_object_instance_idx);
std::string extrude_perimeters(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region);
std::string extrude_infill(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection& support_fills);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
// BBS
LiftType to_lift_type(ZHopType z_hop_types);
std::string set_extruder(unsigned int extruder_id, double print_z);
std::set<ObjectID> m_objsWithBrim; // indicates the objs with brim
std::set<ObjectID> m_objSupportsWithBrim; // indicates the objs' supports with brim
// Cache for custom seam enforcers/blockers for each layer.
SeamPlacer m_seam_placer;
ExtrusionQualityEstimator m_extrusion_quality_estimator;
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude*() and travel_to()
methods. */
@ -444,13 +440,6 @@ private:
// of the G-code lines: _EXTRUDE_SET_SPEED, _WIPE, _OVERHANG_FAN_START, _OVERHANG_FAN_END
// Those comments are received and consumed (removed from the G-code) by the CoolingBuffer.pm Perl module.
bool m_enable_cooling_markers;
bool m_enable_exclude_object;
std::vector<size_t> m_label_objects_ids;
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
// Orca
bool m_is_overhang_fan_on;
bool m_is_supp_interface_fan_on;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
bool m_enable_extrusion_role_markers;
@ -469,8 +458,6 @@ private:
//double m_volumetric_speed;
// Support for the extrusion role markers. Which marker is active?
ExtrusionRole m_last_extrusion_role;
// To ignore gapfill role for retract_lift_enforce
ExtrusionRole m_last_notgapfill_extrusion_role;
// Support for G-Code Processor
float m_last_height{ 0.0f };
float m_last_layer_z{ 0.0f };
@ -498,15 +485,16 @@ private:
bool m_second_layer_things_done;
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
//BBS
bool m_enable_label_object;
std::vector<size_t> m_label_objects_ids;
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
bool m_silent_time_estimator_enabled;
// Processor
GCodeProcessor m_processor;
//some post-processing on the file, with their data class
std::unique_ptr<FanMover> m_fan_mover;
// BBS
Print* m_curr_print = nullptr;
unsigned int m_toolchange_count;
@ -523,12 +511,7 @@ private:
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
// On the first printing layer. This flag triggers first layer speeds.
//BBS
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0 && abs(m_layer->bottom_z()) < EPSILON; }
int layer_id() const {
if (m_layer == nullptr)
return -1;
return m_layer->id();
}
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0 && abs(m_layer->bottom_z()) < EPSILON; }
// To control print speed of 1st object layer over raft interface.
bool object_layer_over_raft() const { return m_object_layer_over_raft; }

View file

@ -5,7 +5,6 @@
#include <boost/log/trivial.hpp>
#include <iostream>
#include <float.h>
#include <unordered_map>
#if 0
#define DEBUG
@ -62,8 +61,7 @@ struct CoolingLine
TYPE_G2 = 1 << 12,
TYPE_G3 = 1 << 13,
TYPE_FORCE_RESUME_FAN = 1 << 14,
TYPE_SUPPORT_INTERFACE_FAN_START = 1 << 15,
TYPE_SUPPORT_INTERFACE_FAN_END = 1 << 16,
TYPE_SET_FAN_CHANGING_LAYER = 1 << 15,
};
CoolingLine(unsigned int type, size_t line_start, size_t line_end) :
@ -482,10 +480,6 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
line.type = CoolingLine::TYPE_OVERHANG_FAN_START;
} else if (boost::starts_with(sline, ";_OVERHANG_FAN_END")) {
line.type = CoolingLine::TYPE_OVERHANG_FAN_END;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_START")) {
line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_END")) {
line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END;
} else if (boost::starts_with(sline, "G4 ")) {
// Parse the wait time.
line.type = CoolingLine::TYPE_G4;
@ -497,6 +491,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
(pos_P > 0) ? atof(sline.c_str() + pos_P + 1) * 0.001 : 0.);
} else if (boost::starts_with(sline, ";_FORCE_RESUME_FAN_SPEED")) {
line.type = CoolingLine::TYPE_FORCE_RESUME_FAN;
} else if (boost::starts_with(sline, ";_SET_FAN_SPEED_CHANGING_LAYER")) {
line.type = CoolingLine::TYPE_SET_FAN_CHANGING_LAYER;
}
if (line.type != 0)
adjustment->lines.emplace_back(std::move(line));
@ -729,9 +725,14 @@ std::string CoolingBuffer::apply_layer_cooldown(
new_gcode.reserve(gcode.size() * 2);
bool overhang_fan_control= false;
int overhang_fan_speed = 0;
bool supp_interface_fan_control= false;
int supp_interface_fan_speed = 0;
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) {
enum class SetFanType {
sfChangingLayer = 0,
sfChangingFilament,
sfImmediatelyApply
};
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed](SetFanType type) {
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
int fan_min_speed = EXTRUDER_CONFIG(fan_min_speed);
int fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
@ -740,8 +741,6 @@ std::string CoolingBuffer::apply_layer_cooldown(
int close_fan_the_first_x_layers = EXTRUDER_CONFIG(close_fan_the_first_x_layers);
// Is the fan speed ramp enabled?
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
if (close_fan_the_first_x_layers <= 0 && full_fan_speed_layer > 0) {
// When ramping up fan speed from close_fan_the_first_x_layers to full_fan_speed_layer, force close_fan_the_first_x_layers above zero,
// so there will be a zero fan speed at least at the 1st layer.
@ -770,9 +769,6 @@ std::string CoolingBuffer::apply_layer_cooldown(
fan_speed_new = std::clamp(int(float(fan_speed_new) * factor + 0.5f), 0, 255);
overhang_fan_speed = std::clamp(int(float(overhang_fan_speed) * factor + 0.5f), 0, 255);
}
supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
supp_interface_fan_control = supp_interface_fan_speed >= 0;
#undef EXTRUDER_CONFIG
overhang_fan_control= overhang_fan_speed > fan_speed_new;
} else {
@ -780,34 +776,34 @@ std::string CoolingBuffer::apply_layer_cooldown(
overhang_fan_speed = 0;
fan_speed_new = 0;
additional_fan_speed_new = 0;
supp_interface_fan_control= false;
supp_interface_fan_speed = 0;
}
if (fan_speed_new != m_fan_speed) {
m_fan_speed = fan_speed_new;
//BBS
m_current_fan_speed = fan_speed_new;
if (immediately_apply)
if (type == SetFanType::sfImmediatelyApply)
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
else if (type == SetFanType::sfChangingLayer)
this->m_set_fan_changing_layer = true;
//BBS: don't need to handle change filament, because we are always force to resume fan speed when filament change is finished
}
//BBS
if (additional_fan_speed_new != m_additional_fan_speed) {
m_additional_fan_speed = additional_fan_speed_new;
if (immediately_apply && m_config.auxiliary_fan.value)
if (type == SetFanType::sfImmediatelyApply)
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
else if (type == SetFanType::sfChangingLayer)
this->m_set_addition_fan_changing_layer = true;
//BBS: don't need to handle change filament, because we are always force to resume fan speed when filament change is finished
}
};
const char *pos = gcode.c_str();
int current_feedrate = 0;
change_extruder_set_fan(true);
// Reduce set fan commands by deferring the GCodeWriter::set_fan calls. Inspired by SuperSlicer
// define fan_speed_change_requests and initialize it with all possible types fan speed change requests
std::unordered_map<int, bool> fan_speed_change_requests = {{CoolingLine::TYPE_OVERHANG_FAN_START, false},
{CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, false},
{CoolingLine::TYPE_FORCE_RESUME_FAN, false}};
bool need_set_fan = false;
//BBS
m_set_fan_changing_layer = false;
m_set_addition_fan_changing_layer = false;
change_extruder_set_fan(SetFanType::sfChangingLayer);
for (const CoolingLine *line : lines) {
const char *line_start = gcode.c_str() + line->line_start;
const char *line_end = gcode.c_str() + line->line_end;
@ -817,37 +813,37 @@ std::string CoolingBuffer::apply_layer_cooldown(
unsigned int new_extruder = (unsigned int)atoi(line_start + m_toolchange_prefix.size());
if (new_extruder != m_current_extruder) {
m_current_extruder = new_extruder;
change_extruder_set_fan(false); //BBS: will force to resume fan speed when filament change is finished
change_extruder_set_fan(SetFanType::sfChangingFilament); //BBS: will force to resume fan speed when filament change is finished
}
new_gcode.append(line_start, line_end - line_start);
} else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_START) {
if (overhang_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
need_set_fan = true;
fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = true;
}
if (overhang_fan_control) {
//BBS
m_current_fan_speed = overhang_fan_speed;
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed);
}
} else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_END) {
if (overhang_fan_control && fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = false;
if (overhang_fan_control) {
//BBS
m_current_fan_speed = m_fan_speed;
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START) {
if (supp_interface_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = true;
need_set_fan = true;
}
} else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_END && fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
if (supp_interface_fan_control) {
fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = false;
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_FORCE_RESUME_FAN) {
// check if any fan speed change request is active
if (m_fan_speed != -1 && !std::any_of(fan_speed_change_requests.begin(), fan_speed_change_requests.end(), [](const std::pair<int, bool>& p) { return p.second; })){
fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = true;
need_set_fan = true;
}
if (m_additional_fan_speed != -1 && m_config.auxiliary_fan.value)
//BBS: force to write a fan speed command again
if (m_current_fan_speed != -1)
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
if (m_additional_fan_speed != -1)
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
} else if (line->type & CoolingLine::TYPE_SET_FAN_CHANGING_LAYER) {
//BBS: check whether fan speed need to changed when change layer
if (m_current_fan_speed != -1 && m_set_fan_changing_layer) {
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
m_set_fan_changing_layer = false;
}
if (m_additional_fan_speed != -1 && m_set_addition_fan_changing_layer) {
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
m_set_addition_fan_changing_layer = false;
}
}
else if (line->type & CoolingLine::TYPE_EXTRUDE_END) {
// Just remove this comment.
@ -933,24 +929,6 @@ std::string CoolingBuffer::apply_layer_cooldown(
} else {
new_gcode.append(line_start, line_end - line_start);
}
if (need_set_fan) {
if (fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed);
m_current_fan_speed = overhang_fan_speed;
}
else if (fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, supp_interface_fan_speed);
m_current_fan_speed = supp_interface_fan_speed;
}
else if(fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] && m_current_fan_speed != -1){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_current_fan_speed);
fan_speed_change_requests[CoolingLine::TYPE_FORCE_RESUME_FAN] = false;
}
else
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
need_set_fan = false;
}
pos = line_end;
}
const char *gcode_end = gcode.c_str() + gcode.size();

View file

@ -59,6 +59,9 @@ private:
bool m_cooling_logic_proportional = false;
//BBS: current fan speed
int m_current_fan_speed;
//BBS:
bool m_set_fan_changing_layer = false;
bool m_set_addition_fan_changing_layer = false;
};
}

View file

@ -1,4 +1,3 @@
#include "ExtrusionEntity.hpp"
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Print.hpp"
@ -17,7 +16,6 @@
#include <float.h>
#include <assert.h>
#include <regex>
#if __has_include(<charconv>)
#include <charconv>
@ -62,23 +60,6 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER"
};
const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
"TYPE:",
"WIPE_START",
"WIPE_END",
"HEIGHT:",
"WIDTH:",
"LAYER_CHANGE",
"COLOR_CHANGE",
"PAUSE_PRINT",
"CUSTOM_GCODE",
"_GP_FIRST_LINE_M73_PLACEHOLDER",
"_GP_LAST_LINE_M73_PLACEHOLDER",
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER",
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER"
};
const std::string GCodeProcessor::Flush_Start_Tag = " FLUSH_START";
const std::string GCodeProcessor::Flush_End_Tag = " FLUSH_END";
@ -92,8 +73,6 @@ const std::map<NozzleType,int> GCodeProcessor::Nozzle_Type_To_HRC={
const float GCodeProcessor::Wipe_Width = 0.05f;
const float GCodeProcessor::Wipe_Height = 0.05f;
bool GCodeProcessor::s_IsBBLPrinter = true;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
const std::string GCodeProcessor::Mm3_Per_Mm_Tag = "MM3_PER_MM:";
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -122,16 +101,16 @@ static float intersection_distance(float initial_rate, float final_rate, float a
static float speed_from_distance(float initial_feedrate, float distance, float acceleration)
{
// to avoid invalid negative numbers due to numerical errors
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(initial_feedrate) + 2.0f * acceleration * distance);
return ::sqrt(value);
}
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// acceleration within the allotted distance.
static float max_allowable_speed(float acceleration, float target_velocity, float distance)
{
// to avoid invalid negative numbers due to numerical errors
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(target_velocity) - 2.0f * acceleration * distance);
return std::sqrt(value);
}
@ -182,7 +161,7 @@ void GCodeProcessor::TimeBlock::calculate_trapezoid()
float cruise_distance = distance - accelerate_distance - decelerate_distance;
// Not enough space to reach the nominal feedrate.
// This means no cruising, and we'll have to use intersection_distance() to calculate when to abort acceleration
// This means no cruising, and we'll have to use intersection_distance() to calculate when to abort acceleration
// and start braking in order to reach the exit_feedrate exactly at the end of this block.
if (cruise_distance < 0.0f) {
accelerate_distance = std::clamp(intersection_distance(feedrate_profile.entry, feedrate_profile.exit, acceleration, distance), 0.0f, distance);
@ -491,17 +470,12 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
char buf[128];
if(!s_IsBBLPrinter)
// SoftFever: compatibility with klipper_estimator
sprintf(buf, "; estimated printing time (normal mode) = %s\n", get_time_dhms(machine.time).c_str());
else {
//sprintf(buf, "; estimated printing time (%s mode) = %s\n",
// (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
// get_time_dhms(machine.time).c_str());
sprintf(buf, "; model printing time: %s; total estimated time: %s\n",
get_time_dhms(machine.time - machine.prepare_time).c_str(),
get_time_dhms(machine.time).c_str());
}
ret += buf;
}
}
@ -662,7 +636,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
if (processed && lines_added_count > 0)
offsets.push_back({ line_id, lines_added_count });
if (! processed && ! is_temporary_decoration(gcode_line) &&
(GCodeReader::GCodeLine::cmd_is(gcode_line, "G1") ||
(GCodeReader::GCodeLine::cmd_is(gcode_line, "G1") ||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G2") ||
GCodeReader::GCodeLine::cmd_is(gcode_line, "G3"))) {
// remove temporary lines, add lines M73 where needed
@ -677,7 +651,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
gcode_line.clear();
}
// Skip EOL.
it = it_end;
it = it_end;
if (it != it_bufend && *it == '\r')
++ it;
if (it != it_bufend && *it == '\n')
@ -848,12 +822,10 @@ void GCodeProcessorResult::reset() {
#endif // ENABLE_GCODE_VIEWER_STATISTICS
const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProcessor::Producers = {
//BBS: OrcaSlicer is also "bambu". Otherwise the time estimation didn't work.
//BBS: BambuStudio is also "bambu". Otherwise the time estimation didn't work.
//FIXME: Workaround and should be handled when do removing-bambu
{ EProducer::OrcaSlicer, SLIC3R_APP_NAME },
{ EProducer::OrcaSlicer, "generated by OrcaSlicer" },
{ EProducer::OrcaSlicer, "generated by BambuStudio" },
{ EProducer::OrcaSlicer, "BambuStudio" }
{ EProducer::BambuStudio, SLIC3R_APP_NAME },
{ EProducer::BambuStudio, "generated by BambuStudio" }
//{ EProducer::Slic3rPE, "generated by Slic3r Bambu Edition" },
//{ EProducer::Slic3r, "generated by Slic3r" },
//{ EProducer::SuperSlicer, "generated by SuperSlicer" },
@ -871,12 +843,11 @@ bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string
bool ret = false;
GCodeReader parser;
auto& _tags = s_IsBBLPrinter ? Reserved_Tags : Reserved_Tags_compatible;
parser.parse_buffer(gcode, [&ret, &found_tag, _tags](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
parser.parse_buffer(gcode, [&ret, &found_tag](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
std::string comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1);
for (const std::string& s : _tags) {
for (const std::string& s : Reserved_Tags) {
if (boost::starts_with(comment, s)) {
ret = true;
found_tag = comment;
@ -899,12 +870,11 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i
CNumericLocalesSetter locales_setter;
GCodeReader parser;
auto& _tags = s_IsBBLPrinter ? Reserved_Tags : Reserved_Tags_compatible;
parser.parse_buffer(gcode, [&ret, &found_tag, max_count, _tags](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
parser.parse_buffer(gcode, [&ret, &found_tag, max_count](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
std::string comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
comment = comment.substr(1);
for (const std::string& s : _tags) {
for (const std::string& s : Reserved_Tags) {
if (boost::starts_with(comment, s)) {
ret = true;
found_tag.push_back(comment);
@ -947,7 +917,6 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_densities.resize(extruders_count);
m_result.filament_vitrification_temperature.resize(extruders_count);
m_extruder_temps.resize(extruders_count);
m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt());
m_result.nozzle_type = config.nozzle_type;
for (size_t i = 0; i < extruders_count; ++ i) {
m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f);
@ -958,17 +927,12 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_vitrification_temperature[i] = static_cast<float>(config.temperature_vitrification.get_at(i));
}
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper || m_flavor == gcfRepRapFirmware) {
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper) {
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
if (m_flavor == gcfMarlinLegacy) {
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
m_time_processor.machine_limits.machine_max_acceleration_travel = m_time_processor.machine_limits.machine_max_acceleration_extruding;
}
if (m_flavor == gcfRepRapFirmware) {
// RRF does not support setting min feedrates. Set them to zero.
m_time_processor.machine_limits.machine_min_travel_rate.values.assign(m_time_processor.machine_limits.machine_min_travel_rate.size(), 0.);
m_time_processor.machine_limits.machine_min_extruding_rate.values.assign(m_time_processor.machine_limits.machine_min_extruding_rate.size(), 0.);
}
}
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
@ -1009,9 +973,6 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (nozzle_volume != nullptr)
m_nozzle_volume = nozzle_volume->value;
const ConfigOptionInt *nozzle_HRC = config.option<ConfigOptionInt>("nozzle_hrc");
if (nozzle_HRC != nullptr) m_result.nozzle_hrc = nozzle_HRC->value;
const ConfigOptionEnum<NozzleType>* nozzle_type = config.option<ConfigOptionEnum<NozzleType>>("nozzle_type");
if (nozzle_type != nullptr)
m_result.nozzle_type=nozzle_type->value;
@ -1119,7 +1080,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
}
}
if (m_extruder_offsets.size() < m_result.extruders_count) {
for (size_t i = m_extruder_offsets.size(); i < m_result.extruders_count; ++i) {
m_extruder_offsets.emplace_back(DEFAULT_EXTRUDER_OFFSET);
@ -1394,12 +1355,12 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
});
m_parser.reset();
// if the gcode was produced by OrcaSlicer,
// if the gcode was produced by BambuStudio,
// extract the config from it
if (m_producer == EProducer::OrcaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
if (m_producer == EProducer::BambuStudio || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
DynamicPrintConfig config;
config.apply(FullPrintConfig::defaults());
// Silently substitute unknown values by new ones for loading configurations from OrcaSlicer's own G-code.
// Silently substitute unknown values by new ones for loading configurations from BambuStudio's own G-code.
// Showing substitution log or errors may make sense, but we are not really reading many values from the G-code config,
// thus a probability of incorrect substitution is low and the G-code viewer is a consumer-only anyways.
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
@ -1449,7 +1410,7 @@ void GCodeProcessor::initialize(const std::string& filename)
void GCodeProcessor::process_buffer(const std::string &buffer)
{
//FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations.
m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
this->process_gcode_line(line, false);
});
}
@ -1491,7 +1452,7 @@ void GCodeProcessor::finalize(bool post_process)
else
m_result.moves[i].layer_duration = 0;
}
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
std::cout << "\n";
m_mm3_per_mm_compare.output();
@ -1647,7 +1608,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename)
}
return false;
};
begin = skip_whitespaces(begin, end);
end = remove_eols(begin, end);
if (begin != end) {
@ -1705,6 +1666,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
m_start_position = m_end_position;
const std::string_view cmd = line.cmd();
//OrcaSlicer
if (m_flavor == gcfKlipper)
{
if (boost::iequals(cmd, "SET_VELOCITY_LIMIT"))
@ -1728,7 +1690,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
case '2':
case '3': { process_G2_G3(line); break; } // Move
//BBS
case 4: { process_G4(line); break; } // Delay
case '4': { process_G4(line); break; } // Delay
default: break;
}
break;
@ -1928,7 +1890,7 @@ template<typename T>
auto str_end = sv.data() + sv.size();
auto [end_ptr, error_code] = std::from_chars(sv.data(), str_end, out);
return error_code == std::errc() && end_ptr == str_end;
}
}
else
#endif
{
@ -2081,7 +2043,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
return;
}
if (!producers_enabled || m_producer == EProducer::OrcaSlicer) {
if (!producers_enabled || m_producer == EProducer::BambuStudio) {
// height tag
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
@ -2219,9 +2181,9 @@ bool GCodeProcessor::process_producers_tags(const std::string_view comment)
switch (m_producer)
{
case EProducer::Slic3rPE:
case EProducer::Slic3r:
case EProducer::Slic3r:
case EProducer::SuperSlicer:
case EProducer::OrcaSlicer: { return process_bambuslicer_tags(comment); }
case EProducer::BambuStudio: { return process_bambuslicer_tags(comment); }
case EProducer::Cura: { return process_cura_tags(comment); }
case EProducer::Simplify3D: { return process_simplify3d_tags(comment); }
case EProducer::CraftWare: { return process_craftware_tags(comment); }
@ -2326,7 +2288,7 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
set_extrusion_role(erSkirt);
return true;
}
// ; outer perimeter
pos = cmt.find(" outer perimeter");
if (pos == 0) {
@ -2370,13 +2332,6 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
return true;
}
// ; internal bridge
pos = cmt.find(" internal bridge");
if (pos == 0) {
set_extrusion_role(erInternalBridgeInfill);
return true;
}
// ; support
pos = cmt.find(" support");
if (pos == 0) {
@ -2528,8 +2483,6 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string_view comment)
set_extrusion_role(erInternalInfill);
else if (type == "BRIDGE")
set_extrusion_role(erBridgeInfill);
else if (type == "INTERNAL BRIDGE")
set_extrusion_role(erInternalBridgeInfill);
else if (type == "SUPPORT")
set_extrusion_role(erSupportMaterial);
else {
@ -2729,7 +2682,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
type = (delta_pos[Z] == 0.0f) ? EMoveType::Unretract : EMoveType::Travel;
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f)
type = EMoveType::Extrude;
}
}
else if (delta_pos[X] != 0.0f || delta_pos[Y] != 0.0f || delta_pos[Z] != 0.0f)
type = EMoveType::Travel;
@ -2802,7 +2755,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
else if (m_extrusion_role == erExternalPerimeter)
// cross section: rectangle
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erInternalBridgeInfill || m_extrusion_role == erNone)
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone)
// cross section: circle
m_width = static_cast<float>(m_result.filament_diameters[m_extruder_id]) * std::sqrt(delta_pos[E] / delta_xyz);
else
@ -2927,7 +2880,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// calculates block acceleration
float acceleration =
float acceleration =
(type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
(is_extrusion_only_move(delta_pos) ?
get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
@ -3259,7 +3212,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
else if (m_extrusion_role == erExternalPerimeter)
//BBS: cross section: rectangle
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erInternalBridgeInfill || m_extrusion_role == erNone)
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone)
//BBS: cross section: circle
m_width = static_cast<float>(m_result.filament_diameters[m_extruder_id]) * std::sqrt(delta_pos[E] / delta_xyz);
else
@ -3402,7 +3355,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
}
else if (a == Y || a == Z) {
continue;
}
}
else {
float v_exit = prev.axis_feedrate[a];
float v_entry = curr.axis_feedrate[a];
@ -3625,7 +3578,7 @@ void GCodeProcessor::process_G92(const GCodeReader::GCodeLine& line)
simulate_st_synchronize();
if (!any_found && !line.has_unknown_axis()) {
// The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
// The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
// where G92 A0 B0 is called although the extruder axis is till E.
for (unsigned char a = X; a <= E; ++a) {
m_origin[a] = m_end_position[a];
@ -3873,7 +3826,7 @@ void GCodeProcessor::process_SET_VELOCITY_LIMIT(const GCodeReader::GCodeLine& li
{
_jerk = std::stof(matches[1]);
}
catch (...){}
catch (...) {}
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, _jerk);
set_option_value(m_time_processor.machine_limits.machine_max_jerk_y, i, _jerk);
@ -3903,8 +3856,8 @@ void GCodeProcessor::process_SET_VELOCITY_LIMIT(const GCodeReader::GCodeLine& li
}
catch (...) {}
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
set_option_value(m_time_processor.machine_limits.machine_max_speed_x, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_y, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_x, i, _speed);
set_option_value(m_time_processor.machine_limits.machine_max_speed_y, i, _speed);
}
}
@ -4336,9 +4289,7 @@ void GCodeProcessor::update_slice_warnings()
warning.params.clear();
warning.level=1;
int nozzle_hrc = m_result.nozzle_hrc;
if(nozzle_hrc <= 0)
nozzle_hrc = Nozzle_Type_To_HRC.find(m_result.nozzle_type)->second;
int nozzle_hrc = Nozzle_Type_To_HRC.find(m_result.nozzle_type)->second;
if (nozzle_hrc!=0) {
for (size_t i = 0; i < used_extruders.size(); i++) {
int HRC=0;
@ -4359,3 +4310,4 @@ void GCodeProcessor::update_slice_warnings()
}
} /* namespace Slic3r */

View file

@ -97,11 +97,11 @@ namespace Slic3r {
{
std::string _objName1;
std::string _objName2;
double _height;
float _height;
const void *_obj1; // nullptr means wipe tower
const void *_obj2;
int layer = -1;
ConflictResult(const std::string &objName1, const std::string &objName2, double height, const void *obj1, const void *obj2)
ConflictResult(const std::string &objName1, const std::string &objName2, float height, const void *obj1, const void *obj2)
: _objName1(objName1), _objName2(objName2), _height(height), _obj1(obj1), _obj2(obj2)
{}
ConflictResult() = default;
@ -192,7 +192,6 @@ namespace Slic3r {
std::vector<std::pair<float, std::pair<size_t, size_t>>> spiral_vase_layers;
//BBS
std::vector<SliceWarning> warnings;
int nozzle_hrc;
NozzleType nozzle_type;
BedType bed_type = BedType::btCount;
#if ENABLE_GCODE_VIEWER_STATISTICS
@ -236,7 +235,6 @@ namespace Slic3r {
class GCodeProcessor
{
static const std::vector<std::string> Reserved_Tags;
static const std::vector<std::string> Reserved_Tags_compatible;
static const std::string Flush_Start_Tag;
static const std::string Flush_End_Tag;
static const std::map<NozzleType, int>Nozzle_Type_To_HRC;
@ -258,8 +256,8 @@ namespace Slic3r {
Total_Layer_Number_Placeholder
};
static const std::string& reserved_tag(ETags tag) { return s_IsBBLPrinter ? Reserved_Tags[static_cast<unsigned char>(tag)] : Reserved_Tags_compatible[static_cast<unsigned char>(tag)]; }
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
static const std::string& reserved_tag(ETags tag) { return Reserved_Tags[static_cast<unsigned char>(tag)]; }
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
static bool contains_reserved_tag(const std::string& gcode, std::string& found_tag);
// checks the given gcode for reserved tags and returns true when finding any
// (the first max_count found tags are returned into found_tag)
@ -271,8 +269,6 @@ namespace Slic3r {
static const float Wipe_Width;
static const float Wipe_Height;
static bool s_IsBBLPrinter;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
static const std::string Mm3_Per_Mm_Tag;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -369,7 +365,7 @@ namespace Slic3r {
AxisCoords axis_feedrate; // mm/s
AxisCoords abs_axis_feedrate; // mm/s
//BBS: unit vector of enter speed and exit speed in x-y-z space.
//BBS: unit vector of enter speed and exit speed in x-y-z space.
//For line move, there are same. For arc move, there are different.
Vec3f enter_direction;
Vec3f exit_direction;
@ -673,7 +669,7 @@ namespace Slic3r {
enum class EProducer
{
Unknown,
OrcaSlicer,
BambuStudio,
Slic3rPE,
Slic3r,
SuperSlicer,

View file

@ -128,9 +128,9 @@ public:
}
WipeTowerWriter& disable_linear_advance() {
if(m_gcode_flavor == gcfKlipper)
if (m_gcode_flavor == gcfKlipper)
m_gcode += "SET_PRESSURE_ADVANCE ADVANCE=0\n";
else if(m_gcode_flavor == gcfRepRapFirmware)
else if (m_gcode_flavor == gcfRepRapFirmware)
m_gcode += std::string("M572 D") + std::to_string(m_current_tool) + " S0\n";
else
m_gcode += "M900 K0\n";

View file

@ -15,21 +15,18 @@
namespace Slic3r {
bool GCodeWriter::full_gcode_comment = true;
const bool GCodeWriter::full_gcode_comment = false;
const double GCodeWriter::slope_threshold = 3 * PI / 180;
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
{
this->config.apply(print_config, true);
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
bool use_mach_limits = print_config.gcode_flavor.value == gcfMarlinLegacy ||
print_config.gcode_flavor.value == gcfMarlinFirmware ||
print_config.gcode_flavor.value == gcfKlipper ||
print_config.gcode_flavor.value == gcfRepRapFirmware;
m_max_acceleration = std::lrint(use_mach_limits ? print_config.machine_max_acceleration_extruding.values.front() : 0);
m_max_jerk = std::lrint(use_mach_limits ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
m_max_jerk_z = print_config.machine_max_jerk_z.values.front();
m_max_jerk_e = print_config.machine_max_jerk_e.values.front();
bool is_marlin = print_config.gcode_flavor.value == gcfMarlinLegacy
|| print_config.gcode_flavor.value == gcfMarlinFirmware
|| print_config.gcode_flavor.value == gcfKlipper;
m_max_acceleration = std::lrint(is_marlin ? print_config.machine_max_acceleration_extruding.values.front() : 0);
m_max_jerk = std::lrint(is_marlin ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
}
void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
@ -176,16 +173,15 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
// This is new MarlinFirmware with separated print/retraction/travel acceleration.
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
gcode << "M204 P" << acceleration;
} else if (FLAVOR_IS(gcfKlipper)) {
gcode << "SET_VELOCITY_LIMIT ACCEL=" << acceleration;
if (this->config.accel_to_decel_enable) {
gcode << " ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
if (GCodeWriter::full_gcode_comment)
gcode << " ; adjust ACCEL_TO_DECEL";
}
} else
} else if (FLAVOR_IS(gcfKlipper) && this->config.accel_to_decel_enable) {
gcode << "SET_VELOCITY_LIMIT ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust ACCEL_TO_DECEL";
gcode << "\nM204 S" << acceleration;
// Set max accel to decel to half of acceleration
} else {
// M204: Set default acceleration
gcode << "M204 S" << acceleration;
}
//BBS
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust acceleration";
gcode << "\n";
@ -193,55 +189,45 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
return gcode.str();
}
std::string GCodeWriter::set_pressure_advance(double pa) const
{
std::ostringstream gcode;
if (pa < 0) return gcode.str();
if (false) { // todo: bbl printer
// OrcaSlicer: set L1000 to use linear model
gcode << "M900 K" << std::setprecision(4) << pa << " L1000 M10 ; Override pressure advance value\n";
} else {
if (this->config.gcode_flavor == gcfKlipper)
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
else if (this->config.gcode_flavor == gcfRepRapFirmware)
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
else
gcode << "M900 K" << std::setprecision(4) << pa << "; Override pressure advance value\n";
}
return gcode.str();
}
std::string GCodeWriter::set_jerk_xy(double jerk)
{
// Clamp the jerk to the allowed maximum.
if (m_max_jerk > 0 && jerk > m_max_jerk)
jerk = m_max_jerk;
if (m_max_jerk > 0 && jerk > m_max_jerk) jerk = m_max_jerk;
if (jerk < 0.01 || is_approx(jerk, m_last_jerk)) return std::string();
if (jerk < 0.01 || is_approx(jerk, m_last_jerk))
return std::string();
m_last_jerk = jerk;
std::ostringstream gcode;
if(FLAVOR_IS(gcfKlipper))
if (FLAVOR_IS(gcfKlipper))
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
else
gcode << "M205 X" << jerk << " Y" << jerk;
if (m_is_bbl_printers)
gcode << std::setprecision(2) << " Z" << m_max_jerk_z << " E" << m_max_jerk_e;
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust jerk";
gcode << "\n";
return gcode.str();
}
std::string GCodeWriter::set_pressure_advance(double pa) const
{
std::ostringstream gcode;
if (pa < 0)
return gcode.str();
if(m_is_bbl_printers){
//SoftFever: set L1000 to use linear model
gcode << "M900 K" <<std::setprecision(4)<< pa << " L1000 M10 ; Override pressure advance value\n";
}
else{
if (FLAVOR_IS(gcfKlipper))
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
else if(FLAVOR_IS(gcfRepRapFirmware))
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
else
gcode << "M900 K" <<std::setprecision(4)<< pa << "; Override pressure advance value\n";
}
return gcode.str();
}
std::string GCodeWriter::reset_e(bool force)
{
if (FLAVOR_IS(gcfMach3)
@ -255,7 +241,7 @@ std::string GCodeWriter::reset_e(bool force)
m_extruder->reset_E();
}
if (! this->config.use_relative_e_distances) {
if (!this->config.use_relative_e_distances) {
std::ostringstream gcode;
gcode << "G92 E0";
//BBS
@ -310,12 +296,11 @@ std::string GCodeWriter::toolchange(unsigned int extruder_id)
return gcode.str();
}
std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker)
std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker) const
{
assert(F > 0.);
assert(F < 100000.);
m_current_speed = F;
GCodeG1Formatter w;
w.emit_f(F);
//BBS
@ -335,9 +320,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
GCodeG1Formatter w;
w.emit_xy(point_on_plate);
auto speed = m_is_first_layer
? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
w.emit_f(speed * 60.0);
w.emit_f(this->config.travel_speed.value * 60.0);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
return w.string();
@ -356,8 +339,6 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
used for unlift. */
// BBS
Vec3d dest_point = point;
auto travel_speed =
m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
//BBS: a z_hop need to be handle when travel
if (std::abs(m_to_lift) > EPSILON) {
assert(std::abs(m_lifted) < EPSILON);
@ -399,9 +380,9 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
Vec3d slope_top_point = Vec3d(temp(0), temp(1), delta(2)) + source;
GCodeG1Formatter w0;
w0.emit_xyz(slope_top_point);
w0.emit_f(travel_speed * 60.0);
w0.emit_f(this->config.travel_speed.value * 60.0);
//BBS
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
w0.emit_comment(GCodeWriter::full_gcode_comment, "slope lift Z");
slop_move = w0.string();
}
else if (m_to_lift_type == LiftType::NormalLift) {
@ -414,13 +395,13 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
GCodeG1Formatter w0;
if (this->is_current_position_clear()) {
w0.emit_xyz(target);
w0.emit_f(travel_speed * 60.0);
w0.emit_f(this->config.travel_speed.value * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
xy_z_move = w0.string();
}
else {
w0.emit_xy(Vec2d(target.x(), target.y()));
w0.emit_f(travel_speed * 60.0);
w0.emit_f(this->config.travel_speed.value * 60.0);
w0.emit_comment(GCodeWriter::full_gcode_comment, comment);
xy_z_move = w0.string() + _travel_to_z(target.z(), comment);
}
@ -494,10 +475,8 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
}
if (speed == 0.)
speed = this->config.travel_speed.value;
GCodeG1Formatter w;
w.emit_z(z);
@ -512,10 +491,8 @@ std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, c
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
}
if (speed == 0.)
speed = this->config.travel_speed.value;
std::string output = "G17\n";
GCodeG2G3Formatter w(true);
@ -548,9 +525,6 @@ std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std:
{
m_pos(0) = point(0);
m_pos(1) = point(1);
if(std::abs(dE) <= std::numeric_limits<double>::epsilon())
force_no_extrusion = true;
if (!force_no_extrusion)
m_extruder->extrude(dE);
@ -631,26 +605,15 @@ std::string GCodeWriter::retract_for_toolchange(bool before_wipe)
std::string GCodeWriter::_retract(double length, double restart_extra, const std::string &comment)
{
/* If firmware retraction is enabled, we use a fake value of 1
since we ignore the actual configured retract_length which
might be 0, in which case the retraction logic gets skipped. */
if (this->config.use_firmware_retraction)
length = 1;
std::string gcode;
if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
if (this->config.use_firmware_retraction) {
gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
}
else {
// BBS
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->retract_speed() * 60.);
// BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
gcode = w.string();
}
//BBS
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->retract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
gcode = w.string();
}
if (FLAVOR_IS(gcfMakerWare))
@ -667,20 +630,14 @@ std::string GCodeWriter::unretract()
gcode = "M101 ; extruder on\n";
if (double dE = m_extruder->unretract(); dE != 0) {
if (this->config.use_firmware_retraction) {
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
gcode += this->reset_e();
}
else {
//BBS
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->deretract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, " ; unretract");
gcode += w.string();
}
//BBS
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
GCodeG1Formatter w;
w.emit_e(m_extruder->E());
w.emit_f(m_extruder->deretract_speed() * 60.);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, " ; unretract");
gcode += w.string();
}
return gcode;
@ -694,10 +651,8 @@ std::string GCodeWriter::lift(LiftType lift_type, bool spiral_vase)
// check whether the above/below conditions are met
double target_lift = 0;
{
double above = this->config.retract_lift_above.get_at(m_extruder->id());
double below = this->config.retract_lift_below.get_at(m_extruder->id());
if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below))
target_lift = this->config.z_hop.get_at(m_extruder->id());
//BBS
target_lift = this->config.z_hop.get_at(m_extruder->id());
}
// BBS
if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) {
@ -747,9 +702,9 @@ std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, unsigned int sp
gcode << "M126"; break;
case gcfMach3:
case gcfMachinekit:
gcode << "M106 P" << static_cast<unsigned int>(255.5 * speed / 100.0); break;
gcode << "M106 P" << 255.0 * speed / 100.0; break;
default:
gcode << "M106 S" << static_cast<unsigned int>(255.5 * speed / 100.0); break;
gcode << "M106 S" << 255.0 * speed / 100.0; break;
}
if (GCodeWriter::full_gcode_comment)
gcode << " ; enable fan";
@ -793,11 +748,6 @@ void GCodeWriter::add_object_end_labels(std::string& gcode)
if (!m_gcode_label_objects_end.empty()) {
gcode += m_gcode_label_objects_end;
m_gcode_label_objects_end = "";
// Orca: reset E so that e value remain correct after skipping the object
// ref to: https://github.com/SoftFever/OrcaSlicer/pull/205/commits/7f1fe0bd544077626080aa1a9a0576aa735da1a4#r1083470162
if (!this->config.use_relative_e_distances)
gcode += reset_e(true);
}
}

View file

@ -11,6 +11,12 @@
namespace Slic3r {
enum class LiftType {
NormalLift,
LazyLift,
SpiralLift
};
class GCodeWriter {
public:
GCodeConfig config;
@ -24,8 +30,7 @@ public:
/*m_last_bed_temperature(0), */m_last_bed_temperature_reached(true),
m_lifted(0),
m_to_lift(0),
m_to_lift_type(LiftType::NormalLift),
m_current_speed(3600), m_is_first_layer(true)
m_to_lift_type(LiftType::NormalLift)
{}
Extruder* extruder() { return m_extruder; }
const Extruder* extruder() const { return m_extruder; }
@ -46,8 +51,8 @@ public:
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
std::string set_bed_temperature(int temperature, bool wait = false);
std::string set_acceleration(unsigned int acceleration);
std::string set_jerk_xy(double jerk);
std::string set_pressure_advance(double pa) const;
std::string set_jerk_xy(double jerk);
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
// return false if this extruder was already selected
@ -59,9 +64,7 @@ public:
// printed with the same extruder.
std::string toolchange_prefix() const;
std::string toolchange(unsigned int extruder_id);
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string());
// SoftFever NOTE: the returned speed is mm/minute
double get_current_speed() const { return m_current_speed;}
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const;
std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string());
std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string());
std::string travel_to_z(double z, const std::string &comment = std::string());
@ -90,26 +93,22 @@ public:
static std::string set_additional_fan(unsigned int speed);
//BBS
void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; }
bool is_object_start_str_empty() { return m_gcode_label_objects_start.empty(); }
bool empty_object_start_str() { return m_gcode_label_objects_start.empty(); }
void set_object_end_str(std::string end_string) { m_gcode_label_objects_end = end_string; }
bool is_object_end_str_empty() { return m_gcode_label_objects_end.empty(); }
void add_object_start_labels(std::string &gcode);
void add_object_end_labels(std::string &gcode);
bool empty_object_end_str() { return m_gcode_label_objects_end.empty(); }
void add_object_start_labels(std::string& gcode);
void add_object_end_labels(std::string& gcode);
void add_object_change_labels(std::string& gcode);
//BBS:
void set_current_position_clear(bool clear) { m_is_current_pos_clear = clear; };
bool is_current_position_clear() const { return m_is_current_pos_clear; };
//BBS:
static bool full_gcode_comment;
static const bool full_gcode_comment;
//Radian threshold of slope for lazy lift and spiral lift;
static const double slope_threshold;
//SoftFever
void set_is_bbl_machine(bool bval) {m_is_bbl_printers = bval;}
const bool is_bbl_printers() const {return m_is_bbl_printers;}
void set_is_first_layer(bool bval) { m_is_first_layer = bval; }
private:
private:
// Extruders are sorted by their ID, so that binary search is possible.
std::vector<Extruder> m_extruders;
bool m_single_extruder_multi_material;
@ -118,15 +117,8 @@ public:
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
// If set to zero, the limit is not in action.
unsigned int m_max_acceleration;
double m_max_jerk;
double m_last_jerk;
double m_max_jerk_z;
double m_max_jerk_e;
unsigned int m_travel_acceleration;
unsigned int m_travel_jerk;
double m_max_jerk;
//BBS
unsigned int m_last_additional_fan_speed;
int m_last_bed_temperature;
@ -144,15 +136,10 @@ public:
//BBS: x, y offset for gcode generated
double m_x_offset{ 0 };
double m_y_offset{ 0 };
std::string m_gcode_label_objects_start;
std::string m_gcode_label_objects_end;
//SoftFever
bool m_is_bbl_printers = false;
double m_current_speed;
bool m_is_first_layer = true;
std::string _travel_to_z(double z, const std::string &comment);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment);
@ -184,13 +171,6 @@ public:
// static constexpr const int XYZF_EXPORT_DIGITS = 6;
// static constexpr const int E_EXPORT_DIGITS = 9;
#endif
static constexpr const std::array<double, 10> pow_10 { 1., 10., 100., 1000., 10000., 100000., 1000000., 10000000., 100000000., 1000000000. };
static constexpr const std::array<double, 10> pow_10_inv { 1. / 1., 1. / 10., 1. / 100., 1. / 1000., 1. / 10000., 1. / 100000., 1. / 1000000., 1. / 10000000., 1. / 100000000., 1. / 1000000000. };
// Quantize doubles to a resolution of the G-code.
static double quantize(double v, size_t ndigits) { return std::round(v * pow_10[ndigits]) * pow_10_inv[ndigits]; }
static double quantize_xyzf(double v) { return quantize(v, XYZF_EXPORT_DIGITS); }
static double quantize_e(double v) { return quantize(v, E_EXPORT_DIGITS); }
void emit_axis(const char axis, const double v, size_t digits);

View file

@ -3,6 +3,12 @@
#include <string>
#ifdef SLIC3R_CURRENTLY_COMPILING_GUI_MODULE
#ifndef SLIC3R_ALLOW_LIBSLIC3R_I18N_IN_SLIC3R
#error You included libslic3r/I18N.hpp into a file belonging to slic3r module.
#endif
#endif
namespace Slic3r {
namespace I18N {
@ -15,4 +21,17 @@ namespace I18N {
} // namespace Slic3r
// When this is included from slic3r, better do not define the translation functions.
// Macros from slic3r/GUI/I18N.hpp should be used there.
#ifndef SLIC3R_CURRENTLY_COMPILING_GUI_MODULE
#ifdef L
#error L macro is defined where it shouldn't be. Didn't you include slic3r/GUI/I18N.hpp in libslic3r by mistake?
#endif
namespace {
[[maybe_unused]] const char* L(const char* s) { return s; }
[[maybe_unused]] const char* L_CONTEXT(const char* s, const char* context) { return s; }
[[maybe_unused]] std::string _u8L(const char* s) { return Slic3r::I18N::translate(s); }
}
#endif
#endif /* slic3r_I18N_hpp_ */

View file

@ -174,6 +174,7 @@ void Layer::make_perimeters()
&& config.gap_infill_speed.value == other_config.gap_infill_speed.value
&& config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value
&& config.detect_overhang_wall == other_config.detect_overhang_wall
&& config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value
&& config.opt_serialize("inner_wall_line_width") == other_config.opt_serialize("inner_wall_line_width")
&& config.opt_serialize("outer_wall_line_width") == other_config.opt_serialize("outer_wall_line_width")
&& config.detect_thin_wall == other_config.detect_thin_wall

View file

@ -71,12 +71,9 @@ Model& Model::assign_copy(const Model &rhs)
// BBS
this->plates_custom_gcodes = rhs.plates_custom_gcodes;
this->curr_plate_index = rhs.curr_plate_index;
this->calib_pa_pattern.reset();
if (rhs.calib_pa_pattern) {
this->calib_pa_pattern = std::make_unique<CalibPressureAdvancePattern>(
CalibPressureAdvancePattern(*rhs.calib_pa_pattern)
);
this->calib_pa_pattern = std::make_unique<CalibPressureAdvancePattern>(CalibPressureAdvancePattern(*rhs.calib_pa_pattern));
}
// BBS: for design info
@ -107,8 +104,7 @@ Model& Model::assign_copy(Model &&rhs)
// BBS
this->plates_custom_gcodes = std::move(rhs.plates_custom_gcodes);
this->curr_plate_index = rhs.curr_plate_index;
this->calib_pa_pattern.reset();
this->calib_pa_pattern.swap(rhs.calib_pa_pattern);
this->calib_pa_pattern = std::move(rhs.calib_pa_pattern);
//BBS: add auxiliary path logic
// BBS: backup, all in one temp dir
@ -814,7 +810,7 @@ std::string Model::get_backup_path()
std::time_t t = std::time(0);
std::tm* now_time = std::localtime(&t);
std::stringstream buf;
buf << "/orcaslicer_model/";
buf << "/bamboo_model/";
buf << std::put_time(now_time, "%a_%b_%d/%H_%M_%S#");
buf << pid << "#";
buf << this->id().id;
@ -1382,11 +1378,19 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
}
// This returns an accurate snug bounding box of the transformed object instance, without the translation applied.
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const {
return instance_bounding_box(*this->instances[instance_idx], dont_translate);
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
{
BoundingBoxf3 bb;
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
for (ModelVolume *v : this->volumes)
{
if (v->is_model_part())
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
}
return bb;
}
BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance &instance, bool dont_translate) const {
BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance& instance, bool dont_translate) const {
BoundingBoxf3 bbox;
const auto& inst_mat = instance.get_transformation().get_matrix(dont_translate);
for (auto vol : this->volumes) {
@ -1396,7 +1400,6 @@ BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance &instance,
return bbox;
}
//BBS: add convex bounding box
BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const
{
@ -2458,6 +2461,7 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
assert(instance_idx < this->instances.size());
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
return;
@ -3246,7 +3250,6 @@ double Model::findMaxSpeed(const ModelObject* object) {
double solidInfillSpeedObj = Model::printSpeedMap.solidInfillSpeed;
double topSolidInfillSpeedObj = Model::printSpeedMap.topSolidInfillSpeed;
double supportSpeedObj = Model::printSpeedMap.supportSpeed;
double smallPerimeterSpeedObj = Model::printSpeedMap.smallPerimeterSpeed;
for (std::string objectKey : objectKeys) {
if (objectKey == "inner_wall_speed"){
perimeterSpeedObj = object->config.opt_float(objectKey);
@ -3262,10 +3265,8 @@ double Model::findMaxSpeed(const ModelObject* object) {
supportSpeedObj = object->config.opt_float(objectKey);
if (objectKey == "outer_wall_speed")
externalPerimeterSpeedObj = object->config.opt_float(objectKey);
if (objectKey == "small_perimeter_speed")
smallPerimeterSpeedObj = object->config.opt_float(objectKey);
}
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, objMaxSpeed)))))));
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, objMaxSpeed))))));
if (objMaxSpeed <= 0) objMaxSpeed = 250.;
return objMaxSpeed;
}

View file

@ -22,6 +22,8 @@
//BBS: add stl
#include "Format/STL.hpp"
#include "Calib.hpp"
#include <map>
#include <memory>
#include <string>

View file

@ -1,6 +1,5 @@
#include "PerimeterGenerator.hpp"
#include "ClipperUtils.hpp"
#include "ExtrusionEntity.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "ShortestPath.hpp"
#include "VariableWidth.hpp"
@ -276,7 +275,7 @@ 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) {
if (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++)
{
@ -323,12 +322,31 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
// outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter
if (remain_polines.size() != 0) {
extrusion_paths_append(paths, std::move(remain_polines), overhang_sampling_number - 1, int(0),
erOverhangPerimeter, perimeter_generator.mm3_per_mm_overhang(),
perimeter_generator.overhang_flow.width(),
perimeter_generator.overhang_flow.height());
}
if (!((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0)
&& perimeter_generator.object_config->support_top_z_distance.value == 0)) {
extrusion_paths_append(
paths,
std::move(remain_polines),
overhang_sampling_number - 1,
int(0),
erOverhangPerimeter,
perimeter_generator.mm3_per_mm_overhang(),
perimeter_generator.overhang_flow.width(),
perimeter_generator.overhang_flow.height());
} else {
extrusion_paths_append(
paths,
std::move(remain_polines),
overhang_sampling_number - 1,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float)perimeter_generator.layer_height);
}
}
// Reapply the nearest point search for starting point.
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
@ -395,22 +413,38 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path& subject, con
ClipperLib_Z::Clipper clipper;
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot,
const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
// The clipping contour may be simplified by clipping it with a bounding box of "subject" path.
// The clipping function used may produce self intersections outside of the "subject" bounding box. Such self intersections are
// harmless to the result of the clipping operation,
// Both ends of each edge belong to the same source: Either they are from subject or from clipping path.
assert(e1bot.z() >= 0 && e1top.z() >= 0);
assert(e2bot.z() >= 0 && e2top.z() >= 0);
assert((e1bot.z() == 0) == (e1top.z() == 0));
assert((e2bot.z() == 0) == (e2top.z() == 0));
// Start & end points of the clipped polyline (extrusion path with a non-zero width).
ClipperLib_Z::IntPoint start = e1bot;
ClipperLib_Z::IntPoint end = e1top;
if (start.z() <= 0 && end.z() <= 0) {
start = e2bot;
end = e2top;
}
assert(start.z() > 0 && end.z() > 0);
if (start.z() <= 0 && end.z() <= 0) {
// Self intersection on the source contour.
assert(start.z() == 0 && end.z() == 0);
pt.z() = 0;
}
else {
// Interpolate extrusion line width.
assert(start.z() > 0 && end.z() > 0);
// Interpolate extrusion line width.
double length_sqr = (end - start).cast<double>().squaredNorm();
double dist_sqr = (pt - start).cast<double>().squaredNorm();
double t = std::sqrt(dist_sqr / length_sqr);
double length_sqr = (end - start).cast<double>().squaredNorm();
double dist_sqr = (pt - start).cast<double>().squaredNorm();
double t = std::sqrt(dist_sqr / length_sqr);
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
}
});
clipper.AddPath(subject, ClipperLib_Z::ptSubject, false);
@ -577,7 +611,9 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
ExtrusionPaths paths;
// detect overhanging/bridging perimeters
if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
if (perimeter_generator.config->detect_overhang_wall && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers
&& !((perimeter_generator.object_config->enable_support || perimeter_generator.object_config->enforce_support_layers > 0) &&
perimeter_generator.object_config->support_top_z_distance.value == 0)) {
ClipperLib_Z::Path extrusion_path;
extrusion_path.reserve(extrusion->size());
BoundingBox extrusion_path_bbox;
@ -609,7 +645,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
extrusion_paths_append(temp_paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role,
is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
if (perimeter_generator.config->enable_overhang_speed && perimeter_generator.config->fuzzy_skin == FuzzySkinType::None) {
Flow flow = is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow;
std::map<double, std::vector<Polygons>> clipper_serise;
@ -759,100 +795,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
return extrusion_coll;
}
void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills,
ExPolygons &non_top_polygons, ExPolygons &fill_clip) const {
// other perimeters
coord_t perimeter_width = this->perimeter_flow.scaled_width();
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
// external perimeters
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
bool has_gap_fill = this->config->gap_infill_speed.value > 0;
// split the polygons with top/not_top
// get the offset from solid surface anchor
coord_t offset_top_surface =
scale_(1.5 * (config->wall_loops.value == 0
? 0.
: unscaled(double(ext_perimeter_width +
perimeter_spacing * int(int(config->wall_loops.value) - int(1))))));
// if possible, try to not push the extra perimeters inside the sparse infill
if (offset_top_surface >
0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))))
offset_top_surface -=
coord_t(0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))));
else
offset_top_surface = 0;
// don't takes into account too thin areas
// skip if the exposed area is smaller than "min_width_top_surface"
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), config->min_width_top_surface.get_abs_value(perimeter_width));
Polygons grown_upper_slices = offset(*this->upper_slices, min_width_top_surface);
// get boungding box of last
BoundingBox last_box = get_extents(orig_polygons);
last_box.offset(SCALED_EPSILON);
// get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped =
ClipperUtils::clip_clipper_polygons_with_subject_bbox(grown_upper_slices, last_box);
// set the clip to a virtual "second perimeter"
fill_clip = offset_ex(orig_polygons, -double(ext_perimeter_spacing));
// get the real top surface
ExPolygons grown_lower_slices;
ExPolygons bridge_checker;
auto nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
// Check whether surface be bridge or not
if (this->lower_slices != NULL) {
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped =
ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, last_box);
double bridge_offset = std::max(double(ext_perimeter_spacing), (double(perimeter_width)));
// SoftFever: improve bridging
const float bridge_margin =
std::min(float(scale_(BRIDGE_INFILL_MARGIN)), float(scale_(nozzle_diameter * BRIDGE_INFILL_MARGIN / 0.4)));
bridge_checker = offset_ex(diff_ex(orig_polygons, lower_polygons_series_clipped, ApplySafetyOffset::Yes),
1.5 * bridge_offset + bridge_margin + perimeter_spacing / 2);
}
ExPolygons delete_bridge = diff_ex(orig_polygons, bridge_checker, ApplySafetyOffset::Yes);
ExPolygons top_polygons = diff_ex(delete_bridge, upper_polygons_series_clipped, ApplySafetyOffset::Yes);
// get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the
// min_width_top_surface we removed a bit before)
ExPolygons temp_gap = diff_ex(top_polygons, fill_clip);
ExPolygons inner_polygons =
diff_ex(orig_polygons,
offset_ex(top_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
ApplySafetyOffset::Yes);
// get the enlarged top surface, by using inner_polygons instead of upper_slices, and clip it for it to be exactly
// the polygons to fill.
top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
// increase by half peri the inner space to fill the frontier between last and stored.
top_fills = union_ex(top_fills, top_polygons);
//set the clip to the external wall but go back inside by infill_extrusion_width/2 to be sure the extrusion won't go outside even with a 100% overlap.
double infill_spacing_unscaled = this->config->sparse_infill_line_width.get_abs_value(nozzle_diameter);
if (infill_spacing_unscaled == 0) infill_spacing_unscaled = Flow::auto_extrusion_width(frInfill, nozzle_diameter);
fill_clip = offset_ex(orig_polygons, double(ext_perimeter_spacing / 2) - scale_(infill_spacing_unscaled / 2));
// ExPolygons oldLast = last;
non_top_polygons = intersection_ex(inner_polygons, orig_polygons);
if (has_gap_fill)
non_top_polygons = union_ex(non_top_polygons, temp_gap);
//{
// std::stringstream stri;
// stri << this->layer_id << "_1_"<< i <<"_only_one_peri"<< ".svg";
// SVG svg(stri.str());
// svg.draw(to_polylines(top_fills), "green");
// svg.draw(to_polylines(inner_polygons), "yellow");
// svg.draw(to_polylines(top_polygons), "cyan");
// svg.draw(to_polylines(oldLast), "orange");
// svg.draw(to_polylines(last), "red");
// svg.Close();
//}
}
void PerimeterGenerator::process_classic()
{
@ -860,17 +803,12 @@ void PerimeterGenerator::process_classic()
m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
coord_t perimeter_width = this->perimeter_flow.scaled_width();
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
// external perimeters
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2;
if(config->precise_outer_wall)
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width()));
else
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
@ -913,13 +851,17 @@ void PerimeterGenerator::process_classic()
// BBS: don't simplify too much which influence arc fitting when export gcode if arc_fitting is enabled
double surface_simplify_resolution = (print_config->enable_arc_fitting && this->config->fuzzy_skin == FuzzySkinType::None) ? 0.2 * m_scaled_resolution : m_scaled_resolution;
for (const Surface &surface : this->slices->surfaces) {
//BBS: reorder the surface to reduce the travel time
ExPolygons surface_exp;
for (const Surface &surface : this->slices->surfaces)
surface_exp.push_back(surface.expolygon);
std::vector<size_t> surface_order = chain_expolygons(surface_exp);
for (size_t order_idx = 0; order_idx < surface_order.size(); order_idx++) {
const Surface &surface = this->slices->surfaces[surface_order[order_idx]];
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
loop_number = 0;
//BBS: set the topmost layer to be one wall
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
//BBS: set the topmost and bottom most layer to be one wall
if (loop_number > 0 && ((this->object_config->top_one_wall_type != TopOneWallType::None && this->upper_slices == nullptr) || (this->object_config->only_one_wall_first_layer && layer_id == 0)))
loop_number = 0;
ExPolygons last = union_ex(surface.expolygon.simplify_p(surface_simplify_resolution));
@ -1066,8 +1008,68 @@ void PerimeterGenerator::process_classic()
//BBS: refer to superslicer
//store surface for top infill if only_one_wall_top
if (i == 0 && i!=loop_number && config->only_one_wall_top && this->upper_slices != NULL) {
this->split_top_surfaces(last, top_fills, last, fill_clip);
if (i == 0 && i != loop_number && this->object_config->top_one_wall_type == TopOneWallType::Alltop && this->upper_slices != NULL) {
//split the polygons with top/not_top
//get the offset from solid surface anchor
coord_t offset_top_surface = scale_(1.5 * (config->wall_loops.value == 0 ? 0. : unscaled(double(ext_perimeter_width + perimeter_spacing * int(int(config->wall_loops.value) - int(1))))));
// if possible, try to not push the extra perimeters inside the sparse infill
if (offset_top_surface > 0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))))
offset_top_surface -= coord_t(0.9 * (config->wall_loops.value <= 1 ? 0. : (perimeter_spacing * (config->wall_loops.value - 1))));
else
offset_top_surface = 0;
//don't takes into account too thin areas
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), 1.0 * (double(perimeter_width)));
//BBS: get boungding box of last
BoundingBox last_box = get_extents(last);
last_box.offset(SCALED_EPSILON);
// BBS: get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, last_box);
upper_polygons_series_clipped = offset(upper_polygons_series_clipped, min_width_top_surface);
//set the clip to a virtual "second perimeter"
fill_clip = offset_ex(last, -double(ext_perimeter_spacing));
// get the real top surface
ExPolygons grown_lower_slices;
ExPolygons bridge_checker;
// BBS: check whether surface be bridge or not
if (this->lower_slices != NULL) {
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, last_box);
double bridge_offset = std::max(double(ext_perimeter_spacing), (double(perimeter_width)));
bridge_checker = offset_ex(diff_ex(last, lower_polygons_series_clipped, ApplySafetyOffset::Yes), 1.5 * bridge_offset);
}
ExPolygons delete_bridge = diff_ex(last, bridge_checker, ApplySafetyOffset::Yes);
ExPolygons top_polygons = diff_ex(delete_bridge, upper_polygons_series_clipped, ApplySafetyOffset::Yes);
//get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the min_width_top_surface we removed a bit before)
ExPolygons temp_gap = diff_ex(top_polygons, fill_clip);
ExPolygons inner_polygons = diff_ex(last,
offset_ex(top_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
ApplySafetyOffset::Yes);
// get the enlarged top surface, by using inner_polygons instead of upper_slices, and clip it for it to be exactly the polygons to fill.
top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
// increase by half peri the inner space to fill the frontier between last and stored.
top_fills = union_ex(top_fills, top_polygons);
//set the clip to the external wall but go back inside by infill_extrusion_width/2 to be sure the extrusion won't go outside even with a 100% overlap.
double infill_spacing_unscaled = this->config->sparse_infill_line_width.value;
fill_clip = offset_ex(last, double(ext_perimeter_spacing / 2) - scale_(infill_spacing_unscaled / 2));
last = intersection_ex(inner_polygons, last);
if (has_gap_fill)
last = union_ex(last,temp_gap);
//{
// std::stringstream stri;
// stri << this->layer->id() << "_1_"<< i <<"_only_one_peri"<< ".svg";
// SVG svg(stri.str());
// svg.draw(to_polylines(top_fills), "green");
// svg.draw(to_polylines(inner_polygons), "yellow");
// svg.draw(to_polylines(top_polygons), "cyan");
// svg.draw(to_polylines(oldLast), "orange");
// svg.draw(to_polylines(last), "red");
// svg.Close();
//}
}
if (i == loop_number && (! has_gap_fill || this->config->sparse_infill_density.value == 0)) {
@ -1133,21 +1135,20 @@ void PerimeterGenerator::process_classic()
}
// at this point, all loops should be in contours[0]
ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls);
// if brim will be printed, reverse the order of perimeters so that
// we continue inwards after having finished the brim
// TODO: add test for perimeter order
bool is_outer_wall_first =
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
bool is_outer_wall_first =
this->print_config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->print_config->wall_infill_order == WallInfillOrder::InfillOuterInner;
if (is_outer_wall_first ||
//BBS: always print outer wall first when there indeed has brim.
(this->layer_id == 0 &&
this->object_config->brim_type == BrimType::btOuterOnly &&
this->object_config->brim_width.value > 0))
this->object_config->brim_type == BrimType::btOuterOnly &&
this->object_config->brim_width.value > 0))
entities.reverse();
// SoftFever: sandwich mode
else if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
//BBS. adjust wall generate seq
else if (this->print_config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
if (entities.entities.size() > 1){
int last_outer=0;
int outer = 0;
@ -1160,7 +1161,6 @@ void PerimeterGenerator::process_classic()
// append perimeters for this slice as a collection
if (! entities.empty())
this->loops->append(entities);
} // for each loop of an island
// fill gaps
@ -1194,12 +1194,10 @@ void PerimeterGenerator::process_classic()
++ irun;
}
#endif
// SoftFever: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
[&](const ThickPolyline& p) {
return p.length() < scale_(config->filter_out_gap_fill.value);
}), polylines.end());
// OrcaSlicer: filter out tiny gap fills
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [&](const ThickPolyline &p) {
return p.length()< scale_(this->config->filter_out_gap_fill.value);
}), polylines.end());
if (! polylines.empty()) {
ExtrusionEntityCollection gap_fill;
@ -1213,8 +1211,7 @@ void PerimeterGenerator::process_classic()
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
// therefore it may cover the area, but no the volume.
last = diff_ex(last, gap_fill.polygons_covered_by_width(10.f));
this->gap_fill->append(std::move(gap_fill.entities));
this->gap_fill->append(std::move(gap_fill.entities));
}
}
@ -1275,6 +1272,39 @@ void PerimeterGenerator::process_classic()
} // for each island
}
//BBS:
void PerimeterGenerator::add_infill_contour_for_arachne( ExPolygons infill_contour,
int loops,
coord_t ext_perimeter_spacing,
coord_t perimeter_spacing,
coord_t min_perimeter_infill_spacing,
coord_t spacing,
bool is_inner_part)
{
if( offset_ex(infill_contour, -float(spacing / 2.)).empty() )
{
infill_contour.clear(); // Infill region is too small, so let's filter it out.
}
// create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary)
// and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions
coord_t insert = (loops < 0) ? 0: ext_perimeter_spacing;
if (is_inner_part || loops > 0)
insert = perimeter_spacing;
insert = coord_t(scale_(this->config->infill_wall_overlap.get_abs_value(unscale<double>(insert))));
Polygons inner_pp;
for (ExPolygon &ex : infill_contour)
ex.simplify_p(m_scaled_resolution, &inner_pp);
this->fill_surfaces->append(offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(insert + min_perimeter_infill_spacing / 2.)), stInternal);
append(*this->fill_no_overlap, offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(+min_perimeter_infill_spacing / 2.)));
}
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
void PerimeterGenerator::process_arachne()
@ -1288,6 +1318,7 @@ void PerimeterGenerator::process_arachne()
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
@ -1309,20 +1340,15 @@ void PerimeterGenerator::process_arachne()
// we need to process each island separately because we might have different
// extra perimeters for each one
for (const Surface& surface : this->slices->surfaces) {
coord_t bead_width_0 = ext_perimeter_spacing;
if (config->precise_outer_wall)
bead_width_0 = ext_perimeter_width + this->perimeter_flow.scaled_width() - perimeter_spacing;
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (loop_number > 0 && this->object_config->only_one_wall_first_layer && layer_id == 0 ||
(this->object_config->top_one_wall_type == TopOneWallType::Topmost && this->upper_slices == nullptr))
loop_number = 0;
// BBS: set the topmost layer to be one wall
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
loop_number = 0;
ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution),
config->precise_outer_wall ? -float(ext_perimeter_width / 2. - bead_width_0 / 2.)
: -float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
ExPolygons last = offset_ex(surface.expolygon.simplify_p(surface_simplify_resolution), -float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
Polygons last_p = to_polygons(last);
double min_nozzle_diameter = *std::min_element(print_config->nozzle_diameter.values.begin(), print_config->nozzle_diameter.values.end());
Arachne::WallToolPathsParams input_params;
{
@ -1341,67 +1367,76 @@ void PerimeterGenerator::process_arachne()
input_params.wall_transition_angle = this->object_config->wall_transition_angle.value;
input_params.wall_distribution_count = this->object_config->wall_distribution_count.value;
}
coord_t wall_0_inset = 0;
//if (config->precise_outer_wall)
// wall_0_inset = 0.5 * (ext_perimeter_width + this->perimeter_flow.scaled_width() - ext_perimeter_spacing -
// perimeter_spacing);
std::vector<Arachne::VariableWidthLines> out_shell;
ExPolygons top_fills;
ExPolygons fill_clip;
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices != nullptr) {
// Check if current layer has surfaces that are not covered by upper layer (i.e., top surfaces)
ExPolygons non_top_polygons;
this->split_top_surfaces(last, top_fills, non_top_polygons, fill_clip);
int remain_loops = -1;
if (this->object_config->top_one_wall_type == TopOneWallType::Alltop) {
if (this->upper_slices != nullptr)
remain_loops = loop_number - 1;
if (top_fills.empty()) {
// No top surfaces, no special handling needed
} else {
// First we slice the outer shell
Polygons last_p = to_polygons(last);
Arachne::WallToolPaths wallToolPaths(last_p, bead_width_0, perimeter_spacing, coord_t(1),
wall_0_inset, layer_height, input_params);
out_shell = wallToolPaths.getToolPaths();
// Make sure infill not overlap with wall
top_fills = intersection_ex(top_fills, wallToolPaths.getInnerContour());
if (!top_fills.empty()) {
// Then get the inner part that needs more walls
last = intersection_ex(non_top_polygons, wallToolPaths.getInnerContour());
loop_number--;
} else {
// Give up the outer shell because we don't have any meaningful top surface
out_shell.clear();
}
}
loop_number = 0;
}
Polygons last_p = to_polygons(last);
Arachne::WallToolPaths wallToolPaths(last_p, bead_width_0, perimeter_spacing, coord_t(loop_number + 1),
wall_0_inset, layer_height, input_params);
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, layer_height, input_params);
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
loop_number = int(perimeters.size()) - 1;
if (!out_shell.empty()) {
// Combine outer shells
size_t inset_offset = 0;
for (auto &p : out_shell) {
for (auto &l : p) {
if (l.inset_idx + 1 > inset_offset) {
inset_offset = l.inset_idx + 1;
//BBS: top one wall for arachne
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
ExPolygons inner_infill_contour;
if( remain_loops >= 0 )
{
ExPolygons the_layer_surface = infill_contour;
// BBS: get boungding box of last
BoundingBox infill_contour_box = get_extents(infill_contour);
infill_contour_box.offset(SCALED_EPSILON);
// BBS: get the Polygons upper the polygon this layer
Polygons upper_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, infill_contour_box);
infill_contour = diff_ex(infill_contour, upper_polygons_series_clipped);
coord_t perimeter_width = this->perimeter_flow.scaled_width();
//BBS: add bridge area
if (this->lower_slices != nullptr) {
BoundingBox infill_contour_box = get_extents(infill_contour);
infill_contour_box.offset(SCALED_EPSILON);
// BBS: get the Polygons below the polygon this layer
Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, infill_contour_box);
ExPolygons bridge_area = offset_ex(diff_ex(infill_contour, lower_polygons_series_clipped), std::max(ext_perimeter_spacing, perimeter_width));
infill_contour = diff_ex(infill_contour, bridge_area);
}
//BBS: filter small area and extend top surface a bit to hide the wall line
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 4 + 10), double(perimeter_width / 4));
infill_contour = offset2_ex(infill_contour, -min_width_top_surface, min_width_top_surface + perimeter_width);
//BBS: get the inner surface that not export to top
ExPolygons surface_not_export_to_top = diff_ex(the_layer_surface, infill_contour);
//BBS: get real top surface
infill_contour = intersection_ex(infill_contour, the_layer_surface);
Polygons surface_not_export_to_top_p = to_polygons(surface_not_export_to_top);
Arachne::WallToolPaths innerWallToolPaths(surface_not_export_to_top_p, ext_perimeter_spacing, perimeter_spacing, coord_t(remain_loops + 1), 0, layer_height, input_params);
std::vector<Arachne::VariableWidthLines> perimeters_inner = innerWallToolPaths.getToolPaths();
remain_loops = int(perimeters_inner.size()) - 1;
//BBS: set wall's perporsity
if (!perimeters.empty()) {
for (int perimeter_idx = 0; perimeter_idx < perimeters_inner.size(); perimeter_idx++) {
if (perimeters_inner[perimeter_idx].empty()) continue;
for (Arachne::ExtrusionLine &wall : perimeters_inner[perimeter_idx]) {
// BBS: 0 means outer wall
wall.inset_idx++;
}
}
}
for (auto &p : perimeters) {
for (auto &l : p) {
l.inset_idx += inset_offset;
}
}
perimeters.insert(perimeters.end(), perimeters_inner.begin(), perimeters_inner.end());
perimeters.insert(perimeters.begin(), out_shell.begin(), out_shell.end());
inner_infill_contour = union_ex(innerWallToolPaths.getInnerContour());
}
loop_number = int(perimeters.size()) - 1;
#ifdef ARACHNE_DEBUG
{
@ -1426,9 +1461,8 @@ void PerimeterGenerator::process_arachne()
int direction = -1;
bool is_outer_wall_first =
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
this->print_config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
this->print_config->wall_infill_order == WallInfillOrder::InfillOuterInner;
if (is_outer_wall_first) {
start_perimeter = 0;
end_perimeter = int(perimeters.size());
@ -1554,102 +1588,32 @@ void PerimeterGenerator::process_arachne()
}
}
}
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill) {
if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner ordering
int position = 0; // index to run the re-ordering for multiple external perimeters in a single island.
int arr_i = 0; // index to run through the walls
int outer, first_internal, second_internal; // allocate index values
// run the re-ordering for all wall loops in the same island
while (position < ordered_extrusions.size()) {
outer = first_internal = second_internal = -1; // initialise all index values to -1
// run through the walls to get the index values that need re-ordering until the first one for each
// is found. Start at "position" index to enable the for loop to iterate for multiple external
// perimeters in a single island
for (arr_i = position; arr_i < ordered_extrusions.size(); ++arr_i) {
switch (ordered_extrusions[arr_i].extrusion->inset_idx) {
case 0: // external perimeter
if (outer == -1)
outer = arr_i;
break;
case 1: // first internal wall
if (first_internal == -1 && arr_i > outer)
first_internal = arr_i;
break;
case 2: // second internal wall
if (ordered_extrusions[arr_i].extrusion->inset_idx == 2 && second_internal == -1 &&
arr_i > first_internal)
second_internal = arr_i;
break;
}
if (second_internal != -1)
break; // found all three perimeters to re-order
// BBS. adjust wall generate seq
if (this->print_config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
if (ordered_extrusions.size() > 1) {
int last_outer = 0;
int outer = 0;
for (; outer < ordered_extrusions.size(); ++outer)
if (ordered_extrusions[outer].extrusion->inset_idx == 0 && outer - last_outer > 1) {
std::swap(ordered_extrusions[outer], ordered_extrusions[outer - 1]);
last_outer = outer;
}
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order?
const auto temp = ordered_extrusions[second_internal];
ordered_extrusions[second_internal] = ordered_extrusions[first_internal];
ordered_extrusions[first_internal] = ordered_extrusions[outer];
ordered_extrusions[outer] = temp;
} else
break; // did not find any more candidates to re-order, so stop the while loop early
// go to the next perimeter to continue scanning for external walls in the same island
position = arr_i + 1;
}
}
}
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty())
this->loops->append(extrusion_coll);
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
const coord_t spacing = (perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
if (offset_ex(infill_contour, -float(spacing / 2.)).empty())
infill_contour.clear(); // Infill region is too small, so let's filter it out.
// create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary)
// and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions
coord_t inset =
(loop_number < 0) ? 0 :
(loop_number == 0) ?
// one loop
ext_perimeter_spacing :
// two or more loops?
perimeter_spacing;
inset = coord_t(scale_(this->config->infill_wall_overlap.get_abs_value(unscale<double>(inset))));
// simplify infill contours according to resolution
Polygons pp;
for (ExPolygon& ex : infill_contour)
ex.simplify_p(m_scaled_resolution, &pp);
ExPolygons not_filled_exp = union_ex(pp);
// collapse too narrow infill areas
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
ExPolygons infill_exp = offset2_ex(
not_filled_exp,
float(-min_perimeter_infill_spacing / 2.),
float(inset + min_perimeter_infill_spacing / 2.));
// append infill areas to fill_surfaces
if (!top_fills.empty()) {
infill_exp = union_ex(infill_exp, offset_ex(top_fills, double(inset)));
}
this->fill_surfaces->append(infill_exp, stInternal);
add_infill_contour_for_arachne(infill_contour, loop_number, ext_perimeter_spacing, perimeter_spacing, min_perimeter_infill_spacing, spacing, false);
//BBS: add infill_contour of top one wall part
if( !inner_infill_contour.empty() )
add_infill_contour_for_arachne(inner_infill_contour, remain_loops, ext_perimeter_spacing, perimeter_spacing, min_perimeter_infill_spacing, spacing, true);
// BBS: get the no-overlap infill expolygons
{
ExPolygons polyWithoutOverlap;
polyWithoutOverlap = offset2_ex(
not_filled_exp,
float(-min_perimeter_infill_spacing / 2.),
float(+min_perimeter_infill_spacing / 2.));
if (!top_fills.empty())
polyWithoutOverlap = union_ex(polyWithoutOverlap, top_fills);
this->fill_no_overlap->insert(this->fill_no_overlap->end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end());
}
}
}
@ -1680,7 +1644,6 @@ std::map<int, Polygons> PerimeterGenerator::generate_lower_polygons_series(float
// 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;
std::map<int, Polygons> lower_polygons_series;
if (this->lower_slices == NULL) {

View file

@ -69,6 +69,8 @@ public:
void process_classic();
void process_arachne();
void add_infill_contour_for_arachne( ExPolygons infill_contour, int loops, coord_t ext_perimeter_spacing, coord_t perimeter_spacing, coord_t min_perimeter_infill_spacing, coord_t spacing, bool is_inner_part );
double ext_mm3_per_mm() const { return m_ext_mm3_per_mm; }
double mm3_per_mm() const { return m_mm3_per_mm; }
double mm3_per_mm_overhang() const { return m_mm3_per_mm_overhang; }

View file

@ -1,6 +1,5 @@
#include <cassert>
#include "Config.hpp"
#include "Exception.hpp"
#include "Preset.hpp"
#include "PresetBundle.hpp"
@ -678,6 +677,25 @@ std::string Preset::get_current_printer_type(PresetBundle *preset_bundle)
return "";
}
bool Preset::has_lidar(PresetBundle *preset_bundle)
{
bool has_lidar = false;
if (preset_bundle) {
auto config = &preset_bundle->printers.get_edited_preset().config;
std::string vendor_name;
for (auto vendor_profile : preset_bundle->vendors) {
for (auto vendor_model : vendor_profile.second.models)
if (vendor_model.name == config->opt_string("printer_model")) {
vendor_name = vendor_profile.first;
break;
}
}
if (!vendor_name.empty())
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
}
return has_lidar;
}
bool Preset::is_custom_defined()
{
if (custom_defined == "1")
@ -685,9 +703,9 @@ bool Preset::is_custom_defined()
return false;
}
bool Preset::has_lidar(PresetBundle *preset_bundle)
bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
{
bool has_lidar = false;
bool is_bbl_vendor_preset = true;
if (preset_bundle) {
auto config = &preset_bundle->printers.get_edited_preset().config;
std::string vendor_name;
@ -700,9 +718,9 @@ bool Preset::has_lidar(PresetBundle *preset_bundle)
}
}
if (!vendor_name.empty())
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
is_bbl_vendor_preset = vendor_name.compare("BBL") == 0 ? true : false;
}
return has_lidar;
return is_bbl_vendor_preset;
}
BedType Preset::get_default_bed_type(PresetBundle* preset_bundle)
@ -739,10 +757,10 @@ static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing",
"seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "sparse_infill_anchor", "sparse_infill_anchor_max",
"top_surface_pattern", "bottom_surface_pattern", "internal_solid_infill_pattern", "infill_direction", "bridge_angle",
"minimum_sparse_infill_area", "reduce_infill_retraction", "ironing_pattern", "ironing_type",
"ironing_flow", "ironing_speed", "ironing_spacing",
"max_travel_detour_distance",
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance",
#ifdef HAS_PRESSURE_EQUALIZER
@ -750,15 +768,19 @@ static std::vector<std::string> s_Preset_print_options {
#endif /* HAS_PRESSURE_EQUALIZER */
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
"bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed", "skirt_distance", "skirt_height", "draft_shield",
"brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
"bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration",
"initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration",
"accel_to_decel_enable", "accel_to_decel_factor", "skirt_loops", "skirt_distance",
"skirt_height", "draft_shield",
"brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
"support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style",
// BBS
"independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence", "support_remove_small_overhang",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "support_remove_small_overhang",
"bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence",
"filename_format", "wall_filament", "support_bottom_z_distance",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament",
"ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",
@ -768,25 +790,23 @@ static std::vector<std::string> s_Preset_print_options {
"prime_tower_width", "prime_tower_brim_width", "prime_volume",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support",
// BBS
"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter",
"tree_support_branch_diameter","tree_support_brim_width",
"detect_narrow_internal_solid_infill",
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/
"support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
"initial_layer_infill_speed", "only_one_wall_top",
"initial_layer_infill_speed", "top_one_wall_type", "only_one_wall_first_layer",
"timelapse_type", "internal_bridge_support_thickness",
"wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width", "post_process",
"small_perimeter_speed", "small_perimeter_threshold","bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops",
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max",
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size"
"seam_gap", "wipe_speed", "top_solid_infill_flow_ratio", "initial_layer_flow_ratio",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk",
"filter_out_gap_fill",
// calib
"print_flow_ratio",
//Orca
"exclude_object"
};
static std::vector<std::string> s_Preset_filament_options {
@ -802,15 +822,15 @@ static std::vector<std::string> s_Preset_filament_options {
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
"filament_start_gcode", "filament_end_gcode",
// Retract overrides
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
"filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe",
// Profile compatibility
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
//BBS
"filament_wipe_distance", "additional_cooling_fan_speed",
"bed_temperature_difference", "nozzle_temperature_range_low", "nozzle_temperature_range_high",
//SoftFever
"enable_pressure_advance", "pressure_advance","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed" /*,"filament_seam_gap"*/
//OrcaSlicer
"enable_pressure_advance", "pressure_advance", "chamber_temperatures"
};
static std::vector<std::string> s_Preset_machine_limits_options {
@ -824,20 +844,20 @@ static std::vector<std::string> s_Preset_machine_limits_options {
static std::vector<std::string> s_Preset_printer_options {
"printer_technology",
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"default_print_profile", "inherits",
"silent_mode",
// BBS
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_pause_gcode", "template_custom_gcode",
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "retract_lift_enforce",
//SoftFever
"nozzle_type","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types",
//OrcaSlicer
"host_type", "print_host", "printhost_apikey",
"print_host_webui",
"printhost_cafile","printhost_port","printhost_authorization_type",
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails",
"use_firmware_retraction", "use_relative_e_distances", "bbl_calib_mark_logo"};
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke",
"use_relative_e_distances", "extruder_type"
};
static std::vector<std::string> s_Preset_sla_print_options {
"layer_height",
@ -1725,14 +1745,12 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
{
// Load the preset over a default preset, so that the missing fields are filled in from the default preset.
DynamicPrintConfig cfg(this->default_preset_for(combined_config).config);
// SoftFever: ignore print connection info from project
auto keys = cfg.keys();
keys.erase(std::remove_if(keys.begin(), keys.end(),
[](std::string &val) {
return val == "print_host" || val == "print_host_webui" || val == "printhost_apikey" ||
val == "printhost_cafile";
}),
keys.end());
// OrcaSlicer: ignore print connection info from project
cfg.erase("print_host");
cfg.erase("print_host_webui");
cfg.erase("printhost_apikey");
cfg.erase("printhost_cafile");
const auto &keys = cfg.keys();
cfg.apply_only(combined_config, keys, true);
std::string &inherits = Preset::inherits(cfg);
@ -2345,7 +2363,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
{
//BBS: add bed_exclude_area
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails") {
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
// Scalar variable, or a vector variable, which is independent from number of extruders,
// thus the vector is presented to the user as a single input.
diff.emplace_back(opt_key);
@ -2667,7 +2685,6 @@ static std::vector<std::string> s_PhysicalPrinter_opts {
"printer_technology",
"host_type",
"print_host",
"print_host_webui",
"printhost_apikey",
"printhost_cafile",
"printhost_port",
@ -2839,8 +2856,6 @@ void PhysicalPrinterCollection::load_printers(
// see https://github.com/prusa3d/PrusaSlicer/issues/732
boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred();
m_dir_path = dir.string();
if(!boost::filesystem::exists(dir))
return;
std::string errors_cummulative;
// Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken.
std::deque<PhysicalPrinter> printers_loaded;
@ -3220,9 +3235,6 @@ namespace PresetUtils {
if (!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/" + preset.vendor->id + "/" + pm->hotend_model;
}
if (out.empty() ||!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/hotend.stl";
return out;
}
} // namespace PresetUtils

View file

@ -300,9 +300,11 @@ public:
std::string get_filament_type(std::string &display_filament_type);
std::string get_printer_type(PresetBundle *preset_bundle); // get edited preset type
std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type
bool is_custom_defined();
bool has_lidar(PresetBundle *preset_bundle);
bool is_custom_defined();
bool is_bbl_vendor_preset(PresetBundle *preset_bundle);
BedType get_default_bed_type(PresetBundle *preset_bundle);
bool has_cali_lines(PresetBundle* preset_bundle);

View file

@ -42,10 +42,10 @@ static std::vector<std::string> s_project_options {
};
//BBS: add BBL as default
const char *PresetBundle::BBL_BUNDLE = "Custom";
const char *PresetBundle::BBL_DEFAULT_PRINTER_MODEL = "MyKlipper 0.4 nozzle";
const char *PresetBundle::BBL_BUNDLE = "BBL";
const char *PresetBundle::BBL_DEFAULT_PRINTER_MODEL = "Bambu Lab X1 Carbon";
const char *PresetBundle::BBL_DEFAULT_PRINTER_VARIANT = "0.4";
const char *PresetBundle::BBL_DEFAULT_FILAMENT = "My Generic PLA";
const char *PresetBundle::BBL_DEFAULT_FILAMENT = "Generic PLA";
PresetBundle::PresetBundle()
: prints(Preset::TYPE_PRINT, Preset::print_options(), static_cast<const PrintRegionConfig &>(FullPrintConfig::defaults()))
@ -88,7 +88,7 @@ PresetBundle::PresetBundle()
for (size_t i = 0; i < 1; ++i) {
// The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one.
Preset &preset = this->printers.default_preset(i);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant", "thumbnails"}) preset.config.optptr(key, true);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant"}) preset.config.optptr(key, true);
//if (i == 0) {
preset.config.optptr("default_print_profile", true);
preset.config.option<ConfigOptionStrings>("default_filament_profile", true);
@ -512,9 +512,6 @@ std::string PresetBundle::get_hotend_model_for_printer_model(std::string model_n
out = Slic3r::resources_dir() + "/profiles/" + vendor_name + "/" + hotend_stl;
}
if (out.empty() ||!boost::filesystem::exists(boost::filesystem::path(out)))
out = Slic3r::resources_dir() + "/profiles/hotend.stl";
return out;
}
@ -919,7 +916,7 @@ void PresetBundle::remove_users_preset(AppConfig &config, std::map<std::string,
bool need_reset_print_preset = false;
// remove preset if user_id is not current user
for (auto it = prints.begin(); it != prints.end();) {
if (it->is_user() && !it->user_id.empty() && it->user_id.compare(preset_folder_user_id) == 0 && check_removed(*it)) {
if (it->is_user() && it->user_id.compare(preset_folder_user_id) == 0 && check_removed(*it)) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":prints erase %1%, type %2% user_id %3%")%it->name %Preset::get_type_string(it->type) %it->user_id;
if (it->name == selected_print_name)
need_reset_print_preset = true;
@ -939,7 +936,7 @@ void PresetBundle::remove_users_preset(AppConfig &config, std::map<std::string,
std::string selected_filament_name = filaments.get_selected_preset().name;
bool need_reset_filament_preset = false;
for (auto it = filaments.begin(); it != filaments.end();) {
if (it->is_user() && !it->user_id.empty() && it->user_id.compare(preset_folder_user_id) == 0 && check_removed(*it)) {
if (it->is_user() && it->user_id.compare(preset_folder_user_id) == 0 && check_removed(*it)) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":filaments erase %1%, type %2% user_id %3%")%it->name %Preset::get_type_string(it->type) %it->user_id;
if (it->name == selected_filament_name)
need_reset_filament_preset = true;
@ -1267,72 +1264,6 @@ void PresetBundle::load_installed_sla_materials(AppConfig &config)
preset.set_visible_from_appconfig(config);
}
void PresetBundle::update_selections(AppConfig &config)
{
std::string initial_printer_profile_name = printers.get_selected_preset_name();
// Orca: load from orca_presets
std::string initial_print_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_PRINT_NAME);
std::string initial_filament_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_FILAMENT_NAME);
// Selects the profiles, which were selected at the last application close.
prints.select_preset_by_name_strict(initial_print_profile_name);
filaments.select_preset_by_name_strict(initial_filament_profile_name);
// Load the names of the other filament profiles selected for a multi-material printer.
// Load it even if the current printer technology is SLA.
// The possibly excessive filament names will be later removed with this->update_multi_material_filament_presets()
// once the FFF technology gets selected.
this->filament_presets = { filaments.get_selected_preset_name() };
for (unsigned int i = 1; i < 1000; ++ i) {
char name[64];
sprintf(name, "filament_%02u", i);
auto f_name = config.get_printer_setting(initial_printer_profile_name, name);
if (f_name.empty())
break;
this->filament_presets.emplace_back(remove_ini_suffix(f_name));
}
std::vector<std::string> filament_colors;
auto f_colors = config.get_printer_setting(initial_printer_profile_name, "filament_colors");
if (!f_colors.empty()) {
boost::algorithm::split(filament_colors, f_colors, boost::algorithm::is_any_of(","));
}
filament_colors.resize(filament_presets.size(), "#FF8040");
project_config.option<ConfigOptionStrings>("filament_colour")->values = filament_colors;
std::vector<std::string> matrix;
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
auto flush_volumes_matrix = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values = std::vector<double>(flush_volumes_matrix.begin(), flush_volumes_matrix.end());
}
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
auto flush_volumes_vector = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values = std::vector<double>(flush_volumes_vector.begin(), flush_volumes_vector.end());
}
if (config.has("app", "flush_multiplier")) {
std::string str_flush_multiplier = config.get("app", "flush_multiplier");
if (!str_flush_multiplier.empty())
project_config.option<ConfigOptionFloat>("flush_multiplier")->set(new ConfigOptionFloat(std::stof(str_flush_multiplier)));
}
// Update visibility of presets based on their compatibility with the active printer.
// Always try to select a compatible print and filament preset to the current printer preset,
// as the application may have been closed with an active "external" preset, which does not
// exist.
this->update_compatible(PresetSelectCompatibleType::Always);
this->update_multi_material_filament_presets();
std::string first_visible_filament_name;
for (auto & fp : filament_presets) {
if (auto it = filaments.find_preset_internal(fp); it == filaments.end() || !it->is_visible || !it->is_compatible) {
if (first_visible_filament_name.empty())
first_visible_filament_name = filaments.first_compatible().name;
fp = first_visible_filament_name;
}
}
}
// Load selections (current print, current filaments, current printer) from config.ini
// This is done on application start up or after updates are applied.
void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& preferred_selection/* = PresetPreferences()*/)
@ -1346,8 +1277,10 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
this->load_installed_sla_materials(config);
// Parse the initial print / filament / printer profile names.
// std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_PRINT_NAME));
// std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_MATERIALS_NAME));
std::string initial_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_PRINT_NAME));
std::string initial_sla_print_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_PRINT_NAME));
std::string initial_filament_profile_name = remove_ini_suffix(config.get("presets", PRESET_FILAMENT_NAME));
std::string initial_sla_material_profile_name = remove_ini_suffix(config.get("presets", PRESET_SLA_MATERIALS_NAME));
std::string initial_printer_profile_name = remove_ini_suffix(config.get("presets", PRESET_PRINTER_NAME));
// Activate print / filament / printer profiles from either the config,
@ -1361,11 +1294,6 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant);
printers.select_preset_by_name(preferred_printer ? preferred_printer->name : initial_printer_profile_name, true);
// Orca: load from orca_presets
// const auto os_presets = config.get_machine_settings(initial_printer_profile_name);
std::string initial_print_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_PRINT_NAME);
std::string initial_filament_profile_name = config.get_printer_setting(initial_printer_profile_name, PRESET_FILAMENT_NAME);
//BBS: set default print/filament profiles to BBL's default setting
if (preferred_printer)
{
@ -1381,8 +1309,8 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
// Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found.
prints.select_preset_by_name_strict(initial_print_profile_name);
filaments.select_preset_by_name_strict(initial_filament_profile_name);
// sla_prints.select_preset_by_name_strict(initial_sla_print_profile_name);
// sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name);
sla_prints.select_preset_by_name_strict(initial_sla_print_profile_name);
sla_materials.select_preset_by_name_strict(initial_sla_material_profile_name);
// Load the names of the other filament profiles selected for a multi-material printer.
// Load it even if the current printer technology is SLA.
@ -1392,26 +1320,24 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p
for (unsigned int i = 1; i < 1000; ++ i) {
char name[64];
sprintf(name, "filament_%02u", i);
auto f_name = config.get_printer_setting(initial_printer_profile_name, name);
if (f_name.empty())
if (! config.has("presets", name))
break;
this->filament_presets.emplace_back(remove_ini_suffix(f_name));
this->filament_presets.emplace_back(remove_ini_suffix(config.get("presets", name)));
}
std::vector<std::string> filament_colors;
auto f_colors = config.get_printer_setting(initial_printer_profile_name, "filament_colors");
if (!f_colors.empty()) {
boost::algorithm::split(filament_colors, f_colors, boost::algorithm::is_any_of(","));
if (config.has("presets", "filament_colors")) {
boost::algorithm::split(filament_colors, config.get("presets", "filament_colors"), boost::algorithm::is_any_of(","));
}
filament_colors.resize(filament_presets.size(), "#FF8040");
filament_colors.resize(filament_presets.size(), "#00AE42");
project_config.option<ConfigOptionStrings>("filament_colour")->values = filament_colors;
std::vector<std::string> matrix;
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
if (config.has("presets", "flush_volumes_matrix")) {
boost::algorithm::split(matrix, config.get("presets", "flush_volumes_matrix"), boost::algorithm::is_any_of("|"));
auto flush_volumes_matrix = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values = std::vector<double>(flush_volumes_matrix.begin(), flush_volumes_matrix.end());
}
if (config.has_printer_setting(initial_printer_profile_name, "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get_printer_setting(initial_printer_profile_name, "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
if (config.has("presets", "flush_volumes_vector")) {
boost::algorithm::split(matrix, config.get("presets", "flush_volumes_vector"), boost::algorithm::is_any_of("|"));
auto flush_volumes_vector = matrix | boost::adaptors::transformed(boost::lexical_cast<double, std::string>);
project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values = std::vector<double>(flush_volumes_vector.begin(), flush_volumes_vector.end());
}
@ -1473,32 +1399,27 @@ void PresetBundle::export_selections(AppConfig &config)
assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() >= 1);
//assert(this->printers.get_edited_preset().printer_technology() != ptFFF || filament_presets.size() > 1 || filaments.get_selected_preset_name() == filament_presets.front());
config.clear_section("presets");
auto printer_name = printers.get_selected_preset_name();
config.set("presets", PRESET_PRINTER_NAME, printer_name);
config.clear_printer_settings(printer_name);
config.set_printer_setting(printer_name, PRESET_PRINTER_NAME, printer_name);
config.set_printer_setting(printer_name, PRESET_PRINT_NAME, prints.get_selected_preset_name());
config.set_printer_setting(printer_name, PRESET_FILAMENT_NAME, filament_presets.front());
config.set_printer_setting(printer_name, "curr_bed_type", config.get("curr_bed_type"));
config.set("presets", PRESET_PRINT_NAME, prints.get_selected_preset_name());
config.set("presets", PRESET_FILAMENT_NAME, filament_presets.front());
for (unsigned i = 1; i < filament_presets.size(); ++i) {
char name[64];
assert(!filament_presets[i].empty());
sprintf(name, "filament_%02u", i);
config.set_printer_setting(printer_name, name, filament_presets[i]);
config.set("presets", name, filament_presets[i]);
}
CNumericLocalesSetter locales_setter;
std::string filament_colors = boost::algorithm::join(project_config.option<ConfigOptionStrings>("filament_colour")->values, ",");
config.set_printer_setting(printer_name, "filament_colors", filament_colors);
config.set("presets", "filament_colors", filament_colors);
std::string flush_volumes_matrix = boost::algorithm::join(project_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values |
boost::adaptors::transformed(static_cast<std::string (*)(double)>(std::to_string)),
"|");
config.set_printer_setting(printer_name, "flush_volumes_matrix", flush_volumes_matrix);
config.set("presets", "flush_volumes_matrix", flush_volumes_matrix);
std::string flush_volumes_vector = boost::algorithm::join(project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values |
boost::adaptors::transformed(static_cast<std::string (*)(double)>(std::to_string)),
"|");
config.set_printer_setting(printer_name, "flush_volumes_vector", flush_volumes_vector);
config.set("presets", "flush_volumes_vector", flush_volumes_vector);
config.set("presets", PRESET_PRINTER_NAME, printers.get_selected_preset_name());
auto flush_multi_opt = project_config.option<ConfigOptionFloat>("flush_multiplier");
config.set("flush_multiplier", std::to_string(flush_multi_opt ? flush_multi_opt->getFloat() : 1.0f));
@ -1539,7 +1460,8 @@ unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns)
{
std::vector<std::string> filament_presets;
std::vector<std::string> filament_colors;
for (auto &ams : filament_ams_list) {
for (auto &entry : filament_ams_list) {
auto & ams = entry.second;
auto filament_id = ams.opt_string("filament_id", 0u);
auto filament_color = ams.opt_string("filament_colour", 0u);
auto filament_changed = !ams.has("filament_changed") || ams.opt_bool("filament_changed");
@ -1552,10 +1474,14 @@ unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns)
auto iter = std::find_if(filaments.begin(), filaments.end(), [&filament_id](auto &f) { return f.is_compatible && f.is_system && f.filament_id == filament_id; });
if (iter == filaments.end()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
auto filament_type = "Generic " + ams.opt_string("filament_type", 0u);
iter = std::find_if(filaments.begin(), filaments.end(), [&filament_type](auto &f) { return f.is_compatible && f.is_system
auto filament_type = ams.opt_string("filament_type", 0u);
if (!filament_type.empty()) {
filament_type = "Generic " + filament_type;
iter = std::find_if(filaments.begin(), filaments.end(), [&filament_type](auto &f) {
return f.is_compatible && f.is_system
&& boost::algorithm::starts_with(f.name, filament_type);
});
}
if (iter == filaments.end())
iter = std::find_if(filaments.begin(), filaments.end(), [&filament_type](auto &f) { return f.is_compatible && f.is_system; });
if (iter == filaments.end())
@ -1637,11 +1563,11 @@ DynamicPrintConfig PresetBundle::full_config() const
DynamicPrintConfig PresetBundle::full_config_secure() const
{
DynamicPrintConfig config = this->full_config();
//FIXME legacy, the keys should not be there after conversion to a Physical Printer profile.
config.erase("print_host");
//BBS example: config.erase("print_host");
config.erase("print_host_webui");
config.erase("printhost_apikey");
config.erase("printhost_cafile"); return config;
config.erase("printhost_cafile");
return config;
}
const std::set<std::string> ignore_settings_list ={
@ -3645,9 +3571,9 @@ std::vector<std::string> PresetBundle::export_current_configs(const std::string
if (overwrite == 0) overwrite = 1;
if (boost::filesystem::exists(file) && overwrite < 2) {
overwrite = override_confirm(preset->name);
if (overwrite == 0 || overwrite == 2)
continue;
}
if (overwrite == 0 || overwrite == 2)
continue;
preset->config.save_to_json(file, preset->name, "", preset->version.to_string());
result.push_back(file);
}

View file

@ -86,8 +86,6 @@ public:
//BBS: check whether this is the only edited filament
bool is_the_only_edited_filament(unsigned int filament_index);
// Orca: update selected filament and print
void update_selections(AppConfig &config);
void set_calibrate_printer(std::string name);
PresetCollection prints;
@ -102,7 +100,7 @@ public:
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
std::vector<std::string> filament_presets;
// BBS: ams
std::vector<DynamicPrintConfig> filament_ams_list;
std::map<int, DynamicPrintConfig> filament_ams_list;
// Calibrate
Preset const * calibrate_printer = nullptr;
std::set<Preset const *> calibrate_filaments;

View file

@ -23,7 +23,6 @@
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>
//BBS: add json support
#include "nlohmann/json.hpp"
@ -80,7 +79,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"before_layer_change_gcode",
"enable_pressure_advance",
"pressure_advance",
"enable_overhang_bridge_fan",
"enable_overhang_bridge_fan"
"overhang_fan_speed",
"overhang_fan_threshold",
"slow_down_for_layer_cooling",
@ -93,28 +92,23 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"extruder_clearance_height_to_rod",
"extruder_clearance_height_to_lid",
"extruder_clearance_radius",
"extruder_clearance_max_radius",
"extruder_colour",
"extruder_offset",
"filament_flow_ratio",
"reduce_fan_stop_start_freq",
"fan_cooling_layer_time",
"full_fan_speed_layer",
"fan_kickstart",
"fan_speedup_overhangs",
"fan_speedup_time",
"filament_colour",
"default_filament_colour",
"filament_diameter",
"filament_density",
"filament_cost",
"outer_wall_acceleration",
"inner_wall_acceleration",
"initial_layer_acceleration",
"outer_wall_acceleration",
"top_surface_acceleration",
"bridge_acceleration",
"travel_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration"
"accel_to_decel_enable",
"accel_to_decel_factor",
// BBS
"cool_plate_temp_initial_layer",
"eng_plate_temp_initial_layer",
@ -137,14 +131,10 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"retract_when_changing_layer",
"retraction_length",
"retract_length_toolchange",
"z_hop",
"retract_lift_above",
"retract_lift_below",
"retract_lift_enforce",
"z_hop",
"retract_restart_extra",
"retract_restart_extra_toolchange",
"retraction_speed",
"use_firmware_retraction",
"slow_down_layer_time",
"standby_temperature_delta",
"machine_start_gcode",
@ -155,23 +145,23 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"wipe_distance",
"curr_bed_type",
"nozzle_volume",
"chamber_temperature",
"thumbnails",
"nozzle_hrc",
"chamber_temperatures",
"required_nozzle_HRC",
"upward_compatible_machine",
// SoftFever
//OrcaSlicer
"seam_gap",
"role_based_wipe_speed",
"wipe_speed",
"use_relative_e_distances",
"accel_to_decel_enable",
"accel_to_decel_factor",
"wipe_on_loops",
"gcode_comments",
"gcode_label_objects",
"wipe_speed"
"default_jerk",
"outer_wall_jerk",
"inner_wall_jerk",
"infill_jerk",
"top_surface_jerk",
"initial_layer_jerk",
"travel_jerk",
"inner_wall_acceleration",
"sparse_infill_acceleration",
"exclude_object",
"support_material_interface_fan_speed"
"use_relative_e_distances"
};
static std::unordered_set<std::string> steps_ignore;
@ -189,7 +179,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
// These steps have no influence on the G-code whatsoever. Just ignore them.
} else if (
opt_key == "skirt_loops"
|| opt_key == "skirt_speed"
|| opt_key == "skirt_height"
|| opt_key == "draft_shield"
|| opt_key == "skirt_distance"
@ -201,7 +190,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
} else if (
opt_key == "initial_layer_print_height"
|| opt_key == "nozzle_diameter"
|| opt_key == "filament_shrink"
|| opt_key == "resolution"
// 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.
@ -210,8 +198,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posSlice);
} else if (
opt_key == "print_sequence"
|| opt_key == "chamber_temperatures"
|| opt_key == "filament_type"
|| opt_key == "chamber_temperature"
|| opt_key == "nozzle_temperature_initial_layer"
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|| opt_key == "filament_max_volumetric_speed"
@ -236,9 +224,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "initial_layer_infill_speed"
|| opt_key == "travel_speed"
|| opt_key == "travel_speed_z"
|| opt_key == "initial_layer_speed"
|| opt_key == "initial_layer_travel_speed"
|| opt_key == "slow_down_layers") {
|| opt_key == "initial_layer_speed") {
//|| opt_key == "z_offset") {
steps.emplace_back(psWipeTower);
steps.emplace_back(psSkirtBrim);
@ -262,7 +248,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posPerimeters);
osteps.emplace_back(posInfill);
osteps.emplace_back(posSupportMaterial);
osteps.emplace_back(posSimplifyPath);
osteps.emplace_back(posSimplifyWall);
osteps.emplace_back(posSimplifyInfill);
osteps.emplace_back(posSimplifySupportPath);
steps.emplace_back(psSkirtBrim);
@ -288,9 +274,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
return invalidated;
}
void Print::set_calib_params(const Calib_Params& params) {
m_calib_params = params;
m_calib_params.mode = params.mode;
void Print::set_calib_params(const Calib_Params &params)
{
m_calib_params = params;
}
bool Print::invalidate_step(PrintStep step)
@ -541,7 +527,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
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 - EPSILON)),
float(scale_(0.5 * print.config().extruder_clearance_max_radius.value - EPSILON)),
jtRound, scale_(0.1));
if (!tmp.empty()) { // tmp may be empty due to clipper's bug, see STUDIO-2452
convex_hull = tmp.front();
@ -954,10 +940,6 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
return {std::string()};
}
// Orca: this g92e0 regex is used copied from PrusaSlicer
// Matches "G92 E0" with various forms of writing the zero and with an optional comment.
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
//BBS: refine seq-print validation logic
StringObjectException Print::validate(StringObjectException *warning, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
@ -1138,15 +1120,19 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
return ("One or more object were assigned an extruder that the printer does not have.");
#endif
auto validate_extrusion_width = [min_nozzle_diameter, max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
auto validate_extrusion_width = [/*min_nozzle_diameter,*/ max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
// This may change in the future, if we switch to "extrusion width wrt. nozzle diameter"
// instead of currently used logic "extrusion width wrt. layer height", see GH issues #1923 #2829.
// double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
// double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
double extrusion_width_min = config.get_abs_value(opt_key);
double extrusion_width_max = config.get_abs_value(opt_key);
if (extrusion_width_min == 0) {
// Default "auto-generated" extrusion width is always valid.
} else if (extrusion_width_min <= layer_height) {
err_msg = L("Too small line width");
return false;
} else if (extrusion_width_max > max_nozzle_diameter * 5) {
} else if (extrusion_width_max >= max_nozzle_diameter * 2.5) {
err_msg = L("Too large line width");
return false;
}
@ -1232,56 +1218,33 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
}
// Orca: G92 E0 is not supported when using absolute extruder addressing
// This check is copied from PrusaSlicer, the original author is Vojtech Bubnik
{
bool before_layer_gcode_resets_extruder =
boost::regex_search(m_config.before_layer_change_gcode.value, regex_g92e0);
bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_change_gcode.value, regex_g92e0);
if (m_config.use_relative_e_distances) {
// See GH issues #6336 #5073
if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
!before_layer_gcode_resets_extruder && !layer_gcode_resets_extruder)
return {L("Relative extruder addressing requires resetting the extruder position at each layer to "
"prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."),
nullptr, "before_layer_change_gcode"};
} else if (before_layer_gcode_resets_extruder)
return {L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder "
"addressing."),
nullptr, "before_layer_change_gcode"};
else if (layer_gcode_resets_extruder)
return {L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."),
nullptr, "layer_change_gcode"};
}
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
assert(bed_type_def != nullptr);
if (is_BBL_printer()) {
const t_config_enum_values* bed_type_keys_map = bed_type_def->enum_keys_map;
for (unsigned int extruder_id : extruders) {
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
for (unsigned int extruder_id : extruders) {
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
std::string bed_type_name;
for (auto item : *bed_type_keys_map) {
if (item.second == m_config.curr_bed_type) {
bed_type_name = item.first;
break;
}
}
const t_config_enum_values* bed_type_keys_map = bed_type_def->enum_keys_map;
for (unsigned int extruder_id : extruders) {
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
for (unsigned int extruder_id : extruders) {
int curr_bed_temp = bed_temp_opt->get_at(extruder_id);
if (curr_bed_temp == 0 && bed_type_keys_map != nullptr) {
std::string bed_type_name;
for (auto item : *bed_type_keys_map) {
if (item.second == m_config.curr_bed_type) {
bed_type_name = item.first;
break;
}
}
StringObjectException except;
except.string = format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
except.string += "\n";
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
except.params.push_back(std::to_string(this->get_plate_index() + 1));
except.params.push_back(L(bed_type_name));
except.params.push_back(std::to_string(extruder_id+1));
except.object = nullptr;
return except;
}
StringObjectException except;
except.string = format(L("Plate %d: %s does not support filament %s"), this->get_plate_index() + 1, L(bed_type_name), extruder_id + 1);
except.string += "\n";
except.type = STRING_EXCEPT_FILAMENT_NOT_MATCH_BED_TYPE;
except.params.push_back(std::to_string(this->get_plate_index() + 1));
except.params.push_back(L(bed_type_name));
except.params.push_back(std::to_string(extruder_id+1));
except.object = nullptr;
return except;
}
}
}
@ -1353,10 +1316,10 @@ double Print::skirt_first_layer_height() const
Flow Print::brim_flow() const
{
ConfigOptionFloatOrPercent width = m_config.initial_layer_line_width;
if (width.value <= 0)
ConfigOptionFloat width = m_config.initial_layer_line_width;
if (width.value == 0)
width = m_print_regions.front()->config().inner_wall_line_width;
if (width.value <= 0)
if (width.value == 0)
width = m_objects.front()->config().line_width;
/* We currently use a random region's perimeter extruder.
@ -1366,7 +1329,6 @@ Flow Print::brim_flow() const
generation as well. */
return Flow::new_from_config_width(
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().wall_filament-1),
(float)this->skirt_first_layer_height());
@ -1374,8 +1336,8 @@ Flow Print::brim_flow() const
Flow Print::skirt_flow() const
{
ConfigOptionFloatOrPercent width = m_config.initial_layer_line_width;
if (width.value <= 0)
ConfigOptionFloat width = m_config.initial_layer_line_width;
if (width.value == 0)
width = m_objects.front()->config().line_width;
/* We currently use a random object's support material extruder.
@ -1385,7 +1347,6 @@ Flow Print::skirt_flow() const
generation as well. */
return Flow::new_from_config_width(
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_objects.front()->config().support_filament-1),
(float)this->skirt_first_layer_height());
@ -1776,7 +1737,7 @@ void Print::process(bool use_cache)
// BBS: m_brimMap and m_supportBrimMap are used instead of m_brim to generate brim of objs and supports seperately
m_brimMap.clear();
m_supportBrimMap.clear();
m_first_layer_convex_hull.points.clear();
m_first_layer_convex_hull.points.clear(); // BBS: plate offset is contained in this convexhull
if (this->has_brim()) {
Polygons islands_area;
make_brim(*this, this->make_try_cancel(), islands_area, m_brimMap,
@ -1805,8 +1766,8 @@ void Print::process(bool use_cache)
obj->simplify_extrusion_path();
}
else {
if (obj->set_started(posSimplifyPath))
obj->set_done(posSimplifyPath);
if (obj->set_started(posSimplifyWall))
obj->set_done(posSimplifyWall);
if (obj->set_started(posSimplifyInfill))
obj->set_done(posSimplifyInfill);
if (obj->set_started(posSimplifySupportPath))
@ -2109,15 +2070,16 @@ std::vector<Point> Print::first_layer_wipe_tower_corners(bool check_wipe_tower_e
return corners;
}
//SoftFever
Vec2d Print::translate_to_print_space(const Vec2d &point) const {
//OrcaSlicer
Vec2d Print::translate_to_print_space(const Vec2d& point) const {
//const BoundingBoxf bed_bbox(config().printable_area.values);
return Vec2d(point(0) - m_origin(0), point(1) - m_origin(1));
}
Vec2d Print::translate_to_print_space(const Point &point) const {
Vec2d Print::translate_to_print_space(const Point& point) const {
return Vec2d(unscaled(point.x()) - m_origin(0), unscaled(point.y()) - m_origin(1));
}
void Print::finalize_first_layer_convex_hull()
{
append(m_first_layer_convex_hull.points, m_skirt_convex_hull);

View file

@ -14,14 +14,14 @@
#include "GCode/ThumbnailData.hpp"
#include "GCode/GCodeProcessor.hpp"
#include "MultiMaterialSegmentation.hpp"
#include "libslic3r.h"
#include <Eigen/Geometry>
#include <functional>
#include <set>
#include "calib.hpp"
#include "Calib.hpp"
namespace Slic3r {
@ -87,9 +87,9 @@ enum PrintStep {
enum PrintObjectStep {
posSlice, posPerimeters, posPrepareInfill,
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
posInfill, posIroning, posSupportMaterial,
// BBS
posSimplifyInfill,
posSimplifyWall, posSimplifyInfill, posSimplifySupportPath,
posDetectOverhangsForLift,
posCount,
};
@ -194,11 +194,11 @@ struct PrintInstance
const ModelInstance *model_instance;
// Shift of this instance's center into the world coordinates.
Point shift;
BoundingBoxf3 get_bounding_box();
Polygon get_convex_hull_2d();
// SoftFever
//
// OrcaSlicer
//
// instance id
size_t id;
@ -305,7 +305,7 @@ public:
Transform3d trafo_centered() const
{ Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale<double>(m_center_offset.x()), - unscale<double>(m_center_offset.y()), 0)); return t; }
const PrintInstances& instances() const { return m_instances; }
PrintInstances &instances() { return m_instances; }
PrintInstances& instances() { return m_instances; }
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
LayerPtrs& layers() { return m_layers; }
@ -434,11 +434,11 @@ public:
// BBS: Boundingbox of the first layer
BoundingBox firstLayerObjectBrimBoundingBox;
// SoftFever
size_t get_id() const { return m_id; }
void set_id(size_t id) { m_id = id; }
// OrcaSlicer
size_t get_klipper_object_id() const { return m_klipper_object_id; }
void set_klipper_object_id(size_t id) { m_klipper_object_id = id; }
private:
private:
// to be called from Print only.
friend class Print;
@ -522,12 +522,10 @@ private:
PrintObject* m_shared_object{ nullptr };
// SoftFever
//
// object id
size_t m_id;
void apply_conical_overhang();
// OrcaSlicer
//
// object id for klipper firmware only
size_t m_klipper_object_id;
public:
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
@ -739,7 +737,7 @@ public:
const PrintConfig& config() const { return m_config; }
const PrintObjectConfig& default_object_config() const { return m_default_object_config; }
const PrintRegionConfig& default_region_config() const { return m_default_region_config; }
const PrintRegionConfig& default_region_config() const { return m_default_region_config; }
ConstPrintObjectPtrsAdaptor objects() const { return ConstPrintObjectPtrsAdaptor(&m_objects); }
PrintObject* get_object(size_t idx) { return const_cast<PrintObject*>(m_objects[idx]); }
const PrintObject* get_object(size_t idx) const { return m_objects[idx]; }
@ -797,6 +795,8 @@ public:
int get_modified_count() const {return m_modified_count;}
//BBS: add status for whether support used
bool is_support_used() const {return m_support_used;}
bool is_BBL_Printer() const { return m_isBBLPrinter;}
void set_BBL_Printer(const bool isBBL) { m_isBBLPrinter = isBBL;}
std::string get_conflict_string() const
{
std::string result;
@ -806,28 +806,23 @@ public:
return result;
}
//BBS
static StringObjectException sequential_print_clearance_valid(const Print &print, Polygons *polygons = nullptr, std::vector<std::pair<Polygon, float>>* height_polygons = nullptr);
ConflictResultOpt get_conflict_result() const { return m_conflict_result; }
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
//SoftFever
bool &is_BBL_printer() { return m_isBBLPrinter; }
const bool is_BBL_printer() const { return m_isBBLPrinter; }
CalibMode& calib_mode() { return m_calib_params.mode; }
const CalibMode calib_mode() const { return m_calib_params.mode; }
void set_calib_params(const Calib_Params& params);
//OrcaSlicer
CalibMode & calib_mode() { return m_calib_params.mode; }
const CalibMode& calib_mode() const { return m_calib_params.mode; }
void set_calib_params(const Calib_Params &params);
const Calib_Params& calib_params() const { return m_calib_params; }
Vec2d translate_to_print_space(const Vec2d &point) const;
Vec2d translate_to_print_space(const Vec2d& point) const;
// scaled point
Vec2d translate_to_print_space(const Point &point) const;
Vec2d translate_to_print_space(const Point& point) const;
static bool check_multi_filaments_compatibility(const std::vector<std::string>& filament_types);
protected:
protected:
// Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step);
@ -849,10 +844,8 @@ private:
PrintRegionConfig m_default_region_config;
PrintObjectPtrs m_objects;
PrintRegionPtrs m_print_regions;
//SoftFever
bool m_isBBLPrinter;
//BBS.
bool m_isBBLPrinter = false;
// Ordered collections of extrusion paths to build skirt loops and brim.
ExtrusionEntityCollection m_skirt;
// BBS: collecting extrusion paths to build brim by objs
@ -881,8 +874,8 @@ private:
//BBS
ConflictResultOpt m_conflict_result;
FakeWipeTower m_fake_wipe_tower;
//SoftFever: calibration
// OrcaSlicer: calibration
Calib_Params m_calib_params;
// To allow GCode to set the Print's GCodeExport step status.

View file

@ -581,7 +581,7 @@ static void transformed_its_bboxes_in_z_ranges(
if (p2->z() <= z_range.first || p1->z() >= z_range.second) {
// Out of this slab.
} else if (p1->z() < z_range.first) {
if (p1->z() > z_range.second) {
if (p2->z() > z_range.second) {
// Two intersections.
float zspan = p2->z() - p1->z();
float t1 = (z_range.first - p1->z()) / zspan;

View file

@ -516,9 +516,9 @@ public:
bool get_no_check_flag() const { return m_no_check; }
void set_no_check_flag(bool no_check) { m_no_check = no_check; }
//SoftFever plate name
std::string get_plate_name() const { return m_plate_name; }
void set_plate_name(const std::string& name) { m_plate_name = name; }
void set_plate_name(const std::string &name) { m_plate_name = name; }
protected:
friend class PrintObjectBase;
friend class BackgroundSlicingProcess;
@ -554,9 +554,8 @@ protected:
int m_plate_index{ 0 };
bool m_no_check = false;
// SoftFever: current plate name
std::string m_plate_name;
// current plate name
std::string m_plate_name; // utf8 string
// Callback to be evoked regularly to update state of the UI thread.
status_callback_type m_status_callback;

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,7 @@
namespace Slic3r {
enum GCodeFlavor : unsigned char {
gcfMarlinLegacy, gcfKlipper, gcfRepRapFirmware, gcfRepRapSprinter, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
gcfMarlinLegacy, gcfKlipper, gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
gcfSmoothie, gcfNoExtrusion
};
@ -129,12 +129,6 @@ enum SeamPosition {
spNearest, spAligned, spRear, spRandom
};
enum LiftType {
NormalLift,
SpiralLift,
LazyLift
};
enum SLAMaterial {
slamTough,
slamFlex,
@ -156,7 +150,6 @@ enum SLAPillarConnectionMode {
enum BrimType {
btAutoBrim, // BBS
btEar, // Orca
btOuterOnly,
btInnerOnly,
btOuterAndInner,
@ -181,6 +174,13 @@ enum class PerimeterGeneratorType
Arachne
};
enum class TopOneWallType
{
None,
Alltop,
Topmost
};
// BBS
enum OverhangFanThreshold {
Overhang_threshold_none = 0,
@ -219,11 +219,10 @@ enum ZHopType {
zhtCount
};
enum RetractLiftEnforceType {
rletAllSurfaces = 0,
rletTopOnly,
rletBottomOnly,
rletTopAndBottom
// BBS
enum ExtruderType {
etDirectDrive = 0,
etBowden
};
static std::string bed_type_to_gcode_string(const BedType type)
@ -312,7 +311,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TopOneWallType)
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
// Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs.
@ -641,12 +640,10 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, brim_object_gap))
((ConfigOptionEnum<BrimType>, brim_type))
((ConfigOptionFloat, brim_width))
((ConfigOptionFloat, brim_ears_detection_length))
((ConfigOptionFloat, brim_ears_max_angle))
((ConfigOptionBool, bridge_no_support))
((ConfigOptionFloat, elefant_foot_compensation))
((ConfigOptionFloat, max_bridge_length))
((ConfigOptionFloatOrPercent, line_width))
((ConfigOptionFloat, line_width))
// Force the generation of solid shells between adjacent materials/volumes.
((ConfigOptionBool, interface_shells))
((ConfigOptionFloat, layer_height))
@ -656,7 +653,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, raft_first_layer_expansion))
((ConfigOptionInt, raft_layers))
((ConfigOptionEnum<SeamPosition>, seam_position))
((ConfigOptionBool, staggered_inner_seams))
((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))
((ConfigOptionBool, enable_support))
@ -671,7 +667,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, support_bottom_z_distance))
((ConfigOptionInt, enforce_support_layers))
((ConfigOptionInt, support_filament))
((ConfigOptionFloatOrPercent, support_line_width))
((ConfigOptionFloat, support_line_width))
((ConfigOptionBool, support_interface_loop_pattern))
((ConfigOptionInt, support_interface_filament))
((ConfigOptionInt, support_interface_top_layers))
@ -703,8 +699,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, tree_support_branch_diameter))
((ConfigOptionFloat, tree_support_branch_angle))
((ConfigOptionInt, tree_support_wall_count))
((ConfigOptionBool, tree_support_adaptive_layer_height))
((ConfigOptionBool, tree_support_auto_brim))
((ConfigOptionFloat, tree_support_brim_width))
((ConfigOptionBool, detect_narrow_internal_solid_infill))
// ((ConfigOptionBool, adaptive_layer_height))
@ -717,39 +711,39 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, wall_distribution_count))
((ConfigOptionPercent, min_feature_size))
((ConfigOptionPercent, min_bead_width))
// Orca
((ConfigOptionFloat, make_overhang_printable_angle))
((ConfigOptionFloat, make_overhang_printable_hole_size))
((ConfigOptionEnum<TopOneWallType>, top_one_wall_type))
((ConfigOptionBool, only_one_wall_first_layer))
// OrcaSlicer
((ConfigOptionPercent, seam_gap))
((ConfigOptionPercent, wipe_speed))
)
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
PRINT_CONFIG_CLASS_DEFINE(
PrintRegionConfig,
((ConfigOptionInt, bottom_shell_layers))
((ConfigOptionFloat, bottom_shell_thickness))
((ConfigOptionFloat, bridge_angle))
((ConfigOptionFloat, bridge_flow))
((ConfigOptionFloat, bridge_speed))
((ConfigOptionFloatOrPercent, internal_bridge_speed))
((ConfigOptionBool, ensure_vertical_shell_thickness))
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionInt, bottom_shell_layers))
((ConfigOptionFloat, bottom_shell_thickness))
((ConfigOptionFloat, bridge_angle))
((ConfigOptionFloat, bridge_flow))
((ConfigOptionFloat, bridge_speed))
((ConfigOptionBool, ensure_vertical_shell_thickness))
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))
((ConfigOptionFloatOrPercent, outer_wall_line_width))
((ConfigOptionFloat, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionPercent, sparse_infill_density))
((ConfigOptionEnum<InfillPattern>, sparse_infill_pattern))
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
((ConfigOptionFloat, fuzzy_skin_thickness))
((ConfigOptionFloat, fuzzy_skin_point_distance))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament))
((ConfigOptionFloatOrPercent, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionFloat, sparse_infill_speed))
((ConfigOptionFloat, outer_wall_line_width))
((ConfigOptionFloat, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionPercent, sparse_infill_density))
((ConfigOptionEnum<InfillPattern>, sparse_infill_pattern))
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
((ConfigOptionFloat, fuzzy_skin_thickness))
((ConfigOptionFloat, fuzzy_skin_point_distance))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament))
((ConfigOptionFloat, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionFloat, sparse_infill_speed))
//BBS
((ConfigOptionBool, infill_combination))
// Ironing options
@ -761,51 +755,34 @@ PRINT_CONFIG_CLASS_DEFINE(
// Detect bridging perimeters
((ConfigOptionBool, detect_overhang_wall))
((ConfigOptionInt, wall_filament))
((ConfigOptionFloatOrPercent, inner_wall_line_width))
((ConfigOptionFloat, inner_wall_line_width))
((ConfigOptionFloat, inner_wall_speed))
// Total number of perimeters.
((ConfigOptionInt, wall_loops))
((ConfigOptionFloat, minimum_sparse_infill_area))
((ConfigOptionInt, solid_infill_filament))
((ConfigOptionFloatOrPercent, internal_solid_infill_line_width))
((ConfigOptionFloat, internal_solid_infill_line_width))
((ConfigOptionFloat, internal_solid_infill_speed))
// Detect thin walls.
((ConfigOptionBool, detect_thin_wall))
((ConfigOptionFloatOrPercent, top_surface_line_width))
((ConfigOptionFloat, top_surface_line_width))
((ConfigOptionInt, top_shell_layers))
((ConfigOptionFloat, top_shell_thickness))
((ConfigOptionFloat, top_surface_speed))
//BBS
((ConfigOptionBool, enable_overhang_speed))
((ConfigOptionFloatOrPercent, overhang_1_4_speed))
((ConfigOptionFloatOrPercent, overhang_2_4_speed))
((ConfigOptionFloatOrPercent, overhang_3_4_speed))
((ConfigOptionFloatOrPercent, overhang_4_4_speed))
((ConfigOptionBool, only_one_wall_top))
//SoftFever
((ConfigOptionFloatOrPercent, min_width_top_surface))
((ConfigOptionBool, only_one_wall_first_layer))
((ConfigOptionFloat, print_flow_ratio))
((ConfigOptionFloatOrPercent, seam_gap))
((ConfigOptionBool, role_based_wipe_speed))
((ConfigOptionFloatOrPercent, wipe_speed))
((ConfigOptionBool, wipe_on_loops))
((ConfigOptionEnum<WallInfillOrder>, wall_infill_order))
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionBool, overhang_speed_classic))
((ConfigOptionPercent, bridge_density))
((ConfigOptionFloat, filter_out_gap_fill))
((ConfigOptionFloatOrPercent, small_perimeter_speed))
((ConfigOptionFloat, small_perimeter_threshold))
((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
((ConfigOptionFloatOrPercent, infill_anchor))
((ConfigOptionFloatOrPercent, infill_anchor_max))
// Orca
((ConfigOptionBool, make_overhang_printable))
)
((ConfigOptionBool, enable_overhang_speed))
((ConfigOptionFloat, overhang_1_4_speed))
((ConfigOptionFloat, overhang_2_4_speed))
((ConfigOptionFloat, overhang_3_4_speed))
((ConfigOptionFloat, overhang_4_4_speed))
((ConfigOptionFloatOrPercent, sparse_infill_anchor))
((ConfigOptionFloatOrPercent, sparse_infill_anchor_max))
//OrcaSlicer
((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, initial_layer_flow_ratio))
((ConfigOptionFloat, filter_out_gap_fill))
//calib
((ConfigOptionFloat, print_flow_ratio)))
PRINT_CONFIG_CLASS_DEFINE(
MachineEnvelopeConfig,
@ -850,9 +827,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, filament_flow_ratio))
((ConfigOptionBools, enable_pressure_advance))
((ConfigOptionFloats, pressure_advance))
((ConfigOptionFloat, fan_kickstart))
((ConfigOptionBool, fan_speedup_overhangs))
((ConfigOptionFloat, fan_speedup_time))
((ConfigOptionFloats, filament_diameter))
((ConfigOptionFloats, filament_density))
((ConfigOptionStrings, filament_type))
@ -872,7 +846,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, gcode_add_line_number))
((ConfigOptionBool, bbl_bed_temperature_gcode))
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
((ConfigOptionString, layer_change_gcode))
//#ifdef HAS_PRESSURE_EQUALIZER
// ((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_positive))
@ -884,9 +857,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, z_hop))
// BBS
((ConfigOptionEnumsGeneric, z_hop_types))
((ConfigOptionFloats, retract_lift_above))
((ConfigOptionFloats, retract_lift_below))
((ConfigOptionEnumsGeneric, retract_lift_enforce))
((ConfigOptionFloats, retract_restart_extra))
((ConfigOptionFloats, retract_restart_extra_toolchange))
((ConfigOptionFloats, retraction_speed))
@ -897,21 +867,16 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionString, change_filament_gcode))
((ConfigOptionFloat, travel_speed))
((ConfigOptionFloat, travel_speed_z))
((ConfigOptionBool, use_relative_e_distances))
((ConfigOptionBool, silent_mode))
((ConfigOptionString, machine_pause_gcode))
((ConfigOptionString, template_custom_gcode))
//BBS
((ConfigOptionEnum<NozzleType>, nozzle_type))
((ConfigOptionInt, nozzle_hrc))
((ConfigOptionBool, auxiliary_fan))
// SoftFever
((ConfigOptionBool, use_firmware_retraction))
((ConfigOptionBool, use_relative_e_distances))
((ConfigOptionBool, accel_to_decel_enable))
((ConfigOptionPercent, accel_to_decel_factor))
((ConfigOptionFloatOrPercent, initial_layer_travel_speed))
((ConfigOptionBool, bbl_calib_mark_logo))
((ConfigOptionEnumsGeneric, extruder_type))
)
// This object is mapped to Perl as Slic3r::Config::Print.
@ -943,39 +908,30 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, first_layer_print_sequence))
((ConfigOptionBools, slow_down_for_layer_cooling))
((ConfigOptionFloat, default_acceleration))
((ConfigOptionFloat, inner_wall_acceleration))
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
((ConfigOptionInts, close_fan_the_first_x_layers))
((ConfigOptionEnum<DraftShield>, draft_shield))
((ConfigOptionFloat, extruder_clearance_height_to_rod))//BBs
((ConfigOptionFloat, extruder_clearance_height_to_lid))//BBS
((ConfigOptionFloat, extruder_clearance_radius))
((ConfigOptionFloat, extruder_clearance_max_radius))
((ConfigOptionStrings, extruder_colour))
((ConfigOptionPoints, extruder_offset))
((ConfigOptionBools, reduce_fan_stop_start_freq))
((ConfigOptionFloats, fan_cooling_layer_time))
((ConfigOptionInts, fan_cooling_layer_time))
((ConfigOptionStrings, filament_colour))
((ConfigOptionFloat, outer_wall_acceleration))
((ConfigOptionFloat, inner_wall_acceleration))
((ConfigOptionFloat, top_surface_acceleration))
((ConfigOptionFloat, outer_wall_acceleration))
((ConfigOptionFloat, initial_layer_acceleration))
((ConfigOptionFloatOrPercent, bridge_acceleration))
((ConfigOptionFloat, travel_acceleration))
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
((ConfigOptionFloatOrPercent, internal_solid_infill_acceleration))
((ConfigOptionFloatOrPercent, initial_layer_line_width))
((ConfigOptionFloat, initial_layer_line_width))
((ConfigOptionFloat, initial_layer_print_height))
((ConfigOptionFloat, initial_layer_speed))
((ConfigOptionFloat, default_jerk))
((ConfigOptionFloat, outer_wall_jerk))
((ConfigOptionFloat, inner_wall_jerk))
((ConfigOptionFloat, infill_jerk))
((ConfigOptionFloat, top_surface_jerk))
((ConfigOptionFloat, initial_layer_jerk))
((ConfigOptionFloat, travel_jerk))
//BBS
((ConfigOptionFloat, initial_layer_infill_speed))
((ConfigOptionInts, nozzle_temperature_initial_layer))
((ConfigOptionInts, full_fan_speed_layer))
((ConfigOptionEnum<WallInfillOrder>,wall_infill_order))
((ConfigOptionInts, fan_max_speed))
((ConfigOptionFloats, max_layer_height))
((ConfigOptionInts, fan_min_speed))
@ -994,12 +950,11 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, skirt_distance))
((ConfigOptionInt, skirt_height))
((ConfigOptionInt, skirt_loops))
((ConfigOptionFloat, skirt_speed))
((ConfigOptionFloats, slow_down_layer_time))
((ConfigOptionInts, slow_down_layer_time))
((ConfigOptionBool, spiral_mode))
((ConfigOptionInt, standby_temperature_delta))
((ConfigOptionInts, nozzle_temperature))
((ConfigOptionInts , chamber_temperature))
((ConfigOptionInts, chamber_temperatures))
((ConfigOptionBools, wipe))
// BBS
((ConfigOptionInts, bed_temperature_difference))
@ -1028,18 +983,17 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, nozzle_volume))
((ConfigOptionPoints, start_end_points))
((ConfigOptionEnum<TimelapseType>, timelapse_type))
((ConfigOptionPoints, thumbnails))
((ConfigOptionFloat, default_jerk))
((ConfigOptionFloat, outer_wall_jerk))
((ConfigOptionFloat, inner_wall_jerk))
((ConfigOptionFloat, infill_jerk))
((ConfigOptionFloat, top_surface_jerk))
((ConfigOptionFloat, initial_layer_jerk))
((ConfigOptionFloat, travel_jerk))
// BBS: move from PrintObjectConfig
((ConfigOptionBool, independent_support_layer_height))
// SoftFever
((ConfigOptionPercents, filament_shrink))
((ConfigOptionBool, gcode_label_objects))
((ConfigOptionBool, exclude_object))
((ConfigOptionBool, gcode_comments))
((ConfigOptionInt, slow_down_layers))
((ConfigOptionInts, support_material_interface_fan_speed))
((ConfigOptionBool, independent_support_layer_height))
((ConfigOptionBool, exclude_object))
)
// This object is mapped to Perl as Slic3r::Config::Full.
@ -1408,12 +1362,7 @@ public:
const ConfigOption* option(const t_config_option_key &opt_key) const { return m_data.option(opt_key); }
int opt_int(const t_config_option_key &opt_key) const { return m_data.opt_int(opt_key); }
int extruder() const { return opt_int("extruder"); }
double opt_float(const t_config_option_key &opt_key) const {
return m_data.opt_float(opt_key);
}
double get_abs_value(const t_config_option_key &opt_key) const {
return m_data.get_abs_value(opt_key);
}
double opt_float(const t_config_option_key &opt_key) const { return m_data.opt_float(opt_key); }
std::string opt_serialize(const t_config_option_key &opt_key) const { return m_data.opt_serialize(opt_key); }
// Return an optional timestamp of this object.

View file

@ -423,10 +423,7 @@ static const float g_min_overhang_percent_for_lift = 0.3f;
void PrintObject::detect_overhangs_for_lift()
{
if (this->set_started(posDetectOverhangsForLift)) {
const double nozzle_diameter = m_print->config().nozzle_diameter.get_at(0);
const coordf_t line_width = this->config().get_abs_value("line_width", nozzle_diameter);
const float min_overlap = line_width * g_min_overhang_percent_for_lift;
const float min_overlap = m_config.line_width * g_min_overhang_percent_for_lift;
size_t num_layers = this->layer_count();
size_t num_raft_layers = m_slicing_params.raft_layers();
@ -436,18 +433,17 @@ void PrintObject::detect_overhangs_for_lift()
tbb::spin_mutex layer_storage_mutex;
tbb::parallel_for(tbb::blocked_range<size_t>(num_raft_layers + 1, num_layers),
[this, min_overlap, line_width](const tbb::blocked_range<size_t>& range)
[this, min_overlap](const tbb::blocked_range<size_t>& range)
{
for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) {
Layer& layer = *m_layers[layer_id];
Layer& lower_layer = *layer.lower_layer;
ExPolygons overhangs = diff_ex(layer.lslices, offset_ex(lower_layer.lslices, scale_(min_overlap)));
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(line_width), 0.1f * scale_(line_width)));
layer.loverhangs = std::move(offset2_ex(overhangs, -0.1f * scale_(m_config.line_width), 0.1f * scale_(m_config.line_width)));
layer.loverhangs_bbox = get_extents(layer.loverhangs);
}
});
this->set_done(posDetectOverhangsForLift);
}
}
@ -499,10 +495,10 @@ void PrintObject::generate_support_material()
void PrintObject::simplify_extrusion_path()
{
if (this->set_started(posSimplifyPath)) {
if (this->set_started(posSimplifyWall)) {
m_print->set_status(75, L("Optimizing toolpath"));
BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of object in parallel - start";
//BBS: infill and walls
BOOST_LOG_TRIVIAL(debug) << "Simplify wall extrusion path of object in parallel - start";
//BBS: walls
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this](const tbb::blocked_range<size_t>& range) {
@ -514,7 +510,7 @@ void PrintObject::simplify_extrusion_path()
);
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Simplify wall extrusion path of object in parallel - end";
this->set_done(posSimplifyPath);
this->set_done(posSimplifyWall);
}
if (this->set_started(posSimplifyInfill)) {
@ -694,12 +690,8 @@ bool PrintObject::invalidate_state_by_config_options(
if ( opt_key == "brim_width"
|| opt_key == "brim_object_gap"
|| opt_key == "brim_type"
|| opt_key == "brim_ears_max_angle"
|| opt_key == "brim_ears_detection_length"
// BBS: brim generation depends on printing speed
|| opt_key == "outer_wall_speed"
|| opt_key == "small_perimeter_speed"
|| opt_key == "small_perimeter_threshold"
|| opt_key == "sparse_infill_speed"
|| opt_key == "inner_wall_speed"
|| opt_key == "support_speed"
@ -717,18 +709,13 @@ bool PrintObject::invalidate_state_by_config_options(
}
} else if (
opt_key == "wall_loops"
|| opt_key == "only_one_wall_top"
|| opt_key == "top_one_wall_type"
|| opt_key == "only_one_wall_first_layer"
|| opt_key == "initial_layer_line_width"
|| opt_key == "inner_wall_line_width"
|| opt_key == "infill_wall_overlap"
|| opt_key == "seam_gap"
|| opt_key == "role_based_wipe_speed"
|| opt_key == "wipe_on_loops"
|| opt_key == "wipe_speed") {
|| opt_key == "infill_wall_overlap") {
steps.emplace_back(posPerimeters);
} else if (opt_key == "gap_infill_speed"
|| opt_key == "filter_out_gap_fill" ) {
} else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") {
// Return true if gap-fill speed has changed from zero value to non-zero or from non-zero value to zero.
auto is_gap_fill_changed_state_due_to_speed = [&opt_key, &old_config, &new_config]() -> bool {
if (opt_key == "gap_infill_speed") {
@ -742,9 +729,9 @@ bool PrintObject::invalidate_state_by_config_options(
};
// Filtering of unprintable regions in multi-material segmentation depends on if gap-fill is enabled or not.
// So step posSlice is invalidated when gap-fill was enabled/disabled by option "filter_out_gap_fill" or by
// So step posSlice is invalidated when gap-fill was enabled/disabled by option "gap_fill_enabled" or by
// changing "gap_infill_speed" to force recomputation of the multi-material segmentation.
if (this->is_mm_painted() && (opt_key == "filter_out_gap_fill" && (opt_key == "gap_infill_speed" && is_gap_fill_changed_state_due_to_speed())))
if (this->is_mm_painted() && ((opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill") && is_gap_fill_changed_state_due_to_speed()))
steps.emplace_back(posSlice);
steps.emplace_back(posPerimeters);
} else if (
@ -752,24 +739,14 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "raft_layers"
|| opt_key == "raft_contact_distance"
|| opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode"
|| opt_key == "make_overhang_printable"
|| opt_key == "make_overhang_printable_angle"
|| opt_key == "make_overhang_printable_hole_size") {
|| opt_key == "slicing_mode") {
steps.emplace_back(posSlice);
} else if (
opt_key == "elefant_foot_compensation"
|| opt_key == "support_top_z_distance"
|| opt_key == "support_bottom_z_distance"
|| opt_key == "xy_hole_compensation"
|| opt_key == "xy_contour_compensation"
//BBS: [Arthur] the following params affect bottomBridge surface type detection
|| opt_key == "support_type"
|| opt_key == "bridge_no_support"
|| opt_key == "max_bridge_length"
|| opt_key == "support_interface_top_layers"
|| opt_key == "support_critical_regions_only"
) {
|| opt_key == "xy_contour_compensation") {
steps.emplace_back(posSlice);
} else if (opt_key == "enable_support") {
steps.emplace_back(posSupportMaterial);
@ -809,12 +786,10 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "bridge_no_support"
|| opt_key == "max_bridge_length"
|| opt_key == "initial_layer_line_width"
|| opt_key == "tree_support_adaptive_layer_height"
|| opt_key == "tree_support_auto_brim"
|| opt_key == "tree_support_brim_width"
|| opt_key == "tree_support_branch_distance"
|| opt_key == "tree_support_branch_diameter"
|| opt_key == "tree_support_branch_angle"
|| opt_key == "tree_support_brim_width"
|| opt_key == "tree_support_wall_count") {
steps.emplace_back(posSupportMaterial);
} else if (
@ -847,21 +822,19 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "sparse_infill_filament"
|| opt_key == "solid_infill_filament"
|| opt_key == "sparse_infill_line_width"
|| opt_key == "infill_direction"
|| opt_key == "ensure_vertical_shell_thickness"
|| opt_key == "bridge_angle"
//BBS
|| opt_key == "internal_bridge_support_thickness"
|| opt_key == "bridge_density") {
|| opt_key == "internal_bridge_support_thickness") {
steps.emplace_back(posPrepareInfill);
} else if (
opt_key == "top_surface_pattern"
|| opt_key == "bottom_surface_pattern"
|| opt_key == "internal_solid_infill_pattern"
|| opt_key == "external_fill_link_max_length"
|| opt_key == "sparse_infill_pattern"
|| opt_key == "infill_anchor"
|| opt_key == "infill_anchor_max"
|| opt_key == "infill_direction"
|| opt_key == "sparse_infill_anchor"
|| opt_key == "sparse_infill_anchor_max"
|| opt_key == "top_surface_line_width"
|| opt_key == "initial_layer_line_width") {
steps.emplace_back(posInfill);
@ -898,9 +871,7 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "detect_overhang_wall"
//BBS
|| opt_key == "enable_overhang_speed"
|| opt_key == "detect_thin_wall"
|| opt_key == "precise_outer_wall"
|| opt_key == "overhang_speed_classic") {
|| opt_key == "detect_thin_wall") {
steps.emplace_back(posPerimeters);
steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bridge_flow") {
@ -922,6 +893,8 @@ bool PrintObject::invalidate_state_by_config_options(
steps.emplace_back(posSlice);
} else if (
opt_key == "seam_position"
|| opt_key == "seam_gap"
|| opt_key == "wipe_speed"
|| opt_key == "support_speed"
|| opt_key == "support_interface_speed"
|| opt_key == "overhang_1_4_speed"
@ -929,10 +902,7 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "overhang_3_4_speed"
|| opt_key == "overhang_4_4_speed"
|| opt_key == "bridge_speed"
|| opt_key == "internal_bridge_speed"
|| opt_key == "outer_wall_speed"
|| opt_key == "small_perimeter_speed"
|| opt_key == "small_perimeter_threshold"
|| opt_key == "sparse_infill_speed"
|| opt_key == "inner_wall_speed"
|| opt_key == "internal_solid_infill_speed"
@ -963,15 +933,15 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// propagate to dependent steps
if (step == posPerimeters) {
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyWall, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posPrepareInfill) {
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyWall, posSimplifyInfill });
} else if (step == posInfill) {
invalidated |= this->invalidate_steps({ posIroning, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posSlice) {
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyWall, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false;
} else if (step == posSupportMaterial) {
@ -2646,7 +2616,6 @@ SupportNecessaryType PrintObject::is_support_necessary()
#if 0
double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.;
int enforce_support_layers = m_config.enforce_support_layers;
// not fixing in extrusion width % PR b/c never called
const coordf_t extrusion_width = m_config.line_width.value;
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
float max_bridge_length = scale_(m_config.max_bridge_length.value);

View file

@ -164,27 +164,27 @@ SlicingParameters SlicingParameters::create_from_config(
// Convert layer_config_ranges to layer_height_profile. Both are referenced to z=0, meaning the raft layers are not accounted for
// in the height profile and the printed object may be lifted by the raft thickness at the time of the G-code generation.
std::vector<coordf_t> layer_height_profile_from_ranges(
const SlicingParameters &slicing_params,
const t_layer_config_ranges &layer_config_ranges)
const SlicingParameters& slicing_params,
const t_layer_config_ranges& layer_config_ranges)
{
// 1) If there are any height ranges, trim one by the other to make them non-overlapping. Insert the 1st layer if fixed.
std::vector<std::pair<t_layer_height_range,coordf_t>> ranges_non_overlapping;
std::vector<std::pair<t_layer_height_range, coordf_t>> ranges_non_overlapping;
ranges_non_overlapping.reserve(layer_config_ranges.size() * 4);
if (slicing_params.first_object_layer_height_fixed())
ranges_non_overlapping.push_back(std::pair<t_layer_height_range,coordf_t>(
t_layer_height_range(0., slicing_params.first_object_layer_height),
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(
t_layer_height_range(0., slicing_params.first_object_layer_height),
slicing_params.first_object_layer_height));
// The height ranges are sorted lexicographically by low / high layer boundaries.
for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++ it_range) {
for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++it_range) {
coordf_t lo = it_range->first.first;
coordf_t hi = std::min(it_range->first.second, slicing_params.object_print_z_height());
coordf_t height = it_range->second.option("layer_height")->getFloat();
if (! ranges_non_overlapping.empty())
if (!ranges_non_overlapping.empty())
// Trim current low with the last high.
lo = std::max(lo, ranges_non_overlapping.back().first.second);
if (lo + EPSILON < hi)
// Ignore too narrow ranges.
ranges_non_overlapping.push_back(std::pair<t_layer_height_range,coordf_t>(t_layer_height_range(lo, hi), height));
ranges_non_overlapping.push_back(std::pair<t_layer_height_range, coordf_t>(t_layer_height_range(lo, hi), height));
}
// 2) Convert the trimmed ranges to a height profile, fill in the undefined intervals between z=0 and z=slicing_params.object_print_z_max()
@ -233,7 +233,7 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
lh_append(slicing_params.object_print_z_height(), slicing_params.layer_height);
}
return layer_height_profile;
return layer_height_profile;
}
// Based on the work of @platsch

View file

@ -25,7 +25,7 @@
#define TAU (2.0 * M_PI)
#define NO_INDEX (std::numeric_limits<unsigned int>::max())
// #define SUPPORT_TREE_DEBUG_TO_SVG
//#define SUPPORT_TREE_DEBUG_TO_SVG
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
#include "nlohmann/json.hpp"
@ -687,12 +687,12 @@ TreeSupport::TreeSupport(PrintObject& object, const SlicingParameters &slicing_p
m_object_config->support_interface_pattern == smipConcentric ?
ipConcentric :
(m_support_params.interface_density > 0.95 ? ipRectilinear : ipSupportBase);
const auto nozzle_diameter = object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1);
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(nozzle_diameter);
const coordf_t support_extrusion_width = m_object_config->support_line_width.get_abs_value(nozzle_diameter);
m_support_params.support_extrusion_width = support_extrusion_width > 0 ? support_extrusion_width : extrusion_width;
m_support_params.support_extrusion_width = m_object_config->support_line_width.value > 0 ? m_object_config->support_line_width : m_object_config->line_width;
// Check if set to zero, use default if so.
if (m_support_params.support_extrusion_width <= 0.0) {
const auto nozzle_diameter = object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament - 1);
m_support_params.support_extrusion_width = Flow::auto_extrusion_width(FlowRole::frSupportMaterial, (float)nozzle_diameter);
}
is_slim = is_tree_slim(support_type, support_style);
is_strong = is_tree(support_type) && support_style == smsTreeStrong;
MAX_BRANCH_RADIUS = 10.0;
@ -726,8 +726,7 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
const PrintObjectConfig& config = m_object->config();
SupportType stype = support_type;
const coordf_t radius_sample_resolution = g_config_tree_support_collision_resolution;
const double nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(0);
const coordf_t extrusion_width = config.get_abs_value("line_width", nozzle_diameter);
const coordf_t extrusion_width = config.line_width.value;
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
const coordf_t max_bridge_length = scale_(config.max_bridge_length.value);
const bool bridge_no_support = max_bridge_length > 0;
@ -1405,10 +1404,6 @@ void TreeSupport::generate_toolpaths()
coordf_t layer_height = object_config.layer_height.value;
const size_t wall_count = object_config.tree_support_wall_count.value;
// Check if set to zero, use default if so.
if (support_extrusion_width <= 0.0)
support_extrusion_width = Flow::auto_extrusion_width(FlowRole::frSupportMaterial, (float)nozzle_diameter);
// coconut: use same intensity settings as SupportMaterial.cpp
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
coordf_t interface_spacing = object_config.support_interface_spacing.value + m_support_material_interface_flow.spacing();
@ -1908,10 +1903,10 @@ void TreeSupport::generate()
smooth_nodes(contact_nodes);
if (!m_object->config().tree_support_adaptive_layer_height)
// Adjust support layer heights
adjust_layer_heights(contact_nodes);
#if !USE_PLAN_LAYER_HEIGHTS
// Adjust support layer heights
adjust_layer_heights(contact_nodes);
#endif
//Generate support areas.
profiler.stage_start(STAGE_DRAW_CIRCLES);
@ -2116,13 +2111,11 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
const size_t top_interface_layers = config.support_interface_top_layers.value;
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
const double diameter_angle_scale_factor = tan(tree_support_branch_diameter_angle * M_PI / 180.);// * layer_height / branch_radius; //Scale factor per layer to produce the desired angle.
const double nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(0);
const coordf_t line_width = config.get_abs_value("support_line_width", nozzle_diameter);
const coordf_t line_width_scaled = scale_(line_width);
const bool with_lightning_infill = m_support_params.base_fill_pattern == ipLightning;
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
const size_t wall_count = config.tree_support_wall_count.value;
const coordf_t line_width_scaled = scale_(support_extrusion_width);
const float tree_brim_width = config.tree_support_brim_width.value;
const PrintObjectConfig& object_config = m_object->config();
BOOST_LOG_TRIVIAL(info) << "draw_circles for object: " << m_object->model_object()->name;
@ -2212,11 +2205,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
}
}
if (layer_nr == 0 && m_raft_layers == 0) {
double brim_width =
config.tree_support_auto_brim
? layers_to_top * layer_height /
(scale * branch_radius) * 0.5
: config.tree_support_brim_width;
double brim_width = tree_brim_width > 0 ? tree_brim_width : layers_to_top * layer_height / (scale * branch_radius) * 0.5;
circle = offset(circle, scale_(brim_width))[0];
}
area.emplace_back(ExPolygon(circle));
@ -2301,7 +2290,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
if (SQUARE_SUPPORT) {
// simplify support contours
ExPolygons base_areas_simplified;
for (auto &area : base_areas) { area.simplify(scale_(line_width / 2), &base_areas_simplified); }
for (auto &area : base_areas) { area.simplify(scale_(support_extrusion_width / 2), &base_areas_simplified); }
base_areas = std::move(base_areas_simplified);
}
//Subtract support floors. We can only compute floor_areas here instead of with roof_areas,
@ -2580,14 +2569,12 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
const size_t top_interface_layers = config.support_interface_top_layers.value;
float DO_NOT_MOVER_UNDER_MM = is_slim ? 0 : 5; // do not move contact points under 5mm
const auto nozzle_diameter = m_object->print()->config().nozzle_diameter.get_at(m_object->config().support_interface_filament-1);
const auto support_line_width = config.support_line_width.get_abs_value(nozzle_diameter);
auto get_branch_angle = [this,&config](coordf_t radius) {
if (config.tree_support_branch_angle.value < 30.0) return config.tree_support_branch_angle.value;
return (radius - MIN_BRANCH_RADIUS) / (MAX_BRANCH_RADIUS - MIN_BRANCH_RADIUS) * (config.tree_support_branch_angle.value - 30.0) + 30.0;
};
auto get_max_move_dist = [this, &config, branch_radius, tip_layers, diameter_angle_scale_factor, wall_count, support_extrusion_width, support_line_width](const Node *node, int power = 1) {
auto get_max_move_dist = [this, &config, branch_radius, tip_layers, diameter_angle_scale_factor, wall_count, support_extrusion_width](const Node *node, int power = 1) {
double move_dist = node->max_move_dist;
if (node->max_move_dist == 0) {
if (node->radius == 0) node->radius = calc_branch_radius(branch_radius, node->dist_mm_to_top, diameter_angle_scale_factor);
@ -2595,7 +2582,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
if (angle > 30.0 && node->radius > MIN_BRANCH_RADIUS)
angle = (node->radius - MIN_BRANCH_RADIUS) / (MAX_BRANCH_RADIUS - MIN_BRANCH_RADIUS) * (config.tree_support_branch_angle.value - 30.0) + 30.0;
double tan_angle = tan(angle * M_PI / 180);
int wall_count_ = node->radius > 2 * support_line_width ? wall_count : 1;
int wall_count_ = node->radius > 2 * support_extrusion_width ? wall_count : 1;
node->max_move_dist = (angle < 90) ? (coordf_t) (tan_angle * node->height) * wall_count_ : std::numeric_limits<coordf_t>::max();
node->max_move_dist = std::min(node->max_move_dist, support_extrusion_width);
move_dist = node->max_move_dist;
@ -3075,7 +3062,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
}
}
}
BOOST_LOG_TRIVIAL(debug) << "after m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size();
for (Node *node : to_free_node_set)
@ -3282,7 +3269,7 @@ std::vector<LayerHeightData> TreeSupport::plan_layer_heights(std::vector<std::ve
std::vector<LayerHeightData> layer_heights(contact_nodes.size());
std::vector<int> bounds;
if (!config.tree_support_adaptive_layer_height || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
if (!USE_PLAN_LAYER_HEIGHTS || layer_height == max_layer_height || !print_config.independent_support_layer_height) {
for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) {
layer_heights[layer_nr] = {m_object->get_layer(layer_nr)->print_z, m_object->get_layer(layer_nr)->height, layer_nr > 0 ? size_t(layer_nr - 1) : 0};
}

View file

@ -9,10 +9,6 @@
#include <boost/system/error_code.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/date_time.hpp>
#include "boost/date_time/posix_time/ptime.hpp"
#include <openssl/md5.h>
#include "libslic3r.h"
@ -558,21 +554,6 @@ inline std::string get_bbl_monitor_time_dhm(float time_in_secs)
return buffer;
}
inline std::string get_bbl_monitor_end_time_dhm(float time_in_secs)
{
if (time_in_secs == 0.0f)
return {};
std::stringstream stream;
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
auto endTime = now + boost::posix_time::seconds(static_cast<int>(time_in_secs));
auto facet = new boost::posix_time::time_facet("%H:%M");//%Y-%m-%d %H:%M:%S
stream.imbue(std::locale(std::locale::classic(), facet));
stream << endTime;
return stream.str();
}
inline std::string get_bbl_remain_time_dhms(float time_in_secs)
{
int days = (int) (time_in_secs / 86400.0f);
@ -610,9 +591,6 @@ inline std::string filter_characters(const std::string& str, const std::string&
return filteredStr;
}
void copy_directory_recursively(const boost::filesystem::path &source, const boost::filesystem::path &target);
} // namespace Slic3r
#if WIN32

View file

@ -2,18 +2,29 @@
namespace Slic3r {
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance)
{
ExtrusionPaths paths;
ExtrusionPath path(role);
ThickLines lines = thick_polyline.thicklines();
ExtrusionMultiPath multi_path;
ExtrusionPath path(role);
ThickLines lines = thick_polyline.thicklines();
for (int i = 0; i < (int)lines.size(); ++i) {
const ThickLine& line = lines[i];
assert(line.a_width >= SCALED_EPSILON && line.b_width >= SCALED_EPSILON);
const coordf_t line_len = line.length();
if (line_len < SCALED_EPSILON) continue;
if (line_len < SCALED_EPSILON) {
// The line is so tiny that we don't care about its width when we connect it to another line.
if (!path.empty())
path.polyline.points.back() = line.b; // If the variable path is non-empty, connect this tiny line to it.
else if (i + 1 < (int)lines.size()) // If there is at least one following line, connect this tiny line to it.
lines[i + 1].a = line.a;
else if (!multi_path.paths.empty())
multi_path.paths.back().polyline.points.back() = line.b; // Connect this tiny line to the last finished path.
// If any of the above isn't satisfied, then remove this tiny line.
continue;
}
double thickness_delta = fabs(line.a_width - line.b_width);
if (thickness_delta > tolerance) {
@ -73,15 +84,15 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly
path.polyline.append(line.b);
} else {
// we need to initialize a new line
paths.emplace_back(std::move(path));
multi_path.paths.emplace_back(std::move(path));
path = ExtrusionPath(role);
-- i;
}
}
}
if (path.polyline.is_valid())
paths.emplace_back(std::move(path));
return paths;
multi_path.paths.emplace_back(std::move(path));
return multi_path;
}
//BBS: new function to filter width to avoid too fragmented segments

View file

@ -6,7 +6,7 @@
#include "Flow.hpp"
namespace Slic3r {
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance);
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance);
void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow& flow, std::vector<ExtrusionEntity*>& out);
}

View file

@ -1,23 +1,23 @@
#include "calib.hpp"
#include "BoundingBox.hpp"
#include "Calib.hpp"
#include "Config.hpp"
#include "Model.hpp"
#include "GCode.hpp"
#include <cmath>
namespace Slic3r {
// Calculate the optimal Pressure Advance speed
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height,
int filament_idx) {
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed,config.option<ConfigOptionFloat>("outer_wall_speed")->value), filament_max_volumetric_speed / pattern_line.mm3_per_mm());
namespace Slic3r {
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx)
{
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
Flow pattern_line = Flow(line_width, layer_height, config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0));
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),
filament_max_volumetric_speed / pattern_line.mm3_per_mm());
return std::floor(pa_speed);
}
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter& writer, std::string comment)
std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter &writer, std::string comment)
{
std::stringstream gcode;
@ -27,18 +27,12 @@ std::string CalibPressureAdvance::move_to(Vec2d pt, GCodeWriter& writer, std::st
m_last_pos = Vec3d(pt.x(), pt.y(), 0);
return gcode.str();
return gcode.str();
}
double CalibPressureAdvance::e_per_mm(
double line_width,
double layer_height,
float nozzle_diameter,
float filament_diameter,
float print_flow_ratio
) const
double CalibPressureAdvance::e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const
{
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const Flow line_flow = Flow(line_width, layer_height, nozzle_diameter);
const double filament_area = M_PI * std::pow(filament_diameter / 2, 2);
return line_flow.mm3_per_mm() / filament_area * print_flow_ratio;
@ -54,19 +48,12 @@ std::string CalibPressureAdvance::convert_number_to_string(double num) const
}
std::string CalibPressureAdvance::draw_digit(
double startx,
double starty,
char c,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
GCodeWriter& writer
)
double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer)
{
const double len = m_digit_segment_len;
const double gap = line_width / 2.0;
const auto dE = e_per_mm * len;
const auto dE = e_per_mm * len;
const auto two_dE = dE * 2;
Vec2d p0, p1, p2, p3, p4, p5;
@ -79,33 +66,33 @@ std::string CalibPressureAdvance::draw_digit(
// | | |
// | | |
// 0-------3-------4
p0 = Vec2d(startx, starty);
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx, starty + len / 2);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p1 = Vec2d(startx, starty + len);
p2 = Vec2d(startx + len, starty + len);
p3 = Vec2d(startx + len, starty);
p4 = Vec2d(startx + len * 2, starty);
p4_5 = Vec2d(startx + len * 2, starty + len / 2);
p5 = Vec2d(startx + len * 2, starty + len);
p5 = Vec2d(startx + len * 2, starty + len);
gap_p0_toward_p3 = p0 + Vec2d(gap, 0);
gap_p2_toward_p3 = p2 + Vec2d(0, gap);
dot_direction = Vec2d(-len / 2, 0);
} else {
// 0-------1
// 0-------1
// | |
// 3-------2
// | |
// 4-------5
p0 = Vec2d(startx, starty);
p0 = Vec2d(startx, starty);
p0_5 = Vec2d(startx + len / 2, starty);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p1 = Vec2d(startx + len, starty);
p2 = Vec2d(startx + len, starty - len);
p3 = Vec2d(startx, starty - len);
p4 = Vec2d(startx, starty - len * 2);
p4_5 = Vec2d(startx + len / 2, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
p5 = Vec2d(startx + len, starty - len * 2);
gap_p0_toward_p3 = p0 - Vec2d(0, gap);
gap_p2_toward_p3 = p2 - Vec2d(gap, 0);
@ -191,120 +178,71 @@ std::string CalibPressureAdvance::draw_digit(
gcode << move_to(p4_5, writer, "Glyph: .");
gcode << writer.extrude_to_xy(p4_5 + dot_direction, dE);
break;
default:
break;
default: break;
}
return gcode.str();
}
std::string CalibPressureAdvance::draw_number(
double startx,
double starty,
double value,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
double speed,
GCodeWriter& writer
)
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer)
{
auto sNumber = convert_number_to_string(value);
auto sNumber = convert_number_to_string(value);
std::stringstream gcode;
gcode << writer.set_speed(speed);
for (std::string::size_type i = 0; i < sNumber.length(); ++i) {
if (i > m_max_number_len) {
break;
}
if (i > m_max_number_len) { break; }
switch (mode) {
case DrawDigitMode::Bottom_To_Top:
gcode << draw_digit(
startx,
starty + i * number_spacing(),
sNumber[i],
mode,
line_width,
e_per_mm,
writer
);
break;
default:
gcode << draw_digit(
startx + i * number_spacing(),
starty,
sNumber[i],
mode,
line_width,
e_per_mm,
writer
);
case DrawDigitMode::Bottom_To_Top: gcode << draw_digit(startx, starty + i * number_spacing(), sNumber[i], mode, line_width, e_per_mm, writer); break;
default: gcode << draw_digit(startx + i * number_spacing(), starty, sNumber[i], mode, line_width, e_per_mm, writer);
}
}
return gcode.str();
}
CalibPressureAdvanceLine::CalibPressureAdvanceLine(GCode *gcodegen)
: mp_gcodegen(gcodegen)
, m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{
}
std::string CalibPressureAdvanceLine::generate_test(double start_pa /*= 0*/, double step_pa /*= 0.002*/, int count /*= 10*/)
{
BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values);
if (is_delta()) {
CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext);
}
if (is_delta()) { CalibPressureAdvanceLine::delta_scale_bed_ext(bed_ext); }
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
auto bed_sizes = mp_gcodegen->config().printable_area.values;
const auto &w = bed_ext.size().x();
const auto &h = bed_ext.size().y();
count = std::min(count, int((h - 10) / m_space_y));
m_length_long = 40 + std::min(w - 120.0, 0.0);
auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2;
auto starty = (h - count * m_space_y) / 2;
if (is_delta()) {
CalibPressureAdvanceLine::delta_modify_start(startx, starty, count);
}
if (is_delta()) { CalibPressureAdvanceLine::delta_modify_start(startx, starty, count); }
return print_pa_lines(startx, starty, start_pa, step_pa, count);
}
bool CalibPressureAdvanceLine::is_delta() const
{
return mp_gcodegen->config().printable_area.values.size() > 4;
}
bool CalibPressureAdvanceLine::is_delta() const { return mp_gcodegen->config().printable_area.values.size() > 4; }
std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num)
{
auto& writer = mp_gcodegen->writer();
const auto& config = mp_gcodegen->config();
auto & writer = mp_gcodegen->writer();
const auto &config = mp_gcodegen->config();
const auto filament_diameter = config.filament_diameter.get_at(0);
const auto print_flow_ratio = config.print_flow_ratio;
const auto print_flow_ratio = config.print_flow_ratio;
const double e_per_mm = CalibPressureAdvance::e_per_mm(
m_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(
m_thin_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(
m_number_line_width,
m_height_layer,
m_nozzle_diameter,
filament_diameter,
print_flow_ratio
);
const double e_per_mm = CalibPressureAdvance::e_per_mm(m_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double thin_e_per_mm = CalibPressureAdvance::e_per_mm(m_thin_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double number_e_per_mm = CalibPressureAdvance::e_per_mm(m_number_line_width, m_height_layer, m_nozzle_diameter, filament_diameter, print_flow_ratio);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
const double fast = CalibPressureAdvance::speed_adjust(m_fast_speed);
const double slow = CalibPressureAdvance::speed_adjust(m_slow_speed);
std::stringstream gcode;
gcode << mp_gcodegen->writer().travel_to_z(m_height_layer);
double y_pos = start_y;
@ -336,47 +274,28 @@ std::string CalibPressureAdvanceLine::print_pa_lines(double start_x, double star
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), thin_e_per_mm * 7);
for (int i = 0; i < num; i += 2) {
gcode << draw_number(
start_x + m_length_short + m_length_long + m_length_short + 3,
y_pos + i * m_space_y + m_space_y / 2,
start_pa + i * step_pa,
m_draw_digit_mode,
m_number_line_width,
number_e_per_mm,
3600,
writer
);
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa, m_draw_digit_mode,
m_number_line_width, number_e_per_mm, 3600, writer);
}
}
return gcode.str();
}
void CalibPressureAdvanceLine::delta_modify_start(double& startx, double& starty, int count)
void CalibPressureAdvanceLine::delta_modify_start(double &startx, double &starty, int count)
{
startx = -startx;
starty = -(count * m_space_y) / 2;
}
CalibPressureAdvancePattern::CalibPressureAdvancePattern(
const Calib_Params& params,
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
) :
m_params(params)
CalibPressureAdvancePattern::CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
: m_params(params)
{
this->m_draw_digit_mode = DrawDigitMode::Bottom_To_Top;
refresh_setup(config, is_bbl_machine, model, origin);
};
void CalibPressureAdvancePattern::generate_custom_gcodes(
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
)
void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin)
{
std::stringstream gcode;
gcode << "; start pressure advance pattern for layer\n";
@ -390,29 +309,18 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(
const DrawBoxOptArgs default_box_opt_args(*this);
// create anchoring frame
gcode << draw_box(
m_starting_point.x(),
m_starting_point.y(),
print_size_x(),
frame_size_y(),
default_box_opt_args
);
gcode << draw_box(m_starting_point.x(), m_starting_point.y(), print_size_x(), frame_size_y(), default_box_opt_args);
// create tab for numbers
DrawBoxOptArgs draw_box_opt_args = default_box_opt_args;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.is_filled = true;
draw_box_opt_args.num_perimeters = wall_count();
gcode << draw_box(
m_starting_point.x(),
m_starting_point.y() + frame_size_y() + line_spacing_first_layer(),
glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2,
draw_box_opt_args
);
gcode << draw_box(m_starting_point.x(), m_starting_point.y() + frame_size_y() + line_spacing_first_layer(), glyph_tab_max_x() - m_starting_point.x(),
max_numbering_height() + line_spacing_first_layer() + m_glyph_padding_vertical * 2, draw_box_opt_args);
std::vector<CustomGCode::Item> gcode_items;
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
const DrawLineOptArgs default_line_opt_args(*this);
const int num_patterns = get_num_patterns(); // "cache" for use in loops
// draw pressure advance pattern
for (int i = 0; i < m_num_layers; ++i) {
@ -420,13 +328,13 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(
gcode << "; end pressure advance pattern for layer\n";
CustomGCode::Item item;
item.print_z = height_first_layer() + (i - 1) * height_layer();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
gcode = std::stringstream(); // reset for next layer contents
gcode << "; start pressure advance pattern for layer\n";
const double layer_height = height_first_layer() + (i * height_layer());
gcode << m_writer.travel_to_z(layer_height, "Move to layer height");
}
@ -435,49 +343,29 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(
if (i == 1) {
gcode << m_writer.set_pressure_advance(m_params.start);
double number_e_per_mm = e_per_mm(
line_width(),
height_layer(),
m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0)
);
double number_e_per_mm = e_per_mm(line_width(), height_layer(), m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
// glyph on every other line
for (int j = 0; j < num_patterns; j += 2) {
gcode << draw_number(
glyph_start_x(j),
m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(),
m_params.start + (j * m_params.step),
m_draw_digit_mode,
line_width(),
number_e_per_mm,
speed_first_layer(),
m_writer
);
gcode << draw_number(glyph_start_x(j), m_starting_point.y() + frame_size_y() + m_glyph_padding_vertical + line_width(), m_params.start + (j * m_params.step),
m_draw_digit_mode, line_width(), number_e_per_mm, speed_first_layer(), m_writer);
}
}
DrawLineOptArgs draw_line_opt_args = default_line_opt_args;
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double to_x = m_starting_point.x() + pattern_shift();
double to_y = m_starting_point.y();
double side_length = m_wall_side_length;
// shrink first layer to fit inside frame
if (i == 0) {
double shrink =
(
line_spacing_first_layer() * (wall_count() - 1) +
(line_width_first_layer() * (1 - m_encroachment))
) / std::sin(to_radians(m_corner_angle) / 2)
;
side_length = m_wall_side_length - shrink;
double shrink = (line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment))) / std::sin(to_radians(m_corner_angle) / 2);
side_length = m_wall_side_length - shrink;
to_x += shrink * std::sin(to_radians(90) - to_radians(m_corner_angle) / 2);
to_y +=
line_spacing_first_layer() * (wall_count() - 1) +
(line_width_first_layer() * (1 - m_encroachment))
;
to_y += line_spacing_first_layer() * (wall_count() - 1) + (line_width_first_layer() * (1 - m_encroachment));
}
double initial_x = to_x;
@ -492,12 +380,12 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(
for (int k = 0; k < wall_count(); ++k) {
to_x += std::cos(to_radians(m_corner_angle) / 2) * side_length;
to_y += std::sin(to_radians(m_corner_angle) / 2) * side_length;
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
draw_line_opt_args = default_line_opt_args;
draw_line_opt_args.height = i == 0 ? height_first_layer() : height_layer();
draw_line_opt_args.line_width = line_width(); // don't use line_width_first_layer so results are consistent across all layers
draw_line_opt_args.speed = i == 0 ? speed_adjust(speed_first_layer()) : speed_adjust(speed_perimeter());
draw_line_opt_args.comment = "Print pattern wall";
gcode << draw_line(Vec2d(to_x, to_y), draw_line_opt_args);
to_x -= std::cos(to_radians(m_corner_angle) / 2) * side_length;
@ -530,23 +418,18 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(
CustomGCode::Item item;
item.print_z = max_layer_z();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
item.type = CustomGCode::Type::Custom;
item.extra = gcode.str();
gcode_items.push_back(item);
CustomGCode::Info info;
info.mode = CustomGCode::Mode::SingleExtruder;
info.mode = CustomGCode::Mode::SingleExtruder;
info.gcodes = gcode_items;
model.plates_custom_gcodes[model.curr_plate_index] = info;
}
void CalibPressureAdvancePattern::refresh_setup(
const DynamicPrintConfig& config,
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
)
void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
m_config = config;
m_config.apply(model.objects.front()->config.get(), true);
@ -558,15 +441,10 @@ void CalibPressureAdvancePattern::refresh_setup(
_refresh_writer(is_bbl_machine, model, origin);
}
void CalibPressureAdvancePattern::_refresh_starting_point(const Model& model)
void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
{
ModelObject* obj = model.objects.front();
BoundingBoxf3 bbox =
obj->instance_bounding_box(
*obj->instances.front(),
false
)
;
ModelObject * obj = model.objects.front();
BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false);
m_starting_point = Vec3d(bbox.min.x(), bbox.max.y(), 0);
m_starting_point.y() += m_handle_spacing;
@ -577,39 +455,28 @@ void CalibPressureAdvancePattern::_refresh_starting_point(const Model& model)
}
}
void CalibPressureAdvancePattern::_refresh_writer(
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
)
void CalibPressureAdvancePattern::_refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin)
{
PrintConfig print_config;
print_config.apply(m_config, true);
m_writer.apply_print_config(print_config);
m_writer.set_xy_offset(origin(0), origin(1));
m_writer.set_is_bbl_machine(is_bbl_machine);
//m_writer.set_is_bbl_machine(is_bbl_machine);
const unsigned int extruder_id = model.objects.front()->volumes.front()->extruder_id();
m_writer.set_extruders({ extruder_id });
m_writer.set_extruders({extruder_id});
m_writer.set_extruder(extruder_id);
}
std::string CalibPressureAdvancePattern::draw_line(
Vec2d to_pt,
DrawLineOptArgs opt_args
)
std::string CalibPressureAdvancePattern::draw_line(Vec2d to_pt, DrawLineOptArgs opt_args)
{
const double e_per_mm = CalibPressureAdvance::e_per_mm(
opt_args.line_width,
opt_args.height,
m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0)
);
const double e_per_mm = CalibPressureAdvance::e_per_mm(opt_args.line_width, opt_args.height, m_config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_diameter")->get_at(0),
m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0));
const double length = get_distance(Vec2d(m_last_pos.x(), m_last_pos.y()), to_pt);
auto dE = e_per_mm * length;
auto dE = e_per_mm * length;
std::stringstream gcode;
@ -621,40 +488,31 @@ std::string CalibPressureAdvancePattern::draw_line(
return gcode.str();
}
std::string CalibPressureAdvancePattern::draw_box(
double min_x,
double min_y,
double size_x,
double size_y,
DrawBoxOptArgs opt_args
)
std::string CalibPressureAdvancePattern::draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args)
{
std::stringstream gcode;
double x = min_x;
double y = min_y;
double x = min_x;
double y = min_y;
const double max_x = min_x + size_x;
const double max_y = min_y + size_y;
const double spacing = opt_args.line_width - opt_args.height * (1 - M_PI / 4);
// if number of perims exceeds size of box, reduce it to max
const int max_perimeters =
std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45)))
)
;
const int max_perimeters = std::min(
// this is the equivalent of number of perims for concentric fill
std::floor(size_x * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))),
std::floor(size_y * std::sin(to_radians(45))) / (spacing / std::sin(to_radians(45))));
opt_args.num_perimeters = std::min(opt_args.num_perimeters, max_perimeters);
gcode << move_to(Vec2d(min_x, min_y), m_writer, "Move to box start");
DrawLineOptArgs line_opt_args(*this);
line_opt_args.height = opt_args.height;
line_opt_args.height = opt_args.height;
line_opt_args.line_width = opt_args.line_width;
line_opt_args.speed = opt_args.speed;
line_opt_args.speed = opt_args.speed;
for (int i = 0; i < opt_args.num_perimeters; ++i) {
if (i != 0) { // after first perimeter, step inwards to start next perimeter
@ -680,23 +538,18 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
if (!opt_args.is_filled) {
return gcode.str();
}
if (!opt_args.is_filled) { return gcode.str(); }
// create box infill
const double spacing_45 = spacing / std::sin(to_radians(45));
const double bound_modifier =
(spacing * (opt_args.num_perimeters - 1)) +
(opt_args.line_width * (1 - m_encroachment))
;
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
const double bound_modifier = (spacing * (opt_args.num_perimeters - 1)) + (opt_args.line_width * (1 - m_encroachment));
const double x_min_bound = min_x + bound_modifier;
const double x_max_bound = max_x - bound_modifier;
const double y_min_bound = min_y + bound_modifier;
const double y_max_bound = max_y - bound_modifier;
const int x_count = std::floor((x_max_bound - x_min_bound) / spacing_45);
const int y_count = std::floor((y_max_bound - y_min_bound) / spacing_45);
double x_remainder = std::fmod((x_max_bound - x_min_bound), spacing_45);
double y_remainder = std::fmod((y_max_bound - y_min_bound), spacing_45);
@ -706,7 +559,8 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Move to fill start");
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0); ++i) { // this isn't the most robust way, but less expensive than finding line intersections
for (int i = 0; i < x_count + y_count + (x_remainder + y_remainder >= spacing_45 ? 1 : 0);
++i) { // this isn't the most robust way, but less expensive than finding line intersections
if (i < std::min(x_count, y_count)) {
if (i % 2 == 0) {
x += spacing_45;
@ -714,7 +568,7 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y += x - x_min_bound;
x = x_min_bound;
x = x_min_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -723,7 +577,7 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x += y - y_min_bound;
y = y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -736,7 +590,7 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x -= y_max_bound - y_min_bound;
y = y_max_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -748,9 +602,9 @@ std::string CalibPressureAdvancePattern::draw_box(
}
y = y_max_bound;
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
x += y_max_bound - y_min_bound;
y = y_min_bound;
y = y_min_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -792,7 +646,7 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step up");
x -= y_max_bound - y;
y = y_max_bound;
y = y_max_bound;
line_opt_args.comment = "Fill: Print up/left";
gcode << draw_line(Vec2d(x, y), line_opt_args);
} else {
@ -805,7 +659,7 @@ std::string CalibPressureAdvancePattern::draw_box(
gcode << move_to(Vec2d(x, y), m_writer, "Fill: Step right");
y -= x_max_bound - x;
x = x_max_bound;
x = x_max_bound;
line_opt_args.comment = "Fill: Print down/right";
gcode << draw_line(Vec2d(x, y), line_opt_args);
}
@ -815,26 +669,17 @@ std::string CalibPressureAdvancePattern::draw_box(
return gcode.str();
}
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const
{
return std::hypot((to.x() - from.x()), (to.y() - from.y()));
}
double CalibPressureAdvancePattern::get_distance(Vec2d from, Vec2d to) const { return std::hypot((to.x() - from.x()), (to.y() - from.y())); }
double CalibPressureAdvancePattern::object_size_x() const
{
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) +
(get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length +
line_spacing_first_layer() * wall_count()
;
return get_num_patterns() * ((wall_count() - 1) * line_spacing_angle()) + (get_num_patterns() - 1) * (m_pattern_spacing + line_width()) +
std::cos(to_radians(m_corner_angle) / 2) * m_wall_side_length + line_spacing_first_layer() * wall_count();
}
double CalibPressureAdvancePattern::object_size_y() const
{
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) +
max_numbering_height() +
m_glyph_padding_vertical * 2 +
line_width_first_layer();
return 2 * (std::sin(to_radians(m_corner_angle) / 2) * m_wall_side_length) + max_numbering_height() + m_glyph_padding_vertical * 2 + line_width_first_layer();
}
double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
@ -843,16 +688,14 @@ double CalibPressureAdvancePattern::glyph_start_x(int pattern_i) const
// align glyph's start with first perimeter of specified pattern
double x =
// starting offset
m_starting_point.x() +
pattern_shift() +
m_starting_point.x() + pattern_shift() +
// width of pattern extrusions
pattern_i * (wall_count() - 1) * line_spacing_angle() + // center to center distance of extrusions
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
pattern_i * line_width() + // endcaps. center to end on either side = 1 line width
// space between each pattern
pattern_i * m_pattern_spacing
;
pattern_i * m_pattern_spacing;
// align to middle of pattern walls
x += wall_count() * line_spacing_angle() / 2;
@ -873,35 +716,26 @@ double CalibPressureAdvancePattern::glyph_length_x() const
double CalibPressureAdvancePattern::glyph_tab_max_x() const
{
// only every other glyph is shown, starting with 1
int num = get_num_patterns();
int max_num =
(num % 2 == 0)
? num - 1
: num
;
int num = get_num_patterns();
int max_num = (num % 2 == 0) ? num - 1 : num;
// padding at end should be same as padding at start
double padding = glyph_start_x(0) - m_starting_point.x();
return
glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) +
padding
;
return glyph_start_x(max_num - 1) + // glyph_start_x is zero-based
(glyph_length_x() - line_width() / 2) + padding;
}
double CalibPressureAdvancePattern::max_numbering_height() const
{
std::string::size_type most_characters = 0;
const int num_patterns = get_num_patterns();
const int num_patterns = get_num_patterns();
// note: only every other number is printed
for (std::string::size_type i = 0; i < num_patterns; i += 2) {
std::string sNumber = convert_number_to_string(m_params.start + (i * m_params.step));
if (sNumber.length() > most_characters) {
most_characters = sNumber.length();
}
if (sNumber.length() > most_characters) { most_characters = sNumber.length(); }
}
most_characters = std::min(most_characters, m_max_number_len);
@ -909,12 +743,6 @@ double CalibPressureAdvancePattern::max_numbering_height() const
return (most_characters * m_digit_segment_len) + ((most_characters - 1) * m_digit_gap_len);
}
double CalibPressureAdvancePattern::pattern_shift() const
{
return
(wall_count() - 1) * line_spacing_first_layer() +
line_width_first_layer() +
m_glyph_padding_horizontal
;
}
double CalibPressureAdvancePattern::pattern_shift() const { return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; }
} // namespace Slic3r

View file

@ -1,157 +1,215 @@
#pragma once
#define calib_pressure_advance_dd
#include "GCode.hpp"
#include "GCodeWriter.hpp"
#include "PrintConfig.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
class GCode;
class Model;
enum class CalibMode : int {
Calib_None = 0,
Calib_PA_Line,
Calib_PA_Pattern,
Calib_PA_Tower,
Calib_Flow_Rate,
Calib_Temp_Tower,
Calib_Vol_speed_Tower,
Calib_VFA_Tower,
Calib_Retraction_tower
};
struct Calib_Params {
Calib_Params() : mode(CalibMode::Calib_None) { };
enum class CalibState {
Start = 0,
Preset,
Calibration,
CoarseSave,
FineCalibration,
Save,
Finish
};
struct Calib_Params
{
Calib_Params() : mode(CalibMode::Calib_None){}
double start, end, step;
bool print_numbers;
CalibMode mode;
};
class CalibPressureAdvance {
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height,
int filament_idx = 0);
protected:
CalibPressureAdvance() =default;
~CalibPressureAdvance() =default;
enum class DrawDigitMode {
Left_To_Right,
Bottom_To_Top
class X1CCalibInfos
{
public:
struct X1CCalibInfo
{
int tray_id;
int bed_temp;
int nozzle_temp;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float max_volumetric_speed;
float flow_rate = 0.98f; // for flow ratio
};
void delta_scale_bed_ext(BoundingBoxf& bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
std::string move_to(Vec2d pt, GCodeWriter& writer, std::string comment = std::string());
double e_per_mm(
double line_width,
double layer_height,
float nozzle_diameter,
float filament_diameter,
float print_flow_ratio
) const;
double speed_adjust(int speed) const { return speed * 60; };
std::string convert_number_to_string(double num) const;
double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; };
std::string draw_digit(
double startx,
double starty,
char c,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
GCodeWriter& writer
);
std::string draw_number(
double startx,
double starty,
double value,
CalibPressureAdvance::DrawDigitMode mode,
double line_width,
double e_per_mm,
double speed,
GCodeWriter& writer
);
Vec3d m_last_pos;
DrawDigitMode m_draw_digit_mode {DrawDigitMode::Left_To_Right};
const double m_digit_segment_len {2};
const double m_digit_gap_len {1};
const std::string::size_type m_max_number_len {5};
std::vector<X1CCalibInfo> calib_datas;
};
class CalibPressureAdvanceLine : public CalibPressureAdvance {
class CaliPresetInfo
{
public:
CalibPressureAdvanceLine(GCode* gcodegen) :
mp_gcodegen(gcodegen),
m_nozzle_diameter(gcodegen->config().nozzle_diameter.get_at(0))
{ };
~CalibPressureAdvanceLine() { };
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
CaliPresetInfo &operator=(const CaliPresetInfo &other)
{
this->tray_id = other.tray_id;
this->nozzle_diameter = other.nozzle_diameter;
this->filament_id = other.filament_id;
this->setting_id = other.setting_id;
this->name = other.name;
return *this;
}
};
struct PrinterCaliInfo
{
std::string dev_id;
bool cali_finished = true;
float cache_flow_ratio;
std::vector<CaliPresetInfo> selected_presets;
};
class PACalibResult
{
public:
enum CalibResult {
CALI_RESULT_SUCCESS = 0,
CALI_RESULT_PROBLEM = 1,
CALI_RESULT_FAILED = 2,
};
int tray_id;
int cali_idx = -1;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
std::string name;
float k_value = 0.0;
float n_coef = 0.0;
int confidence = -1; // 0: success 1: uncertain 2: failed
};
struct PACalibIndexInfo
{
int tray_id;
int cali_idx;
float nozzle_diameter;
std::string filament_id;
};
class FlowRatioCalibResult
{
public:
int tray_id;
float nozzle_diameter;
std::string filament_id;
std::string setting_id;
float flow_ratio;
int confidence; // 0: success 1: uncertain 2: failed
};
class CalibPressureAdvance
{
public:
static float find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx = 0);
protected:
CalibPressureAdvance() = default;
~CalibPressureAdvance() = default;
enum class DrawDigitMode { Left_To_Right, Bottom_To_Top };
void delta_scale_bed_ext(BoundingBoxf &bed_ext) const { bed_ext.scale(1.0f / 1.41421f); }
std::string move_to(Vec2d pt, GCodeWriter &writer, std::string comment = std::string());
double e_per_mm(double line_width, double layer_height, float nozzle_diameter, float filament_diameter, float print_flow_ratio) const;
double speed_adjust(int speed) const { return speed * 60; };
std::string convert_number_to_string(double num) const;
double number_spacing() const { return m_digit_segment_len + m_digit_gap_len; };
std::string draw_digit(double startx, double starty, char c, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, GCodeWriter &writer);
std::string draw_number(
double startx, double starty, double value, CalibPressureAdvance::DrawDigitMode mode, double line_width, double e_per_mm, double speed, GCodeWriter &writer);
Vec3d m_last_pos;
DrawDigitMode m_draw_digit_mode{DrawDigitMode::Left_To_Right};
const double m_digit_segment_len{2};
const double m_digit_gap_len{1};
const std::string::size_type m_max_number_len{5};
};
class CalibPressureAdvanceLine : public CalibPressureAdvance
{
public:
CalibPressureAdvanceLine(GCode *gcodegen);
~CalibPressureAdvanceLine(){};
std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50);
void set_speed(double fast = 100.0, double slow = 20.0) {
void set_speed(double fast = 100.0, double slow = 20.0)
{
m_slow_speed = slow;
m_fast_speed = fast;
}
const double& line_width() { return m_line_width; };
bool is_delta() const;
bool& draw_numbers() { return m_draw_numbers; }
const double &line_width() { return m_line_width; };
bool is_delta() const;
bool & draw_numbers() { return m_draw_numbers; }
private:
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
void delta_modify_start(double& startx, double& starty, int count);
GCode* mp_gcodegen;
void delta_modify_start(double &startx, double &starty, int count);
GCode *mp_gcodegen;
double m_nozzle_diameter;
double m_slow_speed, m_fast_speed;
const double m_height_layer {0.2};
const double m_line_width {0.6};
const double m_thin_line_width {0.44};
const double m_number_line_width {0.48};
const double m_space_y {3.5};
double m_length_short {20.0}, m_length_long {40.0};
bool m_draw_numbers {true};
const double m_height_layer{0.2};
const double m_line_width{0.6};
const double m_thin_line_width{0.44};
const double m_number_line_width{0.48};
const double m_space_y{3.5};
double m_length_short{20.0}, m_length_long{40.0};
bool m_draw_numbers{true};
};
struct SuggestedConfigCalibPAPattern {
const std::vector<std::pair<std::string, double>> float_pairs {
{"initial_layer_print_height", 0.25},
{"layer_height", 0.2},
{"initial_layer_speed", 30}
};
struct SuggestedConfigCalibPAPattern
{
const std::vector<std::pair<std::string, double>> float_pairs{{"initial_layer_print_height", 0.25}, {"layer_height", 0.2}, {"initial_layer_speed", 30}};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs {
{"line_width", 112.5},
{"initial_layer_line_width", 140}
};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
const std::vector<std::pair<std::string, int>> int_pairs {
{"skirt_loops", 0},
{"wall_loops", 3}
};
const std::vector<std::pair<std::string, int>> int_pairs{{"skirt_loops", 0}, {"wall_loops", 3}};
const std::pair<std::string, BrimType> brim_pair {"brim_type", BrimType::btNoBrim};
const std::pair<std::string, BrimType> brim_pair{"brim_type", BrimType::btNoBrim};
};
class CalibPressureAdvancePattern : public CalibPressureAdvance {
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
class CalibPressureAdvancePattern : public CalibPressureAdvance
{
friend struct DrawLineOptArgs;
friend struct DrawBoxOptArgs;
public:
CalibPressureAdvancePattern(
const Calib_Params& params,
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
);
CalibPressureAdvancePattern(const Calib_Params &params, const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
double handle_xy_size() const { return m_handle_xy_size; };
double handle_spacing() const { return m_handle_spacing; };
@ -159,85 +217,53 @@ public:
double print_size_y() const { return object_size_y(); };
double max_layer_z() const { return height_first_layer() + ((m_num_layers - 1) * height_layer()); };
void generate_custom_gcodes(
const DynamicPrintConfig& config,
bool is_bbl_machine,
Model& model,
const Vec3d& origin
);
void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
protected:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double line_width_first_layer() const { return m_config.get_abs_value("initial_layer_line_width"); };
double line_width() const { return m_config.get_abs_value("line_width"); };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
int wall_count() const { return m_config.option<ConfigOptionInt>("wall_loops")->value; };
private:
struct DrawLineOptArgs {
DrawLineOptArgs(const CalibPressureAdvancePattern& p) :
height {p.height_layer()},
line_width {p.line_width()},
speed {p.speed_adjust(p.speed_perimeter())}
{ };
double height;
double line_width;
double speed;
std::string comment {"Print line"};
};
struct DrawBoxOptArgs {
DrawBoxOptArgs(const CalibPressureAdvancePattern& p) :
num_perimeters {p.wall_count()},
height {p.height_first_layer()},
line_width {p.line_width_first_layer()},
speed {p.speed_adjust(p.speed_first_layer())}
{ };
bool is_filled {false};
int num_perimeters;
double height;
double line_width;
double speed;
};
void refresh_setup(
const DynamicPrintConfig& config,
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
);
void _refresh_starting_point(const Model& model);
void _refresh_writer(
bool is_bbl_machine,
const Model& model,
const Vec3d& origin
);
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const
struct DrawLineOptArgs
{
return std::ceil((m_params.end - m_params.start) / m_params.step + 1);
}
DrawLineOptArgs(const CalibPressureAdvancePattern &p) : height{p.height_layer()}, line_width{p.line_width()}, speed{p.speed_adjust(p.speed_perimeter())} {};
std::string draw_line(
Vec2d to_pt,
DrawLineOptArgs opt_args
);
std::string draw_box(
double min_x,
double min_y,
double size_x,
double size_y,
DrawBoxOptArgs opt_args
);
double height;
double line_width;
double speed;
std::string comment{"Print line"};
};
struct DrawBoxOptArgs
{
DrawBoxOptArgs(const CalibPressureAdvancePattern &p)
: num_perimeters{p.wall_count()}, height{p.height_first_layer()}, line_width{p.line_width_first_layer()}, speed{p.speed_adjust(p.speed_first_layer())} {};
bool is_filled{false};
int num_perimeters;
double height;
double line_width;
double speed;
};
void refresh_setup(const DynamicPrintConfig &config, bool is_bbl_machine, const Model &model, const Vec3d &origin);
void _refresh_starting_point(const Model &model);
void _refresh_writer(bool is_bbl_machine, const Model &model, const Vec3d &origin);
double height_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_print_height")->value; };
double height_layer() const { return m_config.option<ConfigOptionFloat>("layer_height")->value; };
const int get_num_patterns() const { return std::ceil((m_params.end - m_params.start) / m_params.step + 1); }
std::string draw_line(Vec2d to_pt, DrawLineOptArgs opt_args);
std::string draw_box(double min_x, double min_y, double size_x, double size_y, DrawBoxOptArgs opt_args);
double to_radians(double degrees) const { return degrees * M_PI / 180; };
double get_distance(Vec2d from, Vec2d to) const;
/*
/*
from slic3r documentation: spacing = extrusion_width - layer_height * (1 - PI/4)
"spacing" = center-to-center distance of adjacent extrusions, which partially overlap
https://manual.slic3r.org/advanced/flow-math
@ -258,23 +284,24 @@ private:
double pattern_shift() const;
const Calib_Params& m_params;
const Calib_Params &m_params;
DynamicPrintConfig m_config;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
GCodeWriter m_writer;
bool m_is_delta;
Vec3d m_starting_point;
const double m_handle_xy_size {5};
const double m_handle_spacing {2};
const int m_num_layers {4};
const double m_wall_side_length {30.0};
const int m_corner_angle {90};
const int m_pattern_spacing {2};
const double m_encroachment {1. / 3.};
const double m_handle_xy_size{5};
const double m_handle_spacing{2};
const int m_num_layers{4};
const double m_glyph_padding_horizontal {1};
const double m_glyph_padding_vertical {1};
const double m_wall_side_length{30.0};
const int m_corner_angle{90};
const int m_pattern_spacing{2};
const double m_encroachment{1. / 3.};
const double m_glyph_padding_horizontal{1};
const double m_glyph_padding_vertical{1};
};
} // namespace Slic3r

View file

@ -89,7 +89,6 @@ static constexpr double BRIDGE_INFILL_MARGIN = 1;
//BBS: some global const config which user can not change, but developer can
static constexpr bool g_config_support_sharp_tails = true;
static constexpr bool g_config_remove_small_overhangs = true;
static constexpr float g_config_tree_support_collision_resolution = 0.2;
// Write slices as SVG images into out directory during the 2D processing of the slices.

View file

@ -297,88 +297,88 @@ endif()
# TODO: package documentation files
# if(MCUT_BUILD_AS_SHARED_LIB)
# #
# # dynamic libs
# #
if(MCUT_BUILD_AS_SHARED_LIB)
#
# dynamic libs
#
# install(TARGETS ${mpn_shared_lib_name}
# LIBRARY
# DESTINATION lib/shared
# COMPONENT dynamic_libraries)
# else()
# #
# # static libs
# #
install(TARGETS ${mpn_shared_lib_name}
LIBRARY
DESTINATION lib/shared
COMPONENT dynamic_libraries)
else()
#
# static libs
#
# install(TARGETS ${mpn_static_lib_name}
# ARCHIVE
# DESTINATION lib/static
# COMPONENT static_libraries)
# endif()
install(TARGETS ${mpn_static_lib_name}
ARCHIVE
DESTINATION lib/static
COMPONENT static_libraries)
endif()
#
# headers
#
# install(FILES ${MCUT_INCLUDE_DIR}/mcut/mcut.h ${MCUT_INCLUDE_DIR}/mcut/platform.h
# DESTINATION include/mcut
# COMPONENT headers)
install(FILES ${MCUT_INCLUDE_DIR}/mcut/mcut.h ${MCUT_INCLUDE_DIR}/mcut/platform.h
DESTINATION include/mcut
COMPONENT headers)
# install(FILES
# ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
# ${CMAKE_CURRENT_SOURCE_DIR}/README.md
# DESTINATION ./
# COMPONENT text_files)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
${CMAKE_CURRENT_SOURCE_DIR}/README.md
DESTINATION ./
COMPONENT text_files)
#
# notify CPack of the names of all of the components in the project
#
# set(CPACK_COMPONENTS_ALL static_libraries dynamic_libraries headers text_files) # applications
set(CPACK_COMPONENTS_ALL static_libraries dynamic_libraries headers text_files) # applications
# set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MCUT Application")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_DISPLAY_NAME "Static Libraries")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DISPLAY_NAME "Dynamics Libraries")
# set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MCUT Application")
set(CPACK_COMPONENT_STATIC_LIBRARIES_DISPLAY_NAME "Static Libraries")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DISPLAY_NAME "Dynamics Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
# set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
# "A simple application using MCUT")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_DESCRIPTION
# "Static libraries used to build programs with MCUT")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DESCRIPTION
# "Dynamic libraries used to build programs with MCUT")
# set(CPACK_COMPONENT_HEADERS_DESCRIPTION
# "C/C++ header files for use with MCUT")
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
"A simple application using MCUT")
set(CPACK_COMPONENT_STATIC_LIBRARIES_DESCRIPTION
"Static libraries used to build programs with MCUT")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_DESCRIPTION
"Dynamic libraries used to build programs with MCUT")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with MCUT")
# #
# # component dependencies
# #
# set(CPACK_COMPONENT_HEADERS_DEPENDS static_libraries dynamic_libraries)
#
# component dependencies
#
set(CPACK_COMPONENT_HEADERS_DEPENDS static_libraries dynamic_libraries)
# set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
# set(CPACK_COMPONENT_STATIC_LIBRARIES_GROUP "Development")
# set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_GROUP "Development")
# set(CPACK_COMPONENT_HEADERS_GROUP "Development")
set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_STATIC_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_DYNAMIC_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
# set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
# "All of the tools you'll ever need to develop software")
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
"All of the tools you'll ever need to develop software")
# set (CPACK_PACKAGE_NAME "MCUT")
# set (CPACK_PACKAGE_VENDOR "Floyd M. Chitalu")
# set (CPACK_PACKAGE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
# set (CPACK_PACKAGE_VERSION_MAJOR "${MCUT_MAJOR}")
# set (CPACK_PACKAGE_VERSION_MINOR "${MCUT_MINOR}")
# set (CPACK_PACKAGE_VERSION_PATCH "${MCUT_PATCH}")
# #set (CPACK_PACKAGE_DESCRIPTION "MCUT (pronounced emcut) is a tool for cutting meshes.")
# #set (CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DESCRIPTION.txt)
# set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "MCUT is a library for cutting meshes to perform tasks like boolean operations and more.")
# set (CPACK_PACKAGE_HOMEPAGE_URL "https://cutdigital.github.io/mcut.site/")
# set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
# # set (CPACK_PACKAGE_ICON )
# set (CPACK_PACKAGE_CHECKSUM SHA256)
# #set (CPACK_PROJECT_CONFIG_FILE )
# set (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) # must also include in install command
# set (CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
# #set (CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WELCOME.txt)
set (CPACK_PACKAGE_NAME "MCUT")
set (CPACK_PACKAGE_VENDOR "Floyd M. Chitalu")
set (CPACK_PACKAGE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set (CPACK_PACKAGE_VERSION_MAJOR "${MCUT_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${MCUT_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${MCUT_PATCH}")
#set (CPACK_PACKAGE_DESCRIPTION "MCUT (pronounced emcut) is a tool for cutting meshes.")
#set (CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DESCRIPTION.txt)
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "MCUT is a library for cutting meshes to perform tasks like boolean operations and more.")
set (CPACK_PACKAGE_HOMEPAGE_URL "https://cutdigital.github.io/mcut.site/")
set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
# set (CPACK_PACKAGE_ICON )
set (CPACK_PACKAGE_CHECKSUM SHA256)
#set (CPACK_PROJECT_CONFIG_FILE )
set (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) # must also include in install command
set (CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
#set (CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/WELCOME.txt)
if (WIN32)
if (USE_WIX_TOOLSET)
@ -394,7 +394,7 @@ endif ()
#set (CPACK_OUTPUT_CONFIG_FILE ) # Defaults to CPackConfig.cmake.
#set (CPACK_PACKAGE_EXECUTABLES )
# set (CPACK_STRIP_FILES TRUE)
set (CPACK_STRIP_FILES TRUE)
# set (CPACK_VERBATIM_VARIABLES )
# set (CPACK_SOURCE_PACKAGE_FILE_NAME )
# set (CPACK_SOURCE_STRIP_FILES )
@ -412,6 +412,6 @@ endif ()
# set ( )
# include(CPack)
include(CPack)
# eof

View file

@ -22,6 +22,17 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>@SLIC3R_BUILD_ID@</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>bambustudioopen url</string>
<key>CFBundleURLSchemes</key>
<array>
<string>bambustudioopen</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>

View file

@ -179,6 +179,8 @@ set(SLIC3R_GUI_SOURCES
GUI/MainFrame.hpp
GUI/BBLTopbar.cpp
GUI/BBLTopbar.hpp
GUI/BedShapeDialog.cpp
GUI/BedShapeDialog.hpp
GUI/Plater.cpp
GUI/Plater.hpp
GUI/PartPlate.cpp
@ -191,10 +193,6 @@ set(SLIC3R_GUI_SOURCES
GUI/SavePresetDialog.cpp
GUI/GUI_Colors.hpp
GUI/GUI_Colors.cpp
GUI/PhysicalPrinterDialog.hpp
GUI/PhysicalPrinterDialog.cpp
GUI/PrintHostDialogs.cpp
GUI/PrintHostDialogs.hpp
GUI/GUI_Factories.cpp
GUI/GUI_Factories.hpp
GUI/GUI_ObjectList.cpp
@ -394,14 +392,30 @@ set(SLIC3R_GUI_SOURCES
GUI/AmsMappingPopup.cpp
GUI/ReleaseNote.hpp
GUI/ReleaseNote.cpp
GUI/SingleChoiceDialog.hpp
GUI/SingleChoiceDialog.cpp
GUI/CaliHistoryDialog.hpp
GUI/CaliHistoryDialog.cpp
GUI/CalibrationPanel.hpp
GUI/CalibrationPanel.cpp
GUI/CalibrationWizard.hpp
GUI/CalibrationWizard.cpp
GUI/CalibrationWizardPage.cpp
GUI/CalibrationWizardPage.hpp
GUI/CalibrationWizardStartPage.cpp
GUI/CalibrationWizardStartPage.hpp
GUI/CalibrationWizardPresetPage.cpp
GUI/CalibrationWizardPresetPage.hpp
GUI/CalibrationWizardCaliPage.cpp
GUI/CalibrationWizardCaliPage.hpp
GUI/CalibrationWizardSavePage.cpp
GUI/CalibrationWizardSavePage.hpp
GUI/calib_dlg.cpp
GUI/calib_dlg.hpp
GUI/Calibration.hpp
GUI/Calibration.cpp
GUI/PrintOptionsDialog.hpp
GUI/PrintOptionsDialog.cpp
GUI/BonjourDialog.hpp
GUI/BonjourDialog.cpp
GUI/BedShapeDialog.hpp
GUI/BedShapeDialog.cpp
Utils/json_diff.hpp
Utils/json_diff.cpp
GUI/KBShortcutsDialog.hpp
@ -433,12 +447,6 @@ set(SLIC3R_GUI_SOURCES
Utils/PrintHost.cpp
Utils/NetworkAgent.cpp
Utils/NetworkAgent.hpp
Utils/OctoPrint.cpp
Utils/OctoPrint.hpp
Utils/PrintHost.cpp
Utils/PrintHost.hpp
Utils/Serial.cpp
Utils/Serial.hpp
Utils/MKS.hpp
Utils/MKS.cpp
Utils/Duet.cpp
@ -449,8 +457,9 @@ set(SLIC3R_GUI_SOURCES
Utils/AstroBox.hpp
Utils/Repetier.cpp
Utils/Repetier.hpp
GUI/calib_dlg.hpp
GUI/calib_dlg.cpp
Utils/CalibUtils.cpp
Utils/CalibUtils.hpp
)
if (WIN32)
@ -500,7 +509,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES})
encoding_check(libslic3r_gui)
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto)
#target_link_libraries(libslic3r_gui libslic3r cereal imgui minilzo GLEW::GLEW OpenGL::GL hidapi libcurl OpenSSL::SSL OpenSSL::Crypto ${wxWidgets_LIBRARIES} glfw)
if (MSVC)
@ -528,10 +537,6 @@ if (SLIC3R_STATIC)
target_compile_definitions(libslic3r_gui PUBLIC -DwxDEBUG_LEVEL=0)
endif()
if (HAVE_SPNAV)
target_link_libraries(libslic3r_gui spnav)
endif()
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_CURL AND UNIX AND NOT APPLE)
target_compile_definitions(libslic3r_gui PRIVATE OPENSSL_CERT_OVERRIDE)
endif ()
@ -556,4 +561,4 @@ if (UNIX AND NOT APPLE)
endif ()
# Add a definition so that we can tell we are compiling slic3r.
target_compile_definitions(libslic3r_gui PRIVATE SLIC3R_CURRENTLY_COMPILING_GUI_MODULE)
target_compile_definitions(libslic3r_gui PRIVATE SLIC3R_CURRENTLY_COMPILING_GUI_MODULE)

View file

@ -18,12 +18,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#if BOOST_VERSION >= 107800
#include <boost/timer/timer.hpp>
#else
#include <boost/timer.hpp>
#endif
static const float GROUND_Z = -0.04f;
static const std::array<float, 4> DEFAULT_MODEL_COLOR = { 0.3255f, 0.337f, 0.337f, 1.0f };
@ -138,7 +133,7 @@ const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadiu
const float Bed3D::Axes::DefaultTipLength = 5.0f;
std::array<float, 4> Bed3D::AXIS_X_COLOR = decode_color_to_float_array("#FF0000");
std::array<float, 4> Bed3D::AXIS_Y_COLOR = decode_color_to_float_array("#52c7b8");
std::array<float, 4> Bed3D::AXIS_Y_COLOR = decode_color_to_float_array("#00FF00");
std::array<float, 4> Bed3D::AXIS_Z_COLOR = decode_color_to_float_array("#0000FF");
void Bed3D::update_render_colors()
@ -343,6 +338,7 @@ void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
if (show_axes)
render_axes();
glsafe(::glEnable(GL_DEPTH_TEST));
m_model.set_color(-1, m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR);
@ -608,17 +604,17 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const
void Bed3D::update_model_offset() const
{
// move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad
Vec3d shift = m_extended_bounding_box.center();
Vec3d shift = m_build_volume.bounding_volume().center();
shift(2) = -0.03;
Vec3d* model_offset_ptr = const_cast<Vec3d*>(&m_model_offset);
*model_offset_ptr = shift;
//BBS: TODO: hack for current stl for BBL printer
if (std::string::npos != m_model_filename.find("bbl-3dp-"))
{
(*model_offset_ptr)(0) -= 128.f;
(*model_offset_ptr)(1) -= 128.f;
(*model_offset_ptr)(0) -= m_bed_shape[2].x() / 2.0f;
(*model_offset_ptr)(1) -= m_bed_shape[2].y() / 2.0f;
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
}
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
// update extended bounding box
const_cast<BoundingBoxf3&>(m_extended_bounding_box) = calc_extended_bounding_box();
@ -635,9 +631,9 @@ GeometryBuffer Bed3D::update_bed_triangles() const
BoundingBoxf3 build_volume;
if (!m_build_volume.valid()) return new_triangles;
auto bed_ext = get_extents(m_bed_shape);
(*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x() - bed_ext.min.x();
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y() - bed_ext.min.y();
(*model_offset_ptr)(0) = m_build_volume.bounding_volume2d().min.x();
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y();
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
std::vector<Vec2d> new_bed_shape;

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,7 @@
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/TextInput.hpp"
#include "../slic3r/Utils/CalibUtils.hpp"
#define AMS_MATERIALS_SETTING_DEF_COLOUR wxColour(255, 255, 255)
#define AMS_MATERIALS_SETTING_GREY900 wxColour(38, 46, 48)
@ -32,11 +33,14 @@ class ColorPicker : public wxWindow
{
public:
wxBitmap m_bitmap_border;
wxBitmap m_bitmap_transparent;
wxColour m_colour;
std::vector<wxColour> m_cols;
bool m_selected{false};
bool m_show_full{false};
bool m_is_empty{false};
ColorPicker(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
~ColorPicker();
@ -45,6 +49,7 @@ public:
void set_colors(std::vector<wxColour> cols);
void set_selected(bool sel) {m_selected = sel;Refresh();};
void set_show_full(bool full) {m_show_full = full;Refresh();};
void is_empty(bool empty) {m_is_empty = empty;};
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
@ -54,6 +59,8 @@ public:
class ColorPickerPopup : public PopupWindow
{
public:
ScalableBitmap m_ts_bitmap_custom;
wxStaticBitmap* m_ts_stbitmap_custom;
StaticBox* m_custom_cp;
wxColourData* m_clrData;
StaticBox* m_def_color_box;
@ -96,9 +103,10 @@ public:
wxString temp_min = wxEmptyString, wxString temp_max = wxEmptyString,
wxString k = wxEmptyString, wxString n = wxEmptyString);
void post_select_event();
void post_select_event(int index);
void msw_rescale();
void set_color(wxColour color);
void set_empty_color(wxColour color);
void set_colors(std::vector<wxColour> colors);
void on_picker_color(wxCommandEvent& color);
@ -116,12 +124,15 @@ public:
wxColour m_brand_colour;
std::string m_filament_type;
ColorPickerPopup m_color_picker_popup;
ColorPicker * m_clr_picker;
std::vector<PACalibResult> m_pa_profile_items;
protected:
void create_panel_normal(wxWindow* parent);
void create_panel_kn(wxWindow* parent);
void on_dpi_changed(const wxRect &suggested_rect) override;
void on_select_filament(wxCommandEvent& evt);
void on_select_cali_result(wxCommandEvent &evt);
void on_select_ok(wxCommandEvent &event);
void on_select_reset(wxCommandEvent &event);
void on_select_close(wxCommandEvent &event);
@ -138,15 +149,18 @@ protected:
wxStaticText * warning_text;
//wxPanel * m_panel_body;
wxStaticText * m_title_filament;
wxStaticText * m_title_pa_profile;
wxStaticText * m_title_colour;
wxStaticText * m_title_temperature;
TextInput * m_input_nozzle_min;
TextInput* m_input_nozzle_max;
ScalableBitmap * degree;
wxStaticBitmap * bitmap_max_degree;
wxStaticBitmap * bitmap_min_degree;
Button * m_button_reset;
Button * m_button_confirm;
wxStaticText* m_tip_readonly;
Button * m_button_close;
ColorPicker * m_clr_picker;
wxColourData * m_clrData;
wxPanel * m_panel_kn;
@ -157,11 +171,14 @@ protected:
TextInput* m_input_n_val;
int m_filament_selection;
int m_pa_cali_select_id = 0;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament;
#else
ComboBox *m_comboBox_filament;
#endif
ComboBox * m_comboBox_cali_result;
TextInput* m_readonly_filament;
};

View file

@ -15,6 +15,7 @@
#include <wx/progdlg.h>
#include <wx/clipbrd.h>
#include <wx/dcgraph.h>
#include <wx/graphics.h>
#include <miniz.h>
#include <algorithm>
#include "Plater.hpp"
@ -30,7 +31,7 @@ wxDEFINE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent);
{
m_arraw_bitmap_gray = ScalableBitmap(this, "drop_down", FromDIP(12));
m_arraw_bitmap_white = ScalableBitmap(this, "topbar_dropdown", FromDIP(12));
m_transparent_mitem = ScalableBitmap(this, "transparent_material_item", FromDIP(32));
m_material_coloul = mcolour;
m_material_name = mname;
@ -51,7 +52,11 @@ wxDEFINE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent);
MaterialItem::~MaterialItem() {}
void MaterialItem::msw_rescale() {}
void MaterialItem::msw_rescale() {
m_arraw_bitmap_gray = ScalableBitmap(this, "drop_down", FromDIP(12));
m_arraw_bitmap_white = ScalableBitmap(this, "topbar_dropdown", FromDIP(12));
m_transparent_mitem = ScalableBitmap(this, "transparent_material_item", FromDIP(32));
}
void MaterialItem::set_ams_info(wxColour col, wxString txt)
{
@ -61,6 +66,22 @@ void MaterialItem::set_ams_info(wxColour col, wxString txt)
if (need_refresh) { Refresh();}
}
void MaterialItem::disable()
{
if (IsEnabled()) {
this->Disable();
Refresh();
}
}
void MaterialItem::enable()
{
if (!IsEnabled()) {
this->Enable();
Refresh();
}
}
void MaterialItem::on_selected()
{
if (!m_selected) {
@ -117,15 +138,26 @@ void MaterialItem::render(wxDC &dc)
doRender(dc);
#endif
auto mcolor = m_material_coloul;
auto acolor = m_ams_coloul;
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);
auto material_name_colour = m_material_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
auto material_name_colour = mcolor.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
if (mcolor.Alpha() == 0) {material_name_colour = wxColour(0x26, 0x2E, 0x30);}
dc.SetTextForeground(material_name_colour);
if (dc.GetTextExtent(m_material_name).x > GetSize().x - 10) {
dc.SetFont(::Label::Body_10);
}
auto material_txt_size = dc.GetTextExtent(m_material_name);
@ -133,7 +165,10 @@ void MaterialItem::render(wxDC &dc)
// mapping num
dc.SetFont(::Label::Body_10);
dc.SetTextForeground(m_ams_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30));
dc.SetTextForeground(acolor.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30));
if (acolor.Alpha() == 0) {
dc.SetTextForeground(wxColour(0x26, 0x2E, 0x30));
}
wxString mapping_txt = wxEmptyString;
if (m_ams_name.empty()) {
@ -148,28 +183,44 @@ void MaterialItem::render(wxDC &dc)
void MaterialItem::doRender(wxDC &dc)
{
auto mcolor = m_material_coloul;
auto acolor = m_ams_coloul;
if (mcolor.Alpha() == 0) {
dc.DrawBitmap(m_transparent_mitem.bmp(), FromDIP(1), FromDIP(1));
}
if (!IsEnabled()) {
mcolor = wxColour(0x90, 0x90, 0x90);
acolor = wxColour(0x90, 0x90, 0x90);
}
else {
mcolor = m_material_coloul;
acolor = m_ams_coloul;
}
//top
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(m_material_coloul));
dc.SetBrush(wxBrush(mcolor));
dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(18), 5);
//bottom
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(wxColour(m_ams_coloul)));
dc.SetBrush(wxBrush(wxColour(acolor)));
dc.DrawRoundedRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16), 5);
////middle
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(m_material_coloul));
dc.SetBrush(wxBrush(mcolor));
dc.DrawRectangle(FromDIP(1), FromDIP(11), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(m_ams_coloul));
dc.SetBrush(wxBrush(acolor));
dc.DrawRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8));
////border
#if __APPLE__
if (m_material_coloul == *wxWHITE || m_ams_coloul == *wxWHITE) {
if (mcolor == *wxWHITE || acolor == *wxWHITE) {
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5);
@ -181,7 +232,7 @@ void MaterialItem::doRender(wxDC &dc)
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5);
}
#else
if (m_material_coloul == *wxWHITE || m_ams_coloul == *wxWHITE) {
if (mcolor == *wxWHITE || acolor == *wxWHITE || acolor.Alpha() == 0) {
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5);
@ -194,9 +245,8 @@ void MaterialItem::doRender(wxDC &dc)
}
#endif
//arrow
if ( (m_ams_coloul.Red() > 160 && m_ams_coloul.Green() > 160 && m_ams_coloul.Blue() > 160) &&
(m_ams_coloul.Red() < 180 && m_ams_coloul.Green() < 180 && m_ams_coloul.Blue() < 180)) {
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);
}
else {
@ -535,6 +585,8 @@ void AmsMapingPopup::paintEvent(wxPaintEvent &evt)
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
m_transparent_mapping_item = ScalableBitmap(this, "transparent_mapping_item", FromDIP(44));
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
Bind(wxEVT_PAINT, &MappingItem::paintEvent, this);
}
@ -550,7 +602,7 @@ void MappingItem::send_event(int fliament_id)
wxCommandEvent event(EVT_SET_FINISH_MAPPING);
event.SetInt(m_tray_data.id);
wxString param = wxString::Format("%d|%d|%d|%s|%d", m_coloul.Red(), m_coloul.Green(), m_coloul.Blue(), number, fliament_id);
wxString param = wxString::Format("%d|%d|%d|%d|%s|%d", m_coloul.Red(), m_coloul.Green(), m_coloul.Blue(), m_coloul.Alpha(), number, fliament_id);
event.SetString(param);
event.SetEventObject(this->GetParent()->GetParent());
wxPostEvent(this->GetParent()->GetParent()->GetParent(), event);
@ -592,16 +644,11 @@ void MappingItem::render(wxDC &dc)
// materials name
dc.SetFont(::Label::Head_13);
auto txt_colour = m_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
auto txt_colour = m_coloul.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
txt_colour = m_unmatch ? wxColour(0xCE, 0xCE, 0xCE) : txt_colour;
if (m_coloul.Alpha() == 0) txt_colour = wxColour(0x26, 0x2E, 0x30);
dc.SetTextForeground(txt_colour);
/*if (dc.GetTextExtent(m_name).x > GetSize().x - 10) {
dc.SetFont(::Label::Body_10);
m_name = m_name.substr(0, 3) + "." + m_name.substr(m_name.length() - 1);
}*/
auto txt_size = dc.GetTextExtent(m_tray_index);
auto top = (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2 + FromDIP(8);
dc.DrawText(m_tray_index, wxPoint((GetSize().x - txt_size.x) / 2, top));
@ -628,16 +675,14 @@ void MappingItem::doRender(wxDC &dc)
{
dc.SetPen(m_coloul);
dc.SetBrush(wxBrush(m_coloul));
dc.DrawRectangle(0, (GetSize().y - MAPPING_ITEM_REAL_SIZE.y) / 2, MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y);
// if (m_coloul == *wxWHITE) {
// dc.SetPen(wxPen(wxColour(0xAC, 0xAC, 0xAC), 1));
//#ifdef __APPLE__
// dc.DrawRectangle(1, 1, GetSize().x - 1, GetSize().y - 1);
//#else
// dc.DrawRectangle(0, 0, tray_size.x, tray_size.y);
//#endif // __APPLE__
// }
if (m_coloul.Alpha() == 0) {
dc.DrawBitmap( m_transparent_mapping_item.bmp(), 0, (GetSize().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);
}
wxColour side_colour = wxColour(0xE4E4E4);
@ -1116,8 +1161,11 @@ void MappingContainer::doRender(wxDC& dc)
}
AmsReplaceMaterialDialog::AmsReplaceMaterialDialog(wxWindow* parent)
: DPIDialog(parent, wxID_ANY, _L("Filaments replace"), wxDefaultPosition, wxDefaultSize, wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX)
: DPIDialog(parent, wxID_ANY, _L("Auto Refill"), wxDefaultPosition, wxDefaultSize, wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
SetBackgroundColour(*wxWHITE);
create();
wxGetApp().UpdateDlgDarkUI(this);
@ -1125,14 +1173,13 @@ AmsReplaceMaterialDialog::AmsReplaceMaterialDialog(wxWindow* parent)
void AmsReplaceMaterialDialog::create()
{
SetSize(wxSize(FromDIP(376), -1));
SetMinSize(wxSize(FromDIP(376), -1));
SetMaxSize(wxSize(FromDIP(376), -1));
SetSize(wxSize(FromDIP(445), -1));
SetMinSize(wxSize(FromDIP(445), -1));
SetMaxSize(wxSize(FromDIP(445), -1));
// set icon for dialog
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetSizeHints(wxDefaultSize, wxDefaultSize);
m_main_sizer = new wxBoxSizer(wxVERTICAL);
auto m_top_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
@ -1140,8 +1187,31 @@ void AmsReplaceMaterialDialog::create()
m_main_sizer->Add(m_top_line, 0, wxEXPAND, 0);
auto m_button_sizer = new wxBoxSizer(wxHORIZONTAL);
auto label_title = new Label(this, _L("Auto Refill"));
label_title->SetFont(Label::Head_14);
label_title->SetForegroundColour(0x00AE42);
label_txt = new Label(this, _L("When the current material run out, the printer will continue to print in the following order."));
label_txt->SetFont(Label::Body_13);
label_txt->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3C")));
label_txt->SetMinSize(wxSize(FromDIP(380), -1));
label_txt->SetMaxSize(wxSize(FromDIP(380), -1));
label_txt->Wrap(FromDIP(380));
m_scrollview_groups = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
m_scrollview_groups->SetScrollRate(5, 5);
//m_scrollview_groups->SetMinSize(wxSize(400, 400));
//m_scrollview_groups->SetMaxSize(wxSize(400, 400));
m_scrollview_sizer = new wxBoxSizer(wxVERTICAL);
m_groups_sizer = new wxWrapSizer( wxHORIZONTAL, wxWRAPSIZER_DEFAULT_FLAGS );
m_scrollview_sizer->Add( m_groups_sizer, 0, wxALIGN_CENTER, 0 );
m_scrollview_groups->SetSizer(m_scrollview_sizer);
m_scrollview_groups->Layout();
auto m_button_sizer = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_white(std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled),
std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Pressed),
std::pair<wxColour, int>(AMS_CONTROL_DEF_BLOCK_BK_COLOUR, StateColor::Hovered),
@ -1153,26 +1223,18 @@ void AmsReplaceMaterialDialog::create()
StateColor btn_text_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
auto m_button_close = new Button(this, _L("Close"));
m_button_close->SetCornerRadius(FromDIP(11));
m_button_close->SetBackgroundColor(btn_bg_white);
m_button_close->SetBorderColor(btn_bd_white);
m_button_close->SetTextColor(btn_text_white);
m_button_close->SetFont(Label::Body_13);
m_button_close->SetMinSize(wxSize(FromDIP(42), FromDIP(24)));
m_button_close->Bind(wxEVT_BUTTON, [this](auto& e) {
EndModal(wxCLOSE);
});
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_sizer->Add( 0, 0, 1, wxEXPAND, 0 );
m_button_sizer->Add(m_button_close, 0, wxALIGN_CENTER, 0);
m_groups_sizer = new wxBoxSizer(wxVERTICAL);
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(12));
m_main_sizer->Add(m_groups_sizer,0,wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
m_main_sizer->Add(label_title,0, wxLEFT, FromDIP(30));
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(4));
m_main_sizer->Add(label_txt,0, wxLEFT, FromDIP(30));
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(16));
m_main_sizer->Add(m_scrollview_groups, 1, wxALIGN_CENTER, 0);
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(20));
m_main_sizer->Add(m_button_sizer,0,wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
m_main_sizer->Add(m_button_sizer,0,wxALIGN_CENTER, FromDIP(16));
m_main_sizer->Add(0,0,0, wxTOP, FromDIP(20));
@ -1198,6 +1260,14 @@ std::vector<bool> AmsReplaceMaterialDialog::GetStatus(unsigned int status)
return listStatus;
}
void AmsReplaceMaterialDialog::update_mapping_result( std::vector<FilamentInfo> result)
{
m_tray_used.clear();
for (int i = 0; i < result.size(); i++) {
m_tray_used.push_back(wxGetApp().transition_tridid(result[i].tray_id).ToStdString());
}
}
void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj)
{
if (obj) {m_obj = obj;}
@ -1222,116 +1292,58 @@ void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj)
catch (...) {}
//creat group
int group_index = 1;
int group_index = 0;
for (int filam : m_obj->filam_bak) {
auto status_list = GetStatus(filam);
wxColour group_color;
std::map<std::string, wxColour> group_info;
std::string group_material;
bool is_in_tray = false;
//get color & material
for (auto i = 0; i < status_list.size(); i++) {
if (status_list[i] && tray_list[i] != nullptr) {
group_color = AmsTray::decode_color(tray_list[i]->color);
auto tray_name = wxGetApp().transition_tridid(i).ToStdString();
auto it = std::find(m_tray_used.begin(), m_tray_used.end(), tray_name);
if (it != m_tray_used.end()) {
is_in_tray = true;
}
group_info[tray_name] = AmsTray::decode_color(tray_list[i]->color);
group_material = tray_list[i]->get_display_filament_type();
}
}
m_groups_sizer->Add(create_split_line(wxString::Format("%s%d", _L("Group"), group_index), group_color, group_material, status_list), 0, wxEXPAND, 0);
m_groups_sizer->Add(0, 0, 0, wxTOP, FromDIP(12));
group_index++;
if (is_in_tray || m_tray_used.size() <= 0) {
m_groups_sizer->Add(create_backup_group(wxString::Format("%s%d", _L("Group"), group_index + 1), group_info, group_material, status_list), 0, wxALL, FromDIP(10));
group_index++;
}
}
if (group_index > 0) {
auto height = 0;
if (group_index > 6) {
height = FromDIP(550);
}
else {
height = FromDIP(200) * (std::ceil(group_index / 2.0));
}
m_scrollview_groups->SetMinSize(wxSize(FromDIP(400), height));
m_scrollview_groups->SetMaxSize(wxSize(FromDIP(400), height));
} else {
if (label_txt)
label_txt->SetLabelText(_L("There are currently no identical spare consumables available, and automatic replenishment is currently not possible. \n(Currently supporting automatic supply of consumables with the same brand, material type, and color)"));
}
m_scrollview_groups->Layout();
Layout();
Fit();
}
wxWindow* AmsReplaceMaterialDialog::create_split_line(wxString gname, wxColour col, wxString material, std::vector<bool> status_list)
AmsRMGroup* AmsReplaceMaterialDialog::create_backup_group(wxString gname, std::map<std::string, wxColour> group_info, wxString material, std::vector<bool> status_list)
{
wxColour background_color = wxColour(0xF4F4F4);
if (abs(col.Red() - background_color.Red()) <= 5 &&
abs(col.Green() - background_color.Green()) <= 5 &&
abs(col.Blue() - background_color.Blue()) <= 5) {
background_color = wxColour(0xE6E6E6);
}
auto m_panel_group = new StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_panel_group->SetCornerRadius(FromDIP(4));
m_panel_group->SetBackgroundColor(StateColor(std::pair<wxColour, int>(background_color, StateColor::Normal)));
m_panel_group->SetSize(wxSize(FromDIP(344), -1));
m_panel_group->SetMinSize(wxSize(FromDIP(344), -1));
m_panel_group->SetMaxSize(wxSize(FromDIP(344), -1));
wxBoxSizer* group_sizer = new wxBoxSizer(wxVERTICAL);
//group title
wxBoxSizer* title_sizer = new wxBoxSizer(wxHORIZONTAL);
auto group_name = new Label(m_panel_group, gname);
group_name->SetFont(::Label::Head_12);
Button* material_info = new Button(m_panel_group, material);
material_info->SetFont(Label::Head_12);
material_info->SetCornerRadius(FromDIP(2));
material_info->SetBorderColor(background_color);
if (col.GetLuminance() < 0.5)
material_info->SetTextColor(*wxWHITE);
else
material_info->SetTextColor(0x6B6B6B);
material_info->SetMinSize(wxSize(-1, FromDIP(24)));
material_info->SetBackgroundColor(col);
title_sizer->Add(group_name, 0, wxALIGN_CENTER, 0);
title_sizer->Add(0, 0, 0, wxLEFT, FromDIP(10));
title_sizer->Add(material_info, 0, wxALIGN_CENTER, 0);
//group item
wxGridSizer* grid_Sizer = new wxGridSizer(0, 8, 0, 0);
for (int i = 0; i < status_list.size(); i++) {
if (status_list[i]) {
AmsRMItem* amsitem = new AmsRMItem(m_panel_group, wxID_ANY, wxDefaultPosition, wxDefaultSize);
amsitem->set_color(col);
//set current tray
if (!m_obj->m_tray_now.empty() && m_obj->m_tray_now == std::to_string(i)) {
amsitem->set_focus(true);
}
amsitem->set_type(RMTYPE_NORMAL);
amsitem->set_index(wxGetApp().transition_tridid(i).ToStdString());
amsitem->SetBackgroundColour(background_color);
grid_Sizer->Add(amsitem, 0, wxALIGN_CENTER | wxTOP | wxBottom, FromDIP(10));
}
}
//add the first tray
for (int i = 0; i < status_list.size(); i++) {
if (status_list[i]) {
AmsRMItem* amsitem = new AmsRMItem(m_panel_group, wxID_ANY, wxDefaultPosition, wxDefaultSize);
amsitem->set_color(col);
amsitem->set_type(RMTYPE_VIRTUAL);
amsitem->set_index(wxGetApp().transition_tridid(i).ToStdString());
amsitem->SetBackgroundColour(background_color);
grid_Sizer->Add(amsitem, 0, wxALIGN_CENTER | wxTOP | wxBottom, FromDIP(10));
break;
}
}
group_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
group_sizer->Add(title_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(12));
group_sizer->Add(grid_Sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(12));
group_sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
m_panel_group->SetSizer(group_sizer);
m_panel_group->Layout();
group_sizer->Fit(m_panel_group);
return m_panel_group;
auto grp = new AmsRMGroup(m_scrollview_groups, group_info, material, gname);
return grp;
}
void AmsReplaceMaterialDialog::paintEvent(wxPaintEvent& evt)
@ -1347,119 +1359,90 @@ void AmsReplaceMaterialDialog::on_dpi_changed(const wxRect& suggested_rect)
}
AmsRMItem::AmsRMItem(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size)
{
wxWindow::Create(parent, id, pos, size);
SetSize(wxSize(FromDIP(42), FromDIP(32)));
SetMinSize(wxSize(FromDIP(42), FromDIP(32)));
SetMaxSize(wxSize(FromDIP(42), FromDIP(32)));
SetBackgroundColour(*wxWHITE);
Bind(wxEVT_PAINT, &AmsRMItem::paintEvent, this);
}
void AmsRMItem::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
render(dc);
}
void AmsRMItem::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 AmsRMItem::doRender(wxDC& dc)
{
wxSize size = GetSize();
if (m_type == RMTYPE_NORMAL) {
dc.SetPen(wxPen(m_color, 2));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
}
else {
dc.SetPen(wxPen(m_color, 2, wxSHORT_DASH));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
}
//top bottom line
dc.DrawLine(FromDIP(0), FromDIP(4), size.x - FromDIP(5), FromDIP(4));
dc.DrawLine(FromDIP(0), size.y - FromDIP(4), size.x - FromDIP(5), size.y - FromDIP(4));
//left right line
dc.DrawLine(FromDIP(1), FromDIP(4), FromDIP(1), FromDIP(11));
dc.DrawLine(FromDIP(1), FromDIP(22), FromDIP(1), size.y - FromDIP(4));
dc.DrawLine(size.x - FromDIP(5), FromDIP(4), size.x - FromDIP(5), FromDIP(11));
dc.DrawLine(size.x - FromDIP(5), FromDIP(22), size.x - FromDIP(5), size.y - FromDIP(4));
//delta
dc.DrawLine(FromDIP(0), FromDIP(11), FromDIP(5), size.y / 2);
dc.DrawLine(FromDIP(0), FromDIP(22), FromDIP(5), size.y / 2);
dc.DrawLine(size.x - FromDIP(5), FromDIP(11), size.x - FromDIP(1), size.y / 2);
dc.DrawLine(size.x - FromDIP(5), FromDIP(22), size.x - FromDIP(1), size.y / 2);
if (m_focus) {
dc.SetPen(wxPen(wxColour(0x00AE42), 2));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawLine(FromDIP(0), FromDIP(1), size.x - FromDIP(5), FromDIP(1));
dc.DrawLine(FromDIP(0), size.y - FromDIP(1), size.x - FromDIP(5), size.y - FromDIP(1));
}
if (m_selected) {
}
auto tsize = dc.GetMultiLineTextExtent(m_index);
auto tpot = wxPoint((size.x - tsize.x) / 2 - FromDIP(2), (size.y - tsize.y) / 2 + FromDIP(2));
dc.SetTextForeground(wxColour(0x6B6B6B));
dc.SetFont(::Label::Head_12);
dc.DrawText(m_index, tpot);
}
AmsRMArrow::AmsRMArrow(wxWindow* parent)
AmsRMGroup::AmsRMGroup(wxWindow* parent, std::map<std::string, wxColour> group_info, wxString mname, wxString group_index)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
m_group_info.clear();
m_group_info = group_info;
m_material_name = mname;
m_group_index = group_index;
wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize);
SetSize(wxSize(FromDIP(166), FromDIP(166)));
SetMinSize(wxSize(FromDIP(166), FromDIP(166)));
SetMaxSize(wxSize(FromDIP(166), FromDIP(166)));
SetBackgroundColour(*wxWHITE);
Bind(wxEVT_PAINT, &AmsRMArrow::paintEvent, this);
m_bitmap_left = ScalableBitmap(this, "replace_arrow_left", 7);
m_bitmap_right = ScalableBitmap(this, "replace_arrow_right", 7);
m_bitmap_down = ScalableBitmap(this, "replace_arrow_down", 7);
backup_current_use_white = ScalableBitmap(this, "backup_current_use1",8);
backup_current_use_black = ScalableBitmap(this, "backup_current_use2", 8);
bitmap_backup_tips_0 = ScalableBitmap(this, "backup_tips_img", 90);
bitmap_editable = ScalableBitmap(this, "ams_editable", 14);
bitmap_bg = ScalableBitmap(this, "back_up_ts_bk", 162);
bitmap_editable_light = ScalableBitmap(this, "ams_editable_light", 14);
SetSize(wxSize(FromDIP(16), FromDIP(32)));
SetMinSize(wxSize(FromDIP(16), FromDIP(32)));
SetMaxSize(wxSize(FromDIP(16), FromDIP(32)));
Bind(wxEVT_PAINT, &AmsRMGroup::paintEvent, this);
Bind(wxEVT_LEFT_DOWN, &AmsRMGroup::on_mouse_move, this);
wxGetApp().UpdateDarkUI(this);
}
void AmsRMArrow::paintEvent(wxPaintEvent& evt)
double AmsRMGroup::GetAngle(wxPoint pointA, wxPoint pointB)
{
double deltaX = pointA.x - pointB.x;
double deltaY = pointA.y - pointB.y;
double angle = atan2(deltaY, deltaX);
angle = angle * 180.0 / M_PI;
if (angle < 0)
angle += 360.0;
return angle;
}
void AmsRMGroup::on_mouse_move(wxMouseEvent& evt)
{
wxSize size = GetSize();
auto mouseX = evt.GetPosition().x;
auto mouseY = evt.GetPosition().y;
auto click_angle = 360.0 - GetAngle(wxPoint(mouseX,mouseY), wxPoint(size.x / 2, size.x / 2));
float ev_angle = 360.0 / m_group_info.size();
float startAngle = 0.0;
float endAngle = 0.0;
for (auto iter = m_group_info.rbegin(); iter != m_group_info.rend(); ++iter) {
std::string tray_name = iter->first;
wxColour tray_color = iter->second;
int x = size.x / 2;
int y = size.y / 2;
int radius = size.x / 2;
endAngle += ev_angle;
if (click_angle >= startAngle && click_angle < endAngle) {
//to do
set_index(tray_name);
Refresh();
return;
}
startAngle += ev_angle;
}
evt.Skip();
}
void AmsRMGroup::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
render(dc);
}
void AmsRMArrow::render(wxDC& dc)
void AmsRMGroup::render(wxDC& dc)
{
#ifdef __WXMSW__
wxSize size = GetSize();
@ -1480,17 +1463,114 @@ void AmsRMArrow::render(wxDC& dc)
#endif
}
void AmsRMArrow::doRender(wxDC& dc)
wxPoint AmsRMGroup::CalculateEndpoint(const wxPoint& startPoint, int angle, int length)
{
int endX = startPoint.x + length * cos(angle * M_PI / 180);
int endY = startPoint.y + length * sin(angle * M_PI / 180);
return wxPoint(endX, endY);
}
void AmsRMGroup::doRender(wxDC& dc)
{
wxSize size = GetSize();
float center_mask_radius = FromDIP(52);
float selected_radius = FromDIP(53);
dc.SetPen(wxPen(wxColour(0, 174, 66)));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
float ev_angle = 360.0 / m_group_info.size();
float startAngle = 0.0;
float endAngle = 0.0;
dc.DrawBitmap(bitmap_bg.bmp(), wxPoint((size.x - bitmap_bg.GetBmpSize().x) / 2, (size.y - bitmap_bg.GetBmpSize().y) / 2));
dc.SetPen(wxPen(wxColour(0xACACAC)));
dc.SetBrush(wxBrush(wxColour(0xACACAC)));
dc.DrawCircle(size.x / 2, size.y / 2, FromDIP(7));
for (auto iter = m_group_info.rbegin(); iter != m_group_info.rend(); ++iter) {
std::string tray_name = iter->first;
wxColour tray_color = iter->second;
dc.SetPen(*wxTRANSPARENT_PEN);
if (tray_color == *wxWHITE) dc.SetPen(wxPen(wxColour(0xEEEEEE), 2));
dc.SetBrush(wxBrush(tray_color));
int x = size.x / 2;
int y = size.y / 2;
int radius = size.x / 2 - FromDIP(2);
endAngle += ev_angle;
//draw body
if (tray_color.Alpha() != 0) {
dc.DrawEllipticArc(x - radius, y - radius, radius * 2, radius * 2, startAngle, endAngle);
if (tray_color == *wxWHITE) dc.DrawEllipticArc(x - center_mask_radius, y - center_mask_radius, center_mask_radius * 2, center_mask_radius * 2, startAngle, endAngle);
}
//draw selected
if (!m_selected_index.empty() && m_selected_index == tray_name) {
dc.SetPen(wxPen(0xCECECE, 2));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawEllipticArc(x - radius, y - radius, radius * 2, radius * 2, startAngle, endAngle);
dc.DrawEllipticArc(x - selected_radius, y - selected_radius,selected_radius * 2, selected_radius * 2, startAngle, endAngle);
}
//...
startAngle += ev_angle;
}
//draw text
startAngle = 0.0;
endAngle = 0.0;
for (auto iter = m_group_info.rbegin(); iter != m_group_info.rend(); ++iter) {
std::string tray_name = iter->first;
wxColour tray_color = iter->second;
int x = size.x / 2;
int y = size.y / 2;
float radius = size.x / 2 - 15.0;
endAngle += ev_angle;
float midAngle = (startAngle + endAngle) / 2;
float x_center = size.x / 2 + radius * cos(midAngle * M_PI / 180.0);
float y_center = size.y / 2 + radius * sin(midAngle * M_PI / 180.0);
//draw tray
dc.SetFont(::Label::Body_12);
auto text_size = dc.GetTextExtent(tray_name);
dc.SetTextForeground(tray_color.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x262E30));
dc.DrawText(tray_name, x_center - text_size.x / 2, size.y - y_center - text_size.y / 2);
//draw split line
dc.SetPen(wxPen(*wxWHITE, 2));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
auto pos_sp_start = CalculateEndpoint(wxPoint(x, y), (360 - startAngle), size.x / 2 - FromDIP(3));
dc.DrawLine(wxPoint(x, y), pos_sp_start);
//draw current
//dc.DrawBitmap(backup_current_use_white.bmp(), x_center - text_size.x / 2 + FromDIP(3), size.y - y_center - text_size.y / 2 + FromDIP(11));
//...
startAngle += ev_angle;
}
//draw center mask
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(*wxWHITE));
int x = size.x / 2;
int y = size.y / 2;
dc.DrawEllipticArc(x - center_mask_radius, y - center_mask_radius, center_mask_radius * 2, center_mask_radius * 2, 0, 360);
//draw center icon
dc.DrawBitmap(bitmap_backup_tips_0.bmp(), wxPoint((size.x - bitmap_backup_tips_0.GetBmpSize().x) / 2, (size.y - bitmap_backup_tips_0.GetBmpSize().y) / 2));
//dc.DrawBitmap(bitmap_backup_tips_1.bmp(), wxPoint((size.x - bitmap_backup_tips_1.GetBmpSize().x) / 2, (size.y - bitmap_backup_tips_1.GetBmpSize().y) / 2));
//draw material
dc.SetTextForeground(wxColour(0x323A3D));
dc.SetFont(Label::Head_15);
auto text_size = dc.GetTextExtent(m_material_name);
dc.DrawText(m_material_name, (size.x - text_size.x) / 2,(size.y - text_size.y) / 2 - FromDIP(12));
dc.SetFont(Label::Body_13);
text_size = dc.GetTextExtent(m_group_index);
dc.DrawText(m_group_index, (size.x - text_size.x) / 2, (size.y - text_size.y) / 2 + FromDIP(10));
}
}} // namespace Slic3r::GUI

View file

@ -75,6 +75,7 @@ public:
ScalableBitmap m_arraw_bitmap_gray;
ScalableBitmap m_arraw_bitmap_white;
ScalableBitmap m_transparent_mitem;
bool m_selected {false};
bool m_warning{false};
@ -82,6 +83,8 @@ public:
void msw_rescale();
void set_ams_info(wxColour col, wxString txt);
void disable();
void enable();
void on_normal();
void on_selected();
void on_warning();
@ -106,6 +109,7 @@ public:
wxColour m_coloul;
wxString m_name;
TrayData m_tray_data;
ScalableBitmap m_transparent_mapping_item;
bool m_unmatch{false};
void msw_rescale();
@ -242,6 +246,35 @@ public:
};
class AmsRMGroup : public wxWindow
{
public:
AmsRMGroup(wxWindow* parent, std::map<std::string, wxColour> group_info, wxString mname, wxString group_index);
~AmsRMGroup() {};
public:
void set_index(std::string index) {m_selected_index = index;};
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
void on_mouse_move(wxMouseEvent& evt);
double GetAngle(wxPoint pointA, wxPoint pointB);
wxPoint CalculateEndpoint(const wxPoint& startPoint, int angle, int length);
private:
std::map<std::string, wxColour> m_group_info;
std::string m_selected_index;
ScalableBitmap backup_current_use_white;
ScalableBitmap backup_current_use_black;
ScalableBitmap bitmap_backup_tips_0;
ScalableBitmap bitmap_backup_tips_1;
ScalableBitmap bitmap_editable;
ScalableBitmap bitmap_bg;
ScalableBitmap bitmap_editable_light;
wxString m_material_name;
wxString m_group_index;
};
class AmsReplaceMaterialDialog : public DPIDialog
{
public:
@ -249,68 +282,25 @@ public:
~AmsReplaceMaterialDialog() {};
public:
wxWindow* create_split_line(wxString gname, wxColour col, wxString material, std::vector<bool> status_list);
AmsRMGroup* create_backup_group(wxString gname, std::map<std::string, wxColour> group_info, wxString material, std::vector<bool> status_list);
void create();
void update_machine_obj(MachineObject* obj);
void on_left_down(wxMouseEvent& evt);
void update_mapping_result(std::vector<FilamentInfo> result);
void paintEvent(wxPaintEvent& evt);
void on_dpi_changed(const wxRect &suggested_rect) override;
void on_dpi_changed(const wxRect& suggested_rect) override;
std::vector<bool> GetStatus(unsigned int status);
public:
wxBoxSizer* m_main_sizer{nullptr};
wxBoxSizer* m_groups_sizer{nullptr};
MachineObject* m_obj{nullptr};
wxScrolledWindow* m_scrollview_groups{ nullptr };
wxBoxSizer* m_scrollview_sizer{ nullptr };
wxBoxSizer* m_main_sizer{ nullptr };
wxWrapSizer* m_groups_sizer{ nullptr };
MachineObject* m_obj{ nullptr };
std::vector<std::string> m_tray_used;
Label* label_txt{nullptr};
};
enum RMTYPE {
RMTYPE_NORMAL = 0,
RMTYPE_VIRTUAL = 1,
};
class AmsRMItem : public wxWindow
{
public:
AmsRMItem(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
~AmsRMItem() {};
public:
void set_color(wxColour col) {m_color = col;};
void set_type(RMTYPE type) {m_type = type;};
void set_index(std::string index) {m_index = index;};
void set_focus(bool focus) {m_focus = focus;};
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
private:
RMTYPE m_type;
wxColour m_color;
std::string m_index;
bool m_focus = false;
bool m_selected = false;
};
class AmsRMArrow : public wxWindow
{
public:
AmsRMArrow(wxWindow* parent);
~AmsRMArrow() {};
public:
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
private:
ScalableBitmap m_bitmap_left;
ScalableBitmap m_bitmap_right;
ScalableBitmap m_bitmap_down;
};
wxDECLARE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent);
}} // namespace Slic3r::GUI

View file

@ -128,7 +128,7 @@ void BBLStatusBar::clear_percent()
}
void BBLStatusBar::show_networking_test(wxString msg)
void BBLStatusBar::show_error_info(wxString msg, int code, wxString description, wxString extra)
{
}

View file

@ -45,7 +45,7 @@ public:
int get_range() const override;
void set_range(int = 100) override;
void clear_percent() override;
void show_networking_test(wxString msg) override;
void show_error_info(wxString msg, int code, wxString description, wxString extra) override;
void show_progress(bool);
void start_busy(int = 100);
void stop_busy();

View file

@ -24,19 +24,9 @@ BBLStatusBarBind::BBLStatusBarBind(wxWindow *parent, int id)
m_self->SetBackgroundColour(wxColour(255,255,255));
m_self->SetMinSize(wxSize(m_self->FromDIP(450), m_self->FromDIP(30)));
//wxBoxSizer *m_sizer_bottom = new wxBoxSizer(wxHORIZONTAL);
/* m_status_text = new wxStaticText(m_self, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0);
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
m_status_text->SetFont(::Label::Body_13);
m_status_text->Wrap(-1);
m_sizer_body->Add(m_status_text, 0, 0, 0);*/
m_prog = new wxGauge(m_self, wxID_ANY, 100, wxDefaultPosition, wxSize(m_self->FromDIP(400), m_self->FromDIP(6)), wxGA_HORIZONTAL);
m_prog->SetValue(0);
m_stext_percent = new wxStaticText(m_self, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, 0);
m_stext_percent->SetForegroundColour(wxColour(107, 107, 107));
m_stext_percent->SetFont(::Label::Body_13);
@ -46,13 +36,9 @@ BBLStatusBarBind::BBLStatusBarBind(wxWindow *parent, int id)
m_sizer->Add(0, 0, 1, wxEXPAND, 0);
m_sizer->Add(m_stext_percent, 1, wxALIGN_CENTER, 0);
//m_sizer->Add(m_sizer_bottom, 1, wxALIGN_CENTER, 0);
m_self->SetSizer(m_sizer);
m_self->Layout();
m_sizer->Fit(m_self);
//set_prog_block();
}
void BBLStatusBarBind::set_prog_block()
@ -97,7 +83,7 @@ void BBLStatusBarBind::clear_percent()
}
void BBLStatusBarBind::show_networking_test(wxString msg)
void BBLStatusBarBind::show_error_info(wxString msg, int code, wxString description, wxString extra)
{
}

View file

@ -48,7 +48,7 @@ public:
int get_range() const override;
void set_range(int = 100) override;
void clear_percent() override;
void show_networking_test(wxString msg) override;
void show_error_info(wxString msg, int code, wxString description, wxString extra) override;
void show_progress(bool);
void start_busy(int = 100);
void stop_busy();

View file

@ -16,6 +16,7 @@
namespace Slic3r {
wxDEFINE_EVENT(EVT_SHOW_ERROR_INFO, wxCommandEvent);
BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
: m_self{new wxPanel(parent, id == -1 ? wxID_ANY : id)}
@ -29,20 +30,32 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
m_status_text = new wxStaticText(m_self, wxID_ANY, wxEmptyString);
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
m_status_text->SetFont(::Label::Body_13);
m_status_text->SetSize(wxSize(m_self->FromDIP(300), m_self->FromDIP(46)));
m_status_text->SetMaxSize(wxSize(m_self->FromDIP(300), m_self->FromDIP(46)));
m_status_text->SetMaxSize(wxSize(m_self->FromDIP(360), m_self->FromDIP(40)));
m_prog = new wxGauge(m_self, wxID_ANY, 100, wxDefaultPosition, wxSize(-1, m_self->FromDIP(6)), wxGA_HORIZONTAL);
m_prog->SetMinSize(wxSize(m_self->FromDIP(300),m_self->FromDIP(6)));
m_prog->SetValue(0);
StateColor btn_bd_white(std::pair<wxColour, int>(*wxWHITE, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
//StateColor btn_bd_white(std::pair<wxColour, int>(*wxWHITE, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
StateColor btn_bt_white(std::pair<wxColour, int>(wxColour(0x90, 0x90, 0x90), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor btn_bd_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
StateColor btn_txt_white(std::pair<wxColour, int>(wxColour("#FFFFFE"), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Normal));
m_cancelbutton = new Button(m_self, _L("Cancel"));
m_cancelbutton->SetSize(wxSize(m_self->FromDIP(58), m_self->FromDIP(22)));
m_cancelbutton->SetMinSize(wxSize(m_self->FromDIP(58), m_self->FromDIP(22)));
m_cancelbutton->SetMaxSize(wxSize(m_self->FromDIP(58), m_self->FromDIP(22)));
m_cancelbutton->SetBackgroundColor(wxColour(255, 255, 255));
m_cancelbutton->SetBackgroundColor(btn_bt_white);
m_cancelbutton->SetBorderColor(btn_bd_white);
m_cancelbutton->SetTextColor(btn_txt_white);
m_cancelbutton->SetCornerRadius(m_self->FromDIP(12));
m_cancelbutton->Bind(wxEVT_BUTTON,
[this](wxCommandEvent &evt) {
@ -56,33 +69,62 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
m_stext_percent->SetFont(::Label::Body_13);
m_stext_percent->Wrap(-1);
m_hyperlink = new Label(m_self, _L("Check the status of current system services"));
m_hyperlink->SetForegroundColour(0x00AE42);
m_hyperlink->SetFont(::Label::Body_12);
m_hyperlink->Hide();
m_sizer_status_text = new wxBoxSizer(wxHORIZONTAL);
m_link_show_error = new Label(m_self, _L("Check the reason"));
m_link_show_error->SetForegroundColour(wxColour(0x6b6b6b));
m_link_show_error->SetFont(::Label::Head_13);
m_bitmap_show_error_close = create_scaled_bitmap("link_more_error_close", nullptr, 7);
m_bitmap_show_error_open = create_scaled_bitmap("link_more_error_open", nullptr, 7);
m_static_bitmap_show_error = new wxStaticBitmap(m_self, wxID_ANY, m_bitmap_show_error_open, wxDefaultPosition, wxSize(m_self->FromDIP(7), m_self->FromDIP(7)));
m_link_show_error->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {this->m_self->SetCursor(wxCURSOR_HAND); });
m_link_show_error->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {this->m_self->SetCursor(wxCURSOR_ARROW); });
m_link_show_error->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
if (!m_show_error_info_state) { m_show_error_info_state = true; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_close); }
else { m_show_error_info_state = false; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_open); }
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_ERROR_INFO);
wxQueueEvent(this->m_self->GetParent(), evt);
});
m_link_show_error->Hide();
m_static_bitmap_show_error->Hide();
m_static_bitmap_show_error->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {this->m_self->SetCursor(wxCURSOR_HAND); });
m_static_bitmap_show_error->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {this->m_self->SetCursor(wxCURSOR_ARROW); });
m_static_bitmap_show_error->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
if (!m_show_error_info_state) {m_show_error_info_state = true;m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_close);}
else {m_show_error_info_state = false;m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_open);}
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_ERROR_INFO);
wxQueueEvent(this->m_self->GetParent(), evt);
});
m_sizer_status_text->Add(m_link_show_error, 0, wxLEFT | wxALIGN_CENTER, 0);
m_sizer_status_text->Add(m_static_bitmap_show_error, 0, wxLEFT | wxTOP| wxALIGN_CENTER, m_self->FromDIP(2));
m_sizer_bottom->Add(m_prog, 1, wxALIGN_CENTER, 0);
m_sizer_bottom->Add(m_stext_percent, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10);
m_sizer_bottom->Add(m_hyperlink, 0, wxALIGN_CENTER, 10);
m_sizer_bottom->Add(m_sizer_status_text, 0, wxALIGN_CENTER, 10);
m_sizer_bottom->Add(0, 0, 1, wxEXPAND, 0);
m_sizer_bottom->Add(m_cancelbutton, 0, wxALIGN_CENTER, 0);
m_sizer_body->Add(m_status_text, 0, wxALL, 0);
m_sizer_body->Add(0, 0, 0, wxTOP, 1);
m_sizer_body->Add(m_sizer_bottom, 1, wxEXPAND, 0);
m_sizer_body->Add(0, 0, 1, wxEXPAND, 0);
m_sizer_body->Add(m_status_text, 0, wxEXPAND, 0);
m_sizer_body->Add(m_sizer_bottom, 0, wxEXPAND, 0);
m_sizer_body->Add(0, 0, 1, wxEXPAND, 0);
m_sizer->Add(m_sizer_body, 1, wxALIGN_CENTER, 0);
m_self->SetSizer(m_sizer);
m_self->Layout();
m_sizer->Fit(m_self);
//set_prog_block();
}
void BBLStatusBarSend::set_prog_block()
{
//block_left->SetPosition(wxPoint(0, 0));
//block_right->SetPosition(wxPoint(m_prog->GetSize().GetWidth() - 2, 0));
}
int BBLStatusBarSend::get_progress() const
@ -92,10 +134,7 @@ int BBLStatusBarSend::get_progress() const
void BBLStatusBarSend::set_progress(int val)
{
//set_prog_block();
if(val < 0)
return;
if(val < 0) return;
//add the logic for arrange/orient jobs, which don't call stop_busy
if (!m_prog->IsShown()) {
@ -126,48 +165,14 @@ void BBLStatusBarSend::clear_percent()
m_cancelbutton->Hide();
}
void BBLStatusBarSend::show_networking_test(wxString msg)
void BBLStatusBarSend::show_error_info(wxString msg, int code, wxString description, wxString extra)
{
std::string url;
std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code();
if (country_code == "US") {
url = "https://status.bambulab.com";
}
else if (country_code == "CN") {
url = "https://status.bambulab.cn";
}
else if (country_code == "ENV_CN_DEV") {
url = "https://status.bambu-lab.com";
}
else if (country_code == "ENV_CN_QA") {
url = "https://status.bambu-lab.com";
}
else if (country_code == "ENV_CN_PRE") {
url = "https://status.bambu-lab.com";
}
else {
url = "https://status.bambu-lab.com";
}
m_hyperlink->Bind(wxEVT_LEFT_DOWN, [this, url](auto& e) {
wxLaunchDefaultBrowser(url);
});
m_hyperlink->Bind(wxEVT_ENTER_WINDOW, [this, url](auto& e) {
m_hyperlink->SetCursor(wxCURSOR_HAND);
});
m_hyperlink->Bind(wxEVT_LEAVE_WINDOW, [this, url](auto& e) {
m_hyperlink->SetCursor(wxCURSOR_ARROW);
});
set_status_text(msg);
m_prog->Hide();
m_stext_percent->Hide();
m_hyperlink->Show();
m_link_show_error->Show();
m_static_bitmap_show_error->Show();
m_cancelbutton->Show();
m_self->Layout();
m_sizer->Layout();
@ -283,9 +288,15 @@ void BBLStatusBarSend::set_status_text(const wxString& txt)
//auto txtss = "Sending the printing task has timed out.\nPlease try again!";
//auto txtss = "The printing project is being uploaded... 25%%";
//m_status_text->SetLabelText(txtss);
wxString str;
format_text(m_status_text, m_self->FromDIP(300), txt, str);
m_status_text->SetLabelText(str);
//wxString str;
//format_text(m_status_text, m_self->FromDIP(300), txt, str);
if (m_status_text->GetTextExtent(txt).x > m_self->FromDIP(360)) {
m_status_text->SetSize(m_self->FromDIP(360), m_self->FromDIP(40));
}
m_status_text->SetLabelText(txt);
m_status_text->Wrap(m_self->FromDIP(360));
m_status_text->Layout();
m_self->Layout();
//if (is_english_text(str)) m_status_text->Wrap(m_self->FromDIP(280));
}
@ -303,6 +314,8 @@ void BBLStatusBarSend::set_status_text(const std::string& txt)
void BBLStatusBarSend::set_status_text(const char *txt)
{
this->set_status_text(wxString::FromUTF8(txt));
get_panel()->GetParent()->Layout();
get_panel()->GetParent()->Update();
}
void BBLStatusBarSend::msw_rescale() {
@ -317,9 +330,7 @@ wxString BBLStatusBarSend::get_status_text() const
bool BBLStatusBarSend::update_status(wxString &msg, bool &was_cancel, int percent, bool yield)
{
//auto test_txt = _L("Unkown Error.") + _L("status=150, body=Timeout was reached: Connection timed out after 10009 milliseconds [Error 28]");
set_status_text(msg);
if (percent >= 0)
this->set_progress(percent);
@ -331,9 +342,11 @@ bool BBLStatusBarSend::update_status(wxString &msg, bool &was_cancel, int percen
void BBLStatusBarSend::reset()
{
m_hyperlink->Hide();
m_link_show_error->Hide();
m_static_bitmap_show_error->Hide();
m_prog->Show();
m_stext_percent->Show();
m_cancelbutton->Enable();
m_cancelbutton->Show();
m_was_cancelled = false;
@ -364,4 +377,14 @@ void BBLStatusBarSend::change_button_label(wxString name)
m_cancelbutton->SetLabel(name);
}
void BBLStatusBarSend::disable_cancel_button()
{
m_cancelbutton->Disable();
}
void BBLStatusBarSend::enable_cancel_button()
{
m_cancelbutton->Enable();
}
}

View file

@ -30,7 +30,11 @@ class BBLStatusBarSend : public ProgressIndicator
{
wxPanel * m_self; // we cheat! It should be the base class but: perl!
wxGauge * m_prog;
Label * m_hyperlink;
Label * m_link_show_error;
wxBoxSizer* m_sizer_status_text;
wxStaticBitmap* m_static_bitmap_show_error;
wxBitmap m_bitmap_show_error_close;
wxBitmap m_bitmap_show_error_open;
Button * m_cancelbutton;
wxStaticText *m_status_text;
wxStaticText *m_stext_percent;
@ -51,7 +55,7 @@ public:
int get_range() const override;
void set_range(int = 100) override;
void clear_percent() override;
void show_networking_test(wxString msg) override;
void show_error_info(wxString msg, int code, wxString description, wxString extra) override;
void show_progress(bool);
void start_busy(int = 100);
void stop_busy();
@ -80,7 +84,10 @@ public:
void hide_cancel_button();
void change_button_label(wxString name);
void disable_cancel_button();
void enable_cancel_button();
private:
bool m_show_error_info_state = false;
bool m_busy = false;
bool m_was_cancelled = false;
CancelFn m_cancel_cb;
@ -91,6 +98,8 @@ namespace GUI {
using Slic3r::BBLStatusBarSend;
}
wxDECLARE_EVENT(EVT_SHOW_ERROR_INFO, wxCommandEvent);
} // namespace Slic3r
#endif // BBLSTATUSBAR_HPP

View file

@ -195,7 +195,8 @@ void BBLTopbar::Init(wxFrame* parent)
m_frame = parent;
m_skip_popup_file_menu = false;
m_skip_popup_dropdown_menu = false;
m_skip_popup_calib_menu = false;
m_skip_popup_calib_menu = false;
wxInitAllImageHandlers();
this->AddSpacer(5);
@ -244,9 +245,9 @@ void BBLTopbar::Init(wxFrame* parent)
this->AddSpacer(FromDIP(10));
wxBitmap calib_bitmap = create_scaled_bitmap("calib_sf", nullptr, TOPBAR_ICON_SIZE);
wxBitmap calib_bitmap = create_scaled_bitmap("calib_sf", nullptr, TOPBAR_ICON_SIZE);
wxBitmap calib_bitmap_inactive = create_scaled_bitmap("calib_sf_inactive", nullptr, TOPBAR_ICON_SIZE);
m_calib_item = this->AddTool(ID_CALIB, _L("Calibration"), calib_bitmap);
m_calib_item = this->AddTool(ID_CALIB, _L("Calibration"), calib_bitmap);
m_calib_item->SetDisabledBitmap(calib_bitmap_inactive);
this->AddSpacer(FromDIP(10));
@ -326,12 +327,6 @@ BBLTopbar::~BBLTopbar()
m_file_menu = nullptr;
}
void BBLTopbar::show_publish_button(bool show)
{
this->EnableTool(m_publish_item->GetId(), show);
Refresh();
}
void BBLTopbar::OnOpenProject(wxAuiToolBarEvent& event)
{
MainFrame* main_frame = dynamic_cast<MainFrame*>(m_frame);
@ -339,6 +334,12 @@ void BBLTopbar::OnOpenProject(wxAuiToolBarEvent& event)
plater->load_project();
}
void BBLTopbar::show_publish_button(bool show)
{
this->EnableTool(m_publish_item->GetId(), show);
Refresh();
}
void BBLTopbar::OnSaveProject(wxAuiToolBarEvent& event)
{
MainFrame* main_frame = dynamic_cast<MainFrame*>(m_frame);
@ -360,7 +361,7 @@ void BBLTopbar::OnRedo(wxAuiToolBarEvent& event)
plater->redo();
}
void BBLTopbar::Enable3DEditorItems()
void BBLTopbar::EnableUndoRedoItems()
{
this->EnableTool(m_undo_item->GetId(), true);
this->EnableTool(m_redo_item->GetId(), true);
@ -368,7 +369,7 @@ void BBLTopbar::Enable3DEditorItems()
Refresh();
}
void BBLTopbar::Disable3DEditorItems()
void BBLTopbar::DisableUndoRedoItems()
{
this->EnableTool(m_undo_item->GetId(), false);
this->EnableTool(m_redo_item->GetId(), false);
@ -381,6 +382,15 @@ void BBLTopbar::SaveNormalRect()
m_normalRect = m_frame->GetRect();
}
void BBLTopbar::ShowCalibrationButton(bool show)
{
m_calib_item->GetSizerItem()->Show(show);
m_sizer->Layout();
if (!show)
m_calib_item->GetSizerItem()->SetDimension({-1000, 0}, {0, 0});
Refresh();
}
void BBLTopbar::OnModelStoreClicked(wxAuiToolBarEvent& event)
{
//GUI::wxGetApp().load_url(wxString(wxGetApp().app_config->get_web_host_url() + MODEL_STORE_URL));
@ -393,12 +403,15 @@ void BBLTopbar::OnPublishClicked(wxAuiToolBarEvent& event)
return;
}
// record
json j;
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent)
agent->track_event("enter_model_mall", j.dump());
//no more check
//if (GUI::wxGetApp().plater()->model().objects.empty()) return;
if (!wxGetApp().check_login())
return;
#ifdef ENABLE_PUBLISHING
wxGetApp().plater()->show_publish_dialog();
#endif
@ -597,17 +610,16 @@ void BBLTopbar::OnDropdownToolItem(wxAuiToolBarEvent& evt)
tb->SetToolSticky(evt.GetId(), false);
}
void BBLTopbar::OnCalibToolItem(wxAuiToolBarEvent& evt)
void BBLTopbar::OnCalibToolItem(wxAuiToolBarEvent &evt)
{
wxAuiToolBar* tb = static_cast<wxAuiToolBar*>(evt.GetEventObject());
wxAuiToolBar *tb = static_cast<wxAuiToolBar *>(evt.GetEventObject());
tb->SetToolSticky(evt.GetId(), true);
if (!m_skip_popup_calib_menu) {
auto rec = this->GetToolRect(ID_CALIB);
PopupMenu(&m_calib_menu, wxPoint(rec.GetLeft(), this->GetSize().GetHeight() - 2));
}
else {
} else {
m_skip_popup_calib_menu = false;
}

View file

@ -16,7 +16,6 @@ public:
BBLTopbar(wxFrame* parent);
void Init(wxFrame *parent);
~BBLTopbar();
void show_publish_button(bool show);
void UpdateToolbarWidth(int width);
void Rescale();
void OnIconize(wxAuiToolBarEvent& event);
@ -24,7 +23,7 @@ public:
void OnCloseFrame(wxAuiToolBarEvent& event);
void OnFileToolItem(wxAuiToolBarEvent& evt);
void OnDropdownToolItem(wxAuiToolBarEvent& evt);
void OnCalibToolItem(wxAuiToolBarEvent& evt);
void OnCalibToolItem(wxAuiToolBarEvent &evt);
void OnMouseLeftDClock(wxMouseEvent& mouse);
void OnMouseLeftDown(wxMouseEvent& event);
void OnMouseLeftUp(wxMouseEvent& event);
@ -32,6 +31,7 @@ public:
void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
void OnMenuClose(wxMenuEvent& event);
void OnOpenProject(wxAuiToolBarEvent& event);
void show_publish_button(bool show);
void OnSaveProject(wxAuiToolBarEvent& event);
void OnUndo(wxAuiToolBarEvent& event);
void OnRedo(wxAuiToolBarEvent& event);
@ -43,17 +43,19 @@ public:
void SetFileMenu(wxMenu* file_menu);
void AddDropDownSubMenu(wxMenu* sub_menu, const wxString& title);
void AddDropDownMenuItem(wxMenuItem* menu_item);
wxMenu* GetTopMenu();
wxMenu *GetTopMenu();
wxMenu *GetCalibMenu();
void SetTitle(wxString title);
void SetMaximizedSize();
void SetWindowSize();
void Enable3DEditorItems();
void Disable3DEditorItems();
void EnableUndoRedoItems();
void DisableUndoRedoItems();
void SaveNormalRect();
void ShowCalibrationButton(bool show = true);
private:
wxFrame* m_frame;
wxAuiToolBarItem* m_file_menu_item;

View file

@ -120,7 +120,7 @@ public:
// Get the current print. It is either m_fff_print or m_sla_print.
const PrintBase* current_print() const { return m_print; }
const Print* fff_print() const { return m_fff_print; }
Print* fff_print() { return m_fff_print; }
Print * fff_print() { return m_fff_print; }
const SLAPrint* sla_print() const { return m_sla_print; }
// Take the project path (if provided), extract the name of the project, run it through the macro processor and save it next to the project file.
// If the project_path is empty, just run output_filepath().

View file

@ -5,20 +5,61 @@
#include <wx/sizer.h>
#include <wx/statbox.h>
#include "wx/evtloop.h"
#include <wx/tokenzr.h>
#include <wx/richmsgdlg.h>
#include <wx/richtext/richtextctrl.h>
#include "libslic3r/Model.hpp"
#include "libslic3r/Polygon.hpp"
#include "MainFrame.hpp"
#include "GUI_App.hpp"
#include "Plater.hpp"
#include "Widgets/WebView.hpp"
namespace Slic3r {
namespace GUI {
wxString get_fail_reason(int code)
{
if (code == BAMBU_NETWORK_ERR_BIND_CREATE_SOCKET_FAILED)
return _L("Failed to create socket");
else if (code == BAMBU_NETWORK_ERR_BIND_SOCKET_CONNECT_FAILED)
return _L("Failed to connect socket");
else if (code == BAMBU_NETWORK_ERR_BIND_PUBLISH_LOGIN_REQUEST)
return _L("Failed to publish login request");
else if (code == BAMBU_NETWORK_ERR_BIND_GET_PRINTER_TICKET_TIMEOUT)
return _L("Get ticket from device timeout");
else if (code == BAMBU_NETWORK_ERR_BIND_GET_CLOUD_TICKET_TIMEOUT)
return _L("Get ticket from server timeout");
else if (code == BAMBU_NETWORK_ERR_BIND_POST_TICKET_TO_CLOUD_FAILED)
return _L("Failed to post ticket to server");
else if (code == BAMBU_NETWORK_ERR_BIND_PARSE_LOGIN_REPORT_FAILED)
return _L("Failed to parse login report reason");
else if (code == BAMBU_NETWORK_ERR_BIND_ECODE_LOGIN_REPORT_FAILED)
return _L("Failed to parse login report reason");
else if (code == BAMBU_NETWORK_ERR_BIND_RECEIVE_LOGIN_REPORT_TIMEOUT)
return _L("Receive login report timeout");
else
return _L("Unknown Failure");
}
BindMachineDialog::BindMachineDialog(Plater *plater /*= nullptr*/)
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Log in printer"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
{
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
@ -67,42 +108,7 @@ namespace GUI {
wxBoxSizer *m_sizer_right_h = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *m_sizer_right_v = new wxBoxSizer(wxVERTICAL);
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent& evt) {
switch (evt.GetState()) {
// Request completed
case wxWebRequest::State_Completed: {
wxImage avatar_stream = *evt.GetResponse().GetStream();
if (avatar_stream.IsOk()) {
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
auto bitmap = new wxBitmap(avatar_stream);
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
m_avatar->SetBitmap(*bitmap);
Layout();
}
break;
}
// Request failed
case wxWebRequest::State_Failed: {
break;
}
}
});
if (wxGetApp().is_user_login()) {
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickanme());
m_user_name->SetLabelText(username_text);
m_avatar = new wxStaticBitmap(m_panel_right, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(60), FromDIP(60)), 0);
web_request = wxWebSession::GetDefault().CreateRequest(this, wxGetApp().getAgent()->get_user_avatar());
if (!web_request.IsOk()) {
// todo request fail
}
// Start the request
web_request.Start();
}
m_avatar = new wxStaticBitmap(m_panel_right, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(60), FromDIP(60)), 0);
m_sizer_right_v->Add(m_avatar, 0, wxALIGN_CENTER, 0);
m_sizer_right_v->Add(0, 0, 0, wxTOP, 7);
m_sizer_right_v->Add(m_user_name, 0, wxALIGN_CENTER, 0);
@ -116,12 +122,252 @@ namespace GUI {
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(20));
m_status_text = new wxStaticText(this, wxID_ANY, _L("Would you like to log in this printer with current account?"), wxDefaultPosition,
wxSize(BIND_DIALOG_BUTTON_PANEL_SIZE.x, -1), wxST_ELLIPSIZE_END);
auto m_sizer_status_text = new wxBoxSizer(wxHORIZONTAL);
m_status_text = new wxStaticText(this, wxID_ANY, _L("Would you like to log in this printer with current account?"));
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
m_status_text->SetFont(::Label::Body_13);
m_status_text->Wrap(-1);
m_link_show_error = new wxStaticText(this, wxID_ANY, _L("Check the reason"));
m_link_show_error->SetForegroundColour(wxColour(0x6b6b6b));
m_link_show_error->SetFont(::Label::Head_13);
m_bitmap_show_error_close = create_scaled_bitmap("link_more_error_close",nullptr, 7);
m_bitmap_show_error_open = create_scaled_bitmap("link_more_error_open",nullptr, 7);
m_static_bitmap_show_error = new wxStaticBitmap(this, wxID_ANY, m_bitmap_show_error_open, wxDefaultPosition, wxSize(FromDIP(7), FromDIP(7)));
m_link_show_error->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
m_link_show_error->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
m_link_show_error->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
if (!m_show_error_info_state) { m_show_error_info_state = true; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_open); }
else { m_show_error_info_state = false; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_close); }
show_bind_failed_info(true);}
);
m_static_bitmap_show_error->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
m_static_bitmap_show_error->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
m_static_bitmap_show_error->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
if (!m_show_error_info_state) { m_show_error_info_state = true; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_open); }
else { m_show_error_info_state = false; m_static_bitmap_show_error->SetBitmap(m_bitmap_show_error_close); }
show_bind_failed_info(true);
});
m_link_show_error->Hide();
m_static_bitmap_show_error->Hide();
m_sizer_status_text->SetMinSize(wxSize(BIND_DIALOG_BUTTON_PANEL_SIZE.x, -1));
m_sizer_status_text->Add(m_status_text, 0, wxALIGN_CENTER, 0);
m_sizer_status_text->Add(m_link_show_error, 0, wxLEFT|wxALIGN_CENTER, FromDIP(8));
m_sizer_status_text->Add(m_static_bitmap_show_error, 0, wxLEFT|wxALIGN_CENTER, FromDIP(2));
//agreement
m_panel_agreement = new wxWindow(this,wxID_ANY);
m_panel_agreement->SetBackgroundColour(*wxWHITE);
m_panel_agreement->SetMinSize(wxSize(FromDIP(450), -1));
m_panel_agreement->SetMaxSize(wxSize(FromDIP(450), -1));
wxWrapSizer* sizer_privacy_agreement = new wxWrapSizer( wxHORIZONTAL, wxWRAPSIZER_DEFAULT_FLAGS );
wxWrapSizer* sizere_notice_agreement= new wxWrapSizer( wxHORIZONTAL, wxWRAPSIZER_DEFAULT_FLAGS );
wxBoxSizer* sizer_privacy_body = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizere_notice_body = new wxBoxSizer(wxHORIZONTAL);
auto m_checkbox_privacy = new CheckBox(m_panel_agreement, wxID_ANY);
auto m_st_privacy_title = new Label(m_panel_agreement, _L("Read and accept"));
m_st_privacy_title->SetFont(Label::Body_13);
m_st_privacy_title->SetForegroundColour(wxColour(38, 46, 48));
auto m_link_Terms_title = new Label(m_panel_agreement, _L("Terms and Conditions"));
m_link_Terms_title->SetFont(Label::Head_13);
m_link_Terms_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_Terms_title->Wrap(FromDIP(450));
m_link_Terms_title->SetForegroundColour(wxColour(0x00AE42));
m_link_Terms_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
wxString txt = _L("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.");
ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, _L("Terms and Conditions"), ConfirmBeforeSendDialog::ButtonStyle::ONLY_CONFIRM);
confirm_dlg.update_text(txt);
confirm_dlg.CenterOnParent();
confirm_dlg.on_show();
});
m_link_Terms_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
m_link_Terms_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
auto m_st_and_title = new Label(m_panel_agreement, _L("and"));
m_st_and_title->SetFont(Label::Body_13);
m_st_and_title->SetForegroundColour(wxColour(38, 46, 48));
auto m_link_privacy_title = new Label(m_panel_agreement, _L("Privacy Policy"));
m_link_privacy_title->SetFont(Label::Head_13);
m_link_privacy_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_privacy_title->Wrap(FromDIP(450));
m_link_privacy_title->SetForegroundColour(wxColour(0x00AE42));
m_link_privacy_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
std::string url;
std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code();
if (country_code == "CN") {
url = "https://www.bambulab.cn/policies/privacy";
}
else{
url = "https://www.bambulab.com/policies/privacy";
}
wxLaunchDefaultBrowser(url);
});
m_link_privacy_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND);});
m_link_privacy_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW);});
sizere_notice_agreement->Add(0, 0, 0, wxTOP, FromDIP(4));
sizer_privacy_agreement->Add(m_st_privacy_title, 0, wxALIGN_CENTER, 0);
sizer_privacy_agreement->Add(0, 0, 0, wxLEFT, FromDIP(5));
sizer_privacy_agreement->Add(m_link_Terms_title, 0, wxALIGN_CENTER, 0);
sizer_privacy_agreement->Add(m_st_and_title, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(5));
sizer_privacy_agreement->Add(m_link_privacy_title, 0, wxALIGN_CENTER, 0);
sizer_privacy_body->Add(m_checkbox_privacy, 0, wxALL, 0);
sizer_privacy_body->Add(0, 0, 0, wxLEFT, FromDIP(8));
sizer_privacy_body->Add(sizer_privacy_agreement, 1, wxEXPAND, 0);
wxString notice_title = _L("We ask for your help to improve everyone's printer");
wxString notice_link_title = _L("Statement about User Experience Improvement Program");
auto m_checkbox_notice = new CheckBox(m_panel_agreement, wxID_ANY);
auto m_st_notice_title = new Label(m_panel_agreement, notice_title);
m_st_notice_title->SetFont(Label::Body_13);
m_st_notice_title->SetForegroundColour(wxColour(38, 46, 48));
auto m_link_notice_title = new Label(m_panel_agreement, notice_link_title);
m_link_notice_title->SetFont(Label::Head_13);
m_link_notice_title->SetMaxSize(wxSize(FromDIP(450), -1));
m_link_notice_title->Wrap(FromDIP(450));
m_link_notice_title->SetForegroundColour(wxColour(0x00AE42));
m_link_notice_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
m_link_notice_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
m_link_notice_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
wxString txt = _L("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.");
ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, _L("Statement on User Experience Improvement Plan"), ConfirmBeforeSendDialog::ButtonStyle::ONLY_CONFIRM);
wxString model_id_text;
if (m_machine_info) {
model_id_text = m_machine_info->get_printer_type_display_str();
}
confirm_dlg.update_text(wxString::Format(txt, model_id_text, model_id_text));
confirm_dlg.CenterOnParent();
confirm_dlg.on_show();
});
sizere_notice_agreement->Add(0, 0, 0, wxTOP, FromDIP(4));
sizere_notice_agreement->Add(m_st_notice_title, 0, 0, wxALIGN_CENTER, 0);
sizere_notice_agreement->Add(0, 0, 0, wxLEFT, FromDIP(2));
sizere_notice_agreement->Add(m_link_notice_title, 0, 0, wxALIGN_CENTER, 0);
sizere_notice_body->Add(m_checkbox_notice, 0, wxALL, 0);
sizere_notice_body->Add(0, 0, 0, wxLEFT, FromDIP(8));
sizere_notice_body->Add(sizere_notice_agreement, 1, wxEXPAND, 0);
wxBoxSizer* sizer_agreement = new wxBoxSizer(wxVERTICAL);
sizer_agreement->Add(sizer_privacy_body, 1, wxEXPAND, 0);
sizer_agreement->Add(sizere_notice_body, 1, wxEXPAND, 0);
m_checkbox_privacy->Bind(wxEVT_TOGGLEBUTTON, [this, m_checkbox_privacy](auto& e) {
m_allow_privacy = m_checkbox_privacy->GetValue();
m_button_bind->Enable(m_allow_privacy);
e.Skip();
});
m_checkbox_notice->Bind(wxEVT_TOGGLEBUTTON, [this, m_checkbox_notice](auto& e) {
m_allow_notice = m_checkbox_notice->GetValue();
e.Skip();
});
m_panel_agreement->SetSizer(sizer_agreement);
m_panel_agreement->Layout();
//show bind failed info
m_sw_bind_failed_info = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(450), FromDIP(300)), wxVSCROLL);
m_sw_bind_failed_info->SetBackgroundColour(*wxWHITE);
m_sw_bind_failed_info->SetScrollRate(5, 5);
m_sw_bind_failed_info->SetMinSize(wxSize(FromDIP(450), FromDIP(90)));
m_sw_bind_failed_info->SetMaxSize(wxSize(FromDIP(450), FromDIP(90)));
wxBoxSizer* m_sizer_bind_failed_info = new wxBoxSizer(wxVERTICAL);
m_sw_bind_failed_info->SetSizer( m_sizer_bind_failed_info );
m_link_network_state = new Label(m_sw_bind_failed_info, _L("Check the status of current system services"));
m_link_network_state->SetForegroundColour(0x00AE42);
m_link_network_state->SetFont(::Label::Body_12);
m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); });
m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); });
m_link_network_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_ARROW); });
wxBoxSizer* sizer_error_code = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizer_extra_info = new wxBoxSizer(wxHORIZONTAL);
auto st_title_error_code = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, _L("Error code"));
auto st_title_error_code_doc = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, ": ");
m_st_txt_error_code = new Label(m_sw_bind_failed_info, wxEmptyString);
st_title_error_code->SetForegroundColour(0x909090);
st_title_error_code_doc->SetForegroundColour(0x909090);
m_st_txt_error_code->SetForegroundColour(0x909090);
st_title_error_code->SetFont(::Label::Body_13);
st_title_error_code_doc->SetFont(::Label::Body_13);
m_st_txt_error_code->SetFont(::Label::Body_13);
st_title_error_code->SetMinSize(wxSize(FromDIP(80), -1));
st_title_error_code->SetMaxSize(wxSize(FromDIP(80), -1));
m_st_txt_error_code->SetMinSize(wxSize(FromDIP(340), -1));
m_st_txt_error_code->SetMaxSize(wxSize(FromDIP(340), -1));
sizer_error_code->Add(st_title_error_code, 0, wxALL, 0);
sizer_error_code->Add(st_title_error_code_doc, 0, wxALL, 0);
sizer_error_code->Add(m_st_txt_error_code, 0, wxALL, 0);
auto st_title_error_desc = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, wxT("Error desc"));
auto st_title_error_desc_doc = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, ": ");
m_st_txt_error_desc = new Label(m_sw_bind_failed_info, wxEmptyString);
st_title_error_desc->SetForegroundColour(0x909090);
st_title_error_desc_doc->SetForegroundColour(0x909090);
m_st_txt_error_desc->SetForegroundColour(0x909090);
st_title_error_desc->SetFont(::Label::Body_13);
st_title_error_desc_doc->SetFont(::Label::Body_13);
m_st_txt_error_desc->SetFont(::Label::Body_13);
st_title_error_desc->SetMinSize(wxSize(FromDIP(80), -1));
st_title_error_desc->SetMaxSize(wxSize(FromDIP(80), -1));
m_st_txt_error_desc->SetMinSize(wxSize(FromDIP(340), -1));
m_st_txt_error_desc->SetMaxSize(wxSize(FromDIP(340), -1));
sizer_error_desc->Add(st_title_error_desc, 0, wxALL, 0);
sizer_error_desc->Add(st_title_error_desc_doc, 0, wxALL, 0);
sizer_error_desc->Add(m_st_txt_error_desc, 0, wxALL, 0);
auto st_title_extra_info = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, wxT("Extra info"));
auto st_title_extra_info_doc = new wxStaticText(m_sw_bind_failed_info, wxID_ANY, ": ");
m_st_txt_extra_info = new Label(m_sw_bind_failed_info, wxEmptyString);
st_title_extra_info->SetForegroundColour(0x909090);
st_title_extra_info_doc->SetForegroundColour(0x909090);
m_st_txt_extra_info->SetForegroundColour(0x909090);
st_title_extra_info->SetFont(::Label::Body_13);
st_title_extra_info_doc->SetFont(::Label::Body_13);
m_st_txt_extra_info->SetFont(::Label::Body_13);
st_title_extra_info->SetMinSize(wxSize(FromDIP(80), -1));
st_title_extra_info->SetMaxSize(wxSize(FromDIP(80), -1));
m_st_txt_extra_info->SetMinSize(wxSize(FromDIP(340), -1));
m_st_txt_extra_info->SetMaxSize(wxSize(FromDIP(340), -1));
sizer_extra_info->Add(st_title_extra_info, 0, wxALL, 0);
sizer_extra_info->Add(st_title_extra_info_doc, 0, wxALL, 0);
sizer_extra_info->Add(m_st_txt_extra_info, 0, wxALL, 0);
m_sizer_bind_failed_info->Add(m_link_network_state, 0, wxLEFT, 0);
m_sizer_bind_failed_info->Add(sizer_error_code, 0, wxLEFT, 0);
m_sizer_bind_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
m_sizer_bind_failed_info->Add(sizer_error_desc, 0, wxLEFT, 0);
m_sizer_bind_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
m_sizer_bind_failed_info->Add(sizer_extra_info, 0, wxLEFT, 0);
m_simplebook = new wxSimplebook(this, wxID_ANY, wxDefaultPosition,BIND_DIALOG_BUTTON_PANEL_SIZE, 0);
m_simplebook->SetBackgroundColour(*wxWHITE);
@ -132,14 +378,18 @@ namespace GUI {
wxBoxSizer *m_sizer_button = new wxBoxSizer(wxHORIZONTAL);
m_sizer_button->Add(0, 0, 1, wxEXPAND, 5);
m_button_bind = new Button(button_panel, _L("Confirm"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_bind->SetBackgroundColor(btn_bg_green);
m_button_bind->SetBorderColor(wxColour(0, 150, 136));
m_button_bind->SetBorderColor(*wxWHITE);
m_button_bind->SetTextColor(wxColour("#FFFFFE"));
m_button_bind->SetSize(BIND_DIALOG_BUTTON_SIZE);
m_button_bind->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
m_button_bind->SetCornerRadius(FromDIP(12));
m_button_bind->Enable(false);
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Hovered),
@ -165,8 +415,14 @@ namespace GUI {
//m_sizer_main->Add(m_sizer_button, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30));
m_sizer_main->Add(m_status_text, 0, wxALIGN_CENTER, 0);
show_bind_failed_info(false);
m_sizer_main->Add(m_sizer_status_text, 0, wxALIGN_CENTER, FromDIP(40));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10));
m_sizer_main->Add(m_panel_agreement, 0, wxALIGN_CENTER, 0);
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(10));
m_sizer_main->Add(m_sw_bind_failed_info, 0, wxALIGN_CENTER, 0);
m_sizer_main->Add(m_simplebook, 0, wxALIGN_CENTER, 0);
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(20));
@ -176,8 +432,27 @@ namespace GUI {
Centre(wxBOTH);
Bind(wxEVT_SHOW, &BindMachineDialog::on_show, this);
Bind(wxEVT_CLOSE_WINDOW, &BindMachineDialog::on_close, this);
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent& evt) {
switch (evt.GetState()) {
// Request completed
case wxWebRequest::State_Completed: {
wxImage avatar_stream = *evt.GetResponse().GetStream();
if (avatar_stream.IsOk()) {
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
auto bitmap = new wxBitmap(avatar_stream);
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
m_avatar->SetBitmap(*bitmap);
Layout();
}
break;
}
// Request failed
case wxWebRequest::State_Failed: {
break;
}
}
});
m_button_bind->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BindMachineDialog::on_bind_printer), NULL, this);
m_button_cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BindMachineDialog::on_cancel), NULL, this);
@ -198,19 +473,56 @@ namespace GUI {
this->Disconnect(EVT_BIND_UPDATE_MESSAGE, wxCommandEventHandler(BindMachineDialog::on_update_message), NULL, this);
}
//static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
//{
// register int realsize = size * nmemb;
// struct MemoryStruct *mem = (struct MemoryStruct *) userp;
// mem->memory = (char *) realloc(mem->memory, mem->size + realsize + 1);
// if (mem->memory) {
// memcpy(&(mem->memory[mem->size]), contents, realsize);
// mem->size += realsize;
// mem->memory[mem->size] = 0;
// }
// return realsize;
//}
wxString BindMachineDialog::get_print_error(wxString str)
{
wxString extra;
try {
json j = json::parse(str.utf8_string());
if (j.contains("err_code")) {
int error_code = j["err_code"].get<int>();
extra = wxGetApp().get_hms_query()->query_print_error_msg(error_code);
}
}
catch (...) {
;
}
if (extra.empty())
extra = str;
return extra;
}
void BindMachineDialog::show_bind_failed_info(bool show, int code, wxString description, wxString extra)
{
if (show) {
if (!m_sw_bind_failed_info->IsShown()) {
m_sw_bind_failed_info->Show(true);
m_result_extra = get_print_error(m_result_extra);
m_st_txt_error_code->SetLabelText(wxString::Format("%d", m_result_code));
m_st_txt_error_desc->SetLabelText( wxGetApp().filter_string(m_result_info));
m_st_txt_extra_info->SetLabelText( wxGetApp().filter_string(m_result_extra));
m_st_txt_error_code->Wrap(FromDIP(330));
m_st_txt_error_desc->Wrap(FromDIP(330));
m_st_txt_extra_info->Wrap(FromDIP(330));
}
else {
m_sw_bind_failed_info->Show(false);
}
Layout();
Fit();
}
else {
if (!m_sw_bind_failed_info->IsShown()) { return; }
m_sw_bind_failed_info->Show(false);
m_st_txt_error_code->SetLabelText(wxEmptyString);
m_st_txt_error_desc->SetLabelText(wxEmptyString);
m_st_txt_extra_info->SetLabelText(wxEmptyString);
Layout();
Fit();
}
}
void BindMachineDialog::on_cancel(wxCommandEvent &event)
{
@ -238,8 +550,15 @@ namespace GUI {
void BindMachineDialog::on_bind_fail(wxCommandEvent &event)
{
//m_status_text->SetLabel(_L("Would you like to log in this printer with current account?"));
m_simplebook->SetSelection(1);
m_link_show_error->Show(true);
m_static_bitmap_show_error->Show(true);
m_result_code = event.GetInt();
m_result_info = get_fail_reason(event.GetInt());
m_result_extra = event.GetString();
show_bind_failed_info(true, event.GetInt(), get_fail_reason(event.GetInt()), event.GetString());
}
void BindMachineDialog::on_update_message(wxCommandEvent &event)
@ -251,11 +570,19 @@ namespace GUI {
{
EndModal(wxID_OK);
MessageDialog msg_wingow(nullptr, _L("Log in successful."), "", wxAPPLY | wxOK);
if (msg_wingow.ShowModal() == wxOK) { return; }
msg_wingow.ShowModal();
if(m_machine_info) wxGetApp().on_start_subscribe_again(m_machine_info->dev_id);
}
void BindMachineDialog::on_bind_printer(wxCommandEvent &event)
{
m_result_code = 0;
m_result_extra = wxEmptyString;
m_result_info = wxEmptyString;
m_link_show_error->Hide();
m_static_bitmap_show_error->Hide();
show_bind_failed_info(false);
//check isset info
if (m_machine_info == nullptr || m_machine_info == NULL) return;
@ -269,6 +596,14 @@ namespace GUI {
m_simplebook->SetSelection(0);
m_bind_job = std::make_shared<BindJob>(m_status_bar, wxGetApp().plater(), m_machine_info->dev_id, m_machine_info->dev_ip, m_machine_info->bind_sec_link);
if (m_machine_info && (m_machine_info->printer_type == "BL-P001" || m_machine_info->printer_type == "BL-P002")) {
m_bind_job->set_improved(false);
}
else {
m_bind_job->set_improved(m_allow_notice);
}
m_bind_job->set_event_handle(this);
m_bind_job->start();
}
@ -279,8 +614,29 @@ void BindMachineDialog::on_dpi_changed(const wxRect &suggested_rect)
m_button_cancel->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
}
void BindMachineDialog::update_machine_info(MachineObject* info)
{
m_machine_info = info;
if (m_machine_info && (m_machine_info->printer_type == "BL-P001" || m_machine_info->printer_type == "BL-P002")) {
m_button_bind->Enable(true);
m_panel_agreement->Hide();
}
else {
m_button_bind->Enable(false);
m_panel_agreement->Show();
}
Layout();
Fit();
}
void BindMachineDialog::on_show(wxShowEvent &event)
{
m_allow_privacy = false;
m_allow_notice = false;
m_result_code = 0;
m_result_extra = wxEmptyString;
m_result_info = wxEmptyString;
if (event.IsShown()) {
auto img = m_machine_info->get_printer_thumbnail_img_str();
if (wxGetApp().dark_mode()) { img += "_dark"; }
@ -290,6 +646,18 @@ void BindMachineDialog::on_show(wxShowEvent &event)
m_printer_img->Show();
m_printer_name->SetLabelText(from_u8(m_machine_info->dev_name));
if (wxGetApp().is_user_login()) {
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickanme());
m_user_name->SetLabelText(username_text);
web_request = wxWebSession::GetDefault().CreateRequest(this, wxGetApp().getAgent()->get_user_avatar());
if (!web_request.IsOk()) {
// todo request fail
}
// Start the request
web_request.Start();
}
Layout();
event.Skip();
}
@ -299,7 +667,7 @@ void BindMachineDialog::on_show(wxShowEvent &event)
UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Log out printer"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
{
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetBackgroundColour(*wxWHITE);
@ -349,42 +717,6 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
wxBoxSizer *m_sizer_right_v = new wxBoxSizer(wxVERTICAL);
m_avatar = new wxStaticBitmap(m_panel_right, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(60), FromDIP(60)), 0);
if (wxGetApp().is_user_login()) {
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_name());
m_user_name->SetLabelText(username_text);
wxString avatar_url = wxGetApp().getAgent()->get_user_avatar();
wxWebRequest request = wxWebSession::GetDefault().CreateRequest(this, avatar_url);
if (!request.IsOk()) {
// todo request fail
}
request.Start();
}
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent &evt) {
switch (evt.GetState()) {
// Request completed
case wxWebRequest::State_Completed: {
wxImage avatar_stream = *evt.GetResponse().GetStream();
if (avatar_stream.IsOk()) {
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
auto bitmap = new wxBitmap(avatar_stream);
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
m_avatar->SetBitmap(*bitmap);
Layout();
}
break;
}
// Request failed
case wxWebRequest::State_Failed: {
break;
}
}
});
m_sizer_right_v->Add(m_avatar, 0, wxALIGN_CENTER, 0);
m_sizer_right_v->Add(0, 0, 0, wxTOP, 7);
m_sizer_right_v->Add(m_user_name, 0, wxALIGN_CENTER, 0);
@ -398,11 +730,9 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(20));
m_status_text = new wxStaticText(this, wxID_ANY, _L("Would you like to log out the printer?"), wxDefaultPosition,
wxSize(BIND_DIALOG_BUTTON_PANEL_SIZE.x, -1), wxST_ELLIPSIZE_END);
m_status_text = new wxStaticText(this, wxID_ANY, _L("Would you like to log out the printer?"), wxDefaultPosition, wxSize(BIND_DIALOG_BUTTON_PANEL_SIZE.x, -1), wxST_ELLIPSIZE_END);
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
m_status_text->SetFont(::Label::Body_13);
m_status_text->Wrap(-1);
@ -410,10 +740,10 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
m_sizer_button->Add(0, 0, 1, wxEXPAND, 5);
m_button_unbind = new Button(this, _L("Confirm"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_unbind->SetBackgroundColor(btn_bg_green);
m_button_unbind->SetBorderColor(wxColour(0, 150, 136));
m_button_unbind->SetBorderColor(wxColour(0, 174, 66));
m_button_unbind->SetTextColor(wxColour("#FFFFFE"));
m_button_unbind->SetSize(BIND_DIALOG_BUTTON_SIZE);
m_button_unbind->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
@ -448,11 +778,34 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
Bind(wxEVT_SHOW, &UnBindMachineDialog::on_show, this);
m_button_unbind->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_unbind_printer), NULL, this);
m_button_cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_cancel), NULL, this);
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent& evt) {
switch (evt.GetState()) {
// Request completed
case wxWebRequest::State_Completed: {
wxImage avatar_stream = *evt.GetResponse().GetStream();
if (avatar_stream.IsOk()) {
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
auto bitmap = new wxBitmap(avatar_stream);
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
m_avatar->SetBitmap(*bitmap);
Layout();
}
break;
}
// Request failed
case wxWebRequest::State_Failed: {
break;
}
}
});
wxGetApp().UpdateDlgDarkUI(this);
}
UnBindMachineDialog::~UnBindMachineDialog()
{
web_request.Cancel();
m_button_unbind->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_unbind_printer), NULL, this);
m_button_cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_cancel), NULL, this);
}
@ -516,6 +869,19 @@ void UnBindMachineDialog::on_show(wxShowEvent &event)
m_printer_img->Show();
m_printer_name->SetLabelText(from_u8(m_machine_info->dev_name));
if (wxGetApp().is_user_login()) {
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_name());
m_user_name->SetLabelText(username_text);
wxString avatar_url = wxGetApp().getAgent()->get_user_avatar();
web_request = wxWebSession::GetDefault().CreateRequest(this, avatar_url);
if (!web_request.IsOk()) {
// todo request fail
}
web_request.Start();
}
Layout();
event.Skip();
}

View file

@ -46,17 +46,34 @@ struct MemoryStruct
class BindMachineDialog : public DPIDialog
{
private:
wxWindow* m_panel_agreement;
wxStaticText * m_printer_name;
wxStaticText * m_user_name;
StaticBox * m_panel_left;
StaticBox * m_panel_right;
wxStaticText *m_status_text;
wxStaticText* m_link_show_error;
Button * m_button_bind;
Button * m_button_cancel;
wxSimplebook *m_simplebook;
wxStaticBitmap *m_avatar;
wxStaticBitmap *m_printer_img;
wxStaticBitmap *m_static_bitmap_show_error;
wxBitmap m_bitmap_show_error_close;
wxBitmap m_bitmap_show_error_open;
wxWebRequest web_request;
wxScrolledWindow* m_sw_bind_failed_info;
Label* m_bind_failed_info;
Label* m_st_txt_error_code{ nullptr };
Label* m_st_txt_error_desc{ nullptr };
Label* m_st_txt_extra_info{ nullptr };
Label* m_link_network_state{ nullptr };
wxString m_result_info;
wxString m_result_extra;
bool m_show_error_info_state = true;
bool m_allow_privacy{false};
bool m_allow_notice{false};
int m_result_code;
MachineObject * m_machine_info{nullptr};
std::shared_ptr<BindJob> m_bind_job;
@ -65,16 +82,19 @@ private:
public:
BindMachineDialog(Plater *plater = nullptr);
~BindMachineDialog();
void on_cancel(wxCommandEvent &event);
void show_bind_failed_info(bool show, int code = 0, wxString description = wxEmptyString, wxString extra = wxEmptyString);
void on_cancel(wxCommandEvent& event);
void on_bind_fail(wxCommandEvent &event);
void on_update_message(wxCommandEvent &event);
void on_bind_success(wxCommandEvent &event);
void on_bind_printer(wxCommandEvent &event);
void on_dpi_changed(const wxRect &suggested_rect) override;
void update_machine_info(MachineObject *info) { m_machine_info = info; };
void update_machine_info(MachineObject *info);
void on_show(wxShowEvent &event);
void on_close(wxCloseEvent& event);
void on_destroy();
wxString get_print_error(wxString str);
};
class UnBindMachineDialog : public DPIDialog
@ -88,6 +108,7 @@ protected:
MachineObject *m_machine_info{nullptr};
wxStaticBitmap *m_avatar;
wxStaticBitmap *m_printer_img;
wxWebRequest web_request;
public:
UnBindMachineDialog(Plater *plater = nullptr);

View file

@ -0,0 +1,462 @@
#include "CaliHistoryDialog.hpp"
#include "I18N.hpp"
#include "libslic3r/Utils.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "format.hpp"
#include "MsgDialog.hpp"
#include "slic3r/Utils/CalibUtils.hpp"
namespace Slic3r {
namespace GUI {
#define HISTORY_WINDOW_SIZE wxSize(FromDIP(700), FromDIP(600))
#define EDIT_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(160), FromDIP(24))
#define HISTORY_WINDOW_ITEMS_COUNT 5
static wxString get_preset_name_by_filament_id(std::string filament_id)
{
auto preset_bundle = wxGetApp().preset_bundle;
auto collection = &preset_bundle->filaments;
wxString preset_name = "";
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
if (filament_id.compare(it->filament_id) == 0) {
auto preset_parent = collection->get_preset_parent(*it);
if (preset_parent) {
if (!preset_parent->alias.empty())
preset_name = from_u8(preset_parent->alias);
else
preset_name = from_u8(preset_parent->name);
}
else {
if (!it->alias.empty())
preset_name = from_u8(it->alias);
else
preset_name = from_u8(it->name);
}
}
}
return preset_name;
}
HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history)
: DPIDialog(parent, wxID_ANY, _L("Flow Dynamics Calibration Result"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
, m_calib_results_history(calib_results_history)
{
this->SetBackgroundColour(*wxWHITE);
auto main_sizer = new wxBoxSizer(wxVERTICAL);
auto scroll_window = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
scroll_window->SetScrollRate(5, 5);
scroll_window->SetBackgroundColour(*wxWHITE);
scroll_window->SetMinSize(HISTORY_WINDOW_SIZE);
scroll_window->SetSize(HISTORY_WINDOW_SIZE);
scroll_window->SetMaxSize(HISTORY_WINDOW_SIZE);
auto scroll_sizer = new wxBoxSizer(wxVERTICAL);
scroll_window->SetSizer(scroll_sizer);
wxPanel* comboBox_panel = new wxPanel(scroll_window);
comboBox_panel->SetBackgroundColour(wxColour(238, 238, 238));
auto comboBox_sizer = new wxBoxSizer(wxVERTICAL);
comboBox_panel->SetSizer(comboBox_sizer);
comboBox_sizer->AddSpacer(10);
auto nozzle_dia_title = new Label(comboBox_panel, _L("Nozzle Diameter"));
nozzle_dia_title->SetFont(Label::Head_14);
comboBox_sizer->Add(nozzle_dia_title, 0, wxLEFT | wxRIGHT, FromDIP(15));
comboBox_sizer->AddSpacer(10);
m_comboBox_nozzle_dia = new ComboBox(comboBox_panel, wxID_ANY, "", wxDefaultPosition, wxSize(-1, FromDIP(24)), 0, nullptr, wxCB_READONLY);
comboBox_sizer->Add(m_comboBox_nozzle_dia, 0, wxLEFT | wxEXPAND | wxRIGHT, FromDIP(15));
comboBox_sizer->AddSpacer(10);
scroll_sizer->Add(comboBox_panel, 0, wxEXPAND | wxRIGHT, FromDIP(10));
scroll_sizer->AddSpacer(FromDIP(15));
wxPanel* tips_panel = new wxPanel(scroll_window, wxID_ANY);
tips_panel->SetBackgroundColour(*wxWHITE);
auto tips_sizer = new wxBoxSizer(wxVERTICAL);
tips_panel->SetSizer(tips_sizer);
m_tips = new Label(tips_panel, "");
m_tips->SetForegroundColour({ 145, 145, 145 });
tips_sizer->Add(m_tips, 0, wxEXPAND);
scroll_sizer->Add(tips_panel, 0, wxEXPAND);
scroll_sizer->AddSpacer(FromDIP(15));
m_history_data_panel = new wxPanel(scroll_window);
m_history_data_panel->SetBackgroundColour(*wxWHITE);
scroll_sizer->Add(m_history_data_panel, 1, wxEXPAND);
main_sizer->Add(scroll_window, 1, wxEXPAND | wxALL, FromDIP(10));
SetSizer(main_sizer);
Layout();
main_sizer->Fit(this);
CenterOnParent();
wxGetApp().UpdateDlgDarkUI(this);
m_comboBox_nozzle_dia->Bind(wxEVT_COMBOBOX, &HistoryWindow::on_select_nozzle, this);
m_refresh_timer = new wxTimer();
m_refresh_timer->SetOwner(this);
m_refresh_timer->Start(200);
Bind(wxEVT_TIMER, &HistoryWindow::on_timer, this);
}
HistoryWindow::~HistoryWindow()
{
m_refresh_timer->Stop();
}
void HistoryWindow::sync_history_result(MachineObject* obj)
{
BOOST_LOG_TRIVIAL(info) << "sync_history_result";
m_calib_results_history.clear();
if (obj)
m_calib_results_history = obj->pa_calib_tab;
sync_history_data();
if (m_calib_results_history.empty()) {
m_tips->SetLabel(_L("No History Result"));
}
else {
m_tips->SetLabel(_L("Success to get history result"));
}
m_tips->Refresh();
}
void HistoryWindow::on_device_connected(MachineObject* obj)
{
if (!obj) {
return;
}
curr_obj = obj;
// init nozzle value
static std::array<float, 4> nozzle_diameter_list = { 0.2f, 0.4f, 0.6f, 0.8f };
int selection = 1;
for (int i = 0; i < nozzle_diameter_list.size(); i++) {
m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f mm", nozzle_diameter_list[i]));
if (abs(curr_obj->nozzle_diameter - nozzle_diameter_list[i]) < 1e-3) {
selection = i;
}
}
m_comboBox_nozzle_dia->SetSelection(selection);
// trigger on_select nozzle
wxCommandEvent evt(wxEVT_COMBOBOX);
evt.SetEventObject(m_comboBox_nozzle_dia);
wxPostEvent(m_comboBox_nozzle_dia, evt);
}
void HistoryWindow::on_timer(wxTimerEvent& event)
{
update(curr_obj);
}
void HistoryWindow::update(MachineObject* obj)
{
if (!obj) return;
if (obj->cali_version != history_version) {
if (obj->has_get_pa_calib_tab) {
history_version = obj->cali_version;
reqeust_history_result(obj);
}
}
// sync when history is not empty
if (obj->has_get_pa_calib_tab && m_calib_results_history.empty()) {
sync_history_result(curr_obj);
}
}
void HistoryWindow::on_select_nozzle(wxCommandEvent& evt)
{
reqeust_history_result(curr_obj);
}
void HistoryWindow::reqeust_history_result(MachineObject* obj)
{
if (curr_obj) {
curr_obj->reset_pa_cali_history_result();
sync_history_result(curr_obj);
float nozzle_value = get_nozzle_value();
if (nozzle_value > 0) {
CalibUtils::emit_get_PA_calib_infos(nozzle_value);
m_tips->SetLabel(_L("Refreshing the historical Flow Dynamics Calibration records"));
BOOST_LOG_TRIVIAL(info) << "request calib history";
}
}
}
void HistoryWindow::enbale_action_buttons(bool enable) {
auto childern = m_history_data_panel->GetChildren();
for (auto child : childern) {
auto button = dynamic_cast<Button*>(child);
if (button) {
button->Enable(enable);
}
}
}
void HistoryWindow::sync_history_data() {
Freeze();
m_history_data_panel->DestroyChildren();
m_history_data_panel->Enable();
wxGridBagSizer* gbSizer;
gbSizer = new wxGridBagSizer(FromDIP(0), FromDIP(50));
gbSizer->SetFlexibleDirection(wxBOTH);
gbSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
m_history_data_panel->SetSizer(gbSizer, true);
auto title_name = new Label(m_history_data_panel, _L("Name"));
title_name->SetFont(Label::Head_14);
gbSizer->Add(title_name, { 0, 0 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
auto title_preset_name = new Label(m_history_data_panel, _L("Filament"));
title_preset_name->SetFont(Label::Head_14);
gbSizer->Add(title_preset_name, { 0, 1 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
auto title_k = new Label(m_history_data_panel, _L("Factor K"));
title_k->SetFont(Label::Head_14);
gbSizer->Add(title_k, { 0, 2 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
// Hide
//auto title_n = new Label(m_history_data_panel, wxID_ANY, _L("N"));
//title_n->SetFont(Label::Head_14);
//gbSizer->Add(title_n, { 0, 3 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
auto title_action = new Label(m_history_data_panel, _L("Action"));
title_action->SetFont(Label::Head_14);
gbSizer->Add(title_action, { 0, 3 }, { 1, 1 });
int i = 1;
for (auto& result : m_calib_results_history) {
auto name_value = new Label(m_history_data_panel, from_u8(result.name));
wxString preset_name = get_preset_name_by_filament_id(result.filament_id);
auto preset_name_value = new Label(m_history_data_panel, preset_name);
auto k_str = wxString::Format("%.3f", result.k_value);
auto n_str = wxString::Format("%.3f", result.n_coef);
auto k_value = new Label(m_history_data_panel, k_str);
auto n_value = new Label(m_history_data_panel, n_str);
n_value->Hide();
auto delete_button = new Button(m_history_data_panel, _L("Delete"));
delete_button->SetBackgroundColour(*wxWHITE);
delete_button->SetMinSize(wxSize(-1, FromDIP(24)));
delete_button->SetCornerRadius(FromDIP(12));
delete_button->Bind(wxEVT_BUTTON, [this, gbSizer, i, &result](auto& e) {
for (int j = 0; j < HISTORY_WINDOW_ITEMS_COUNT; j++) {
auto item = gbSizer->FindItemAtPosition({ i, j });
item->GetWindow()->Hide();
}
gbSizer->SetEmptyCellSize({ 0,0 });
m_history_data_panel->Layout();
m_history_data_panel->Fit();
CalibUtils::delete_PA_calib_result({ result.tray_id, result.cali_idx, result.nozzle_diameter, result.filament_id });
});
auto edit_button = new Button(m_history_data_panel, _L("Edit"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
edit_button->SetBackgroundColour(*wxWHITE);
edit_button->SetBackgroundColor(btn_bg_green);
edit_button->SetBorderColor(wxColour(0, 174, 66));
edit_button->SetTextColor(wxColour("#FFFFFE"));
edit_button->SetMinSize(wxSize(-1, FromDIP(24)));
edit_button->SetCornerRadius(FromDIP(12));
edit_button->Bind(wxEVT_BUTTON, [this, result, k_value, name_value, edit_button](auto& e) {
PACalibResult result_buffer = result;
result_buffer.k_value = stof(k_value->GetLabel().ToStdString());
result_buffer.name = name_value->GetLabel().ToUTF8().data();
EditCalibrationHistoryDialog dlg(this, result_buffer);
if (dlg.ShowModal() == wxID_OK) {
auto new_result = dlg.get_result();
wxString new_k_str = wxString::Format("%.3f", new_result.k_value);
k_value->SetLabel(new_k_str);
name_value->SetLabel(from_u8(new_result.name));
new_result.tray_id = -1;
CalibUtils::set_PA_calib_result({ new_result }, true);
enbale_action_buttons(false);
}
});
gbSizer->Add(name_value, { i, 0 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
gbSizer->Add(preset_name_value, { i, 1 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
gbSizer->Add(k_value, { i, 2 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
//gbSizer->Add(n_value, { i, 3 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
gbSizer->Add(delete_button, { i, 3 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
gbSizer->Add(edit_button, { i, 4 }, { 1, 1 }, wxBOTTOM, FromDIP(15));
i++;
}
wxGetApp().UpdateDlgDarkUI(this);
Layout();
Fit();
Thaw();
}
float HistoryWindow::get_nozzle_value()
{
double nozzle_value = 0.0;
wxString nozzle_value_str = m_comboBox_nozzle_dia->GetValue();
try {
nozzle_value_str.ToDouble(&nozzle_value);
}
catch (...) {
;
}
return nozzle_value;
}
EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow* parent, const PACalibResult& result)
: DPIDialog(parent, wxID_ANY, _L("Edit Flow Dynamics Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
, m_new_result(result)
{
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"));
TextInput* name_value = new TextInput(top_panel, from_u8(m_new_result.name), "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
name_value->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, name_value](auto& e) {
if (!name_value->GetTextCtrl()->GetValue().IsEmpty())
m_new_result.name = name_value->GetTextCtrl()->GetValue().ToUTF8().data();
});
name_value->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, name_value](auto& e) {
if (!name_value->GetTextCtrl()->GetValue().IsEmpty())
m_new_result.name = name_value->GetTextCtrl()->GetValue().ToUTF8().data();
e.Skip();
});
flex_sizer->Add(name_title);
flex_sizer->Add(name_value);
Label* preset_name_title = new Label(top_panel, _L("Filament"));
wxString preset_name = get_preset_name_by_filament_id(result.filament_id);
Label* preset_name_value = new Label(top_panel, preset_name);
flex_sizer->Add(preset_name_title);
flex_sizer->Add(preset_name_value);
Label* k_title = new Label(top_panel, _L("Factor K"));
auto k_str = wxString::Format("%.3f", m_new_result.k_value);
TextInput* k_value = new TextInput(top_panel, k_str, "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
k_value->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, k_value](auto& e) {
float k = 0.0f;
if (!CalibUtils::validate_input_k_value(k_value->GetTextCtrl()->GetValue(), &k)) {
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
}
wxString k_str = wxString::Format("%.3f", k);
k_value->GetTextCtrl()->SetValue(k_str);
m_new_result.k_value = k;
});
k_value->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, k_value](auto& e) {
float k = 0.0f;
if (!CalibUtils::validate_input_k_value(k_value->GetTextCtrl()->GetValue(), &k)) {
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
}
wxString k_str = wxString::Format("%.3f", k);
k_value->GetTextCtrl()->SetValue(k_str);
m_new_result.k_value = k;
e.Skip();
});
flex_sizer->Add(k_title);
flex_sizer->Add(k_value);
// Hide:
//Label* n_title = new Label(top_panel, _L("Factor N"));
//TextInput* n_value = new TextInput(top_panel, n, "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
//flex_sizer->Add(n_title);
//flex_sizer->Add(n_value);
panel_sizer->Add(flex_sizer);
panel_sizer->AddSpacer(FromDIP(25));
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
Button* save_btn = new Button(top_panel, _L("Save"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
save_btn->SetBackgroundColour(*wxWHITE);
save_btn->SetBackgroundColor(btn_bg_green);
save_btn->SetBorderColor(wxColour(0, 174, 66));
save_btn->SetTextColor(wxColour("#FFFFFE"));
save_btn->SetMinSize(wxSize(-1, FromDIP(24)));
save_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));
save_btn->Bind(wxEVT_BUTTON, &EditCalibrationHistoryDialog::on_save, this);
cancel_btn->Bind(wxEVT_BUTTON, &EditCalibrationHistoryDialog::on_cancel, this);
btn_sizer->AddStretchSpacer();
btn_sizer->Add(save_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);
}
EditCalibrationHistoryDialog::~EditCalibrationHistoryDialog() {
}
PACalibResult EditCalibrationHistoryDialog::get_result() {
return m_new_result;
}
void EditCalibrationHistoryDialog::on_save(wxCommandEvent& event) {
EndModal(wxID_OK);
}
void EditCalibrationHistoryDialog::on_cancel(wxCommandEvent& event) {
EndModal(wxID_CANCEL);
}
void EditCalibrationHistoryDialog::on_dpi_changed(const wxRect& suggested_rect)
{
}
} // namespace GUI
} // namespace Slic3r

View file

@ -0,0 +1,58 @@
#ifndef slic3r_GUI_CaliHistory_hpp_
#define slic3r_GUI_CaliHistory_hpp_
#include "GUI_Utils.hpp"
#include "wxExtensions.hpp"
#include "Widgets/ComboBox.hpp"
#include "DeviceManager.hpp"
namespace Slic3r {
namespace GUI {
class HistoryWindow : public DPIDialog {
public:
HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history);
~HistoryWindow();
void on_dpi_changed(const wxRect& suggested_rect) {}
void on_select_nozzle(wxCommandEvent& evt);
void reqeust_history_result(MachineObject* obj);
void sync_history_result(MachineObject* obj);
void on_device_connected(MachineObject* obj);
void on_timer(wxTimerEvent& event);
void update(MachineObject* obj);
protected:
void sync_history_data();
void enbale_action_buttons(bool enable);
float get_nozzle_value();
wxPanel* m_history_data_panel;
ComboBox* m_comboBox_nozzle_dia;
Label* m_tips;
wxTimer* m_refresh_timer { nullptr };
std::vector<PACalibResult> m_calib_results_history;
MachineObject* curr_obj { nullptr };
int history_version = -1;
};
class EditCalibrationHistoryDialog : public DPIDialog
{
public:
EditCalibrationHistoryDialog(wxWindow* parent, const PACalibResult& result);
~EditCalibrationHistoryDialog();
void on_dpi_changed(const wxRect& suggested_rect) override;
PACalibResult get_result();
protected:
virtual void on_save(wxCommandEvent& event);
virtual void on_cancel(wxCommandEvent& event);
protected:
PACalibResult m_new_result;
};
} // namespace GUI
} // namespace Slic3r
#endif

View file

@ -214,7 +214,8 @@ wxWindow* CalibrationDialog::create_check_option(wxString title, wxWindow* paren
void CalibrationDialog::update_cali(MachineObject *obj)
{
if (!obj) return;
if (obj->is_function_supported(PrinterFunction::FUNC_AI_MONITORING)) {
if (obj->is_function_supported(PrinterFunction::FUNC_AI_MONITORING)
&& obj->is_function_supported(PrinterFunction::FUNC_LIDAR_CALIBRATION)) {
select_xcam_cali->Show();
} else {
select_xcam_cali->Hide();

View file

@ -0,0 +1,727 @@
#include <wx/dcgraph.h>
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "CalibrationPanel.hpp"
#include "I18N.hpp"
namespace Slic3r { namespace GUI {
#define REFRESH_INTERVAL 1000
#define INITIAL_NUMBER_OF_MACHINES 0
#define LIST_REFRESH_INTERVAL 200
#define MACHINE_LIST_REFRESH_INTERVAL 2000
wxDEFINE_EVENT(EVT_FINISHED_UPDATE_MLIST, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_USER_MLIST, wxCommandEvent);
wxString get_calibration_type_name(CalibMode cali_mode)
{
switch (cali_mode) {
case CalibMode::Calib_PA_Line:
return _L("Flow Dynamics");
case CalibMode::Calib_Flow_Rate:
return _L("Flow Rate");
case CalibMode::Calib_Vol_speed_Tower:
return _L("Max Volumetric Speed");
case CalibMode::Calib_Temp_Tower:
return _L("Temperature");
case CalibMode::Calib_Retraction_tower:
return _L("Retraction");
default:
return "";
}
}
MObjectPanel::MObjectPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
{
wxPanel::Create(parent, id, pos, SELECT_MACHINE_ITEM_SIZE, style, name);
Bind(wxEVT_PAINT, &MObjectPanel::OnPaint, this);
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
m_printer_status_offline = ScalableBitmap(this, "printer_status_offline", 12);
m_printer_status_busy = ScalableBitmap(this, "printer_status_busy", 12);
m_printer_status_idle = ScalableBitmap(this, "printer_status_idle", 12);
m_printer_status_lock = ScalableBitmap(this, "printer_status_lock", 16);
m_printer_in_lan = ScalableBitmap(this, "printer_in_lan", 16);
Bind(wxEVT_ENTER_WINDOW, &MObjectPanel::on_mouse_enter, this);
Bind(wxEVT_LEAVE_WINDOW, &MObjectPanel::on_mouse_leave, this);
Bind(wxEVT_LEFT_UP, &MObjectPanel::on_mouse_left_up, this);
}
MObjectPanel::~MObjectPanel() {}
void MObjectPanel::set_printer_state(PrinterState state)
{
m_state = state;
Refresh();
}
void MObjectPanel::OnPaint(wxPaintEvent & event)
{
wxPaintDC dc(this);
doRender(dc);
}
void MObjectPanel::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 MObjectPanel::doRender(wxDC& dc)
{
auto left = 10;
wxSize size = GetSize();
dc.SetPen(*wxTRANSPARENT_PEN);
auto dwbitmap = m_printer_status_offline;
if (m_state == PrinterState::IDLE) { dwbitmap = m_printer_status_idle; }
if (m_state == PrinterState::BUSY) { dwbitmap = m_printer_status_busy; }
if (m_state == PrinterState::OFFLINE) { dwbitmap = m_printer_status_offline; }
if (m_state == PrinterState::LOCK) { dwbitmap = m_printer_status_lock; }
if (m_state == PrinterState::IN_LAN) { dwbitmap = m_printer_in_lan; }
// dc.DrawCircle(left, size.y / 2, 3);
dc.DrawBitmap(dwbitmap.bmp(), wxPoint(left, (size.y - dwbitmap.GetBmpSize().y) / 2));
left += dwbitmap.GetBmpSize().x + 8;
dc.SetFont(Label::Body_13);
dc.SetBackgroundMode(wxTRANSPARENT);
dc.SetTextForeground(StateColor::darkModeColorFor(SELECT_MACHINE_GREY900));
wxString dev_name = "";
if (m_info) {
dev_name = from_u8(m_info->dev_name);
if (m_state == PrinterState::IN_LAN) {
dev_name += _L("(LAN)");
}
}
auto sizet = dc.GetTextExtent(dev_name);
auto text_end = size.x - FromDIP(15);
wxString finally_name = dev_name;
if (sizet.x > (text_end - left)) {
auto limit_width = text_end - left - dc.GetTextExtent("...").x - 15;
for (auto i = 0; i < dev_name.length(); i++) {
auto curr_width = dc.GetTextExtent(dev_name.substr(0, i));
if (curr_width.x >= limit_width) {
finally_name = dev_name.substr(0, i) + "...";
break;
}
}
}
dc.DrawText(finally_name, wxPoint(left, (size.y - sizet.y) / 2));
if (m_hover) {
dc.SetPen(SELECT_MACHINE_BRAND);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(0, 0, size.x, size.y);
}
}
void MObjectPanel::update_machine_info(MachineObject* info, bool is_my_devices)
{
m_info = info;
m_is_my_devices = is_my_devices;
Refresh();
}
void MObjectPanel::on_mouse_enter(wxMouseEvent& evt)
{
m_hover = true;
Refresh();
}
void MObjectPanel::on_mouse_leave(wxMouseEvent& evt)
{
m_hover = false;
Refresh();
}
void MObjectPanel::on_mouse_left_up(wxMouseEvent& evt)
{
if (m_is_my_devices) {
if (m_info && m_info->is_lan_mode_printer()) {
if (m_info->has_access_right() && m_info->is_avaliable()) {
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
dev->set_selected_machine(m_info->dev_id);
}
}
else {
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
dev->set_selected_machine(m_info->dev_id);
}
wxCommandEvent event(EVT_DISSMISS_MACHINE_LIST);
event.SetEventObject(this->GetParent()->GetParent());
wxPostEvent(this, event);
}
}
SelectMObjectPopup::SelectMObjectPopup(wxWindow* parent)
:PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS), m_dismiss(false)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
SetSize(SELECT_MACHINE_POPUP_SIZE);
SetMinSize(SELECT_MACHINE_POPUP_SIZE);
SetMaxSize(SELECT_MACHINE_POPUP_SIZE);
Freeze();
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
SetBackgroundColour(SELECT_MACHINE_GREY400);
m_scrolledWindow = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, SELECT_MACHINE_LIST_SIZE, wxHSCROLL | wxVSCROLL);
m_scrolledWindow->SetBackgroundColour(*wxWHITE);
m_scrolledWindow->SetMinSize(SELECT_MACHINE_LIST_SIZE);
m_scrolledWindow->SetScrollRate(0, 5);
auto m_sizxer_scrolledWindow = new wxBoxSizer(wxVERTICAL);
m_scrolledWindow->SetSizer(m_sizxer_scrolledWindow);
m_scrolledWindow->Layout();
m_sizxer_scrolledWindow->Fit(m_scrolledWindow);
m_sizer_my_devices = new wxBoxSizer(wxVERTICAL);
m_sizxer_scrolledWindow->Add(m_sizer_my_devices, 0, wxEXPAND, 0);
m_sizer_main->Add(m_scrolledWindow, 0, wxALL | wxEXPAND, FromDIP(2));
SetSizer(m_sizer_main);
Layout();
Thaw();
#ifdef __APPLE__
m_scrolledWindow->Bind(wxEVT_LEFT_UP, &SelectMObjectPopup::OnLeftUp, this);
#endif // __APPLE__
m_refresh_timer = new wxTimer();
m_refresh_timer->SetOwner(this);
Bind(EVT_UPDATE_USER_MLIST, &SelectMObjectPopup::update_machine_list, this);
Bind(wxEVT_TIMER, &SelectMObjectPopup::on_timer, this);
Bind(EVT_DISSMISS_MACHINE_LIST, &SelectMObjectPopup::on_dissmiss_win, this);
}
SelectMObjectPopup::~SelectMObjectPopup() { delete m_refresh_timer; }
void SelectMObjectPopup::Popup(wxWindow* WXUNUSED(focus))
{
BOOST_LOG_TRIVIAL(trace) << "get_print_info: start";
if (m_refresh_timer) {
m_refresh_timer->Stop();
m_refresh_timer->Start(MACHINE_LIST_REFRESH_INTERVAL);
}
if (wxGetApp().is_user_login()) {
if (!get_print_info_thread) {
get_print_info_thread = new boost::thread(Slic3r::create_thread([&] {
NetworkAgent* agent = wxGetApp().getAgent();
unsigned int http_code;
std::string body;
int result = agent->get_user_print_info(&http_code, &body);
if (result == 0) {
m_print_info = body;
}
else {
m_print_info = "";
}
wxCommandEvent event(EVT_UPDATE_USER_MLIST);
event.SetEventObject(this);
wxPostEvent(this, event);
}));
}
}
wxPostEvent(this, wxTimerEvent());
PopupWindow::Popup();
}
void SelectMObjectPopup::OnDismiss()
{
BOOST_LOG_TRIVIAL(trace) << "get_print_info: dismiss";
m_dismiss = true;
if (m_refresh_timer) {
m_refresh_timer->Stop();
}
if (get_print_info_thread) {
if (get_print_info_thread->joinable()) {
get_print_info_thread->join();
delete get_print_info_thread;
get_print_info_thread = nullptr;
}
}
wxCommandEvent event(EVT_FINISHED_UPDATE_MLIST);
event.SetEventObject(this);
wxPostEvent(this, event);
}
bool SelectMObjectPopup::ProcessLeftDown(wxMouseEvent& event) {
return PopupWindow::ProcessLeftDown(event);
}
bool SelectMObjectPopup::Show(bool show) {
if (show) {
for (int i = 0; i < m_user_list_machine_panel.size(); i++) {
m_user_list_machine_panel[i]->mPanel->update_machine_info(nullptr);
m_user_list_machine_panel[i]->mPanel->Hide();
}
}
return PopupWindow::Show(show);
}
void SelectMObjectPopup::on_timer(wxTimerEvent& event)
{
BOOST_LOG_TRIVIAL(trace) << "SelectMObjectPopup on_timer";
wxGetApp().reset_to_active();
wxCommandEvent user_event(EVT_UPDATE_USER_MLIST);
user_event.SetEventObject(this);
wxPostEvent(this, user_event);
}
void SelectMObjectPopup::update_user_devices()
{
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
if (!m_print_info.empty()) {
dev->parse_user_print_info(m_print_info);
m_print_info = "";
}
m_bind_machine_list.clear();
m_bind_machine_list = dev->get_my_machine_list();
//sort list
std::vector<std::pair<std::string, MachineObject*>> user_machine_list;
for (auto& it : m_bind_machine_list) {
user_machine_list.push_back(it);
}
std::sort(user_machine_list.begin(), user_machine_list.end(), [&](auto& a, auto& b) {
if (a.second && b.second) {
return a.second->dev_name.compare(b.second->dev_name) < 0;
}
return false;
});
BOOST_LOG_TRIVIAL(trace) << "SelectMObjectPopup update_machine_list start";
this->Freeze();
m_scrolledWindow->Freeze();
int i = 0;
for (auto& elem : user_machine_list) {
MachineObject* mobj = elem.second;
MObjectPanel* op = nullptr;
if (i < m_user_list_machine_panel.size()) {
op = m_user_list_machine_panel[i]->mPanel;
op->Show();
}
else {
op = new MObjectPanel(m_scrolledWindow, wxID_ANY);
MPanel* mpanel = new MPanel();
mpanel->mIndex = wxString::Format("%d", i);
mpanel->mPanel = op;
m_user_list_machine_panel.push_back(mpanel);
m_sizer_my_devices->Add(op, 0, wxEXPAND, 0);
}
i++;
op->update_machine_info(mobj, true);
//set in lan
if (mobj->is_lan_mode_printer()) {
if (!mobj->is_online()) {
continue;
}
else {
if (mobj->has_access_right() && mobj->is_avaliable()) {
op->set_printer_state(PrinterState::IN_LAN);
op->SetToolTip(_L("Online"));
}
else {
op->set_printer_state(PrinterState::LOCK);
}
}
}
else {
if (!mobj->is_online()) {
op->SetToolTip(_L("Offline"));
op->set_printer_state(PrinterState::OFFLINE);
}
else {
if (mobj->is_in_printing()) {
op->SetToolTip(_L("Busy"));
op->set_printer_state(PrinterState::BUSY);
}
else {
op->SetToolTip(_L("Online"));
op->set_printer_state(PrinterState::IDLE);
}
}
}
}
for (int j = i; j < m_user_list_machine_panel.size(); j++) {
m_user_list_machine_panel[j]->mPanel->update_machine_info(nullptr);
m_user_list_machine_panel[j]->mPanel->Hide();
}
//m_sizer_my_devices->Layout();
if (m_my_devices_count != i) {
m_scrolledWindow->Fit();
}
m_scrolledWindow->Layout();
m_scrolledWindow->Thaw();
Layout();
Fit();
this->Thaw();
m_my_devices_count = i;
}
void SelectMObjectPopup::on_dissmiss_win(wxCommandEvent& event)
{
Dismiss();
}
void SelectMObjectPopup::update_machine_list(wxCommandEvent& event)
{
update_user_devices();
BOOST_LOG_TRIVIAL(trace) << "SelectMObjectPopup update_machine_list end";
}
void SelectMObjectPopup::OnLeftUp(wxMouseEvent& event)
{
auto mouse_pos = ClientToScreen(event.GetPosition());
auto wxscroll_win_pos = m_scrolledWindow->ClientToScreen(wxPoint(0, 0));
if (mouse_pos.x > wxscroll_win_pos.x && mouse_pos.y > wxscroll_win_pos.y && mouse_pos.x < (wxscroll_win_pos.x + m_scrolledWindow->GetSize().x) &&
mouse_pos.y < (wxscroll_win_pos.y + m_scrolledWindow->GetSize().y)) {
for (MPanel* p : m_user_list_machine_panel) {
auto p_rect = p->mPanel->ClientToScreen(wxPoint(0, 0));
if (mouse_pos.x > p_rect.x && mouse_pos.y > p_rect.y && mouse_pos.x < (p_rect.x + p->mPanel->GetSize().x) && mouse_pos.y < (p_rect.y + p->mPanel->GetSize().y)) {
wxMouseEvent event(wxEVT_LEFT_UP);
auto tag_pos = p->mPanel->ScreenToClient(mouse_pos);
event.SetPosition(tag_pos);
event.SetEventObject(p->mPanel);
wxPostEvent(p->mPanel, event);
}
}
}
}
CalibrationPanel::CalibrationPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style),
m_mobjectlist_popup(SelectMObjectPopup(this))
{
SetBackgroundColour(*wxWHITE);
init_tabpanel();
wxBoxSizer* sizer_main = new wxBoxSizer(wxVERTICAL);
sizer_main->Add(m_tabpanel, 1, wxEXPAND, 0);
SetSizerAndFit(sizer_main);
Layout();
init_timer();
Bind(wxEVT_TIMER, &CalibrationPanel::on_timer, this);
}
void CalibrationPanel::init_tabpanel() {
m_side_tools = new SideTools(this, wxID_ANY);
m_side_tools->get_panel()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CalibrationPanel::on_printer_clicked), NULL, this);
wxBoxSizer* sizer_side_tools = new wxBoxSizer(wxVERTICAL);
sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0);
m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
m_side_tools->set_table_panel(m_tabpanel);
m_tabpanel->SetBackgroundColour(*wxWHITE);
m_cali_panels[0] = new PressureAdvanceWizard(m_tabpanel);
m_cali_panels[1] = new FlowRateWizard(m_tabpanel);
//m_cali_panels[2] = new MaxVolumetricSpeedWizard(m_tabpanel);
for (int i = 0; i < (int)CALI_MODE_COUNT; i++) {
bool selected = false;
if (i == 0)
selected = true;
m_tabpanel->AddPage(m_cali_panels[i],
get_calibration_type_name(m_cali_panels[i]->get_calibration_mode()),
"",
selected);
}
for (int i = 0; i < (int)CALI_MODE_COUNT; i++)
m_tabpanel->SetPageImage(i, "");
auto padding_size = m_tabpanel->GetBtnsListCtrl()->GetPaddingSize(0);
m_tabpanel->GetBtnsListCtrl()->SetPaddingSize({ FromDIP(15), padding_size.y });
m_initialized = true;
}
void CalibrationPanel::init_timer()
{
m_refresh_timer = new wxTimer();
m_refresh_timer->SetOwner(this);
m_refresh_timer->Start(REFRESH_INTERVAL);
wxPostEvent(this, wxTimerEvent());
}
void CalibrationPanel::on_timer(wxTimerEvent& event) {
update_all();
}
void CalibrationPanel::update_print_error_info(int code, std::string msg, std::string extra) {
// update current wizard only
int curr_selected = m_tabpanel->GetSelection();
if (curr_selected >= 0 && curr_selected < CALI_MODE_COUNT) {
if (m_cali_panels[curr_selected]) {
auto page = m_cali_panels[curr_selected]->get_curr_step()->page;
if(page && page->get_page_type() == CaliPageType::CALI_PAGE_PRESET){
auto preset_page = static_cast<CalibrationPresetPage*>(page);
if (preset_page->get_page_status() == CaliPresetPageStatus::CaliPresetStatusSending)
preset_page->update_print_error_info(code, msg, extra);
}
}
}
}
void CalibrationPanel::update_all() {
NetworkAgent* m_agent = wxGetApp().getAgent();
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
obj = dev->get_selected_machine();
// update current wizard only
int curr_selected = m_tabpanel->GetSelection();
if (curr_selected >= 0 && curr_selected < CALI_MODE_COUNT) {
if (m_cali_panels[curr_selected])
m_cali_panels[curr_selected]->update(obj);
}
if (obj) {
if (last_obj != obj && obj->is_info_ready()) {
for (int i = 0; i < CALI_MODE_COUNT; i++) {
m_cali_panels[i]->on_device_connected(obj);
}
last_obj = obj;
}
}
// check valid machine
if (obj && dev->get_my_machine(obj->dev_id) == nullptr) {
dev->set_selected_machine("");
if (m_agent)
m_agent->set_user_selected_machine("");
show_status((int)MONITOR_NO_PRINTER);
return;
}
if (wxGetApp().is_user_login()) {
dev->check_pushing();
try {
m_agent->refresh_connection();
}
catch (...) {
;
}
}
if (obj) {
wxGetApp().reset_to_active();
if (obj->connection_type() != last_conn_type) {
last_conn_type = obj->connection_type();
}
}
m_side_tools->update_status(obj);
if (!obj) {
show_status((int)MONITOR_NO_PRINTER);
return;
}
if (obj->is_connecting()) {
show_status(MONITOR_CONNECTING);
return;
}
else if (!obj->is_connected()) {
int server_status = 0;
// only disconnected server in cloud mode
if (obj->connection_type() != "lan") {
if (m_agent) {
server_status = m_agent->is_server_connected() ? 0 : (int)MONITOR_DISCONNECTED_SERVER;
}
}
show_status((int)MONITOR_DISCONNECTED + server_status);
return;
}
show_status(MONITOR_NORMAL);
}
void CalibrationPanel::show_status(int status)
{
if (!m_initialized) return;
if (last_status == status)return;
if (last_status & (int)MonitorStatus::MONITOR_CONNECTING != 0) {
NetworkAgent* agent = wxGetApp().getAgent();
json j;
j["dev_id"] = obj ? obj->dev_id : "obj_nullptr";
if (status & (int)MonitorStatus::MONITOR_DISCONNECTED != 0) {
j["result"] = "failed";
if (agent) {
agent->track_event("connect_dev", j.dump());
}
}
else if (status & (int)MonitorStatus::MONITOR_NORMAL != 0) {
j["result"] = "success";
if (agent) {
agent->track_event("connect_dev", j.dump());
}
}
}
last_status = status;
BOOST_LOG_TRIVIAL(info) << "monitor: show_status = " << status;
Freeze();
// update panels
if (m_side_tools) { m_side_tools->show_status(status); };
if ((status & (int)MonitorStatus::MONITOR_NO_PRINTER) != 0) {
set_default();
m_tabpanel->Layout();
}
else if (((status & (int)MonitorStatus::MONITOR_NORMAL) != 0)
|| ((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0)
|| ((status & (int)MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|| ((status & (int)MonitorStatus::MONITOR_CONNECTING) != 0))
{
if (((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0)
|| ((status & (int)MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|| ((status & (int)MonitorStatus::MONITOR_CONNECTING) != 0))
{
set_default();
}
m_tabpanel->Layout();
}
Layout();
Thaw();
}
bool CalibrationPanel::Show(bool show) {
if (show) {
m_refresh_timer->Stop();
m_refresh_timer->SetOwner(this);
m_refresh_timer->Start(REFRESH_INTERVAL);
wxPostEvent(this, wxTimerEvent());
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
//set a default machine when obj is null
obj = dev->get_selected_machine();
if (obj == nullptr) {
dev->load_last_machine();
obj = dev->get_selected_machine();
if (obj)
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
}
else {
obj->reset_update_time();
}
}
}
else {
m_refresh_timer->Stop();
}
return wxPanel::Show(show);
}
void CalibrationPanel::on_printer_clicked(wxMouseEvent& event)
{
auto mouse_pos = ClientToScreen(event.GetPosition());
wxPoint rect = m_side_tools->ClientToScreen(wxPoint(0, 0));
if (!m_side_tools->is_in_interval()) {
wxPoint pos = m_side_tools->ClientToScreen(wxPoint(0, 0));
pos.y += m_side_tools->GetRect().height;
m_mobjectlist_popup.Move(pos);
#ifdef __linux__
m_mobjectlist_popup.SetSize(wxSize(m_side_tools->GetSize().x, -1));
m_mobjectlist_popup.SetMaxSize(wxSize(m_side_tools->GetSize().x, -1));
m_mobjectlist_popup.SetMinSize(wxSize(m_side_tools->GetSize().x, -1));
#endif
m_mobjectlist_popup.Popup();
}
}
void CalibrationPanel::set_default()
{
obj = nullptr;
last_conn_type = "undefined";
wxGetApp().sidebar().load_ams_list({}, {});
}
void CalibrationPanel::msw_rescale()
{
for (int i = 0; i < (int)CALI_MODE_COUNT; i++) {
m_cali_panels[i]->msw_rescale();
}
}
void CalibrationPanel::on_sys_color_changed()
{
for (int i = 0; i < (int)CALI_MODE_COUNT; i++) {
m_cali_panels[i]->on_sys_color_changed();
}
}
CalibrationPanel::~CalibrationPanel() {
m_side_tools->get_panel()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CalibrationPanel::on_printer_clicked), NULL, this);
if (m_refresh_timer)
m_refresh_timer->Stop();
delete m_refresh_timer;
}
}}

View file

@ -0,0 +1,135 @@
#ifndef slic3r_GUI_CalibrationPanel_hpp_
#define slic3r_GUI_CalibrationPanel_hpp_
#include "CalibrationWizard.hpp"
#include "Tabbook.hpp"
//#include "Widgets/SideTools.hpp"
namespace Slic3r { namespace GUI {
#define SELECT_MACHINE_GREY900 wxColour(38, 46, 48)
#define SELECT_MACHINE_GREY600 wxColour(144,144,144)
#define SELECT_MACHINE_GREY400 wxColour(206, 206, 206)
#define SELECT_MACHINE_BRAND wxColour(0, 174, 66)
#define SELECT_MACHINE_REMIND wxColour(255,111,0)
#define SELECT_MACHINE_LIGHT_GREEN wxColour(219, 253, 231)
#define CALI_MODE_COUNT 2
wxString get_calibration_type_name(CalibMode cali_mode);
class MObjectPanel : public wxPanel
{
private:
bool m_is_my_devices{ false };
bool m_hover{ false };
PrinterState m_state;
ScalableBitmap m_printer_status_offline;
ScalableBitmap m_printer_status_busy;
ScalableBitmap m_printer_status_idle;
ScalableBitmap m_printer_status_lock;
ScalableBitmap m_printer_in_lan;
MachineObject* m_info;
public:
MObjectPanel(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString& name = wxEmptyString);
~MObjectPanel();
void set_printer_state(PrinterState state);
void update_machine_info(MachineObject* info, bool is_my_devices = false);
protected:
void OnPaint(wxPaintEvent& event);
void render(wxDC& dc);
void doRender(wxDC& dc);
void on_mouse_enter(wxMouseEvent& evt);
void on_mouse_leave(wxMouseEvent& evt);
void on_mouse_left_up(wxMouseEvent& evt);
};
class MPanel
{
public:
wxString mIndex;
MObjectPanel* mPanel;
};
class SelectMObjectPopup : public PopupWindow
{
public:
SelectMObjectPopup(wxWindow* parent);
~SelectMObjectPopup();
// PopupWindow virtual methods are all overridden to log them
virtual void Popup(wxWindow* focus = NULL) wxOVERRIDE;
virtual void OnDismiss() wxOVERRIDE;
virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE;
virtual bool Show(bool show = true) wxOVERRIDE;
void update_machine_list(wxCommandEvent& event);
bool was_dismiss() { return m_dismiss; }
private:
int m_my_devices_count{ 0 };
int m_other_devices_count{ 0 };
bool m_dismiss{ false };
wxWindow* m_placeholder_panel { nullptr };
wxWindow* m_panel_body{ nullptr };
wxBoxSizer* m_sizer_body{ nullptr };
wxBoxSizer* m_sizer_my_devices{ nullptr };
wxScrolledWindow* m_scrolledWindow{ nullptr };
wxTimer* m_refresh_timer{ nullptr };
std::vector<MPanel*> m_user_list_machine_panel;
boost::thread* get_print_info_thread{ nullptr };
std::string m_print_info;
std::map<std::string, MachineObject*> m_bind_machine_list;
private:
void OnLeftUp(wxMouseEvent& event);
void on_timer(wxTimerEvent& event);
void update_user_devices();
void on_dissmiss_win(wxCommandEvent& event);
};
class CalibrationPanel : public wxPanel
{
public:
CalibrationPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~CalibrationPanel();
Tabbook* get_tabpanel() { return m_tabpanel; };
void update_print_error_info(int code, std::string msg, std::string extra);
void update_all();
void show_status(int status);
bool Show(bool show);
void on_printer_clicked(wxMouseEvent& event);
void set_default();
void msw_rescale();
void on_sys_color_changed();
protected:
void init_tabpanel();
void init_timer();
void on_timer(wxTimerEvent& event);
int last_status;
bool m_initialized { false };
std::string last_conn_type = "undedefined";
MachineObject* obj{ nullptr };
MachineObject* last_obj { nullptr };
SideTools* m_side_tools{ nullptr };
Tabbook* m_tabpanel{ nullptr };
SelectMObjectPopup m_mobjectlist_popup;
CalibrationWizard* m_cali_panels[CALI_MODE_COUNT];
wxTimer* m_refresh_timer = nullptr;
};
}} // namespace Slic3r::GUI
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,174 @@
#ifndef slic3r_GUI_CalibrationWizard_hpp_
#define slic3r_GUI_CalibrationWizard_hpp_
#include "../slic3r/Utils/CalibUtils.hpp"
#include "DeviceManager.hpp"
#include "CalibrationWizardPage.hpp"
#include "CalibrationWizardStartPage.hpp"
#include "CalibrationWizardPresetPage.hpp"
#include "CalibrationWizardCaliPage.hpp"
#include "CalibrationWizardSavePage.hpp"
namespace Slic3r { namespace GUI {
class CalibrationWizardPageStep
{
public:
CalibrationWizardPageStep(CalibrationWizardPage* data) {
page = data;
}
CalibrationWizardPageStep* prev { nullptr };
CalibrationWizardPageStep* next { nullptr };
CalibrationWizardPage* page { nullptr };
void chain(CalibrationWizardPageStep* step) {
if (!step) return;
this->next = step;
step->prev = this;
}
};
class CalibrationWizard : public wxPanel {
public:
CalibrationWizard(wxWindow* parent, CalibMode mode,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
~CalibrationWizard();
void on_cali_job_finished(wxCommandEvent& event);
virtual void on_cali_job_finished(wxString evt_data) {}
CalibrationWizardPageStep* get_curr_step() { return m_curr_step; }
void show_step(CalibrationWizardPageStep* step);
virtual void update(MachineObject* obj);
virtual void on_device_connected(MachineObject* obj);
virtual void set_cali_style(CalibrationStyle style) {
m_cali_style = style;
}
virtual void set_cali_method(CalibrationMethod method);
CalibMode get_calibration_mode() { return m_mode; }
bool save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, std::string& message);
virtual void cache_preset_info(MachineObject* obj, float nozzle_dia);
virtual void recover_preset_info(MachineObject *obj);
virtual void back_preset_info(MachineObject *obj, bool cali_finish);
void msw_rescale();
void on_sys_color_changed();
protected:
void on_cali_go_home();
protected:
/* wx widgets*/
wxScrolledWindow* m_scrolledWindow;
wxBoxSizer* m_all_pages_sizer;
CalibMode m_mode;
CalibrationStyle m_cali_style;
CalibrationMethod m_cali_method { CalibrationMethod::CALI_METHOD_MANUAL };
MachineObject* curr_obj { nullptr };
MachineObject* last_obj { nullptr };
CalibrationWizardPageStep* m_curr_step { nullptr };
CalibrationWizardPageStep* start_step { nullptr };
CalibrationWizardPageStep* preset_step { nullptr };
CalibrationWizardPageStep* cali_step { nullptr };
CalibrationWizardPageStep* save_step { nullptr };
CalibrationWizardPageStep* cali_coarse_step { nullptr };
CalibrationWizardPageStep* coarse_save_step { nullptr };
CalibrationWizardPageStep* cali_fine_step { nullptr };
CalibrationWizardPageStep* fine_save_step { nullptr };
/* save steps of calibration pages */
std::vector<CalibrationWizardPageStep*> m_page_steps;
SecondaryCheckDialog *go_home_dialog = nullptr;
};
class PressureAdvanceWizard : public CalibrationWizard {
public:
PressureAdvanceWizard(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~PressureAdvanceWizard() {};
protected:
void create_pages();
void on_cali_start();
void on_cali_save();
void on_cali_action(wxCommandEvent& evt);
void update(MachineObject* obj) override;
void on_device_connected(MachineObject* obj) override;
std::vector<PACalibResult> m_calib_results_history;
};
class FlowRateWizard : public CalibrationWizard {
public:
FlowRateWizard(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~FlowRateWizard() {};
void set_cali_method(CalibrationMethod method) override;
void on_cali_job_finished(wxString evt_data) override;
void cache_coarse_info(MachineObject *obj);
protected:
void create_pages();
void on_cali_action(wxCommandEvent& evt);
void on_cali_start(CaliPresetStage stage = CaliPresetStage::CALI_MANULA_STAGE_NONE, float cali_value = 0.0f, FlowRatioCaliSource from_page = FlowRatioCaliSource::FROM_PRESET_PAGE);
void on_cali_save();
void update(MachineObject* obj) override;
void on_device_connected(MachineObject* obj) override;
};
class MaxVolumetricSpeedWizard : public CalibrationWizard {
public:
MaxVolumetricSpeedWizard(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~MaxVolumetricSpeedWizard() {};
void on_cali_job_finished(wxString evt_data) override;
protected:
void create_pages();
void on_cali_action(wxCommandEvent& evt);
void on_cali_start();
void on_cali_save();
void on_device_connected(MachineObject *obj) override;
};
// save printer_type in command event
wxDECLARE_EVENT(EVT_DEVICE_CHANGED, wxCommandEvent);
wxDECLARE_EVENT(EVT_CALIBRATION_JOB_FINISHED, wxCommandEvent);
}} // namespace Slic3r::GUI
#endif

View file

@ -0,0 +1,456 @@
#include "CalibrationWizardCaliPage.hpp"
#include "MainFrame.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
namespace Slic3r { namespace GUI {
static const wxString NA_STR = _L("N/A");
CalibrationCaliPage::CalibrationCaliPage(wxWindow* parent, CalibMode cali_mode, CaliPageType cali_type,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationWizardPage(parent, id, pos, size, style)
{
m_cali_mode = cali_mode;
m_page_type = cali_type;
m_top_sizer = new wxBoxSizer(wxVERTICAL);
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
CalibrationCaliPage::~CalibrationCaliPage()
{
m_printing_panel->get_pause_resume_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CalibrationCaliPage::on_subtask_pause_resume), NULL, this);
m_printing_panel->get_abort_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CalibrationCaliPage::on_subtask_abort), NULL, this);
}
void CalibrationCaliPage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(true);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration"));
steps.Add(_L("Record Factor"));
m_step_panel = new CaliPageStepGuide(parent, steps);
m_step_panel->set_steps(1);
m_top_sizer->Add(m_step_panel, 0, wxEXPAND, 0);
m_picture_panel = new CaliPagePicture(parent);
m_top_sizer->Add(m_picture_panel, 0, wxEXPAND, 0);
m_top_sizer->AddSpacer(FromDIP(20));
set_cali_img();
m_printing_panel = new PrintingTaskPanel(parent, PrintingTaskType::CALIBRATION);
m_printing_panel->SetDoubleBuffered(true);
m_printing_panel->SetSize({ CALIBRATION_PROGRESSBAR_LENGTH, -1 });
m_printing_panel->SetMinSize({ CALIBRATION_PROGRESSBAR_LENGTH, -1 });
m_printing_panel->enable_pause_resume_button(false, "resume_disable");
m_printing_panel->enable_abort_button(false);
m_top_sizer->Add(m_printing_panel, 0, wxALIGN_CENTER, 0);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_CALI);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
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)
{
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
MachineObject* obj = dev->get_selected_machine();
if (!obj) return;
if (obj->can_resume())
obj->command_task_resume();
else
obj->command_task_pause();
}
void CalibrationCaliPage::on_subtask_abort(wxCommandEvent& event)
{
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
MachineObject* obj = dev->get_selected_machine();
if (!obj) return;
if (abort_dlg == nullptr) {
abort_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Cancel print"));
abort_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, obj](wxCommandEvent& e) {
if (obj) obj->command_task_abort();
});
}
abort_dlg->update_text(_L("Are you sure you want to cancel this print?"));
abort_dlg->on_show();
}
void CalibrationCaliPage::set_cali_img()
{
if (m_cali_mode == CalibMode::Calib_PA_Line) {
if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual", nullptr, 400));
}
else if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_auto", nullptr, 400));
}
}
else if (m_cali_mode == CalibMode::Calib_Flow_Rate) {
if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (m_page_type == CaliPageType::CALI_PAGE_CALI)
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse", nullptr, 400));
if (m_page_type == CaliPageType::CALI_PAGE_FINE_CALI)
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_fine", nullptr, 400));
else
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse", nullptr, 400));
}
else if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_auto", nullptr, 400));
}
}
else if (m_cali_mode == CalibMode::Calib_Vol_speed_Tower) {
m_picture_panel->set_img(create_scaled_bitmap("max_volumetric_speed_calibration", nullptr, 400));
}
}
void CalibrationCaliPage::clear_last_job_status()
{
m_is_between_start_and_running = true;
}
void CalibrationCaliPage::update(MachineObject* obj)
{
static int get_result_count = 0;
// enable calibration when finished
bool enable_cali = false;
if (obj) {
if (obj->print_error > 0) {
StatusPanel* status_panel = Slic3r::GUI::wxGetApp().mainframe->m_monitor->get_status_panel();
status_panel->obj = obj;
status_panel->update_error_message();
}
if (obj->print_status == "RUNNING")
m_is_between_start_and_running = false;
if (obj->is_connecting() || !obj->is_connected() || m_is_between_start_and_running) {
reset_printing_values();
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_CALI_NEXT, false);
return;
}
if (m_cali_mode == CalibMode::Calib_PA_Line) {
if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
if (get_obj_calibration_mode(obj) == m_cali_mode) {
if (obj->is_printing_finished()) {
if (obj->print_status == "FINISH") {
if (obj->get_pa_calib_result) {
enable_cali = true;
}
else {
// use selected diameter, add a counter to timeout, add a warning tips when get result failed
CalibUtils::emit_get_PA_calib_results(get_selected_calibration_nozzle_dia(obj));
BOOST_LOG_TRIVIAL(trace) << "CalibUtils::emit_get_PA_calib_results, auto count = " << get_result_count++;
enable_cali = false;
}
}
else if (obj->print_status == "FAILED") {
enable_cali = false;
}
}
else {
enable_cali = false;
}
}
} else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (get_obj_calibration_mode(obj) == m_cali_mode && obj->is_printing_finished()) {
enable_cali = true;
} else {
enable_cali = false;
}
} else {
assert(false);
}
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_CALI_NEXT, enable_cali);
} else if (m_cali_mode == CalibMode::Calib_Flow_Rate) {
if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
if (get_obj_calibration_mode(obj) == m_cali_mode) {
if (obj->is_printing_finished()) {
if (obj->print_status == "FINISH") {
if (obj->get_flow_calib_result) {
enable_cali = true;
}
else {
// use selected diameter, add a counter to timeout, add a warning tips when get result failed
CalibUtils::emit_get_flow_ratio_calib_results(get_selected_calibration_nozzle_dia(obj));
enable_cali = false;
}
}
else if (obj->print_status == "FAILED") {
enable_cali = false;
}
}
else {
enable_cali = false;
}
}
} else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (get_obj_calibration_mode(obj) == m_cali_mode && obj->is_printing_finished()) {
// use selected diameter, add a counter to timeout, add a warning tips when get result failed
CalibUtils::emit_get_flow_ratio_calib_results(get_selected_calibration_nozzle_dia(obj));
enable_cali = true;
}
else {
enable_cali = false;
}
} else {
assert(false);
}
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_CALI_NEXT, enable_cali);
}
else if (m_cali_mode == CalibMode::Calib_Vol_speed_Tower) {
if (get_obj_calibration_mode(obj) == m_cali_mode && obj->is_printing_finished()) {
enable_cali = true;
} else {
enable_cali = false;
}
}
else {
assert(false);
}
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_NEXT, enable_cali);
}
// only display calibration printing status
if (get_obj_calibration_mode(obj) == m_cali_mode) {
update_subtask(obj);
} else {
update_subtask(nullptr);
}
}
void CalibrationCaliPage::update_subtask(MachineObject* obj)
{
if (!obj) return;
if (obj->is_support_layer_num) {
m_printing_panel->update_layers_num(true);
}
else {
m_printing_panel->update_layers_num(false);
}
if (obj->is_system_printing()
|| obj->is_in_calibration()) {
reset_printing_values();
}
else if (obj->is_in_printing() || obj->print_status == "FINISH") {
if (obj->is_in_prepare() || obj->print_status == "SLICING") {
m_printing_panel->get_market_scoring_button()->Hide();
m_printing_panel->enable_abort_button(false);
m_printing_panel->enable_pause_resume_button(false, "pause_disable");
wxString prepare_text;
bool show_percent = true;
if (obj->is_in_prepare()) {
prepare_text = wxString::Format(_L("Downloading..."));
}
else if (obj->print_status == "SLICING") {
if (obj->queue_number <= 0) {
prepare_text = wxString::Format(_L("Cloud Slicing..."));
}
else {
prepare_text = wxString::Format(_L("In Cloud Slicing Queue, there are %s tasks ahead."), std::to_string(obj->queue_number));
show_percent = false;
}
}
else
prepare_text = wxString::Format(_L("Downloading..."));
if (obj->gcode_file_prepare_percent >= 0 && obj->gcode_file_prepare_percent <= 100 && show_percent)
prepare_text += wxString::Format("(%d%%)", obj->gcode_file_prepare_percent);
m_printing_panel->update_stage_value(prepare_text, 0);
m_printing_panel->update_progress_percent(NA_STR, wxEmptyString);
m_printing_panel->update_left_time(NA_STR);
m_printing_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
m_printing_panel->update_subtask_name(wxString::Format("%s", GUI::from_u8(obj->subtask_name)));
if (obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
m_printing_panel->show_profile_info(true, wxString::FromUTF8(obj->get_modeltask()->profile_name));
}
else {
m_printing_panel->show_profile_info(false);
}
if (obj->slice_info)
update_basic_print_data(false, obj->slice_info->weight, obj->slice_info->prediction);
}
else {
if (obj->can_resume()) {
m_printing_panel->enable_pause_resume_button(true, "resume");
}
else {
m_printing_panel->enable_pause_resume_button(true, "pause");
}
if (obj->print_status == "FINISH") {
m_printing_panel->enable_abort_button(false);
m_printing_panel->enable_pause_resume_button(false, "resume_disable");
bool is_market_task = obj->get_modeltask() && obj->get_modeltask()->design_id > 0;
if (is_market_task) {
m_printing_panel->get_market_scoring_button()->Show();
BOOST_LOG_TRIVIAL(info) << "SHOW_SCORE_BTU: design_id [" << obj->get_modeltask()->design_id << "] print_finish [" << m_print_finish << "]";
if (!m_print_finish && IsShownOnScreen()) {
m_print_finish = true;
}
}
else {
m_printing_panel->get_market_scoring_button()->Hide();
}
}
else {
m_printing_panel->enable_abort_button(true);
m_printing_panel->get_market_scoring_button()->Hide();
if (m_print_finish) {
m_print_finish = false;
}
}
// update printing stage
m_printing_panel->update_left_time(obj->mc_left_time);
if (obj->subtask_) {
m_printing_panel->update_stage_value(obj->get_curr_stage(), obj->subtask_->task_progress);
m_printing_panel->update_progress_percent(wxString::Format("%d", obj->subtask_->task_progress), "%");
m_printing_panel->update_layers_num(true, wxString::Format(_L("Layer: %d/%d"), obj->curr_layer, obj->total_layers));
}
else {
m_printing_panel->update_stage_value(obj->get_curr_stage(), 0);
m_printing_panel->update_progress_percent(NA_STR, wxEmptyString);
m_printing_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
}
}
m_printing_panel->update_subtask_name(wxString::Format("%s", GUI::from_u8(obj->subtask_name)));
if (obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
m_printing_panel->show_profile_info(wxString::FromUTF8(obj->get_modeltask()->profile_name));
}
else {
m_printing_panel->show_profile_info(false);
}
}
else {
reset_printing_values();
}
this->Layout();
}
void CalibrationCaliPage::update_basic_print_data(bool def, float weight, int prediction)
{
if (def) {
wxString str_prediction = wxString::Format("%s", get_bbl_time_dhms(prediction));
wxString str_weight = wxString::Format("%.2fg", weight);
m_printing_panel->show_priting_use_info(true, str_prediction, str_weight);
}
else {
m_printing_panel->show_priting_use_info(false, "0m", "0g");
}
}
void CalibrationCaliPage::reset_printing_values()
{
m_printing_panel->enable_pause_resume_button(false, "pause_disable");
m_printing_panel->enable_abort_button(false);
m_printing_panel->reset_printing_value();
m_printing_panel->update_subtask_name(NA_STR);
m_printing_panel->show_profile_info(false);
m_printing_panel->update_stage_value(wxEmptyString, 0);
m_printing_panel->update_progress_percent(NA_STR, wxEmptyString);
m_printing_panel->get_market_scoring_button()->Hide();
m_printing_panel->update_left_time(NA_STR);
m_printing_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
update_basic_print_data(false);
this->Layout();
}
void CalibrationCaliPage::on_device_connected(MachineObject* obj)
{
;
}
void CalibrationCaliPage::set_cali_method(CalibrationMethod method)
{
m_cali_method = method;
set_cali_img();
wxArrayString auto_steps;
auto_steps.Add(_L("Preset"));
auto_steps.Add(_L("Calibration"));
auto_steps.Add(_L("Record Factor"));
wxArrayString manual_steps;
manual_steps.Add(_L("Preset"));
manual_steps.Add(_L("Calibration1"));
manual_steps.Add(_L("Calibration2"));
manual_steps.Add(_L("Record Factor"));
if (method == CalibrationMethod::CALI_METHOD_AUTO) {
m_step_panel->set_steps_string(auto_steps);
m_step_panel->set_steps(1);
}
else if (method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (m_cali_mode == CalibMode::Calib_PA_Line) {
m_step_panel->set_steps_string(auto_steps);
m_step_panel->set_steps(1);
} else {
m_step_panel->set_steps_string(manual_steps);
if (m_page_type == CaliPageType::CALI_PAGE_CALI)
m_step_panel->set_steps(1);
else if (m_page_type == CaliPageType::CALI_PAGE_FINE_CALI) {
m_step_panel->set_steps(2);
}
else {
m_step_panel->set_steps(1);
}
}
}
else {
assert(false);
}
}
float CalibrationCaliPage::get_selected_calibration_nozzle_dia(MachineObject* obj)
{
// return selected if this is set
if (obj->cali_selected_nozzle_dia > 1e-3 && obj->cali_selected_nozzle_dia < 10.0f)
return obj->cali_selected_nozzle_dia;
// return default nozzle if nozzle diameter is set
if (obj->nozzle_diameter > 1e-3 && obj->nozzle_diameter < 10.0f)
return obj->nozzle_diameter;
// return 0.4 by default
return 0.4;
}
}}

View file

@ -0,0 +1,49 @@
#ifndef slic3r_GUI_CalibrationWizardCaliPage_hpp_
#define slic3r_GUI_CalibrationWizardCaliPage_hpp_
#include "CalibrationWizardPage.hpp"
#include "StatusPanel.hpp"
namespace Slic3r { namespace GUI {
class CalibrationCaliPage : public CalibrationWizardPage
{
public:
CalibrationCaliPage(wxWindow* parent,
CalibMode cali_mode,
CaliPageType cali_type = CaliPageType::CALI_PAGE_CALI,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
~CalibrationCaliPage();
void create_page(wxWindow* parent);
void on_subtask_pause_resume(wxCommandEvent& event);
void on_subtask_abort(wxCommandEvent& event);
void set_cali_img();
void update(MachineObject* obj) override;
void update_subtask(MachineObject* obj);
void update_basic_print_data(bool def, float weight = 0.0, int prediction = 0);
void reset_printing_values();
void clear_last_job_status();
void on_device_connected(MachineObject* obj) override;
void set_cali_method(CalibrationMethod method) override;
protected:
float get_selected_calibration_nozzle_dia(MachineObject* obj);
bool m_print_finish {false};
bool m_is_between_start_and_running { false };
wxBoxSizer* m_top_sizer;
CaliPageStepGuide* m_step_panel { nullptr };
PrintingTaskPanel* m_printing_panel { nullptr };
CaliPagePicture* m_picture_panel;
SecondaryCheckDialog* abort_dlg { nullptr };
};
}} // namespace Slic3r::GUI
#endif

View file

@ -0,0 +1,774 @@
#include "CalibrationWizardPage.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "MsgDialog.hpp"
namespace Slic3r { namespace GUI {
wxDEFINE_EVENT(EVT_CALI_ACTION, wxCommandEvent);
wxDEFINE_EVENT(EVT_CALI_TRAY_CHANGED, wxCommandEvent);
CalibrationStyle get_cali_style(MachineObject* obj)
{
if (!obj) return CalibrationStyle::CALI_STYLE_DEFAULT;
if (obj->get_printer_series() == PrinterSeries::SERIES_X1)
return CalibrationStyle::CALI_STYLE_X1;
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P)
return CalibrationStyle::CALI_STYLE_P1P;
return CalibrationStyle::CALI_STYLE_DEFAULT;
}
wxString get_cali_mode_caption_string(CalibMode mode)
{
if (mode == CalibMode::Calib_PA_Line)
return _L("Flow Dynamics Calibration");
if (mode == CalibMode::Calib_Flow_Rate)
return _L("Flow Rate Calibration");
if (mode == CalibMode::Calib_Vol_speed_Tower)
return _L("Max Volumetric Speed Calibration");
return "no cali_mode_caption";
}
wxString get_calibration_wiki_page(CalibMode cali_mode)
{
switch (cali_mode) {
case CalibMode::Calib_PA_Line:
return wxString("https://wiki.bambulab.com/en/software/bambu-studio/calibration_pa");
case CalibMode::Calib_Flow_Rate:
return wxString("https://wiki.bambulab.com/en/software/bambu-studio/calibration_flow_rate");
case CalibMode::Calib_Vol_speed_Tower:
return wxString("https://wiki.bambulab.com/en/software/bambu-studio/calibration_volumetric");
case CalibMode::Calib_Temp_Tower:
return wxString("https://wiki.bambulab.com/en/software/bambu-studio/calibration_temperature");
case CalibMode::Calib_Retraction_tower:
return wxString("https://wiki.bambulab.com/en/software/bambu-studio/calibration_retraction");
default:
return "";
}
}
CalibrationFilamentMode get_cali_filament_mode(MachineObject* obj, CalibMode mode)
{
// default
if (!obj) return CalibrationFilamentMode::CALI_MODEL_SINGLE;
if (mode == CalibMode::Calib_PA_Line) {
if (obj->get_printer_series() == PrinterSeries::SERIES_X1)
return CalibrationFilamentMode::CALI_MODEL_MULITI;
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P)
return CalibrationFilamentMode::CALI_MODEL_SINGLE;
}
else if (mode == CalibMode::Calib_Flow_Rate) {
if (obj->get_printer_series() == PrinterSeries::SERIES_X1)
return CalibrationFilamentMode::CALI_MODEL_SINGLE;
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P)
return CalibrationFilamentMode::CALI_MODEL_SINGLE;
}
return CalibrationFilamentMode::CALI_MODEL_SINGLE;
}
CalibMode get_obj_calibration_mode(const MachineObject* obj)
{
CalibrationMethod method;
int cali_stage;
return get_obj_calibration_mode(obj, method, cali_stage);
}
CalibMode get_obj_calibration_mode(const MachineObject* obj, int& cali_stage)
{
CalibrationMethod method;
return get_obj_calibration_mode(obj, method, cali_stage);
}
CalibMode get_obj_calibration_mode(const MachineObject* obj, CalibrationMethod& method, int& cali_stage)
{
method = CalibrationMethod::CALI_METHOD_MANUAL;
if (!obj) return CalibMode::Calib_None;
if (boost::contains(obj->m_gcode_file, "auto_filament_cali")) {
method = CalibrationMethod::CALI_METHOD_AUTO;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->m_gcode_file, "user_cali_manual_pa")) {
method = CalibrationMethod::CALI_METHOD_MANUAL;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->m_gcode_file, "extrusion_cali")) {
method = CalibrationMethod::CALI_METHOD_MANUAL;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->m_gcode_file, "abs_flowcalib_cali")) {
method = CalibrationMethod::CALI_METHOD_AUTO;
return CalibMode::Calib_Flow_Rate;
}
if (obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
if (boost::contains(obj->subtask_name, "auto_filament_cali")) {
method = CalibrationMethod::CALI_METHOD_AUTO;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->subtask_name, "user_cali_manual_pa")) {
method = CalibrationMethod::CALI_METHOD_MANUAL;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->subtask_name, "extrusion_cali")) {
method = CalibrationMethod::CALI_METHOD_MANUAL;
return CalibMode::Calib_PA_Line;
}
if (boost::contains(obj->subtask_name, "abs_flowcalib_cali")) {
method = CalibrationMethod::CALI_METHOD_AUTO;
return CalibMode::Calib_Flow_Rate;
}
}
CalibMode cali_mode = CalibUtils::get_calib_mode_by_name(obj->subtask_name, cali_stage);
if (cali_mode != CalibMode::Calib_None) {
method = CalibrationMethod::CALI_METHOD_MANUAL;
}
return cali_mode;
}
CaliPageButton::CaliPageButton(wxWindow* parent, CaliPageActionType type, wxString text)
: m_action_type(type),
Button(parent, text)
{
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
StateColor btn_bd_green(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Enabled));
StateColor btn_bd_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
StateColor btn_text_green(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Enabled));
StateColor btn_text_white(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
switch (m_action_type)
{
case CaliPageActionType::CALI_ACTION_MANAGE_RESULT:
this->SetLabel(_L("Manage Result"));
break;
case CaliPageActionType::CALI_ACTION_MANUAL_CALI:
this->SetLabel(_L("Manual Calibration"));
this->SetToolTip(_L("Result can be read by human eyes."));
break;
case CaliPageActionType::CALI_ACTION_AUTO_CALI:
this->SetLabel(_L("Auto-Calibration"));
this->SetToolTip(_L("We would use Lidar to read the calibration result"));
break;
case CaliPageActionType::CALI_ACTION_START:
this->SetLabel(_L("Start Calibration"));
break;
case CaliPageActionType::CALI_ACTION_PREV:
this->SetLabel(_L("Prev"));
break;
case CaliPageActionType::CALI_ACTION_RECALI:
this->SetLabel(_L("Recalibration"));
break;
case CaliPageActionType::CALI_ACTION_NEXT:
this->SetLabel(_L("Next"));
break;
case CaliPageActionType::CALI_ACTION_CALI_NEXT:
this->SetLabel(_L("Next"));
break;
case CaliPageActionType::CALI_ACTION_CALI:
this->SetLabel(_L("Calibrate"));
break;
case CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2:
this->SetLabel(_L("Calibrate"));
break;
case CaliPageActionType::CALI_ACTION_PA_SAVE:
this->SetLabel(_L("Finish"));
break;
case CaliPageActionType::CALI_ACTION_FLOW_SAVE:
this->SetLabel(_L("Finish"));
break;
case CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE:
this->SetLabel(_L("Finish"));
break;
case CaliPageActionType::CALI_ACTION_FLOW_FINE_SAVE:
this->SetLabel(_L("Finish"));
break;
case CaliPageActionType::CALI_ACTION_COMMON_SAVE:
this->SetLabel(_L("Finish"));
break;
default:
this->SetLabel("Unknown");
break;
}
switch (m_action_type)
{
case CaliPageActionType::CALI_ACTION_PREV:
case CaliPageActionType::CALI_ACTION_RECALI:
SetBackgroundColor(btn_bg_white);
SetBorderColor(btn_bd_white);
SetTextColor(btn_text_white);
break;
case CaliPageActionType::CALI_ACTION_START:
case CaliPageActionType::CALI_ACTION_NEXT:
case CaliPageActionType::CALI_ACTION_CALI:
case CaliPageActionType::CALI_ACTION_CALI_NEXT:
case CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2:
case CaliPageActionType::CALI_ACTION_PA_SAVE:
case CaliPageActionType::CALI_ACTION_FLOW_SAVE:
case CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE:
case CaliPageActionType::CALI_ACTION_FLOW_FINE_SAVE:
case CaliPageActionType::CALI_ACTION_COMMON_SAVE:
SetBackgroundColor(btn_bg_green);
SetBorderColor(btn_bd_green);
SetTextColor(btn_text_green);
break;
default:
break;
}
SetBackgroundColour(*wxWHITE);
SetFont(Label::Body_13);
SetMinSize(wxSize(-1, FromDIP(24)));
SetCornerRadius(FromDIP(12));
}
FilamentComboBox::FilamentComboBox(wxWindow* parent, const wxPoint& pos, const wxSize& size)
: wxPanel(parent, wxID_ANY, pos, size, wxTAB_TRAVERSAL)
{
SetBackgroundColour(*wxWHITE);
wxBoxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL);
m_comboBox = new CalibrateFilamentComboBox(this);
m_comboBox->SetSize(CALIBRATION_FILAMENT_COMBOX_SIZE);
m_comboBox->SetMinSize(CALIBRATION_FILAMENT_COMBOX_SIZE);
main_sizer->Add(m_comboBox->clr_picker, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(8));
main_sizer->Add(m_comboBox, 0, wxALIGN_CENTER);
this->SetSizer(main_sizer);
this->Layout();
main_sizer->Fit(this);
}
void FilamentComboBox::set_select_mode(CalibrationFilamentMode mode)
{
m_mode = mode;
if (m_checkBox)
m_checkBox->Show(m_mode == CalibrationFilamentMode::CALI_MODEL_MULITI);
if (m_radioBox)
m_radioBox->Show(m_mode == CalibrationFilamentMode::CALI_MODEL_SINGLE);
Layout();
}
void FilamentComboBox::load_tray_from_ams(int id, DynamicPrintConfig& tray)
{
m_comboBox->load_tray(tray);
m_tray_id = id;
m_tray_name = m_comboBox->get_tray_name();
m_is_bbl_filamnet = MachineObject::is_bbl_filament(m_comboBox->get_tag_uid());
Enable(m_comboBox->is_tray_exist());
if (m_comboBox->is_tray_exist()) {
if (!m_comboBox->is_compatible_with_printer()) {
SetValue(false);
}
if (m_radioBox)
m_radioBox->Enable(m_comboBox->is_compatible_with_printer());
if (m_checkBox)
m_checkBox->Enable(m_comboBox->is_compatible_with_printer());
}
// check compatibility
wxCommandEvent event(EVT_CALI_TRAY_CHANGED);
event.SetEventObject(GetParent());
wxPostEvent(GetParent(), event);
}
void FilamentComboBox::update_from_preset() { m_comboBox->update(); }
bool FilamentComboBox::Show(bool show)
{
return wxPanel::Show(show);
}
bool FilamentComboBox::Enable(bool enable) {
if (!enable)
SetValue(false);
if (m_radioBox)
m_radioBox->Enable(enable);
if (m_checkBox)
m_checkBox->Enable(enable);
return wxPanel::Enable(enable);
}
void FilamentComboBox::SetValue(bool value, bool send_event) {
if (m_radioBox) {
if (value == m_radioBox->GetValue()) {
if (m_checkBox) {
if (value == m_checkBox->GetValue())
return;
}
else {
return;
}
}
}
if (m_radioBox)
m_radioBox->SetValue(value);
if (m_checkBox)
m_checkBox->SetValue(value);
}
CaliPageCaption::CaliPageCaption(wxWindow* parent, CalibMode cali_mode,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
{
init_bitmaps();
SetBackgroundColour(*wxWHITE);
auto top_sizer = new wxBoxSizer(wxVERTICAL);
auto caption_sizer = new wxBoxSizer(wxHORIZONTAL);
m_prev_btn = new ScalableButton(this, wxID_ANY, "cali_page_caption_prev",
wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 30);
m_prev_btn->SetBackgroundColour(*wxWHITE);
caption_sizer->Add(m_prev_btn, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(10));
wxString title = get_cali_mode_caption_string(cali_mode);
Label* title_text = new Label(this, title);
title_text->SetFont(Label::Head_20);
title_text->Wrap(-1);
caption_sizer->Add(title_text, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(10));
m_help_btn = new ScalableButton(this, wxID_ANY, "cali_page_caption_help",
wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 30);
m_help_btn->Hide();
m_help_btn->SetBackgroundColour(*wxWHITE);
caption_sizer->Add(m_help_btn, 0, wxALIGN_CENTER);
caption_sizer->AddStretchSpacer();
m_wiki_url = get_calibration_wiki_page(cali_mode);
create_wiki(this);
caption_sizer->Add(m_wiki_text, 0);
top_sizer->Add(caption_sizer, 1, wxEXPAND);
top_sizer->AddSpacer(FromDIP(35));
this->SetSizer(top_sizer);
top_sizer->Fit(this);
// hover effect
//m_prev_btn->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {
// m_prev_btn->SetBitmap(m_prev_bmp_hover.bmp());
//});
//m_prev_btn->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {
// m_prev_btn->SetBitmap(m_prev_bmp_normal.bmp());
//});
// hover effect
//m_help_btn->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {
// m_help_btn->SetBitmap(m_help_bmp_hover.bmp());
// });
//m_help_btn->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {
// m_help_btn->SetBitmap(m_help_bmp_normal.bmp());
// });
// send event
m_prev_btn->Bind(wxEVT_BUTTON, [this](auto& e) {
wxCommandEvent event(EVT_CALI_ACTION);
event.SetEventObject(m_parent);
event.SetInt((int)(CaliPageActionType::CALI_ACTION_GO_HOME));
wxPostEvent(m_parent, event);
});
#ifdef __linux__
wxGetApp().CallAfter([this, title_text]() {
title_text->SetMinSize(title_text->GetSize() + wxSize{ FromDIP(150), title_text->GetCharHeight() / 2 });
Layout();
Fit();
});
#endif
}
void CaliPageCaption::init_bitmaps() {
m_prev_bmp_normal = ScalableBitmap(this, "cali_page_caption_prev", 30);
m_prev_bmp_hover = ScalableBitmap(this, "cali_page_caption_prev_hover", 30);
m_help_bmp_normal = ScalableBitmap(this, "cali_page_caption_help", 30);
m_help_bmp_hover = ScalableBitmap(this, "cali_page_caption_help_hover", 30);
}
void CaliPageCaption::create_wiki(wxWindow* parent)
{
m_wiki_text = new Label(parent, _L("Wiki"));
m_wiki_text->SetFont(Label::Head_14);
m_wiki_text->SetForegroundColour({ 0, 88, 220 });
m_wiki_text->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent& e) {
e.Skip();
SetCursor(wxCURSOR_HAND);
});
m_wiki_text->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) {
e.Skip();
SetCursor(wxCURSOR_ARROW);
});
m_wiki_text->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) {
if (!m_wiki_url.empty())
wxLaunchDefaultBrowser(m_wiki_url);
});
}
void CaliPageCaption::show_prev_btn(bool show)
{
m_prev_btn->Show(show);
}
void CaliPageCaption::show_help_icon(bool show)
{
//m_help_btn->Show(show);
m_help_btn->Hide();
}
void CaliPageCaption::on_sys_color_changed()
{
m_prev_btn->msw_rescale();
}
CaliPageStepGuide::CaliPageStepGuide(wxWindow* parent, wxArrayString steps,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style),
m_steps(steps)
{
SetBackgroundColour(*wxWHITE);
auto top_sizer = new wxBoxSizer(wxVERTICAL);
m_step_sizer = new wxBoxSizer(wxHORIZONTAL);
m_step_sizer->AddSpacer(FromDIP(90));
for (int i = 0; i < m_steps.size(); i++) {
Label* step_text = new Label(this, m_steps[i]);
step_text->SetForegroundColour(wxColour(206, 206, 206));
m_text_steps.push_back(step_text);
m_step_sizer->Add(step_text, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(15));
if (i != m_steps.size() - 1) {
auto line = new wxPanel(this, wxID_ANY, wxDefaultPosition);
line->SetBackgroundColour(*wxBLACK);
m_step_sizer->Add(line, 1, wxALIGN_CENTER);
}
}
m_step_sizer->AddSpacer(FromDIP(90));
top_sizer->Add(m_step_sizer, 0, wxEXPAND);
top_sizer->AddSpacer(FromDIP(30));
this->SetSizer(top_sizer);
top_sizer->Fit(this);
wxGetApp().UpdateDarkUIWin(this);
}
void CaliPageStepGuide::set_steps(int index)
{
for (Label* text_step : m_text_steps) {
text_step->SetForegroundColour(wxColour(206, 206, 206));
}
m_text_steps[index]->SetForegroundColour(*wxBLACK);
wxGetApp().UpdateDarkUIWin(this);
}
void CaliPageStepGuide::set_steps_string(wxArrayString steps)
{
m_steps.Clear();
m_text_steps.clear();
m_step_sizer->Clear(true);
m_steps = steps;
m_step_sizer->AddSpacer(FromDIP(90));
for (int i = 0; i < m_steps.size(); i++) {
Label* step_text = new Label(this, m_steps[i]);
step_text->SetForegroundColour(wxColour(206, 206, 206));
m_text_steps.push_back(step_text);
m_step_sizer->Add(step_text, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(15));
if (i != m_steps.size() - 1) {
auto line = new wxPanel(this, wxID_ANY, wxDefaultPosition);
line->SetBackgroundColour(*wxBLACK);
m_step_sizer->Add(line, 1, wxALIGN_CENTER);
}
}
m_step_sizer->AddSpacer(FromDIP(90));
wxGetApp().UpdateDarkUIWin(this);
Layout();
}
CaliPagePicture::CaliPagePicture(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
{
SetBackgroundColour(wxColour(0xCECECE));
auto top_sizer = new wxBoxSizer(wxHORIZONTAL);
top_sizer->AddStretchSpacer();
m_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
top_sizer->Add(m_img);
top_sizer->AddStretchSpacer();
this->SetSizer(top_sizer);
top_sizer->Fit(this);
}
void CaliPagePicture::set_img(const wxBitmap& bmp)
{
m_img->SetBitmap(bmp);
}
PAPageHelpPanel::PAPageHelpPanel(wxWindow* parent, bool ground_panel, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
{
if (ground_panel)
SetBackgroundColour(wxColour(238, 238, 238));
else
SetBackgroundColour(parent->GetBackgroundColour());
int left_align_padding = ground_panel ? FromDIP(20) : 0;
wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL);
top_sizer->AddSpacer(FromDIP(10));
auto help_text_title = new Label(this, _L("How to use calibration result?"));
help_text_title->SetFont(Label::Head_14);
top_sizer->Add(help_text_title, 0, wxLEFT | wxRIGHT, left_align_padding);
wxBoxSizer* help_text_sizer = new wxBoxSizer(wxHORIZONTAL);
auto help_text = new Label(this, _L("You could change the Flow Dynamics Calibration Factor in material editing"));
help_text->SetFont(Label::Body_14);
m_help_btn = new ScalableButton(this, wxID_ANY, "cali_page_caption_help", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 24);
m_help_btn->SetBackgroundColour(m_help_btn->GetParent()->GetBackgroundColour());
help_text_sizer->Add(help_text, 0, wxALIGN_CENTER | wxLEFT, left_align_padding);
help_text_sizer->Add(m_help_btn, 0, wxALIGN_CENTER | wxLEFT, FromDIP(8));
help_text_sizer->AddSpacer(FromDIP(20));
top_sizer->Add(help_text_sizer);
top_sizer->AddSpacer(FromDIP(6));
create_pop_window();
SetSizer(top_sizer);
top_sizer->Fit(this);
}
void PAPageHelpPanel::create_pop_window()
{
m_pop_win = new PopupWindow(this);
m_pop_win->SetBackgroundColour(*wxWHITE);
wxBoxSizer* pop_sizer = new wxBoxSizer(wxVERTICAL);
m_pop_win->SetSizer(pop_sizer);
wxStaticBitmap* img = new wxStaticBitmap(m_pop_win, wxID_ANY, wxNullBitmap);
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
img->SetBitmap(ScalableBitmap(this, "cali_fdc_editing_diagram_CN", 206).bmp());
} else {
img->SetBitmap(ScalableBitmap(this, "cali_fdc_editing_diagram", 206).bmp());
}
pop_sizer->Add(img, 1, wxEXPAND | wxALL, FromDIP(20));
m_pop_win->Layout();
m_pop_win->Fit();
m_pop_win->Bind(wxEVT_PAINT, [this](auto&) {
wxPaintDC dc(m_pop_win);
dc.SetPen({ 0xACACAC });
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle({ 0, 0 }, m_pop_win->GetSize());
});
m_help_btn->Bind(wxEVT_ENTER_WINDOW, [this](auto&) {
wxPoint pop_pos = m_help_btn->ClientToScreen(wxPoint(0, 0));
pop_pos.x -= FromDIP(60);
pop_pos.y -= m_pop_win->GetSize().y + FromDIP(10);
m_pop_win->Position(pop_pos, wxSize(0, 0));
m_pop_win->Popup();
});
m_help_btn->Bind(wxEVT_LEAVE_WINDOW, [this](auto&) {
m_pop_win->Dismiss();
});
}
CaliPageActionPanel::CaliPageActionPanel(wxWindow* parent,
CalibMode cali_mode,
CaliPageType page_type,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
{
m_parent = parent;
wxWindow* btn_parent = this;
if (cali_mode == CalibMode::Calib_PA_Line) {
if (page_type == CaliPageType::CALI_PAGE_START) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_MANAGE_RESULT));
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_MANUAL_CALI));
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_AUTO_CALI));
}
else if (page_type == CaliPageType::CALI_PAGE_PRESET) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI));
}
else if (page_type == CaliPageType::CALI_PAGE_CALI) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI_NEXT));
}
else if (page_type == CaliPageType::CALI_PAGE_PA_SAVE) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_PA_SAVE));
}
}
else if (cali_mode == CalibMode::Calib_Flow_Rate) {
if (page_type == CaliPageType::CALI_PAGE_START) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_MANUAL_CALI));
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_AUTO_CALI));
}
else if (page_type == CaliPageType::CALI_PAGE_PRESET) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI));
}
else if (page_type == CaliPageType::CALI_PAGE_CALI) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI_NEXT));
}
else if (page_type == CaliPageType::CALI_PAGE_COARSE_SAVE) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE));
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2));
}
else if (page_type == CaliPageType::CALI_PAGE_FINE_SAVE) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_FLOW_FINE_SAVE));
}
else if (page_type == CaliPageType::CALI_PAGE_FLOW_SAVE) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_FLOW_SAVE));
}
}
else {
if (page_type == CaliPageType::CALI_PAGE_START) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_START));
}
else if (page_type == CaliPageType::CALI_PAGE_PRESET) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI));
}
else if (page_type == CaliPageType::CALI_PAGE_CALI) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_CALI_NEXT));
}
else if (page_type == CaliPageType::CALI_PAGE_COMMON_SAVE) {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_COMMON_SAVE));
}
else {
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_PREV));
m_action_btns.push_back(new CaliPageButton(btn_parent, CaliPageActionType::CALI_ACTION_NEXT));
}
}
auto top_sizer = new wxBoxSizer(wxHORIZONTAL);
top_sizer->Add(0, 0, 1, wxEXPAND, 0);
for (int i = 0; i < m_action_btns.size(); i++) {
top_sizer->Add(m_action_btns[i], 0, wxALL, FromDIP(5));
m_action_btns[i]->Bind(wxEVT_BUTTON,
[this, i](wxCommandEvent& evt) {
wxCommandEvent event(EVT_CALI_ACTION);
event.SetEventObject(m_parent);
event.SetInt((int)m_action_btns[i]->get_action_type());
wxPostEvent(m_parent, event);
});
}
top_sizer->Add(0, 0, 1, wxEXPAND, 0);
this->SetSizer(top_sizer);
top_sizer->Fit(this);
}
void CaliPageActionPanel::bind_button(CaliPageActionType action_type, bool is_block)
{
for (int i = 0; i < m_action_btns.size(); i++) {
if (m_action_btns[i]->get_action_type() == action_type) {
if (is_block) {
m_action_btns[i]->Bind(wxEVT_BUTTON,
[this](wxCommandEvent& evt) {
MessageDialog msg(nullptr, _L("The current firmware version of the printer does not support calibration.\nPlease upgrade the printer firmware."), _L("Calibration not supported"), wxOK | wxICON_WARNING);
msg.ShowModal();
});
}
else {
m_action_btns[i]->Bind(wxEVT_BUTTON,
[this, i](wxCommandEvent& evt) {
wxCommandEvent event(EVT_CALI_ACTION);
event.SetEventObject(m_parent);
event.SetInt((int)m_action_btns[i]->get_action_type());
wxPostEvent(m_parent, event);
});
}
}
}
}
void CaliPageActionPanel::show_button(CaliPageActionType action_type, bool show)
{
for (int i = 0; i < m_action_btns.size(); i++) {
if (m_action_btns[i]->get_action_type() == action_type) {
m_action_btns[i]->Show(show);
}
}
Layout();
}
void CaliPageActionPanel::enable_button(CaliPageActionType action_type, bool enable)
{
for (int i = 0; i < m_action_btns.size(); i++) {
if (m_action_btns[i]->get_action_type() == action_type) {
m_action_btns[i]->Enable(enable);
}
}
}
CalibrationWizardPage::CalibrationWizardPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
, m_parent(parent)
{
SetBackgroundColour(*wxWHITE);
SetMinSize({ MIN_CALIBRATION_PAGE_WIDTH, -1 });
}
void CalibrationWizardPage::msw_rescale()
{
}
void CalibrationWizardPage::on_sys_color_changed()
{
m_page_caption->on_sys_color_changed();
}
}}

View file

@ -0,0 +1,306 @@
#ifndef slic3r_GUI_CalibrationWizardPage_hpp_
#define slic3r_GUI_CalibrationWizardPage_hpp_
#include "wx/event.h"
#include "Widgets/Button.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/TextInput.hpp"
#include "Widgets/AMSControl.hpp"
#include "Widgets/ProgressBar.hpp"
#include "wxExtensions.hpp"
#include "PresetComboBoxes.hpp"
#include "../slic3r/Utils/CalibUtils.hpp"
#include "../../libslic3r/Calib.hpp"
namespace Slic3r { namespace GUI {
#define MIN_CALIBRATION_PAGE_WIDTH FromDIP(1100)
#define PRESET_GAP FromDIP(25)
#define CALIBRATION_COMBOX_SIZE wxSize(FromDIP(500), FromDIP(24))
#define CALIBRATION_FILAMENT_COMBOX_SIZE wxSize(FromDIP(250), FromDIP(24))
#define CALIBRATION_OPTIMAL_INPUT_SIZE wxSize(FromDIP(300), FromDIP(24))
#define CALIBRATION_FROM_TO_INPUT_SIZE wxSize(FromDIP(160), FromDIP(24))
#define CALIBRATION_FGSIZER_HGAP FromDIP(50)
#define CALIBRATION_TEXT_MAX_LENGTH FromDIP(90) + CALIBRATION_FGSIZER_HGAP + 2 * CALIBRATION_FILAMENT_COMBOX_SIZE.x
#define CALIBRATION_PROGRESSBAR_LENGTH FromDIP(690)
class CalibrationWizard;
enum class CalibrationStyle : int
{
CALI_STYLE_DEFAULT = 0,
CALI_STYLE_X1,
CALI_STYLE_P1P,
};
CalibrationStyle get_cali_style(MachineObject* obj);
wxString get_cali_mode_caption_string(CalibMode mode);
enum CalibrationFilamentMode {
/* calibration single filament at once */
CALI_MODEL_SINGLE = 0,
/* calibration multi filament at once */
CALI_MODEL_MULITI,
};
enum CalibrationMethod {
CALI_METHOD_MANUAL = 0,
CALI_METHOD_AUTO,
CALI_METHOD_NONE,
};
wxString get_calibration_wiki_page(CalibMode cali_mode);
CalibrationFilamentMode get_cali_filament_mode(MachineObject* obj, CalibMode mode);
CalibMode get_obj_calibration_mode(const MachineObject* obj);
CalibMode get_obj_calibration_mode(const MachineObject* obj, int& cali_stage);
CalibMode get_obj_calibration_mode(const MachineObject* obj, CalibrationMethod& method, int& cali_stage);
enum class CaliPageType {
CALI_PAGE_START = 0,
CALI_PAGE_PRESET,
CALI_PAGE_CALI,
CALI_PAGE_COARSE_SAVE,
CALI_PAGE_FINE_CALI,
CALI_PAGE_FINE_SAVE,
CALI_PAGE_PA_SAVE,
CALI_PAGE_FLOW_SAVE,
CALI_PAGE_COMMON_SAVE,
};
class FilamentComboBox : public wxPanel
{
public:
FilamentComboBox(wxWindow* parent, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
~FilamentComboBox() {};
void set_select_mode(CalibrationFilamentMode mode);
CalibrationFilamentMode get_select_mode() { return m_mode; }
void load_tray_from_ams(int id, DynamicPrintConfig& tray);
void update_from_preset();
int get_tray_id() { return m_tray_id; }
bool is_bbl_filament() { return m_is_bbl_filamnet; }
std::string get_tray_name() { return m_tray_name; }
CalibrateFilamentComboBox* GetComboBox() { return m_comboBox; }
CheckBox* GetCheckBox() { return m_checkBox; }
void SetCheckBox(CheckBox* cb) { m_checkBox = cb; }
wxRadioButton* GetRadioBox() { return m_radioBox; }
void SetRadioBox(wxRadioButton* btn) { m_radioBox = btn; }
virtual bool Show(bool show = true);
virtual bool Enable(bool enable);
virtual void SetValue(bool value, bool send_event = true);
protected:
int m_tray_id { -1 };
std::string m_tray_name;
bool m_is_bbl_filamnet{ false };
CheckBox* m_checkBox{ nullptr };
wxRadioButton* m_radioBox{ nullptr };
CalibrateFilamentComboBox* m_comboBox{ nullptr };
CalibrationFilamentMode m_mode { CalibrationFilamentMode::CALI_MODEL_SINGLE };
};
typedef std::vector<FilamentComboBox*> FilamentComboBoxList;
class CaliPageCaption : public wxPanel
{
public:
CaliPageCaption(wxWindow* parent,
CalibMode cali_mode,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void show_prev_btn(bool show = true);
void show_help_icon(bool show = true);
void on_sys_color_changed();
protected:
ScalableButton* m_prev_btn;
ScalableButton* m_help_btn;
private:
void init_bitmaps();
void create_wiki(wxWindow* parent);
Label* m_wiki_text;
wxString m_wiki_url;
ScalableBitmap m_prev_bmp_normal;
ScalableBitmap m_prev_bmp_hover;
ScalableBitmap m_help_bmp_normal;
ScalableBitmap m_help_bmp_hover;
};
class CaliPageStepGuide : public wxPanel
{
public:
CaliPageStepGuide(wxWindow* parent,
wxArrayString steps,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void set_steps(int index);
void set_steps_string(wxArrayString steps);
protected:
wxArrayString m_steps;
wxBoxSizer* m_step_sizer;
std::vector<Label*> m_text_steps;
};
class CaliPagePicture : public wxPanel
{
public:
CaliPagePicture(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void set_img(const wxBitmap& bmp);
void paint_on_img();
protected:
wxStaticBitmap* m_img;
};
class PAPageHelpPanel : public wxPanel
{
public:
PAPageHelpPanel(wxWindow* parent,
bool ground_panel = true,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
protected:
void create_pop_window();
ScalableButton* m_help_btn;
PopupWindow* m_pop_win;
wxStaticBitmap* m_img;
};
enum class CaliPageActionType : int
{
CALI_ACTION_MANAGE_RESULT = 0,
CALI_ACTION_MANUAL_CALI,
CALI_ACTION_AUTO_CALI,
CALI_ACTION_START,
CALI_ACTION_CALI,
CALI_ACTION_FLOW_CALI_STAGE_2,
CALI_ACTION_RECALI,
CALI_ACTION_PREV,
CALI_ACTION_NEXT,
CALI_ACTION_CALI_NEXT,
CALI_ACTION_PA_SAVE,
CALI_ACTION_FLOW_SAVE,
CALI_ACTION_FLOW_COARSE_SAVE,
CALI_ACTION_FLOW_FINE_SAVE,
CALI_ACTION_COMMON_SAVE,
CALI_ACTION_GO_HOME,
CALI_ACTION_COUNT
};
class CaliPageButton : public Button
{
public:
CaliPageButton(wxWindow* parent, CaliPageActionType type, wxString text = wxEmptyString);
CaliPageActionType get_action_type() { return m_action_type; }
private:
CaliPageActionType m_action_type;
};
class CaliPageActionPanel : public wxPanel
{
public:
CaliPageActionPanel(wxWindow* parent,
CalibMode cali_mode,
CaliPageType page_type,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void bind_button(CaliPageActionType action_type, bool is_block);
void show_button(CaliPageActionType action_type, bool show = true);
void enable_button(CaliPageActionType action_type, bool enable = true);
protected:
std::vector<CaliPageButton*> m_action_btns;
};
class CalibrationWizardPage : public wxPanel
{
public:
CalibrationWizardPage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~CalibrationWizardPage() {};
CaliPageType get_page_type() { return m_page_type; }
CalibrationWizardPage* get_prev_page() { return m_prev_page; }
CalibrationWizardPage* get_next_page() { return m_next_page; }
void set_prev_page(CalibrationWizardPage* prev) { m_prev_page = prev; }
void set_next_page(CalibrationWizardPage* next) { m_next_page = next; }
CalibrationWizardPage* chain(CalibrationWizardPage* next)
{
set_next_page(next);
next->set_prev_page(this);
return next;
}
virtual void update(MachineObject* obj) { curr_obj = obj; }
/* device changed and connected */
virtual void on_device_connected(MachineObject* obj) { curr_obj = obj; }
virtual void on_reset_page() {}
virtual void set_cali_filament_mode(CalibrationFilamentMode mode) {
m_cali_filament_mode = mode;
}
virtual void set_cali_method(CalibrationMethod method) {
m_cali_method = method;
if (method == CalibrationMethod::CALI_METHOD_MANUAL) {
set_cali_filament_mode(CalibrationFilamentMode::CALI_MODEL_SINGLE);
}
}
void msw_rescale();
void on_sys_color_changed();
protected:
CalibMode m_cali_mode;
CaliPageType m_page_type;
CalibrationFilamentMode m_cali_filament_mode;
CalibrationMethod m_cali_method{ CalibrationMethod::CALI_METHOD_MANUAL };
MachineObject* curr_obj { nullptr };
wxWindow* m_parent { nullptr };
CaliPageCaption* m_page_caption { nullptr };
CaliPageActionPanel* m_action_panel { nullptr };
Label* m_statictext_printer_msg{ nullptr };
private:
CalibrationWizardPage* m_prev_page {nullptr};
CalibrationWizardPage* m_next_page {nullptr};
};
wxDECLARE_EVENT(EVT_CALI_ACTION, wxCommandEvent);
wxDECLARE_EVENT(EVT_CALI_TRAY_CHANGED, wxCommandEvent);
}} // namespace Slic3r::GUI
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,292 @@
#ifndef slic3r_GUI_CalibrationWizardPresetPage_hpp_
#define slic3r_GUI_CalibrationWizardPresetPage_hpp_
#include "CalibrationWizardPage.hpp"
namespace Slic3r { namespace GUI {
enum CaliPresetStage {
CALI_MANULA_STAGE_NONE = 0,
CALI_MANUAL_STAGE_1,
CALI_MANUAL_STAGE_2,
};
enum FlowRatioCaliSource {
FROM_PRESET_PAGE = 0,
FROM_COARSE_PAGE,
};
class CaliPresetCaliStagePanel : public wxPanel
{
public:
CaliPresetCaliStagePanel(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_cali_stage(CaliPresetStage stage, float value);
void get_cali_stage(CaliPresetStage& stage, float& value);
void set_flow_ratio_value(float flow_ratio);
protected:
CaliPresetStage m_stage;
wxBoxSizer* m_top_sizer;
wxRadioButton* m_complete_radioBox;
wxRadioButton* m_fine_radioBox;
TextInput * flow_ratio_input;
float m_flow_ratio_value;
};
class CaliPresetWarningPanel : public wxPanel
{
public:
CaliPresetWarningPanel(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_warning(wxString text);
protected:
wxBoxSizer* m_top_sizer;
Label* m_warning_text;
};
class CaliPresetTipsPanel : public wxPanel
{
public:
CaliPresetTipsPanel(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_params(int nozzle_temp, int bed_temp, float max_volumetric);
void get_params(int& nozzle_temp, int& bed_temp, float& max_volumetric);
protected:
wxBoxSizer* m_top_sizer;
TextInput* m_nozzle_temp;
Label* m_bed_temp;
TextInput* m_max_volumetric_speed;
};
class CaliPresetCustomRangePanel : public wxPanel
{
public:
CaliPresetCustomRangePanel(wxWindow* parent,
int input_value_nums = 3,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_unit(wxString unit);
void set_titles(wxArrayString titles);
void set_values(wxArrayString values);
wxArrayString get_values();
protected:
wxBoxSizer* m_top_sizer;
int m_input_value_nums;
std::vector<Label*> m_title_texts;
std::vector<TextInput*> m_value_inputs;
};
enum CaliPresetPageStatus
{
CaliPresetStatusInit = 0,
CaliPresetStatusNormal,
CaliPresetStatusSending,
CaliPresetStatusNoUserLogin,
CaliPresetStatusInvalidPrinter,
CaliPresetStatusConnectingServer,
CaliPresetStatusInUpgrading,
CaliPresetStatusInSystemPrinting,
CaliPresetStatusInPrinting,
CaliPresetStatusSendingCanceled,
CaliPresetStatusLanModeNoSdcard,
CaliPresetStatusNoSdcard,
CaliPresetStatusNeedForceUpgrading,
CaliPresetStatusNeedConsistencyUpgrading,
CaliPresetStatusUnsupportedPrinter,
CaliPresetStatusInConnecting,
CaliPresetStatusFilamentIncompatible,
};
class CalibrationPresetPage : public CalibrationWizardPage
{
public:
CalibrationPresetPage(wxWindow* parent,
CalibMode cali_mode,
bool custom_range = false,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void update_print_status_msg(wxString msg, bool is_warning);
wxString format_text(wxString& m_msg);
void stripWhiteSpace(std::string& str);
void update_priner_status_msg(wxString msg, bool is_warning);
void update(MachineObject* obj) override;
void on_device_connected(MachineObject* obj) override;
void update_print_error_info(int code, const std::string& msg, const std::string& extra);
void show_send_failed_info(bool show, int code = 0, wxString description = wxEmptyString, wxString extra = wxEmptyString);
void set_cali_filament_mode(CalibrationFilamentMode mode) override;
void set_cali_method(CalibrationMethod method) override;
void on_cali_start_job();
void on_cali_finished_job();
void init_with_machine(MachineObject* obj);
void sync_ams_info(MachineObject* obj);
void select_default_compatible_filament();
std::vector<FilamentComboBox*> get_selected_filament_combobox();
// key is tray_id
std::map<int, Preset*> get_selected_filaments();
void get_preset_info(
float& nozzle_dia,
BedType& plate_type);
void get_cali_stage(CaliPresetStage& stage, float& value);
std::shared_ptr<ProgressIndicator> get_sending_progress_bar() {
return m_send_progress_bar;
}
Preset* get_printer_preset(MachineObject* obj, float nozzle_value);
Preset* get_print_preset();
std::string get_print_preset_name();
wxArrayString get_custom_range_values();
CaliPresetPageStatus get_page_status() { return m_page_status; }
protected:
void create_selection_panel(wxWindow* parent);
void create_filament_list_panel(wxWindow* parent);
void create_ext_spool_panel(wxWindow* parent);
void create_sending_panel(wxWindow* parent);
void init_selection_values();
void update_filament_combobox(std::string ams_id = "");
void on_select_nozzle(wxCommandEvent& evt);
void on_select_plate_type(wxCommandEvent& evt);
void on_choose_ams(wxCommandEvent& event);
void on_choose_ext_spool(wxCommandEvent& event);
void on_select_tray(wxCommandEvent& event);
void on_switch_ams(std::string ams_id = "");
void on_recommend_input_value();
void check_filament_compatible();
bool is_filaments_compatiable(const std::vector<Preset*>& prests);
bool is_filament_in_blacklist(Preset* preset, std::string& error_tips);
bool is_filaments_compatiable(const std::vector<Preset*>& prests,
int& bed_temp,
std::string& incompatiable_filament_name,
std::string& error_tips);
float get_nozzle_value();
void update_plate_type_collection(CalibrationMethod method);
void update_combobox_filaments(MachineObject* obj);
void update_show_status();
void show_status(CaliPresetPageStatus status);
void Enable_Send_Button(bool enable);
void prepare_mode();
void sending_mode();
bool is_blocking_printing();
bool need_check_sdcard(MachineObject* obj);
CaliPresetPageStatus get_status() { return m_page_status; }
CaliPageStepGuide* m_step_panel{ nullptr };
CaliPresetCaliStagePanel* m_cali_stage_panel { nullptr };
wxPanel* m_selection_panel { nullptr };
wxPanel* m_filament_from_panel { nullptr };
Label* m_filament_list_tips{ nullptr };
wxPanel* m_multi_ams_panel { nullptr };
wxPanel* m_filament_list_panel { nullptr };
wxPanel* m_ext_spool_panel { nullptr };
CaliPresetWarningPanel* m_warning_panel { nullptr };
CaliPresetCustomRangePanel* m_custom_range_panel { nullptr };
CaliPresetTipsPanel* m_tips_panel { nullptr };
wxPanel* m_sending_panel { nullptr };
wxBoxSizer* m_top_sizer;
// m_selection_panel widgets
ComboBox* m_comboBox_nozzle_dia;
ComboBox* m_comboBox_bed_type;
ComboBox* m_comboBox_process;
wxRadioButton* m_ams_radiobox;
wxRadioButton* m_ext_spool_radiobox;
ScalableButton* m_ams_sync_button;
FilamentComboBoxList m_filament_comboBox_list;
FilamentComboBox* m_virtual_tray_comboBox;
// m_sending panel widgets
std::shared_ptr<BBLStatusBarSend> m_send_progress_bar;
wxScrolledWindow* m_sw_print_failed_info { nullptr };
Label* m_st_txt_error_code { nullptr };
Label* m_st_txt_error_desc { nullptr };
Label* m_st_txt_extra_info { nullptr };
int m_print_error_code;
std::string m_print_error_msg;
std::string m_print_error_extra;
std::vector<AMSItem*> m_ams_item_list;
// for update filament combobox, key : tray_id
std::map<int, DynamicPrintConfig> filament_ams_list;
CaliPresetPageStatus m_page_status { CaliPresetPageStatus::CaliPresetStatusInit };
bool m_show_custom_range { false };
bool m_has_filament_incompatible { false };
MachineObject* curr_obj { nullptr };
};
class MaxVolumetricSpeedPresetPage : public CalibrationPresetPage
{
public:
MaxVolumetricSpeedPresetPage(wxWindow * parent,
CalibMode cali_mode,
bool custom_range = false,
wxWindowID id = wxID_ANY,
const wxPoint &pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
};
}} // namespace Slic3r::GUI
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,296 @@
#ifndef slic3r_GUI_CalibrationWizardSavePage_hpp_
#define slic3r_GUI_CalibrationWizardSavePage_hpp_
#include "CalibrationWizardPage.hpp"
#include "Widgets/TextInput.hpp"
namespace Slic3r { namespace GUI {
enum CaliSaveStyle {
CALI_SAVE_P1P_STYLE = 0,
CALI_SAVE_X1_STYLE,
};
class CalibrationCommonSavePage : public CalibrationWizardPage
{
public:
CalibrationCommonSavePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
protected:
wxBoxSizer* m_top_sizer;
};
class PAColumnDataPanel : wxPanel {
public:
PAColumnDataPanel(
wxWindow* parent,
bool is_failed,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
bool is_failed() { return m_is_failed; }
int get_col_idx() { return m_col_idx; }
wxString get_k_str();
wxString get_n_str();
wxString get_name();
void set_data(wxString k_str, wxString n_str, wxString name);
private:
wxBoxSizer* m_top_sizer;
TextInput* m_k_value_input;
TextInput* m_n_value_input;
ComboBox* m_comboBox_tray_name;
int m_col_idx;
bool m_is_failed;
};
class CaliSavePresetValuePanel : public wxPanel
{
protected:
wxBoxSizer* m_top_sizer;
CaliPagePicture* m_picture_panel;
Label* m_value_title;
Label* m_save_name_title;
::TextInput* m_input_value;
::TextInput* m_input_name;
public:
CaliSavePresetValuePanel(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_img(const std::string& bmp_name_in);
void set_value_title(const wxString& title);
void set_save_name_title(const wxString& title);
void get_value(double& value);
void get_save_name(std::string& name);
void set_save_name(const std::string& name);
};
class CaliPASaveAutoPanel : public wxPanel
{
public:
CaliPASaveAutoPanel(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_machine_obj(MachineObject* obj) { m_obj = obj; }
std::vector<std::pair<int, std::string>> default_naming(std::vector<std::pair<int, std::string>> preset_names);
void sync_cali_result(const std::vector<PACalibResult>& cali_result, const std::vector<PACalibResult>& history_result);
void save_to_result_from_widgets(wxWindow* window, bool* out_is_valid, wxString* out_msg);
bool get_result(std::vector<PACalibResult>& out_result);
bool is_all_failed() { return m_is_all_failed; }
protected:
wxBoxSizer* m_top_sizer;
wxPanel* m_complete_text_panel;
wxPanel* m_part_failed_panel;
wxPanel* m_grid_panel{ nullptr };
std::map<int, PACalibResult> m_calib_results;// map<tray_id, PACalibResult>
std::vector<PACalibResult> m_history_results;
bool m_is_all_failed{ true };
MachineObject* m_obj{ nullptr };
};
class CaliPASaveManualPanel : public wxPanel
{
public:
CaliPASaveManualPanel(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_save_img();
void set_machine_obj(MachineObject* obj) { m_obj = obj; }
void set_default_name(const wxString& name);
bool get_result(PACalibResult& out_result);
virtual bool Show(bool show = true) override;
protected:
wxBoxSizer* m_top_sizer;
CaliPagePicture* m_picture_panel;
::TextInput* m_save_name_input;
::TextInput* m_k_val;
::TextInput* m_n_val;
MachineObject* m_obj{ nullptr };
};
class CaliPASaveP1PPanel : public wxPanel
{
public:
CaliPASaveP1PPanel(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_save_img();
bool get_result(float* out_k, float* out_n);
protected:
wxBoxSizer* m_top_sizer;
CaliPagePicture* m_picture_panel;
::TextInput* m_k_val;
::TextInput* m_n_val;
};
class CalibrationPASavePage : public CalibrationCommonSavePage
{
public:
CalibrationPASavePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void set_cali_method(CalibrationMethod method) override;
// sync widget value from obj cali result
void sync_cali_result(MachineObject* obj);
bool get_auto_result(std::vector<PACalibResult>& result) { return m_auto_panel->get_result(result); }
bool is_all_failed() { return m_auto_panel->is_all_failed(); }
bool get_manual_result(PACalibResult& result) { return m_manual_panel->get_result(result); }
bool get_p1p_result(float* k, float* n) { return m_p1p_panel->get_result(k, n); }
void show_panels(CalibrationMethod method, const PrinterSeries printer_ser);
void on_device_connected(MachineObject* obj);
void update(MachineObject* obj) override;
virtual bool Show(bool show = true) override;
protected:
CaliPageStepGuide* m_step_panel { nullptr };
CaliPASaveAutoPanel* m_auto_panel { nullptr };
CaliPASaveManualPanel* m_manual_panel { nullptr };
CaliPASaveP1PPanel* m_p1p_panel{ nullptr };
PAPageHelpPanel* m_help_panel;
CaliSaveStyle m_save_style;
};
class CalibrationFlowX1SavePage : public CalibrationCommonSavePage
{
public:
CalibrationFlowX1SavePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
// sync widget value from cali flow rate result
void sync_cali_result(const std::vector<FlowRatioCalibResult>& cali_result);
void save_to_result_from_widgets(wxWindow* window, bool* out_is_valid, wxString* out_msg);
bool get_result(std::vector<std::pair<wxString, float>>& out_results);
bool is_all_failed() { return m_is_all_failed; }
virtual bool Show(bool show = true) override;
protected:
CaliPageStepGuide* m_step_panel{ nullptr };
wxPanel* m_complete_text_panel;
wxPanel* m_part_failed_panel;
wxPanel* m_grid_panel{ nullptr };
std::map<int, std::pair<wxString, float>> m_save_results; // map<tray_id, <name, flow ratio>>
bool m_is_all_failed{ true };
};
class CalibrationFlowCoarseSavePage : public CalibrationCommonSavePage
{
public:
CalibrationFlowCoarseSavePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void set_save_img();
void set_default_name(const wxString& name);
bool is_skip_fine_calibration();
void set_curr_flow_ratio(float value);
bool get_result(float* out_value, wxString* out_name);
virtual bool Show(bool show = true) override;
protected:
CaliPageStepGuide* m_step_panel{ nullptr };
CaliPagePicture* m_picture_panel;
ComboBox* m_optimal_block_coarse;
TextInput* m_save_name_input;
bool m_skip_fine_calibration = false;
float m_curr_flow_ratio;
float m_coarse_flow_ratio;
};
class CalibrationFlowFineSavePage : public CalibrationCommonSavePage
{
public:
CalibrationFlowFineSavePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void set_save_img();
void set_default_name(const wxString& name);
void set_curr_flow_ratio(float value);
bool get_result(float* out_value, wxString* out_name);
virtual bool Show(bool show = true) override;
protected:
CaliPageStepGuide* m_step_panel{ nullptr };
CaliPagePicture* m_picture_panel;
ComboBox* m_optimal_block_fine;
TextInput* m_save_name_input;
float m_curr_flow_ratio;
float m_fine_flow_ratio;
};
class CalibrationMaxVolumetricSpeedSavePage : public CalibrationCommonSavePage
{
public:
CalibrationMaxVolumetricSpeedSavePage(wxWindow *parent, wxWindowID id = wxID_ANY,
const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
void create_page(wxWindow *parent);
void set_save_img();
bool get_save_result(double &value, std::string &name);
void set_prest_name(const std::string &name) { m_save_preset_panel->set_save_name(name); };
virtual bool Show(bool show = true) override;
protected:
CaliPageStepGuide *m_step_panel{nullptr};
CaliSavePresetValuePanel *m_save_preset_panel;
};
}} // namespace Slic3r::GUI
#endif

View file

@ -0,0 +1,352 @@
#include "CalibrationWizardStartPage.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
namespace Slic3r { namespace GUI {
#define CALIBRATION_START_PAGE_TEXT_MAX_LENGTH FromDIP(1000)
CalibrationStartPage::CalibrationStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
:CalibrationWizardPage(parent, id, pos, size, style)
{
m_top_sizer = new wxBoxSizer(wxVERTICAL);
}
void CalibrationStartPage::create_when(wxWindow* parent, wxString title, wxString content)
{
m_when_title = new Label(this, title);
m_when_title->SetFont(Label::Head_14);
m_when_title->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
m_when_content = new Label(this, content);;
m_when_content->SetFont(Label::Body_14);
m_when_content->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
}
void CalibrationStartPage::create_about(wxWindow* parent, wxString title, wxString content)
{
m_about_title = new Label(this, title);
m_about_title->SetFont(Label::Head_14);
m_about_title->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
m_about_content = new Label(this, content);
m_about_content->SetFont(Label::Body_14);
m_about_content->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
}
void CalibrationStartPage::create_bitmap(wxWindow* parent, const wxBitmap& before_img, const wxBitmap& after_img)
{
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
m_before_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
m_before_bmp->SetBitmap(before_img);
m_images_sizer->Add(m_before_bmp, 0, wxALL, 0);
m_images_sizer->AddSpacer(FromDIP(20));
m_after_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
m_after_bmp->SetBitmap(after_img);
m_images_sizer->Add(m_after_bmp, 0, wxALL, 0);
}
void CalibrationStartPage::create_bitmap(wxWindow* parent, std::string before_img, std::string after_img)
{
wxBitmap before_bmp = create_scaled_bitmap(before_img, nullptr, 350);
wxBitmap after_bmp = create_scaled_bitmap(after_img, nullptr, 350);
create_bitmap(parent, before_bmp, after_bmp);
}
void CalibrationStartPage::create_bitmap(wxWindow* parent, std::string img) {
wxBitmap before_bmp = create_scaled_bitmap(img, nullptr, 350);
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
m_bmp_intro = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
m_bmp_intro->SetBitmap(before_bmp);
m_images_sizer->Add(m_bmp_intro, 0, wxALL, 0);
}
CalibrationPAStartPage::CalibrationPAStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationStartPage(parent, id, pos, size, style)
{
m_cali_mode = CalibMode::Calib_PA_Line;
m_page_type = CaliPageType::CALI_PAGE_START;
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationPAStartPage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, CalibMode::Calib_PA_Line);
m_page_caption->show_prev_btn(false);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
create_when(parent,
_L("When do you need Flow Dynamics Calibration"),
_L("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:\
\n1. If you introduce a new filament of different brands/models or the filament is damp;\
\n2. if the nozzle is worn out or replaced with a new one;\
\n3. If the max volumetric speed or print temperature is changed in the filament setting."));
m_top_sizer->Add(m_when_title);
m_top_sizer->Add(m_when_content);
m_top_sizer->AddSpacer(PRESET_GAP);
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
create_bitmap(parent, "cali_page_before_pa_CN", "cali_page_after_pa_CN");
} else {
create_bitmap(parent, "cali_page_before_pa", "cali_page_after_pa");
}
m_top_sizer->Add(m_images_sizer, 0, wxALL, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
PAPageHelpPanel* m_help_panel = new PAPageHelpPanel(parent, false);
m_top_sizer->Add(m_help_panel, 0, wxALL, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
create_about(parent,
_L("About this calibration"),
_L("Please find the details of Flow Dynamics Calibration from our wiki.\
\n\nUsually 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\nPlease 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\nThe 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."));
m_top_sizer->Add(m_about_title);
m_top_sizer->Add(m_about_content);
m_top_sizer->AddSpacer(PRESET_GAP);
m_action_panel = new CaliPageActionPanel(parent, CalibMode::Calib_PA_Line, CaliPageType::CALI_PAGE_START);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
#ifdef __linux__
wxGetApp().CallAfter([this]() {
m_when_content->SetMinSize(m_when_content->GetSize() + wxSize{ 0, wxWindow::GetCharHeight() / 2 });
m_about_content->SetMinSize(m_about_content->GetSize() + wxSize{ 0, wxWindow::GetCharHeight() / 2 });
Layout();
Fit();
});
#endif
}
void CalibrationPAStartPage::on_reset_page()
{
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
}
void CalibrationPAStartPage::on_device_connected(MachineObject* obj)
{
//enable all button
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, true);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, true);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
if (obj->cali_version <= -1) {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, true);
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
}
else {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false);
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
}
}
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
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);
if (!obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
}
else {
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);
}
}
CalibrationFlowRateStartPage::CalibrationFlowRateStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationStartPage(parent, id, pos, size, style)
{
m_cali_mode = CalibMode::Calib_Flow_Rate;
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationFlowRateStartPage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, CalibMode::Calib_Flow_Rate);
m_page_caption->show_prev_btn(false);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
create_when(parent,
_L("When to use Flow Rate Calibration"),
_L("After using Flow Dynamics Calibration, there might still be some extrusion issues, such as:\
\n1. Over-Extrusion: Excess material on your printed object, forming blobs or zits, or the layers seem thicker than expected and not uniform.\
\n2. Under-Extrusion: Very thin layers, weak infill strength, or gaps in the top layer of the model, even when printing slowly.\
\n3. Poor Surface Quality: The surface of your prints seems rough or uneven.\
\n4. Weak Structural Integrity: Prints break easily or don't seem as sturdy as they should be."));
m_top_sizer->Add(m_when_title);
m_top_sizer->Add(m_when_content);
m_top_sizer->AddSpacer(PRESET_GAP);
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
create_bitmap(parent, "cali_page_flow_introduction_CN");
} else {
create_bitmap(parent, "cali_page_flow_introduction");
}
m_top_sizer->Add(m_images_sizer, 0, wxALL, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
auto extra_text = new Label(parent, _L("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."));
extra_text->SetFont(Label::Body_14);
extra_text->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
m_top_sizer->Add(extra_text);
m_top_sizer->AddSpacer(PRESET_GAP);
create_about(parent,
_L("About this calibration"),
_L("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."));
m_top_sizer->Add(m_about_title);
m_top_sizer->Add(m_about_content);
m_top_sizer->AddSpacer(PRESET_GAP);
auto auto_cali_title = new Label(parent, _L("Auto-Calibration"));
auto_cali_title->SetFont(Label::Head_14);
auto_cali_title->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
auto auto_cali_content = new Label(this,
_L("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\nThe 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\nCaution: 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."));
auto_cali_content->SetFont(Label::Body_14);
auto_cali_content->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
m_top_sizer->Add(auto_cali_title);
m_top_sizer->Add(auto_cali_content);
m_top_sizer->AddSpacer(PRESET_GAP);
m_action_panel = new CaliPageActionPanel(parent, CalibMode::Calib_Flow_Rate, CaliPageType::CALI_PAGE_START);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
#ifdef __linux__
wxGetApp().CallAfter([this, auto_cali_content]() {
m_when_content->SetMinSize(m_when_content->GetSize() + wxSize{ 0, wxWindow::GetCharHeight() / 2 });
auto_cali_content->SetMinSize(auto_cali_content->GetSize() + wxSize{ 0, wxWindow::GetCharHeight() / 2 });
Layout();
Fit();
});
#endif
}
void CalibrationFlowRateStartPage::on_reset_page()
{
//disable all button
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
}
void CalibrationFlowRateStartPage::on_device_connected(MachineObject* obj)
{
//enable all button
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, true);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
if (obj->cali_version <= -1) {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, true);
}
else {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
}
}
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
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_flow_rate_auto = (obj->home_flag >> 15 & 1) == 1;
if (!is_support_flow_rate_auto) {
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
}
}
CalibrationMaxVolumetricSpeedStartPage::CalibrationMaxVolumetricSpeedStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: CalibrationStartPage(parent, id, pos, size, style)
{
m_cali_mode = CalibMode::Calib_Vol_speed_Tower;
create_page(this);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
}
void CalibrationMaxVolumetricSpeedStartPage::create_page(wxWindow* parent)
{
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
m_page_caption->show_prev_btn(false);
m_top_sizer->Add(m_page_caption, 0, wxEXPAND, 0);
create_when(parent, _L("When you need Max Volumetric Speed Calibration"), _L("Over-extrusion or under extrusion"));
m_top_sizer->Add(m_when_title);
m_top_sizer->Add(m_when_content);
m_top_sizer->AddSpacer(PRESET_GAP);
auto recommend_title = new Label(parent, _L("Max Volumetric Speed calibration is recommended when you print with:"));
recommend_title->SetFont(Label::Head_14);
recommend_title->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
m_top_sizer->Add(recommend_title);
auto recommend_text1 = new Label(parent, _L("material with significant thermal shrinkage/expansion, such as..."));
recommend_text1->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
recommend_text1->SetFont(Label::Body_14);
m_top_sizer->Add(recommend_text1);
auto recommend_text2 = new Label(parent, _L("materials with inaccurate filament diameter"));
recommend_text2->Wrap(CALIBRATION_START_PAGE_TEXT_MAX_LENGTH);
recommend_text2->SetFont(Label::Body_14);
m_top_sizer->Add(recommend_text2);
m_top_sizer->AddSpacer(PRESET_GAP);
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
create_bitmap(parent, "cali_page_before_pa_CN", "cali_page_after_pa_CN");
} else {
create_bitmap(parent, "cali_page_before_pa", "cali_page_after_pa");
}
m_top_sizer->Add(m_images_sizer, 0, wxALL, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_START);
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
}
}}

View file

@ -0,0 +1,82 @@
#ifndef slic3r_GUI_CalibrationWizardStartPage_hpp_
#define slic3r_GUI_CalibrationWizardStartPage_hpp_
#include "CalibrationWizardPage.hpp"
namespace Slic3r { namespace GUI {
class CalibrationStartPage : public CalibrationWizardPage
{
public:
CalibrationStartPage(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
protected:
CalibMode m_cali_mode;
wxBoxSizer* m_top_sizer;
wxBoxSizer* m_images_sizer;
Label* m_when_title;
Label* m_when_content;
Label* m_about_title;
Label* m_about_content;
wxStaticBitmap* m_before_bmp{ nullptr };
wxStaticBitmap* m_after_bmp{ nullptr };
wxStaticBitmap* m_bmp_intro{ nullptr };
void create_when(wxWindow* parent, wxString title, wxString content);
void create_about(wxWindow* parent, wxString title, wxString content);
void create_bitmap(wxWindow* parent, const wxBitmap& before_img, const wxBitmap& after_img);
void create_bitmap(wxWindow* parent, std::string before_img, std::string after_img);
void create_bitmap(wxWindow* parent, std::string img);
};
class CalibrationPAStartPage : public CalibrationStartPage
{
public:
CalibrationPAStartPage(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void on_reset_page();
void on_device_connected(MachineObject* obj);
};
class CalibrationFlowRateStartPage : public CalibrationStartPage
{
public:
CalibrationFlowRateStartPage(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
void on_reset_page();
void on_device_connected(MachineObject* obj);
};
class CalibrationMaxVolumetricSpeedStartPage : public CalibrationStartPage
{
public:
CalibrationMaxVolumetricSpeedStartPage(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
void create_page(wxWindow* parent);
};
}} // namespace Slic3r::GUI
#endif

View file

@ -55,6 +55,7 @@ void Camera::select_next_type()
void Camera::translate(const Vec3d& displacement) {
if (!displacement.isApprox(Vec3d::Zero())) {
m_view_matrix.translate(-displacement);
update_target();
}
}
@ -62,6 +63,7 @@ void Camera::set_target(const Vec3d& target)
{
//BBS do not check validation
//const Vec3d new_target = validate_target(target);
update_target();
const Vec3d new_target = target;
const Vec3d new_displacement = new_target - m_target;
if (!new_displacement.isApprox(Vec3d::Zero())) {
@ -84,7 +86,7 @@ void Camera::set_zoom(double zoom)
void Camera::select_view(const std::string& direction)
{
if (direction == "iso")
set_default_orientation();
set_iso_orientation();
else if (direction == "left")
look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
else if (direction == "right")
@ -505,6 +507,8 @@ void Camera::set_distance(double distance)
if (m_distance != distance) {
m_view_matrix.translate((distance - m_distance) * get_dir_forward());
m_distance = distance;
update_target();
}
}
@ -570,6 +574,19 @@ void Camera::set_default_orientation()
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
}
void Camera::set_iso_orientation()
{
m_zenit = 45.0f;
const double theta_rad = Geometry::deg2rad(-(double)m_zenit);
const double phi_rad = Geometry::deg2rad(45.0);
const double sin_theta = ::sin(theta_rad);
const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ());
m_view_rotation.normalize();
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
}
Vec3d Camera::validate_target(const Vec3d& target) const
{
BoundingBoxf3 test_box = m_scene_box;
@ -587,7 +604,13 @@ Vec3d Camera::validate_target(const Vec3d& target) const
void Camera::update_zenit()
{
m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0)));
m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0))); }
void Camera::update_target() {
Vec3d temptarget = get_position() + m_distance * get_dir_forward();
if (!(temptarget-m_target).isApprox(Vec3d::Zero())){
m_target = temptarget;
}
}
} // GUI

View file

@ -69,10 +69,12 @@ public:
void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; }
void translate(const Vec3d& displacement);
const Vec3d& get_target() const { return m_target; }
const Vec3d& get_target() {
update_target();
return m_target; }
void set_target(const Vec3d& target);
double get_distance() const { return (get_position() - m_target).norm(); }
double get_distance() { return (get_position() - get_target()).norm(); }
double get_gui_scale() const { return m_gui_scale; }
float get_zenit() const { return m_zenit; }
@ -161,8 +163,10 @@ private:
void set_distance(double distance);
void set_default_orientation();
void set_iso_orientation();
Vec3d validate_target(const Vec3d& target) const;
void update_zenit();
void update_target();
};
} // GUI

View file

@ -28,9 +28,8 @@ wxDEFINE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
const wxColour TEXT_COL = wxColour(43, 52, 54);
CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
: PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS),
m_obj(obj)
CameraPopup::CameraPopup(wxWindow *parent)
: PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
@ -52,8 +51,6 @@ CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
m_text_recording->SetFont(Label::Head_14);
m_text_recording->SetForegroundColour(TEXT_COL);
m_switch_recording = new SwitchButton(m_panel);
if (obj)
m_switch_recording->SetValue(obj->camera_recording_when_printing);
//vcamera
m_text_vcamera = new wxStaticText(m_panel, wxID_ANY, _L("Go Live"));
@ -80,8 +77,6 @@ CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
top_sizer->Add(m_resolution_options[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
top_sizer->Add(0, 0, wxALL, 0);
}
if (obj)
sync_resolution_setting(obj->camera_resolution);
main_sizer->Add(top_sizer, 0, wxALL, FromDIP(10));
@ -127,7 +122,6 @@ CameraPopup::CameraPopup(wxWindow *parent, MachineObject* obj)
m_interval_timer = new wxTimer();
m_interval_timer->SetOwner(this);
check_func_supported();
wxGetApp().UpdateDarkUIWin(this);
}
@ -260,8 +254,11 @@ void CameraPopup::sync_vcamera_state(bool show_vcamera)
rescale();
}
void CameraPopup::check_func_supported()
void CameraPopup::check_func_supported(MachineObject *obj2)
{
m_obj = obj2;
if (m_obj == nullptr)
return;
// function supported
if (m_obj->is_function_supported(PrinterFunction::FUNC_RECORDING) && m_obj->has_ipcam) {
m_text_recording->Show();
@ -300,12 +297,21 @@ void CameraPopup::check_func_supported()
auto curr_res = to_resolution_msg_string(CameraResolution(i));
std::vector <std::string> ::iterator it = std::find(resolution_supported.begin(), resolution_supported.end(), curr_res);
if ((it == resolution_supported.end())||(support_count <= 1) || !obj->is_support_1080dpi)
m_resolution_options[i] -> Hide();
m_resolution_options[i]->Hide();
else {
m_resolution_options[i]->Show();
if (m_obj->camera_resolution == curr_res) {
resolution_rbtns[i]->SetValue(true);
}
}
}
//hide resolution if there is only one choice
if (support_count <= 1 || !obj->is_support_1080dpi) {
m_text_resolution->Hide();
}
else {
m_text_resolution->Show();
}
}
void CameraPopup::update(bool vcamera_streaming)

View file

@ -24,7 +24,7 @@ wxDECLARE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
class CameraPopup : public PopupWindow
{
public:
CameraPopup(wxWindow *parent, MachineObject* obj = nullptr);
CameraPopup(wxWindow *parent);
virtual ~CameraPopup() {}
// PopupWindow virtual methods are all overridden to log them
@ -34,7 +34,7 @@ public:
virtual bool Show(bool show = true) wxOVERRIDE;
void sync_vcamera_state(bool show_vcamera);
void check_func_supported();
void check_func_supported(MachineObject* obj);
void update(bool vcamera_streaming);
enum CameraResolution

View file

@ -173,11 +173,10 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
return;
// layer_height shouldn't be equal to zero
auto gpreset = GUI::wxGetApp().preset_bundle->printers.get_edited_preset();
if (config->opt_float("layer_height") < EPSILON)
{
const wxString msg_text = _(L("Too small layer height.\nReset to 0.2"));
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
MessageDialog dialog(m_msg_dlg_parent, msg_text,"", wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *config;
is_msg_dlg_already_exist = true;
dialog.ShowModal();
@ -187,15 +186,14 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
}
//BBS: limite the max layer_herght
auto max_lh = gpreset.config.opt_float("max_layer_height",0);
if (max_lh > 0.2 && config->opt_float("layer_height") > max_lh+ EPSILON)
if (config->opt_float("layer_height") > 0.6 + EPSILON)
{
const wxString msg_text = wxString::Format(L"Too large layer height.\nReset to %0.3f", max_lh);
const wxString msg_text = _(L("Too large layer height.\nReset to 0.2"));
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *config;
is_msg_dlg_already_exist = true;
dialog.ShowModal();
new_conf.set_key_value("layer_height", new ConfigOptionFloat(max_lh));
new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.2));
apply(config, &new_conf);
is_msg_dlg_already_exist = false;
}
@ -321,6 +319,37 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
is_msg_dlg_already_exist = false;
}
//BBS
//if (config->opt_enum<PerimeterGeneratorType>("wall_generator") == PerimeterGeneratorType::Arachne &&
// config->opt_bool("enable_overhang_speed"))
//{
// wxString msg_text = _(L("Arachne engine only works when overhang slowing down is disabled.\n"
// "This may cause decline in the quality of overhang surface when print fastly")) + "\n";
// if (is_global_config)
// msg_text += "\n" + _(L("Disable overhang slowing down automatically? \n"
// "Yes - Enable arachne and disable overhang slowing down\n"
// "No - Give up using arachne 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();
// bool enable_overhang_slow_down = true;
// if (!is_global_config || answer == wxID_YES) {
// new_conf.set_key_value("enable_overhang_speed", new ConfigOptionBool(false));
// enable_overhang_slow_down = false;
// }
// else {
// new_conf.set_key_value("wall_generator", new ConfigOptionEnum<PerimeterGeneratorType>(PerimeterGeneratorType::Classic));
// }
// apply(config, &new_conf);
// if (cb_value_change) {
// if (!enable_overhang_slow_down)
// cb_value_change("enable_overhang_speed", false);
// }
// is_msg_dlg_already_exist = false;
//}
// BBS
int filament_cnt = wxGetApp().preset_bundle->filament_presets.size();
#if 0
@ -479,8 +508,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector<std::string> const &keys, std::map<ObjectBase *, ModelConfig *> const &configs)
{
for (auto &k : keys) {
if (/*k == "adaptive_layer_height" || */ k == "independent_support_layer_height" || k == "enable_support" ||
k == "detect_thin_wall" || k == "tree_support_adaptive_layer_height")
if (/*k == "adaptive_layer_height" || */k == "independent_support_layer_height" || k == "enable_support" || k == "detect_thin_wall")
config->set_key_value(k, new ConfigOptionBool(true));
else if (k == "wall_loops")
config->set_key_value(k, new ConfigOptionInt(0));
@ -503,25 +531,20 @@ void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::
void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, const bool is_global_config)
{
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
//SoftFever
auto gcflavor = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
bool have_perimeters = config->opt_int("wall_loops") > 0;
for (auto el : { "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width",
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" })
"seam_position","seam_gap","wipe_speed", "wall_infill_order", "outer_wall_line_width",
"inner_wall_speed", "outer_wall_speed" })
toggle_field(el, have_perimeters);
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
// sparse_infill_filament uses the same logic as in Print::extruders()
for (auto el : { "sparse_infill_pattern", "infill_combination",
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"})
for (auto el : { "sparse_infill_pattern", "sparse_infill_anchor_max", "infill_combination",
"minimum_sparse_infill_area", "sparse_infill_filament"})
toggle_line(el, have_infill);
// Only allow configuration of open anchors if the anchoring is enabled.
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0;
toggle_field("infill_anchor", has_infill_anchors);
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("sparse_infill_anchor_max")->value > 0;
toggle_line("sparse_infill_anchor", has_infill_anchors);
bool has_spiral_vase = config->opt_bool("spiral_mode");
bool has_top_solid_infill = config->opt_int("top_shell_layers") > 0;
@ -531,8 +554,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : { "top_surface_pattern", "bottom_surface_pattern", "internal_solid_infill_pattern", "solid_infill_filament"})
toggle_field(el, has_solid_infill);
for (auto el : { "infill_direction", "sparse_infill_line_width",
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle" })
for (auto el : { "infill_direction", "sparse_infill_line_width", "bridge_angle",
"sparse_infill_speed", "bridge_speed" })
toggle_field(el, have_infill || has_solid_infill);
toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill);
@ -546,14 +569,19 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
//BBS
for (auto el : {"outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration",
"top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"})
for (auto el : { "initial_layer_acceleration", "outer_wall_acceleration", "top_surface_acceleration", "inner_wall_acceleration", "sparse_infill_acceleration" })
toggle_field(el, have_default_acceleration);
if (is_BBL_Printer) {
for (auto el : {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_line(el, false);
} else {
for (auto el : {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_line(el, true);
bool have_default_jerk = config->opt_float("default_jerk") > 0;
for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk","travel_jerk", "infill_jerk"})
toggle_field(el, have_default_jerk);
bool quality_default_jerk = config->opt_float("default_jerk") > 0;
for (auto el : {"outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk"})
toggle_field(el, quality_default_jerk);
}
bool have_skirt = config->opt_int("skirt_loops") > 0;
toggle_field("skirt_height", have_skirt && config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
@ -567,15 +595,6 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
// wall_filament uses the same logic as in Print::extruders()
toggle_field("wall_filament", have_perimeters || have_brim);
bool have_brim_ear = (config->opt_enum<BrimType>("brim_type") == btEar);
const auto brim_width = config->opt_float("brim_width");
// disable brim_ears_max_angle and brim_ears_detection_length if brim_width is 0
toggle_field("brim_ears_max_angle", brim_width > 0.0f);
toggle_field("brim_ears_detection_length", brim_width > 0.0f);
// hide brim_ears_max_angle and brim_ears_detection_length if brim_ear is not selected
toggle_line("brim_ears_max_angle", have_brim_ear);
toggle_line("brim_ears_detection_length", have_brim_ear);
bool have_raft = config->opt_int("raft_layers") > 0;
bool have_support_material = config->opt_bool("enable_support") || have_raft;
// BBS
@ -588,23 +607,22 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
//BBS: add more support params to dependent of enable_support
"support_type", "support_on_build_plate_only", "support_critical_regions_only",
"support_type", "support_on_build_plate_only",
"support_remove_small_overhang",
"support_object_xy_distance"/*, "independent_support_layer_height"*/})
toggle_field(el, have_support_material);
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
//toggle_field("support_closing_radius", have_support_material && support_style == smsSnug);
bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type);
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter", "tree_support_adaptive_layer_height", "tree_support_auto_brim", "tree_support_brim_width"})
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter","tree_support_brim_width"})
toggle_field(el, support_is_tree);
// hide tree support settings when normal is selected
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance",
"tree_support_branch_diameter", "max_bridge_length", "tree_support_adaptive_layer_height", "tree_support_auto_brim", "tree_support_brim_width"})
for (auto el : {"tree_support_branch_angle", "tree_support_wall_count", "tree_support_branch_distance", "tree_support_branch_diameter", "max_bridge_length","tree_support_brim_width" })
toggle_line(el, support_is_tree);
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree);
toggle_field("tree_support_brim_width", support_is_tree && !config->opt_bool("tree_support_auto_brim"));
// tree support use max_bridge_length instead of bridge_no_support
toggle_line("bridge_no_support", !support_is_tree);
@ -629,7 +647,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line(el, have_raft);
bool has_ironing = (config->opt_enum<IroningType>("ironing_type") != IroningType::NoIroning);
for (auto el : { "ironing_flow", "ironing_spacing", "ironing_speed" })
for (auto el : {"ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed"})
toggle_line(el, has_ironing);
// bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
@ -646,16 +664,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : {"flush_into_infill", "flush_into_support", "flush_into_objects"})
toggle_field(el, have_prime_tower);
// BBS: MusangKing - Hide "Independent support layer height" option
toggle_line("independent_support_layer_height", have_support_material && !have_prime_tower);
bool have_avoid_crossing_perimeters = config->opt_bool("reduce_crossing_wall");
toggle_line("max_travel_detour_distance", have_avoid_crossing_perimeters);
bool has_overhang_speed = config->opt_bool("enable_overhang_speed");
for (auto el :
{"overhang_speed_classic", "overhang_1_4_speed",
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
for (auto el : { "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
toggle_line(el, has_overhang_speed);
toggle_line("flush_into_objects", !is_global_config);
@ -669,24 +682,22 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"min_feature_size", "min_bead_width", "wall_distribution_count" })
toggle_line(el, have_arachne);
toggle_field("detect_thin_wall", !have_arachne);
// Orca
auto is_role_based_wipe_speed = config->opt_bool("role_based_wipe_speed");
toggle_field("wipe_speed",!is_role_based_wipe_speed);
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, gcflavor == gcfKlipper);
if(gcflavor == gcfKlipper)
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
// OrcaSlicer
auto gcflavor = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
if( gcflavor != gcfKlipper )
{
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, false);
}
else {
for (auto el : {"accel_to_decel_enable", "accel_to_decel_factor"})
toggle_line(el, true);
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
bool have_make_overhang_printable = config->opt_bool("make_overhang_printable");
toggle_line("make_overhang_printable_angle", have_make_overhang_printable);
toggle_line("make_overhang_printable_hole_size", have_make_overhang_printable);
}
toggle_line("exclude_object", gcflavor == gcfKlipper);
toggle_line("min_width_top_surface",config->opt_bool("only_one_wall_top"));
}
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)

View file

@ -23,6 +23,7 @@ class ConfigManipulation
bool is_msg_dlg_already_exist{ false };
bool m_is_initialized_support_material_overhangs_queried{ false };
bool m_support_material_overhangs_queried{ false };
bool is_BBL_Printer{false};
// function to loading of changed configuration
std::function<void()> load_config = nullptr;
@ -77,7 +78,7 @@ public:
void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config);
void check_bed_temperature_difference(int bed_type, DynamicPrintConfig* config);
void check_filament_max_volumetric_speed(DynamicPrintConfig *config);
void set_is_BBL_Printer(bool is_bbl_printer) { is_BBL_Printer = is_bbl_printer; };
// SLA print
void update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config = false);
void toggle_print_sla_options(DynamicPrintConfig* config);

Some files were not shown because too many files have changed in this diff Show more