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

@ -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);

View file

@ -2735,6 +2735,16 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->init_dialog_size();
});
p->btn_prev->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&)
{
ConfigWizardPage* active_page = this->p->index->active_page();
if ((active_page == p->page_filaments || active_page == p->page_sla_materials) &&
!p->check_and_install_missing_materials(dynamic_cast<PageMaterials*>(active_page)->materials->technology))
// In that case don't leave the page and the function above queried the user whether to install default materials.
return;
this->p->index->go_prev();
});
p->btn_next->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &)
{
ConfigWizardPage* active_page = this->p->index->active_page();

View file

@ -149,7 +149,9 @@ void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event)
}
if (m_obj) {
m_obj->set_user_access_code(code.ToStdString());
wxGetApp().getDeviceManager()->set_selected_machine(m_obj->dev_id);
if (m_need_connect) {
wxGetApp().getDeviceManager()->set_selected_machine(m_obj->dev_id);
}
}
EndModal(wxID_OK);
}

View file

@ -25,6 +25,7 @@ class ConnectPrinterDialog : public DPIDialog
{
private:
protected:
bool m_need_connect{true};
wxStaticText * m_staticText_connection_code;
TextInput * m_textCtrl_code;
Button * m_button_confirm;
@ -45,6 +46,7 @@ public:
~ConnectPrinterDialog();
void go_connect_printer(bool need) {m_need_connect = need;};
void end_modal(wxStandardID id);
void init_bitmap();
void set_machine_object(MachineObject* obj);

File diff suppressed because it is too large Load diff

View file

@ -12,13 +12,15 @@
#include "slic3r/Utils/json_diff.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "CameraPopup.hpp"
#include "libslic3r/Calib.hpp"
#define USE_LOCAL_SOCKET_BIND 0
#define DISCONNECT_TIMEOUT 30000.f // milliseconds
#define PUSHINFO_TIMEOUT 15000.f // milliseconds
#define TIMEOUT_FOR_STRAT 20000.f // milliseconds
#define REQUEST_PUSH_MIN_TIME 15000.f // milliseconds
#define TIMEOUT_FOR_KEEPALIVE 5* 60 * 1000.f // milliseconds
#define REQUEST_PUSH_MIN_TIME 3000.f // milliseconds
#define REQUEST_START_MIN_TIME 15000.f // milliseconds
#define EXTRUSION_OMIT_TIME 20000.f // milliseconds
#define HOLD_TIMEOUT 10000.f // milliseconds
@ -49,6 +51,13 @@ using namespace nlohmann;
namespace Slic3r {
enum PrinterSeries {
SERIES_X1 = 0,
SERIES_P1P,
SERIES_UNKNOWN,
};
enum PRINTING_STAGE {
PRINTING_STAGE_PRINTING = 0,
PRINTING_STAGE_BED_LEVELING,
@ -74,6 +83,7 @@ enum PrinterFunction {
FUNC_RECORDING,
FUNC_FIRSTLAYER_INSPECT,
FUNC_AI_MONITORING,
FUNC_LIDAR_CALIBRATION,
FUNC_BUILDPLATE_MARKER_DETECT,
FUNC_AUTO_RECOVERY_STEP_LOSS,
FUNC_FLOW_CALIBRATION,
@ -173,19 +183,19 @@ public:
static wxColour decode_color(const std::string &color)
{
std::array<int, 3> ret = {0, 0, 0};
std::array<int, 4> ret = {0, 0, 0, 0};
const char * c = color.data();
if (color.size() == 8) {
for (size_t j = 0; j < 3; ++j) {
for (size_t j = 0; j < 4; ++j) {
int digit1 = hex_digit_to_int(*c++);
int digit2 = hex_digit_to_int(*c++);
if (digit1 == -1 || digit2 == -1) break;
ret[j] = float(digit1 * 16 + digit2);
}
} else {
return wxColour(255, 255, 255);
return wxColour(255, 255, 255, 255);
}
return wxColour(ret[0], ret[1], ret[2]);
return wxColour(ret[0], ret[1], ret[2], ret[3]);
}
std::string id;
@ -208,6 +218,7 @@ public:
std::string uuid;
float k = 0.0f; // k range: 0 ~ 0.5
float n = 0.0f; // k range: 0.6 ~ 2.0
int cali_idx = 0;
wxColour wx_color;
bool is_bbl;
@ -384,6 +395,12 @@ public:
SDCARD_STATE_NUM = 3
};
enum ActiveState {
NotActive,
Active,
UpdateToDate
};
class ExtrusionRatioInfo
{
public:
@ -409,23 +426,26 @@ public:
std::string dev_name;
std::string dev_ip;
std::string dev_id;
bool local_use_ssl { false };
bool local_use_ssl_for_mqtt { true };
bool local_use_ssl_for_ftp { true };
float nozzle_diameter { 0.0f };
std::string dev_connection_type; /* lan | cloud */
std::string connection_type() { return dev_connection_type; }
void set_dev_ip(std::string ip) {dev_ip = ip;};
bool has_access_right() { return !get_access_code().empty(); }
std::string get_ftp_folder();
void set_access_code(std::string code);
std::string get_access_code();
void set_user_access_code(std::string code);
void set_access_code(std::string code, bool only_refresh = true);
void set_user_access_code(std::string code, bool only_refresh = true);
void erase_user_access_code();
std::string get_user_access_code();
bool is_lan_mode_printer();
bool is_high_printer_type();
//PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN;
std::string printer_type; /* model_id */
PrinterSeries get_printer_series() const;
std::string printer_thumbnail_img;
std::string monitor_upgrade_printer_img;
@ -436,6 +456,7 @@ public:
std::string product_name; // set by iot service, get /user/print
std::vector<int> filam_bak;
bool m_is_support_show_bak{false};
std::string bind_user_name;
std::string bind_user_id;
@ -448,11 +469,17 @@ public:
void set_lan_mode_connection_state(bool state) {m_lan_mode_connection_state = state;};
bool get_lan_mode_connection_state() {return m_lan_mode_connection_state;};
int parse_msg_count = 0;
int keep_alive_count = 0;
std::chrono::system_clock::time_point last_update_time; /* last received print data from machine */
std::chrono::system_clock::time_point last_keep_alive; /* last received print data from machine */
std::chrono::system_clock::time_point last_push_time; /* last received print push from machine */
std::chrono::system_clock::time_point last_request_push; /* last received print push from machine */
std::chrono::system_clock::time_point last_request_start; /* last received print push from machine */
int m_active_state = 0; // 0 - not active, 1 - active, 2 - update-to-date
bool is_support_tunnel_mqtt = false;
bool is_tunnel_mqtt = false;
/* ams properties */
std::map<std::string, Ams*> amsList; // key: ams[id], start with 0
AmsTray vt_tray; // virtual tray
@ -484,6 +511,7 @@ public:
std::chrono::system_clock::time_point last_extrusion_cali_start_time;
int extrusion_cali_set_tray_id = -1;
std::chrono::system_clock::time_point extrusion_cali_set_hold_start;
std::string extrusion_cali_filament_name;
bool is_in_extrusion_cali();
bool is_extrusion_cali_finished();
@ -548,6 +576,7 @@ public:
int upgrade_display_state = 0; // 0 : upgrade unavailable, 1: upgrade idle, 2: upgrading, 3: upgrade_finished
int upgrade_display_hold_count = 0;
PrinterFirmwareType firmware_type; // engineer|production
PrinterFirmwareType lifecycle { PrinterFirmwareType::FIRMEARE_TYPE_UKNOWN };
std::string upgrade_progress;
std::string upgrade_message;
std::string upgrade_status;
@ -564,6 +593,7 @@ public:
std::vector<FirmwareInfo> firmware_list;
std::string get_firmware_type_str();
std::string get_lifecycle_type_str();
bool is_in_upgrading();
bool is_upgrading_avalable();
int get_upgrade_percent();
@ -593,6 +623,41 @@ public:
int total_layers = 0;
bool is_support_layer_num { false };
int cali_version = -1;
float cali_selected_nozzle_dia { 0.0 };
// 1: record when start calibration in preset page
// 2: reset when start calibration in start page
// 3: save tray_id, filament_id, setting_id, and name, nozzle_dia
std::vector<CaliPresetInfo> selected_cali_preset;
float cache_flow_ratio { 0.0 };
bool cali_finished = true;
bool has_get_pa_calib_tab{ false };
std::vector<PACalibResult> pa_calib_tab;
float pa_calib_tab_nozzle_dia;
bool get_pa_calib_result { false };
std::vector<PACalibResult> pa_calib_results;
bool get_flow_calib_result { false };
std::vector<FlowRatioCalibResult> flow_ratio_results;
void reset_pa_cali_history_result()
{
pa_calib_tab_nozzle_dia = 0.4f;
has_get_pa_calib_tab = false;
pa_calib_tab.clear();
}
void reset_pa_cali_result() {
get_pa_calib_result = false;
pa_calib_results.clear();
}
void reset_flow_rate_cali_result() {
get_flow_calib_result = false;
flow_ratio_results.clear();
}
bool check_pa_result_validation(PACalibResult& result);
std::vector<int> stage_list_info;
int stage_curr = 0;
int m_push_count = 0;
@ -632,6 +697,11 @@ public:
std::string camera_resolution = "";
bool xcam_first_layer_inspector { false };
int xcam_first_layer_hold_count = 0;
int local_camera_proto = -1;
int file_proto = 0;
std::string local_rtsp_url;
std::string tutk_state;
bool is_support_remote_tunnel{false};
bool xcam_ai_monitoring{ false };
int xcam_ai_monitoring_hold_count = 0;
@ -648,8 +718,8 @@ public:
bool is_support_1080dpi {false};
bool is_support_ai_monitoring {false};
bool is_support_ams_humidity {true};
bool is_support_filament_edit_virtual_tray {true};
bool is_cloud_print_only {false};
bool is_support_mqtt_alive {false};
/* sdcard */
MachineObject::SdcardState sdcard_state { NO_SDCARD };
@ -660,7 +730,7 @@ public:
std::vector<HMSItem> hms_list;
/* machine mqtt apis */
int connect(bool is_anonymous = false);
int connect(bool is_anonymous = false, bool use_openssl = true);
int disconnect();
json_diff print_json;
@ -678,6 +748,7 @@ public:
std::string m_gcode_file;
int gcode_file_prepare_percent = 0;
BBLSubTask* subtask_;
BBLModelTask* model_task;
std::string obj_subtask_id; // subtask_id == 0 for sdcard
std::string subtask_name;
bool is_sdcard_printing();
@ -694,7 +765,7 @@ public:
bool is_studio_cmd(int seq);
/* command commands */
int command_get_version(bool with_retry = true);
int command_request_push_all();
int command_request_push_all(bool request_now = false);
int command_pushing(std::string cmd);
int command_clean_print_error(std::string task_id, int print_error);
@ -745,6 +816,18 @@ public:
bool is_support_command_calibration();
int command_start_calibration(bool vibration, bool bed_leveling, bool xcam_cali);
// PA calibration
int command_start_pa_calibration(const X1CCalibInfos& pa_data, int mode = 0); // 0: automatic mode; 1: manual mode. default: automatic mode
int command_set_pa_calibration(const std::vector<PACalibResult>& pa_calib_values, bool is_auto_cali);
int command_delete_pa_calibration(const PACalibIndexInfo& pa_calib);
int command_get_pa_calibration_tab(float nozzle_diameter, const std::string &filament_id = "");
int command_get_pa_calibration_result(float nozzle_diameter);
int commnad_select_pa_calibration(const PACalibIndexInfo& pa_calib_info);
// flow ratio calibration
int command_start_flow_ratio_calibration(const X1CCalibInfos& calib_data);
int command_get_flow_ratio_calibration_result(float nozzle_diameter);
int command_unload_filament();
// camera control
@ -773,6 +856,7 @@ public:
static bool is_in_printing_status(std::string status);
void set_print_state(std::string status);
std::vector<std::string> get_compatible_machine();
bool is_connected();
bool is_connecting();
@ -782,7 +866,10 @@ public:
bool is_function_supported(PrinterFunction func);
std::vector<std::string> get_resolution_supported();
bool is_support_print_with_timelapse();
bool is_camera_busy_off();
int get_local_camera_proto();
bool has_local_file_proto();
bool has_remote_file_proto();
/* Msg for display MsgFn */
typedef std::function<void(std::string topic, std::string payload)> MsgFn;
@ -793,6 +880,8 @@ public:
int publish_gcode(std::string gcode_str);
BBLSubTask* get_subtask();
BBLModelTask* get_modeltask();
void set_modeltask(BBLModelTask* task);
void update_slice_info(std::string project_id, std::string profile_id, std::string subtask_id, int plate_idx);
bool m_firmware_valid { false };
@ -817,6 +906,7 @@ public:
std::map<std::string, MachineObject*> localMachineList; /* dev_id -> MachineObject*, localMachine SSDP */
std::map<std::string, MachineObject*> userMachineList; /* dev_id -> MachineObject* cloudMachine of User */
void keep_alive();
void check_pushing();
MachineObject* get_default_machine();
@ -863,6 +953,7 @@ public:
static bool load_filaments_blacklist_config(std::string config_file);
static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info);
static std::string load_gcode(std::string type_str, std::string gcode_file);
static std::vector<std::string> get_compatible_machine(std::string type_str);
};
} // namespace Slic3r

View file

@ -49,9 +49,9 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title)
m_simplebook_status = new wxSimplebook(this);
m_simplebook_status->SetSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMinSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetMaxSize(wxSize(FromDIP(400), FromDIP(70)));
m_simplebook_status->SetSize(wxSize(FromDIP(400), -1));
m_simplebook_status->SetMinSize(wxSize(FromDIP(400), -1));
m_simplebook_status->SetMaxSize(wxSize(FromDIP(400), -1));
//mode normal
m_status_bar = std::make_shared<BBLStatusBarSend>(m_simplebook_status);
@ -98,8 +98,8 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title)
sizer_install_failed->Add(m_install_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_panel_download_failed->SetSizer(sizer_install_failed);
m_panel_download_failed->Layout();
m_panel_install_failed->SetSizer(sizer_install_failed);
m_panel_install_failed->Layout();
sizer_install_failed->Fit(m_panel_install_failed);
m_sizer_main->Add(m_simplebook_status, 0, wxALL, FromDIP(20));

View file

@ -217,6 +217,7 @@ wxWindow* BitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRec
text_editor->SetInsertionPointEnd();
text_editor->SelectAll();
text_editor->SetBackgroundColour(parent->GetBackgroundColour());
text_editor->SetForegroundColour(parent->GetForegroundColour());
return text_editor;
}

View file

@ -675,6 +675,11 @@ void ExtrusionCalibration::update_combobox_filaments()
curr_selection = filament_index;
}
if (filament_it->name == obj->extrusion_cali_filament_name && !obj->extrusion_cali_filament_name.empty())
{
curr_selection = filament_index;
}
wxString filament_name = wxString::FromUTF8(filament_it->name);
filament_items.Add(filament_name);
break;
@ -784,6 +789,11 @@ void ExtrusionCalibration::update_filament_info()
if (filament_name.compare(m_comboBox_filament->GetValue()) == 0) {
m_filament_type = filament_it->name;
if (obj) {
obj->extrusion_cali_filament_name = filament_it->name;
BOOST_LOG_TRIVIAL(info) << "set extrusion cali filament name = " << obj->extrusion_cali_filament_name;
}
// update nozzle temperature
ConfigOption* opt_nozzle_temp = filament_it->config.option("nozzle_temperature");
if (opt_nozzle_temp) {

View file

@ -385,7 +385,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
wxString y_str = thumbnail.GetNextToken();
if (y_str.ToDouble(&y) && !thumbnail.HasMoreTokens()) {
if (m_opt_id == "bed_exclude_area") {
if (0 <= x && 0 <= y) {
if (0 <= x && x <= 256 && 0 <= y && y <= 256) {
out_values.push_back(Vec2d(x, y));
continue;
}
@ -511,10 +511,11 @@ void TextCtrl::BUILD() {
m_combine_side_text = !m_opt.multiline;
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double) text_ctrl->GetSize().GetHeight() / m_em_unit;
temp->SetFont(m_opt.is_code ?
Slic3r::GUI::wxGetApp().code_font() :
Slic3r::GUI::wxGetApp().normal_font());
if (m_opt.is_code) // BBS
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
temp->SetForegroundColour(StateColor::darkModeColorFor(*wxBLACK));
wxGetApp().UpdateDarkUI(temp);
if (! m_opt.multiline && !wxOSX)
@ -1382,7 +1383,8 @@ boost::any& Choice::get_value()
{
if (m_opt.nullable && field->GetSelection() == -1)
m_value = ConfigOptionEnumsGenericNullable::nil_value();
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style") {
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" ||
m_opt_id == "support_style") {
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(m_opt.enum_keys_map->at(key));
}

View file

@ -105,6 +105,16 @@ static std::array<float, 4> decode_color(const std::string& color) {
ret[j] = float(digit1 * 16 + digit2) * INV_255;
}
}
else if (color.size() == 9 && color.front() == '#') {
for (size_t j = 0; j < 4; ++j) {
int digit1 = hex_digit_to_int(*c++);
int digit2 = hex_digit_to_int(*c++);
if (digit1 == -1 || digit2 == -1)
break;
ret[j] = float(digit1 * 16 + digit2) * INV_255;
}
}
return ret;
}
@ -317,7 +327,7 @@ void GCodeViewer::SequentialRangeCap::reset() {
void GCodeViewer::SequentialView::Marker::init(std::string filename)
{
if (filename.empty()) {
//m_model.init_from(stilized_arrow(16, 1.5f, 3.0f, 0.8f, 3.0f));
m_model.init_from(stilized_arrow(16, 1.5f, 3.0f, 0.8f, 3.0f));
} else {
m_model.init_from_file(filename);
}
@ -1150,6 +1160,9 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
for (auto item : m_tools.m_tool_visibles) item = true;
}
for (int i = 0; i < m_tools.m_tool_colors.size(); i++) {
m_tools.m_tool_colors[i] = adjust_color_for_rendering(m_tools.m_tool_colors[i]);
}
// ensure there are enough colors defined
while (m_tools.m_tool_colors.size() < std::max(size_t(1), gcode_result.extruders_count)) {
m_tools.m_tool_colors.push_back(decode_color("#FF8000"));
@ -1175,7 +1188,7 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v
m_extrusions.ranges.temperature.update_from(curr.temperature);
if (curr.extrusion_role != erCustom || is_visible(erCustom))
m_extrusions.ranges.volumetric_rate.update_from(round_to_bin(curr.volumetric_rate()));
if (curr.layer_duration > 0.f) {
m_extrusions.ranges.layer_duration.update_from(curr.layer_duration);
m_extrusions.ranges.layer_duration_log.update_from(curr.layer_duration);
@ -1213,7 +1226,7 @@ void GCodeViewer::refresh_render_paths()
void GCodeViewer::update_shells_color_by_extruder(const DynamicPrintConfig* config)
{
if (config != nullptr)
m_shells.volumes.update_colors_by_extruder(config);
m_shells.volumes.update_colors_by_extruder(config,false);
}
//BBS: always load shell at preview
@ -3829,7 +3842,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE));
glsafe(::glEnable(GL_POINT_SPRITE));
@ -3856,7 +3869,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
@ -3874,7 +3887,7 @@ void GCodeViewer::render_toolpaths()
#if ENABLE_GCODE_VIEWER_STATISTICS
this
#endif // ENABLE_GCODE_VIEWER_STATISTICS
](std::vector<RenderPath>::iterator it_path, std::vector<RenderPath>::iterator it_end, GLShaderProgram& shader, int uniform_color) {
](std::vector<RenderPath>::reverse_iterator it_path, std::vector<RenderPath>::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) {
for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) {
const RenderPath& path = *it;
// Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415.
@ -4004,13 +4017,15 @@ void GCodeViewer::render_toolpaths()
default: break;
}
int uniform_color = shader->get_uniform_location("uniform_color");
auto it_path = buffer.render_paths.begin();
auto it_path = buffer.render_paths.rbegin();
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":buffer indices size %1%, render_path size %2% ")%buffer.indices.size() %buffer.render_paths.size();
for (unsigned int ibuffer_id = 0; ibuffer_id < static_cast<unsigned int>(buffer.indices.size()); ++ibuffer_id) {
unsigned int indices_count = static_cast<unsigned int>(buffer.indices.size());
for (unsigned int index = 0; index < indices_count; ++index) {
unsigned int ibuffer_id = indices_count - index - 1;
const IBuffer& i_buffer = buffer.indices[ibuffer_id];
// Skip all paths with ibuffer_id < ibuffer_id.
for (; it_path != buffer.render_paths.end() && it_path->ibuffer_id < ibuffer_id; ++ it_path) ;
if (it_path == buffer.render_paths.end() || it_path->ibuffer_id > ibuffer_id)
for (; it_path != buffer.render_paths.rend() && it_path->ibuffer_id > ibuffer_id; ++ it_path) ;
if (it_path == buffer.render_paths.rend() || it_path->ibuffer_id < ibuffer_id)
// Not found. This shall not happen.
continue;
@ -4029,16 +4044,16 @@ void GCodeViewer::render_toolpaths()
switch (buffer.render_primitive_type)
{
case TBuffer::ERenderPrimitiveType::Point: {
render_as_points(it_path, buffer.render_paths.end(), *shader, uniform_color);
render_as_points(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Line: {
glsafe(::glLineWidth(static_cast<GLfloat>(line_width(zoom))));
render_as_lines(it_path, buffer.render_paths.end(), *shader, uniform_color);
render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
render_as_triangles(it_path, buffer.render_paths.end(), *shader, uniform_color);
render_as_triangles(it_path, buffer.render_paths.rend(), *shader, uniform_color);
break;
}
default: { break; }
@ -4161,6 +4176,10 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
std::vector<float> filament_densities = gcode_result_list.front()->filament_densities;
std::vector<Color> filament_colors = decode_colors(wxGetApp().plater()->get_extruder_colors_from_plater_config(gcode_result_list.back()));
for (int i = 0; i < filament_colors.size(); i++) {
filament_colors[i] = adjust_color_for_rendering(filament_colors[i]);
}
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
float window_padding = 4.0f * m_scale;
const float icon_size = ImGui::GetTextLineHeight() * 0.7;
@ -4304,18 +4323,20 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
char buf[64];
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0;
if (show_detailed_statistics_page) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i]),
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i]);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
}
@ -4409,21 +4430,21 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
default:
case EItemType::Rect: {
draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale },
ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
ImGui::GetColorU32({color[0], color[1], color[2], color[3]}));
break;
}
case EItemType::Circle: {
ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size + 5.0f));
draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 16);
break;
}
case EItemType::Hexagon: {
ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size + 5.0f));
draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6);
draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 6);
break;
}
case EItemType::Line: {
draw_list->AddLine({ pos.x + 1, pos.y + icon_size + 2 }, { pos.x + icon_size - 1, pos.y + 4 }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 3.0f);
draw_list->AddLine({pos.x + 1, pos.y + icon_size + 2}, {pos.x + icon_size - 1, pos.y + 4}, ImGui::GetColorU32({color[0], color[1], color[2], color[3]}), 3.0f);
break;
case EItemType::None:
break;
@ -4938,7 +4959,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0] , model_used_filaments_g[0]);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0], model_used_filaments_g[0] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false);
@ -4972,19 +4993,20 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
char buf[64];
if (show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i] + flushed_filaments_m[i], model_used_filaments_g[i] + flushed_filaments_g[i]);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i]),
(model_used_filaments_g[i] + flushed_filaments_g[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i]);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({buf, offsets[2]});
}
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false, filament_visible, [this, extruder_idx]() {
@ -5033,20 +5055,20 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ _u8L("Total"), offsets[0] });
if (!show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);
}
else {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (total_model_used_filament_m + total_flushed_filament_m) * 1000 / /*1000*/koef, (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m, (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);

View file

@ -492,7 +492,7 @@ class GCodeViewer
std::vector<Endpoints>& get_endpoints() { return m_endpoints; }
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
Endpoints get_endpoints_at(unsigned int id) const { return (id < m_endpoints.size()) ? m_endpoints[id] : Endpoints(); }
int get_l_at(double z) const
int get_l_at(float z) const
{
auto iter = std::upper_bound(m_zs.begin(), m_zs.end(), z);
return std::distance(m_zs.begin(), iter);
@ -737,7 +737,6 @@ public:
//BBS
ConflictResultOpt m_conflict_result;
private:
std::vector<int> m_plater_extruder;
bool m_gl_data_initialized{ false };

View file

@ -119,7 +119,7 @@ RetinaHelper::~RetinaHelper() {}
float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); }
#endif // __WXGTK3__
// Fixed the collision between BuildVolume_Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
// Fixed the collision between BuildVolume::Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
#if defined(__linux__) && defined(Convex)
#undef Convex
#endif
@ -287,7 +287,7 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.81f, 0.81f, 0.81f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
if(ImGui::BBLSliderScalar("##radius_slider", ImGuiDataType_S32, &radius, &v_min, &v_max)){
radius = std::clamp(radius, 1, 10);
m_smooth_params.radius = (unsigned int)radius;
@ -298,9 +298,9 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv
input_align = std::max(input_align, ImGui::GetCursorPosX());
ImGui::SetCursorPosX(input_align);
ImGui::PushItemWidth(input_box_width);
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.68f, 0.26f, 0.00f));
ImGui::BBLDragScalar("##radius_input", ImGuiDataType_S32, &radius, 1, &v_min, &v_max);
ImGui::PopStyleColor(3);
@ -999,6 +999,7 @@ void GLCanvas3D::SequentialPrintClearance::render()
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_PLATE_NAME_CHANGE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_PLATE_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_PLATE_RIGHT_CLICK, RBtnPlateEvent);
@ -1046,30 +1047,22 @@ const double GLCanvas3D::DefaultCameraZoomToPlateMarginFactor = 1.25;
void GLCanvas3D::load_arrange_settings()
{
std::string dist_fff_str =
wxGetApp().app_config->get("arrange", "min_object_distance_fff");
wxGetApp().app_config->get("arrange", "min_object_distance");
std::string dist_fff_seq_print_str =
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print_fff");
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print");
std::string dist_sla_str =
wxGetApp().app_config->get("arrange", "min_object_distance_sla");
std::string en_rot_fff_str =
wxGetApp().app_config->get("arrange", "enable_rotation_fff");
wxGetApp().app_config->get("arrange", "enable_rotation");
std::string en_rot_fff_seqp_str =
wxGetApp().app_config->get("arrange", "enable_rotation_seq_print");
std::string en_rot_sla_str =
wxGetApp().app_config->get("arrange", "enable_rotation_sla");
std::string en_allow_multiple_materials_str =
wxGetApp().app_config->get("arrange", "allow_multi_materials_on_same_plate");
std::string en_avoid_region_str =
wxGetApp().app_config->get("arrange", "avoid_extrusion_cali_region");
if (!dist_fff_str.empty())
m_arrange_settings_fff.distance = std::stof(dist_fff_str);
@ -1081,27 +1074,27 @@ void GLCanvas3D::load_arrange_settings()
m_arrange_settings_sla.distance = std::stof(dist_sla_str);
if (!en_rot_fff_str.empty())
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "true");
if (!en_allow_multiple_materials_str.empty())
m_arrange_settings_fff.allow_multi_materials_on_same_plate = (en_allow_multiple_materials_str == "1" || en_allow_multiple_materials_str == "true");
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "yes");
if (!en_rot_fff_seqp_str.empty())
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "true");
if(!en_avoid_region_str.empty())
m_arrange_settings_fff.avoid_extrusion_cali_region = (en_avoid_region_str == "1" || en_avoid_region_str == "true");
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "yes");
if (!en_rot_sla_str.empty())
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "true");
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "yes");
//BBS: add specific arrange settings
m_arrange_settings_fff_seq_print.is_seq_print = true;
}
PrinterTechnology GLCanvas3D::current_printer_technology() const
int GLCanvas3D::GetHoverId()
{
if (m_hover_plate_idxs.size() == 0) {
return -1; }
return m_hover_plate_idxs.front();
}
PrinterTechnology GLCanvas3D::current_printer_technology() const {
return m_process->current_printer_technology();
}
@ -3125,15 +3118,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case WXK_BACK: { post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; }
#endif
case WXK_ESCAPE: { deselect_all(); break; }
case WXK_F5: {
if (wxGetApp().mainframe->is_printer_view())
wxGetApp().mainframe->load_printer_url();
//if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
// (wxGetApp().is_gcode_viewer() && !wxGetApp().plater()->get_last_loaded_gcode().empty()))
// post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK));
break;
}
//case WXK_F5: {
// if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
// (wxGetApp().is_gcode_viewer() && !wxGetApp().plater()->get_last_loaded_gcode().empty()))
// post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK));
// break;
//}
// BBS: use keypad to change extruder
case '1':
@ -3185,8 +3175,10 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
}
//case 'B':
//case 'b': { zoom_to_bed(); break; }
#if !BBL_RELEASE_TO_PUBLIC
case 'C':
case 'c': { m_gcode_viewer.toggle_gcode_window_visibility(); m_dirty = true; request_extra_frame(); break; }
#endif
//case 'G':
//case 'g': {
// if ((evt.GetModifiers() & shiftMask) != 0) {
@ -3384,11 +3376,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
else if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
// Enable switching between 3D and Preview with Tab
// m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux
post_event(SimpleEvent(EVT_GLCANVAS_TAB));
}
else if (keyCode == WXK_TAB && evt.ShiftDown() && !evt.ControlDown() && ! wxGetApp().is_gcode_viewer()) {
// Collapse side-panel with Shift+Tab
post_event(SimpleEvent(EVT_GLCANVAS_COLLAPSE_SIDEBAR));
//post_event(SimpleEvent(EVT_GLCANVAS_TAB));
}
else if (keyCode == WXK_SHIFT) {
translationProcessor.process(evt);
@ -5056,7 +5044,7 @@ void GLCanvas3D::update_sequential_clearance()
// the results are then cached for following displacements
if (m_sequential_print_clearance_first_displacement) {
m_sequential_print_clearance.m_hull_2d_cache.clear();
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON));
float shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_max_radius.value - EPSILON));
double mitter_limit = scale_(0.1);
m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
for (size_t i = 0; i < m_model->objects.size(); ++i) {
@ -5407,22 +5395,20 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
ImGui::Separator();
if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings.enable_rotation)) {
settings_out.enable_rotation = settings.enable_rotation;
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation);
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
settings_changed = true;
}
if (imgui->bbl_checkbox(_L("Allow multiple materials on same plate"), settings.allow_multi_materials_on_same_plate)) {
settings_out.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate );
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate ? "1" : "0");
settings_changed = true;
}
// only show this option if the printer has micro Lidar and can do first layer scan
DynamicPrintConfig &current_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
auto op = current_config.option("scan_first_layer");
if (has_lidar && op && op->getBool()) {
if (op && op->getBool()) {
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings.avoid_extrusion_cali_region)) {
settings_out.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region ? "1" : "0");
@ -5581,19 +5567,25 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
//camera.select_view("top");
}
else {
camera.zoom_to_box(volumes_box);
const Vec3d& target = camera.get_target();
double distance = camera.get_distance();
camera.select_view("iso");
camera.apply_view_matrix();
//camera.zoom_to_box(volumes_box);
camera.apply_projection(plate_build_volume);
//const Vec3d& target = camera.get_target();
//double distance = camera.get_distance();
//camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
//BBS: use original iso view for thumbnail
camera.select_view("iso");
camera.zoom_to_box(volumes_box);
}
camera.apply_view_matrix();
camera.apply_projection(plate_build_volume);
//double near_z = -1.0;
//double far_z = -1.0;
//camera.apply_projection(volumes_box, near_z, far_z);
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (!for_picking && (shader == nullptr)) {
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
@ -5601,8 +5593,17 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
}
//if (thumbnail_params.transparent_background)
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
if (for_picking)
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
else {
//glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
//glsafe(::glClearColor(0.50f, 0.5f, 0.5f, 1.0f));
//glsafe(::glClearColor(0.121568f, 0.121568f, 0.121568f, 1.0f));
//glsafe(::glClearColor(0.17647f, 0.17647f, 0.17647f, 1.0f));
//glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
//glsafe(::glClearColor(0.37647f, 0.37647f, 0.37647f, 0.5f)); too lite
glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
}
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
@ -6104,7 +6105,12 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "toolbar_arrange_dark.svg" : "toolbar_arrange.svg";
item.tooltip = _utf8(L("Arrange all objects")) + " [A]\n" + _utf8(L("Arrange objects on selected plates")) + " [Shift+A]";
item.sprite_id++;
item.left.action_callback = []() {};
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("auto_arrange", std::to_string(++auto_arrange_count));
}
};
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
item.left.toggable = true;
//BBS: GUI refactor: adjust the main toolbar position
@ -6129,7 +6135,13 @@ bool GLCanvas3D::_init_main_toolbar()
item.tooltip = _utf8(L("Split to objects"));
item.sprite_id++;
item.left.render_callback = nullptr;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("split_to_objects", std::to_string(++split_to_objects_count));
}
};
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
if (!m_main_toolbar.add_item(item))
@ -6139,7 +6151,13 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "split_parts_dark.svg" : "split_parts.svg";
item.tooltip = _utf8(L("Split to parts"));
item.sprite_id++;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("split_to_part", std::to_string(++split_to_part_count));
}
};
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
if (!m_main_toolbar.add_item(item))
@ -6149,7 +6167,13 @@ bool GLCanvas3D::_init_main_toolbar()
item.icon_filename = m_is_dark ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg";
item.tooltip = _utf8(L("Variable layer height"));
item.sprite_id++;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING));
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("custom_height", std::to_string(++custom_height_count));
}
};
item.visibility_callback = [this]()->bool {
bool res = current_printer_technology() == ptFFF;
// turns off if changing printer technology
@ -6173,7 +6197,6 @@ bool GLCanvas3D::_init_select_plate_toolbar()
bool result = item->image_texture.load_from_svg_file(path + "im_all_plates_stats.svg", false, false, false, 128);
result = result && item->image_texture_transparent.load_from_svg_file(path + "im_all_plates_stats_transparent.svg", false, false, false, 128);
m_sel_plate_toolbar.m_all_plates_stats_item = item;
return result;
}
@ -6253,7 +6276,13 @@ bool GLCanvas3D::_init_assemble_view_toolbar()
item.tooltip = _utf8(L("Assembly View"));
item.sprite_id = 1;
item.left.toggable = false;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); };
item.left.action_callback = [this]() {
if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); m_gizmos.reset_all_states(); wxGetApp().plater()->get_assmeble_canvas3D()->get_gizmos_manager().reset_all_states();
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("custom_painting", std::to_string(++custom_painting_count));
}
};
item.left.render_callback = GLToolbarItem::Default_Render_Callback;
item.visible = true;
item.visibility_callback = [this]()->bool { return true; };
@ -6722,22 +6751,22 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
if (const BuildVolume &build_volume = m_bed.build_volume(); build_volume.valid()) {
switch (build_volume.type()) {
case BuildVolume_Type::Rectangle: {
case BuildVolume::Type::Rectangle: {
const BoundingBox3Base<Vec3d> bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon);
m_volumes.set_print_volume({ 0, // Rectangle
{ float(bed_bb.min.x()), float(bed_bb.min.y()), float(bed_bb.max.x()), float(bed_bb.max.y()) },
{ 0.0f, float(build_volume.printable_height()) } });
break;
}
case BuildVolume_Type::Circle: {
case BuildVolume::Type::Circle: {
m_volumes.set_print_volume({ 1, // Circle
{ unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()), unscaled<float>(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f },
{ 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } });
break;
}
default:
case BuildVolume_Type::Convex:
case BuildVolume_Type::Custom: {
case BuildVolume::Type::Convex:
case BuildVolume::Type::Custom: {
m_volumes.set_print_volume({ static_cast<int>(type),
{ -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX },
{ -FLT_MAX, FLT_MAX } }
@ -8970,8 +8999,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2;
double height = m_gcode_viewer.m_conflict_result.value()._height;
int layer = m_gcode_viewer.m_conflict_result.value().layer;
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
height % objName1 % objName2)
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d. Please separate the conflicted objects farther (%s <-> %s).")) % (layer + 1) %
objName1 % objName2)
.str();
prevConflictText = text;
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(m_gcode_viewer.m_conflict_result.value()._obj2);

View file

@ -138,6 +138,7 @@ private:
wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_PLATE_NAME_CHANGE, SimpleEvent);
//BBS: declare EVT_GLCANVAS_PLATE_SELECT
wxDECLARE_EVENT(EVT_GLCANVAS_PLATE_SELECT, SimpleEvent);
@ -413,6 +414,7 @@ class GLCanvas3D
void render(const std::vector<const ModelInstance*>& sorted_instances) const;
};
class Tooltip
{
std::string m_text;
@ -498,6 +500,8 @@ public:
CanvasAssembleView = 2,
};
int GetHoverId();
private:
bool m_is_dark = false;
wxGLCanvas* m_canvas;
@ -593,6 +597,7 @@ private:
Labels m_labels;
Tooltip m_tooltip;
bool m_tooltip_enabled{ true };
Slope m_slope;
OrientSettings m_orient_settings_fff, m_orient_settings_sla;

View file

@ -483,7 +483,7 @@ bool GLTexture::generate_from_text(const std::string &text_str, wxFont &font, wx
return false;
}
wxString msg = _(text_str);
wxString msg = from_u8(text_str);
wxMemoryDC memDC;
memDC.SetFont(font);

View file

@ -112,6 +112,7 @@ namespace GUI {
bool generate_from_text_string(const std::string& text_str, wxFont& font, wxColor background = *wxBLACK, wxColor foreground = *wxWHITE);
unsigned int get_id() const { return m_id; }
int get_original_width() const { return m_original_width; }
int get_width() const { return m_width; }
int get_height() const { return m_height; }

View file

@ -554,7 +554,7 @@ void desktop_open_any_folder( const std::string path )
#elif __APPLE__
openFolderForFile(from_u8(path));
#else
const char *argv[] = {"xdg-open", path.data(), nullptr};
const char *argv[] = {"nautilus", path.data(), nullptr};
// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
// because they may mess up the environment expected by the file manager.

File diff suppressed because it is too large Load diff

View file

@ -115,9 +115,9 @@ enum ConfigMenuIDs {
ConfigMenuCnt,
};
enum OrcaSlicerMenuIDs {
OrcaSlicerMenuAbout,
OrcaSlicerMenuPreferences,
enum BambuStudioMenuIDs {
BambuStudioMenuAbout,
BambuStudioMenuPreferences,
};
enum CameraMenuIDs {
@ -292,20 +292,26 @@ private:
bool m_is_dark_mode{ false };
bool m_adding_script_handler { false };
bool m_side_popup_status{false};
wxString m_info_dialog_content;
HttpServer m_http_server;
bool m_show_gcode_window{true};
public:
boost::thread m_check_network_thread;
public:
//try again when subscription fails
void on_start_subscribe_again(std::string dev_id);
void check_filaments_in_blacklist(std::string tag_supplier, std::string tag_material, bool& in_blacklist, std::string& action, std::string& info);
std::string get_local_models_path();
bool OnInit() override;
bool initialized() const { return m_initialized; }
std::map<std::string, bool> test_url_state;
//BBS: remove GCodeViewer as seperate APP logic
explicit GUI_App();
//explicit GUI_App(EAppMode mode = EAppMode::Editor);
~GUI_App() override;
void show_message_box(std::string msg) { wxMessageBox(msg); }
EAppMode get_app_mode() const { return m_app_mode; }
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
@ -314,12 +320,10 @@ private:
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
bool is_recreating_gui() const { return m_is_recreating_gui; }
std::string logo_name() const { return is_editor() ? "OrcaSlicer" : "OrcaSlicer-gcodeviewer"; }
// SoftFever
bool show_gcode_window() const { return m_show_gcode_window; }
void set_show_gcode_window(bool val) { m_show_gcode_window = val; }
std::string logo_name() const { return is_editor() ? "BambuStudio" : "BambuStudio-gcodeviewer"; }
wxString get_inf_dialog_contect () {return m_info_dialog_content;};
std::vector<std::string> split_str(std::string src, std::string separator);
// To be called after the GUI is fully built up.
// Process command line parameters cached in this->init_params,
// load configs, STLs etc.
@ -338,6 +342,8 @@ private:
const wxColour get_label_default_clr_modified();
void init_label_colours();
void update_label_colours_from_appconfig();
void update_publish_status();
bool has_model_mall();
void update_label_colours();
// update color mode for window
void UpdateDarkUI(wxWindow *window, bool highlited = false, bool just_font = false);
@ -357,6 +363,8 @@ private:
//update side popup status
bool get_side_menu_popup_status();
void set_side_menu_popup_status(bool status);
void link_to_network_check();
const wxColour& get_label_clr_modified(){ return m_color_label_modified; }
const wxColour& get_label_clr_sys() { return m_color_label_sys; }
@ -411,7 +419,7 @@ private:
int request_user_unbind(std::string dev_id);
std::string handle_web_request(std::string cmd);
void handle_script_message(std::string msg);
void request_model_download(std::string url);
void request_model_download(wxString url);
void download_project(std::string project_id);
void request_project_download(std::string project_id);
void request_open_project(std::string project_id);
@ -432,7 +440,6 @@ private:
void check_update(bool show_tips, int by_user);
void check_new_version(bool show_tips = false, int by_user = 0);
void check_new_version_sf(bool show_tips = false, int by_user = 0);
void request_new_version(int by_user);
void enter_force_upgrade();
void set_skip_version(bool skip = true);
@ -442,10 +449,11 @@ private:
void reload_settings();
void remove_user_presets();
void sync_preset(Preset* preset);
void start_sync_user_preset(bool load_immediately = false, bool with_progress_dlg = false);
void start_sync_user_preset(bool with_progress_dlg = false);
void stop_sync_user_preset();
void start_http_server();
void stop_http_server();
void switch_staff_pick(bool on);
void on_show_check_privacy_dlg(int online_login = 0);
void show_check_privacy_dlg(wxCommandEvent& evt);
@ -466,8 +474,10 @@ private:
Tab* get_model_tab(bool part = false);
Tab* get_layer_tab();
ConfigOptionMode get_mode();
std::string get_mode_str();
void save_mode(const /*ConfigOptionMode*/int mode) ;
void update_mode();
void update_internal_development();
void show_ip_address_enter_dialog(wxString title = wxEmptyString);
void show_ip_address_enter_dialog_handler(wxCommandEvent &evt);
bool show_modal_ip_address_enter_dialog(wxString title = wxEmptyString);
@ -492,6 +502,7 @@ private:
void delete_preset_from_cloud(std::string setting_id);
void preset_deleted_from_cloud(std::string setting_id);
wxString filter_string(wxString str);
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
wxString current_language_code_safe() const;
@ -602,7 +613,7 @@ private:
std::string get_plugin_url(std::string name, std::string country_code);
int download_plugin(std::string name, std::string package_name, InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
int install_plugin(std::string name, std::string package_name, InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
std::string get_http_url(std::string country_code);
std::string get_http_url(std::string country_code, std::string path = {});
std::string get_model_http_url(std::string country_code);
bool is_compatibility_version();
bool check_networking_version();

View file

@ -57,6 +57,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF =
// BBS
{ L("Support") , { "enable_support", "support_type", "support_threshold_angle",
"support_base_pattern", "support_on_build_plate_only","support_critical_regions_only",
"support_remove_small_overhang",
"support_base_pattern_spacing", "support_expansion"}},
//BBS
{ L("Flush options") , { "flush_into_infill", "flush_into_objects", "flush_into_support"} }
@ -73,18 +74,17 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
{
{ L("Quality"), {{"layer_height", "",1},
//{"initial_layer_print_height", "",2},
{"seam_position", "",2},
{"slice_closing_radius", "",3}, {"resolution", "",4},
{"xy_hole_compensation", "",5}, {"xy_contour_compensation", "",6}, {"elefant_foot_compensation", "",7},
{"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}
{"seam_position", "",2}, {"seam_gap", "",3}, {"wipe_speed", "",4},
{"slice_closing_radius", "",5}, {"resolution", "",6},
{"xy_hole_compensation", "",7}, {"xy_contour_compensation", "",8}, {"elefant_foot_compensation", "",9}
}},
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7},
{"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25},
{"tree_support_branch_angle", "",10}, {"tree_support_wall_count", "",11},//tree support
{"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10}, {"tree_support_wall_count", "",11},//tree support
{"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15},
{"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19},
{"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23}
{"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23},{"support_remove_small_overhang","",27}
}},
{ L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13}
}}
@ -92,16 +92,16 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CATEGORY_SETTINGS=
{
{ L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11},{"make_overhang_printable", "",11},{"bridge_density", "", 1}
{ L("Quality"), {{"ironing_type", "",8},{"ironing_flow", "",9},{"ironing_spacing", "",10},{"bridge_flow", "",11}
}},
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", "",1},{"top_shell_thickness", "",1},
{"bottom_shell_layers", "",1}, {"bottom_shell_thickness", "",1}, {"sparse_infill_density", "",1},
{"sparse_infill_pattern", "",1},{"sparse_infill_anchor", "",1},{"sparse_infill_anchor_max", "",1}, {"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1},
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1},{"minimum_sparse_infill_area", "",1}
}},
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
{"enable_overhang_speed", "",6}, {"overhang_speed_classic", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"bridge_speed", "",11}, {"gap_infill_speed", "",12}, {"internal_bridge_speed", "", 13}
{"enable_overhang_speed", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"bridge_speed", "",11}, {"gap_infill_speed", "",12}
}}
};
@ -141,7 +141,7 @@ std::vector<SimpleSettingData> SettingsFactory::get_visible_options(const std::s
//Quality
"layer_height", "initial_layer_print_height", "adaptive_layer_height", "seam_position", "xy_hole_compensation", "xy_contour_compensation", "elefant_foot_compensation", "support_line_width",
//Support
"enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "support_critical_regions_only", "enforce_support_layers",
"enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "support_critical_regions_only", "enforce_support_layers","support_remove_small_overhang",
//tree support
"tree_support_wall_count",
//support
@ -484,38 +484,18 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty
sub_menu->AppendSeparator();
}
for (auto &item : {L("Orca Cube"), L("3DBenchy"), L("Autodesk FDM Test"),
L("Voron Cube")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent &) {
std::vector<boost::filesystem::path> input_files;
std::string file_name = item;
if (file_name == L("Orca Cube"))
file_name = "OrcaCube_v2.3mf";
else if (file_name == L("3DBenchy"))
file_name = "3DBenchy.stl";
else if (file_name == L("Autodesk FDM Test"))
file_name = "ksr_fdmtest_v4.stl";
else if (file_name == L("Voron Cube"))
file_name = "Voron_Design_Cube_v7.stl";
else
return;
input_files.push_back(
(boost::filesystem::path(Slic3r::resources_dir()) /
"handy_models" / file_name));
plater()->load_files(input_files, LoadStrategy::LoadModel);
},
"", menu);
for (auto &item : {L("Cube"), L("Cylinder"), L("Sphere"), L("Cone")})
{
append_menu_item(sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent&) { obj_list()->load_generic_subobject(item, type); }, "", menu);
}
sub_menu->AppendSeparator();
for (auto &item : {L("Cube"), L("Cylinder"), L("Sphere"), L("Cone")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent &) {
obj_list()->load_generic_subobject(item, type);
},
"", menu);
if (type == ModelVolumeType::INVALID) {
sub_menu->AppendSeparator();
for (auto &item : {L("Bambu Cube"), L("Bambu Cube V2"), L("3DBenchy"), L("ksr FDMTest")}) {
append_menu_item(
sub_menu, wxID_ANY, _(item), "", [type, item](wxCommandEvent &) { obj_list()->load_generic_subobject(item, type); }, "", menu);
}
}
return sub_menu;
@ -656,13 +636,6 @@ wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu)
return menu_item;
}
void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
{
append_menu_item(
menu, wxID_ANY, _L("Fill bed with copies"), _L("Fill the remaining area of bed with copies of the selected object"),
[](wxCommandEvent &) { plater()->fill_bed_with_instances(); }, "", nullptr, []() { return plater()->can_increase_instances(); }, m_parent);
}
wxMenuItem* MenuFactory::append_menu_item_printable(wxMenu* menu)
{
// BBS: to be checked
@ -824,36 +797,57 @@ void MenuFactory::append_menu_items_flush_options(wxMenu* menu)
DynamicPrintConfig& global_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
ModelConfig& select_object_config = object_list->object(selection.get_object_idx())->config;
auto keys = select_object_config.keys();
for (auto key : FREQ_SETTINGS_BUNDLE_FFF["Flush options"]) {
if (find(keys.begin(), keys.end(), key) == keys.end()) {
const ConfigOption* option = global_config.option(key);
select_object_config.set_key_value(key, option->clone());
}
}
wxMenu* flush_options_menu = new wxMenu();
append_menu_check_item(flush_options_menu, wxID_ANY, _L("Flush into objects' infill"), "",
[&select_object_config](wxCommandEvent&) {
[&select_object_config, &global_config](wxCommandEvent&) {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0]);
}
select_object_config.set_key_value(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0], new ConfigOptionBool(!option->getBool()));
wxGetApp().obj_settings()->UpdateAndShow(true);
}, menu, []() {return true; }, [&select_object_config]() {const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0]); return option->getBool(); }, m_parent);
}, menu, []() {return true; },
[&select_object_config, &global_config]() {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][0]);
}
return option->getBool();
}, m_parent);
append_menu_check_item(flush_options_menu, wxID_ANY, _L("Flush into this object"), "",
[&select_object_config](wxCommandEvent&) {
[&select_object_config, &global_config](wxCommandEvent&) {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1]);
}
select_object_config.set_key_value(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1], new ConfigOptionBool(!option->getBool()));
wxGetApp().obj_settings()->UpdateAndShow(true);
}, menu, []() {return true; }, [&select_object_config]() {const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1]); return option->getBool(); }, m_parent);
}, menu, []() {return true; },
[&select_object_config, &global_config]() {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][1]);
}
return option->getBool();
}, m_parent);
append_menu_check_item(flush_options_menu, wxID_ANY, _L("Flush into objects' support"), "",
[&select_object_config](wxCommandEvent&) {
[&select_object_config, &global_config](wxCommandEvent&) {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2]);
}
select_object_config.set_key_value(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2], new ConfigOptionBool(!option->getBool()));
wxGetApp().obj_settings()->UpdateAndShow(true);
}, menu, []() {return true; }, [&select_object_config]() {const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2]); return option->getBool(); }, m_parent);
}, menu, []() {return true; },
[&select_object_config, &global_config]() {
const ConfigOption* option = select_object_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2]);
if (!option) {
option = global_config.option(FREQ_SETTINGS_BUNDLE_FFF["Flush options"][2]);
}
return option->getBool();
}, m_parent);
size_t i = 0;
for (auto node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
@ -940,9 +934,9 @@ void MenuFactory::append_menu_item_merge_to_single_object(wxMenu* menu)
void MenuFactory::append_menu_item_merge_parts_to_single_part(wxMenu* menu)
{
menu->AppendSeparator();
append_menu_item(menu, wxID_ANY, _L("Assemble"), _L("Assemble the selected parts to a single part"),
[](wxCommandEvent&) { obj_list()->merge_volumes(); }, "", menu,
[]() { return true; }, m_parent);
append_menu_item(menu, wxID_ANY, _L("Mesh boolean"), _L("Mesh boolean operations including union and subtraction"),
[](wxCommandEvent&) { obj_list()->boolean/*merge_volumes*/(); }, "", menu,
[]() { return obj_list()->can_mesh_boolean(); }, m_parent);
}
void MenuFactory::append_menu_items_mirror(wxMenu* menu)
@ -1047,7 +1041,7 @@ void MenuFactory::create_object_menu()
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
}
void MenuFactory::create_extra_object_menu()
void MenuFactory::create_bbl_object_menu()
{
append_menu_item_fill_bed(&m_object_menu);
// Object Clone
@ -1056,6 +1050,8 @@ void MenuFactory::create_extra_object_menu()
append_menu_item_fix_through_netfabb(&m_object_menu);
// Object Simplify
append_menu_item_simplify(&m_object_menu);
// merge to single part
append_menu_item_merge_parts_to_single_part(&m_object_menu);
// Object Center
append_menu_item_center(&m_object_menu);
// Object Split
@ -1270,7 +1266,7 @@ void MenuFactory::init(wxWindow* parent)
create_sla_object_menu();
//create_part_menu();
create_extra_object_menu();
create_bbl_object_menu();
create_bbl_part_menu();
create_bbl_assemble_object_menu();
create_bbl_assemble_part_menu();
@ -1295,10 +1291,10 @@ wxMenu* MenuFactory::default_menu()
wxMenu* MenuFactory::object_menu()
{
append_menu_item_change_filament(&m_object_menu);
append_menu_items_convert_unit(&m_object_menu);
append_menu_items_flush_options(&m_object_menu);
append_menu_item_invalidate_cut_info(&m_object_menu);
append_menu_item_change_filament(&m_object_menu);
return &m_object_menu;
}
@ -1358,13 +1354,13 @@ wxMenu* MenuFactory::multi_selection_menu()
//append_menu_item_simplify(menu);
append_menu_item_delete(menu);
menu->AppendSeparator();
//BBS
append_menu_item_change_filament(menu);
append_menu_item_set_printable(menu);
append_menu_item_per_object_process(menu);
menu->AppendSeparator();
append_menu_items_convert_unit(menu);
//BBS
append_menu_item_change_filament(menu);
menu->AppendSeparator();
append_menu_item_export_stl(menu, true);
}
@ -1374,6 +1370,7 @@ wxMenu* MenuFactory::multi_selection_menu()
//append_menu_item_simplify(menu);
append_menu_item_delete(menu);
append_menu_items_convert_unit(menu);
append_menu_item_change_filament(menu);
wxMenu* split_menu = new wxMenu();
if (split_menu) {
append_menu_item(split_menu, wxID_ANY, _L("To objects"), _L("Split the selected object into multiple objects"),
@ -1386,8 +1383,6 @@ wxMenu* MenuFactory::multi_selection_menu()
append_submenu(menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "",
[]() { return plater()->can_split(true); }, m_parent);
}
menu->AppendSeparator();
append_menu_item_change_filament(menu);
}
return menu;
}
@ -1417,6 +1412,7 @@ wxMenu* MenuFactory::assemble_multi_selection_menu()
wxMenu* MenuFactory::plate_menu()
{
append_menu_item_locked(&m_plate_menu);
append_menu_item_plate_name(&m_plate_menu);
return &m_plate_menu;
}
@ -1621,11 +1617,16 @@ void MenuFactory::append_menu_item_set_printable(wxMenu* menu)
}
}
wxString menu_text = all_printable ? _L("Set Unprintable") : _L("Set Printable");
append_menu_item(menu, wxID_ANY, menu_text, "", [this, all_printable](wxCommandEvent&) {
wxString menu_text = _L("Printable");
wxMenuItem* menu_item_set_printable = append_menu_check_item(menu, wxID_ANY, menu_text, "", [this, all_printable](wxCommandEvent&) {
Selection& selection = plater()->canvas3D()->get_selection();
selection.set_printable(!all_printable);
}, "", nullptr, []() { return true; }, m_parent);
}, menu);
m_parent->Bind(wxEVT_UPDATE_UI, [all_printable](wxUpdateUIEvent& evt) {
evt.Check(all_printable);
plater()->set_current_canvas_as_dirty();
}, menu_item_set_printable->GetId());
}
void MenuFactory::append_menu_item_locked(wxMenu* menu)
@ -1657,6 +1658,47 @@ void MenuFactory::append_menu_item_locked(wxMenu* menu)
}, item->GetId());
}
void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
{
append_menu_item(
menu, wxID_ANY, _L("Fill bed with copies"), _L("Fill the remaining area of bed with copies of the selected object"),
[](wxCommandEvent &) { plater()->fill_bed_with_instances(); }, "", nullptr, []() { return plater()->can_increase_instances(); }, m_parent);
}
void MenuFactory::append_menu_item_plate_name(wxMenu *menu)
{
wxString name= _L("Edit Plate Name");
// Delete old menu item
const int item_id = menu->FindItem(name);
if (item_id != wxNOT_FOUND) menu->Destroy(item_id);
PartPlate *plate = plater()->get_partplate_list().get_selected_plate();
assert(plate);
auto item = append_menu_item(
menu, wxID_ANY, name, "",
[plate](wxCommandEvent &e) {
int hover_idx =plater()->canvas3D()->GetHoverId();
if (hover_idx == -1) {
int plate_idx=plater()->GetPlateIndexByRightMenuInLeftUI();
plater()->select_plate_by_hover_id(plate_idx * PartPlate::GRABBER_COUNT, false, true);
}
else
{
plater()->select_plate_by_hover_id(hover_idx, false, true);
}
plater()->get_current_canvas3D()->post_event(SimpleEvent(EVT_GLCANVAS_PLATE_NAME_CHANGE));
},
"", nullptr, []() { return true; }, m_parent);
m_parent->Bind(
wxEVT_UPDATE_UI,
[](wxUpdateUIEvent &evt) {
PartPlate *plate = plater()->get_partplate_list().get_selected_plate();
assert(plate);
plater()->set_current_canvas_as_dirty();
},
item->GetId());
}
void MenuFactory::update_object_menu()
{

View file

@ -108,7 +108,7 @@ private:
//BBS: add part plate related logic
void create_plate_menu();
//BBS: add bbl object menu
void create_extra_object_menu();
void create_bbl_object_menu();
void create_bbl_part_menu();
void create_bbl_assemble_object_menu();
void create_bbl_assemble_part_menu();
@ -151,7 +151,7 @@ private:
void append_menu_item_set_printable(wxMenu* menu);
void append_menu_item_locked(wxMenu* menu);
void append_menu_item_fill_bed(wxMenu *menu);
void append_menu_item_plate_name(wxMenu *menu);
};
}}

View file

@ -35,7 +35,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) :
void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range)
{
if (is_last_edited_range && m_selection_type == editor->type()) {
//if (is_last_edited_range && m_selection_type == editor->type()) {
/* Workaround! Under OSX we should use CallAfter() for SetFocus() after LayerEditors "reorganizations",
* because of selected control's strange behavior:
* cursor is set to the control, but blue border - doesn't.
@ -44,12 +44,12 @@ void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_ed
#ifdef __WXOSX__
wxTheApp->CallAfter([editor]() {
#endif
editor->SetFocus();
editor->SetInsertionPointEnd();
//editor->SetFocus();
//editor->SelectAll();
#ifdef __WXOSX__
});
#endif
}
//}
}
wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinusButton *delete_button, PlusMinusButton *add_button)
@ -131,7 +131,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
return wxGetApp().obj_list()->edit_layer_range(range, new_range, dont_update_ui);
});
select_editor(editor, is_last_edited_range);
//select_editor(editor, is_last_edited_range);
auto sizer2 = new wxBoxSizer(wxHORIZONTAL);
sizer2->Add(editor);
@ -170,11 +170,13 @@ void ObjectLayers::create_layers_list()
{
for (const auto &layer : m_object->layer_config_ranges) {
const t_layer_height_range& range = layer.first;
auto del_btn = new PlusMinusButton(m_parent, m_bmp_delete, range);
auto del_btn = new PlusMinusButton(m_parent, m_bmp_delete, range);
del_btn->DisableFocusFromKeyboard();
del_btn->SetBackgroundColour(m_parent->GetBackgroundColour());
del_btn->SetToolTip(_L("Remove height range"));
auto add_btn = new PlusMinusButton(m_parent, m_bmp_add, range);
auto add_btn = new PlusMinusButton(m_parent, m_bmp_add, range);
add_btn->DisableFocusFromKeyboard();
add_btn->SetBackgroundColour(m_parent->GetBackgroundColour());
wxString tooltip = wxGetApp().obj_list()->can_add_new_range_after_current(range);
add_btn->SetToolTip(tooltip.IsEmpty() ? _L("Add height range") : tooltip);

View file

@ -21,6 +21,7 @@
#include "NotificationManager.hpp"
#include "MsgDialog.hpp"
#include "Widgets/ProgressDialog.hpp"
#include "SingleChoiceDialog.hpp"
#include <boost/algorithm/string.hpp>
#include <wx/progdlg.h>
@ -169,7 +170,11 @@ ObjectList::ObjectList(wxWindow* parent) :
ObjectDataViewModelNode* sel_node = (ObjectDataViewModelNode*)event.GetItem().GetID();
if (sel_node && (sel_node->GetType() & ItemType::itPlate)) {
wxGetApp().plater()->select_plate(sel_node->GetPlateIdx());
if (wxGetApp().plater()->is_preview_shown()) {
wxGetApp().plater()->select_sliced_plate(sel_node->GetPlateIdx());
} else {
wxGetApp().plater()->select_plate(sel_node->GetPlateIdx());
}
wxGetApp().plater()->deselect_all();
}
else {
@ -267,6 +272,12 @@ ObjectList::ObjectList(wxWindow* parent) :
//Bind(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, [this](wxCommandEvent& e) { last_volume_is_deleted(e.GetInt()); });
Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) {
if (m_last_size == this->GetSize()) {
e.Skip();
return;
} else {
m_last_size = this->GetSize();
}
#ifdef __WXGTK__
// On GTK, the EnsureVisible call is postponed to Idle processing (see wxDataViewCtrl::m_ensureVisibleDefered).
// So the postponed EnsureVisible() call is planned for an item, which may not exist at the Idle processing time, if this wxEVT_SIZE
@ -281,7 +292,7 @@ ObjectList::ObjectList(wxWindow* parent) :
#endif
e.Skip();
}));
m_last_size = this->GetSize();
}
ObjectList::~ObjectList()
@ -377,7 +388,8 @@ void ObjectList::create_objects_ctrl()
return m_objects_model->GetDefaultExtruderIdx(GetSelection());
});
bmp_choice_renderer->set_has_default_extruder([this]() {
return m_objects_model->GetVolumeType(GetSelection()) == ModelVolumeType::PARAMETER_MODIFIER;
return m_objects_model->GetVolumeType(GetSelection()) == ModelVolumeType::PARAMETER_MODIFIER ||
m_objects_model->GetItemType(GetSelection()) == itLayer;
});
AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer,
colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0));
@ -1193,13 +1205,15 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
}
}
else if (col_num == colColorPaint) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
if (node->HasColorPainting()) {
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation)
gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation);
else
gizmos_mgr.reset_all_states();
if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
if (node->HasColorPainting()) {
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation)
gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation);
else
gizmos_mgr.reset_all_states();
}
}
}
else if (col_num == colSinking) {
@ -1258,7 +1272,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
const auto item = GetSelection();
if (item)
{
const ItemType type = m_objects_model->GetItemType(item);
const ItemType type = m_objects_model->GetItemType(item);
if (!(type & (itPlate | itObject | itVolume | itInstance)))
return;
@ -1266,6 +1280,14 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
type & itInstance ? plater->instance_menu() :
type & itVolume ? plater->part_menu() :
printer_technology() == ptFFF ? plater->object_menu() : plater->sla_object_menu();
plater->SetPlateIndexByRightMenuInLeftUI(-1);
if (type & itPlate) {
int plate_idx = -1;
const ItemType type0 = m_objects_model->GetItemType(item, plate_idx);
if (plate_idx >= 0) {
plater->SetPlateIndexByRightMenuInLeftUI(plate_idx);
}
}
}
else if (evt_context_menu)
menu = plater->default_menu();
@ -1934,12 +1956,13 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
Model model;
try {
model = Model::read_from_file(input_file);
model = Model::read_from_file(input_file, nullptr, nullptr, LoadStrategy::LoadModel);
}
catch (std::exception& e) {
auto msg = _L("Error!") + " " + input_file + " : " + e.what() + ".";
// auto msg = _L("Error!") + " " + input_file + " : " + e.what() + ".";
auto msg = _L("Error!") + " " + _L("Failed to get the model data in the current file.");
show_error(parent, msg);
exit(1);
return;
}
if (from_galery)
@ -1956,6 +1979,7 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
}
}
model.add_default_instances();
TriangleMesh mesh = model.mesh();
// Mesh will be centered when loading.
ModelVolume* new_volume = model_object.add_volume(std::move(mesh), type);
@ -1996,24 +2020,32 @@ static TriangleMesh create_mesh(const std::string& type_name, const BoundingBoxf
{
const double side = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.1);
indexed_triangle_set mesh;
TriangleMesh mesh;
if (type_name == "Cube")
// Sitting on the print bed, left front front corner at (0, 0).
mesh = its_make_cube(side, side, side);
mesh = TriangleMesh(its_make_cube(side, side, side));
else if (type_name == "Cylinder")
// Centered around 0, sitting on the print bed.
// The cylinder has the same volume as the box above.
mesh = its_make_cylinder(0.5 * side, side);
mesh = TriangleMesh(its_make_cylinder(0.5 * side, side));
else if (type_name == "Sphere")
// Centered around 0, half the sphere below the print bed, half above.
// The sphere has the same volume as the box above.
mesh = its_make_sphere(0.5 * side, PI / 18);
mesh = TriangleMesh(its_make_sphere(0.5 * side, PI / 18));
else if (type_name == "Slab")
// Sitting on the print bed, left front front corner at (0, 0).
mesh = its_make_cube(bb.size().x() * 1.5, bb.size().y() * 1.5, bb.size().z() * 0.5);
mesh = TriangleMesh(its_make_cube(bb.size().x() * 1.5, bb.size().y() * 1.5, bb.size().z() * 0.5));
else if (type_name == "Cone")
mesh = its_make_cone(0.5 * side, side);
return TriangleMesh(mesh);
mesh = TriangleMesh(its_make_cone(0.5 * side, side));
else if (type_name == "Bambu Cube")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/Bambu_Cube.stl").c_str(), true, nullptr);
else if (type_name == "Bambu Cube V2")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/Bambu_Cube_V2.stl").c_str(), true, nullptr);
else if (type_name == "3DBenchy")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/3DBenchy.stl").c_str(), true, nullptr);
else if (type_name == "ksr FDMTest")
mesh.ReadSTLFile((Slic3r::resources_dir() + "/model/ksr_FDMTest.stl").c_str(), true, nullptr);
return mesh;
}
void ObjectList::load_generic_subobject(const std::string& type_name, const ModelVolumeType type)
@ -2744,6 +2776,9 @@ void ObjectList::merge(bool to_multipart_object)
new_object->center_around_origin();
new_object->translate_instances(-new_object->origin_translation);
new_object->origin_translation = Vec3d::Zero();
//BBS init asssmble transformation
Geometry::Transformation t = new_object->instances[0]->get_transformation();
new_object->instances[0]->set_assemble_transformation(t);
//BBS: notify it before remove
notify_instance_updated(m_objects->size() - 1);
@ -2851,6 +2886,45 @@ void ObjectList::layers_editing()
Expand(layers_item);
}
// BBS: merge parts of a single object into one volume, similar to export_stl, but no need to export and then import
void ObjectList::boolean()
{
std::vector<int> obj_idxs, vol_idxs;
get_selection_indexes(obj_idxs, vol_idxs);
if (obj_idxs.empty() && vol_idxs.empty())
return;
Plater::TakeSnapshot snapshot(wxGetApp().plater(), "boolean");
Model* model = (*m_objects)[0]->get_model();
ModelObject* new_object = model->add_object();
new_object->name = (*m_objects)[0]->name;
new_object->config.assign_config((*m_objects)[0]->config);
if (new_object->instances.empty())
new_object->add_instance();
ModelObject* object = (*m_objects)[obj_idxs.front()];
TriangleMesh mesh = Plater::combine_mesh_fff(*object, -1, [this](const std::string& msg) {return wxGetApp().notification_manager()->push_plater_error_notification(msg); });
ModelVolume* new_volume = new_object->add_volume(mesh);
// BBS: ensure on bed but no need to ensure locate in the center around origin
new_object->ensure_on_bed();
new_object->center_around_origin();
new_object->translate_instances(-new_object->origin_translation);
new_object->origin_translation = Vec3d::Zero();
// BBS: notify it before move
notify_instance_updated(m_objects->size() - 1);
// remove selected objects
remove();
// Add new object(UNION) to the object_list
add_object_to_list(m_objects->size() - 1);
select_item(m_objects_model->GetItemById(m_objects->size() - 1));
update_selections_on_canvas();
}
wxDataViewItem ObjectList::add_layer_root_item(const wxDataViewItem obj_item)
{
const int obj_idx = m_objects_model->GetIdByItem(obj_item);
@ -2881,7 +2955,7 @@ DynamicPrintConfig ObjectList::get_default_layer_config(const int obj_idx)
int extruder = object(obj_idx)->config.has("extruder") ?
object(obj_idx)->config.opt_int("extruder") :
wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("extruder");
config.set_key_value("extruder", new ConfigOptionInt(extruder));
config.set_key_value("extruder", new ConfigOptionInt(0));
return config;
}
@ -2988,6 +3062,16 @@ bool ObjectList::can_merge_to_single_object() const
return (*m_objects)[obj_idx]->volumes.size() > 1;
}
bool ObjectList::can_mesh_boolean() const
{
int obj_idx = get_selected_obj_idx();
if (obj_idx < 0)
return false;
// selected object should be multi mesh
return (*m_objects)[obj_idx]->volumes.size() > 1 || ((*m_objects)[obj_idx]->volumes.size() == 1 && (*m_objects)[obj_idx]->volumes[0]->is_splittable());
}
bool ObjectList::has_selected_cut_object() const
{
wxDataViewItemArray sels;
@ -3150,7 +3234,7 @@ void ObjectList::part_selection_changed()
for (auto item : sels) {
int obj_idx = m_objects_model->GetObjectIdByItem(item);
const ModelObject *obj = object(obj_idx);
if (obj->is_cut()) {
if (obj && obj->is_cut()) {
if (cut_objects.find(obj->cut_id) == cut_objects.end())
cut_objects[obj->cut_id] = std::set<int>{obj_idx};
else
@ -3295,7 +3379,11 @@ void ObjectList::part_selection_changed()
Sidebar& panel = wxGetApp().sidebar();
panel.Freeze();
//wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
const ItemType type = m_objects_model->GetItemType(item);
if (!(type & itLayer)) {
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
}
// BBS
//wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
@ -3523,6 +3611,7 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
}
}
void ObjectList::add_objects_to_list(std::vector<size_t> obj_idxs, bool call_selection_changed, bool notify_partplate, bool do_info_update)
{
#ifdef __WXOSX__
@ -3536,7 +3625,6 @@ void ObjectList::add_objects_to_list(std::vector<size_t> obj_idxs, bool call_sel
#endif
}
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, bool notify_partplate, bool do_info_update)
{
auto model_object = (*m_objects)[obj_idx];
@ -3778,10 +3866,16 @@ void ObjectList::update_lock_icons_for_model()
void ObjectList::delete_all_objects_from_list()
{
#ifdef __WXOSX__
AssociateModel(nullptr);
#endif
m_prevent_list_events = true;
reload_all_plates();
m_prevent_list_events = false;
part_selection_changed();
#ifdef __WXOSX__
AssociateModel(m_objects_model);
#endif
}
void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num)
@ -4438,12 +4532,12 @@ void ObjectList::update_selections()
void ObjectList::update_selections_on_canvas()
{
Selection& selection = wxGetApp().plater()->get_view3D_canvas3D()->get_selection();
Selection& selection = wxGetApp().plater()->get_current_canvas3D()->get_selection();
const int sel_cnt = GetSelectedItemsCount();
if (sel_cnt == 0) {
selection.remove_all();
wxGetApp().plater()->get_view3D_canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
return;
}
@ -4547,7 +4641,7 @@ void ObjectList::update_selections_on_canvas()
selection.add_volumes(mode, volume_idxs, single_selection);
}
wxGetApp().plater()->get_view3D_canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->canvas3D()->render();
}
@ -4922,7 +5016,8 @@ void ObjectList::change_part_type()
}
const wxString names[] = { _L("Part"), _L("Negative Part"), _L("Modifier"), _L("Support Blocker"), _L("Support Enforcer") };
auto new_type = ModelVolumeType(wxGetApp().GetSingleChoiceIndex(_L("Type:"), _L("Choose part type"), wxArrayString(5, names), int(type)));
SingleChoiceDialog dlg(_L("Type:"), _L("Choose part type"), wxArrayString(5, names), int(type));
auto new_type = ModelVolumeType(dlg.GetSingleChoiceIndex());
if (new_type == type || new_type == ModelVolumeType::INVALID)
return;
@ -5516,6 +5611,9 @@ void ObjectList::set_extruder_for_selected_items(const int extruder)
}
}
if (type & itLayerRoot)
continue;
ModelConfig& config = get_item_config(item);
if (config.has("extruder"))
config.set("extruder", extruder);
@ -5592,10 +5690,10 @@ void ObjectList::reload_all_plates(bool notify_partplate)
m_prevent_canvas_selection_update = false;
// update printable states on canvas
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
// update scene
wxGetApp().plater()->update();
// update printable states on canvas
wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
}
void ObjectList::on_plate_selected(int plate_index)

View file

@ -300,6 +300,7 @@ public:
void merge_volumes(); // BBS: merge parts to single part
void layers_editing();
void boolean(); // BBS: Boolean Operation of parts
wxDataViewItem add_layer_root_item(const wxDataViewItem obj_item);
wxDataViewItem add_settings_item(wxDataViewItem parent_item, const DynamicPrintConfig* config);
@ -310,6 +311,7 @@ public:
bool can_split_instances();
bool can_merge_to_multipart_object() const;
bool can_merge_to_single_object() const;
bool can_mesh_boolean() const;
bool has_selected_cut_object() const;
void invalidate_cut_info_for_selection();
@ -477,6 +479,7 @@ private:
void apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object, bool need_update_assemble_matrix = true);
std::vector<int> m_columns_width;
wxSize m_last_size;
};

View file

@ -356,6 +356,10 @@ void ObjectSettings::update_config_values(ModelConfig* config)
//BBS: change local config to DynamicPrintConfig
ConfigManipulation config_manipulation(load_config, toggle_field, nullptr, nullptr, &(config->get()));
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
if (!is_object_settings)
{

View file

@ -1799,15 +1799,6 @@ wxString ObjectGridTable::convert_filament_string(int index, wxString& filament_
return result_str;
}
static wxString brim_choices[] =
{
L("Auto"),
L("Manual"),
L("No-brim"),
//L("Inner brim only"),
//L("Outer and inner brim")
};
void ObjectGridTable::init_cols(ObjectGrid *object_grid)
{
const float font_size = 1.5f * wxGetApp().em_unit();
@ -1839,7 +1830,7 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
col = new ObjectGridCol(coEnum, "extruder", ObjectGridTable::category_all, false, false, true, true, wxALIGN_CENTRE);
col->size = 128;
//the spec now guarantees vectors store their elements contiguously
col->choices = &m_panel->m_filaments_name[0];
col->choices.assign(m_panel->m_filaments_name.begin(), m_panel->m_filaments_name.end());
col->choice_count = m_panel->m_filaments_count;
m_col_data.push_back(col);
@ -1886,8 +1877,12 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
//Bed Adhesion
col = new ObjectGridCol(coEnum, "brim_type", L("Support"), true, false, true, true, wxALIGN_LEFT);
col->size = object_grid->GetTextExtent(L("Auto Brim")).x + 8; //add 8 for border
col->choices = brim_choices;
col->choice_count = WXSIZEOF(brim_choices);
col->choices.Add(_L("Auto"));
col->choices.Add(_L("Outer brim only"));
col->choices.Add(_L("Inner brim only"));
col->choices.Add(_L("Outer and inner brim"));
col->choices.Add(_L("No-brim"));
col->choice_count = col->choices.size();
m_col_data.push_back(col);
//reset icon for Bed Adhesion
@ -2240,11 +2235,11 @@ void ObjectGridTable::update_row_properties()
break;
case coEnum:
if (col == ObjectGridTable::col_filaments) {
GridCellFilamentsEditor *filament_editor = new GridCellFilamentsEditor(grid_col->choice_count, grid_col->choices, false, &m_panel->m_color_bitmaps);
GridCellFilamentsEditor *filament_editor = new GridCellFilamentsEditor(grid_col->choices, false, &m_panel->m_color_bitmaps);
grid_table->SetCellEditor(row, col, filament_editor);
grid_table->SetCellRenderer(row, col, new GridCellFilamentsRenderer());
} else {
GridCellChoiceEditor *combo_editor = new GridCellChoiceEditor(grid_col->choice_count, grid_col->choices);
GridCellChoiceEditor *combo_editor = new GridCellChoiceEditor(grid_col->choices);
grid_table->SetCellEditor(row, col, combo_editor);
grid_table->SetCellRenderer(row, col, new wxGridCellChoiceRenderer());
//new wxGridCellChoiceEditor(grid_col->choice_count, grid_col->choices));
@ -2704,7 +2699,7 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
SetSize(wxSize(-1, FromDIP(450)));
SetMinSize(wxSize(-1, FromDIP(450)));
SetMaxSize(wxSize(-1, FromDIP(450)));
//SetMaxSize(wxSize(-1, FromDIP(450)));
//m_search_line = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
@ -2768,13 +2763,13 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
//m_page_sizer->Add(m_page_top_sizer, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_page_sizer->Add(m_object_settings->get_sizer(), 1, wxEXPAND | wxALL, 2 );
auto m_line_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(1,-1), wxTAB_TRAVERSAL);
auto m_line_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(2, -1), wxTAB_TRAVERSAL);
m_line_left->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_top_sizer->Add(m_object_grid, 1, wxEXPAND,0);
m_top_sizer->Add(m_line_left, 0, wxEXPAND, 0);
m_top_sizer->Add(m_side_window,0,0,0);
m_top_sizer->Add(m_side_window, 0, wxEXPAND, 0);
//wxBoxSizer * page_sizer = new wxBoxSizer(wxHORIZONTAL);
@ -2966,7 +2961,7 @@ void ObjectTablePanel::load_data()
case coEnum:
if (col == ObjectGridTable::col_filaments) {
if (grid_row->model_volume_type != ModelVolumeType::NEGATIVE_VOLUME) {
GridCellFilamentsEditor* filament_editor = new GridCellFilamentsEditor(grid_col->choice_count, grid_col->choices, false, &m_color_bitmaps);
GridCellFilamentsEditor* filament_editor = new GridCellFilamentsEditor(grid_col->choices, false, &m_color_bitmaps);
m_object_grid->SetCellEditor(row, col, filament_editor);
m_object_grid->SetCellRenderer(row, col, new GridCellFilamentsRenderer());
}
@ -2979,7 +2974,7 @@ void ObjectTablePanel::load_data()
}
}
else {
GridCellChoiceEditor* combo_editor = new GridCellChoiceEditor(grid_col->choice_count, grid_col->choices);
GridCellChoiceEditor* combo_editor = new GridCellChoiceEditor(grid_col->choices);
m_object_grid->SetCellEditor(row, col, combo_editor);
m_object_grid->SetCellRenderer(row, col, new wxGridCellChoiceRenderer());
}
@ -3260,6 +3255,10 @@ void ObjectTablePanel::resetAllValuesInSideWindow(int row, bool is_object, Model
m_object_settings->resetAllValues(row, is_object, object, config, category);
}
void ObjectTablePanel::msw_rescale() {
m_object_grid->HideRowLabels();
}
// ----------------------------------------------------------------------------
// ObjectTableDialog
// ----------------------------------------------------------------------------
@ -3299,7 +3298,7 @@ ObjectTableDialog::ObjectTableDialog(wxWindow* parent, Plater* platerObj, Model
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
//top line
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 2), wxTAB_TRAVERSAL);
m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
@ -3370,6 +3369,8 @@ void ObjectTableDialog::on_dpi_changed(const wxRect& suggested_rect)
const wxSize& size = wxSize(40 * em, 30 * em);
SetMinSize(size);
m_obj_panel->msw_rescale();
Fit();
Refresh();
@ -3423,9 +3424,9 @@ void ObjectTableDialog::OnSize(wxSizeEvent& event)
SetMinSize(wxSize(GetSize().x, -1));
SetSize(wxSize(GetSize().x, -1));
m_obj_panel->SetSize(wxSize(-1, GetSize().y));
m_obj_panel->SetMinSize(wxSize(-1, GetSize().y));
m_obj_panel->SetMaxSize(wxSize(-1, GetSize().y));
//m_obj_panel->SetSize(wxSize(-1, GetSize().y));
//m_obj_panel->SetMinSize(wxSize(-1, GetSize().y));
//m_obj_panel->SetMaxSize(wxSize(-1, GetSize().y));
event.Skip();
}

View file

@ -416,7 +416,7 @@ public:
bool b_icon;
bool b_editable;
bool b_from_config;
wxString *choices;
wxArrayString choices;
int choice_count;
int horizontal_align;
@ -427,13 +427,11 @@ public:
size = 32;
else
size = -1;
choices = nullptr;
choice_count = 0;
}
~ObjectGridCol()
{
choices = nullptr;
}
};
ObjectGridTable(ObjectTablePanel* panel): m_panel(panel) { }
@ -573,6 +571,7 @@ public:
void sort_by_default() { m_object_grid_table->sort_by_default(); }
wxSize get_init_size();
void resetAllValuesInSideWindow(int row, bool is_object, ModelObject* object, ModelConfig* config, const std::string& category);
void msw_rescale();
//set ObjectGridTable as friend
friend class ObjectGridTable;

View file

@ -290,10 +290,20 @@ bool ObjectTableSettings::update_settings_list(bool is_object, bool is_multiple_
if (field)
field->toggle(toggle);
};
ConfigManipulation config_manipulation(nullptr, toggle_field, nullptr, nullptr, &m_current_config);
auto toggle_line = [this, optgroup](const t_config_option_key & opt_key, bool toggle)
{
Line* line = optgroup->get_line(opt_key);
if (line) line->toggle_visible = toggle;
};
ConfigManipulation config_manipulation(nullptr, toggle_field, toggle_line, nullptr, &m_current_config);
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
printer_technology == ptFFF ? config_manipulation.toggle_print_fff_options(&m_current_config) :
config_manipulation.toggle_print_sla_options(&m_current_config) ;
optgroup->update_visibility(wxGetApp().get_mode());
}
//if (!categories.empty()) {
@ -383,15 +393,30 @@ void ObjectTableSettings::update_config_values(bool is_object, ModelObject* obje
if (field)
field->toggle(toggle);
};
auto toggle_line = [this](const t_config_option_key &opt_key, bool toggle) {
for (auto og : m_og_settings) {
Line *line = og->get_line(opt_key);
if (line) { line->toggle_visible = toggle; break; }
}
};
ConfigManipulation config_manipulation(nullptr, toggle_field, nullptr, nullptr, &m_current_config);
ConfigManipulation config_manipulation(nullptr, toggle_field, toggle_line, nullptr, &m_current_config);
// BBS: whether the preset is Bambu Lab printer
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
bool is_BBL_printer = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
config_manipulation.set_is_BBL_Printer(is_BBL_printer);
printer_technology == ptFFF ? config_manipulation.update_print_fff_config(&main_config) :
config_manipulation.update_print_sla_config(&main_config) ;
printer_technology == ptFFF ? config_manipulation.toggle_print_fff_options(&main_config) :
config_manipulation.toggle_print_sla_options(&main_config) ;
for (auto og : m_og_settings) {
og->update_visibility(wxGetApp().get_mode());
}
m_parent->Layout();
m_parent->Fit();
m_parent->GetParent()->Layout();
t_config_option_keys diff_keys;
for (const t_config_option_key &opt_key : main_config.keys()) {
const ConfigOption *this_opt = main_config.option(opt_key);

View file

@ -477,7 +477,7 @@ void Preview::update_layers_slider_mode()
// BBS
if (wxGetApp().filaments_cnt() > 1) {
//const ModelObjectPtrs& objects = wxGetApp().plater()->model().objects;
auto plate_extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders();
auto plate_extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders_without_support();
for (auto extruder : plate_extruders) {
if (extruder != plate_extruders[0])
can_change_color = false;
@ -486,23 +486,23 @@ void Preview::update_layers_slider_mode()
if (!plate_extruders.empty()) {
//const int extruder = objects[0]->config.has("extruder") ? objects[0]->config.option("extruder")->getInt() : 0;
only_extruder = plate_extruders[0];
// auto is_one_extruder_printed_model = [objects, extruder]() {
// for (ModelObject *object : objects) {
// if (object->config.has("extruder") && object->config.option("extruder")->getInt() != extruder) /*return false*/;
// auto is_one_extruder_printed_model = [objects, extruder]() {
// for (ModelObject *object : objects) {
// if (object->config.has("extruder") && object->config.option("extruder")->getInt() != extruder) /*return false*/;
// for (ModelVolume *volume : object->volumes)
// if ((volume->config.has("extruder") && volume->config.option("extruder")->getInt() != extruder) || !volume->mmu_segmentation_facets.empty()) return false;
// for (ModelVolume *volume : object->volumes)
// if ((volume->config.has("extruder") && volume->config.option("extruder")->getInt() != extruder) || !volume->mmu_segmentation_facets.empty()) return false;
// for (const auto &range : object->layer_config_ranges)
// if (range.second.has("extruder") && range.second.option("extruder")->getInt() != extruder) return false;
// }
// return true;
// };
// for (const auto &range : object->layer_config_ranges)
// if (range.second.has("extruder") && range.second.option("extruder")->getInt() != extruder) return false;
// }
// return true;
// };
// if (is_one_extruder_printed_model())
// only_extruder = extruder;
// else
// one_extruder_printed_model = false;
// if (is_one_extruder_printed_model())
// only_extruder = extruder;
// else
// one_extruder_printed_model = false;
}
}

View file

@ -52,6 +52,15 @@ static std::array<float, 4> decode_color_to_float_array(const std::string color)
ret[j] = float(digit1 * 16 + digit2) / 255.0f;
}
}
else if (color.size() == 9 && color.front() == '#') {
for (size_t j = 0; j < 4; ++j) {
int digit1 = hex_to_int(*c++);
int digit2 = hex_to_int(*c++);
if (digit1 == -1 || digit2 == -1) break;
ret[j] = float(digit1 * 16 + digit2) / 255.0f;
}
}
return ret;
}
@ -189,9 +198,12 @@ public:
this->Bind(wxEVT_SYS_COLOUR_CHANGED, [this](wxSysColourChangedEvent& event)
{
update_dark_config();
on_sys_color_changed();
event.Skip();
#ifndef __WINDOWS__
update_dark_config();
on_sys_color_changed();
event.Skip();
#endif // __WINDOWS__
});
if (std::is_same<wxDialog, P>::value) {

View file

@ -132,7 +132,7 @@ void GLGizmoMeshBoolean::on_render()
}
float src_color[3] = { 1.0f, 1.0f, 1.0f };
float tool_color[3] = { 0.0f, 150.0f / 255.0f, 136.0f / 255.0f };
float tool_color[3] = { 0.0f, 174.0f / 255.0f, 66.0f / 255.0f };
m_parent.get_selection().render_bounding_box(src_bb, src_color, m_parent.get_scale());
m_parent.get_selection().render_bounding_box(tool_bb, tool_color, m_parent.get_scale());
}
@ -179,17 +179,12 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
GizmoImguiBegin("MeshBoolean", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
const int max_tab_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(_u8L("Union").c_str()).x,
std::max(ImGui::CalcTextSize(_u8L("Difference").c_str()).x, ImGui::CalcTextSize(_u8L("Intersection").c_str()).x));
const int max_cap_length = ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ItemSpacing.x +
std::max({ImGui::CalcTextSize(_u8L("Source Volume").c_str()).x,
ImGui::CalcTextSize(_u8L("Tool Volume").c_str()).x,
ImGui::CalcTextSize(_u8L("Subtract from").c_str()).x,
ImGui::CalcTextSize(_u8L("Subtract with").c_str()).x});
const int max_tab_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(_L("Union").c_str()).x,
std::max(ImGui::CalcTextSize(_L("Difference").c_str()).x, ImGui::CalcTextSize(_L("Intersection").c_str()).x));
const int max_cap_length = ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ItemSpacing.x + std::max(ImGui::CalcTextSize(_L("Source Volume").c_str()).x, ImGui::CalcTextSize(_L("Tool Volume").c_str()).x);
const int select_btn_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(("1 " + _L("selected")).c_str()).x, ImGui::CalcTextSize(_L("Select").c_str()).x);
const int select_btn_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(("1 " + _u8L("selected")).c_str()).x, ImGui::CalcTextSize(_u8L("Select").c_str()).x);
auto selectable = [this](const std::string& label, bool selected, const ImVec2& size_arg) {
auto selectable = [this](const wxString& label, bool selected, const ImVec2& size_arg) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });
ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -200,13 +195,13 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
if (selected || hovered) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
}
else {
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 150.0f / 255.0f, 136.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
}
bool res = ImGui::Button(label.c_str(), size_arg);
@ -245,15 +240,15 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
};
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
if (selectable(_u8L("Union"), m_operation_mode == MeshBooleanOperation::Union, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_L("Union").c_str(), m_operation_mode == MeshBooleanOperation::Union, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Union;
}
ImGui::SameLine(0, 0);
if (selectable(_u8L("Difference"), m_operation_mode == MeshBooleanOperation::Difference, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_L("Difference").c_str(), m_operation_mode == MeshBooleanOperation::Difference, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Difference;
}
ImGui::SameLine(0, 0);
if (selectable(_u8L("Intersection"), m_operation_mode == MeshBooleanOperation::Intersection, ImVec2(max_tab_length, 0.0f))) {
if (selectable(_L("Intersection").c_str(), m_operation_mode == MeshBooleanOperation::Intersection, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Intersection;
}
ImGui::PopStyleVar();
@ -262,10 +257,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
std::string cap_str1 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 1") : _u8L("Subtract from");
m_imgui->text(cap_str1);
ImGui::SameLine(max_cap_length);
std::string select_src_str = m_src.mv ? "1 " + _u8L("selected") : _u8L("Select");
select_src_str += "##select_source_volume";
wxString select_src_str = m_src.mv ? "1 " + _L("selected") : _L("Select");
select_src_str << "##select_source_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_src_str, m_selecting_state == MeshBooleanSelectingState::SelectSource, ImVec2(select_btn_length, 0)))
if (selectable(select_src_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectSource, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectSource;
ImGui::PopItemWidth();
if (m_src.mv) {
@ -290,10 +285,10 @@ void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_l
std::string cap_str2 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 2") : _u8L("Subtract with");
m_imgui->text(cap_str2);
ImGui::SameLine(max_cap_length);
std::string select_tool_str = m_tool.mv ? "1 " + _u8L("selected") : _u8L("Select");
select_tool_str += "##select_tool_volume";
wxString select_tool_str = m_tool.mv ? "1 " + _L("selected") : _L("Select");
select_tool_str << "##select_tool_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_tool_str, m_selecting_state == MeshBooleanSelectingState::SelectTool, ImVec2(select_btn_length, 0)))
if (selectable(select_tool_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectTool, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectTool;
ImGui::PopItemWidth();
if (m_tool.mv) {

View file

@ -1,5 +1,6 @@
#include "HMS.hpp"
#include "HMSPanel.hpp"
#include <slic3r/GUI/Widgets/SideTools.hpp>
#include <slic3r/GUI/Widgets/Label.hpp>
#include <slic3r/GUI/I18N.hpp>
#include "GUI.hpp"
@ -231,4 +232,4 @@ bool HMSPanel::Show(bool show)
return wxPanel::Show(show);
}
}}
}}

View file

@ -243,8 +243,11 @@ void IMSlider::SetTicksValues(const Info &custom_gcode_per_print_z)
;// post_ticks_changed_event();
if (m_ticks.has_tick_with_code(ToolChange) && !m_can_change_color) {
m_ticks.erase_all_ticks_with_code(ToolChange);
post_ticks_changed_event();
if (!wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->using_exported_file())
{
m_ticks.erase_all_ticks_with_code(ToolChange);
post_ticks_changed_event();
}
}
if (last_spiral_vase_status != m_is_spiral_vase) {
@ -550,7 +553,7 @@ void IMSlider::draw_colored_band(const ImRect& groove, const ImRect& slideable_r
auto draw_band = [this](const ImU32& clr, const ImRect& band_rc)
{
if (clr == m_is_dark ? BACKGROUND_COLOR_DARK : BACKGROUND_COLOR_LIGHT) {
if (clr == (m_is_dark ? BACKGROUND_COLOR_DARK : BACKGROUND_COLOR_LIGHT)) {
ImRect rc = band_rc;
rc.Min += ImVec2(1, 1) * m_scale;
rc.Max -= ImVec2(1, 1) * m_scale;
@ -569,7 +572,7 @@ void IMSlider::draw_colored_band(const ImRect& groove, const ImRect& slideable_r
}
};
auto draw_main_band = [&main_band, this](const ImU32& clr) {
if (clr == m_is_dark ? BACKGROUND_COLOR_DARK : BACKGROUND_COLOR_LIGHT) {
if (clr == (m_is_dark ? BACKGROUND_COLOR_DARK : BACKGROUND_COLOR_LIGHT)) {
ImRect rc = main_band;
rc.Min += ImVec2(1, 1) * m_scale;
rc.Max -= ImVec2(1, 1) * m_scale;
@ -1205,9 +1208,9 @@ void IMSlider::render_menu() {
m_ticks.ticks.end();
std::string custom_code;
if (tick_it != m_ticks.ticks.end()) {
render_edit_menu(*tick_it);
if (tick_it->type == CustomGCode::Custom)
custom_code = tick_it->extra;
render_edit_menu(*tick_it);
}
else {
render_add_menu();
@ -1262,6 +1265,8 @@ void IMSlider::render_add_menu()
for (int i = 0; i < extruder_num; i++) {
std::array<float, 4> rgba = decode_color_to_float_array(m_extruder_colors[i]);
ImU32 icon_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
if (rgba[3] == 0)
icon_clr = 0;
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", ImVec2(14, 14) * m_scale, icon_clr, false, true, &hovered)) add_code_as_tick(ToolChange, i + 1);
if (hovered) { show_tooltip(_u8L("Change filament at the beginning of this layer.")); }
}

View file

@ -88,6 +88,9 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::ExpandBtn , "expand_btn" },
{ImGui::CollapseBtn , "collapse_btn" },
{ImGui::RevertBtn , "revert_btn" },
{ImGui::CloseBlockNotifButton , "block_notification_close" },
{ImGui::CloseBlockNotifHoverButton , "block_notification_close_hover" },
};
static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" },
@ -113,6 +116,7 @@ static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::CloseNotifHoverDarkButton , "notification_close_hover_dark" },
{ImGui::DocumentationDarkButton , "notification_documentation_dark" },
{ImGui::DocumentationHoverDarkButton, "notification_documentation_hover_dark"},
{ImGui::BlockNotifErrorIcon, "block_notification_error" },
};
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
@ -1478,7 +1482,13 @@ bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_si
float icon_pos_y = selectable_pos_y + (label_size.y + style.ItemSpacing.y - icon_size.y) / 2;
float icon_pos_x = pos.x + window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f;
ImVec2 icon_pos = ImVec2(icon_pos_x, icon_pos_y);
ImGui::RenderFrame(icon_pos, icon_pos + icon_size, icon_color);
if (icon_color != 0)
ImGui::RenderFrame(icon_pos, icon_pos + icon_size, icon_color);
else {
static ImTextureID transparent;
IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/transparent.svg", icon_size.x, icon_size.y, transparent);
window->DrawList->AddImage(transparent, icon_pos, icon_pos + icon_size, { 0,0 }, { 1,1 }, ImGui::GetColorU32(ImVec4(1.f, 1.f, 1.f, 1.f)));
}
}
if (shortcut_w > 0.0f) {
@ -2067,6 +2077,7 @@ void ImGuiWrapper::init_font(bool compress)
ImVector<ImWchar> basic_ranges;
ImFontAtlas::GlyphRangesBuilder builder;
builder.AddRanges(m_glyph_ranges);
builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesDefault());
#ifdef __APPLE__
if (m_font_cjk)
// Apple keyboard shortcuts are only contained in the CJK fonts.

View file

@ -5,16 +5,10 @@
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "MsgDialog.hpp"
#include <wx/dcgraph.h>
#ifdef __WXMSW__
#include <shellapi.h>
#endif
#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp"
#endif
wxDEFINE_EVENT(EVT_ITEM_ACTION, wxCommandEvent);
BEGIN_EVENT_TABLE(Slic3r::GUI::ImageGrid, wxPanel)
@ -34,14 +28,21 @@ END_EVENT_TABLE()
namespace Slic3r {
namespace GUI {
static constexpr int SHADOW_WIDTH = 3;
ImageGrid::ImageGrid(wxWindow * parent)
: wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
, m_buttonBackgroundColor(StateColor(
std::make_pair(*wxWHITE, (int) StateColor::Pressed),
std::make_pair(*wxRED, (int) StateColor::Normal)))
, m_buttonTextColor(StateColor(
std::make_pair(0x3B4446, (int) StateColor::Pressed),
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
std::make_pair(*wxWHITE, (int) StateColor::Normal)))
, m_checked_icon(this, "check_on", 16)
, m_unchecked_icon(this, "check_off", 16)
, m_model_time_icon(this, "model_time", 14)
, m_model_weight_icon(this, "model_weight", 14)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
SetBackgroundColour(0xEEEEEE);
@ -82,11 +83,11 @@ void ImageGrid::SetStatus(ScalableBitmap const & icon, wxString const &msg)
Refresh();
}
void Slic3r::GUI::ImageGrid::SetFileType(int type)
void Slic3r::GUI::ImageGrid::SetFileType(int type, std::string const &storage)
{
if (!m_file_sys)
return;
m_file_sys->SetFileType((PrinterFileSystem::FileType) type);
m_file_sys->SetFileType((PrinterFileSystem::FileType) type, storage);
}
void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
@ -96,7 +97,7 @@ void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
wxSize size = GetClientSize();
int index = (m_row_offset + 1 < m_row_count || m_row_count == 0)
? m_row_offset / 4 * m_col_count
: ((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size.y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
: ((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size.y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
auto & file = m_file_sys->GetFile(index);
m_file_sys->SetGroupMode((PrinterFileSystem::GroupMode) mode);
index = m_file_sys->GetIndexAtTime(file.time);
@ -119,6 +120,8 @@ void Slic3r::GUI::ImageGrid::DoActionOnSelection(int action) { DoAction(-1, acti
void Slic3r::GUI::ImageGrid::Rescale()
{
m_title_mask = wxBitmap();
m_border_mask = wxBitmap();
UpdateFileSystem();
auto em = em_unit(this);
wxSize size1{384 * em / 10, 4 * em};
@ -149,81 +152,33 @@ void Slic3r::GUI::ImageGrid::Select(size_t index)
void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
{
if (action == 0) {
if (m_file_sys->GetSelectCount() > 1) {
MessageDialog dlg(this,
wxString::Format(_L("You are going to delete %u files. Are you sure to continue?"), m_file_sys->GetSelectCount()),
_L("Delete files"), wxYES_NO | wxICON_WARNING);
if (dlg.ShowModal() != wxID_YES)
return;
}
m_file_sys->DeleteFiles(index);
} else if (action == 1) {
if (index != -1) {
auto &file = m_file_sys->GetFile(index);
if (file.IsDownload() && file.progress >= -1) {
if (file.progress >= 100) {
if (!m_file_sys->DownloadCheckFile(index)) {
MessageDialog(this,
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
_L("Error"), wxOK).ShowModal();
Refresh();
return;
}
#ifdef __WXMSW__
auto wfile = boost::filesystem::path(file.path).wstring();
SHELLEXECUTEINFO info{sizeof(info), 0, NULL, L"open", wfile.c_str(), L"", SW_HIDE};
::ShellExecuteEx(&info);
#else
wxShell("open " + file.path);
#endif
} else {
m_file_sys->DownloadCancel(index);
}
return;
}
}
m_file_sys->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
} else if (action == 2) {
if (index != -1) {
auto &file = m_file_sys->GetFile(index);
if (file.IsDownload() && file.progress >= -1) {
if (file.progress >= 100) {
if (!m_file_sys->DownloadCheckFile(index)) {
MessageDialog(this,
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
_L("Error"), wxOK).ShowModal();
Refresh();
return;
}
#ifdef __WIN32__
wxExecute(L"explorer.exe /select," + from_u8(file.path));
#elif __APPLE__
openFolderForFile(from_u8(file.path));
#else
#endif
}
return;
}
}
m_file_sys->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
}
wxCommandEvent event(EVT_ITEM_ACTION);
event.SetEventObject(this);
event.SetInt(action);
event.SetExtraLong(long(index));
ProcessEventLocally(event);
}
void Slic3r::GUI::ImageGrid::UpdateFileSystem()
{
if (!m_file_sys) return;
wxSize mask_size{0, 60};
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
m_image_size.Set(384, 216);
m_cell_size.Set(396, 228);
if (m_file_sys->GetFileType() < PrinterFileSystem::F_MODEL) {
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
m_cell_size.Set(396, 228);
m_border_size.Set(384, 216);
}
else {
m_cell_size.Set(496, 286);
m_border_size.Set(480, 270);
}
} else {
m_cell_size.Set(292, 288);
m_border_size.Set(266, 264);
}
else {
m_image_size.Set(480, 270);
m_cell_size.Set(496, 296);
}
m_image_size = m_image_size * em_unit(this) / 10;
m_cell_size = m_cell_size * em_unit(this) / 10;
m_border_size = m_border_size * em_unit(this) / 10;
m_content_rect = wxRect(SHADOW_WIDTH, SHADOW_WIDTH, m_border_size.GetWidth(), m_border_size.GetHeight());
m_border_size += wxSize(SHADOW_WIDTH, SHADOW_WIDTH) * 2;
UpdateLayout();
}
@ -231,16 +186,16 @@ void ImageGrid::UpdateLayout()
{
if (!m_file_sys) return;
wxSize size = GetClientSize();
wxSize mask_size{0, 60 * em_unit(this) / 10};
wxSize title_mask_size{0, 60 * em_unit(this) / 10};
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
mask_size.y = 20 * em_unit(this) / 10;
size.y -= mask_size.y;
title_mask_size.y = 20 * em_unit(this) / 10;
size.y -= title_mask_size.y;
}
int cell_width = m_cell_size.GetWidth();
int cell_height = m_cell_size.GetHeight();
int ncol = (size.GetWidth() - cell_width + m_image_size.GetWidth()) / cell_width;
int ncol = (size.GetWidth() - cell_width + m_border_size.GetWidth()) / cell_width;
if (ncol <= 0) ncol = 1;
int total_height = (m_file_sys->GetCount() + ncol - 1) / ncol * cell_height + cell_height - m_image_size.GetHeight();
int total_height = (m_file_sys->GetCount() + ncol - 1) / ncol * cell_height + cell_height - m_border_size.GetHeight();
int nrow = (total_height - size.GetHeight() + cell_height / 4 - 1) / (cell_height / 4);
m_row_offset = m_row_offset * m_col_count / ncol;
m_col_count = ncol;
@ -250,13 +205,15 @@ void ImageGrid::UpdateLayout()
m_scroll_offset = 0;
// create mask
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
mask_size.x = (m_col_count - 1) * m_cell_size.GetWidth() + m_image_size.GetWidth();
title_mask_size.x = (m_col_count - 1) * m_cell_size.GetWidth() + m_border_size.GetWidth();
}
else {
mask_size.x = m_image_size.x;
title_mask_size.x = m_border_size.x;
}
if (!m_mask.IsOk() || m_mask.GetSize() != mask_size)
m_mask = createAlphaBitmap(mask_size, 0x6f6f6f, 255, 0);
if (!m_title_mask.IsOk() || m_title_mask.GetSize() != title_mask_size)
m_title_mask = createAlphaBitmap(title_mask_size, 0x6f6f6f, 255, 0);
if (!m_border_mask.IsOk() || m_border_mask.GetSize() != m_border_size)
m_border_mask = createShadowBorder(m_border_size, StateColor::darkModeColorFor(0xEEEEEE), em_unit(this), 3);
UpdateFocusRange();
Refresh();
}
@ -280,7 +237,7 @@ std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
return {HIT_NONE, -1};
wxSize size = GetClientSize();
if (m_file_sys->GetCount() == 0) {
if (wxRect({0, 0}, m_image_size).CenterIn(wxRect({0, 0}, size)).Contains(pt))
if (wxRect({0, 0}, m_border_size).CenterIn(wxRect({0, 0}, size)).Contains(pt))
return {HIT_STATUS, 0};
return {HIT_NONE, -1};
}
@ -292,17 +249,21 @@ std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
++n;
off.x -= m_cell_size.GetWidth();
}
if (off.x < 0 || off.x >= m_image_size.GetWidth()) { return {HIT_NONE, -1}; }
index += n;
while (off.y > m_cell_size.GetHeight()) {
index += m_col_count;
off.y -= m_cell_size.GetHeight();
}
if (index >= m_file_sys->GetCount()) { return {HIT_NONE, -1}; }
if (!m_content_rect.Contains(off)) { return {HIT_NONE, -1}; }
if (!m_selecting) {
wxRect hover_rect{0, m_image_size.y - 40, m_image_size.GetWidth(), 40};
wxRect hover_rect{0, m_content_rect.GetHeight() - m_buttons_background.GetHeight(), m_content_rect.GetWidth(), m_buttons_background.GetHeight()};
auto & file = m_file_sys->GetFile(index);
int btn = file.IsDownload() && file.progress >= 0 ? 3 : 2;
int btn = file.IsDownload() && file.DownloadProgress() >= 0 ? 3 : 2;
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
btn = 3;
hover_rect.y -= m_content_rect.GetHeight() * 64 / 264;
}
if (hover_rect.Contains(off.x, off.y)) { return {HIT_ACTION, index * 4 + off.x * btn / hover_rect.GetWidth()}; } // Two buttons
}
return {HIT_ITEM, index};
@ -317,7 +278,7 @@ void ImageGrid::mouseMoved(wxMouseEvent& event)
m_hit_type = hit.first;
m_hit_item = hit.second;
if (hit.first == HIT_ITEM)
SetToolTip(m_file_sys->GetFile(hit.second).name);
SetToolTip(from_u8(m_file_sys->GetFile(hit.second).Title()));
else
SetToolTip({});
Refresh();
@ -402,7 +363,8 @@ void ImageGrid::mouseWheelMoved(wxMouseEvent &event)
void Slic3r::GUI::ImageGrid::changedEvent(wxCommandEvent& evt)
{
evt.Skip();
BOOST_LOG_TRIVIAL(info) << "ImageGrid::changedEvent: " << evt.GetEventType() << " index: " << evt.GetInt() << " name: " << evt.GetString() << " extra: " << evt.GetExtraLong();
BOOST_LOG_TRIVIAL(debug) << "ImageGrid::changedEvent: " << evt.GetEventType() << " index: " << evt.GetInt()
<< " name: " << evt.GetString().ToUTF8().data() << " extra: " << evt.GetExtraLong();
if (evt.GetEventType() == EVT_FILE_CHANGED) {
if (evt.GetInt() == -1)
m_file_sys->DownloadCheckFiles(wxGetApp().app_config->get("download_path"));
@ -410,6 +372,8 @@ void Slic3r::GUI::ImageGrid::changedEvent(wxCommandEvent& evt)
}
else if (evt.GetEventType() == EVT_MODE_CHANGED)
UpdateFileSystem();
//else if (evt.GetEventType() == EVT_THUMBNAIL)
// RefreshRect(itemRect(evt.GetInt()), false);
else
Refresh();
}
@ -425,16 +389,16 @@ size_t Slic3r::GUI::ImageGrid::firstItem(wxSize const &size, wxPoint &off)
{
int size_y = size.y;
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
size_y -= m_mask.GetHeight();
int offx = (size.x - (m_col_count - 1) * m_cell_size.GetWidth() - m_image_size.GetWidth()) / 2;
size_y -= m_title_mask.GetHeight();
int offx = (size.x - (m_col_count - 1) * m_cell_size.GetWidth() - m_border_size.GetWidth()) / 2;
int offy = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
m_cell_size.GetHeight() - m_image_size.GetHeight() - m_row_offset * m_cell_size.GetHeight() / 4 + m_row_offset / 4 * m_cell_size.GetHeight() :
size_y - (size_y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight() * m_cell_size.GetHeight();
m_cell_size.GetHeight() - m_border_size.GetHeight() - m_row_offset * m_cell_size.GetHeight() / 4 + m_row_offset / 4 * m_cell_size.GetHeight() :
size_y - (size_y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight() * m_cell_size.GetHeight();
int index = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
m_row_offset / 4 * m_col_count :
((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size_y + m_image_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size_y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
offy += m_mask.GetHeight();
offy += m_title_mask.GetHeight();
off = wxPoint{offx, offy};
return index;
}
@ -454,6 +418,38 @@ wxBitmap Slic3r::GUI::ImageGrid::createAlphaBitmap(wxSize size, wxColour color,
return wxBitmap(std::move(image));
}
wxBitmap Slic3r::GUI::ImageGrid::createShadowBorder(wxSize size, wxColour color, int radius, int shadow)
{
wxImage image(size);
image.InitAlpha();
memset(image.GetAlpha(), 0, size.GetWidth() * size.GetHeight());
wxBitmap bmp(std::move(image));
wxMemoryDC memdc;
memdc.SelectObject(bmp);
#ifdef __WXMSW__
wxGCDC dc2(memdc);
#else
wxDC &dc2(memdc);
#endif
wxRect rc(0, 0, size.x, size.y);
dc2.SetBrush(*wxTRANSPARENT_BRUSH);
auto n = ((radius + shadow) * 1414 / 1000 - radius);
dc2.SetPen(wxPen(color, n | 1));
n = n / 2 - shadow + 1;
rc.Inflate(n, n);
dc2.DrawRoundedRectangle(rc, radius + shadow);
rc.Deflate(n, n);
rc.Deflate(shadow, shadow);
for (int i = 0; i < shadow; ++i) {
rc.Inflate(1, 1);
dc2.SetPen(wxColor(0, 0, 0, 100 - i * 30));
dc2.DrawRoundedRectangle(rc, radius + i);
}
memdc.SelectObject(wxNullBitmap);
return bmp;
}
wxBitmap Slic3r::GUI::ImageGrid::createCircleBitmap(wxSize size, int borderWidth, int percent, wxColour fillColor, wxColour borderColor)
{
wxImage image(size);
@ -525,27 +521,37 @@ void ImageGrid::render(wxDC& dc)
wxPoint pt{off.x, off.y};
end = (index + m_col_count) < m_file_sys->GetCount() ? index + m_col_count : m_file_sys->GetCount();
while (index < end) {
renderContent(dc, pt, index, hit_image == index);
pt += m_content_rect.GetTopLeft();
// Draw content
decltype(&ImageGrid::renderContent1) contentRender[] = {
&ImageGrid::renderContent1,
&ImageGrid::renderContent1,
&ImageGrid::renderContent2
};
(this->*contentRender[m_file_sys->GetFileType()])(dc, pt, index, hit_image == index);
pt -= m_content_rect.GetTopLeft();
// Draw colume spacing at right
dc.DrawRectangle({pt.x + m_image_size.GetWidth(), pt.y, m_cell_size.GetWidth() - m_image_size.GetWidth(), m_image_size.GetHeight()});
dc.DrawRectangle({pt.x + m_border_size.GetWidth(), pt.y, m_cell_size.GetWidth() - m_border_size.GetWidth(), m_border_size.GetHeight()});
// Draw overlay border mask
dc.DrawBitmap(m_border_mask, pt.x, pt.y);
++index;
pt.x += m_cell_size.GetWidth();
}
// Draw line fill items
if (end < index + m_col_count)
dc.DrawRectangle({pt.x, pt.y, size.x - pt.x - off.x, m_image_size.GetHeight()});
dc.DrawRectangle({pt.x, pt.y, size.x - pt.x - off.x, m_border_size.GetHeight()});
// Draw line spacing at bottom
dc.DrawRectangle({off.x, pt.y + m_image_size.GetHeight(), size.x - off.x * 2, m_cell_size.GetHeight() - m_image_size.GetHeight()});
dc.DrawRectangle({off.x, pt.y + m_border_size.GetHeight(), size.x - off.x * 2, m_cell_size.GetHeight() - m_border_size.GetHeight()});
off.y += m_cell_size.GetHeight();
}
// Draw floating date range for non-group list
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE && m_file_sys->GetCount() > 0) {
//dc.DrawBitmap(m_mask, {off.x, 0});
dc.DrawRectangle({off.x, 0}, m_mask.GetSize());
//dc.DrawBitmap(m_title_mask, {off.x, 0});
dc.DrawRectangle({off.x, 0}, m_title_mask.GetSize());
auto & file1 = m_file_sys->GetFile(start);
auto & file2 = m_file_sys->GetFile(end - 1);
auto date1 = wxDateTime((time_t) file1.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
auto date2 = wxDateTime((time_t) file2.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
auto date1 = wxDateTime((time_t) file1.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
auto date2 = wxDateTime((time_t) file2.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
dc.SetFont(Label::Head_16);
dc.SetTextForeground(StateColor::darkModeColorFor("#262E30"));
dc.DrawText(date1 + " - " + date2, wxPoint{off.x, 2});
@ -555,7 +561,7 @@ void ImageGrid::render(wxDC& dc)
dc.DrawRectangle({off.x, off.y, size.x - off.x * 2, size.y - off.y});
// Draw position bar
if (m_timer.IsRunning()) {
int total_height = (m_file_sys->GetCount() + m_col_count - 1) / m_col_count * m_cell_size.GetHeight() + m_cell_size.GetHeight() - m_image_size.GetHeight();
int total_height = (m_file_sys->GetCount() + m_col_count - 1) / m_col_count * m_cell_size.GetHeight() + m_cell_size.GetHeight() - m_border_size.GetHeight();
if (total_height > size.y) {
int offset = (m_row_offset + 1 < m_row_count || m_row_count == 0) ? m_row_offset * (m_cell_size.GetHeight() / 4) : total_height - size.y;
wxRect rect = {size.x - 16, offset * size.y / total_height, 8,
@ -566,25 +572,23 @@ void ImageGrid::render(wxDC& dc)
}
}
void Slic3r::GUI::ImageGrid::renderContent(wxDC &dc, wxPoint const &pt, int index, bool hit)
void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int index, bool hit)
{
bool selected = false;
auto &file = m_file_sys->GetFile(index, selected);
// Draw thumbnail
if (file.thumbnail.IsOk()) {
float hs = (float) m_image_size.GetWidth() / file.thumbnail.GetWidth();
float vs = (float) m_image_size.GetHeight() / file.thumbnail.GetHeight();
float hs = (float) m_content_rect.GetWidth() / file.thumbnail.GetWidth();
float vs = (float) m_content_rect.GetHeight() / file.thumbnail.GetHeight();
dc.SetUserScale(hs, vs);
dc.DrawBitmap(file.thumbnail, {(int) (pt.x / hs), (int) (pt.y / vs)});
dc.SetUserScale(1, 1);
if (m_file_sys->GetGroupMode() != PrinterFileSystem::G_NONE) {
dc.DrawBitmap(m_mask, pt);
}
if (m_file_sys->GetGroupMode() != PrinterFileSystem::G_NONE) { dc.DrawBitmap(m_title_mask, pt); }
}
bool show_download_state_always = true;
// Draw checked icon
if (m_selecting && !show_download_state_always)
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_content_rect.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
// can't handle alpha
// dc.GradientFillLinear({pt.x, pt.y, m_border_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
@ -594,25 +598,31 @@ void Slic3r::GUI::ImageGrid::renderContent(wxDC &dc, wxPoint const &pt, int inde
int states = 0;
// Draw download progress
if (file.IsDownload()) {
if (file.progress == -1) {
int progress = file.DownloadProgress();
if (progress == -1) {
secondAction = _L("Cancel");
nonHoverText = _L("Download waiting...");
} else if (file.progress < 0) {
} else if (progress < 0) {
secondAction = _L("Retry");
nonHoverText = _L("Download failed");
states = StateColor::Checked;
} else if (file.progress >= 100) {
} else if (progress >= 100) {
secondAction = _L("Play");
thirdAction = _L("Open Folder");
nonHoverText = _L("Download finished");
} else {
secondAction = _L("Cancel");
nonHoverText = wxString::Format(_L("Downloading %d%%..."), file.progress);
thirdAction = wxString::Format(L"%d%%...", file.progress);
nonHoverText = wxString::Format(_L("Downloading %d%%..."), progress);
thirdAction = wxString::Format(L"%d%%...", progress);
}
}
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
if (secondAction != _L("Play"))
thirdAction = secondAction;
secondAction = _L("Print");
}
// Draw buttons on hovered item
wxRect rect{pt.x, pt.y + m_image_size.GetHeight() - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
wxRect rect{pt.x, pt.y + m_content_rect.GetBottom() - m_buttons_background.GetHeight(), m_content_rect.GetWidth(), m_buttons_background.GetHeight()};
if (hit) {
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, thirdAction.IsEmpty() ? nullptr : (wxChar const *) thirdAction, nullptr}, rect,
m_hit_type == HIT_ACTION ? m_hit_item & 3 : -1, states);
@ -625,7 +635,42 @@ void Slic3r::GUI::ImageGrid::renderContent(wxDC &dc, wxPoint const &pt, int inde
dc.DrawText(date, pt + wxPoint{24, 16});
}
if (m_selecting && show_download_state_always)
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_content_rect.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
}
void Slic3r::GUI::ImageGrid::renderContent2(wxDC &dc, wxPoint const &pt, int index, bool hit)
{
auto &file = m_file_sys->GetFile(index);
// Draw thumbnail & buttons
int h = m_content_rect.GetHeight() * 64 / 264;
m_content_rect.SetHeight(m_content_rect.GetHeight() - h);
auto br = dc.GetBrush();
auto pn = dc.GetPen();
dc.SetBrush(StateColor::darkModeColorFor(0xEEEEEE));
dc.SetPen(StateColor::darkModeColorFor(0xEEEEEE));
dc.DrawRectangle(pt, m_content_rect.GetSize()); // Fix translucent model thumbnail
renderContent1(dc, pt, index, hit);
m_content_rect.SetHeight(m_content_rect.GetHeight() + h);
// Draw info bar
dc.SetBrush(StateColor::darkModeColorFor(*wxWHITE));
dc.SetPen(StateColor::darkModeColorFor(*wxWHITE));
dc.DrawRectangle(pt.x, pt.y + m_content_rect.GetHeight() - h, m_content_rect.GetWidth(), h);
dc.SetBrush(br);
dc.SetPen(pn);
// Draw infos
dc.SetFont(Label::Head_16);
dc.SetTextForeground(StateColor::darkModeColorFor("#323A3D"));
auto em = em_unit(this);
wxRect rect{pt.x, pt.y + m_content_rect.GetHeight() - h, m_content_rect.GetWidth(), h / 2};
rect.Deflate(em, 0);
renderText2(dc, from_u8(file.name), rect);
rect.Offset(0, h / 2);
rect.SetWidth(rect.GetWidth() / 2 - em);
dc.SetFont(Label::Body_13);
dc.SetTextForeground(StateColor::darkModeColorFor("#6B6B6B"));
renderIconText(dc, m_model_time_icon, file.Metadata("Time", "0m"), rect);
rect.Offset(m_content_rect.GetWidth() / 2, 0);
renderIconText(dc, m_model_weight_icon, file.Metadata("Weight", "0g"), rect);
}
void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect2, size_t hit, int states)
@ -646,7 +691,9 @@ void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts,
// Draw button background
//dc.Blit(rect.GetTopLeft(), rect.GetSize(), &mdc, {m_buttonBackgroundColor.colorIndexForStates(states) * 128, 0});
//dc.DrawBitmap(m_button_background, rect2.GetTopLeft());
rect.Deflate(10, 5);
//dc.SetBrush(m_buttonBackgroundColor.colorForStates(states2));
//dc.DrawRectangle(rect);
//rect.Deflate(10, 5);
// Draw button splitter
auto pen = dc.GetPen();
dc.SetPen(wxPen("#616161"));
@ -654,7 +701,7 @@ void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts,
dc.SetPen(pen);
// Draw button text
renderText(dc, texts[i], rect, states | states2);
rect.Inflate(10, 5);
//rect.Inflate(10, 5);
rect.Offset(rect.GetWidth(), 0);
}
dc.SetFont(GetFont());
@ -668,4 +715,20 @@ void Slic3r::GUI::ImageGrid::renderText(wxDC &dc, wxString const &text, wxRect c
dc.DrawText(text, rc.GetTopLeft());
}
void Slic3r::GUI::ImageGrid::renderText2(wxDC &dc, wxString text, wxRect const &rect)
{
wxRect rc({0, 0}, dc.GetTextExtent(text));
rc = rc.CenterIn(rect);
rc.SetLeft(rect.GetLeft());
if (rc.GetWidth() > rect.GetWidth())
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, rect.GetWidth());
dc.DrawText(text, rc.GetTopLeft());
}
void Slic3r::GUI::ImageGrid::renderIconText(wxDC & dc, ScalableBitmap const & icon, wxString text, wxRect const & rect)
{
dc.DrawBitmap(icon.bmp(), rect.x, rect.y + (rect.height - icon.GetBmpHeight()) / 2);
renderText2(dc, text, {rect.x + icon.GetBmpWidth() + 4, rect.y, rect.width - icon.GetBmpWidth() - 4, rect.height});
}
}}

View file

@ -19,6 +19,8 @@ class Label;
class PrinterFileSystem;
wxDECLARE_EVENT(EVT_ITEM_ACTION, wxCommandEvent);
namespace Slic3r {
class MachineObject;
@ -36,7 +38,7 @@ public:
boost::shared_ptr<PrinterFileSystem> GetFileSystem() { return m_file_sys; }
void SetFileType(int type);
void SetFileType(int type, std::string const &storage);
void SetGroupMode(int mode);
@ -72,15 +74,23 @@ protected:
wxBitmap createAlphaBitmap(wxSize size, wxColour color, int alpha1, int alpha2);
wxBitmap createShadowBorder(wxSize size, wxColour color, int radius, int shadow);
wxBitmap createCircleBitmap(wxSize size, int borderWidth, int percent, wxColour fillColor, wxColour borderColor = wxTransparentColour);
void render(wxDC &dc);
void renderContent(wxDC &dc, wxPoint const &pt, int index, bool hit);
void renderContent1(wxDC &dc, wxPoint const &pt, int index, bool hit);
void renderContent2(wxDC &dc, wxPoint const &pt, int index, bool hit);
void renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect, size_t hit, int states);
void renderText(wxDC &dc, wxString const & text, wxRect const & rect, int states);
void renderText(wxDC &dc, wxString const &text, wxRect const &rect, int states);
void renderText2(wxDC &dc, wxString text, wxRect const &rect);
void renderIconText(wxDC &dc, ScalableBitmap const & icon, wxString text, wxRect const &rect);
// some useful events
void mouseMoved(wxMouseEvent& event);
@ -100,14 +110,17 @@ private:
ScalableBitmap m_checked_icon;
ScalableBitmap m_unchecked_icon;
StateColor m_buttonBackgroundColor;
ScalableBitmap m_model_time_icon;
ScalableBitmap m_model_weight_icon;
StateColor m_buttonBackgroundColor;
StateColor m_buttonTextColor;
bool m_hovered = false;
bool m_pressed = false;
wxTimer m_timer;
wxBitmap m_mask;
wxBitmap m_title_mask;
wxBitmap m_border_mask;
wxBitmap m_buttons_background;
wxBitmap m_buttons_background_checked;
// wxBitmap m_button_background;
@ -128,8 +141,9 @@ private:
int m_row_offset = 0; // 1/4 row height
int m_row_count = 0; // 1/4 row height
int m_col_count = 1;
wxSize m_image_size;
wxSize m_cell_size;
wxSize m_border_size;
wxRect m_content_rect;
};
}}

View file

@ -498,9 +498,7 @@ void ArrangeJob::process()
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_arrange_params(params, *m_plater, m_selected);
@ -738,7 +736,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
params.cleareance_radius = print.config().extruder_clearance_radius.value;
params.cleareance_radius = print.config().extruder_clearance_max_radius.value;
params.printable_height = print.config().printable_height.value;
params.allow_rotations = settings.enable_rotation;
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;

View file

@ -16,22 +16,6 @@ static wxString waiting_auth_str = _L("Logging in");
static wxString login_failed_str = _L("Login failed");
wxString get_login_fail_reason(std::string fail_reason)
{
if (fail_reason == "NO Regions")
return _L("The region parameter is incorrrect");
else if (fail_reason == "Cloud Timeout")
return _L("Failure of printer login");
else if (fail_reason == "Ticket Failed")
return _L("Failed to get ticket");
else if (fail_reason == "Wait Auth Timeout")
return _L("User authorization timeout");
else if (fail_reason == "Bind Failure")
return _L("Failure of bind");
else
return _L("Unknown Failure");
}
BindJob::BindJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id, std::string dev_ip, std::string sec_link)
: PlaterJob{std::move(pri), plater},
m_dev_id(dev_id),
@ -59,7 +43,6 @@ void BindJob::on_success(std::function<void()> success)
void BindJob::update_status(int st, const wxString &msg)
{
GUI::Job::update_status(st, msg);
//post_event(wxCommandEvent(EVT_BIND_UPDATE_MESSAGE), msg);
wxCommandEvent event(EVT_BIND_UPDATE_MESSAGE);
event.SetString(msg);
event.SetEventObject(m_event_handle);
@ -68,6 +51,9 @@ void BindJob::update_status(int st, const wxString &msg)
void BindJob::process()
{
int result_code = 0;
std::string result_info;
/* display info */
wxString msg = waiting_auth_str;
int curr_percent = 0;
@ -80,8 +66,12 @@ void BindJob::process()
long offset = tz.GetOffset();
std::string timezone = get_timezone_utc_hm(offset);
int result = m_agent->bind(m_dev_ip, m_dev_id, m_sec_link, timezone,
[this, &curr_percent, &msg](int stage, int code, std::string info) {
int result = m_agent->bind(m_dev_ip, m_dev_id, m_sec_link, timezone, m_improved,
[this, &curr_percent, &msg, &result_code, &result_info](int stage, int code, std::string info) {
result_code = code;
result_info = info;
if (stage == BBL::BindJobStage::LoginStageConnect) {
curr_percent = 15;
msg = _L("Logging in");
@ -103,8 +93,9 @@ void BindJob::process()
} else {
msg = _L("Logging in");
}
if (code != 0) {
msg = _L("Login failed") + wxString::Format("(code=%d,info=%s). ", code, info);
msg = _L("Login failed");
if (code == BAMBU_NETWORK_ERR_TIMEOUT) {
msg += _L("Please check the printer network connection.");
}
@ -115,14 +106,28 @@ void BindJob::process()
if (result < 0) {
BOOST_LOG_TRIVIAL(trace) << "login: result = " << result;
post_fail_event();
if (result_code == BAMBU_NETWORK_ERR_BIND_ECODE_LOGIN_REPORT_FAILED) {
int error_code;
try
{
error_code = stoi(result_info);
result_info = wxGetApp().get_hms_query()->query_print_error_msg(error_code).ToStdString();
}
catch (...) {
;
}
}
post_fail_event(result_code, result_info);
return;
}
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) {
BOOST_LOG_TRIVIAL(trace) << "login: dev is null";
post_fail_event();
post_fail_event(result_code, result_info);
return;
}
dev->update_user_machine_list_info();
@ -145,9 +150,11 @@ void BindJob::set_event_handle(wxWindow *hanle)
m_event_handle = hanle;
}
void BindJob::post_fail_event()
void BindJob::post_fail_event(int code, std::string info)
{
wxCommandEvent event(EVT_BIND_MACHINE_FAIL);
event.SetInt(code);
event.SetString(info);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
}

View file

@ -19,6 +19,7 @@ class BindJob : public PlaterJob
std::string m_sec_link;
bool m_job_finished{ false };
int m_print_job_completed_id = 0;
bool m_improved{false};
protected:
void on_exception(const std::exception_ptr &) override;
@ -37,7 +38,8 @@ public:
void process() override;
void finalize() override;
void set_event_handle(wxWindow* hanle);
void post_fail_event();
void post_fail_event(int code, std::string info);
void set_improved(bool improved){m_improved = improved;};
};
wxDECLARE_EVENT(EVT_BIND_UPDATE_MESSAGE, wxCommandEvent);

View file

@ -211,9 +211,7 @@ void FillBedJob::process()
auto &partplate_list = m_plater->get_partplate_list();
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_selected_items_inflation(m_selected, *m_plater, params);
@ -233,7 +231,7 @@ void FillBedJob::process()
do_stop = ap.bed_idx > 0 && ap.priority == 0;
};
// final align用的是凸包在有fixed item的情况下可能找到的参考点位置是错的这里就不做了。见STUDIO-3265
params.do_final_align = !has_lidar;
params.do_final_align = false;
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);

View file

@ -35,9 +35,9 @@ void GUI::Job::update_percent_finish()
m_progress->clear_percent();
}
void GUI::Job::show_networking_test(wxString msg)
void GUI::Job::show_error_info(wxString msg, int code, wxString description, wxString extra)
{
m_progress->show_networking_test(msg);
m_progress->show_error_info(msg, code, description, extra);
}
GUI::Job::Job(std::shared_ptr<ProgressIndicator> pri)

View file

@ -47,7 +47,7 @@ protected:
void update_percent_finish();
void show_networking_test(wxString msg);
void show_error_info(wxString msg, int code, wxString description, wxString extra);
bool was_canceled() const { return m_canceled.load(); }

View file

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

View file

@ -15,7 +15,7 @@ public:
explicit NotificationProgressIndicator(NotificationManager *nm);
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 set_range(int range) override;
void set_cancel_callback(CancelFn = CancelFn()) override;
void set_progress(int pr) override;

View file

@ -2,27 +2,32 @@
#include "libslic3r/MTUtils.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "bambu_networking.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/MainFrame.hpp"
#include "bambu_networking.hpp"
namespace Slic3r {
namespace GUI {
static wxString check_gcode_failed_str = _L("Abnormal print file data. Please slice again");
static wxString printjob_cancel_str = _L("Task canceled");
static wxString timeout_to_upload_str = _L("Upload task timed out. Please check the network problem and try again");
static wxString check_gcode_failed_str = _L("Abnormal print file data. Please slice again.");
static wxString printjob_cancel_str = _L("Task canceled.");
static wxString timeout_to_upload_str = _L("Upload task timed out. Please check the network status and try again.");
static wxString failed_in_cloud_service_str = _L("Cloud service connection failed. Please try again.");
static wxString file_is_not_exists_str = _L("Print file not found, please slice again");
static wxString file_over_size_str = _L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again");
static wxString print_canceled_str = _L("Task canceled");
static wxString upload_failed_str = _L("Failed uploading print file");
static wxString upload_login_failed_str = _L("Wrong Access code");
static wxString file_is_not_exists_str = _L("Print file not found. please slice again.");
static wxString file_over_size_str = _L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again.");
static wxString print_canceled_str = _L("Task canceled.");
static wxString send_print_failed_str = _L("Failed to send the print job. Please try again.");
static wxString upload_ftp_failed_str = _L("Failed to upload file to ftp. Please try again.");
static wxString desc_network_error = _L("Check the current status of the bambu server by clicking on the link above.");
static wxString desc_file_too_large = _L("The size of the print file is too large. Please adjust the file size and try again.");
static wxString desc_fail_not_exist = _L("Print file not found, Please slice it again and send it for printing.");
static wxString desc_upload_ftp_failed = _L("Failed to upload print file to FTP. Please check the network status and try again.");
static wxString sending_over_lan_str = _L("Sending print job over LAN");
static wxString sending_over_cloud_str = _L("Sending print job through cloud service");
static wxString sending_over_lan_str = _L("Sending print job over LAN");
static wxString sending_over_cloud_str = _L("Sending print job through cloud service");
PrintJob::PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::string dev_id)
: PlaterJob{ std::move(pri), plater },
@ -33,7 +38,8 @@ PrintJob::PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::
void PrintJob::prepare()
{
m_plater->get_print_job_data(&job_data);
if (job_data.is_from_plater)
m_plater->get_print_job_data(&job_data);
if (&job_data) {
std::string temp_file = Slic3r::resources_dir() + "/check_access_code.txt";
auto check_access_code_path = temp_file.c_str();
@ -57,6 +63,21 @@ void PrintJob::on_success(std::function<void()> success)
m_success_fun = success;
}
std::string PrintJob::truncate_string(const std::string& str, size_t maxLength)
{
if (str.length() <= maxLength)
{
return str;
}
wxString local_str = wxString::FromUTF8(str);
wxString truncatedStr = local_str.Mid(0, maxLength - 3);
truncatedStr.append("...");
return truncatedStr.utf8_string();
}
wxString PrintJob::get_http_error_msg(unsigned int status, std::string body)
{
try {
@ -126,54 +147,62 @@ void PrintJob::process()
unsigned int http_code;
std::string http_body;
int total_plate_num = m_plater->get_partplate_list().get_plate_count();
int total_plate_num = plate_data.plate_count;
if (!plate_data.is_valid) {
total_plate_num = m_plater->get_partplate_list().get_plate_count();
PartPlate *plate = m_plater->get_partplate_list().get_plate(job_data.plate_idx);
if (plate == nullptr) {
plate = m_plater->get_partplate_list().get_curr_plate();
if (plate == nullptr) return;
}
PartPlate* plate = m_plater->get_partplate_list().get_plate(job_data.plate_idx);
if (plate == nullptr) {
plate = m_plater->get_partplate_list().get_curr_plate();
if (plate == nullptr)
return;
/* check gcode is valid */
if (!plate->is_valid_gcode_file() && m_print_type == "from_normal") {
update_status(curr_percent, check_gcode_failed_str);
return;
}
if (was_canceled()) {
update_status(curr_percent, printjob_cancel_str);
return;
}
}
/* check gcode is valid */
if (!plate->is_valid_gcode_file()) {
update_status(curr_percent, check_gcode_failed_str);
return;
}
if (was_canceled()) {
update_status(curr_percent, printjob_cancel_str);
return;
}
// task name
std::string project_name = wxGetApp().plater()->get_project_name().ToUTF8().data();
m_project_name = truncate_string(m_project_name, 100);
int curr_plate_idx = 0;
if (job_data.plate_idx >= 0)
curr_plate_idx = job_data.plate_idx + 1;
else if (job_data.plate_idx == PLATE_CURRENT_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
else if (job_data.plate_idx == PLATE_ALL_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
else
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
if (m_print_type == "from_normal") {
if (plate_data.is_valid)
curr_plate_idx = plate_data.cur_plate_index;
if (job_data.plate_idx >= 0)
curr_plate_idx = job_data.plate_idx + 1;
else if (job_data.plate_idx == PLATE_CURRENT_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
else if (job_data.plate_idx == PLATE_ALL_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
else
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
}
else if(m_print_type == "from_sdcard_view") {
curr_plate_idx = m_print_from_sdc_plate_idx;
}
PartPlate* curr_plate = m_plater->get_partplate_list().get_curr_plate();
if (curr_plate) {
this->task_bed_type = bed_type_to_gcode_string(curr_plate->get_bed_type(true));
this->task_bed_type = bed_type_to_gcode_string(plate_data.is_valid ? plate_data.bed_type : curr_plate->get_bed_type(true));
}
BBL::PrintParams params;
// local print access
params.dev_ip = m_dev_ip;
params.use_ssl = m_local_use_ssl;
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
params.use_ssl_for_mqtt = m_local_use_ssl_for_mqtt;
params.username = "bblp";
params.password = m_access_code;
// check access code and ip address
if (this->connection_type == "lan") {
if (this->connection_type == "lan" && m_print_type == "from_normal") {
params.dev_id = m_dev_id;
params.project_name = "verify_job";
params.filename = job_data._temp_path.string();
@ -186,16 +215,16 @@ void PrintJob::process()
m_job_finished = true;
return;
}
params.project_name = "";
params.filename = "";
}
params.dev_id = m_dev_id;
params.ftp_folder = m_ftp_folder;
//params.project_name = project_name;
params.project_name = m_project_name;
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
params.filename = job_data._3mf_path.string();
params.config_filename = job_data._3mf_config_path.string();
params.plate_index = curr_plate_idx;
params.dev_id = m_dev_id;
params.ftp_folder = m_ftp_folder;
params.filename = job_data._3mf_path.string();
params.config_filename = job_data._3mf_config_path.string();
params.plate_index = curr_plate_idx;
params.task_bed_leveling = this->task_bed_leveling;
params.task_flow_cali = this->task_flow_cali;
params.task_vibration_cali = this->task_vibration_cali;
@ -206,6 +235,13 @@ void PrintJob::process()
params.connection_type = this->connection_type;
params.task_use_ams = this->task_use_ams;
params.task_bed_type = this->task_bed_type;
params.print_type = this->m_print_type;
if (m_print_type == "from_sdcard_view") {
params.dst_file = m_dst_path;
}
if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) {
ModelInfo* model_info = wxGetApp().model().model_info.get();
auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG);
@ -222,7 +258,27 @@ void PrintJob::process()
}
catch(...) {}
}
auto profile_name = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_TITLE_TAG);
if (profile_name != model_info->metadata_items.end()) {
try {
params.preset_name = profile_name->second;
}
catch (...) {}
}
auto model_name = model_info->metadata_items.find(BBL_DESIGNER_MODEL_TITLE_TAG);
if (model_name != model_info->metadata_items.end()) {
try {
params.project_name = model_name->second;
}
catch (...) {}
}
}
if (params.preset_name.empty() && m_print_type == "from_normal") { params.preset_name = wxString::Format("%s_plate_%d", m_project_name, curr_plate_idx).ToStdString(); }
if (params.project_name.empty()) {params.project_name = m_project_name;}
wxString error_text;
wxString msg_text;
@ -240,7 +296,16 @@ void PrintJob::process()
bool is_try_lan_mode = false;
bool is_try_lan_mode_failed = false;
auto update_fn = [this, &is_try_lan_mode, &is_try_lan_mode_failed, &msg, &error_str, &curr_percent, &error_text, StagePercentPoint](int stage, int code, std::string info) {
auto update_fn = [this,
&is_try_lan_mode,
&is_try_lan_mode_failed,
&msg,
&error_str,
&curr_percent,
&error_text,
StagePercentPoint
](int stage, int code, std::string info) {
if (stage == BBL::SendingPrintJobStage::PrintingStageCreate && !is_try_lan_mode_failed) {
if (this->connection_type == "lan") {
msg = _L("Sending print job over LAN");
@ -277,6 +342,9 @@ void PrintJob::process()
}
else if (stage == BBL::SendingPrintJobStage::PrintingStageFinished) {
msg = wxString::Format(_L("Successfully sent. Will automatically jump to the device page in %ss"), info);
if (m_print_job_completed_id == wxGetApp().plater()->get_send_calibration_finished_event()) {
msg = wxString::Format(_L("Successfully sent. Will automatically jump to the next page in %ss"), info);
}
this->update_percent_finish();
} else {
if (this->connection_type == "lan") {
@ -296,13 +364,21 @@ void PrintJob::process()
}
}
if (code > 100 || code < 0) {
error_text = this->get_http_error_msg(code, info);
error_str = wxString::Format("[%s]", error_text);
} else {
error_str = wxEmptyString;
//get errors
if (code > 100 || code < 0 || stage == BBL::SendingPrintJobStage::PrintingStageERROR) {
if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE) {
m_plater->update_print_error_info(code, desc_file_too_large.ToStdString(), info);
}else if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST){
m_plater->update_print_error_info(code, desc_fail_not_exist.ToStdString(), info);
}else if (code == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || code == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
m_plater->update_print_error_info(code, desc_upload_ftp_failed.ToStdString(), info);
}else {
m_plater->update_print_error_info(code, desc_network_error.ToStdString(), info);
}
}
else {
this->update_status(curr_percent, msg);
}
this->update_status(curr_percent, msg + error_str);
};
auto cancel_fn = [this]() {
@ -351,10 +427,7 @@ void PrintJob::process()
if (result == 0) {
params.comments = "";
}
else if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
params.comments = "wrong_code";
}
else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
else if (result == BAMBU_NETWORK_ERR_PRINT_WR_UPLOAD_FTP_FAILED) {
params.comments = "upload_failed";
}
else {
@ -385,45 +458,45 @@ void PrintJob::process()
}
if (result < 0) {
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
msg_text = _L("Failed to send the print job. Please try again.");
} if (result == BAMBU_NETWORK_ERR_FILE_NOT_EXIST) {
curr_percent = -1;
if (result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST) {
msg_text = file_is_not_exists_str;
} else if (result == BAMBU_NETWORK_ERR_FILE_OVER_SIZE) {
} else if (result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE || result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE) {
msg_text = file_over_size_str;
} else if (result == BAMBU_NETWORK_ERR_CHECK_MD5_FAILED) {
} else if (result == BAMBU_NETWORK_ERR_PRINT_WR_CHECK_MD5_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SP_CHECK_MD5_FAILED) {
msg_text = failed_in_cloud_service_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_PARAMS) {
msg_text = _L("Failed to send the print job. Please try again.");
} else if (result == BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_TIMEOUT || result == BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_TIMEOUT) {
msg_text = timeout_to_upload_str;
} else if (result == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
msg_text = upload_ftp_failed_str;
} else if (result == BAMBU_NETWORK_ERR_CANCELED) {
msg_text = print_canceled_str;
} else if (result == BAMBU_NETWORK_ERR_TIMEOUT) {
msg_text = timeout_to_upload_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
msg_text = _L("Failed to send the print job. Please try again.");
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
msg_text = _L("Failed to send the print job. Please try again.");
this->update_status(0, msg_text);
} else {
update_status(curr_percent, failed_in_cloud_service_str);
}
if (!error_text.IsEmpty()) {
curr_percent = 0;
msg_text += wxString::Format("[%d][%s]", result, error_text);
}
if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
this->show_networking_test(msg_text);
}
else {
update_status(curr_percent, msg_text);
msg_text = send_print_failed_str;
}
if (result != BAMBU_NETWORK_ERR_CANCELED) {
this->show_error_info(msg_text, 0, "", "");
}
BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result;
} else {
wxGetApp().plater()->record_slice_preset("print");
BOOST_LOG_TRIVIAL(error) << "print_job: send ok.";
wxCommandEvent* evt = new wxCommandEvent(m_print_job_completed_id);
evt->SetString(m_dev_id);
if (!m_completed_evt_data.empty())
evt->SetString(m_completed_evt_data);
else
evt->SetString(m_dev_id);
if (m_print_job_completed_id == wxGetApp().plater()->get_send_calibration_finished_event()) {
int sel = wxGetApp().mainframe->get_calibration_curr_tab();
if (sel >= 0) {
evt->SetInt(sel);
}
}
wxQueueEvent(m_plater, evt);
m_job_finished = true;
}
@ -440,6 +513,12 @@ void PrintJob::set_project_name(std::string name)
m_project_name = name;
}
void PrintJob::set_dst_name(std::string path)
{
m_dst_path = path;
}
void PrintJob::on_check_ip_address_fail(std::function<void()> func)
{
m_enter_ip_address_fun_fail = func;
@ -450,4 +529,10 @@ void PrintJob::on_check_ip_address_success(std::function<void()> func)
m_enter_ip_address_fun_success = func;
}
void PrintJob::connect_to_local_mqtt()
{
this->update_status(0, wxEmptyString);
}
}} // namespace Slic3r::GUI

View file

@ -13,6 +13,7 @@ namespace GUI {
class PrintPrepareData
{
public:
bool is_from_plater = true;
int plate_idx;
fs::path _3mf_path;
fs::path _3mf_config_path;
@ -22,20 +23,31 @@ public:
}
};
class PlateListData
{
public:
bool is_valid = false;
int plate_count = 0;
int cur_plate_index = 0;
BedType bed_type = BedType::btDefault;
};
class PrintJob : public PlaterJob
{
std::function<void()> m_success_fun{nullptr};
PrintPrepareData job_data;
std::string m_dev_id;
bool m_job_finished{ false };
int m_print_job_completed_id = 0;
wxString m_completed_evt_data;
std::function<void()> m_enter_ip_address_fun_fail{ nullptr };
std::function<void()> m_enter_ip_address_fun_success{ nullptr };
public:
PrintPrepareData job_data;
PlateListData plate_data;
protected:
void prepare() override;
void on_exception(const std::exception_ptr &) override;
public:
PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater, std::string dev_id = "");
@ -43,17 +55,23 @@ public:
std::string m_project_name;
std::string m_dev_ip;
std::string m_ftp_folder;
bool m_local_use_ssl { true };
std::string m_access_code;
std::string task_bed_type;
std::string task_ams_mapping;
std::string task_ams_mapping_info;
std::string connection_type;
std::string m_print_type;
std::string m_dst_path;
int m_print_from_sdc_plate_idx = 0;
bool m_local_use_ssl_for_mqtt { true };
bool m_local_use_ssl_for_ftp { true };
bool task_bed_leveling;
bool task_flow_cali;
bool task_vibration_cali;
bool task_record_timelapse;
bool task_layer_inspect;
std::string task_ams_mapping;
std::string task_ams_mapping_info;
std::string connection_type;
bool cloud_print_only { false };
bool has_sdcard { false };
bool task_use_ams { true };
@ -74,15 +92,21 @@ public:
}
bool is_finished() { return m_job_finished; }
void set_print_job_finished_event(int event_id) { m_print_job_completed_id = event_id; }
void set_print_job_finished_event(int event_id, wxString evt_data = wxEmptyString) {
m_print_job_completed_id = event_id;
m_completed_evt_data = evt_data;
}
void on_success(std::function<void()> success);
wxString get_http_error_msg(unsigned int status, std::string body);
void process() override;
void finalize() override;
void set_project_name(std::string name);
void set_dst_name(std::string path);
void on_check_ip_address_fail(std::function<void()> func);
void on_check_ip_address_success(std::function<void()> func);
void connect_to_local_mqtt();
wxString get_http_error_msg(unsigned int status, std::string body);
std::string truncate_string(const std::string& str, size_t maxLength);
};
}} // namespace Slic3r::GUI

View file

@ -18,7 +18,7 @@ public:
virtual ~ProgressIndicator() = default;
virtual void clear_percent() = 0;
virtual void show_networking_test(wxString msg) = 0;
virtual void show_error_info(wxString msg, int code, wxString description, wxString extra) = 0;
virtual void set_range(int range) = 0;
virtual void set_cancel_callback(CancelFn = CancelFn()) = 0;
virtual void set_progress(int pr) = 0;

View file

@ -9,20 +9,23 @@
namespace Slic3r {
namespace GUI {
static wxString check_gcode_failed_str = _L("Abnormal print file data. Please slice again");
static wxString printjob_cancel_str = _L("Task canceled");
static wxString timeout_to_upload_str = _L("Upload task timed out. Please check the network problem and try again");
static wxString failed_in_cloud_service_str = _L("Send to Printer failed. Please try again.");
static wxString file_is_not_exists_str = _L("Print file not found, please slice again");
static wxString file_over_size_str = _L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again");
static wxString print_canceled_str = _L("Task canceled");
static wxString upload_failed_str = _L("Failed uploading print file");
static wxString upload_login_failed_str = _L("Wrong Access code");
static wxString upload_no_space_left_str = _L("No space left on Printer SD card");
static wxString check_gcode_failed_str = _L("Abnormal print file data. Please slice again.");
static wxString printjob_cancel_str = _L("Task canceled.");
static wxString timeout_to_upload_str = _L("Upload task timed out. Please check the network status and try again.");
static wxString failed_in_cloud_service_str = _L("Cloud service connection failed. Please try again.");
static wxString file_is_not_exists_str = _L("Print file not found. please slice again.");
static wxString file_over_size_str = _L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again.");
static wxString print_canceled_str = _L("Task canceled.");
static wxString send_print_failed_str = _L("Failed to send the print job. Please try again.");
static wxString upload_ftp_failed_str = _L("Failed to upload file to ftp. Please try again.");
static wxString desc_network_error = _L("Check the current status of the bambu server by clicking on the link above.");
static wxString desc_file_too_large = _L("The size of the print file is too large. Please adjust the file size and try again.");
static wxString desc_fail_not_exist = _L("Print file not found, Please slice it again and send it for printing.");
static wxString desc_upload_ftp_failed = _L("Failed to upload print file to FTP. Please check the network status and try again.");
static wxString sending_over_lan_str = _L("Sending gcode file over LAN");
static wxString sending_over_cloud_str = _L("Sending gcode file through cloud service");
static wxString sending_over_lan_str = _L("Sending print job over LAN");
static wxString sending_over_cloud_str = _L("Sending print job through cloud service");
SendJob::SendJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::string dev_id)
: PlaterJob{ std::move(pri), plater },
@ -127,7 +130,8 @@ void SendJob::process()
params.dev_ip = m_dev_ip;
params.username = "bblp";
params.password = m_access_code;
params.use_ssl = m_local_use_ssl;
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
params.use_ssl_for_mqtt = m_local_use_ssl_for_mqtt;
// check access code and ip address
params.dev_id = m_dev_id;
@ -202,12 +206,12 @@ void SendJob::process()
else if (job_data.plate_idx == PLATE_CURRENT_IDX)
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
params.dev_id = m_dev_id;
params.project_name = m_project_name + ".gcode.3mf";
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
params.filename = job_data._3mf_path.string();
params.config_filename = job_data._3mf_config_path.string();
params.plate_index = curr_plate_idx;
params.dev_id = m_dev_id;
params.project_name = m_project_name + ".gcode.3mf";
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
params.filename = job_data._3mf_path.string();
params.config_filename = job_data._3mf_config_path.string();
params.plate_index = curr_plate_idx;
params.ams_mapping = this->task_ams_mapping;
params.connection_type = this->connection_type;
params.task_use_ams = this->task_use_ams;
@ -216,7 +220,8 @@ void SendJob::process()
params.dev_ip = m_dev_ip;
params.username = "bblp";
params.password = m_access_code;
params.use_ssl = m_local_use_ssl;
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
params.use_ssl_for_mqtt = m_local_use_ssl_for_mqtt;
wxString error_text;
wxString msg_text;
@ -271,11 +276,24 @@ void SendJob::process()
}
}
if (code < 0 || code > 100) {
error_text = this->get_http_error_msg(code, info);
msg += wxString::Format("[%s]", error_text);
//get errors
if (code > 100 || code < 0 || stage == BBL::SendingPrintJobStage::PrintingStageERROR) {
if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE) {
m_plater->update_print_error_info(code, desc_file_too_large.ToStdString(), info);
}
else if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST) {
m_plater->update_print_error_info(code, desc_fail_not_exist.ToStdString(), info);
}
else if (code == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || code == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
m_plater->update_print_error_info(code, desc_upload_ftp_failed.ToStdString(), info);
}
else {
m_plater->update_print_error_info(code, desc_network_error.ToStdString(), info);
}
}
else {
this->update_status(curr_percent, msg);
}
this->update_status(curr_percent, msg);
};
auto cancel_fn = [this]() {
@ -300,9 +318,7 @@ void SendJob::process()
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode to printer";
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn);
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
params.comments = "wrong_code";
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
params.comments = "upload_failed";
} else {
params.comments = (boost::format("failed(%1%)") % result).str();
@ -332,50 +348,40 @@ void SendJob::process()
}
if (result < 0) {
if (result == BAMBU_NETWORK_ERR_NO_SPACE_LEFT_ON_DEVICE) {
msg_text = upload_no_space_left_str;
} else if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
msg_text = upload_login_failed_str;
} else if (result == BAMBU_NETWORK_ERR_FILE_NOT_EXIST) {
curr_percent = -1;
if (result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST) {
msg_text = file_is_not_exists_str;
} else if (result == BAMBU_NETWORK_ERR_FILE_OVER_SIZE) {
}
else if (result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE || result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE) {
msg_text = file_over_size_str;
} else if (result == BAMBU_NETWORK_ERR_CHECK_MD5_FAILED) {
}
else if (result == BAMBU_NETWORK_ERR_PRINT_WR_CHECK_MD5_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SP_CHECK_MD5_FAILED) {
msg_text = failed_in_cloud_service_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_PARAMS) {
msg_text = upload_failed_str;
} else if (result == BAMBU_NETWORK_ERR_CANCELED) {
}
else if (result == BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_TIMEOUT || result == BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_TIMEOUT) {
msg_text = timeout_to_upload_str;
}
else if (result == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
msg_text = upload_ftp_failed_str;
}
else if (result == BAMBU_NETWORK_ERR_CANCELED) {
msg_text = print_canceled_str;
} else if (result == BAMBU_NETWORK_ERR_TIMEOUT) {
msg_text = timeout_to_upload_str;
} else if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
msg_text = upload_failed_str;
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
msg_text = upload_failed_str;
} else {
update_status(curr_percent, failed_in_cloud_service_str);
}
else {
msg_text = send_print_failed_str;
}
if (!error_text.IsEmpty()) {
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
msg_text += ". ";
msg_text += _L("Please log out and login to the printer again.");
}
else {
msg_text += wxString::Format("[%s]", error_text);
}
if (result != BAMBU_NETWORK_ERR_CANCELED) {
this->show_error_info(msg_text, 0, "", "");
}
if (result == BAMBU_NETWORK_ERR_WRONG_IP_ADDRESS) {
msg_text = timeout_to_upload_str;
}
update_status(curr_percent, msg_text);
BOOST_LOG_TRIVIAL(error) << "send_job: failed, result = " << result;
} else {
}
else {
BOOST_LOG_TRIVIAL(error) << "send_job: send ok.";
wxCommandEvent* evt = new wxCommandEvent(m_print_job_completed_id);
evt->SetString(from_u8(params.project_name));
evt->SetString(params.project_name);
wxQueueEvent(m_plater, evt);
m_job_finished = true;
}

View file

@ -37,11 +37,12 @@ public:
std::string m_project_name;
std::string m_dev_ip;
std::string m_access_code;
bool m_local_use_ssl{false};
std::string task_bed_type;
std::string task_ams_mapping;
std::string connection_type;
bool m_local_use_ssl_for_ftp{true};
bool m_local_use_ssl_for_mqtt{true};
bool cloud_print_only { false };
bool has_sdcard { false };
bool task_use_ams { true };

View file

@ -175,7 +175,7 @@ void KBShortcutsDialog::fill_shortcuts()
{ ctrl + "N", L("New Project") },
{ ctrl + "O", L("Open Project") },
{ ctrl + "S", L("Save Project") },
{ ctrl + alt + "S", L("Save Project as") },
{ ctrl + "Shift+S", L("Save Project as")},
// File>Import
{ ctrl + "I", L("Import geometry data from STL/STEP/3MF/OBJ/AMF files") },
// File>Export

File diff suppressed because it is too large Load diff

View file

@ -21,13 +21,15 @@
#include "Monitor.hpp"
#include "Auxiliary.hpp"
#include "Project.hpp"
#include "CalibrationPanel.hpp"
#include "UnsavedChangesDialog.hpp"
#include "Widgets/SideButton.hpp"
#include "Widgets/SideMenuPopup.hpp"
// BBS
#include "BBLTopbar.hpp"
#include "PrinterWebView.hpp"
#include "calib_dlg.hpp"
#include "PrinterWebView.hpp"
#include "calib_dlg.hpp"
@ -95,7 +97,8 @@ class MainFrame : public DPIFrame
wxString m_last_config = wxEmptyString;
wxMenuBar* m_menubar{ nullptr };
wxMenu* publishMenu{ nullptr };
//wxMenu* publishMenu{ nullptr };
wxMenu * m_calib_menu{nullptr};
#if 0
wxMenuItem* m_menu_item_repeat { nullptr }; // doesn't used now
@ -217,13 +220,14 @@ public:
//BBS GUI refactor
enum TabPosition
{
tpHome = 0,
tp3DEditor = 1,
//tpSettings = 1,
tpPreview = 2,
tpMonitor = 3,
tpProject = 4,
toDebugTool = 5,
tpHome = 0,
tp3DEditor = 1,
tpPreview = 2,
tpMonitor = 3,
tpProject = 4,
tpCalibration = 5,
tpAuxiliary = 6,
toDebugTool = 7,
};
//BBS: add slice&&print status update logic
@ -246,10 +250,15 @@ public:
// BBS
BBLTopbar* topbar() { return m_topbar; }
// for cali to update tab when save new preset
void update_filament_tab_ui();
void update_title();
void show_publish_button(bool show);
void set_max_recent_count(int max);
void show_publish_button(bool show);
void show_calibration_button(bool show);
void update_title_colour_after_set_title();
void show_option(bool show);
void init_tabpanel();
@ -307,6 +316,7 @@ public:
void select_tab(wxPanel* panel);
void select_tab(size_t tab = size_t(-1));
void request_select_tab(TabPosition pos);
int get_calibration_curr_tab();
void select_view(const std::string& direction);
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
void on_config_changed(DynamicPrintConfig* cfg) const ;
@ -320,7 +330,7 @@ public:
bool save_project_as(const wxString& filename = wxString());
void add_to_recent_projects(const wxString& filename);
void get_recent_projects(boost::property_tree::wptree & tree);
void get_recent_projects(boost::property_tree::wptree &tree, int images);
void open_recent_project(size_t file_id, wxString const & filename);
void remove_recent_project(size_t file_id, wxString const &filename);
@ -333,6 +343,14 @@ public:
bool is_printer_view() const;
void refresh_plugin_tips();
void RunScript(wxString js);
void show_device(bool bBBLPrinter);
// OrcaSlicer calibration
PA_Calibration_Dlg * m_pa_calib_dlg{nullptr};
Temp_Calibration_Dlg * m_temp_calib_dlg{nullptr};
MaxVolumetricSpeed_Test_Dlg *m_vol_test_dlg{nullptr};
VFA_Test_Dlg * m_vfa_test_dlg{nullptr};
Retraction_Test_Dlg * m_retraction_calib_dlg{nullptr};
//SoftFever
void show_device(bool bBBLPrinter);
@ -353,6 +371,7 @@ public:
//AuxiliaryPanel* m_auxiliary{ nullptr };
ProjectPanel* m_project{ nullptr };
CalibrationPanel* m_calibration{ nullptr };
WebViewPanel* m_webview { nullptr };
PrinterWebView* m_printer_view{nullptr};
wxLogWindow* m_log_window { nullptr };
@ -371,6 +390,7 @@ public:
// BBS
mutable int m_print_select{ ePrintAll };
mutable int m_slice_select{ eSliceAll };
Button* m_publish_btn{ nullptr };
SideButton* m_slice_btn{ nullptr };
SideButton* m_slice_option_btn{ nullptr };
SideButton* m_print_btn{ nullptr };

View file

@ -2,11 +2,22 @@
#include "ImageGrid.h"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "Plater.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/SwitchButton.hpp"
#include "Widgets/Label.hpp"
#include "Printer/PrinterFileSystem.h"
#include "MsgDialog.hpp"
#include "Widgets/ProgressDialog.hpp"
#include <libslic3r/Model.hpp>
#include <libslic3r/Format/bbs_3mf.hpp>
#ifdef __WXMSW__
#include <shellapi.h>
#endif
#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp"
#endif
namespace Slic3r {
namespace GUI {
@ -26,9 +37,11 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
top_sizer->SetMinSize({-1, 75 * em_unit(this) / 10});
// Time group
m_time_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_time_panel->SetBackgroundColor(StateColor());
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
auto time_panel = new wxWindow(this, wxID_ANY);
time_panel->SetBackgroundColour(0xEEEEEE);
m_time_panel = new ::StaticBox(time_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_time_panel->SetCornerRadius(0);
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
m_button_month = new ::Button(m_time_panel, _L("Month"), "", wxBORDER_NONE);
m_button_all = new ::Button(m_time_panel, _L("All Files"), "", wxBORDER_NONE);
m_button_year->SetToolTip(_L("Group files by year, recent first."));
@ -49,7 +62,10 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
time_sizer->Add(m_button_month, 0, wxALIGN_CENTER_VERTICAL);
time_sizer->Add(m_button_all, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
m_time_panel->SetSizer(time_sizer);
top_sizer->Add(m_time_panel, 1, wxEXPAND);
wxBoxSizer *time_sizer2 = new wxBoxSizer(wxHORIZONTAL);
time_sizer2->Add(m_time_panel, 1, wxEXPAND);
time_panel->SetSizer(time_sizer2);
top_sizer->Add(time_panel, 1, wxEXPAND);
// File type
StateColor background(
@ -61,30 +77,33 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
m_type_panel->SetCornerRadius(FromDIP(5));
m_type_panel->SetMinSize({-1, 48 * em_unit(this) / 10});
m_button_timelapse = new ::Button(m_type_panel, _L("Timelapse"), "", wxBORDER_NONE);
m_button_timelapse->SetToolTip(L("Switch to timelapse files."));
m_button_timelapse->SetToolTip(_L("Switch to timelapse files."));
m_button_video = new ::Button(m_type_panel, _L("Video"), "", wxBORDER_NONE);
m_button_video->SetToolTip(L("Switch to video files."));
for (auto b : {m_button_timelapse, m_button_video} ) {
m_button_video->SetToolTip(_L("Switch to video files."));
m_button_model = new ::Button(m_type_panel, _L("Model"), "", wxBORDER_NONE);
m_button_video->SetToolTip(_L("Switch to 3mf model files."));
for (auto b : {m_button_timelapse, m_button_video, m_button_model}) {
b->SetBackgroundColor(background);
b->SetCanFocus(false);
}
wxBoxSizer *type_sizer = new wxBoxSizer(wxHORIZONTAL);
type_sizer->Add(m_button_timelapse, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
type_sizer->Add(m_button_video, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
//type_sizer->Add(m_button_video, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
m_button_video->Hide();
type_sizer->Add(m_button_model, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
m_type_panel->SetSizer(type_sizer);
m_type_panel->Hide();
// top_sizer->Add(m_type_panel, 0, wxALIGN_CENTER_VERTICAL);
top_sizer->Add(m_type_panel, 0, wxALIGN_CENTER_VERTICAL);
// File management
m_manage_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_manage_panel->SetBackgroundColor(StateColor());
m_button_delete = new ::Button(m_manage_panel, _L("Delete"));
m_button_delete->SetToolTip(L("Delete selected files from printer."));
m_button_delete->SetToolTip(_L("Delete selected files from printer."));
m_button_download = new ::Button(m_manage_panel, _L("Download"));
m_button_download->SetToolTip(L("Download selected files from printer."));
m_button_download->SetToolTip(_L("Download selected files from printer."));
m_button_management = new ::Button(m_manage_panel, _L("Select"));
m_button_management->SetToolTip(L("Batch manage files."));
m_button_management->SetToolTip(_L("Batch manage files."));
for (auto b : {m_button_delete, m_button_download, m_button_management}) {
b->SetFont(Label::Body_12);
b->SetCornerRadius(12);
@ -109,6 +128,7 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
sizer->Add(top_sizer, 0, wxEXPAND);
m_image_grid = new ImageGrid(this);
m_image_grid->Bind(EVT_ITEM_ACTION, [this](wxCommandEvent &e) { doAction(size_t(e.GetExtraLong()), e.GetInt()); });
m_image_grid->SetStatus(m_bmp_failed, _L("No printers."));
sizer->Add(m_image_grid, 1, wxEXPAND);
@ -130,19 +150,20 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
// File type
auto type_button_clicked = [this](wxEvent &e) {
auto type = PrinterFileSystem::F_TIMELAPSE;
auto b = dynamic_cast<Button *>(e.GetEventObject());
if (b == m_button_video)
type = PrinterFileSystem::F_VIDEO;
Button *buttons[]{m_button_timelapse, m_button_video, m_button_model};
auto type = std::find(buttons, buttons + sizeof(buttons) / sizeof(buttons[0]), e.GetEventObject()) - buttons;
if (m_last_type == type)
return;
m_image_grid->SetFileType(type);
m_image_grid->SetFileType(type, m_external ? "" : "internal");
buttons[m_last_type]->SetValue(!buttons[m_last_type]->GetValue());
m_last_type = type;
m_button_timelapse->SetValue(!m_button_timelapse->GetValue());
m_button_video->SetValue(!m_button_video->GetValue());
buttons[m_last_type]->SetValue(!buttons[m_last_type]->GetValue());
if (type == PrinterFileSystem::F_MODEL)
m_image_grid->SetGroupMode(PrinterFileSystem::G_NONE);
};
m_button_video->Bind(wxEVT_COMMAND_BUTTON_CLICKED, type_button_clicked);
m_button_timelapse->Bind(wxEVT_COMMAND_BUTTON_CLICKED, type_button_clicked);
m_button_video->Bind(wxEVT_COMMAND_BUTTON_CLICKED, type_button_clicked);
m_button_model->Bind(wxEVT_COMMAND_BUTTON_CLICKED, type_button_clicked);
m_button_timelapse->SetValue(true);
// File management
@ -161,9 +182,12 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
auto onShowHide = [this](auto &e) {
e.Skip();
if (m_isBeingDeleted) return;
auto fs = m_image_grid ? m_image_grid->GetFileSystem() : nullptr;
if (fs) IsShownOnScreen() ? fs->Start() : fs->Stop();
if (auto w = dynamic_cast<wxWindow *>(e.GetEventObject()); !w || w->IsBeingDeleted())
return;
CallAfter([this] {
auto fs = m_image_grid ? m_image_grid->GetFileSystem() : nullptr;
if (fs) IsShownOnScreen() ? fs->Start() : fs->Stop();
});
};
Bind(wxEVT_SHOW, onShowHide);
parent->GetParent()->Bind(wxEVT_SHOW, onShowHide);
@ -180,19 +204,27 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
if (obj && obj->is_function_supported(PrinterFunction::FUNC_MEDIA_FILE)) {
m_supported = true;
m_lan_mode = obj->is_lan_mode_printer();
m_lan_ip = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->dev_ip : "";
m_lan_ip = obj->dev_ip;
m_lan_passwd = obj->get_access_code();
m_tutk_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
m_local_support = obj->has_local_file_proto();
m_remote_support = obj->has_remote_file_proto();
} else {
m_supported = false;
m_lan_mode = false;
m_lan_ip.clear();
m_lan_passwd.clear();
m_tutk_support = false;
m_local_support = false;
m_remote_support = false;
}
if (machine == m_machine)
if (machine == m_machine) {
if (m_waiting_enable && IsEnabled()) {
auto fs = m_image_grid->GetFileSystem();
if (fs) fs->Retry();
}
return;
}
m_machine = machine;
m_last_errors.clear();
auto fs = m_image_grid->GetFileSystem();
if (fs) {
m_image_grid->SetFileSystem(nullptr);
@ -204,17 +236,19 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
if (m_machine.empty()) {
m_image_grid->SetStatus(m_bmp_failed, _L("No printers."));
} else if (!m_supported) {
m_image_grid->SetStatus(m_bmp_failed, _L("Not supported by this model of printer!"));
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not supported on the current printer version)!"));
} else {
boost::shared_ptr<PrinterFileSystem> fs(new PrinterFileSystem);
fs->Attached();
m_image_grid->SetFileType(m_last_type);
m_image_grid->SetFileSystem(fs);
m_image_grid->SetFileType(m_last_type, m_external ? "" : "internal");
fs->Bind(EVT_FILE_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
if (fs == nullptr || m_image_grid->GetFileSystem() != fs) // canceled
return;
m_time_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL);
//m_manage_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL);
m_button_management->Enable(fs->GetCount() > 0);
if (fs->GetCount() == 0)
SetSelecting(false);
@ -222,7 +256,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
fs->Bind(EVT_SELECT_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
if (fs == nullptr || m_image_grid->GetFileSystem() != fs) // canceled
return;
m_button_delete->Enable(e.GetInt() > 0);
m_button_download->Enable(e.GetInt() > 0);
@ -231,31 +265,34 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
fs->Bind(EVT_STATUS_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto& e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
if (fs == nullptr || m_image_grid->GetFileSystem() != fs) // canceled
return;
ScalableBitmap icon;
wxString msg;
int status = e.GetInt();
int extra = e.GetExtraLong();
switch (status) {
case PrinterFileSystem::Initializing: icon = m_bmp_loading; msg = _L("Initializing..."); break;
case PrinterFileSystem::Connecting: icon = m_bmp_loading; msg = _L("Connecting..."); break;
case PrinterFileSystem::Failed: icon = m_bmp_failed; msg = _L("Connect failed [%d]!"); break;
case PrinterFileSystem::Failed: icon = m_bmp_failed; if (extra != 1) msg = _L("Connect failed [%d]!"); break;
case PrinterFileSystem::ListSyncing: icon = m_bmp_loading; msg = _L("Loading file list..."); break;
case PrinterFileSystem::ListReady: icon = m_bmp_empty; msg = _L("No files"); break;
case PrinterFileSystem::ListReady: icon = extra == 0 ? m_bmp_empty : m_bmp_failed; msg = extra == 0 ? _L("No files [%d]") : _L("Load failed [%d]"); break;
}
if (fs->GetCount() == 0)
if (!e.GetString().IsEmpty()) msg = _L(e.GetString());
if (fs->GetCount() == 0 && !msg.empty())
m_image_grid->SetStatus(icon, msg);
if (e.GetInt() == PrinterFileSystem::Initializing)
fetchUrl(boost::weak_ptr(fs));
if (status == PrinterFileSystem::Failed
|| status == PrinterFileSystem::ListReady) {
int err = fs->GetLastError();
if ((status == PrinterFileSystem::Failed && m_last_errors.find(err) == m_last_errors.end()) ||
status == PrinterFileSystem::ListReady) {
json j;
j["code"] = fs->GetLastError();
j["code"] = err;
j["dev_id"] = m_machine;
j["dev_ip"] = m_lan_ip;
NetworkAgent* agent = wxGetApp().getAgent();
if (status == PrinterFileSystem::Failed) {
if (status == PrinterFileSystem::Failed && err != 0) {
j["result"] = "failed";
if (agent)
agent->track_event("download_video_conn", j.dump());
@ -264,12 +301,13 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
if (agent)
agent->track_event("download_video_conn", j.dump());
}
m_last_errors.insert(fs->GetLastError());
}
});
fs->Bind(EVT_DOWNLOAD, [this, wfs = boost::weak_ptr(fs)](auto& e) {
e.Skip();
boost::shared_ptr fs(wfs.lock());
if (m_image_grid->GetFileSystem() != fs) // canceled
if (fs == nullptr || m_image_grid->GetFileSystem() != fs) // canceled
return;
int result = e.GetExtraLong();
@ -301,6 +339,22 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
modeChanged(e);
}
void MediaFilePanel::SwitchStorage(bool external)
{
if (m_external == external)
return;
m_external = external;
m_type_panel->Show(external);
if (!external) {
Button *buttons[]{m_button_timelapse, m_button_video, m_button_model};
auto button = buttons[PrinterFileSystem::F_MODEL];
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, button->GetId());
event.SetEventObject(button);
wxPostEvent(button, event);
}
m_image_grid->SetFileType(m_last_type, m_external ? "" : "internal");
}
void MediaFilePanel::Rescale()
{
m_bmp_loading.msw_rescale();
@ -315,6 +369,7 @@ void MediaFilePanel::Rescale()
m_button_video->Rescale();
m_button_timelapse->Rescale();
m_button_model->Rescale();
m_type_panel->SetMinSize({-1, 48 * em_unit(this) / 10});
m_button_download->Rescale();
@ -354,17 +409,31 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
{
boost::shared_ptr fs(wfs.lock());
if (!fs || fs != m_image_grid->GetFileSystem()) return;
if (!m_lan_ip.empty()) {
if (!IsEnabled()) {
m_waiting_enable = true;
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Device connection not ready)!"));
fs->SetUrl("0");
return;
}
m_waiting_enable = false;
if (!m_local_support && !m_remote_support) {
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not supported on the current printer version)!"));
fs->SetUrl("0");
return;
}
if ((m_lan_mode || !m_remote_support) && m_local_support && !m_lan_ip.empty()) {
std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
fs->SetUrl(url);
return;
}
if (m_lan_mode ) { // not support tutk
m_image_grid->SetStatus(m_bmp_failed, _L("Not accessible in LAN-only mode!"));
if (m_lan_mode) {
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not accessible in LAN-only mode)!"));
fs->SetUrl("0");
return;
}
if (!m_tutk_support) { // not support tutk
m_image_grid->SetStatus(m_bmp_failed, _L("Missing LAN ip of printer!"));
if (!m_remote_support && m_local_support) { // not support tutk
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Missing LAN ip of printer)!"));
fs->SetUrl("1");
return;
}
NetworkAgent *agent = wxGetApp().getAgent();
@ -375,15 +444,138 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
CallAfter([this, url, wfs] {
boost::shared_ptr fs(wfs.lock());
if (!fs || fs != m_image_grid->GetFileSystem()) return;
if (boost::algorithm::starts_with(url, "bambu:///"))
if (boost::algorithm::starts_with(url, "bambu:///")) {
fs->SetUrl(url);
else
m_image_grid->SetStatus(m_bmp_failed, url.empty() ? _L("Network unreachable") : from_u8(url));
} else {
m_image_grid->SetStatus(m_bmp_failed, wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
fs->SetUrl("3");
}
});
});
}
}
struct MediaProgressDialog : ProgressDialog
{
MediaProgressDialog(wxString title, wxWindow * parent, std::function<void()> cancel)
: ProgressDialog(title, "", 100, parent, wxPD_NO_PROGRESS | wxPD_APP_MODAL | wxPD_CAN_ABORT)
, m_cancel(cancel) {}
void OnCancel() override{m_cancel(); }
std::function<void()> m_cancel;
};
void MediaFilePanel::doAction(size_t index, int action)
{
auto fs = m_image_grid->GetFileSystem();
if (action == 0) {
if (index == -1) {
MessageDialog dlg(this,
wxString::Format(_L_PLURAL("You are going to delete %u file from printer. Are you sure to continue?",
"You are going to delete %u files from printer. Are you sure to continue?", fs->GetSelectCount()),
fs->GetSelectCount()),
_L("Delete files"), wxYES_NO | wxICON_WARNING);
if (dlg.ShowModal() != wxID_YES)
return;
} else {
MessageDialog dlg(this,
wxString::Format(_L("Do you want to delete the file '%s' from printer?"), from_u8(fs->GetFile(index).name)),
_L("Delete file"), wxYES_NO | wxICON_WARNING);
if (dlg.ShowModal() != wxID_YES)
return;
}
fs->DeleteFiles(index);
} else if (action == 1) {
if (fs->GetFileType() == PrinterFileSystem::F_MODEL) {
if (index != -1) {
auto dlg = new MediaProgressDialog(_L("Print"), this, [fs] { fs->FetchModelCancel(); });
dlg->Update(0, _L("Fetching model infomations ..."));
fs->FetchModel(index, [this, fs, dlg, index](int result, std::string const &data) {
dlg->Destroy();
if (result == PrinterFileSystem::ERROR_CANCEL)
return;
if (result != 0) {
MessageDialog(this,
_L("Failed to fetching model infomations from printer."),
_L("Error"), wxOK).ShowModal();
return;
}
Slic3r::DynamicPrintConfig config;
Slic3r::Model model;
Slic3r::PlateDataPtrs plate_data_list;
Slic3r::Semver file_version;
std::istringstream is(data);
if (!Slic3r::load_gcode_3mf_from_stream(is, &config, &model, &plate_data_list, &file_version)
|| plate_data_list.empty()) {
MessageDialog(this,
_L("Failed to parse model infomations."),
_L("Error"), wxOK).ShowModal();
return;
}
auto &file = fs->GetFile(index);
int gcode_file_count = Slic3r::GUI::wxGetApp().plater()->update_print_required_data(config, model, plate_data_list, from_u8(file.name).ToStdString(), file.path);
if (gcode_file_count > 0) {
wxPostEvent(Slic3r::GUI::wxGetApp().plater(), SimpleEvent(EVT_PRINT_FROM_SDCARD_VIEW));
}
else {
MessageDialog dlg(this, _L("The .gcode.3mf file contains no G-code data.Please slice it whthBambu Studio and export a new .gcode.3mf file."), wxEmptyString, wxICON_WARNING | wxOK);
auto res = dlg.ShowModal();
}
});
return;
}
}
if (index != -1) {
auto &file = fs->GetFile(index);
if (file.IsDownload() && file.DownloadProgress() >= -1) {
if (!file.local_path.empty()) {
if (!fs->DownloadCheckFile(index)) {
MessageDialog(this,
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
_L("Error"), wxOK).ShowModal();
Refresh();
return;
}
#ifdef __WXMSW__
auto wfile = boost::filesystem::path(file.local_path).wstring();
SHELLEXECUTEINFO info{sizeof(info), 0, NULL, NULL, wfile.c_str(), L"", SW_HIDE};
::ShellExecuteEx(&info);
#else
wxShell("open " + file.local_path);
#endif
} else {
fs->DownloadCancel(index);
}
return;
}
}
fs->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
} else if (action == 2) {
if (index != -1) {
auto &file = fs->GetFile(index);
if (file.IsDownload() && file.DownloadProgress() >= -1) {
if (!file.local_path.empty()) {
if (!fs->DownloadCheckFile(index)) {
MessageDialog(this,
wxString::Format(_L("File '%s' was lost! Please download it again."), from_u8(file.name)),
_L("Error"), wxOK).ShowModal();
Refresh();
return;
}
desktop_open_any_folder(file.local_path);
} else if (fs->GetFileType() == PrinterFileSystem::F_MODEL) {
fs->DownloadCancel(index);
}
return;
}
}
fs->DownloadFiles(index, wxGetApp().app_config->get("download_path"));
}
}
MediaFileFrame::MediaFileFrame(wxWindow* parent)
: DPIFrame(parent, wxID_ANY, "Media Files", wxDefaultPosition, { 1600, 900 })
{

View file

@ -36,6 +36,8 @@ public:
void SetMachineObject(MachineObject * obj);
void SwitchStorage(bool external);
public:
void Rescale();
@ -46,6 +48,8 @@ private:
void fetchUrl(boost::weak_ptr<PrinterFileSystem> fs);
void doAction(size_t index, int action);
private:
ScalableBitmap m_bmp_loading;
ScalableBitmap m_bmp_failed;
@ -59,25 +63,31 @@ private:
::StaticBox * m_type_panel = nullptr;
::Button * m_button_video = nullptr;
::Button * m_button_timelapse = nullptr;
::Button * m_button_timelapse = nullptr;
::Button * m_button_model = nullptr;
::StaticBox *m_manage_panel = nullptr;
::Button * m_button_delete = nullptr;
::Button *m_button_download = nullptr;
::Button *m_button_management = nullptr;
ImageGrid * m_image_grid = nullptr;
bool m_external = true;
std::string m_machine;
std::string m_lan_ip;
std::string m_lan_user;
std::string m_lan_passwd;
bool m_supported = false;
bool m_lan_mode = false;
bool m_tutk_support = false;
ImageGrid * m_image_grid = nullptr;
bool m_local_support = false;
bool m_remote_support = false;
bool m_waiting_enable = false;
int m_last_mode = 0;
int m_last_type = 0;
std::set<int> m_last_errors;
};

View file

@ -32,7 +32,7 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w
m_button_play->SetCanFocus(false);
m_label_status = new Label(this, "");
m_label_status->SetForegroundColour(wxColour("#2C2C2E"));
m_label_status->SetForegroundColour(wxColour("#323A3C"));
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) { m_media_ctrl->Play(); });
@ -78,28 +78,35 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
{
std::string machine = obj ? obj->dev_id : "";
if (obj && obj->is_function_supported(PrinterFunction::FUNC_CAMERA_VIDEO)) {
m_camera_exists = obj->has_ipcam;
m_lan_mode = obj->is_lan_mode_printer();
m_lan_ip = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->dev_ip : "";
m_lan_passwd = obj->is_function_supported(PrinterFunction::FUNC_LOCAL_TUNNEL) ? obj->get_access_code() : "";
m_tutk_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
m_device_busy = obj->is_in_prepare() || obj->is_in_upgrading();
m_camera_exists = obj->has_ipcam;
m_lan_mode = obj->is_lan_mode_printer();
m_lan_proto = obj->get_local_camera_proto();
m_lan_ip = obj->dev_ip;
m_lan_passwd = obj->get_access_code();
m_remote_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
m_device_busy = obj->is_camera_busy_off();
m_tutk_state = obj->tutk_state;
} else {
m_camera_exists = false;
m_lan_mode = false;
m_lan_proto = -1;
m_lan_ip.clear();
m_lan_passwd.clear();
m_tutk_support = true;
m_tutk_state.clear();
m_remote_support = true;
m_device_busy = false;
}
if (machine == m_machine) {
if (m_last_state == MEDIASTATE_IDLE)
if (m_last_state == MEDIASTATE_IDLE && IsEnabled())
Play();
return;
}
m_machine = machine;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
m_disable_lan = false;
m_failed_retry = 0;
m_last_failed_codes.clear();
m_last_user_play = wxDateTime::Now();
std::string stream_url;
if (get_stream_url(&stream_url)) {
m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
@ -107,9 +114,9 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
m_streaming = false;
}
if (m_last_state != MEDIASTATE_IDLE)
Stop();
Stop(" ");
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2 * m_failed_retry);
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
else
SetStatus("", false);
}
@ -128,22 +135,36 @@ void MediaPlayCtrl::Play()
Stop(_L("Initialize failed (No Device)!"));
return;
}
if (!IsEnabled()) {
Stop(_L("Initialize failed (Device connection not ready)!"));
return;
}
if (!m_camera_exists) {
Stop(_L("Initialize failed (No Camera Device)!"));
return;
}
if (m_device_busy) {
Stop(_L("Printer is busy downloading, Please wait for the downloading to finish."));
m_failed_retry = 0;
return;
}
m_last_state = MEDIASTATE_INITIALIZING;
m_button_play->SetIcon("media_stop");
SetStatus(_L("Initializing..."));
NetworkAgent *agent = wxGetApp().getAgent();
std::string agent_version = agent ? agent->get_version() : "";
if (!m_lan_ip.empty() && (!m_lan_mode || !m_lan_passwd.empty()) && !m_device_busy) {
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + "&device=" + m_machine + "&version=" + agent_version;
if (m_lan_proto > 0 && (m_lan_mode ||!m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
m_disable_lan = m_remote_support && !m_lan_mode; // try remote next time
if (m_lan_proto == 1)
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + "&device=" + m_machine + "&version=" + agent_version;
else if (m_lan_proto == 2)
m_url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
else if (m_lan_proto == 3)
m_url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl camera_url: " << m_url;
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("dump_video") == "true") {
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
std::string file_h264 = data_dir() + "/video.h264";
std::string file_info = data_dir() + "/video.info";
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
@ -159,27 +180,27 @@ void MediaPlayCtrl::Play()
return;
}
m_disable_lan = false;
if (m_lan_ip.empty())
m_failed_code = -1;
if (m_lan_mode) {
m_failed_code = 1;
Stop(m_lan_passwd.empty()
? _L("Initialize failed (Not supported with LAN-only mode)!")
: _L("Initialize failed (Not accessible in LAN-only mode)!"));
Stop(m_lan_proto < 0
? _L("Initialize failed (Not supported on the current printer version)!")
: _L("Initialize failed (Not accessible in LAN-only mode)!"));
return;
}
if (!m_tutk_support) { // not support tutk
if (m_device_busy) {
Stop(_L("Printer is busy downloading, Please wait for the downloading to finish."));
m_failed_retry = 0;
return;
}
m_failed_code = 1;
if (!m_remote_support) { // not support tutk
Stop(m_lan_ip.empty()
? _L("Initialize failed (Missing LAN ip of printer)!")
: _L("Initialize failed (Not supported by printer)!"));
: _L("Initialize failed (Not supported on the current printer version)!"));
return;
}
m_failed_code = 0;
SetStatus(_L("Initializing..."));
if (agent) {
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent_version](std::string url) {
if (boost::algorithm::starts_with(url, "bambu:///")) {
@ -188,7 +209,10 @@ void MediaPlayCtrl::Play()
}
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl camera_url: " << url << ", machine: " << m_machine;
CallAfter([this, m, url] {
if (m != m_machine) return;
if (m != m_machine) {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
return;
}
m_url = url;
if (m_last_state == MEDIASTATE_INITIALIZING) {
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
@ -197,7 +221,7 @@ void MediaPlayCtrl::Play()
} else {
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("dump_video") == "true") {
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << boost::filesystem::current_path();
m_url = m_url + "&dump=video.h264";
}
@ -215,7 +239,7 @@ void MediaPlayCtrl::Play()
void MediaPlayCtrl::Stop(wxString const &msg)
{
bool init_failed = m_last_state != wxMEDIASTATE_PLAYING;
int last_state = m_last_state;
if (m_last_state != MEDIASTATE_IDLE) {
m_media_ctrl->InvalidateBestSize();
@ -238,27 +262,40 @@ void MediaPlayCtrl::Stop(wxString const &msg)
m_failed_code = 0;
}
if (init_failed && m_failed_code != 0 && m_last_failed_code != m_failed_code) {
if (last_state != wxMEDIASTATE_PLAYING && m_failed_code != 0
&& m_last_failed_codes.find(m_failed_code) == m_last_failed_codes.end()
&& (m_user_triggered || m_failed_retry > 3)) {
json j;
j["stage"] = std::to_string(m_last_state);
j["stage"] = last_state;
j["dev_id"] = m_machine;
j["dev_ip"] = m_lan_ip;
j["result"] = "failed";
j["user_triggered"] = m_user_triggered;
j["failed_retry"] = m_failed_retry;
bool remote = m_url.find("/local/") == wxString::npos;
j["tunnel"] = remote ? "remote" : "local";
j["code"] = m_failed_code;
if (remote)
j["tutk_state"] = m_tutk_state;
j["msg"] = into_u8(msg);
NetworkAgent *agent = wxGetApp().getAgent();
if (agent)
agent->track_event("start_liveview", j.dump());
m_last_failed_codes.insert(m_failed_code);
}
m_last_failed_code = m_failed_code;
m_url.clear();
++m_failed_retry;
if (m_failed_code != 0 && (m_failed_retry > 1 || m_user_triggered)) {
if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && (!m_remote_support || m_lan_mode) && (m_failed_retry > 1 || m_user_triggered)) {
m_next_retry = wxDateTime(); // stop retry
if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to start liveview)"))) {
m_failed_retry = 0;
m_user_triggered = true;
m_last_failed_code = 0;
if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
m_last_failed_codes.clear();
m_last_user_play = wxDateTime::Now();
}
m_next_retry = wxDateTime::Now();
return;
}
@ -270,14 +307,18 @@ void MediaPlayCtrl::Stop(wxString const &msg)
void MediaPlayCtrl::TogglePlay()
{
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::TogglePlay";
if (m_last_state != MEDIASTATE_IDLE) {
m_next_retry = wxDateTime();
Stop();
} else {
m_failed_retry = 0;
m_user_triggered = true;
m_last_failed_code = 0;
m_next_retry = wxDateTime::Now();
if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
m_last_failed_codes.clear();
m_last_user_play = wxDateTime::Now();
}
m_next_retry = wxDateTime::Now();
Play();
}
}
@ -330,7 +371,7 @@ void MediaPlayCtrl::ToggleStream()
}
}
if (!url.empty() && wxGetApp().app_config->get("not_show_vcamera_stop_prev") != "1") {
MessageDialog dlg(this->GetParent(), _L("Another virtual camera is running.\nOrca Slicer supports only a single virtual camera.\nDo you want to stop this virtual camera?"), _L("Warning"),
MessageDialog dlg(this->GetParent(), _L("Another virtual camera is running.\nBambu Studio supports only a single virtual camera.\nDo you want to stop this virtual camera?"), _L("Warning"),
wxYES | wxCANCEL | wxICON_INFORMATION);
dlg.show_dsa_button();
auto res = dlg.ShowModal();
@ -387,7 +428,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
wxSize size = m_media_ctrl->GetVideoSize();
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
m_failed_code = m_media_ctrl->GetLastError();
if (size.GetWidth() > 1000) {
if (size.GetWidth() >= 320) {
m_last_state = state;
SetStatus(_L("Playing..."), false);
@ -404,6 +445,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
m_failed_retry = 0;
m_failed_code = 0;
m_disable_lan = false;
boost::unique_lock lock(m_mutex);
m_tasks.push_back("<play>");
m_cond.notify_all();
@ -443,6 +485,8 @@ void MediaPlayCtrl::on_show_hide(wxShowEvent &evt)
evt.Skip();
if (m_isBeingDeleted) return;
m_failed_retry = 0;
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid quick play/stop
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
IsShownOnScreen() ? Play() : Stop();
}
@ -454,6 +498,12 @@ void MediaPlayCtrl::media_proc()
m_cond.wait(lock);
}
wxString url = m_tasks.front();
if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "<stop>") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: busy skip url" << url;
m_tasks.pop_front();
m_tasks.pop_front();
continue;
}
lock.unlock();
if (url.IsEmpty()) {
break;

View file

@ -16,6 +16,7 @@
#include <boost/thread/condition_variable.hpp>
#include <deque>
#include <set>
class Button;
class Label;
@ -68,13 +69,16 @@ private:
wxMediaCtrl2 * m_media_ctrl;
wxMediaState m_last_state = MEDIASTATE_IDLE;
std::string m_machine;
int m_lan_proto = 0;
std::string m_lan_ip;
std::string m_lan_user;
std::string m_lan_passwd;
std::string m_tutk_state;
bool m_camera_exists = false;
bool m_lan_mode = false;
bool m_tutk_support = false;
bool m_remote_support = false;
bool m_device_busy = false;
bool m_disable_lan = false;
wxString m_url;
std::deque<wxString> m_tasks;
@ -86,8 +90,9 @@ private:
bool m_user_triggered = false;
int m_failed_retry = 0;
int m_failed_code = 0;
int m_last_failed_code = 0;
wxDateTime m_next_retry;
std::set<int> m_last_failed_codes;
wxDateTime m_last_user_play;
wxDateTime m_next_retry;
::Button *m_button_play;
::Label * m_label_status;

View file

@ -112,7 +112,7 @@ AddMachinePanel::~AddMachinePanel() {
init_timer();
m_side_tools->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MonitorPanel::on_printer_clicked), NULL, this);
m_side_tools->get_panel()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MonitorPanel::on_printer_clicked), NULL, this);
Bind(wxEVT_TIMER, &MonitorPanel::on_timer, this);
Bind(wxEVT_SIZE, &MonitorPanel::on_size, this);
@ -125,7 +125,7 @@ AddMachinePanel::~AddMachinePanel() {
MonitorPanel::~MonitorPanel()
{
m_side_tools->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MonitorPanel::on_printer_clicked), NULL, this);
m_side_tools->get_panel()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(MonitorPanel::on_printer_clicked), NULL, this);
if (m_refresh_timer)
m_refresh_timer->Stop();
@ -153,59 +153,33 @@ MonitorPanel::~MonitorPanel()
if (!dev) return;
MachineObject *obj_ = dev->get_selected_machine();
if (obj_)
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_);
}
void MonitorPanel::init_tabpanel()
{
m_side_tools = new SideTools(this, wxID_ANY);
wxBoxSizer* sizer_side_tools = new wxBoxSizer(wxVERTICAL);
/* auto warning_panel = new wxPanel(this, wxID_ANY);
warning_panel->SetBackgroundColour(wxColour(255, 111, 0));
warning_panel->SetSize(wxSize(FromDIP(220), FromDIP(25)));
warning_panel->SetMinSize(wxSize(FromDIP(220), FromDIP(25)));
warning_panel->SetMaxSize(wxSize(FromDIP(220), FromDIP(25)));
sizer_side_tools->Add(warning_panel, 0, wxEXPAND, 0);
wxBoxSizer *sizer_boxh = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *sizer_boxv = new wxBoxSizer(wxHORIZONTAL);*/
m_connection_info = new Button(this, "Failed to connect to the printer");
m_connection_info->SetBackgroundColor(wxColour(255, 111, 0));
m_connection_info->SetBorderColor(wxColour(255, 111, 0));
m_connection_info->SetTextColor(*wxWHITE);
m_connection_info->SetFont(::Label::Body_13);
m_connection_info->SetCornerRadius(0);
m_connection_info->SetSize(wxSize(FromDIP(-1), FromDIP(25)));
m_connection_info->SetMinSize(wxSize(FromDIP(-1), FromDIP(25)));
m_connection_info->SetMaxSize(wxSize(FromDIP(-1), FromDIP(25)));
wxBoxSizer* connection_sizer = new wxBoxSizer(wxVERTICAL);
m_hyperlink = new wxHyperlinkCtrl(m_connection_info, wxID_ANY, _L("Failed to connect to the server"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
connection_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_hyperlink->SetBackgroundColour(wxColour(255, 111, 0));
m_connection_info->SetSizer(connection_sizer);
m_connection_info->Layout();
connection_sizer->Fit(m_connection_info);
m_connection_info->Hide();
sizer_side_tools->Add(m_connection_info, 0, wxEXPAND, 0);
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(wxColour("#FEFFFF"));
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {
;
});
auto page = m_tabpanel->GetCurrentPage();
if (page == m_media_file_panel) {
auto title = m_tabpanel->GetPageText(m_tabpanel->GetSelection());
m_media_file_panel->SwitchStorage(title == _L("SD Card"));
}
page->SetFocus();
}, m_tabpanel->GetId());
//m_status_add_machine_panel = new AddMachinePanel(m_tabpanel);
m_status_info_panel = new StatusPanel(m_tabpanel);
m_tabpanel->AddPage(m_status_info_panel, _L("Status"), "", true);
m_media_file_panel = new MediaFilePanel(m_tabpanel);
m_tabpanel->AddPage(m_media_file_panel, _L("Media"), "", false);
m_tabpanel->AddPage(m_media_file_panel, _L("SD Card"), "", false);
//m_tabpanel->AddPage(m_media_file_panel, _L("Internal Storage"), "", false);
m_upgrade_panel = new UpgradePanel(m_tabpanel);
m_tabpanel->AddPage(m_upgrade_panel, _L("Update"), "", false);
@ -249,6 +223,7 @@ void MonitorPanel::on_sys_color_changed()
{
m_status_info_panel->on_sys_color_changed();
m_upgrade_panel->on_sys_color_changed();
m_media_file_panel->Rescale();
}
void MonitorPanel::msw_rescale()
@ -257,7 +232,6 @@ void MonitorPanel::msw_rescale()
/* side_tool rescale */
m_side_tools->msw_rescale();
m_tabpanel->Rescale();
//m_status_add_machine_panel->msw_rescale();
m_status_info_panel->msw_rescale();
@ -265,11 +239,6 @@ void MonitorPanel::msw_rescale()
m_upgrade_panel->msw_rescale();
m_hms_panel->msw_rescale();
m_connection_info->SetCornerRadius(0);
m_connection_info->SetSize(wxSize(FromDIP(220), FromDIP(25)));
m_connection_info->SetMinSize(wxSize(FromDIP(220), FromDIP(25)));
m_connection_info->SetMaxSize(wxSize(FromDIP(220), FromDIP(25)));
Layout();
Refresh();
}
@ -305,11 +274,12 @@ void MonitorPanel::on_update_all(wxMouseEvent &event)
return;
set_default();
m_status_info_panel->set_print_finish_status(false);
update_all();
MachineObject *obj_ = dev->get_selected_machine();
if (obj_)
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_);
Layout();
Refresh();
@ -342,41 +312,6 @@ void MonitorPanel::on_size(wxSizeEvent &event)
Refresh();
}
void MonitorPanel::update_status(MachineObject* obj)
{
if (!obj) return;
/* Update Device Info */
m_side_tools->set_current_printer_name(obj->dev_name);
// update wifi signal image
int wifi_signal_val = 0;
if (!obj->is_connected() || obj->is_connecting()) {
m_side_tools->set_current_printer_signal(WifiSignal::NONE);
} else {
if (!obj->wifi_signal.empty() && boost::ends_with(obj->wifi_signal, "dBm")) {
try {
wifi_signal_val = std::stoi(obj->wifi_signal.substr(0, obj->wifi_signal.size() - 3));
}
catch (...) {
;
}
if (wifi_signal_val > -45) {
m_side_tools->set_current_printer_signal(WifiSignal::STRONG);
}
else if (wifi_signal_val <= -45 && wifi_signal_val >= -60) {
m_side_tools->set_current_printer_signal(WifiSignal::MIDDLE);
}
else {
m_side_tools->set_current_printer_signal(WifiSignal::WEAK);
}
}
else {
m_side_tools->set_current_printer_signal(WifiSignal::MIDDLE);
}
}
}
void MonitorPanel::update_all()
{
NetworkAgent* m_agent = wxGetApp().getAgent();
@ -414,13 +349,10 @@ void MonitorPanel::update_all()
}
m_status_info_panel->obj = obj;
m_upgrade_panel->update(obj);
m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj);
m_upgrade_panel->update(obj);
m_media_file_panel->SetMachineObject(obj);
update_status(obj);
m_side_tools->update_status(obj);
if (!obj) {
show_status((int)MONITOR_NO_PRINTER);
@ -452,6 +384,7 @@ void MonitorPanel::update_all()
if (m_hms_panel->IsShown()) {
m_hms_panel->update(obj);
}
#if !BBL_RELEASE_TO_PUBLIC
if (m_upgrade_panel->IsShown()) {
m_upgrade_panel->update(obj);
@ -480,7 +413,7 @@ bool MonitorPanel::Show(bool show)
dev->load_last_machine();
obj = dev->get_selected_machine();
if (obj)
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj->amsList);
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
} else {
obj->reset_update_time();
}
@ -511,10 +444,7 @@ void MonitorPanel::update_side_panel()
void MonitorPanel::show_status(int status)
{
if (!m_initialized) return;
if (last_status == status)
return;
if (last_status == status)return;
if (last_status & (int)MonitorStatus::MONITOR_CONNECTING != 0) {
NetworkAgent* agent = wxGetApp().getAgent();
json j;
@ -536,64 +466,38 @@ void MonitorPanel::show_status(int status)
BOOST_LOG_TRIVIAL(info) << "monitor: show_status = " << status;
if (((status & (int) MonitorStatus::MONITOR_DISCONNECTED) != 0) || ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)) {
if ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER))
m_hyperlink->SetLabel(_L("Failed to connect to the server"));
//m_connection_info->SetLabel(_L("Failed to connect to the server"));
else
m_hyperlink->SetLabel(_L("Failed to connect to the printer"));
//m_connection_info->SetLabel(_L("Failed to connect to the printer"));
m_hyperlink->Show();
m_connection_info->SetLabel(wxEmptyString);
m_connection_info->Show();
m_connection_info->SetBackgroundColor(wxColour(255, 111, 0));
m_connection_info->SetBorderColor(wxColour(255, 111, 0));
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(nullptr);
m_upgrade_panel->update(nullptr);
#endif
} else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
m_connection_info->Hide();
} else if ((status & (int) MonitorStatus::MONITOR_CONNECTING) != 0) {
m_hyperlink->Hide();
m_connection_info->SetLabel(_L("Connecting..."));
m_connection_info->SetBackgroundColor(wxColour(0, 150, 136));
m_connection_info->SetBorderColor(wxColour(0, 150, 136));
m_connection_info->Show();
}
Freeze();
Freeze();
// update panels
if (m_side_tools) { m_side_tools->show_status(status); };
m_status_info_panel->show_status(status);
m_hms_panel->show_status(status);
m_upgrade_panel->show_status(status);
m_media_file_panel->Enable(status == MonitorStatus::MONITOR_NORMAL);
if ((status & (int)MonitorStatus::MONITOR_NO_PRINTER) != 0) {
set_default();
m_side_tools->set_none_printer_mode();
m_connection_info->Hide();
m_tabpanel->Refresh();
m_tabpanel->Layout();
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(nullptr);
#endif
} 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)) {
m_side_tools->set_current_printer_signal(WifiSignal::NONE);
} 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->Refresh();
m_tabpanel->Layout();
}
Layout();
Thaw();
Thaw();
}
} // GUI

View file

@ -83,8 +83,6 @@ private:
MediaFilePanel* m_media_file_panel;
UpgradePanel* m_upgrade_panel;
HMSPanel* m_hms_panel;
Button * m_connection_info{nullptr};
wxHyperlinkCtrl* m_hyperlink{nullptr};
/* side tools */
SideTools* m_side_tools{nullptr};
@ -93,8 +91,6 @@ private:
wxStaticText* m_staticText_printer_name;
wxStaticBitmap* m_bitmap_wifi_signal;
wxBoxSizer * m_side_tools_sizer;
SelectMachinePopup m_select_machine;
/* images */
@ -106,9 +102,9 @@ private:
wxBitmap m_arrow_img;
int last_wifi_signal = -1;
wxTimer* m_refresh_timer = nullptr;
int last_status;
bool m_initialized { false };
wxTimer* m_refresh_timer = nullptr;
public:
MonitorPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
@ -133,6 +129,7 @@ public:
void on_sys_color_changed();
void msw_rescale();
StatusPanel* get_status_panel() {return m_status_info_panel;};
void select_machine(std::string machine_sn);
void on_update_all(wxMouseEvent &event);
void on_timer(wxTimerEvent& event);
@ -141,7 +138,6 @@ public:
void on_size(wxSizeEvent &event);
/* update apis */
void update_status(MachineObject* obj);
//void update_ams(MachineObject* obj);
void update_all();
@ -154,6 +150,7 @@ public:
std::string last_conn_type = "undedefined";
};
} // GUI
} // Slic3r

View file

@ -91,7 +91,7 @@ void MsgDialog::show_dsa_button(wxString const &title)
m_text_dsa->SetFont(::Label::Body_13);
m_text_dsa->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3D")));
btn_sizer->Layout();
//Fit();
Fit();
}
bool MsgDialog::get_checkbox_state()
@ -316,7 +316,7 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin
// Code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
msg_escaped = std::string("<pre><code>") + msg_escaped + "</code></pre>";
html->SetPage("<html><body bgcolor=\"" + bgr_clr_str + "\"><font color=\"" + text_clr_str + "\">" + wxString::FromUTF8(msg_escaped.data()) + "</font></body></html>");
content_sizer->Add(html, 1, wxEXPAND);
content_sizer->Add(html, 1, wxEXPAND|wxRIGHT, 8);
wxGetApp().UpdateDarkUIWin(html);
}

View file

@ -30,7 +30,6 @@ public:
wxString GetPageText(size_t n) const;
private:
wxWindow* m_parent;
wxFlexGridSizer* m_buttons_sizer;
wxBoxSizer* m_sizer;
// BBS: use Button
@ -398,9 +397,6 @@ private:
unsigned m_showTimeout,
m_hideTimeout;
ButtonsListCtrl* m_ctrl{ nullptr };
};
//#endif // _WIN32
#endif // slic3r_Notebook_hpp_

View file

@ -351,8 +351,6 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
wxString tooltip;
std::string markdowntip;
wxString language = wxGetApp().app_config->get("language");
// BBS: markdown tip
CtrlLine* focusedLine = nullptr;
// BBS
@ -496,7 +494,7 @@ bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode)
// BBS: call by Tab/Page
void OG_CustomCtrl::fixup_items_positions()
{
if (GetParent() == nullptr || GetPosition().y < GetParent()->GetSize().y)
if (GetParent() == nullptr || GetPosition().y + GetSize().y < GetParent()->GetSize().y)
return;
for (CtrlLine& line : ctrl_lines) {
line.correct_items_positions();
@ -826,7 +824,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos)
draw_buttons(field);
// update width for full_width fields
if (option_set.front().opt.full_width && field && field->getWindow())
field->getWindow()->SetSize(ctrl->GetSize().x - h_pos2 + h_pos3 - h_pos, -1);
field->getWindow()->SetSize(ctrl->GetSize().x - h_pos2 + h_pos3 - h_pos - ctrl->m_em_unit * 3, -1);
return;
}

View file

@ -328,7 +328,14 @@ bool ObjectDataViewModelNode::SetValue(const wxVariant& variant, unsigned col)
return false;
}
void ObjectDataViewModelNode::SetIdx(const int& idx)
void ObjectDataViewModelNode::SetName(const wxString &tempName)
{
if (m_name != tempName) {
m_name = tempName;
}
}
void ObjectDataViewModelNode::SetIdx(const int &idx)
{
m_idx = idx;
// update name if this node is instance
@ -368,6 +375,10 @@ void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= "
m_extruder_bmp = *get_default_extruder_color_icon();
return;
}
else if (m_type & itLayer) {
m_extruder_bmp = *get_default_extruder_color_icon();
return;
}
else {
m_extruder_bmp = wxNullBitmap;
return;
@ -447,11 +458,14 @@ wxBitmap& ObjectDataViewModel::GetWarningBitmap(const std::string& warning_icon_
wxDataViewItem ObjectDataViewModel::AddPlate(PartPlate* part_plate, wxString name, bool refresh)
{
int plate_idx = part_plate ? part_plate->get_index() : -1;
wxString plate_name = name;
if (plate_name == "") {
int plate_idx = part_plate ? part_plate->get_index() : -1;
wxString plate_name;
if (name.empty()) {
plate_name = _L("Plate");
plate_name << " " << plate_idx + 1;
plate_name += wxString::Format(" %d", plate_idx + 1);
if (!part_plate->get_plate_name().empty()) {
plate_name += wxString(" (", wxConvUTF8) + from_u8(part_plate->get_plate_name()) + wxString(")", wxConvUTF8);
}
}
auto plate_node = new ObjectDataViewModelNode(part_plate, plate_name);
@ -469,7 +483,7 @@ wxDataViewItem ObjectDataViewModel::AddPlate(PartPlate* part_plate, wxString nam
if (!is_added) {
m_plates.push_back(plate_node);
}
wxDataViewItem plate_item(plate_node);
if (refresh) {
ItemAdded(wxDataViewItem(nullptr), plate_item);
@ -1241,6 +1255,19 @@ wxDataViewItem ObjectDataViewModel::GetItemByPlateId(int plate_idx)
return wxDataViewItem(nullptr);
}
void ObjectDataViewModel::SetCurSelectedPlateFullName(int plate_idx, const std::string & custom_name) {
for (auto plate : m_plates) {
if (plate->m_plate_idx == plate_idx) {
wxString plate_full_name =_L("Plate");
plate_full_name += wxString::Format(" %d", plate_idx + 1);
if (!custom_name.empty()) {
plate_full_name += wxString(" (", wxConvUTF8) + from_u8(custom_name) + wxString(")", wxConvUTF8);
}
plate->SetName(plate_full_name);
}
}
}
wxDataViewItem ObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx)
{
if (size_t(obj_idx) >= m_objects.size()) {
@ -1950,10 +1977,19 @@ bool ObjectDataViewModel::HasInfoItem(InfoItemType type) const
}
ItemType ObjectDataViewModel::GetItemType(const wxDataViewItem &item) const
{
if (!item.IsOk())
return itUndef;
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode *>(item.GetID());
return node->m_type < 0 ? itUndef : node->m_type;
}
ItemType ObjectDataViewModel::GetItemType(const wxDataViewItem &item, int &plate_idx) const
{
if (!item.IsOk())
return itUndef;
ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(item.GetID());
plate_idx=node->m_plate_idx;
return node->m_type < 0 ? itUndef : node->m_type;
}

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