From 661b112a6870d12892423a3a77555af3eeaaddc3 Mon Sep 17 00:00:00 2001 From: QIDI TECH <893239786@qq.com> Date: Mon, 4 Aug 2025 16:30:53 +0800 Subject: [PATCH] update slic3r --- .gitignore | 6 + BuildMac.sh | 244 + CMakeLists.txt | 15 +- Dockerfile | 2 +- qdt/i18n/QIDIStudio.pot | 2 +- qdt/i18n/cs/QIDIStudio_cs.po | 15 +- qdt/i18n/de/QIDIStudio_de.po | 15 +- qdt/i18n/en/QIDIStudio_en.po | 11 +- qdt/i18n/es/QIDIStudio_es.po | 15 +- qdt/i18n/fr/QIDIStudio_fr.po | 15 +- qdt/i18n/hu/QIDIStudio_hu.po | 15 +- qdt/i18n/it/QIDIStudio_it.po | 15 +- qdt/i18n/ja/QIDIStudio_ja.po | 15 +- qdt/i18n/ko/QIDIStudio_ko.po | 15 +- qdt/i18n/nl/QIDIStudio_nl.po | 15 +- qdt/i18n/pl/QIDIStudio_pl.po | 15 +- qdt/i18n/pt-BR/QIDIStudio_pt-BR.po | 15 +- qdt/i18n/ru/QIDIStudio_ru.po | 15 +- qdt/i18n/sv/QIDIStudio_sv.po | 15 +- qdt/i18n/tr/QIDIStudio_tr.po | 15 +- qdt/i18n/uk/QIDIStudio_uk.po | 15 +- qdt/i18n/zh_cn/QIDIStudio_zh_CN.po | 15 +- resources/i18n/cs/QIDIStudio.mo | Bin 263759 -> 264293 bytes resources/i18n/de/QIDIStudio.mo | Bin 530114 -> 530684 bytes resources/i18n/es/QIDIStudio.mo | Bin 516954 -> 517611 bytes resources/i18n/fr/QIDIStudio.mo | Bin 525756 -> 526284 bytes resources/i18n/hu/QIDIStudio.mo | Bin 515450 -> 515982 bytes resources/i18n/it/QIDIStudio.mo | Bin 518674 -> 519208 bytes resources/i18n/ja/QIDIStudio.mo | Bin 561477 -> 562014 bytes resources/i18n/ko/QIDIStudio.mo | Bin 516957 -> 517464 bytes resources/i18n/nl/QIDIStudio.mo | Bin 504561 -> 505193 bytes resources/i18n/pl/QIDIStudio.mo | Bin 512726 -> 513216 bytes resources/i18n/pt-BR/QIDIStudio.mo | Bin 495872 -> 496406 bytes resources/i18n/pt_br/QIDIStudio.mo | Bin 495872 -> 496406 bytes resources/i18n/ru/QIDIStudio.mo | Bin 653702 -> 654422 bytes resources/i18n/sv/QIDIStudio.mo | Bin 502105 -> 502662 bytes resources/i18n/tr/QIDIStudio.mo | Bin 501757 -> 502269 bytes resources/i18n/uk/QIDIStudio.mo | Bin 548956 -> 549652 bytes resources/i18n/zh_cn/QIDIStudio.mo | Bin 453403 -> 453879 bytes resources/images/canvas_drag.svg | 3 + resources/images/canvas_drag_active.svg | 3 + resources/images/canvas_zoom_in.svg | 3 + resources/images/canvas_zoom_in_disable.svg | 3 + resources/images/canvas_zoom_out.svg | 3 + resources/images/canvas_zoom_out_disable.svg | 3 + resources/images/delete2.svg | 1 + resources/images/menu_export_toolpaths.svg | 3 + resources/images/more.svg | 6 + resources/images/more_dark.svg | 6 + resources/images/partskip_retry.svg | 26 + resources/images/preset_empty.svg | 19 + resources/images/preset_empty_dark.svg | 19 + resources/images/print_control_partskip.svg | 4 + .../images/print_control_partskip_disable.svg | 4 + .../images/print_control_partskip_hover.svg | 4 + resources/images/toolbar_fuzzyskin.svg | 13 + resources/images/toolbar_fuzzyskin_dark.svg | 14 + .../Q Series/filament/Generic TPU 95A.json | 2 + .../Q Series/filament/QIDI TPU 95A-HF.json | 2 + .../X 3 Series/filament/Generic TPU 95A.json | 2 + .../X 3 Series/filament/QIDI TPU 95A-HF.json | 2 + .../X 4 Series/filament/Generic TPU 95A.json | 2 + .../X 4 Series/filament/QIDI TPU 95A-HF.json | 2 + resources/web/filament/index.html | 76 +- src/QIDIStudio.cpp | 70 +- src/earcut/CHANGELOG.md | 27 + src/earcut/CMakeLists.txt | 151 + src/earcut/LICENSE | 15 + src/earcut/README.md | 131 + src/earcut/earcut.hpp | 814 +++ src/libslic3r/GCode/GCodeProcessor.cpp | 8 +- src/slic3r/CMakeLists.txt | 27 + src/slic3r/GUI/3DBed.cpp | 17 +- src/slic3r/GUI/3DScene.cpp | 8 +- src/slic3r/GUI/3DScene.hpp | 20 +- src/slic3r/GUI/AMSMaterialsSetting.cpp | 46 +- src/slic3r/GUI/AMSMaterialsSetting.hpp | 2 +- src/slic3r/GUI/AmsMappingPopup.cpp | 37 +- src/slic3r/GUI/BonjourDialog.cpp | 2 + src/slic3r/GUI/Calibration.cpp | 9 +- src/slic3r/GUI/CalibrationWizard.cpp | 4 +- src/slic3r/GUI/CalibrationWizardPage.cpp | 1 + src/slic3r/GUI/CalibrationWizardPage.hpp | 3 - .../GUI/CalibrationWizardPresetPage.cpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 46 +- src/slic3r/GUI/CreatePresetsDialog.cpp | 22 +- src/slic3r/GUI/DeviceManager.cpp | 787 +-- src/slic3r/GUI/DeviceManager.hpp | 103 +- .../GUI/DeviceTab/uiAmsHumidityPopup.cpp | 18 +- src/slic3r/GUI/EncodedFilament.cpp | 217 + src/slic3r/GUI/EncodedFilament.hpp | 227 + src/slic3r/GUI/Field.cpp | 11 +- src/slic3r/GUI/FilamentBitmapUtils.cpp | 184 + src/slic3r/GUI/FilamentBitmapUtils.hpp | 26 + src/slic3r/GUI/FilamentMapDialog.cpp | 4 +- src/slic3r/GUI/FilamentPickerDialog.cpp | 733 +++ src/slic3r/GUI/FilamentPickerDialog.hpp | 97 + src/slic3r/GUI/GCodeViewer.cpp | 82 +- src/slic3r/GUI/GLCanvas3D.cpp | 1370 +++--- src/slic3r/GUI/GLCanvas3D.hpp | 57 +- src/slic3r/GUI/GLShader.cpp | 10 + src/slic3r/GUI/GLShader.hpp | 4 +- src/slic3r/GUI/GLTexture.cpp | 20 +- src/slic3r/GUI/GLTexture.hpp | 22 + src/slic3r/GUI/GLToolbar.cpp | 2730 ++++++---- src/slic3r/GUI/GLToolbar.hpp | 469 +- src/slic3r/GUI/GUI_App.cpp | 139 +- src/slic3r/GUI/GUI_App.hpp | 31 +- src/slic3r/GUI/GUI_Factories.cpp | 42 +- src/slic3r/GUI/GUI_ObjectList.cpp | 162 +- src/slic3r/GUI/GUI_ObjectList.hpp | 3 +- src/slic3r/GUI/GUI_Preview.cpp | 7 +- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp | 124 +- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp | 12 +- src/slic3r/GUI/Gizmos/GLGizmoAssembly.hpp | 5 +- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 75 +- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 18 +- src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp | 19 +- src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp | 5 + src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp | 5 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 21 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 35 +- src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp | 3 +- src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp | 550 +++ src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp | 82 + src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 20 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 32 +- src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp | 7 +- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp | 9 +- src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp | 6 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 137 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 12 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 40 +- src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 59 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 57 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 22 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp | 54 +- src/slic3r/GUI/Gizmos/GLGizmoSVG.hpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 14 +- src/slic3r/GUI/Gizmos/GLGizmoScale.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 22 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 22 +- src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 12 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoText.cpp | 4377 ++++++++++++----- src/slic3r/GUI/Gizmos/GLGizmoText.hpp | 184 +- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 58 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 1093 ++-- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 109 +- src/slic3r/GUI/GuiTextShape.cpp | 47 + src/slic3r/GUI/GuiTextShape.hpp | 23 + src/slic3r/GUI/HMS.cpp | 1 - src/slic3r/GUI/HintNotification.cpp | 2 +- src/slic3r/GUI/IMSlider.cpp | 4 +- src/slic3r/GUI/IMToolbar.cpp | 2 - src/slic3r/GUI/IMToolbar.hpp | 1 - src/slic3r/GUI/ImGuiWrapper.cpp | 8 + src/slic3r/GUI/ImGuiWrapper.hpp | 2 + src/slic3r/GUI/ImageDPIFrame.cpp | 17 + src/slic3r/GUI/Jobs/ArrangeJob.cpp | 5 +- .../GUI/Jobs/CreateFontNameImageJob.cpp | 222 + .../GUI/Jobs/CreateFontNameImageJob.hpp | 89 + .../GUI/Jobs/CreateFontStyleImagesJob.cpp | 158 + .../GUI/Jobs/CreateFontStyleImagesJob.hpp | 36 + src/slic3r/GUI/Jobs/EmbossJob.cpp | 857 +++- src/slic3r/GUI/Jobs/EmbossJob.hpp | 104 +- src/slic3r/GUI/Jobs/PrintJob.cpp | 21 +- src/slic3r/GUI/Jobs/PrintJob.hpp | 7 +- src/slic3r/GUI/Jobs/SendJob.cpp | 9 +- src/slic3r/GUI/Jobs/UpgradeNetworkJob.cpp | 4 +- src/slic3r/GUI/KBShortcutsDialog.cpp | 2 + src/slic3r/GUI/MainFrame.cpp | 75 +- src/slic3r/GUI/MainFrame.hpp | 1 + src/slic3r/GUI/MediaFilePanel.cpp | 6 +- src/slic3r/GUI/MediaPlayCtrl.cpp | 40 +- src/slic3r/GUI/MeshUtils.cpp | 32 +- src/slic3r/GUI/MeshUtils.hpp | 12 +- src/slic3r/GUI/Monitor.cpp | 17 - src/slic3r/GUI/Monitor.hpp | 1 - src/slic3r/GUI/MultiTaskManagerPage.cpp | 13 +- src/slic3r/GUI/NetworkTestDialog.cpp | 10 +- src/slic3r/GUI/NotificationManager.cpp | 1 + src/slic3r/GUI/NotificationManager.hpp | 1 + src/slic3r/GUI/OG_CustomCtrl.cpp | 4 +- src/slic3r/GUI/ObjectDataViewModel.cpp | 35 + src/slic3r/GUI/ObjectDataViewModel.hpp | 8 + src/slic3r/GUI/OpenGLManager.cpp | 10 + src/slic3r/GUI/OpenGLManager.hpp | 4 + src/slic3r/GUI/OptionsGroup.cpp | 3 +- src/slic3r/GUI/OptionsGroup.hpp | 13 +- src/slic3r/GUI/PartPlate.cpp | 302 +- src/slic3r/GUI/PartPlate.hpp | 4 +- src/slic3r/GUI/PartSkipCommon.hpp | 18 + src/slic3r/GUI/PartSkipDialog.cpp | 1048 ++++ src/slic3r/GUI/PartSkipDialog.hpp | 163 + src/slic3r/GUI/Plater.cpp | 675 ++- src/slic3r/GUI/Plater.hpp | 20 +- src/slic3r/GUI/PrePrintChecker.cpp | 120 +- src/slic3r/GUI/PrePrintChecker.hpp | 50 +- src/slic3r/GUI/Preferences.cpp | 55 +- src/slic3r/GUI/Preferences.hpp | 2 +- src/slic3r/GUI/PresetComboBoxes.cpp | 234 +- src/slic3r/GUI/PresetComboBoxes.hpp | 6 + src/slic3r/GUI/PrintOptionsDialog.cpp | 656 ++- src/slic3r/GUI/PrintOptionsDialog.hpp | 58 +- src/slic3r/GUI/Printer/PrinterFileSystem.cpp | 238 +- src/slic3r/GUI/Printer/PrinterFileSystem.h | 27 +- src/slic3r/GUI/ReleaseNote.cpp | 30 +- src/slic3r/GUI/ReleaseNote.hpp | 4 +- src/slic3r/GUI/SelectMachine.cpp | 506 +- src/slic3r/GUI/SelectMachine.hpp | 16 +- src/slic3r/GUI/SelectMachinePop.cpp | 6 +- src/slic3r/GUI/Selection.cpp | 34 +- src/slic3r/GUI/Selection.hpp | 3 +- src/slic3r/GUI/SendMultiMachinePage.cpp | 37 +- src/slic3r/GUI/SendToPrinter.cpp | 12 +- src/slic3r/GUI/SkipPartCanvas.cpp | 695 +++ src/slic3r/GUI/SkipPartCanvas.hpp | 169 + src/slic3r/GUI/StatusPanel.cpp | 380 +- src/slic3r/GUI/StatusPanel.hpp | 34 +- src/slic3r/GUI/SurfaceDrag.cpp | 21 +- src/slic3r/GUI/SurfaceDrag.hpp | 10 + src/slic3r/GUI/Tab.cpp | 122 +- src/slic3r/GUI/TaskManager.cpp | 9 +- src/slic3r/GUI/TextLines.cpp | 385 ++ src/slic3r/GUI/TextLines.hpp | 62 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 15 +- src/slic3r/GUI/UserPresetsDialog.cpp | 647 +++ src/slic3r/GUI/UserPresetsDialog.hpp | 87 + src/slic3r/GUI/WebGuideDialog.cpp | 48 +- src/slic3r/GUI/WebUserLoginDialog.cpp | 10 +- src/slic3r/GUI/WebViewDialog.cpp | 17 +- src/slic3r/GUI/Widgets/AMSControl.cpp | 21 +- src/slic3r/GUI/Widgets/AMSControl.hpp | 4 +- src/slic3r/GUI/Widgets/AMSItem.cpp | 7 +- src/slic3r/GUI/Widgets/AnimaController.cpp | 12 +- src/slic3r/GUI/Widgets/Button.cpp | 73 +- src/slic3r/GUI/Widgets/Button.hpp | 11 +- src/slic3r/GUI/Widgets/ComboBox.cpp | 15 +- src/slic3r/GUI/Widgets/DropDown.cpp | 6 +- src/slic3r/GUI/Widgets/FanControl.cpp | 372 +- src/slic3r/GUI/Widgets/FanControl.hpp | 102 +- src/slic3r/GUI/Widgets/SideTools.cpp | 36 +- src/slic3r/GUI/Widgets/StaticBox.cpp | 8 +- src/slic3r/GUI/Widgets/StaticBox.hpp | 7 +- src/slic3r/GUI/Widgets/StaticLine.cpp | 6 +- src/slic3r/GUI/Widgets/TabCtrl.cpp | 6 + src/slic3r/GUI/Widgets/TabCtrl.hpp | 6 +- src/slic3r/GUI/Widgets/TempInput.cpp | 35 +- src/slic3r/GUI/Widgets/TextInput.cpp | 4 +- src/slic3r/GUI/Widgets/WebView.cpp | 5 +- src/slic3r/GUI/WipeTowerDialog.cpp | 31 +- src/slic3r/GUI/WipeTowerDialog.hpp | 2 +- src/slic3r/GUI/calib_dlg.cpp | 41 +- src/slic3r/GUI/wxExtensions.cpp | 174 +- src/slic3r/GUI/wxExtensions.hpp | 5 + src/slic3r/GUI/wxMediaCtrl2.cpp | 4 +- src/slic3r/GUI/wxMediaCtrl3.cpp | 21 + src/slic3r/Utils/Bonjour.cpp | 605 +-- src/slic3r/Utils/Bonjour.hpp | 210 +- src/slic3r/Utils/CalibUtils.cpp | 21 +- src/slic3r/Utils/CalibUtils.hpp | 2 + src/slic3r/Utils/EmbossStyleManager.cpp | 864 ++++ src/slic3r/Utils/EmbossStyleManager.hpp | 323 ++ src/slic3r/Utils/FontConfigHelp.cpp | 4 - src/slic3r/Utils/FontConfigHelp.hpp | 8 +- src/slic3r/Utils/FontUtils.cpp | 2 +- src/slic3r/Utils/NetworkAgent.cpp | 111 +- src/slic3r/Utils/NetworkAgent.hpp | 6 - src/slic3r/Utils/OctoPrint.cpp | 19 +- src/slic3r/Utils/PresetUpdater.cpp | 37 +- src/slic3r/Utils/PrintHost.cpp | 6 - src/slic3r/Utils/QDTUtil.cpp | 173 + src/slic3r/Utils/QDTUtil.hpp | 23 + src/slic3r/Utils/TCPConsole.cpp | 35 - src/slic3r/Utils/Udp.hpp | 3 - src/slic3r/Utils/UndoRedo.cpp | 3 +- src/slic3r/Utils/json_diff.cpp | 33 +- src/slic3r/Utils/qidi_networking.hpp | 3 +- 287 files changed, 22250 insertions(+), 7322 deletions(-) create mode 100644 BuildMac.sh create mode 100644 resources/images/canvas_drag.svg create mode 100644 resources/images/canvas_drag_active.svg create mode 100644 resources/images/canvas_zoom_in.svg create mode 100644 resources/images/canvas_zoom_in_disable.svg create mode 100644 resources/images/canvas_zoom_out.svg create mode 100644 resources/images/canvas_zoom_out_disable.svg create mode 100644 resources/images/delete2.svg create mode 100644 resources/images/menu_export_toolpaths.svg create mode 100644 resources/images/more.svg create mode 100644 resources/images/more_dark.svg create mode 100644 resources/images/partskip_retry.svg create mode 100644 resources/images/preset_empty.svg create mode 100644 resources/images/preset_empty_dark.svg create mode 100644 resources/images/print_control_partskip.svg create mode 100644 resources/images/print_control_partskip_disable.svg create mode 100644 resources/images/print_control_partskip_hover.svg create mode 100644 resources/images/toolbar_fuzzyskin.svg create mode 100644 resources/images/toolbar_fuzzyskin_dark.svg create mode 100644 src/earcut/CHANGELOG.md create mode 100644 src/earcut/CMakeLists.txt create mode 100644 src/earcut/LICENSE create mode 100644 src/earcut/README.md create mode 100644 src/earcut/earcut.hpp create mode 100644 src/slic3r/GUI/EncodedFilament.cpp create mode 100644 src/slic3r/GUI/EncodedFilament.hpp create mode 100644 src/slic3r/GUI/FilamentBitmapUtils.cpp create mode 100644 src/slic3r/GUI/FilamentBitmapUtils.hpp create mode 100644 src/slic3r/GUI/FilamentPickerDialog.cpp create mode 100644 src/slic3r/GUI/FilamentPickerDialog.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp create mode 100644 src/slic3r/GUI/GuiTextShape.cpp create mode 100644 src/slic3r/GUI/GuiTextShape.hpp create mode 100644 src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp create mode 100644 src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp create mode 100644 src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp create mode 100644 src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp create mode 100644 src/slic3r/GUI/PartSkipCommon.hpp create mode 100644 src/slic3r/GUI/PartSkipDialog.cpp create mode 100644 src/slic3r/GUI/PartSkipDialog.hpp create mode 100644 src/slic3r/GUI/SkipPartCanvas.cpp create mode 100644 src/slic3r/GUI/SkipPartCanvas.hpp create mode 100644 src/slic3r/GUI/TextLines.cpp create mode 100644 src/slic3r/GUI/TextLines.hpp create mode 100644 src/slic3r/GUI/UserPresetsDialog.cpp create mode 100644 src/slic3r/GUI/UserPresetsDialog.hpp create mode 100644 src/slic3r/Utils/EmbossStyleManager.cpp create mode 100644 src/slic3r/Utils/EmbossStyleManager.hpp create mode 100644 src/slic3r/Utils/QDTUtil.cpp create mode 100644 src/slic3r/Utils/QDTUtil.hpp diff --git a/.gitignore b/.gitignore index 4389e41..5ea57b4 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ SVG **/machine_full/ **/filament_full/ .idea/ +<<<<<<< HEAD (ad709f NEW: Official filament color selection approved) +======= +test.js +/.cache/ +.clangd +>>>>>>> CHANGE (a6529d ENH: support parts skipping function) \ No newline at end of file diff --git a/BuildMac.sh b/BuildMac.sh new file mode 100644 index 0000000..8f48cde --- /dev/null +++ b/BuildMac.sh @@ -0,0 +1,244 @@ +#!/bin/bash + +set -e +set -o pipefail + +while getopts "1dpa:st:xbc:h" opt; do + case "${opt}" in + d ) + export BUILD_TARGET="deps" + ;; + p ) + export PACK_DEPS="1" + ;; + a ) + export ARCH="$OPTARG" + ;; + s ) + export BUILD_TARGET="slicer" + ;; + t ) + export OSX_DEPLOYMENT_TARGET="$OPTARG" + ;; + x ) + export SLICER_CMAKE_GENERATOR="Ninja" + export SLICER_BUILD_TARGET="all" + export DEPS_CMAKE_GENERATOR="Ninja" + ;; + b ) + export BUILD_ONLY="1" + ;; + c ) + export BUILD_CONFIG="$OPTARG" + ;; + 1 ) + export CMAKE_BUILD_PARALLEL_LEVEL=1 + ;; + h ) echo "Usage: ./BuildMac.sh [-1][-d][-s][-x][-b][-c]" + echo " -d: Build deps" + echo " -a: Set ARCHITECTURE (arm64 or x86_64 or universal)" + echo " -s: Build slicer only" + echo " -t: Specify minimum version of the target platform, default is 10.15" + echo " -x: Use Ninja CMake generator, default is Xcode" + echo " -b: Build without reconfiguring CMake" + echo " -c: Set CMake build configuration, default is Release" + echo " -1: limit builds to 1 core (where possible)" + exit 0 + ;; + * ) + ;; + esac +done + +if [ -z "$ARCH" ]; then + ARCH="$(uname -m)" + export ARCH +fi + +if [ -z "$BUILD_CONFIG" ]; then + export BUILD_CONFIG="Release" +fi + +if [ -z "$BUILD_TARGET" ]; then + export BUILD_TARGET="all" +fi + +if [ -z "$SLICER_CMAKE_GENERATOR" ]; then + export SLICER_CMAKE_GENERATOR="Xcode" +fi + +if [ -z "$SLICER_BUILD_TARGET" ]; then + export SLICER_BUILD_TARGET="ALL_BUILD" +fi + +if [ -z "$DEPS_CMAKE_GENERATOR" ]; then + export DEPS_CMAKE_GENERATOR="Unix Makefiles" +fi + +if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then + export OSX_DEPLOYMENT_TARGET="10.15" +fi + +echo "Build params:" +echo " - ARCH: $ARCH" +echo " - BUILD_CONFIG: $BUILD_CONFIG" +echo " - BUILD_TARGET: $BUILD_TARGET" +echo " - CMAKE_GENERATOR: $SLICER_CMAKE_GENERATOR for Slicer, $DEPS_CMAKE_GENERATOR for deps" +echo " - OSX_DEPLOYMENT_TARGET: $OSX_DEPLOYMENT_TARGET" +echo " - CMAKE_BUILD_PARALLEL_LEVEL: $CMAKE_BUILD_PARALLEL_LEVEL" +echo + +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_BUILD_DIR="$PROJECT_DIR/build/$ARCH" +DEPS_DIR="$PROJECT_DIR/deps" +DEPS_BUILD_DIR="$DEPS_DIR/build/$ARCH" +DEPS="$DEPS_BUILD_DIR/QIDIStudio_deps" + +if [ "$SLICER_CMAKE_GENERATOR" == "Xcode" ]; then + export BUILD_DIR_CONFIG_SUBDIR="/$BUILD_CONFIG" +else + export BUILD_DIR_CONFIG_SUBDIR="" +fi + +function build_deps() { + # iterate over two architectures: x86_64 and arm64 + for _ARCH in x86_64 arm64; do + # if ARCH is universal or equal to _ARCH + if [ "$ARCH" == "universal" ] || [ "$ARCH" == "$_ARCH" ]; then + + PROJECT_BUILD_DIR="$PROJECT_DIR/build/$_ARCH" + DEPS_BUILD_DIR="$DEPS_DIR/build/$_ARCH" + DEPS="$DEPS_BUILD_DIR/QIDIStudio_deps" + + echo "Building deps..." + ( + set -x + mkdir -p "$DEPS" + cd "$DEPS_BUILD_DIR" + if [ "1." != "$BUILD_ONLY". ]; then + cmake "${DEPS_DIR}" \ + -G "${DEPS_CMAKE_GENERATOR}" \ + -DDESTDIR="$DEPS" \ + -DOPENSSL_ARCH="darwin64-${_ARCH}-cc" \ + -DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \ + -DCMAKE_OSX_ARCHITECTURES:STRING="${_ARCH}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" + fi + cmake --build . --parallel ${CMAKE_BUILD_PARALLEL_LEVEL} --config "$BUILD_CONFIG" --target deps + ) + fi + done +} + +function pack_deps() { + echo "Packing deps..." + ( + set -x + cd "$DEPS_DIR" + tar -zcvf "QIDIStudio_dep_mac_${ARCH}_$(date +"%Y%m%d").tar.gz" "build" + ) +} + +function build_slicer() { + # iterate over two architectures: x86_64 and arm64 + for _ARCH in x86_64 arm64; do + # if ARCH is universal or equal to _ARCH + if [ "$ARCH" == "universal" ] || [ "$ARCH" == "$_ARCH" ]; then + + PROJECT_BUILD_DIR="$PROJECT_DIR/build/$_ARCH" + DEPS_BUILD_DIR="$DEPS_DIR/build/$_ARCH" + DEPS="$DEPS_BUILD_DIR/QIDIStudio_deps" + + echo "Building slicer for $_ARCH..." + ( + set -x + mkdir -p "$PROJECT_BUILD_DIR" + cd "$PROJECT_BUILD_DIR" + if [ "1." != "$BUILD_ONLY". ]; then + cmake "${PROJECT_DIR}" \ + -G "${SLICER_CMAKE_GENERATOR}" \ + -DQDT_RELEASE_TO_PUBLIC=1 \ + -DQDT_INTERNAL_TESTING=0 \ + -DCMAKE_PREFIX_PATH="$DEPS/usr/local" \ + -DCMAKE_INSTALL_PREFIX="$PWD/QIDIStudio" \ + -DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \ + -DCMAKE_MACOSX_RPATH=ON \ + -DCMAKE_INSTALL_RPATH="${DEPS}/usr/local" \ + -DCMAKE_MACOSX_BUNDLE=ON \ + -DCMAKE_OSX_ARCHITECTURES="${_ARCH}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" + fi + cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET" + ) + + + echo "Fix macOS app package..." + ( + cd "$PROJECT_BUILD_DIR" + mkdir -p QIDIStudio + cd QIDIStudio + # remove previously built app + rm -rf ./QIDIStudio.app + # fully copy newly built app + cp -pR "../src$BUILD_DIR_CONFIG_SUBDIR/QIDIStudio.app" ./QIDIStudio.app + # fix resources + resources_path=$(readlink ./QIDIStudio.app/Contents/Resources) + rm ./QIDIStudio.app/Contents/Resources + cp -R "$resources_path" ./QIDIStudio.app/Contents/Resources + # delete .DS_Store file + find ./QIDIStudio.app/ -name '.DS_Store' -delete + ) + + fi + done +} + +function build_universal() { + echo "Building universal binary..." + + PROJECT_BUILD_DIR="$PROJECT_DIR/build/$ARCH" + + # Create universal binary + echo "Creating universal binary..." + # PROJECT_BUILD_DIR="$PROJECT_DIR/build_Universal" + mkdir -p "$PROJECT_BUILD_DIR/QIDIStudio" + UNIVERSAL_APP="$PROJECT_BUILD_DIR/QIDIStudio/QIDIStudio.app" + rm -rf "$UNIVERSAL_APP" + cp -R "$PROJECT_DIR/build/arm64/QIDIStudio/QIDIStudio.app" "$UNIVERSAL_APP" + + # Get the binary path inside the .app bundle + BINARY_PATH="Contents/MacOS/QIDIStudio" + + # Create universal binary using lipo + lipo -create \ + "$PROJECT_DIR/build/x86_64/QIDIStudio/QIDIStudio.app/$BINARY_PATH" \ + "$PROJECT_DIR/build/arm64/QIDIStudio/QIDIStudio.app/$BINARY_PATH" \ + -output "$UNIVERSAL_APP/$BINARY_PATH" + + echo "Universal binary created at $UNIVERSAL_APP" +} + +case "${BUILD_TARGET}" in + all) + build_deps + build_slicer + ;; + deps) + build_deps + ;; + slicer) + build_slicer + ;; + *) + echo "Unknown target: $BUILD_TARGET. Available targets: deps, slicer, all." + exit 1 + ;; +esac + +if [ "$ARCH" = "universal" ] && [ "$BUILD_TARGET" != "deps" ]; then + build_universal +fi + +if [ "1." == "$PACK_DEPS". ]; then + pack_deps +fi \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index dfe2ff9..78fd42d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,10 @@ if (APPLE) if (CMAKE_MACOSX_BUNDLE) set(CMAKE_INSTALL_RPATH @executable_path/../Frameworks) endif() - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE) + if (NOT CMAKE_OSX_DEPLOYMENT_TARGET) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE) + endif () + message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}") elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") set(CMAKE_INSTALL_RPATH "$ORIGIN") endif () @@ -247,6 +250,8 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP # On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error. add_compile_options(-Werror=return-type) + add_compile_options(-Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-label -Wno-unused-local-typedefs) + # removes LOTS of extraneous Eigen warnings (GCC only supports it since 6.1) # https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1221 if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0) @@ -260,6 +265,10 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP add_compile_options(-Wno-deprecated-declarations) endif() + if((${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER 15) + add_compile_options(-Wno-error=enum-constexpr-conversion) + endif() + #GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431 @@ -314,7 +323,7 @@ if(WIN32) add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) if(MSVC) # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. - add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 -DBOOST_SYSTEM_USE_UTF8 ) + add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x602 -DBOOST_SYSTEM_USE_UTF8 ) # Force the source code encoding to UTF-8. See QIDIStudio GH pull request #5583 add_compile_options("$<$:/utf-8>") add_compile_options("$<$:/utf-8>") @@ -356,7 +365,7 @@ endif() # set(Boost_COMPILER "-mgw81") # boost::process was introduced first in version 1.64.0, # boost::beast::detail::base64 was introduced first in version 1.66.0 -set(MINIMUM_BOOST_VERSION "1.66.0") +set(MINIMUM_BOOST_VERSION "1.83.0") set(_boost_components "system;filesystem;thread;log;locale;regex;chrono;atomic;date_time;iostreams") find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS ${_boost_components}) diff --git a/Dockerfile b/Dockerfile index 9220b28..3205806 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,7 @@ WORKDIR /QIDIStudio # It might conflict with your mapped user, remove if user ubuntu exist RUN if id "ubuntu" >/dev/null 2>&1; then userdel -r ubuntu; fi -# It's easier to run Bambu Studio as the same username, +# It's easier to run QIDI Studio as the same username, # UID and GID as your workstation. Since we bind mount # your home directory into the container, it's handy # to keep permissions the same. Just in case, defaults diff --git a/qdt/i18n/QIDIStudio.pot b/qdt/i18n/QIDIStudio.pot index e319e92..c237f58 100644 --- a/qdt/i18n/QIDIStudio.pot +++ b/qdt/i18n/QIDIStudio.pot @@ -13682,7 +13682,7 @@ msgstr "" msgid "Successfully sent. Close current page in %s s." msgstr "" -msgid "The selected printer is not connect box, please check." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." msgstr "" msgid "Failed to set the box printing slot..." diff --git a/qdt/i18n/cs/QIDIStudio_cs.po b/qdt/i18n/cs/QIDIStudio_cs.po index 5afd7bf..fb372fe 100644 --- a/qdt/i18n/cs/QIDIStudio_cs.po +++ b/qdt/i18n/cs/QIDIStudio_cs.po @@ -15411,8 +15411,8 @@ msgstr "Úspěšně odesláno. Automatický přechod na stránku zařízení za msgid "Successfully sent. Close current page in %s s." msgstr "Úspěšně odesláno. Uzavření aktuální stránky za %s s." -msgid "The selected printer is not connect box, please check." -msgstr "Vybraná tiskárna není připojena k BOXu, prosím zkontrolujte." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Vybraná tiskárna není připojena k BOX nebo filamenty nejsou synchronizovány. Prosím, zkontrolujte." msgid "Failed to set the box printing slot..." msgstr "Nastavení tiskového slotu BOXu selhalo..." @@ -15460,4 +15460,13 @@ msgid "Current printer is printing now" msgstr "Aktuální tiskárna právě tiskne" msgid "Please do not mix-use the Ext with BOX" -msgstr "Prosím, nemíchejte Ext s BOX" \ No newline at end of file +msgstr "Prosím, nemíchejte Ext s BOX" + +msgid "Recommended box temperature" +msgstr "Doporučená teplota boxu" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Doporučený teplotní rozsah boxu pro toto vlákno. 0 znamená žádné nastavení." + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Nastavte teplotu boxu během tisku. Nastavte na 0 (vypnuto)." diff --git a/qdt/i18n/de/QIDIStudio_de.po b/qdt/i18n/de/QIDIStudio_de.po index 263f038..62fe211 100644 --- a/qdt/i18n/de/QIDIStudio_de.po +++ b/qdt/i18n/de/QIDIStudio_de.po @@ -17216,8 +17216,8 @@ msgstr "Erfolgreich gesendet. Automatische Weiterleitung zur Geräteseite in %s msgid "Successfully sent. Close current page in %s s." msgstr "Erfolgreich gesendet. Schließe aktuelle Seite in %s s." -msgid "The selected printer is not connect box, please check." -msgstr "Der gewählte Drucker ist nicht mit der BOX verbunden, bitte überprüfen." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Der ausgewählte Drucker ist nicht mit der BOX verbunden oder die Filamente sind nicht synchronisiert. Bitte überprüfen Sie dies." msgid "Failed to set the box printing slot..." msgstr "Fehler beim Einrichten des Druckfachs der BOX..." @@ -17265,4 +17265,13 @@ msgid "Current printer is printing now" msgstr "Der aktuelle Drucker druckt gerade"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Bitte verwenden Sie das Externe nicht zusammen mit dem BOX." \ No newline at end of file +msgstr "Bitte verwenden Sie das Externe nicht zusammen mit dem BOX." + +msgid "Recommended box temperature" +msgstr "Empfohlene Box-Temperatur" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Empfohlener Temperaturbereich der Box für dieses Filament. 0 bedeutet keine Einstellung." + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Stellen Sie die Temperatur der Box während des Drucks ein. Auf 0 setzen (ausgeschaltet)." \ No newline at end of file diff --git a/qdt/i18n/en/QIDIStudio_en.po b/qdt/i18n/en/QIDIStudio_en.po index b6dd992..c065f86 100644 --- a/qdt/i18n/en/QIDIStudio_en.po +++ b/qdt/i18n/en/QIDIStudio_en.po @@ -16875,7 +16875,7 @@ msgstr "" msgid "Successfully sent. Close current page in %s s." msgstr "" -msgid "The selected printer is not connect box, please check." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." msgstr "" msgid "Failed to set the box printing slot..." @@ -16924,4 +16924,13 @@ msgid "Current printer is printing now"​​ ​msgstr ""​ msgid "Please do not mix-use the Ext with BOX" +msgstr "" + +msgid "Recommended box temperature" +msgstr "" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." msgstr "" \ No newline at end of file diff --git a/qdt/i18n/es/QIDIStudio_es.po b/qdt/i18n/es/QIDIStudio_es.po index 32a4a33..64b2377 100644 --- a/qdt/i18n/es/QIDIStudio_es.po +++ b/qdt/i18n/es/QIDIStudio_es.po @@ -17214,8 +17214,8 @@ msgstr "Enviado correctamente. Redirección automática a la página del disposi msgid "Successfully sent. Close current page in %s s." msgstr "Enviado correctamente. Cierre de página actual en %s s." -msgid "The selected printer is not connect box, please check." -msgstr "La impresora seleccionada no está conectada a la BOX, por favor verifique." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "La impresora seleccionada no está conectada a la BOX o los filamentos no están sincronizados. Por favor, compruébelo." msgid "Failed to set the box printing slot..." msgstr "Error al configurar el compartimento de impresión de la BOX..." @@ -17263,4 +17263,13 @@ msgid "Current printer is printing now"​​ msgstr "La impresora actual está imprimiendo ahora"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Por favor, no mezcle Ext con BOX" \ No newline at end of file +msgstr "Por favor, no mezcle Ext con BOX" + +msgid "Recommended box temperature" +msgstr "Temperatura recomendada de la cámara" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Rango de temperatura recomendado de la cámara para este filamento. 0 significa sin ajustar" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Ajuste la temperatura de la cámara durante la impresión. Configúrela a 0 (apagado)." \ No newline at end of file diff --git a/qdt/i18n/fr/QIDIStudio_fr.po b/qdt/i18n/fr/QIDIStudio_fr.po index 37a9efa..96e98ef 100644 --- a/qdt/i18n/fr/QIDIStudio_fr.po +++ b/qdt/i18n/fr/QIDIStudio_fr.po @@ -17167,8 +17167,8 @@ msgstr "Envoyé avec succès. Redirection automatique vers la page de l'appareil msgid "Successfully sent. Close current page in %s s." msgstr "Envoyé avec succès. Fermeture de la page actuelle dans %s s." -msgid "The selected printer is not connect box, please check." -msgstr "L'imprimante sélectionnée n'est pas connectée à la BOÎTE, veuillez vérifier." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "L’imprimante sélectionnée n’est pas connectée à la BOX ou les filaments ne sont pas synchronisés. Veuillez vérifier." msgid "Failed to set the box printing slot..." msgstr "Échec de la configuration du compartiment d'impression de la BOÎTE..." @@ -17216,4 +17216,13 @@ msgid "Current printer is printing now"​​ ​msgstr "L'imprimante actuelle est en cours d'impression"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Ne pas mélanger l'Ext avec l'BXO" \ No newline at end of file +msgstr "Ne pas mélanger l'Ext avec l'BXO" + +msgid "Recommended box temperature" +msgstr "Température recommandée de l'enceinte" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Plage de température recommandée de l'enceinte pour ce filament. 0 signifie non réglé" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Réglez la température de l'enceinte pendant l'impression. Mettez à 0 (désactivé)." \ No newline at end of file diff --git a/qdt/i18n/hu/QIDIStudio_hu.po b/qdt/i18n/hu/QIDIStudio_hu.po index 3335c71..015388e 100644 --- a/qdt/i18n/hu/QIDIStudio_hu.po +++ b/qdt/i18n/hu/QIDIStudio_hu.po @@ -17210,8 +17210,8 @@ msgstr "Sikeresen elküldve. Automatikusan átirányítja az eszköz oldalra %s msgid "Successfully sent. Close current page in %s s." msgstr "Sikeresen elküldve. Az aktuális oldal bezárása %s másodperc múlva." -msgid "The selected printer is not connect box, please check." -msgstr "A kiválasztott nyomtató nincs csatlakoztatva a BOX-hoz, kérjük ellenőrizze." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "A kiválasztott nyomtató nincs csatlakoztatva a BOX-hoz, vagy a filamentek nincsenek szinkronban. Kérjük, ellenőrizze." msgid "Failed to set the box printing slot..." msgstr "A BOX nyomtatási rekeszének beállítása sikertelen..." @@ -17259,4 +17259,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Az aktuális nyomtató épp nyomtat"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Ne keverd a külső anyagot az BOX-sel" \ No newline at end of file +msgstr "Ne keverd a külső anyagot az BOX-sel" + +msgid "Recommended box temperature" +msgstr "Ajánlott kamra hőmérséklet" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Az ilyen típusú filament ajánlott kamrahőmérséklet-tartománya. 0 értéknél nincs beállítás" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Állítsa be a kamra hőmérsékletét nyomtatás közben. Állítsa 0-ra (kikapcsolva)." \ No newline at end of file diff --git a/qdt/i18n/it/QIDIStudio_it.po b/qdt/i18n/it/QIDIStudio_it.po index 575bd5b..5eebdba 100644 --- a/qdt/i18n/it/QIDIStudio_it.po +++ b/qdt/i18n/it/QIDIStudio_it.po @@ -17213,8 +17213,8 @@ msgstr "Inviato con successo. Reindirizzamento automatico alla pagina del dispos msgid "Successfully sent. Close current page in %s s." msgstr "Inviato con successo. Chiusura pagina corrente tra %s s." -msgid "The selected printer is not connect box, please check." -msgstr "La stampante selezionata non è connessa alla BOX, verificare." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "La stampante selezionata non è connessa alla BOX oppure i filamenti non sono sincronizzati. Si prega di verificare." msgid "Failed to set the box printing slot..." msgstr "Impostazione dello slot di stampa della BOX fallita..." @@ -17262,4 +17262,13 @@ msgid "Current printer is printing now"​​ ​msgstr "La stampante corrente sta stampando"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Non utilizzare contemporaneamente Ext con BOX." \ No newline at end of file +msgstr "Non utilizzare contemporaneamente Ext con BOX." + +msgid "Recommended box temperature" +msgstr "Temperatura consigliata della camera" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Intervallo di temperatura consigliato della camera per questo filamento. 0 significa non impostato" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Imposta la temperatura della camera durante la stampa. Imposta a 0 (spento)." \ No newline at end of file diff --git a/qdt/i18n/ja/QIDIStudio_ja.po b/qdt/i18n/ja/QIDIStudio_ja.po index 185b749..b24ab81 100644 --- a/qdt/i18n/ja/QIDIStudio_ja.po +++ b/qdt/i18n/ja/QIDIStudio_ja.po @@ -17192,8 +17192,8 @@ msgstr "送信に成功しました。%s秒後にデバイスページへ自動 msgid "Successfully sent. Close current page in %s s." msgstr "送信に成功しました。%s秒後に現在のページを閉じます。" -msgid "The selected printer is not connect box, please check." -msgstr "選択したプリンターはBOXに接続されていません。確認してください。" +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "選択されたプリンターがBOXに接続されていないか、フィラメントが同期されていません。確認してください。" msgid "Failed to set the box printing slot..." msgstr "BOX印刷スロットの設定に失敗しました..." @@ -17241,4 +17241,13 @@ msgid "Current printer is printing now"​​ ​msgstr "現在のプリンターは印刷中です"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "ExtとBOXの混合使用はお控えください。" \ No newline at end of file +msgstr "ExtとBOXの混合使用はお控えください。" + +msgid "Recommended box temperature" +msgstr "推奨チャンバー温度" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "このフィラメントの推奨チャンバー温度範囲。0は未設定を意味します" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "印刷中のチャンバー温度を設定します。0に設定(オフ)" \ No newline at end of file diff --git a/qdt/i18n/ko/QIDIStudio_ko.po b/qdt/i18n/ko/QIDIStudio_ko.po index 2421b67..fd2db56 100644 --- a/qdt/i18n/ko/QIDIStudio_ko.po +++ b/qdt/i18n/ko/QIDIStudio_ko.po @@ -15099,8 +15099,8 @@ msgstr "성공적으로 전송되었습니다. %s초 후 장치 페이지로 자 msgid "Successfully sent. Close current page in %s s." msgstr "성공적으로 전송되었습니다. %s초 후 현재 페이지를 닫습니다." -msgid "The selected printer is not connect box, please check." -msgstr "선택한 프린터가 BOX에 연결되지 않았습니다. 확인해 주세요." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "선택한 프린터가 BOX에 연결되어 있지 않거나 필라멘트가 동기화되지 않았습니다. 확인해 주세요." msgid "Failed to set the box printing slot..." msgstr "BOX 인쇄 슬롯 설정에 실패했습니다..." @@ -15148,4 +15148,13 @@ msgid "Current printer is printing now"​​ ​msgstr "현재 프린터가 인쇄 중입니다"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Ext를 BOX와 혼용하지 마세요" \ No newline at end of file +msgstr "Ext를 BOX와 혼용하지 마세요" + +msgid "Recommended box temperature" +msgstr "권장 챔버 온도" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "이 필라멘트의 권장 챔버 온도 범위. 0은 미설정을 의미합니다" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "프린팅 중 챔버 온도를 설정하세요. 0으로 설정(꺼짐)" \ No newline at end of file diff --git a/qdt/i18n/nl/QIDIStudio_nl.po b/qdt/i18n/nl/QIDIStudio_nl.po index 5e61e8e..34e88aa 100644 --- a/qdt/i18n/nl/QIDIStudio_nl.po +++ b/qdt/i18n/nl/QIDIStudio_nl.po @@ -17200,8 +17200,8 @@ msgstr "Succesvol verzonden. Wordt automatisch doorgestuurd naar apparaatpagina msgid "Successfully sent. Close current page in %s s." msgstr "Succesvol verzonden. Huidige pagina sluiten over %s s." -msgid "The selected printer is not connect box, please check." -msgstr "De geselecteerde printer is niet verbonden met de BOX, controleer dit." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "De geselecteerde printer is niet verbonden met de BOX of de filamenten zijn niet gesynchroniseerd. Controleer dit alstublieft." msgid "Failed to set the box printing slot..." msgstr "Instellen BOX-printvak mislukt..." @@ -17249,4 +17249,13 @@ msgid "Current printer is printing now"​​ ​msgstr "De huidige printer is aan het printen"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Gebruik de Ext niet samen met BOX" \ No newline at end of file +msgstr "Gebruik de Ext niet samen met BOX" + +msgid "Recommended box temperature" +msgstr "Aanbevolen kamertemperatuur" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Aanbevolen temperatuurbereik voor dit filament. 0 betekent niet ingesteld" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Stel de kamertemperatuur in tijdens het printen. Stel in op 0 (uitgeschakeld)." \ No newline at end of file diff --git a/qdt/i18n/pl/QIDIStudio_pl.po b/qdt/i18n/pl/QIDIStudio_pl.po index bb330b7..fb813a1 100644 --- a/qdt/i18n/pl/QIDIStudio_pl.po +++ b/qdt/i18n/pl/QIDIStudio_pl.po @@ -17118,8 +17118,8 @@ msgstr "Wysłano pomyślnie. Automatyczne przejście do strony urządzenia za %s msgid "Successfully sent. Close current page in %s s." msgstr "Wysłano pomyślnie. Zamknięcie bieżącej strony za %s s." -msgid "The selected printer is not connect box, please check." -msgstr "Wybrana drukarka nie jest podłączona do BOX-a, proszę sprawdzić." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Wybrana drukarka nie jest podłączona do BOX-a lub filamenty nie są zsynchronizowane. Proszę to sprawdzić." msgid "Failed to set the box printing slot..." msgstr "Nie udało się ustawić gniazda drukującego BOX-a..." @@ -17167,4 +17167,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Aktualna drukarka drukuje"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Nie używaj jednocześnie szpuli zewnętrznej i BOX" \ No newline at end of file +msgstr "Nie używaj jednocześnie szpuli zewnętrznej i BOX" + +msgid "Recommended box temperature" +msgstr "Zalecana temperatura komory" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Zalecany zakres temperatury komory dla tego filamentu. 0 oznacza brak ustawienia" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Ustaw temperaturę komory podczas drukowania. Ustaw na 0 (wyłączone)." \ No newline at end of file diff --git a/qdt/i18n/pt-BR/QIDIStudio_pt-BR.po b/qdt/i18n/pt-BR/QIDIStudio_pt-BR.po index 1b53688..138d1a1 100644 --- a/qdt/i18n/pt-BR/QIDIStudio_pt-BR.po +++ b/qdt/i18n/pt-BR/QIDIStudio_pt-BR.po @@ -17153,8 +17153,8 @@ msgstr "Enviado com sucesso. Será redirecionado automaticamente para a página msgid "Successfully sent. Close current page in %s s." msgstr "Enviado com sucesso. Fechando página atual em %s s." -msgid "The selected printer is not connect box, please check." -msgstr "A impressora selecionada não está conectada à BOX, por favor verifique." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "A impressora selecionada não está conectada à BOX ou os filamentos não estão sincronizados. Por favor, verifique." msgid "Failed to set the box printing slot..." msgstr "Falha ao configurar o slot de impressão da BOX..." @@ -17202,4 +17202,13 @@ msgid "Current printer is printing now"​​ ​msgstr "A impressora atual está imprimindo"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Por favor, não misture o Ext com o BOX" \ No newline at end of file +msgstr "Por favor, não misture o Ext com o BOX" + +msgid "Recommended box temperature" +msgstr "Temperatura recomendada da câmara" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Faixa de temperatura recomendada da câmara para este filamento. 0 significa não definido" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Ajuste a temperatura da câmara durante a impressão. Defina como 0 (desligado)." \ No newline at end of file diff --git a/qdt/i18n/ru/QIDIStudio_ru.po b/qdt/i18n/ru/QIDIStudio_ru.po index f335181..bd77b7e 100644 --- a/qdt/i18n/ru/QIDIStudio_ru.po +++ b/qdt/i18n/ru/QIDIStudio_ru.po @@ -15208,8 +15208,8 @@ msgstr "Успешно отправлено. Автоматический пер msgid "Successfully sent. Close current page in %s s." msgstr "Успешно отправлено. Закрытие текущей страницы через %s с." -msgid "The selected printer is not connect box, please check." -msgstr "Выбранный принтер не подключен к BOX, проверьте." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Выбранный принтер не подключён к BOX или нити не синхронизированы. Пожалуйста, проверьте." msgid "Failed to set the box printing slot..." msgstr "Не удалось установить слот печати BOX..." @@ -15257,4 +15257,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Текущий принтер печатает"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Пожалуйста, не используйте Ext и BOX вместе." \ No newline at end of file +msgstr "Пожалуйста, не используйте Ext и BOX вместе." + +msgid "Recommended box temperature" +msgstr "Рекомендуемая температура камеры" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Рекомендуемый диапазон температуры камеры для этого филамента. 0 означает отсутствие настройки" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Установите температуру камеры во время печати. Установите на 0 (выключено)." \ No newline at end of file diff --git a/qdt/i18n/sv/QIDIStudio_sv.po b/qdt/i18n/sv/QIDIStudio_sv.po index eae08dc..bdecf54 100644 --- a/qdt/i18n/sv/QIDIStudio_sv.po +++ b/qdt/i18n/sv/QIDIStudio_sv.po @@ -17247,8 +17247,8 @@ msgstr "Skickat. Kommer automatiskt att gå till enhetssidan om %s s." msgid "Successfully sent. Close current page in %s s." msgstr "Skickat. Stänger denna sida om %s s." -msgid "The selected printer is not connect box, please check." -msgstr "Den valda skrivaren är inte ansluten till BOX, kontrollera." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Den valda skrivaren är inte ansluten till BOX eller så är filamenten inte synkroniserade. Kontrollera detta." msgid "Failed to set the box printing slot..." msgstr "Misslyckades att ställa in BOX:s utskriftsfack..." @@ -17296,4 +17296,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Den aktuella skrivaren skriver ut"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Blanda inte Ext med BOX" \ No newline at end of file +msgstr "Blanda inte Ext med BOX" + +msgid "Recommended box temperature" +msgstr "Rekommenderad kammartemperatur" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Rekommenderat temperaturområde för kammaren för detta filament. 0 betyder inte inställt" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Ställ in kammarens temperatur under utskrift. Ställ in på 0 (avstängd)." \ No newline at end of file diff --git a/qdt/i18n/tr/QIDIStudio_tr.po b/qdt/i18n/tr/QIDIStudio_tr.po index 0cd9261..dcf8d32 100644 --- a/qdt/i18n/tr/QIDIStudio_tr.po +++ b/qdt/i18n/tr/QIDIStudio_tr.po @@ -15427,8 +15427,8 @@ msgstr "Başarıyla gönderildi. %s saniye sonra cihaz sayfasına otomatik geçi msgid "Successfully sent. Close current page in %s s." msgstr "Başarıyla gönderildi. %s saniye sonra mevcut sayfa kapatılacak." -msgid "The selected printer is not connect box, please check." -msgstr "Seçilen yazıcı BOX'a bağlı değil, lütfen kontrol edin." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Seçilen yazıcı BOX'a bağlı değil veya filamentler senkronize edilmemiş. Lütfen kontrol edin." msgid "Failed to set the box printing slot..." msgstr "BOX yazdırma yuvası ayarlanamadı..." @@ -15476,4 +15476,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Mevcut yazıcı şu anda yazdırıyor"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Lütfen Ext'i BOX ile karıştırarak kullanmayın" \ No newline at end of file +msgstr "Lütfen Ext'i BOX ile karıştırarak kullanmayın" + +msgid "Recommended box temperature" +msgstr "Önerilen hazne sıcaklığı" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Bu filament için önerilen hazne sıcaklık aralığı. 0, ayar yapılmadı anlamına gelir" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Yazdırma sırasında hazne sıcaklığını ayarlayın. 0'a ayarlayın (kapalı)." \ No newline at end of file diff --git a/qdt/i18n/uk/QIDIStudio_uk.po b/qdt/i18n/uk/QIDIStudio_uk.po index 277487d..38fd1b5 100644 --- a/qdt/i18n/uk/QIDIStudio_uk.po +++ b/qdt/i18n/uk/QIDIStudio_uk.po @@ -17178,8 +17178,8 @@ msgstr "Успішно відправлено. Автоматичний пере msgid "Successfully sent. Close current page in %s s." msgstr "Успішно відправлено. Закриття поточної сторінки через %s с." -msgid "The selected printer is not connect box, please check." -msgstr "Вибраний принтер не підключений до BOX, будь ласка, перевірте." +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "Вибраний принтер не підключений до BOX або нитки не синхронізовані. Будь ласка, перевірте." msgid "Failed to set the box printing slot..." msgstr "Не вдалося налаштувати слот для друку BOX..." @@ -17227,4 +17227,13 @@ msgid "Current printer is printing now"​​ ​msgstr "Поточний принтер друкує"​ msgid "Please do not mix-use the Ext with BOX" -msgstr "Будь ласка, не використовуйте Ext та BOX разом." \ No newline at end of file +msgstr "Будь ласка, не використовуйте Ext та BOX разом." + +msgid "Recommended box temperature" +msgstr "Рекомендована температура камери" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "Рекомендований діапазон температури камери для цього філаменту. 0 означає відсутність налаштувань" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "Встановіть температуру камери під час друку. Встановіть на 0 (вимкнено)." \ No newline at end of file diff --git a/qdt/i18n/zh_cn/QIDIStudio_zh_CN.po b/qdt/i18n/zh_cn/QIDIStudio_zh_CN.po index e59341d..bfb99de 100644 --- a/qdt/i18n/zh_cn/QIDIStudio_zh_CN.po +++ b/qdt/i18n/zh_cn/QIDIStudio_zh_CN.po @@ -21055,8 +21055,8 @@ msgstr "发送成功。%s秒后将自动跳转至设备页面。" msgid "Successfully sent. Close current page in %s s." msgstr "发送成功。%s秒后将关闭当前页面。" -msgid "The selected printer is not connect box, please check." -msgstr "所选打印机未连接BOX,请检查。" +msgid "The selected printer is not connected to the BOX or the filaments are not synchronized. Please check." +msgstr "所选打印机未连接到BOX或耗材未同步。请检查。" msgid "Failed to set the box printing slot..." msgstr "设置BOX打印槽位失败..." @@ -21104,4 +21104,13 @@ msgid "Current printer is printing now" msgstr "当前打印机正在打印中" msgid "Please do not mix-use the Ext with BOX" -msgstr "请勿将Ext与BOX混用" \ No newline at end of file +msgstr "请勿将Ext与BOX混用" + +msgid "Recommended box temperature" +msgstr "推荐盒子温度" + +msgid "Recommended box temperature range of this filament. 0 means no set" +msgstr "该耗材推荐的盒子温度范围。0表示未设置" + +msgid "Set the temperature of the box during printing, set to 0 (representing off)." +msgstr "设置打印过程中的盒子温度,设为0(表示关闭)" \ No newline at end of file diff --git a/resources/i18n/cs/QIDIStudio.mo b/resources/i18n/cs/QIDIStudio.mo index d5c3f627dbead8fdec1d53c70338acabbb1c89f5..4c99a684922405c0d1e40b0579bf4b71551fd511 100644 GIT binary patch delta 54156 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 G#{UCqa=PLG delta 53693 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 BZD#-g diff --git a/resources/i18n/de/QIDIStudio.mo b/resources/i18n/de/QIDIStudio.mo index 8285877bb6de7bac568b078ad869fc5b7ee6b5bd..bf534a2a8adf55a85a4cbf4c675c385c69cabf11 100644 GIT binary patch delta 92316 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%0AiJ~R*aqfBvp(e@z<)NHV?R9N? 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 delta 91957 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 Z`o{R-w-h*M{L*_0l$@8pU4cIq{2yYEdQt!Y diff --git a/resources/i18n/es/QIDIStudio.mo b/resources/i18n/es/QIDIStudio.mo index 55ace354f451ff4ad07b2734cb4bc18bdc4f5255..10abe962396acad0a4576deec016c187d29fa0a1 100644 GIT binary patch delta 90659 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 delta 90158 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 YS98X%v+zgQ2+n{ delta 82813 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 diff --git a/resources/i18n/hu/QIDIStudio.mo b/resources/i18n/hu/QIDIStudio.mo index 564ebbab0b8ee73f3598797e9568b607b9d7fe9f..6d2c46e3017e81c2486c7e951c20b0d95c113b55 100644 GIT binary patch delta 82836 zcmXWkbzm09*2nQD$%7V(I~M}MA-Dy15AJS-BE_}HQ{17HQk({Ncb5VM3WXxYo#O7! z{r>jM`^Wp)ncbb8Idf)q6Daq?_OuiCqzzn6=%4E2|C-15`BGz?VLsovBtGA#XhEv> zHEb5-D};?O6;8&ixC*P{IgE*6&4YZgFo&}smZe+@Q{r$;hreSj+=q#LzJM=L3%ejQ zrsYH#Oo*+q6!yl7xEa-vFZeAMY#HQ>f#op{MxqAL7f`bq$zQ@?u8T(>i%!5y{3Z`ovOC~7DhdAJpPE&Q6Wy$&dw)6J+K36 z%KD(LTaAiz*7kNjynRr>yRirrdO$H$1ZpBV=xc>aqQ3YHcc33ves9;U!yhQ`M?D~S z2Wxl*D#Tk+9X){>&?QWaw=p-q?+~!L%+}E!)EJv{VlGy~�uS(8;oPG?t`%5mleE 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 I0MnlT0i&G^&;S4c delta 82483 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

U7Ut>1Ra@rzM6LsN8R0nsX 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 delta 84438 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 diff --git a/resources/i18n/ja/QIDIStudio.mo b/resources/i18n/ja/QIDIStudio.mo index 9192fd2d1ab3ae556b4d256064a150b4fb717fee..f1b252c58bf44b3bf1ae87359d2cd4851b28fe98 100644 GIT binary patch delta 93467 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

Znw)avd8wf)9JU80v8Us-#hW^Q-X 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

Lp0MV1N9 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≥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 D6=7iR delta 91709 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
iKb~4*3g6Xk=?p5AMcZcnk|*krB2AdSG$#D^U@6 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 L-l4k1yUhPzd<5e0 diff --git a/resources/i18n/nl/QIDIStudio.mo b/resources/i18n/nl/QIDIStudio.mo index 7da7fc3ec3a864e32bb0baa968bc7d5811054e18..73793bbc554369ddb6f2191a34a4b6d8a2ec7319 100644 GIT binary patch delta 90633 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 Rvwi(5ufUw^-rl~M{{vm!3jF{8 delta 90199 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 NR4%Ja(LyB`{})q!bg2LU diff --git a/resources/i18n/pl/QIDIStudio.mo b/resources/i18n/pl/QIDIStudio.mo index a947a9083d33ada85c80d6ff0ad616904ce2b622..cce15326f9598f3f2e32febfa25910e53cda6d4e 100644 GIT binary patch delta 84394 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 L>G~rsop1dQ0Aty* delta 84079 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 z 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 LQAOK&x3>HbCj*{+ diff --git a/resources/i18n/pt-BR/QIDIStudio.mo b/resources/i18n/pt-BR/QIDIStudio.mo index b4aa15f47598296614a9932467c796135f0b07c0..6ffd25b8d300d52516ad0458712a2bd84ff31402 100644 GIT binary patch delta 88029 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 delta 79486 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 u@bzSB*xHn!_kVr)!@!P5d(9a<$dvlRIROt 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

p%)D$d0Jzy*9fyYpD{Xf(ObQ5*`16O{6 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 diff --git a/resources/i18n/tr/QIDIStudio.mo b/resources/i18n/tr/QIDIStudio.mo index 6eb4ed7f120312b1655593623a9b3da80effe541..06a532c4200894ee713838696b9b7067f73baba7 100644 GIT binary patch delta 82817 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�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 diff --git a/resources/i18n/uk/QIDIStudio.mo b/resources/i18n/uk/QIDIStudio.mo index 7d611a57f6dfa080de1e29f13b6fe9b2b3f03586..8473c51c8b816ec4af8e0859ddd6597e51ce988a 100644 GIT binary patch delta 70413 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 ux)+;LlpU3x`NV0?lhv;GHLL5s5h delta 91227 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 Sn0EiD(v|W~zp?bnyZ;}R;pgQ5 diff --git a/resources/images/canvas_drag.svg b/resources/images/canvas_drag.svg new file mode 100644 index 0000000..821fa70 --- /dev/null +++ b/resources/images/canvas_drag.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/canvas_drag_active.svg b/resources/images/canvas_drag_active.svg new file mode 100644 index 0000000..5aa863e --- /dev/null +++ b/resources/images/canvas_drag_active.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/canvas_zoom_in.svg b/resources/images/canvas_zoom_in.svg new file mode 100644 index 0000000..3fbf01e --- /dev/null +++ b/resources/images/canvas_zoom_in.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/canvas_zoom_in_disable.svg b/resources/images/canvas_zoom_in_disable.svg new file mode 100644 index 0000000..dc33884 --- /dev/null +++ b/resources/images/canvas_zoom_in_disable.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/canvas_zoom_out.svg b/resources/images/canvas_zoom_out.svg new file mode 100644 index 0000000..70d98c9 --- /dev/null +++ b/resources/images/canvas_zoom_out.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/canvas_zoom_out_disable.svg b/resources/images/canvas_zoom_out_disable.svg new file mode 100644 index 0000000..be4f1d5 --- /dev/null +++ b/resources/images/canvas_zoom_out_disable.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/delete2.svg b/resources/images/delete2.svg new file mode 100644 index 0000000..a8598bd --- /dev/null +++ b/resources/images/delete2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/menu_export_toolpaths.svg b/resources/images/menu_export_toolpaths.svg new file mode 100644 index 0000000..1f09490 --- /dev/null +++ b/resources/images/menu_export_toolpaths.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/more.svg b/resources/images/more.svg new file mode 100644 index 0000000..971a27e --- /dev/null +++ b/resources/images/more.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/images/more_dark.svg b/resources/images/more_dark.svg new file mode 100644 index 0000000..1a851cc --- /dev/null +++ b/resources/images/more_dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/images/partskip_retry.svg b/resources/images/partskip_retry.svg new file mode 100644 index 0000000..ff104e9 --- /dev/null +++ b/resources/images/partskip_retry.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/preset_empty.svg b/resources/images/preset_empty.svg new file mode 100644 index 0000000..77c23b8 --- /dev/null +++ b/resources/images/preset_empty.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/preset_empty_dark.svg b/resources/images/preset_empty_dark.svg new file mode 100644 index 0000000..35956e6 --- /dev/null +++ b/resources/images/preset_empty_dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/print_control_partskip.svg b/resources/images/print_control_partskip.svg new file mode 100644 index 0000000..21fe0bd --- /dev/null +++ b/resources/images/print_control_partskip.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/images/print_control_partskip_disable.svg b/resources/images/print_control_partskip_disable.svg new file mode 100644 index 0000000..79d8a90 --- /dev/null +++ b/resources/images/print_control_partskip_disable.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/images/print_control_partskip_hover.svg b/resources/images/print_control_partskip_hover.svg new file mode 100644 index 0000000..b41ffcc --- /dev/null +++ b/resources/images/print_control_partskip_hover.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/images/toolbar_fuzzyskin.svg b/resources/images/toolbar_fuzzyskin.svg new file mode 100644 index 0000000..a22ad11 --- /dev/null +++ b/resources/images/toolbar_fuzzyskin.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/images/toolbar_fuzzyskin_dark.svg b/resources/images/toolbar_fuzzyskin_dark.svg new file mode 100644 index 0000000..34a08fb --- /dev/null +++ b/resources/images/toolbar_fuzzyskin_dark.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/profiles/Q Series/filament/Generic TPU 95A.json b/resources/profiles/Q Series/filament/Generic TPU 95A.json index 4e01588..cc791a5 100644 --- a/resources/profiles/Q Series/filament/Generic TPU 95A.json +++ b/resources/profiles/Q Series/filament/Generic TPU 95A.json @@ -21,5 +21,7 @@ "pressure_advance": ["0.1"], "slow_down_layer_time": ["8"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/profiles/Q Series/filament/QIDI TPU 95A-HF.json b/resources/profiles/Q Series/filament/QIDI TPU 95A-HF.json index 0a9e296..b4968ae 100644 --- a/resources/profiles/Q Series/filament/QIDI TPU 95A-HF.json +++ b/resources/profiles/Q Series/filament/QIDI TPU 95A-HF.json @@ -22,5 +22,7 @@ "pressure_advance": ["0.1"], "slow_down_layer_time": ["8"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/profiles/X 3 Series/filament/Generic TPU 95A.json b/resources/profiles/X 3 Series/filament/Generic TPU 95A.json index e03c2f6..681508c 100644 --- a/resources/profiles/X 3 Series/filament/Generic TPU 95A.json +++ b/resources/profiles/X 3 Series/filament/Generic TPU 95A.json @@ -21,5 +21,7 @@ "pressure_advance": ["0.1"], "slow_down_layer_time": ["8"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/profiles/X 3 Series/filament/QIDI TPU 95A-HF.json b/resources/profiles/X 3 Series/filament/QIDI TPU 95A-HF.json index 591caf2..f210eef 100644 --- a/resources/profiles/X 3 Series/filament/QIDI TPU 95A-HF.json +++ b/resources/profiles/X 3 Series/filament/QIDI TPU 95A-HF.json @@ -22,5 +22,7 @@ "pressure_advance": ["0.1"], "slow_down_layer_time": ["8"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/profiles/X 4 Series/filament/Generic TPU 95A.json b/resources/profiles/X 4 Series/filament/Generic TPU 95A.json index a02a76a..b267403 100644 --- a/resources/profiles/X 4 Series/filament/Generic TPU 95A.json +++ b/resources/profiles/X 4 Series/filament/Generic TPU 95A.json @@ -18,5 +18,7 @@ "nozzle_temperature": ["230"], "pressure_advance": ["0.1"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/profiles/X 4 Series/filament/QIDI TPU 95A-HF.json b/resources/profiles/X 4 Series/filament/QIDI TPU 95A-HF.json index 4ebbac5..b470e78 100644 --- a/resources/profiles/X 4 Series/filament/QIDI TPU 95A-HF.json +++ b/resources/profiles/X 4 Series/filament/QIDI TPU 95A-HF.json @@ -19,5 +19,7 @@ "nozzle_temperature": ["230"], "pressure_advance": ["0.1"], "temperature_vitrification": ["30"], + "textured_plate_temp_initial_layer" : ["35"], + "textured_plate_temp" : ["35"], "compatible_printers": [] } diff --git a/resources/web/filament/index.html b/resources/web/filament/index.html index d0e357c..f689f81 100644 --- a/resources/web/filament/index.html +++ b/resources/web/filament/index.html @@ -42,7 +42,7 @@ border: none; } - tr:nth-child(2) td, tr:nth-child(3) td, tr:nth-child(4) td, tr:nth-child(5) td, tr:nth-child(6) td, tr:nth-child(9) td, tr:nth-child(13) td, tr:nth-child(14) td, tr:nth-child(15) td, tr:nth-child(16) td, tr:nth-child(17) td, tr:nth-child(18) td, tr:nth-child(19) td { + tr:nth-child(2) td, tr:nth-child(3) td, tr:nth-child(4) td, tr:nth-child(5) td, tr:nth-child(6) td, tr:nth-child(9) td, tr:nth-child(13) td, tr:nth-child(14) td, tr:nth-child(15) td, tr:nth-child(16) td, tr:nth-child(17) td, tr:nth-child(18) td, tr:nth-child(19),tr:nth-child(20) td { height: 20px; } @@ -145,6 +145,9 @@ tr:nth-child(18),tr:nth-child(18) td:nth-child(1) { border-bottom: 1px solid #ccc; } + tr:nth-child(19),tr:nth-child(19) td:nth-child(1) { + border-bottom: 1px solid #ccc; + } .unselected { @@ -359,6 +362,8 @@ "Print speed": "Print speed", "Post processing": "Post processing", "Anneal": "Anneal", + "QIDI BOX settings": "QIDI BOX settings", + "Is QIDI BOX applicable": "Is QIDI BOX applicable", "Compare filaments": "Compare filaments:" }, zh_CN: { @@ -384,6 +389,8 @@ "Print speed": "打印速度", "Post processing": "打印后处理", "Anneal": "退火", + "QIDI BOX settings": "QIDI BOX设置", + "Is QIDI BOX applicable": "是否适用QIDI BOX", "Compare filaments": "比较耗材:" }, fr_FR: { @@ -409,6 +416,8 @@ "Print speed": "Vitesse d'impression", "Post processing": "Post - traitement", "Anneal": "Anneal", + "QIDI BOX settings": "Paramètres QIDI BOX", + "Is QIDI BOX applicable": "Est-ce que QIDI BOX est applicable", "Compare filaments": "Comparer les filaments:" }, cs_CZ: { @@ -434,6 +443,8 @@ "Print speed": "Rychlost tisku", "Post processing": "Pozpracování", "Anneal": "Rozšíření", + "QIDI BOX settings": "Nastavení QIDI BOX", + "Is QIDI BOX applicable": "Je použitelná QIDI BOX", "Compare filaments": "Porovnat vlákna:" }, de_DE: { @@ -459,6 +470,8 @@ "Print speed": "Druckgeschwindigkeit", "Post processing": "Nachbearbeitung", "Anneal": "Anneal", + "QIDI BOX settings": "QIDI BOX-Einstellungen", + "Is QIDI BOX applicable": "Ist QIDI BOX anwendbar", "Compare filaments": "Filamente vergleichen:" }, es_ES: { @@ -484,6 +497,8 @@ "Print speed": "Velocidad de impresión", "Post processing": "Reprocesamiento", "Anneal": "Anneal", + "QIDI BOX settings": "Configuración de QIDI BOX", + "Is QIDI BOX applicable": "Es aplicable QIDI BOX", "Compare filaments": "Filamentos comparativos:" }, hu_HU: { @@ -509,6 +524,8 @@ "Print speed": "Nyomtatási sebesség", "Post processing": "Utófeldolgozás", "Anneal": "Melléklet", + "QIDI BOX settings": "QIDI BOX beállítások", + "Is QIDI BOX applicable": "QIDI BOX alkalmazandó", "Compare filaments": "Szálak összehasonlítása:" }, it_IT: { @@ -534,6 +551,8 @@ "Print speed": "Velocità di stampa", "Post processing": "Post-elaborazione", "Anneal": "Allegato", + "QIDI BOX settings": "Impostazioni QIDI BOX", + "Is QIDI BOX applicable": "È applicabile QIDI BOX", "Compare filaments": "Confronta filamenti:" }, ja_JP: { @@ -559,6 +578,8 @@ "Print speed": "印刷速度", "Post processing": "後処理", "Anneal": "Anneal", + "QIDI BOX settings": "QIDI BOX設定", + "Is QIDI BOX applicable": "QIDIボックス適用か", "Compare filaments": "ひかくフィラメント:" }, ko_KR: { @@ -584,6 +605,8 @@ "Print speed": "인쇄 속도", "Post processing": "후처리", "Anneal": "Anneal", + "QIDI BOX settings": "QIDI BOX 설정", + "Is QIDI BOX applicable": "QIDI BOX 적용 가능합니까", "Compare filaments": "비교적 긴 실:" }, nl_NL: { @@ -609,6 +632,8 @@ "Print speed": "Afdruksnelheid", "Post processing": "Postverwerking", "Anneal": "Anneal", + "QIDI BOX settings": "QIDI BOX instellingen", + "Is QIDI BOX applicable": "Is QIDI BOX van toepassing", "Compare filaments": "Filamenten vergelijken:" }, pl_PL: { @@ -634,6 +659,8 @@ "Print speed": "Szybkość drukowania", "Post processing": "Przetwarzanie po przetwarzaniu", "Anneal": "Wyżej", + "QIDI BOX settings": "Ustawienia QIDI BOX", + "Is QIDI BOX applicable": "Czy stosuje się QIDI BOX", "Compare filaments": "Porównaj filamenty:" }, ru_RU: { @@ -659,6 +686,8 @@ "Print speed": "Скорость печати", "Post processing": "Постобработка", "Anneal": "Температура обжига", + "QIDI BOX settings": "Настройки QIDI BOX", + "Is QIDI BOX applicable": "применяется ли QIDI BOX", "Compare filaments": "Сравнить" }, sv_SE: { @@ -684,6 +713,8 @@ "Print speed": "Utskriftshastighet", "Post processing": "Efterbehandling", "Anneal": "Bilaga", + "QIDI BOX settings": "QIDI BOX-inställningar", + "Is QIDI BOX applicable": "Är QIDI BOX tillämplig", "Compare filaments": "Jämför glödtrådar:" }, tr_TR: { @@ -709,6 +740,8 @@ "Print speed": "Bastırma hızı", "Post processing": "İşlemi", "Anneal": "Annealfrance. kgm", + "QIDI BOX settings": "QIDI BOX ayarları", + "Is QIDI BOX applicable": "QIDI BOX uygulanabilir mi", "Compare filaments": "Kıyafetleri karşılaştır:" }, uk_UA: { @@ -734,6 +767,8 @@ "Print speed": "Швидкість друку", "Post processing": "Посля обробки", "Anneal": "Анналstar name", + "QIDI BOX settings": "Налаштування QIDI BOX", + "Is QIDI BOX applicable": "Чи застосовується QIDI BOX", "Compare filaments": "Порівняти гілки:" }, pt_BR: { @@ -759,6 +794,8 @@ "Print speed": "Velocidade de impressão", "Post processing": "Pós-processamento", "Anneal": "Anexo", + "QIDI BOX settings": "QIDI BOX settings", + "Is QIDI BOX applicable": "É aplicável o QIDI BOX", "Compare filaments": "Comparar filamentos:" }, @@ -1287,7 +1324,7 @@ document.write('260-280℃');//support for pet/pa document.write('270-280℃');//support for paht document.write(''); - + /*Print speed*/ document.write(''); document.write(''); @@ -1319,7 +1356,7 @@ document.write('<120mm/s');//support for pet/pa document.write('<120mm/s');//support for paht document.write(''); - + /*Post processing*/ document.write(''); document.write('' + getTranslation('Post processing', lang) + ''); @@ -1352,7 +1389,38 @@ document.write('/');//support for paht document.write(''); - + + /*Is QIDI BOX applicable*/ + document.write(''); + document.write('' + getTranslation('QIDI BOX settings', lang) + ''); + document.write('' + getTranslation('Is QIDI BOX applicable', lang) + ''); + document.write('√');//pla + document.write('√');//pla matte + document.write('√');//pla metal + document.write('√');//pla silk + document.write('√');//pla cf + document.write('√');//abs + document.write('√');//abs odorless + document.write('√');//abs metal + document.write('√');//abs gf + document.write('√');//asa + document.write('√');//asa aero + document.write('√');//pa12 cf + document.write('√');//paht cf + document.write('√');//paht gf + document.write('√');//pc abs fr + document.write('√');//pet cf + document.write('√');//pet gf + document.write('√');//petg + document.write('√');//pps-cf + document.write('×');//tpu + document.write('√');//ultra pa + document.write('√');//ultra pa-cf25 + document.write('√');//wood rapido + document.write('×');//tpu aero + document.write('√');//support for pet/pa + document.write('√');//support for paht + document.write(''); diff --git a/src/QIDIStudio.cpp b/src/QIDIStudio.cpp index 0890822..b746e0a 100644 --- a/src/QIDIStudio.cpp +++ b/src/QIDIStudio.cpp @@ -3539,19 +3539,36 @@ int CLI::run(int argc, char **argv) std::vector& flush_multipliers = m_print_config.option("flush_multiplier", true)->values; flush_multipliers.resize(new_extruder_count, 1.f); - ConfigOptionEnumsGeneric* nozzle_volume_opt = nullptr; - if (m_print_config.has("nozzle_volume_type")) - nozzle_volume_opt = m_print_config.option("nozzle_volume_type"); - if (m_extra_config.has("nozzle_volume_type")) - nozzle_volume_opt = m_extra_config.option("nozzle_volume_type"); + std::vector nozzle_flush_dataset(new_extruder_count, 0); + { + std::vector nozzle_flush_dataset_full = m_print_config.option("nozzle_flush_dataset",true)->values; + if (m_print_config.has("printer_extruder_variant")) + nozzle_flush_dataset_full.resize(m_print_config.option("printer_extruder_variant")->size(), 0); + else + nozzle_flush_dataset_full.resize(1, 0); - std::vector volume_type_list; - if (nozzle_volume_opt) { - for (size_t idx = 0; idx < nozzle_volume_opt->values.size(); ++idx) { - volume_type_list.emplace_back(NozzleVolumeType(nozzle_volume_opt->values[idx])); + std::vector extruders; + if (m_print_config.has("extruder_type")) + extruders = m_print_config.option("extruder_type")->values; + else + extruders.resize(1,int(ExtruderType::etDirectDrive)); + + std::vector volume_types; + if (m_print_config.has("nozzle_volume_type")) + volume_types = m_print_config.option("nozzle_volume_type")->values; // get volume type from 3mf + else + volume_types.resize(1, int(NozzleVolumeType::nvtStandard)); + + if(m_extra_config.has("nozzle_volume_type")) // get volume type from input + volume_types = m_extra_config.option("nozzle_volume_type")->values; + + for (int eidx = 0; eidx < new_extruder_count; ++eidx) { + int index = 0; + if (m_print_config.has("printer_extruder_id") && m_print_config.has("printer_extruder_variant")) + index = m_print_config.get_index_for_extruder(eidx + 1, "printer_extruder_id", ExtruderType(extruders[eidx]), NozzleVolumeType(volume_types[eidx]), "printer_extruder_variant"); + nozzle_flush_dataset[eidx] = nozzle_flush_dataset_full[index]; } } - volume_type_list.resize(new_extruder_count, NozzleVolumeType::nvtStandard); for (size_t nozzle_id = 0; nozzle_id < new_extruder_count; ++nozzle_id) { std::vector flush_vol_mtx = get_flush_volumes_matrix(flush_vol_matrix, nozzle_id, new_extruder_count); @@ -3573,7 +3590,7 @@ int CLI::run(int argc, char **argv) unsigned char to_rgb[4] = {}; Slic3r::GUI::BitmapCache::parse_color4(to_color, to_rgb); - Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], Slic3r::g_max_flush_volume, new_extruder_count > 1, volume_type_list[nozzle_id]); + Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], Slic3r::g_max_flush_volume,nozzle_flush_dataset[nozzle_id]); flushing_volume = calculator.calc_flush_vol(from_rgb[3], from_rgb[0], from_rgb[1], from_rgb[2], to_rgb[3], to_rgb[0], to_rgb[1], to_rgb[2]); if (is_from_support) { flushing_volume = std::max(Slic3r::g_min_flush_volume_from_support, flushing_volume); } } @@ -4901,6 +4918,37 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(debug) << boost::format("plate %1%: no arrange, directly translate object %2% by {%3%, %4%}") % (i+1) % mo->name %plate_origin(0) %plate_origin(1); } + + bool is_seq_print = false; + get_print_sequence(cur_plate, m_print_config, is_seq_print); + + if (!is_seq_print && assemble_plate.filaments_count > 1) + { + //prepare the wipe tower + auto printer_structure_opt = m_print_config.option>("printer_structure"); + // set the default position, the same with print config(left top) + float x = WIPE_TOWER_DEFAULT_X_POS; + float y = WIPE_TOWER_DEFAULT_Y_POS; + if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) { + x = I3_WIPE_TOWER_DEFAULT_X_POS; + y = I3_WIPE_TOWER_DEFAULT_Y_POS; + } + if (x < WIPE_TOWER_MARGIN) { + x = WIPE_TOWER_MARGIN; + } + if (y < WIPE_TOWER_MARGIN) { + y = WIPE_TOWER_MARGIN; + } + + //create the options using default if neccessary + ConfigOptionFloats* wipe_x_option = m_print_config.option("wipe_tower_x", true); + ConfigOptionFloats* wipe_y_option = m_print_config.option("wipe_tower_y", true); + ConfigOptionFloat wt_x_opt(x); + ConfigOptionFloat wt_y_opt(y); + + wipe_x_option->set_at(&wt_x_opt, i, 0); + wipe_y_option->set_at(&wt_y_opt, i, 0); + } } } diff --git a/src/earcut/CHANGELOG.md b/src/earcut/CHANGELOG.md new file mode 100644 index 0000000..41d9e67 --- /dev/null +++ b/src/earcut/CHANGELOG.md @@ -0,0 +1,27 @@ +## Earcut.hpp changelog + +### master + + - Fixed a bunch of rare edge cases that led to bad triangulation (parity with Earcut v2.2.2) + - Removed use of deprecated `std::allocator::construct` + - Fixed a minor z-order hashing bug + - Improved visualization app, better docs + +### v0.12.4 + + - Fixed a crash in Crash in Earcut::findHoleBridge + - Added coverage checks + - Added macOS, MinGW builds + +### v0.12.3 + + - Fixed -Wunused-lambda-capture + +### v0.12.2 + + - Fixed potential division by zero + - Fixed -fsanitize=integer warning + +### v0.12.1 + + - Fixed cast precision warning diff --git a/src/earcut/CMakeLists.txt b/src/earcut/CMakeLists.txt new file mode 100644 index 0000000..08c7bb1 --- /dev/null +++ b/src/earcut/CMakeLists.txt @@ -0,0 +1,151 @@ +cmake_minimum_required(VERSION 3.2) +project(earcut_hpp LANGUAGES CXX C) + +option(EARCUT_BUILD_TESTS "Build the earcut test program" ON) +option(EARCUT_BUILD_BENCH "Build the earcut benchmark program" ON) +option(EARCUT_BUILD_VIZ "Build the earcut visualizer program" ON) +option(EARCUT_WARNING_IS_ERROR "Treat warnings as errors" OFF) + +if (NOT CMAKE_BUILD_TYPE AND NOT GENERATOR_IS_MULTI_CONFIG) + message(STATUS "No build type specified. Setting to 'Release'") + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "The type of build." FORCE) +endif() + + +include(GNUInstallDirs) + +add_library(earcut_hpp INTERFACE) +add_library(earcut_hpp::earcut_hpp ALIAS earcut_hpp) + +target_include_directories(earcut_hpp INTERFACE + $ + $ +) + +set(CMAKE_CXX_STANDARD 11) + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 3.7) + # Allow C++11 requirements to propagate when using recent CMake versions + target_compile_features(earcut_hpp INTERFACE cxx_std_11) +endif() + +file(GLOB FIXTURE_SOURCE_FILES test/fixtures/*.cpp test/fixtures/*.hpp) +source_group(fixtures FILES ${FIXTURE_SOURCE_FILES}) +add_library(fixtures OBJECT ${FIXTURE_SOURCE_FILES}) +target_compile_options(fixtures PRIVATE $<$:/Od>) + +# In CMake 3.12, use target_link_libraries(fixtures PUBLIC earcut_hpp libtess2). +# Since we support down to CMake 3.2, we need to manually propagate usage requirements of earcut_hpp +target_include_directories(fixtures PRIVATE "$") +target_compile_features(fixtures PRIVATE "$") + + +file(GLOB COMPARISON_SOURCE_FILES test/comparison/*.cpp test/comparison/*.hpp) +source_group(comparison FILES ${COMPARISON_SOURCE_FILES}) +# this is interface since there is no cpp files in the comparison directory +add_library(comparison INTERFACE) + + +file(GLOB LIBTESS2_SOURCE_FILES test/comparison/libtess2/*.c test/comparison/libtess2/*.h) +source_group(comparison/libtess2 FILES ${LIBTESS2_SOURCE_FILES}) +add_library(libtess2 ${LIBTESS2_SOURCE_FILES}) +target_compile_options(libtess2 PRIVATE + $<$:/wd4244 /wd4267> + $<$>:-w> +) + +add_library(common INTERFACE) +target_link_libraries(common INTERFACE libtess2 comparison) + +# optional: -march=native (builds with the optimizations available on the build machine (only for local use!)) +target_compile_options(common INTERFACE + $<$>:-pipe -Wall -Wextra -Wconversion -Wpedantic> +) + +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$" OR CMAKE_COMPILER_IS_GNUCXX) + if ("${CMAKE_CXX_FLAGS}" MATCHES "--coverage") + # We disable debug code for the coverage so it won't see assertion and other things only enabled for debugging + target_compile_definitions(common INTERFACE NDEBUG) + else() + # Here we enable the undefined behavior sanitizer for the tests, benchmarks and the viz + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-fsanitize=undefined" HAVE_FLAG_SANITIZE_UNDEFINED) + if(HAVE_FLAG_SANITIZE_UNDEFINED) + target_compile_options(common INTERFACE $<$:-fsanitize=undefined>) + # TODO: Replace with target link option once we support CMake 3.13 + target_link_libraries(common INTERFACE $<$:-fsanitize=undefined>) + endif() + endif() +endif() + +if (EARCUT_WARNING_IS_ERROR) + target_compile_options(common INTERFACE + $<$:/WX> + $<$>:-Werror> + ) +endif() + +if (EARCUT_BUILD_TESTS) + enable_testing() + add_executable(tests test/tap.cpp test/tap.hpp test/test.cpp $) + target_link_libraries(tests PRIVATE earcut_hpp common) + add_test(NAME earcut_tests COMMAND tests) +endif() +if (EARCUT_BUILD_BENCH) + add_executable(bench test/bench.cpp $) + target_link_libraries(bench PRIVATE earcut_hpp common) +endif() +if (EARCUT_BUILD_VIZ) + add_executable(viz test/viz.cpp $) + + # Setup viz target + # OpenGL + # linux: xorg-dev libgl1-mesa-glx libgl1-mesa-dev + # windows: in the windows sdk + find_package(OpenGL REQUIRED) + + # GLFW3 + find_package(glfw3 QUIET) # try to use the system default + if (NOT glfw3_FOUND) + if(EXISTS "${PROJECT_SOURCE_DIR}/.gitmodules") + find_package(Git REQUIRED) + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_QUIET + ERROR_QUIET + ) + endif() + + set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Build the GLFW example programs" FORCE) + set(GLFW_BUILD_TESTS OFF CACHE BOOL "Build the GLFW test programs" FORCE) + set(GLFW_BUILD_DOCS OFF CACHE BOOL "Build the GLFW documentation" FORCE) + set(GLFW_INSTALL OFF CACHE BOOL "Generate installation target" FORCE) + add_subdirectory(glfw) + endif() + + target_compile_definitions(viz PRIVATE GL_SILENCE_DEPRECATION) + + # TODO: Using old variables for OpenGL package since they were added in CMake 3.8 + target_link_libraries(viz PRIVATE earcut_hpp common glfw ${OPENGL_LIBRARIES}) + target_include_directories(viz PRIVATE ${OPENGL_INCLUDE_DIR}) +endif() + +install( + DIRECTORY include/mapbox + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.hpp" +) + +install(TARGETS earcut_hpp EXPORT earcut_hpp-config) + +# Since there is two projects, we need to export into the parent directory +export( + TARGETS earcut_hpp + NAMESPACE earcut_hpp:: + FILE "${PROJECT_BINARY_DIR}/earcut_hpp-config.cmake" +) + +install(EXPORT earcut_hpp-config + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/earcut_hpp" + NAMESPACE earcut_hpp:: +) diff --git a/src/earcut/LICENSE b/src/earcut/LICENSE new file mode 100644 index 0000000..8bafb57 --- /dev/null +++ b/src/earcut/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2015, Mapbox + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/src/earcut/README.md b/src/earcut/README.md new file mode 100644 index 0000000..67f235b --- /dev/null +++ b/src/earcut/README.md @@ -0,0 +1,131 @@ +## Earcut + +A C++ port of [earcut.js](https://github.com/mapbox/earcut), a fast, [header-only](https://github.com/mapbox/earcut.hpp/blob/master/include/mapbox/earcut.hpp) polygon triangulation library. + +[![Travis](https://img.shields.io/travis/com/mapbox/earcut.hpp.svg)](https://travis-ci.com/github/mapbox/earcut.hpp) +[![AppVeyor](https://ci.appveyor.com/api/projects/status/a1ysrqd69mqn7coo/branch/master?svg=true)](https://ci.appveyor.com/project/Mapbox/earcut-hpp-8wm4o/branch/master) +[![Coverage](https://img.shields.io/coveralls/github/mapbox/earcut.hpp.svg)](https://coveralls.io/github/mapbox/earcut.hpp) +[![Coverity Scan](https://img.shields.io/coverity/scan/14000.svg)](https://scan.coverity.com/projects/14000) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/mapbox/earcut.hpp.svg)](http://isitmaintained.com/project/mapbox/earcut.hpp "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/mapbox/earcut.hpp.svg)](http://isitmaintained.com/project/mapbox/earcut.hpp "Percentage of issues still open") +[![Mourner](https://img.shields.io/badge/simply-awesome-brightgreen.svg)](https://github.com/mourner/projects) + +The library implements a modified ear slicing algorithm, optimized by [z-order curve](http://en.wikipedia.org/wiki/Z-order_curve) hashing and extended to handle holes, twisted polygons, degeneracies and self-intersections in a way that doesn't _guarantee_ correctness of triangulation, but attempts to always produce acceptable results for practical data like geographical shapes. + +It's based on ideas from [FIST: Fast Industrial-Strength Triangulation of Polygons](http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html) by Martin Held and [Triangulation by Ear Clipping](http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) by David Eberly. + +## Usage + +```cpp +#include +``` +```cpp +// The number type to use for tessellation +using Coord = double; + +// The index type. Defaults to uint32_t, but you can also pass uint16_t if you know that your +// data won't have more than 65536 vertices. +using N = uint32_t; + +// Create array +using Point = std::array; +std::vector> polygon; + +// Fill polygon structure with actual data. Any winding order works. +// The first polyline defines the main polygon. +polygon.push_back({{100, 0}, {100, 100}, {0, 100}, {0, 0}}); +// Following polylines define holes. +polygon.push_back({{75, 25}, {75, 75}, {25, 75}, {25, 25}}); + +// Run tessellation +// Returns array of indices that refer to the vertices of the input polygon. +// e.g: the index 6 would refer to {25, 75} in this example. +// Three subsequent indices form a triangle. Output triangles are clockwise. +std::vector indices = mapbox::earcut(polygon); +``` + +Earcut can triangulate a simple, planar polygon of any winding order including holes. It will even return a robust, acceptable solution for non-simple poygons. Earcut works on a 2D plane. If you have three or more dimensions, you can project them onto a 2D surface before triangulation, or use a more suitable library for the task (e.g [CGAL](https://doc.cgal.org/latest/Triangulation_3/index.html)). + + +It is also possible to use your custom point type as input. There are default accessors defined for `std::tuple`, `std::pair`, and `std::array`. For a custom type (like Clipper's `IntPoint` type), do this: + +```cpp +// struct IntPoint { +// int64_t X, Y; +// }; + +namespace mapbox { +namespace util { + +template <> +struct nth<0, IntPoint> { + inline static auto get(const IntPoint &t) { + return t.X; + }; +}; +template <> +struct nth<1, IntPoint> { + inline static auto get(const IntPoint &t) { + return t.Y; + }; +}; + +} // namespace util +} // namespace mapbox +``` + +You can also use a custom container type for your polygon. Similar to std::vector, it has to meet the requirements of [Container](https://en.cppreference.com/w/cpp/named_req/Container), in particular `size()`, `empty()` and `operator[]`. + +

+ example triangulation +

+ +## Additional build instructions +In case you just want to use the earcut triangulation library; copy and include the header file [``](https://github.com/mapbox/earcut.hpp/blob/master/include/mapbox/earcut.hpp) in your project and follow the steps documented in the section [Usage](#usage). + +If you want to build the test, benchmark and visualization programs instead, follow these instructions: + +### Dependencies + +Before you continue, make sure to have the following tools and libraries installed: + * git ([Ubuntu](https://help.ubuntu.com/lts/serverguide/git.html)/[Windows/macOS](http://git-scm.com/downloads)) + * cmake 3.2+ ([Ubuntu](https://launchpad.net/~george-edison55/+archive/ubuntu/cmake-3.x)/[Windows/macOS](https://cmake.org/download/)) + * OpenGL SDK ([Ubuntu](http://packages.ubuntu.com/de/trusty/libgl1-mesa-dev)/[Windows](https://dev.windows.com/en-us/downloads/windows-10-sdk)/[macOS](https://developer.apple.com/opengl/)) + * Compiler such as [GCC 4.9+, Clang 3.4+](https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test), [MSVC12+](https://www.visualstudio.com/) + +Note: On some operating systems such as Windows, manual steps are required to add cmake and [git](http://blog.countableset.ch/2012/06/07/adding-git-to-windows-7-path/) to your PATH environment variable. + +### Manual compilation + +```bash +git clone --recursive https://github.com/mapbox/earcut.hpp.git +cd earcut.hpp +mkdir build +cd build +cmake .. +make +# ./tests +# ./bench +# ./viz +``` + +### [Visual Studio](https://www.visualstudio.com/), [Eclipse](https://eclipse.org/), [XCode](https://developer.apple.com/xcode/), ... + +```batch +git clone --recursive https://github.com/mapbox/earcut.hpp.git +cd earcut.hpp +mkdir project +cd project +cmake .. -G "Visual Studio 14 2015" +::you can also generate projects for "Visual Studio 12 2013", "XCode", "Eclipse CDT4 - Unix Makefiles" +``` +After completion, open the generated project with your IDE. + + +### [CLion](https://www.jetbrains.com/clion/), [Visual Studio 2017+](https://www.visualstudio.com/) + +Import the project from https://github.com/mapbox/earcut.hpp.git and you should be good to go! + +## Status + +This is currently based on [earcut 2.2.4](https://github.com/mapbox/earcut#224-jul-5-2022). diff --git a/src/earcut/earcut.hpp b/src/earcut/earcut.hpp new file mode 100644 index 0000000..fd33814 --- /dev/null +++ b/src/earcut/earcut.hpp @@ -0,0 +1,814 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapbox { + +namespace util { + +template struct nth { + inline static typename std::tuple_element::type + get(const T& t) { return std::get(t); }; +}; + +} + +namespace detail { + +template +class Earcut { +public: + std::vector indices; + std::size_t vertices = 0; + + template + void operator()(const Polygon& points); + +private: + struct Node { + Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {} + Node(const Node&) = delete; + Node& operator=(const Node&) = delete; + Node(Node&&) = delete; + Node& operator=(Node&&) = delete; + + const N i; + const double x; + const double y; + + // previous and next vertice nodes in a polygon ring + Node* prev = nullptr; + Node* next = nullptr; + + // z-order curve value + int32_t z = 0; + + // previous and next nodes in z-order + Node* prevZ = nullptr; + Node* nextZ = nullptr; + + // indicates whether this is a steiner point + bool steiner = false; + }; + + template Node* linkedList(const Ring& points, const bool clockwise); + Node* filterPoints(Node* start, Node* end = nullptr); + void earcutLinked(Node* ear, int pass = 0); + bool isEar(Node* ear); + bool isEarHashed(Node* ear); + Node* cureLocalIntersections(Node* start); + void splitEarcut(Node* start); + template Node* eliminateHoles(const Polygon& points, Node* outerNode); + Node* eliminateHole(Node* hole, Node* outerNode); + Node* findHoleBridge(Node* hole, Node* outerNode); + bool sectorContainsSector(const Node* m, const Node* p); + void indexCurve(Node* start); + Node* sortLinked(Node* list); + int32_t zOrder(const double x_, const double y_); + Node* getLeftmost(Node* start); + bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const; + bool isValidDiagonal(Node* a, Node* b); + double area(const Node* p, const Node* q, const Node* r) const; + bool equals(const Node* p1, const Node* p2); + bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2); + bool onSegment(const Node* p, const Node* q, const Node* r); + int sign(double val); + bool intersectsPolygon(const Node* a, const Node* b); + bool locallyInside(const Node* a, const Node* b); + bool middleInside(const Node* a, const Node* b); + Node* splitPolygon(Node* a, Node* b); + template Node* insertNode(std::size_t i, const Point& p, Node* last); + void removeNode(Node* p); + + bool hashing; + double minX, maxX; + double minY, maxY; + double inv_size = 0; + + template > + class ObjectPool { + public: + ObjectPool() { } + ObjectPool(std::size_t blockSize_) { + reset(blockSize_); + } + ~ObjectPool() { + clear(); + } + template + T* construct(Args&&... args) { + if (currentIndex >= blockSize) { + currentBlock = alloc_traits::allocate(alloc, blockSize); + allocations.emplace_back(currentBlock); + currentIndex = 0; + } + T* object = ¤tBlock[currentIndex++]; + alloc_traits::construct(alloc, object, std::forward(args)...); + return object; + } + void reset(std::size_t newBlockSize) { + for (auto allocation : allocations) { + alloc_traits::deallocate(alloc, allocation, blockSize); + } + allocations.clear(); + blockSize = std::max(1, newBlockSize); + currentBlock = nullptr; + currentIndex = blockSize; + } + void clear() { reset(blockSize); } + private: + T* currentBlock = nullptr; + std::size_t currentIndex = 1; + std::size_t blockSize = 1; + std::vector allocations; + Alloc alloc; + typedef typename std::allocator_traits alloc_traits; + }; + ObjectPool nodes; +}; + +template template +void Earcut::operator()(const Polygon& points) { + // reset + indices.clear(); + vertices = 0; + + if (points.empty()) return; + + double x; + double y; + int threshold = 80; + std::size_t len = 0; + + for (size_t i = 0; threshold >= 0 && i < points.size(); i++) { + threshold -= static_cast(points[i].size()); + len += points[i].size(); + } + + //estimate size of nodes and indices + nodes.reset(len * 3 / 2); + indices.reserve(len + points[0].size()); + + Node* outerNode = linkedList(points[0], true); + if (!outerNode || outerNode->prev == outerNode->next) return; + + if (points.size() > 1) outerNode = eliminateHoles(points, outerNode); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + hashing = threshold < 0; + if (hashing) { + Node* p = outerNode->next; + minX = maxX = outerNode->x; + minY = maxY = outerNode->y; + do { + x = p->x; + y = p->y; + minX = std::min(minX, x); + minY = std::min(minY, y); + maxX = std::max(maxX, x); + maxY = std::max(maxY, y); + p = p->next; + } while (p != outerNode); + + // minX, minY and inv_size are later used to transform coords into integers for z-order calculation + inv_size = std::max(maxX - minX, maxY - minY); + inv_size = inv_size != .0 ? (32767. / inv_size) : .0; + } + + earcutLinked(outerNode); + + nodes.clear(); +} + +// create a circular doubly linked list from polygon points in the specified winding order +template template +typename Earcut::Node* +Earcut::linkedList(const Ring& points, const bool clockwise) { + using Point = typename Ring::value_type; + double sum = 0; + const std::size_t len = points.size(); + std::size_t i, j; + Node* last = nullptr; + + // calculate original winding order of a polygon ring + for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) { + const auto& p1 = points[i]; + const auto& p2 = points[j]; + const double p20 = util::nth<0, Point>::get(p2); + const double p10 = util::nth<0, Point>::get(p1); + const double p11 = util::nth<1, Point>::get(p1); + const double p21 = util::nth<1, Point>::get(p2); + sum += (p20 - p10) * (p11 + p21); + } + + // link points into circular doubly-linked list in the specified winding order + if (clockwise == (sum > 0)) { + for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last); + } else { + for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last); + } + + if (last && equals(last, last->next)) { + removeNode(last); + last = last->next; + } + + vertices += len; + + return last; +} + +// eliminate colinear or duplicate points +template +typename Earcut::Node* +Earcut::filterPoints(Node* start, Node* end) { + if (!end) end = start; + + Node* p = start; + bool again; + do { + again = false; + + if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) { + removeNode(p); + p = end = p->prev; + + if (p == p->next) break; + again = true; + + } else { + p = p->next; + } + } while (again || p != end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +template +void Earcut::earcutLinked(Node* ear, int pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && hashing) indexCurve(ear); + + Node* stop = ear; + Node* prev; + Node* next; + + // iterate through ears, slicing them one by one + while (ear->prev != ear->next) { + prev = ear->prev; + next = ear->next; + + if (hashing ? isEarHashed(ear) : isEar(ear)) { + // cut off the triangle + indices.emplace_back(prev->i); + indices.emplace_back(ear->i); + indices.emplace_back(next->i); + + removeNode(ear); + + // skipping the next vertice leads to less sliver triangles + ear = next->next; + stop = next->next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear == stop) { + // try filtering points and slicing again + if (!pass) earcutLinked(filterPoints(ear), 1); + + // if this didn't work, try curing all small self-intersections locally + else if (pass == 1) { + ear = cureLocalIntersections(filterPoints(ear)); + earcutLinked(ear, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass == 2) splitEarcut(ear); + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +template +bool Earcut::isEar(Node* ear) { + const Node* a = ear->prev; + const Node* b = ear; + const Node* c = ear->next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + Node* p = ear->next->next; + + while (p != ear->prev) { + if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && + area(p->prev, p, p->next) >= 0) return false; + p = p->next; + } + + return true; +} + +template +bool Earcut::isEarHashed(Node* ear) { + const Node* a = ear->prev; + const Node* b = ear; + const Node* c = ear->next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // triangle bbox; min & max are calculated like this for speed + const double minTX = std::min(a->x, std::min(b->x, c->x)); + const double minTY = std::min(a->y, std::min(b->y, c->y)); + const double maxTX = std::max(a->x, std::max(b->x, c->x)); + const double maxTY = std::max(a->y, std::max(b->y, c->y)); + + // z-order range for the current triangle bbox; + const int32_t minZ = zOrder(minTX, minTY); + const int32_t maxZ = zOrder(maxTX, maxTY); + + // first look for points inside the triangle in increasing z-order + Node* p = ear->nextZ; + + while (p && p->z <= maxZ) { + if (p != ear->prev && p != ear->next && + pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && + area(p->prev, p, p->next) >= 0) return false; + p = p->nextZ; + } + + // then look for points in decreasing z-order + p = ear->prevZ; + + while (p && p->z >= minZ) { + if (p != ear->prev && p != ear->next && + pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && + area(p->prev, p, p->next) >= 0) return false; + p = p->prevZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +template +typename Earcut::Node* +Earcut::cureLocalIntersections(Node* start) { + Node* p = start; + do { + Node* a = p->prev; + Node* b = p->next->next; + + // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) + if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) { + indices.emplace_back(a->i); + indices.emplace_back(p->i); + indices.emplace_back(b->i); + + // remove two nodes involved + removeNode(p); + removeNode(p->next); + + p = start = b; + } + p = p->next; + } while (p != start); + + return filterPoints(p); +} + +// try splitting polygon into two and triangulate them independently +template +void Earcut::splitEarcut(Node* start) { + // look for a valid diagonal that divides the polygon into two + Node* a = start; + do { + Node* b = a->next->next; + while (b != a->prev) { + if (a->i != b->i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + Node* c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a->next); + c = filterPoints(c, c->next); + + // run earcut on each half + earcutLinked(a); + earcutLinked(c); + return; + } + b = b->next; + } + a = a->next; + } while (a != start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +template template +typename Earcut::Node* +Earcut::eliminateHoles(const Polygon& points, Node* outerNode) { + const size_t len = points.size(); + + std::vector queue; + for (size_t i = 1; i < len; i++) { + Node* list = linkedList(points[i], false); + if (list) { + if (list == list->next) list->steiner = true; + queue.push_back(getLeftmost(list)); + } + } + std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) { + return a->x < b->x; + }); + + // process holes from left to right + for (size_t i = 0; i < queue.size(); i++) { + outerNode = eliminateHole(queue[i], outerNode); + } + + return outerNode; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +template +typename Earcut::Node* +Earcut::eliminateHole(Node* hole, Node* outerNode) { + Node* bridge = findHoleBridge(hole, outerNode); + if (!bridge) { + return outerNode; + } + + Node* bridgeReverse = splitPolygon(bridge, hole); + + // filter collinear points around the cuts + filterPoints(bridgeReverse, bridgeReverse->next); + + // Check if input node was removed by the filtering + return filterPoints(bridge, bridge->next); +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +template +typename Earcut::Node* +Earcut::findHoleBridge(Node* hole, Node* outerNode) { + Node* p = outerNode; + double hx = hole->x; + double hy = hole->y; + double qx = -std::numeric_limits::infinity(); + Node* m = nullptr; + + // find a segment intersected by a ray from the hole's leftmost Vertex to the left; + // segment's endpoint with lesser x will be potential connection Vertex + do { + if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) { + double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y); + if (x <= hx && x > qx) { + qx = x; + m = p->x < p->next->x ? p : p->next; + if (x == hx) return m; // hole touches outer segment; pick leftmost endpoint + } + } + p = p->next; + } while (p != outerNode); + + if (!m) return 0; + + // look for points inside the triangle of hole Vertex, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the Vertex of the minimum angle with the ray as connection Vertex + + const Node* stop = m; + double tanMin = std::numeric_limits::infinity(); + double tanCur = 0; + + p = m; + double mx = m->x; + double my = m->y; + + do { + if (hx >= p->x && p->x >= mx && hx != p->x && + pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) { + + tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential + + if (locallyInside(p, hole) && + (tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) { + m = p; + tanMin = tanCur; + } + } + + p = p->next; + } while (p != stop); + + return m; +} + +// whether sector in vertex m contains sector in vertex p in the same coordinates +template +bool Earcut::sectorContainsSector(const Node* m, const Node* p) { + return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0; +} + +// interlink polygon nodes in z-order +template +void Earcut::indexCurve(Node* start) { + assert(start); + Node* p = start; + + do { + p->z = p->z ? p->z : zOrder(p->x, p->y); + p->prevZ = p->prev; + p->nextZ = p->next; + p = p->next; + } while (p != start); + + p->prevZ->nextZ = nullptr; + p->prevZ = nullptr; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +template +typename Earcut::Node* +Earcut::sortLinked(Node* list) { + assert(list); + Node* p; + Node* q; + Node* e; + Node* tail; + int i, numMerges, pSize, qSize; + int inSize = 1; + + for (;;) { + p = list; + list = nullptr; + tail = nullptr; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q->nextZ; + if (!q) break; + } + + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize == 0) { + e = q; + q = q->nextZ; + qSize--; + } else if (qSize == 0 || !q) { + e = p; + p = p->nextZ; + pSize--; + } else if (p->z <= q->z) { + e = p; + p = p->nextZ; + pSize--; + } else { + e = q; + q = q->nextZ; + qSize--; + } + + if (tail) tail->nextZ = e; + else list = e; + + e->prevZ = tail; + tail = e; + } + + p = q; + } + + tail->nextZ = nullptr; + + if (numMerges <= 1) return list; + + inSize *= 2; + } +} + +// z-order of a Vertex given coords and size of the data bounding box +template +int32_t Earcut::zOrder(const double x_, const double y_) { + // coords are transformed into non-negative 15-bit integer range + int32_t x = static_cast((x_ - minX) * inv_size); + int32_t y = static_cast((y_ - minY) * inv_size); + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +template +typename Earcut::Node* +Earcut::getLeftmost(Node* start) { + Node* p = start; + Node* leftmost = start; + do { + if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y)) + leftmost = p; + p = p->next; + } while (p != start); + + return leftmost; +} + +// check if a point lies within a convex triangle +template +bool Earcut::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const { + return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && + (ax - px) * (by - py) >= (bx - px) * (ay - py) && + (bx - px) * (cy - py) >= (cx - px) * (by - py); +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +template +bool Earcut::isValidDiagonal(Node* a, Node* b) { + return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && // dones't intersect other edges + ((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible + (area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || // does not create opposite-facing sectors + (equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); // special zero-length case +} + +// signed area of a triangle +template +double Earcut::area(const Node* p, const Node* q, const Node* r) const { + return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y); +} + +// check if two points are equal +template +bool Earcut::equals(const Node* p1, const Node* p2) { + return p1->x == p2->x && p1->y == p2->y; +} + +// check if two segments intersect +template +bool Earcut::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) { + int o1 = sign(area(p1, q1, p2)); + int o2 = sign(area(p1, q1, q2)); + int o3 = sign(area(p2, q2, p1)); + int o4 = sign(area(p2, q2, q1)); + + if (o1 != o2 && o3 != o4) return true; // general case + + if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 + if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 + if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 + if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 + + return false; +} + +// for collinear points p, q, r, check if point q lies on segment pr +template +bool Earcut::onSegment(const Node* p, const Node* q, const Node* r) { + return q->x <= std::max(p->x, r->x) && + q->x >= std::min(p->x, r->x) && + q->y <= std::max(p->y, r->y) && + q->y >= std::min(p->y, r->y); +} + +template +int Earcut::sign(double val) { + return (0.0 < val) - (val < 0.0); +} + +// check if a polygon diagonal intersects any polygon segments +template +bool Earcut::intersectsPolygon(const Node* a, const Node* b) { + const Node* p = a; + do { + if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i && + intersects(p, p->next, a, b)) return true; + p = p->next; + } while (p != a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +template +bool Earcut::locallyInside(const Node* a, const Node* b) { + return area(a->prev, a, a->next) < 0 ? + area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 : + area(a, b, a->prev) < 0 || area(a, a->next, b) < 0; +} + +// check if the middle Vertex of a polygon diagonal is inside the polygon +template +bool Earcut::middleInside(const Node* a, const Node* b) { + const Node* p = a; + bool inside = false; + double px = (a->x + b->x) / 2; + double py = (a->y + b->y) / 2; + do { + if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y && + (px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x)) + inside = !inside; + p = p->next; + } while (p != a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits +// polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a +// single ring +template +typename Earcut::Node* +Earcut::splitPolygon(Node* a, Node* b) { + Node* a2 = nodes.construct(a->i, a->x, a->y); + Node* b2 = nodes.construct(b->i, b->x, b->y); + Node* an = a->next; + Node* bp = b->prev; + + a->next = b; + b->prev = a; + + a2->next = an; + an->prev = a2; + + b2->next = a2; + a2->prev = b2; + + bp->next = b2; + b2->prev = bp; + + return b2; +} + +// create a node and util::optionally link it with previous one (in a circular doubly linked list) +template template +typename Earcut::Node* +Earcut::insertNode(std::size_t i, const Point& pt, Node* last) { + Node* p = nodes.construct(static_cast(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt)); + + if (!last) { + p->prev = p; + p->next = p; + + } else { + assert(last); + p->next = last->next; + p->prev = last; + last->next->prev = p; + last->next = p; + } + return p; +} + +template +void Earcut::removeNode(Node* p) { + p->next->prev = p->prev; + p->prev->next = p->next; + + if (p->prevZ) p->prevZ->nextZ = p->nextZ; + if (p->nextZ) p->nextZ->prevZ = p->prevZ; +} +} + +template +std::vector earcut(const Polygon& poly) { + mapbox::detail::Earcut earcut; + earcut(poly); + return std::move(earcut.indices); +} +} diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 119cccb..5f3693b 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -335,7 +335,7 @@ static void planner_forward_pass_kernel(GCodeProcessor::TimeBlock& prev, GCodePr // speeds have already been reset, maximized, and reverse planned by reverse planner. // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. - // ǰһblockɼ٣ôҪٵٶȣ¼㵱ǰblockentryٶ + // 如果前一个block不能完成加速,那么要根据其加速到的速度,重新计算当前block的entry速度 if (!prev.flags.nominal_length) { if (prev.feedrate_profile.entry < curr.feedrate_profile.entry) { float entry_speed = std::min(curr.feedrate_profile.entry, max_allowable_speed(-prev.acceleration, prev.feedrate_profile.entry, prev.distance)); @@ -3805,7 +3805,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) TimeMachine::State& prev = machine.prev; std::vector& blocks = machine.blocks; - // m_feedrate gcodeнãڱ֤СٶƵ¸feedrate + // m_feedrate 从gcode中解析获得,在保证最小速度限制的情况下赋给feedrate curr.feedrate = (delta_pos[E] == 0.0f) ? minimum_travel_feedrate(static_cast(i), m_feedrate) : minimum_feedrate(static_cast(i), m_feedrate); @@ -3828,7 +3828,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) block.layer_id = std::max(1, m_layer_id); block.flags.prepare_stage = m_processing_start_custom_gcode; - // calculates block acceleration㵱ǰblockܵļٶ + // calculates block acceleration,计算当前block的最高能到达的加速度 float acceleration = (type == EMoveType::Travel) ? get_travel_acceleration(static_cast(i)) : (is_extrusion_only_move(delta_pos) ? @@ -3862,7 +3862,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) } // calculates block cruise feedrate - // ٳǰϵ㵱ǰblockܵٶ + // 刨除前后关系,单纯计算当前block最高能到达的速度 float min_feedrate_factor = 1.0f; for (unsigned char a = X; a <= E; ++a) { curr.axis_feedrate[a] = curr.feedrate * delta_pos[a] * inv_distance; diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 5df1863..6699c60 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -94,6 +94,8 @@ set(SLIC3R_GUI_SOURCES GUI/Auxiliary.hpp GUI/DailyTips.cpp GUI/DailyTips.hpp + GUI/EncodedFilament.hpp + GUI/EncodedFilament.cpp GUI/Project.cpp GUI/Project.hpp GUI/BackgroundSlicingProcess.cpp @@ -146,6 +148,8 @@ set(SLIC3R_GUI_SOURCES GUI/Gizmos/GLGizmoSimplify.hpp GUI/Gizmos/GLGizmoMmuSegmentation.cpp GUI/Gizmos/GLGizmoMmuSegmentation.hpp + GUI/Gizmos/GLGizmoFuzzySkin.cpp + GUI/Gizmos/GLGizmoFuzzySkin.hpp GUI/Gizmos/GLGizmoFaceDetector.cpp GUI/Gizmos/GLGizmoFaceDetector.hpp GUI/Gizmos/GLGizmoMeasure.cpp @@ -316,6 +320,10 @@ set(SLIC3R_GUI_SOURCES GUI/wxExtensions.hpp GUI/ObjColorDialog.cpp GUI/ObjColorDialog.hpp + GUI/FilamentPickerDialog.cpp + GUI/FilamentPickerDialog.hpp + GUI/FilamentBitmapUtils.cpp + GUI/FilamentBitmapUtils.hpp GUI/WipeTowerDialog.cpp GUI/WipeTowerDialog.hpp GUI/RemovableDriveManager.cpp @@ -332,6 +340,8 @@ set(SLIC3R_GUI_SOURCES GUI/SyncBoxInfoDialog.hpp GUI/SurfaceDrag.cpp GUI/SurfaceDrag.hpp + GUI/TextLines.cpp + GUI/TextLines.hpp GUI/PlateSettingsDialog.cpp GUI/PlateSettingsDialog.hpp GUI/ImGuiWrapper.hpp @@ -376,6 +386,10 @@ set(SLIC3R_GUI_SOURCES GUI/Jobs/UpgradeNetworkJob.cpp GUI/Jobs/ArrangeJob.hpp GUI/Jobs/ArrangeJob.cpp + GUI/Jobs/CreateFontNameImageJob.cpp + GUI/Jobs/CreateFontNameImageJob.hpp + GUI/Jobs/CreateFontStyleImagesJob.cpp + GUI/Jobs/CreateFontStyleImagesJob.hpp GUI/Jobs/OrientJob.hpp GUI/Jobs/OrientJob.cpp GUI/Jobs/RotoptimizeJob.hpp @@ -430,6 +444,8 @@ set(SLIC3R_GUI_SOURCES GUI/NotificationManager.hpp GUI/UnsavedChangesDialog.cpp GUI/UnsavedChangesDialog.hpp + GUI/UserPresetsDialog.cpp + GUI/UserPresetsDialog.hpp GUI/ExtraRenderers.cpp GUI/ExtraRenderers.hpp GUI/ProjectDirtyStateManager.hpp @@ -448,6 +464,11 @@ set(SLIC3R_GUI_SOURCES GUI/BonjourDialog.hpp GUI/BindDialog.cpp GUI/BindDialog.hpp + GUI/PartSkipCommon.hpp + GUI/PartSkipDialog.cpp + GUI/PartSkipDialog.hpp + GUI/SkipPartCanvas.cpp + GUI/SkipPartCanvas.hpp GUI/ModelMall.hpp GUI/ModelMall.cpp GUI/SelectMachine.hpp @@ -506,12 +527,18 @@ set(SLIC3R_GUI_SOURCES GUI/SendMultiMachinePage.cpp GUI/TaskManager.cpp GUI/TaskManager.hpp + Utils/WxFontUtils.cpp + Utils/WxFontUtils.hpp + Utils/EmbossStyleManager.cpp + Utils/EmbossStyleManager.hpp Utils/Http.cpp Utils/Http.hpp Utils/FixModelByWin10.cpp Utils/FixModelByWin10.hpp Utils/Bonjour.cpp Utils/Bonjour.hpp + Utils/QDTUtil.hpp + Utils/QDTUtil.cpp Utils/FileHelp.cpp Utils/FileHelp.hpp Utils/PresetUpdater.cpp diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 224a1f3..de14cff 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -18,8 +18,6 @@ #include #include #include -//B -// #include static const float GROUND_Z = -0.04f; static const std::array DEFAULT_MODEL_COLOR = { 0.3255f, 0.337f, 0.337f, 1.0f }; @@ -270,16 +268,7 @@ bool Bed3D::set_shape(const Pointfs& printable_area, const double printable_heig //QDS: add part plate logic //QDS add default bed -#if 1 - ExPolygon poly{ Polygon::new_scale(printable_area) }; -#else - ExPolygon poly; - for (const Vec2d& p : printable_area) { - poly.contour.append(Point(scale_(p(0) + m_position.x()), scale_(p(1) + m_position.y()))); - } -#endif - - calc_triangles(poly); + m_triangles.reset(); //no need gridline for 3dbed //const BoundingBox& bed_bbox = poly.contour.bounding_box(); @@ -675,6 +664,7 @@ void Bed3D::update_bed_triangles() calc_triangles(poly); // update extended bounding box const_cast(m_extended_bounding_box) = calc_extended_bounding_box(); + } void Bed3D::render_model() const @@ -705,6 +695,9 @@ void Bed3D::render_model() const const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); shader->set_uniform("view_normal_matrix", view_normal_matrix); if (m_build_volume.get_extruder_area_count() > 0) { + auto printable_area = m_build_volume.printable_area(); + std::array full_print_volume = {(float)printable_area[0].x(), (float)printable_area[0].y(), (float)printable_area[2].x(), (float)printable_area[2].y()}; + shader->set_uniform("full_print_volume", full_print_volume); const BuildVolume::BuildSharedVolume& shared_volume = m_build_volume.get_shared_volume(); std::array xy_data = shared_volume.data; shader->set_uniform("print_volume.type", shared_volume.type); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index b8f5031..d05bae4 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1731,8 +1731,12 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { shader->set_uniform("is_text_shape", volume.first->is_text_shape); shader->set_uniform("uniform_color", volume.first->render_color); - shader->set_uniform("z_range", m_z_range, 2); - shader->set_uniform("clipping_plane", m_clipping_plane, 4); + shader->set_uniform("z_range", m_z_range); + shader->set_uniform("clipping_plane", m_clipping_plane); + shader->set_uniform("use_color_clip_plane", m_use_color_clip_plane); + shader->set_uniform("color_clip_plane", m_color_clip_plane); + shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]); + shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]); //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] // %with_outline%volume.first->selected; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5a12c72..86adbf2 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -669,10 +669,15 @@ private: PrintVolume m_render_volume; // z range for clipping in shaders - float m_z_range[2]; + std::array m_z_range; // plane coeffs for clipping in shaders - float m_clipping_plane[4]; + std::array m_clipping_plane; + // plane coeffs for render volumes with different colors in shaders + // used by cut gizmo + std::array m_color_clip_plane; + bool m_use_color_clip_plane{false}; + std::array m_color_clip_plane_colors{ColorRGBA::RED(), ColorRGBA::BLUE()}; struct Slope { @@ -784,6 +789,17 @@ public: m_clipping_plane[3] = coeffs[3]; } + const std::array & get_z_range() const { return m_z_range; } + const std::array &get_clipping_plane() const { return m_clipping_plane; } + + void set_use_color_clip_plane(bool use) { m_use_color_clip_plane = use; } + void set_color_clip_plane(const Vec3d &cp_normal, double offset) + { + for (int i = 0; i < 3; ++i) m_color_clip_plane[i] = -cp_normal[i]; + m_color_clip_plane[3] = offset; + } + void set_color_clip_plane_colors(const std::array &colors) { m_color_clip_plane_colors = colors; } + bool is_slope_GlobalActive() const { return m_slope.isGlobalActive; } bool is_slope_active() const { return m_slope.active; } void set_slope_active(bool active) { m_slope.active = active; } diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index 9d61282..ce57f69 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -9,6 +9,8 @@ #include #include "CalibUtils.hpp" #include "../Utils/ColorSpaceConvert.hpp" +#include "EncodedFilament.hpp" + namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent); @@ -178,6 +180,11 @@ void AMSMaterialsSetting::create_panel_normal(wxWindow* parent) m_clr_picker->Bind(wxEVT_LEFT_DOWN, &AMSMaterialsSetting::on_clr_picker, this); m_sizer_colour->Add(m_clr_picker, 0, 0, 0); + m_clr_name = new Label(parent, wxEmptyString); + m_clr_name->SetForegroundColour(*wxBLACK); + m_clr_name->SetBackgroundColour(*wxWHITE); + m_clr_name->SetFont(Label::Body_13); + m_sizer_colour->Add(m_clr_name, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(10)); wxBoxSizer* m_sizer_temperature = new wxBoxSizer(wxHORIZONTAL); m_title_temperature = new wxStaticText(parent, wxID_ANY, _L("Nozzle\nTemperature"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0); @@ -724,18 +731,34 @@ void AMSMaterialsSetting::set_color(wxColour color) //m_clrData->SetColour(color); m_clr_picker->is_empty(false); m_clr_picker->set_color(color); + + FilamentColor fila_color; + fila_color.m_colors.insert(color); + fila_color.EndSet(m_clr_picker->ctype); + auto clr_query = GUI::wxGetApp().get_filament_color_code_query(); + m_clr_name->SetLabelText(clr_query->GetFilaColorName(ams_filament_id, fila_color)); } void AMSMaterialsSetting::set_empty_color(wxColour color) { m_clr_picker->is_empty(true); m_clr_picker->set_color(color); + m_clr_name->SetLabelText(wxEmptyString); } void AMSMaterialsSetting::set_colors(std::vector colors) { //m_clrData->SetColour(color); m_clr_picker->set_colors(colors); + + if (!colors.empty()) + { + FilamentColor fila_color; + for (const auto& clr : colors) { fila_color.m_colors.insert(clr); } + fila_color.EndSet(m_clr_picker->ctype); + auto clr_query = GUI::wxGetApp().get_filament_color_code_query(); + m_clr_name->SetLabelText(clr_query->GetFilaColorName(ams_filament_id, fila_color)); + } } void AMSMaterialsSetting::set_ctype(int ctype) @@ -1075,11 +1098,6 @@ void AMSMaterialsSetting::post_select_event(int index) { wxPostEvent(m_comboBox_filament, event); } -void AMSMaterialsSetting::msw_rescale() -{ - m_clr_picker->msw_rescale(); -} - void AMSMaterialsSetting::on_select_cali_result(wxCommandEvent &evt) { m_pa_cali_select_id = evt.GetSelection(); @@ -1241,9 +1259,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) PACalibResult default_item; default_item.cali_idx = -1; default_item.filament_id = ams_filament_id; - std::vector machine_list = {"N1", "N2S", "C11", "C12", "C13", "BL-P001", "BL-P002"}; - auto iter = std::find(machine_list.begin(), machine_list.end(), obj->printer_type); - if (iter == machine_list.end()) { + if (obj->is_support_auto_flow_calibration) { default_item.k_value = -1; default_item.n_coef = -1; } @@ -1335,7 +1351,7 @@ void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect) m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); m_input_k_val->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); - //m_clr_picker->msw_rescale(); + m_clr_picker->msw_rescale(); degree->msw_rescale(); bitmap_max_degree->SetBitmap(degree->bmp()); bitmap_min_degree->SetBitmap(degree->bmp()); @@ -1369,6 +1385,7 @@ void ColorPicker::msw_rescale() { m_bitmap_border = create_scaled_bitmap("color_picker_border", nullptr, 25); m_bitmap_border_dark = create_scaled_bitmap("color_picker_border_dark", nullptr, 25); + m_bitmap_transparent = create_scaled_bitmap("transparent_color_picker", nullptr, 25); Refresh(); } @@ -1423,7 +1440,10 @@ void ColorPicker::doRender(wxDC& dc) if (m_selected) radius -= FromDIP(1); if (alpha == 0) { - dc.DrawBitmap(m_bitmap_transparent, 0, 0); + wxSize bmp_size = m_bitmap_transparent.GetSize(); + int center_x = (size.x - bmp_size.x) / 2; + int center_y = (size.y - bmp_size.y) / 2; + dc.DrawBitmap(m_bitmap_transparent, center_x, center_y); } else if (alpha != 254 && alpha != 255) { if (transparent_changed) { @@ -1439,7 +1459,11 @@ void ColorPicker::doRender(wxDC& dc) replace.push_back(fill_replace); m_bitmap_transparent = ScalableBitmap(this, "transparent_color_picker", 25, false, false, true, replace).bmp(); transparent_changed = false; - dc.DrawBitmap(m_bitmap_transparent, 0, 0); + + wxSize bmp_size = m_bitmap_transparent.GetSize(); + int center_x = (size.x - bmp_size.x) / 2; + int center_y = (size.y - bmp_size.y) / 2; + dc.DrawBitmap(m_bitmap_transparent, center_x, center_y); } } else { diff --git a/src/slic3r/GUI/AMSMaterialsSetting.hpp b/src/slic3r/GUI/AMSMaterialsSetting.hpp index 939604d..76bad8c 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.hpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.hpp @@ -108,7 +108,6 @@ public: wxString k = wxEmptyString, wxString n = wxEmptyString); 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 colors); @@ -130,6 +129,7 @@ public: std::string m_filament_type; ColorPickerPopup m_color_picker_popup; ColorPicker * m_clr_picker; + Label* m_clr_name; std::vector m_pa_profile_items; protected: diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index 744fb68..9174062 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -1354,7 +1354,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector tray_data, bool remai // temp if (tray_data[i].type == EMPTY) { - m_mapping_item->set_data(m_tag_material, wxColour(0xCE, 0xCE, 0xCE), "-", remain_detect_flag, tray_data[i]); + m_mapping_item->set_data(m_tag_material, wxColour(0xEE, 0xEE, 0xEE), "-", remain_detect_flag, tray_data[i]); m_mapping_item->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_mapping_item](wxMouseEvent &e) { if (!m_mapping_from_multi_machines) { @@ -1392,7 +1392,7 @@ void AmsMapingPopup::add_ext_ams_mapping(TrayData tray_data, MappingItem* item) item->set_data(m_tag_material, tray_data.colour, tray_data.name, false, tray_data); } else { - item->set_data(m_tag_material, wxColour(0xEE, 0xEE, 0xEE), tray_data.name, false, tray_data, true); + item->set_data(m_tag_material, tray_data.colour, tray_data.name, false, tray_data, true); m_has_unmatch_filament = true; } @@ -1507,8 +1507,8 @@ static void _DrawRemainArea(const MappingItem *item, const TrayData &dd, bool su int full_range_width = size.x; /*range background*/ - dc.SetPen(wxColour(0xE4E4E4)); - dc.SetBrush(wxColour(0xE4E4E4)); + dc.SetPen(wxColour("#E4E4E4")); + dc.SetBrush(wxColour("#E4E4E4")); int bg_height = item->FromDIP(6); int bg_width = full_range_width - (2 * x_margin); dc.DrawRoundedRectangle(x_margin, y_margin, bg_width, bg_height, item->FromDIP(2)); @@ -1565,7 +1565,10 @@ void MappingItem::render(wxDC &dc) dc.SetFont(::Label::Head_13); 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_unmatch || m_name == "-") { txt_colour = wxColour(0xCE, 0xCE, 0xCE); } + // 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); @@ -1598,7 +1601,7 @@ void MappingItem::set_data(const wxString &tag_name, wxColour colour, wxString n if (!m_name.IsEmpty() && (m_name != "-")) { const wxString &msg = wxString::Format(_L("Note: the filament type(%s) does not match with the filament type(%s) in the slicing file. " "If you want to use this slot, you can install %s instead of %s and change slot information on the 'Device' page."), - m_name, tag_name, m_name, tag_name); + m_name, tag_name, tag_name, m_name); SetToolTip(msg); } else { const wxString &msg = wxString::Format(_L("Note: the slot is empty or undefined. If you want to use this slot, you can install %s and change slot information on the 'Device' page."), tag_name); @@ -1606,7 +1609,7 @@ void MappingItem::set_data(const wxString &tag_name, wxColour colour, wxString n } } else { - SetToolTip(_L("Note: Only the BOX slots loaded with the same material type can be selected.")); + SetToolTip(_L("Note: Only filament-loaded slots can be selected.")); } } else @@ -1655,14 +1658,14 @@ void MappingItem::doRender(wxDC &dc) } } } - else if (color.Alpha() == 0 && !m_unmatch) { + else if (color.Alpha() == 0) { dc.DrawBitmap(m_transparent_mapping_item.bmp(), 0, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2 + get_remain_area_height()); } else { dc.DrawRectangle(0, (size.y - MAPPING_ITEM_REAL_SIZE.y) / 2 + get_remain_area_height(), MAPPING_ITEM_REAL_SIZE.x, MAPPING_ITEM_REAL_SIZE.y); } - wxColour side_colour = wxColour(0xE4E4E4); + wxColour side_colour = wxColour("#E4E4E4"); dc.SetPen(side_colour); dc.SetBrush(wxBrush(side_colour)); @@ -2012,14 +2015,14 @@ AmsIntroducePopup::AmsIntroducePopup(wxWindow* parent) m_staticText_top = new Label(this, _L("Do not Enable BOX")); m_staticText_top->SetFont(::Label::Head_13); - // m_staticText_top->SetForegroundColour(wxColour(0x323A3D)); + // m_staticText_top->SetForegroundColour(wxColour("#323A3D")); m_staticText_top->Wrap(-1); bSizer4->Add(m_staticText_top, 0, wxALL, 5); m_staticText_bottom = new Label(this, _L("Print using materials mounted on the back of the case")); m_staticText_bottom->Wrap(-1); m_staticText_bottom->SetFont(::Label::Body_13); - m_staticText_bottom->SetForegroundColour(wxColour(0x6B6B6B)); + m_staticText_bottom->SetForegroundColour(wxColour("#6B6B6B")); bSizer4->Add(m_staticText_bottom, 0, wxALL, 5); wxBoxSizer* bSizer5; @@ -2583,7 +2586,7 @@ void AmsRMGroup::doRender(wxDC& dc) dc.SetPen(*wxTRANSPARENT_PEN); - if (tray_color == *wxWHITE) dc.SetPen(wxPen(wxColour(0xEEEEEE), 2)); + if (tray_color == *wxWHITE) dc.SetPen(wxPen(wxColour("#EEEEEE"), 2)); dc.SetBrush(wxBrush(tray_color)); int x = size.x / 2; @@ -2633,14 +2636,14 @@ void AmsRMGroup::doRender(wxDC& dc) //draw tray dc.SetFont(::Label::Body_12); auto text_size = dc.GetTextExtent(tray_name); - dc.SetTextForeground(tray_color.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x262E30)); - if (tray_color.Alpha() == 0) {dc.SetTextForeground(wxColour(0x262E30));} + dc.SetTextForeground(tray_color.GetLuminance() < 0.6 ? *wxWHITE : wxColour("#262E30")); + if (tray_color.Alpha() == 0) { dc.SetTextForeground(wxColour("#262E30")); } 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)); - if (tray_color.Alpha() == 0) {dc.SetPen(wxPen(wxColour(0xCECECE), 2));} + if (tray_color.Alpha() == 0) { dc.SetPen(wxPen(wxColour("#CECECE"), 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); @@ -2664,7 +2667,7 @@ void AmsRMGroup::doRender(wxDC& dc) //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.SetTextForeground(wxColour("#323A3D")); 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)); @@ -2738,7 +2741,7 @@ void AmsHumidityLevelList::doRender(wxDC& dc) //dry / wet - dc.SetTextForeground(wxColour(0x989898)); + dc.SetTextForeground(wxColour("#989898")); dc.SetFont(::Label::Head_20); auto font_top = GetSize().y - dc.GetTextExtent(_L("DRY")).GetHeight(); diff --git a/src/slic3r/GUI/BonjourDialog.cpp b/src/slic3r/GUI/BonjourDialog.cpp index 9d65254..6edf300 100644 --- a/src/slic3r/GUI/BonjourDialog.cpp +++ b/src/slic3r/GUI/BonjourDialog.cpp @@ -86,6 +86,8 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech) , timer_state(0) , tech(tech) { + SetBackgroundColour(*wxWHITE); + const int em = GUI::wxGetApp().em_unit(); list->SetMinSize(wxSize(40 * em, 30 * em)); list->SetTextColour(StateColor::darkModeColorFor(wxColour("#323A3C"))); diff --git a/src/slic3r/GUI/Calibration.cpp b/src/slic3r/GUI/Calibration.cpp index faf6ff7..c911316 100644 --- a/src/slic3r/GUI/Calibration.cpp +++ b/src/slic3r/GUI/Calibration.cpp @@ -118,7 +118,7 @@ CalibrationDialog::CalibrationDialog(Plater *plater) wxBoxSizer *cali_right_sizer_h = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *cali_right_sizer_v = new wxBoxSizer(wxVERTICAL); - auto cali_right_panel = new StaticBox(body_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(182), FromDIP(160))); + auto cali_right_panel = new StaticBox(body_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(182), FromDIP(200))); cali_right_panel->SetBackgroundColor(BG_COLOR); cali_right_panel->SetBorderColor(BG_COLOR); @@ -222,7 +222,7 @@ void CalibrationDialog::update_cali(MachineObject *obj) select_xcam_cali->Hide(); m_checkbox_list["xcam_cali"]->SetValue(false); } - + if(obj->is_support_bed_leveling != 0){ select_bed_leveling->Show(); }else{ @@ -258,12 +258,14 @@ void CalibrationDialog::update_cali(MachineObject *obj) if (obj->is_calibration_done()) { m_calibration_btn->Enable(); m_calibration_btn->SetLabel(_L("Completed")); + } else { // RUNNING && IDLE m_calibration_btn->Disable(); m_calibration_btn->SetLabel(_L("Calibrating")); + } - auto size = wxSize(CALI_FLOW_CONTENT_WIDTH, obj->stage_list_info.size() * FromDIP(44)); + auto size = wxSize(CALI_FLOW_CONTENT_WIDTH, obj->stage_list_info.size() * FromDIP(35)); if (m_calibration_flow->GetSize().y != size.y) { m_calibration_flow->SetSize(size); m_calibration_flow->SetMinSize(size); @@ -271,6 +273,7 @@ void CalibrationDialog::update_cali(MachineObject *obj) m_calibration_flow->Refresh(); Layout(); + } if (is_stage_list_info_changed(obj)) { // change items if stage_list_info changed diff --git a/src/slic3r/GUI/CalibrationWizard.cpp b/src/slic3r/GUI/CalibrationWizard.cpp index e8bdd92..e8cfadd 100644 --- a/src/slic3r/GUI/CalibrationWizard.cpp +++ b/src/slic3r/GUI/CalibrationWizard.cpp @@ -7,6 +7,7 @@ #include "Tabbook.hpp" #include "CaliHistoryDialog.hpp" #include "CalibUtils.hpp" +#include "QDTUtil.hpp" //w29 #include "MainFrame.hpp" @@ -18,7 +19,6 @@ wxDEFINE_EVENT(EVT_DEVICE_CHANGED, wxCommandEvent); wxDEFINE_EVENT(EVT_CALIBRATION_JOB_FINISHED, wxCommandEvent); static const wxString NA_STR = _L("N/A"); -static const float MIN_PA_K_VALUE_STEP = 0.001; static const int MAX_PA_HISTORY_RESULTS_NUMS = 16; //w29 @@ -26,7 +26,7 @@ CalibrationWizard::CalibrationWizard(wxWindow* parent, CalibMode mode, wxWindowI : wxPanel(parent, id, pos, size, style) , m_mode(mode) { - SetBackgroundColour(wxColour(0xEEEEEE)); + SetBackgroundColour(wxColour("#EEEEEE")); wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/CalibrationWizardPage.cpp b/src/slic3r/GUI/CalibrationWizardPage.cpp index 7363b27..cbabed7 100644 --- a/src/slic3r/GUI/CalibrationWizardPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPage.cpp @@ -2,6 +2,7 @@ #include "I18N.hpp" #include "Widgets/Label.hpp" #include "MsgDialog.hpp" +#include "QDTUtil.hpp" namespace Slic3r { namespace GUI { diff --git a/src/slic3r/GUI/CalibrationWizardPage.hpp b/src/slic3r/GUI/CalibrationWizardPage.hpp index 20dd27e..4828947 100644 --- a/src/slic3r/GUI/CalibrationWizardPage.hpp +++ b/src/slic3r/GUI/CalibrationWizardPage.hpp @@ -226,9 +226,6 @@ public: 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); - } } virtual void msw_rescale(); diff --git a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp index 59de2d0..5028346 100644 --- a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp @@ -5,6 +5,7 @@ #include "MsgDialog.hpp" #include "libslic3r/Print.hpp" #include "Tab.hpp" +#include "QDTUtil.hpp" #define CALIBRATION_LABEL_SIZE wxSize(FromDIP(150), FromDIP(24)) #define SYNC_BUTTON_SIZE (wxSize(FromDIP(50), FromDIP(50))) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 245f09b..bbef7df 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -245,6 +245,28 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con is_msg_dlg_already_exist = false; } + //limit scarf start height + double seam_slope_start_height = config->option("seam_slope_start_height")->get_abs_value(1); + bool reset_slope_start_height = false; + if (config->option("seam_slope_start_height")->percent) { + if (seam_slope_start_height >= 1) + reset_slope_start_height = true; + } else { + if (seam_slope_start_height >= config->opt_float("layer_height")) + reset_slope_start_height = true; + } + + if (reset_slope_start_height) { + const wxString msg_text = _(L("Should not large than layer height.\nReset to 10%")); + 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("seam_slope_start_height", new ConfigOptionFloatOrPercent{10, true}); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } + //QDS: top_area_threshold showed if the top one wall function be applyed bool top_one_wall_apply = config->opt_enum("top_one_wall_type") == TopOneWallType::None; toggle_line("top_area_threshold", !top_one_wall_apply); @@ -602,10 +624,13 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in { bool have_perimeters = config->opt_int("wall_loops") > 0; for (auto el : { "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall", - "seam_position","seam_gap","wipe_speed", "wall_sequence", "outer_wall_line_width", + "seam_position","seam_placement_away_from_overhangs","seam_gap","wipe_speed", "wall_sequence", "outer_wall_line_width", "inner_wall_speed", "outer_wall_speed","small_perimeter_speed", "small_perimeter_threshold" }) toggle_field(el, have_perimeters); + SeamPosition seam_pos = config->option>("seam_position")->value; + toggle_line("seam_placement_away_from_overhangs", seam_pos == SeamPosition::spAligned || seam_pos == SeamPosition::spRear); + bool have_infill = config->option("sparse_infill_density")->value > 0; // sparse_infill_filament uses the same logic as in Print::extruders() for (auto el : { "sparse_infill_pattern", "sparse_infill_anchor_max", "infill_combination", "minimum_sparse_infill_area", "sparse_infill_filament", "infill_shift_step", "infill_rotate_step", "symmetric_infill_y_axis"}) @@ -619,7 +644,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in bool is_locked_zig = config->option>("sparse_infill_pattern")->value == InfillPattern::ipLockedZag; toggle_line("infill_shift_step", is_cross_zag || is_locked_zig); - for (auto el : { "skeleton_infill_density", "skin_infill_density", "infill_lock_depth", "skin_infill_depth","skin_infill_line_width", "skeleton_infill_line_width" }) + for (auto el : {"skeleton_infill_density", "skin_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_line_width", "skeleton_infill_line_width", "locked_skin_infill_pattern", "locked_skeleton_infill_pattern"}) toggle_line(el, is_locked_zig); bool is_zig_zag = config->option>("sparse_infill_pattern")->value == InfillPattern::ipZigZag; @@ -703,13 +728,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in //toggle_field("support_closing_radius", have_support_material && support_style == smsSnug); bool support_is_tree = config->opt_bool("enable_support") && is_tree(support_type); - //1.9.5 for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter", "tree_support_branch_diameter_angle"}) toggle_field(el, support_is_tree); // hide tree support settings when normal is selected - //1.9.5 -for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter", "tree_support_branch_diameter_angle", "max_bridge_length"}) + for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tree_support_branch_diameter", "tree_support_branch_diameter_angle", "max_bridge_length"}) toggle_line(el, support_is_tree); toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree); @@ -753,8 +776,8 @@ for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tr bool have_prime_tower = config->opt_bool("enable_prime_tower"); for (auto el : - {"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap", "prime_tower_enable_framework", "prime_tower_max_speed"}) - toggle_line(el, have_prime_tower); + {"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap", "prime_tower_enable_framework", "prime_tower_max_speed"}) + toggle_line(el, have_prime_tower); bool have_rib_wall = config->opt_bool("prime_tower_rib_wall")&&have_prime_tower; for (auto el : {"prime_tower_extra_rib_length", "prime_tower_rib_width", "prime_tower_fillet_wall"}) @@ -770,6 +793,10 @@ for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tr 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, variant_index); + bool has_height_slowdown = config->opt_bool("enable_height_slowdown", variant_index); + for (auto el : { "slowdown_start_height", "slowdown_start_speed", "slowdown_start_acc", "slowdown_end_height", "slowdown_end_speed", "slowdown_end_acc" }) + toggle_line(el, has_height_slowdown, variant_index); + toggle_line("flush_into_objects", !is_global_config); toggle_line("print_flow_ratio", !is_global_config); @@ -814,6 +841,11 @@ for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tr toggle_field("xy_contour_compensation", !enable_auto_hole_and_contour_compensation); toggle_line("circle_compensation_manual_offset", enable_auto_hole_and_contour_compensation); + // override filament scarf seam settings + bool override_filament_scarf_seam_settings = config->opt_bool("override_filament_scarf_seam_setting"); + for (auto el : {"seam_slope_type", "seam_slope_start_height", "seam_slope_gap", "seam_slope_min_length"}) + toggle_line(el, override_filament_scarf_seam_settings); + //w16 bool is_resonance_avoidance = config->opt_bool("resonance_avoidance", 0); toggle_line("min_resonance_avoidance_speed", is_resonance_avoidance); diff --git a/src/slic3r/GUI/CreatePresetsDialog.cpp b/src/slic3r/GUI/CreatePresetsDialog.cpp index aaf59ac..635cc57 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.cpp +++ b/src/slic3r/GUI/CreatePresetsDialog.cpp @@ -928,7 +928,7 @@ wxBoxSizer *CreateFilamentPresetDialog::create_button_item() m_button_create = new Button(this, _L("Create")); m_button_create->SetBackgroundColor(btn_bg_blue); m_button_create->SetBorderColor(*wxWHITE); - m_button_create->SetTextColor(wxColour(0xFFFFFE)); + m_button_create->SetTextColor(wxColour("#FFFFFE")); m_button_create->SetFont(Label::Body_12); m_button_create->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_create->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -1362,9 +1362,9 @@ void CreateFilamentPresetDialog::update_dialog_size() m_filament_preset_panel->SetSizerAndFit(m_filament_presets_sizer); int width = m_filament_preset_panel->GetSize().GetWidth(); int height = m_filament_preset_panel->GetSize().GetHeight(); - m_scrolled_preset_panel->SetMinSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(600, height + FromDIP(18)))); - m_scrolled_preset_panel->SetMaxSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(600, height + FromDIP(18)))); - m_scrolled_preset_panel->SetSize(wxSize(std::min(1500, width + FromDIP(26)), std::min(600, height + FromDIP(18)))); + m_scrolled_preset_panel->SetMinSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(450, height + FromDIP(18)))); + m_scrolled_preset_panel->SetMaxSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(450, height + FromDIP(18)))); + m_scrolled_preset_panel->SetSize(wxSize(std::min(1500, width + FromDIP(26)), std::min(450, height + FromDIP(18)))); Layout(); Fit(); Refresh(); @@ -2001,7 +2001,7 @@ wxBoxSizer *CreatePrinterPresetDialog::create_page1_btns_item(wxWindow *parent) m_button_OK = new Button(parent, _L("OK")); m_button_OK->SetBackgroundColor(btn_bg_blue); m_button_OK->SetBorderColor(*wxWHITE); - m_button_OK->SetTextColor(wxColour(0xFFFFFE)); + m_button_OK->SetTextColor(wxColour("#FFFFFE")); m_button_OK->SetFont(Label::Body_12); m_button_OK->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_OK->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -2686,7 +2686,7 @@ wxBoxSizer *CreatePrinterPresetDialog::create_page2_btns_item(wxWindow *parent) m_button_create = new Button(parent, _L("Create")); m_button_create->SetBackgroundColor(btn_bg_blue); m_button_create->SetBorderColor(*wxWHITE); - m_button_create->SetTextColor(wxColour(0xFFFFFE)); + m_button_create->SetTextColor(wxColour("#FFFFFE")); m_button_create->SetFont(Label::Body_12); m_button_create->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_create->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -4319,7 +4319,7 @@ wxBoxSizer *ExportConfigsDialog::create_button_item(wxWindow* parent) m_button_ok = new Button(this, _L("OK")); m_button_ok->SetBackgroundColor(btn_bg_blue); m_button_ok->SetBorderColor(*wxWHITE); - m_button_ok->SetTextColor(wxColour(0xFFFFFE)); + m_button_ok->SetTextColor(wxColour("#FFFFFE")); m_button_ok->SetFont(Label::Body_12); m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -4873,7 +4873,7 @@ wxBoxSizer *EditFilamentPresetDialog::create_button_sizer() m_del_filament_btn = new Button(this, _L("Delete Filament")); m_del_filament_btn->SetBackgroundColor(*wxRED); m_del_filament_btn->SetBorderColor(*wxWHITE); - m_del_filament_btn->SetTextColor(wxColour(0xFFFFFE)); + m_del_filament_btn->SetTextColor(wxColour("#FFFFFE")); m_del_filament_btn->SetFont(Label::Body_12); m_del_filament_btn->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_del_filament_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -4888,7 +4888,7 @@ wxBoxSizer *EditFilamentPresetDialog::create_button_sizer() m_ok_btn = new Button(this, _L("OK")); m_ok_btn->SetBackgroundColor(btn_bg_blue); m_ok_btn->SetBorderColor(*wxWHITE); - m_ok_btn->SetTextColor(wxColour(0xFFFFFE)); + m_ok_btn->SetTextColor(wxColour("#FFFFFE")); m_ok_btn->SetFont(Label::Body_12); m_ok_btn->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_ok_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -5088,7 +5088,7 @@ wxBoxSizer *CreatePresetForPrinterDialog::create_button_sizer() m_ok_btn = new Button(this, _L("OK")); m_ok_btn->SetBackgroundColor(btn_bg_blue); m_ok_btn->SetBorderColor(*wxWHITE); - m_ok_btn->SetTextColor(wxColour(0xFFFFFE)); + m_ok_btn->SetTextColor(wxColour("#FFFFFE")); m_ok_btn->SetFont(Label::Body_12); m_ok_btn->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_ok_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); @@ -5253,7 +5253,7 @@ wxPanel *PresetTree::get_child_item(wxPanel *parent, std::shared_ptr pre if (base_id_error) { del_preset_btn->SetBackgroundColor(btn_bg_blue); del_preset_btn->SetBorderColor(btn_bg_blue); - del_preset_btn->SetTextColor(wxColour(0xFFFFFE)); + del_preset_btn->SetTextColor(wxColour("#FFFFFE")); } else { del_preset_btn->SetBackgroundColor(flush_bg_col); del_preset_btn->SetBorderColor(flush_bd_col); diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 161788d..86ba801 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -20,6 +20,8 @@ #include #include "fast_float/fast_float.h" +#include "slic3r/Utils/QDTUtil.hpp" + #define CALI_DEBUG #define MINUTE_30 1800000 //ms #define TIME_OUT 5000 //ms @@ -48,11 +50,11 @@ wxString get_stage_string(int stage) case 5: return _L("M400 pause"); case 6: - return _L("Paused due to filament runout"); + return _L("Paused (filament ran out)"); case 7: - return _L("Heating hotend"); + return _L("Heating nozzle"); case 8: - return _L("Calibrating extrusion"); + return _L("Calibrating dynamic flow"); case 9: return _L("Scanning bed surface"); case 10: @@ -68,51 +70,51 @@ wxString get_stage_string(int stage) case 15: return _L("Checking extruder temperature"); case 16: - return _L("Printing was paused by the user"); + return _L("Paused by the user"); case 17: - return _L("Pause of front cover falling"); + return _L("Pause (front cover fall off)"); case 18: return _L("Calibrating the micro lidar"); case 19: - return _L("Calibrating extrusion flow"); + return _L("Calibrating flow ratio"); case 20: - return _L("Paused due to nozzle temperature malfunction"); + return _L("Pause (nozzle temperature malfunction)"); case 21: - return _L("Paused due to heat bed temperature malfunction"); + return _L("Pause (heatbed temperature malfunction)"); case 22: return _L("Filament unloading"); case 23: - return _L("Skip step pause"); + return _L("Pause (step loss)"); case 24: return _L("Filament loading"); case 25: return _L("Motor noise cancellation"); case 26: - return _L("Paused due to BOX lost"); + return _L("Pause (BOX offline)"); case 27: - return _L("Paused due to low speed of the heat break fan"); + return _L("Pause (low speed of the heatbreak fan)"); case 28: - return _L("Paused due to chamber temperature control error"); + return _L("Pause (chamber temperature control problem)"); case 29: return _L("Cooling chamber"); case 30: - return _L("Paused by the Gcode inserted by user"); + return _L("Pause (Gcode inserted by user)"); case 31: return _L("Motor noise showoff"); case 32: - return _L("Nozzle filament covered detected pause"); + return _L("Pause (nozzle clumping)"); case 33: - return _L("Cutter error pause"); + return _L("Pause (cutter error)"); case 34: - return _L("First layer error pause"); + return _L("Pause (first layer error)"); case 35: - return _L("Nozzle clog pause"); + return _L("Pause (nozzle clog)"); case 36: - return _L("Check printer absolute accuracy before calibration"); + return _L("Measuring motion percision"); case 37: - return _L("Absolute accuracy calibration"); + return _L("Enhancing motion percision"); case 38: - return _L("Check printer absolute accuracy after calibration"); + return _L("Measure motion accuracy"); case 39: return _L("Nozzle offset calibration"); case 40: @@ -126,9 +128,9 @@ wxString get_stage_string(int stage) case 44: return _L("Auto Check: Platform"); case 45: - return _L("Confirming birdeye camera position"); + return _L("Confirming BirdsEye Camera location"); case 46: - return _L("Calibrating birdeye camera"); + return _L("Calibrating BirdsEye Camera"); case 47: return _L("Auto bed leveling -phase 1"); case 48: @@ -136,11 +138,21 @@ wxString get_stage_string(int stage) case 49: return _L("Heating chamber"); case 50: - return _L("Heated bed cooling"); + return _L("Cooling heatbed"); case 51: return _L("Printing calibration lines"); + case 52: + return _L("Auto Check: Material"); + case 53: + return _L("Live View Camera Calibration"); + case 54: + return _L("Waiting for heatbed to reach target temperature"); + case 55: + return _L("Auto Check: Material Position"); + case 56: + return _L("Cutting Module Offset Calibration"); default: - ; + BOOST_LOG_TRIVIAL(info) << "stage = " << stage; } return ""; } @@ -314,7 +326,7 @@ bool check_filaments_printable(const std::string &tag_vendor, const std::string if (filament_info.has_value() && !(filament_info->filament_printable >> extruder_idx & 1)) { wxString extruder_name = extruder_idx == 0 ? _L("left") : _L("right"); ac = "prohibition"; - info = (wxString::Format(_L("%s is not supported by %s extruder."), tag_type, extruder_name)).ToUTF8().data(); + info = wxString::Format(_L("%s is not supported by %s extruder."), tag_type, extruder_name); in_blacklist = true; return false; } @@ -618,6 +630,14 @@ std::string MachineObject::convertToIp(long long ip) return ss.str(); } +std::string MachineObject::get_show_printer_type() const +{ + std::string printer_type = this->printer_type; + if (this->is_support_upgrade_kit && this->installed_upgrade_kit) + printer_type = "C12"; + return printer_type; +} + PrinterSeries MachineObject::get_printer_series() const { std::string series = DeviceManager::get_printer_series(printer_type); @@ -922,6 +942,10 @@ std::string MachineObject::get_filament_id(std::string ams_id, std::string tray_ return this->get_tray(ams_id, tray_id).setting_id; } +std::string MachineObject::get_filament_type(const std::string& ams_id, const std::string& tray_id) const { + return this->get_tray(ams_id, tray_id).type; +} + void MachineObject::_parse_ams_status(int ams_status) { ams_status_sub = ams_status & 0xFF; @@ -1178,7 +1202,7 @@ int MachineObject::ams_filament_mapping( // traverse the mapping std::set picked_src; std::set picked_tar; - //y59 + //y59 y68 for (int k = 0; k < distance_map.size(); k++) { float min_val = INT_MAX; int picked_src_idx = -1; @@ -1190,14 +1214,14 @@ int MachineObject::ams_filament_mapping( // try to mapping to different tray for (int j = 0; j < distance_map[i].size(); j++) { if (picked_tar.find(j) != picked_tar.end()) { - if (distance_map[i][j].is_same_color - && distance_map[i][j].is_type_match - && distance_map[i][j].distance < (float)0.0001) { - min_val = distance_map[i][j].distance; - picked_src_idx = i; - picked_tar_idx = j; - tray_filaments[picked_tar_idx].distance = min_val; - } + //if (distance_map[i][j].is_same_color + // && distance_map[i][j].is_type_match + // && distance_map[i][j].distance < (float)0.0001) { + // min_val = distance_map[i][j].distance; + // //picked_src_idx = i; + // //picked_tar_idx = j; + // tray_filaments[picked_tar_idx].distance = min_val; + //} continue; } @@ -1209,29 +1233,29 @@ int MachineObject::ams_filament_mapping( picked_tar_idx = j; tray_filaments[picked_tar_idx].distance = min_val; } - else if (min_val == distance_map[i][j].distance && filaments[picked_src_idx].filament_id!= box_filament_infos[picked_src_idx].filament_id && filaments[i].filament_id == box_filament_infos[j].filament_id) { - picked_src_idx = i; - picked_tar_idx = j; - } + //else if (min_val == distance_map[i][j].distance && filaments[i].filament_id == box_filament_infos[j].filament_id) { + // picked_src_idx = i; + // picked_tar_idx = j; + //} } } - // take a retry to mapping to used tray - if (picked_src_idx < 0 || picked_tar_idx < 0) { - for (int j = 0; j < distance_map[i].size(); j++) { - if (distance_map[i][j].is_same_color && distance_map[i][j].is_type_match) { - if (min_val > distance_map[i][j].distance) { - min_val = distance_map[i][j].distance; - picked_src_idx = i; - picked_tar_idx = j; - tray_filaments[picked_tar_idx].distance = min_val; - } else if (min_val == distance_map[i][j].distance && filaments[picked_src_idx].filament_id != tray_filaments[picked_tar_idx].filament_id && filaments[i].filament_id == tray_filaments[j].filament_id) { - picked_src_idx = i; - picked_tar_idx = j; - } - } - } - } + // // take a retry to mapping to used tray + // if (picked_src_idx < 0 || picked_tar_idx < 0) { + // for (int j = 0; j < distance_map[i].size(); j++) { + // if (distance_map[i][j].is_same_color && distance_map[i][j].is_type_match) { + // if (min_val > distance_map[i][j].distance) { + // min_val = distance_map[i][j].distance; + // picked_src_idx = i; + // picked_tar_idx = j; + // tray_filaments[picked_tar_idx].distance = min_val; + // } else if (min_val == distance_map[i][j].distance && filaments[picked_src_idx].filament_id != tray_filaments[picked_tar_idx].filament_id && filaments[i].filament_id == tray_filaments[j].filament_id) { + // picked_src_idx = i; + // picked_tar_idx = j; + // } + // } + // } + // } } //y59 @@ -1641,8 +1665,6 @@ bool MachineObject::is_in_calibration() return false; } - - bool MachineObject::is_calibration_done() { return calibration_done; @@ -1895,13 +1917,11 @@ bool MachineObject::canEnableTimelapse(wxString &error_message) const int MachineObject::command_select_extruder(int id) { - BOOST_LOG_TRIVIAL(info) << "select_extruder"; - json j; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["command"] = "select_extruder"; j["print"]["extruder_index"] = id; - int rtn = this->publish_json(j.dump(), 1); + int rtn = this->publish_json(j, 1); if (rtn == 0) { targ_nozzle_id_from_pc = id; @@ -1912,22 +1932,20 @@ int MachineObject::command_select_extruder(int id) int MachineObject::command_get_version(bool with_retry) { - BOOST_LOG_TRIVIAL(info) << "command_get_version"; json j; j["info"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["info"]["command"] = "get_version"; if (with_retry) get_version_retry = GET_VERSION_RETRYS; - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_get_access_code() { - BOOST_LOG_TRIVIAL(info) << "command_get_access_code"; json j; j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["system"]["command"] = "get_access_code"; - return this->publish_json(j.dump()); + return this->publish_json(j); } @@ -1938,15 +1956,15 @@ int MachineObject::command_request_push_all(bool request_now) if (diff.count() < REQUEST_PUSH_MIN_TIME) { if (request_now) { - BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); last_request_push = std::chrono::system_clock::now(); } else { - BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all: send request too fast, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all: send request too fast, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); return -1; } } else { - BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); last_request_push = std::chrono::system_clock::now(); } @@ -1955,7 +1973,7 @@ int MachineObject::command_request_push_all(bool request_now) j["pushing"]["command"] = "pushall"; j["pushing"]["version"] = 1; j["pushing"]["push_target"] = 1; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_pushing(std::string cmd) @@ -1963,11 +1981,11 @@ int MachineObject::command_pushing(std::string cmd) auto curr_time = std::chrono::system_clock::now(); auto diff = std::chrono::duration_cast(curr_time - last_request_start); if (diff.count() < REQUEST_START_MIN_TIME) { - BOOST_LOG_TRIVIAL(trace) << "static: command_request_start: send request too fast, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: command_request_start: send request too fast, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); return -1; } else { - BOOST_LOG_TRIVIAL(trace) << "static: command_request_start, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: command_request_start, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); last_request_start = std::chrono::system_clock::now(); } @@ -1975,41 +1993,38 @@ int MachineObject::command_pushing(std::string cmd) json j; j["pushing"]["command"] = cmd; j["pushing"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump()); + return this->publish_json(j); } return -1; } int MachineObject::command_clean_print_error(std::string subtask_id, int print_error) { - BOOST_LOG_TRIVIAL(info) << "command_clean_print_error, id = " << subtask_id; json j; j["print"]["command"] = "clean_print_error"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["subtask_id"] = subtask_id; j["print"]["print_error"] = print_error; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_upgrade_confirm() { - BOOST_LOG_TRIVIAL(info) << "command_upgrade_confirm"; json j; j["upgrade"]["command"] = "upgrade_confirm"; j["upgrade"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["upgrade"]["src_id"] = 1; // 1 for slicer - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_consistency_upgrade_confirm() { - BOOST_LOG_TRIVIAL(info) << "command_consistency_upgrade_confirm"; json j; j["upgrade"]["command"] = "consistency_confirm"; j["upgrade"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["upgrade"]["src_id"] = 1; // 1 for slicer - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_upgrade_firmware(FirmwareInfo info) @@ -2026,7 +2041,7 @@ int MachineObject::command_upgrade_firmware(FirmwareInfo info) j["upgrade"]["version"] = info.version; j["upgrade"]["src_id"] = 1; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_upgrade_module(std::string url, std::string module_type, std::string version) @@ -2039,7 +2054,7 @@ int MachineObject::command_upgrade_module(std::string url, std::string module_ty j["upgrade"]["version"] = version; j["upgrade"]["src_id"] = 1; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_xyz_abs() @@ -2064,11 +2079,10 @@ int MachineObject::command_go_home() int MachineObject::command_go_home2() { - BOOST_LOG_TRIVIAL(info) << "New protocol of command_go_home2"; json j; j["print"]["command"] = "back_to_center"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump()); + return this->publish_json(j); } // Old protocol @@ -2090,51 +2104,56 @@ int MachineObject::command_control_fan(int fan_type, int val) // New protocol int MachineObject::command_control_fan_new(int fan_id, int val, const CommandCallBack &cb) { - BOOST_LOG_TRIVIAL(info) << "New protocol of fan setting(set speed), fan_id = " << fan_id; m_callback_list[std::to_string(m_sequence_id)] = cb; json j; j["print"]["command"] = "set_fan"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["fan_index"] = fan_id; - j["print"]["speed"] = val; - BOOST_LOG_TRIVIAL(info) << "MachineObject::command_control_fan_val, set the speed of fan, fan_id = " << fan_id; - return this->publish_json(j.dump()); + return this->publish_json(j); } -int MachineObject::command_control_air_duct(int mode_id, const CommandCallBack &cb) +int MachineObject::command_control_air_duct(int mode_id, int submode, const CommandCallBack &cb) { - BOOST_LOG_TRIVIAL(info) << "MachineObject::command_control_air_duct, set air duct, d = " << mode_id; m_callback_list[std::to_string(m_sequence_id)] = cb; json j; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["command"] = "set_airduct"; j["print"]["modeId"] = mode_id; + j["print"]["submode"] = submode; - return this->publish_json(j.dump()); + return this->publish_json(j); +} + +int MachineObject::command_task_partskip(std::vector part_ids) +{ + json j; + j["print"]["command"] = "skip_objects"; + j["print"]["obj_list"] = part_ids; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + + return this->publish_json(j, 1); } int MachineObject::command_task_abort() { - BOOST_LOG_TRIVIAL(trace) << "command_task_abort: "; json j; j["print"]["command"] = "stop"; j["print"]["param"] = ""; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_task_cancel(std::string job_id) { - BOOST_LOG_TRIVIAL(trace) << "command_task_cancel: " << job_id; json j; j["print"]["command"] = "stop"; j["print"]["param"] = ""; j["print"]["job_id"] = job_id; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_task_pause() @@ -2144,7 +2163,7 @@ int MachineObject::command_task_pause() j["print"]["param"] = ""; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_task_resume() @@ -2156,7 +2175,7 @@ int MachineObject::command_task_resume() j["print"]["param"] = ""; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_hms_idle_ignore(const std::string &error_str, int type) @@ -2168,7 +2187,7 @@ int MachineObject::command_hms_idle_ignore(const std::string &error_str, int typ j["print"]["err"] = error_str; j["print"]["type"] = type; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_hms_resume(const std::string& error_str, const std::string& job_id) @@ -2182,7 +2201,7 @@ int MachineObject::command_hms_resume(const std::string& error_str, const std::s j["print"]["job_id"] = job_id; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_hms_ignore(const std::string& error_str, const std::string& job_id) @@ -2196,7 +2215,7 @@ int MachineObject::command_hms_ignore(const std::string& error_str, const std::s j["print"]["job_id"] = job_id; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_hms_stop(const std::string &error_str, const std::string &job_id) { @@ -2207,7 +2226,7 @@ int MachineObject::command_hms_stop(const std::string &error_str, const std::str j["print"]["job_id"] = job_id; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_stop_buzzer() @@ -2217,11 +2236,20 @@ int MachineObject::command_stop_buzzer() j["print"]["mode"] = 0; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_set_bed(int temp) { + if (m_support_mqtt_bet_ctrl) + { + json j; + j["print"]["command"] = "set_bed_temp"; + j["print"]["temp"] = temp; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + return this->publish_json(j); + } + std::string gcode_str = (boost::format("M140 S%1%\n") % temp).str(); try { json j; @@ -2253,15 +2281,13 @@ int MachineObject::command_set_nozzle(int temp) int MachineObject::command_set_nozzle_new(int nozzle_id, int temp) { - BOOST_LOG_TRIVIAL(info) << "set_nozzle_temp"; - json j; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["command"] = "set_nozzle_temp"; j["print"]["extruder_index"] = nozzle_id; j["print"]["target_temp"] = temp; - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::command_set_chamber(int temp) @@ -2271,7 +2297,7 @@ int MachineObject::command_set_chamber(int temp) j["print"]["command"] = "set_ctt"; j["print"]["ctt_val"] = temp; - return this->publish_json(j.dump(), 1); + return this->publish_json(j, 1); } int MachineObject::check_resume_condition() @@ -2314,7 +2340,7 @@ int MachineObject::command_ams_change_filament(bool load, std::string ams_id, st } } catch (const std::exception &) {} - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ams_user_settings(int ams_id, bool start_read_opt, bool tray_read_opt, bool remain_flag) @@ -2332,7 +2358,7 @@ int MachineObject::command_ams_user_settings(int ams_id, bool start_read_opt, bo ams_calibrate_remain_flag = remain_flag; ams_user_setting_start = time(nullptr); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ams_calibrate(int ams_id) @@ -2354,10 +2380,6 @@ int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::s tag_tray_id = tag_slot_id; } - - BOOST_LOG_TRIVIAL(info) << "command_ams_filament_settings, ams_id = " << tag_ams_id << ", slot_id = " << tag_slot_id << ", tray_id = " << tag_tray_id << ", tray_color = " << tray_color - << ", tray_type = " << tray_type << ", filament_id = " << filament_id - << ", setting_id = " << setting_id << ", temp_min: = " << nozzle_temp_min << ", temp_max: = " << nozzle_temp_max; json j; j["print"]["command"] = "ams_filament_setting"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2372,7 +2394,7 @@ int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::s j["print"]["nozzle_temp_max"] = nozzle_temp_max; j["print"]["tray_type"] = tray_type; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ams_refresh_rfid(std::string tray_id) @@ -2389,7 +2411,7 @@ int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["ams_id"] = ams_id; j["print"]["slot_id"] = slot_id; - return this->publish_json(j.dump()); + return this->publish_json(j); } @@ -2410,12 +2432,11 @@ int MachineObject::command_ams_control(std::string action) j["print"]["command"] = "ams_control"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["param"] = action; - return this->publish_json(j.dump()); + return this->publish_json(j); } return -1; } - int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) { json j; @@ -2427,7 +2448,7 @@ int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, i j["system"]["led_off_time"] = off_time; j["system"]["loop_times"] = loops; j["system"]["interval_time"] = interval; - return this->publish_json(j.dump()); + return this->publish_json(j); } @@ -2442,26 +2463,26 @@ int MachineObject::command_set_chamber_light2(LIGHT_EFFECT effect, int on_time / j["system"]["led_off_time"] = off_time; j["system"]["loop_times"] = loops; j["system"]["interval_time"] = interval; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_printer_nozzle(std::string nozzle_type, float diameter) { nozzle_setting_hold_count = HOLD_COUNT_MAX * 2; - BOOST_LOG_TRIVIAL(info) << "command_set_printer_nozzle, nozzle_type = " << nozzle_type << " diameter = " << diameter; + json j; j["system"]["command"] = "set_accessories"; j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["system"]["accessory_type"] = "nozzle"; j["system"]["nozzle_type"] = nozzle_type; j["system"]["nozzle_diameter"] = diameter; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter) { nozzle_setting_hold_count = HOLD_COUNT_MAX * 2; - BOOST_LOG_TRIVIAL(info) << "command_set_printer_nozzle2, nozzle_type = " << nozzle_type << " diameter = " << diameter; + json j; j["print"]["command"] = "set_nozzle"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2469,7 +2490,7 @@ int MachineObject::command_set_printer_nozzle2(int id, std::string nozzle_type, j["print"]["type"] = nozzle_type; j["print"]["diameter"] = diameter; j["print"]["wear"] = 0; - return this->publish_json(j.dump()); + return this->publish_json(j); } @@ -2485,14 +2506,11 @@ int MachineObject::command_set_work_light(LIGHT_EFFECT effect, int on_time, int j["system"]["loop_times"] = loops; j["system"]["interval_time"] = interval; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_start_extrusion_cali(int tray_index, int nozzle_temp, int bed_temp, float max_volumetric_speed, std::string setting_id) { - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: tray_id = " << tray_index << ", nozzle_temp = " << nozzle_temp << ", bed_temp = " << bed_temp - << ", max_volumetric_speed = " << max_volumetric_speed; - json j; j["print"]["command"] = "extrusion_cali"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2505,8 +2523,7 @@ int MachineObject::command_start_extrusion_cali(int tray_index, int nozzle_temp, // enter extusion cali last_extrusion_cali_start_time = std::chrono::system_clock::now(); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_stop_extrusion_cali() @@ -2520,8 +2537,6 @@ int MachineObject::command_stop_extrusion_cali() int MachineObject::command_extrusion_cali_set(int tray_index, std::string setting_id, std::string name, float k, float n, int bed_temp, int nozzle_temp, float max_volumetric_speed) { - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali: tray_id = " << tray_index << ", setting_id = " << setting_id << ", k = " << k - << ", n = " << n; json j; j["print"]["command"] = "extrusion_cali_set"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2536,7 +2551,7 @@ int MachineObject::command_extrusion_cali_set(int tray_index, std::string settin j["print"]["nozzle_temp"] = nozzle_temp; j["print"]["max_volumetric_speed"] = max_volumetric_speed; } - return this->publish_json(j.dump()); + return this->publish_json(j); } @@ -2547,7 +2562,7 @@ int MachineObject::command_set_printing_speed(PrintingSpeedLevel lvl) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["param"] = std::to_string((int)lvl); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_printing_option(bool auto_recovery) @@ -2559,7 +2574,7 @@ int MachineObject::command_set_printing_option(bool auto_recovery) j["print"]["option"] = print_option; j["print"]["auto_recovery"] = auto_recovery; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_nozzle_blob_detect(bool nozzle_blob_detect) @@ -2570,7 +2585,7 @@ int MachineObject::command_nozzle_blob_detect(bool nozzle_blob_detect) j["print"]["nozzle_blob_detect"] = nozzle_blob_detect; nozzle_blob_detection_enabled = nozzle_blob_detect; nozzle_blob_detection_hold_start = time(nullptr); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_prompt_sound(bool prompt_sound){ @@ -2579,7 +2594,7 @@ int MachineObject::command_set_prompt_sound(bool prompt_sound){ j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["sound_enable"] = prompt_sound; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_filament_tangle_detect(bool filament_tangle_detect) { @@ -2588,7 +2603,7 @@ int MachineObject::command_set_filament_tangle_detect(bool filament_tangle_detec j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["filament_tangle_detect"] = filament_tangle_detect; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ams_switch_filament(bool switch_filament) @@ -2599,10 +2614,9 @@ int MachineObject::command_ams_switch_filament(bool switch_filament) j["print"]["auto_switch_filament"] = switch_filament; ams_auto_switch_filament_flag = switch_filament; - BOOST_LOG_TRIVIAL(trace) << "command_ams_filament_settings:" << switch_filament; ams_switch_filament_start = time(nullptr); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ams_air_print_detect(bool air_print_detect) @@ -2613,14 +2627,24 @@ int MachineObject::command_ams_air_print_detect(bool air_print_detect) j["print"]["air_print_detect"] = air_print_detect; ams_air_print_status = air_print_detect; - BOOST_LOG_TRIVIAL(trace) << "command_ams_air_print_detect:" << air_print_detect; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_axis_control(std::string axis, double unit, double input_val, int speed) { + if (m_support_mqtt_axis_control) + { + json j; + j["print"]["command"] = "xyz_ctrl"; + j["print"]["axis"] = axis; + j["print"]["dir"] = input_val > 0 ? 1 : -1; + j["print"]["mode"] = (std::abs(input_val) >= 10) ? 1 : 0; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + return this->publish_json(j); + } + double value = input_val; if (!is_core_xy()) { if ( axis.compare("Y") == 0 @@ -2662,7 +2686,7 @@ int MachineObject::command_extruder_control(int nozzle_id, double val) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["extruder_index"] = nozzle_id; j["print"]["length"] = (int)val; - return this->publish_json(j.dump()); + return this->publish_json(j); } bool MachineObject::is_support_command_calibration() @@ -2685,7 +2709,7 @@ int MachineObject::command_start_calibration(bool vibration, bool bed_leveling, j["print"]["command"] = "gcode_file"; j["print"]["param"] = "/usr/etc/print/auto_cali_for_user.gcode"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - return this->publish_json(j.dump()); + return this->publish_json(j); } else { json j; j["print"]["command"] = "calibration"; @@ -2696,7 +2720,7 @@ int MachineObject::command_start_calibration(bool vibration, bool bed_leveling, + (vibration ? 1 << 2 : 0) + (bed_leveling ? 1 << 1 : 0) + (xcam_cali ? 1 << 0 : 0); - return this->publish_json(j.dump()); + return this->publish_json(j); } } @@ -2729,8 +2753,6 @@ int MachineObject::command_start_pa_calibration(const X1CCalibInfos &pa_data, in filament_ids += pa_data.calib_datas[i].filament_id; } - BOOST_LOG_TRIVIAL(info) << "extrusion_cali: " << j.dump(); - try { json js; js["cali_type"] = "cali_pa_auto"; @@ -2741,7 +2763,7 @@ int MachineObject::command_start_pa_calibration(const X1CCalibInfos &pa_data, in if (agent) agent->track_event("cali", js.dump()); } catch (...) {} - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_set_pa_calibration(const std::vector &pa_calib_values, bool is_auto_cali) @@ -2775,8 +2797,7 @@ int MachineObject::command_set_pa_calibration(const std::vector & j["print"]["filaments"][i]["n_coef"] = "0.0"; } - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_set: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } return -1; @@ -2793,8 +2814,7 @@ int MachineObject::command_delete_pa_calibration(const PACalibIndexInfo& pa_cali j["print"]["cali_idx"] = pa_calib.cali_idx; j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib.nozzle_diameter); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_del: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } //w @@ -2808,8 +2828,7 @@ int MachineObject::command_get_pa_calibration_tab(float nozzle_diameter, const s j["print"]["filament_id"] = filament_id; j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(trace) << "extrusion_cali_get: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_get_pa_calibration_tab(const PACalibExtruderInfo &calib_info) @@ -2826,9 +2845,8 @@ int MachineObject::command_get_pa_calibration_tab(const PACalibExtruderInfo &cal j["print"]["nozzle_id"] = generate_nozzle_id(calib_info.nozzle_volume_type, to_string_nozzle_diameter(calib_info.nozzle_diameter)).ToStdString(); j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(calib_info.nozzle_diameter); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_get: " << j.dump(); request_tab_from_qds = true; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_get_pa_calibration_result(float nozzle_diameter) @@ -2838,8 +2856,7 @@ int MachineObject::command_get_pa_calibration_result(float nozzle_diameter) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_get_result: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::commnad_select_pa_calibration(const PACalibIndexInfo& pa_calib_info) @@ -2854,8 +2871,7 @@ int MachineObject::commnad_select_pa_calibration(const PACalibIndexInfo& pa_cali j["print"]["filament_id"] = pa_calib_info.filament_id; j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib_info.nozzle_diameter); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_sel: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_start_flow_ratio_calibration(const X1CCalibInfos& calib_data) @@ -2878,6 +2894,9 @@ int MachineObject::command_start_flow_ratio_calibration(const X1CCalibInfos& cal j["print"]["filaments"][i]["nozzle_temp"] = calib_data.calib_datas[i].nozzle_temp; j["print"]["filaments"][i]["def_flow_ratio"] = std::to_string(calib_data.calib_datas[i].flow_rate); j["print"]["filaments"][i]["max_volumetric_speed"] = std::to_string(calib_data.calib_datas[i].max_volumetric_speed); + j["print"]["filaments"][i]["extruder_id"] = calib_data.calib_datas[i].extruder_id; + j["print"]["filaments"][i]["ams_id"] = calib_data.calib_datas[i].ams_id; + j["print"]["filaments"][i]["slot_id"] = calib_data.calib_datas[i].slot_id; if (i > 0) filament_ids += ","; @@ -2894,8 +2913,7 @@ int MachineObject::command_start_flow_ratio_calibration(const X1CCalibInfos& cal if (agent) agent->track_event("cali", js.dump()); } catch (...) {} - BOOST_LOG_TRIVIAL(info) << "flowrate_cali: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } return -1; } @@ -2907,37 +2925,33 @@ int MachineObject::command_get_flow_ratio_calibration_result(float nozzle_diamet j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - BOOST_LOG_TRIVIAL(info) << "flowrate_get_result: " << j.dump(); - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ipcam_record(bool on_off) { - BOOST_LOG_TRIVIAL(info) << "command_ipcam_record = " << on_off; json j; j["camera"]["command"] = "ipcam_record_set"; j["camera"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["camera"]["control"] = on_off ? "enable" : "disable"; camera_recording_ctl_start = time(nullptr); this->camera_recording_when_printing = on_off; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ipcam_timelapse(bool on_off) { - BOOST_LOG_TRIVIAL(info) << "command_ipcam_timelapse " << on_off; json j; j["camera"]["command"] = "ipcam_timelapse"; j["camera"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["camera"]["control"] = on_off ? "enable" : "disable"; camera_timelapse_hold_count = HOLD_COUNT_CAMERA; this->camera_timelapse = on_off; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_ipcam_resolution_set(std::string resolution) { - BOOST_LOG_TRIVIAL(info) << "command:ipcam_resolution_set" << ", resolution:" << resolution; json j; j["camera"]["command"] = "ipcam_resolution_set"; j["camera"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); @@ -2945,7 +2959,7 @@ int MachineObject::command_ipcam_resolution_set(std::string resolution) camera_resolution_hold_count = HOLD_COUNT_CAMERA; camera_recording_ctl_start = time(nullptr); this->camera_resolution = resolution; - return this->publish_json(j.dump()); + return this->publish_json(j); } int MachineObject::command_xcam_control(std::string module_name, bool on_off, std::string lvl) @@ -2960,8 +2974,8 @@ int MachineObject::command_xcam_control(std::string module_name, bool on_off, st if (!lvl.empty()) { j["xcam"]["halt_print_sensitivity"] = lvl; } - BOOST_LOG_TRIVIAL(info) << "command:xcam_control_set" << ", module_name:" << module_name << ", control:" << on_off << ", halt_print_sensitivity:" << lvl; - return this->publish_json(j.dump()); + + return this->publish_json(j); } int MachineObject::command_xcam_control_ai_monitoring(bool on_off, std::string lvl) @@ -2974,6 +2988,49 @@ int MachineObject::command_xcam_control_ai_monitoring(bool on_off, std::string l return command_xcam_control("printing_monitor", on_off, lvl); } +// refine printer function options +int MachineObject::command_xcam_control_spaghetti_detection(bool on_off, std::string lvl) +{ + bool print_halt = (lvl == "never_halt") ? false : true; + + xcam_spaghetti_detection = on_off; + xcam_ai_monitoring_hold_start = time(nullptr); + xcam_spaghetti_detection_sensitivity = lvl; + return command_xcam_control("spaghetti_detector", on_off, lvl); +} + +int MachineObject::command_xcam_control_purgechutepileup_detection(bool on_off, std::string lvl) +{ + bool print_halt = (lvl == "never_halt") ? false : true; + + xcam_purgechutepileup_detection = on_off; + xcam_ai_monitoring_hold_start = time(nullptr); + xcam_purgechutepileup_detection_sensitivity = lvl; + return command_xcam_control("pileup_detector", on_off, lvl); +} + +int MachineObject::command_xcam_control_nozzleclumping_detection(bool on_off, std::string lvl) +{ + bool print_halt = (lvl == "never_halt") ? false : true; + + xcam_nozzleclumping_detection = on_off; + xcam_ai_monitoring_hold_start = time(nullptr); + xcam_nozzleclumping_detection_sensitivity = lvl; + return command_xcam_control("clump_detector", on_off, lvl); +} + + +int MachineObject::command_xcam_control_airprinting_detection(bool on_off, std::string lvl) +{ + bool print_halt = (lvl == "never_halt") ? false : true; + + xcam_airprinting_detection = on_off; + xcam_ai_monitoring_hold_start = time(nullptr); + xcam_airprinting_detection_sensitivity = lvl; + return command_xcam_control("airprint_detector", on_off, lvl); +} + + int MachineObject::command_xcam_control_buildplate_marker_detector(bool on_off) { xcam_buildplate_marker_detector = on_off; @@ -3107,14 +3164,14 @@ bool MachineObject::is_core_xy() void MachineObject::reset_update_time() { - BOOST_LOG_TRIVIAL(trace) << "reset reset_update_time, dev_id =" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "reset reset_update_time, dev_id =" << QDTCrossTalk::Crosstalk_DevId(dev_id); last_update_time = std::chrono::system_clock::now(); subscribe_counter = SUBSCRIBE_RETRY_COUNT; } void MachineObject::reset() { - BOOST_LOG_TRIVIAL(trace) << "reset dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "reset dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); last_update_time = std::chrono::system_clock::now(); subscribe_counter = SUBSCRIBE_RETRY_COUNT; m_push_count = 0; @@ -3152,6 +3209,7 @@ void MachineObject::reset() } } subtask_ = nullptr; + m_partskip_ids.clear(); } void MachineObject::nt_reset_data() @@ -3196,7 +3254,7 @@ bool MachineObject::is_connected() std::chrono::system_clock::time_point curr_time = std::chrono::system_clock::now(); auto diff = std::chrono::duration_cast(curr_time - last_update_time); if (diff.count() > DISCONNECT_TIMEOUT) { - BOOST_LOG_TRIVIAL(trace) << "machine_object: dev_id=" << dev_id <<", diff count = " << diff.count(); + BOOST_LOG_TRIVIAL(trace) << "machine_object: dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id) <<", diff count = " << diff.count(); return false; } @@ -3251,19 +3309,19 @@ bool MachineObject::is_camera_busy_off() return false; } -int MachineObject::publish_json(std::string json_str, int qos, int flag) +int MachineObject::publish_json(const json& json_item, int qos, int flag) { int rtn = 0; if (is_lan_mode_printer()) { - rtn = local_publish_json(json_str, qos, flag); + rtn = local_publish_json(json_item.dump(), qos, flag); } else { - rtn = cloud_publish_json(json_str, qos, flag); + rtn = cloud_publish_json(json_item.dump(), qos, flag); } if (rtn == 0) { - BOOST_LOG_TRIVIAL(info) << "publish_json: " << json_str << " code: " << rtn; + BOOST_LOG_TRIVIAL(info) << "publish_json: " << QDTCrossTalk::Crosstalk_JsonLog(json_item) << " code: " << rtn; } else { - BOOST_LOG_TRIVIAL(error) << "publish_json: " << json_str << " code: " << rtn; + BOOST_LOG_TRIVIAL(error) << "publish_json: " << QDTCrossTalk::Crosstalk_JsonLog(json_item) << " code: " << rtn; } return rtn; @@ -3358,7 +3416,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (j_pre["print"]["command"].get() == "push_status") { if (j_pre["print"].contains("msg")) { if (j_pre["print"]["msg"].get() == 0) { //all message - BOOST_LOG_TRIVIAL(trace) << "static: get push_all msg, dev_id=" << dev_id; + BOOST_LOG_TRIVIAL(trace) << "static: get push_all msg, dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); m_push_count++; m_full_msg_count++; @@ -3398,6 +3456,29 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ print_json.diff2all_base_reset(j_pre); } + + if (j_pre["print"].contains("s_obj")){ + if(j_pre["print"]["s_obj"].is_array()){ + m_partskip_ids.clear(); + for(auto it=j_pre["print"]["s_obj"].begin(); it!=j_pre["print"]["s_obj"].end(); it++){ + m_partskip_ids.push_back(it.value().get()); + } + } + } + } + } + if (j_pre["print"].contains("plate_idx")){ // && m_plate_index == -1 + if (j_pre["print"]["plate_idx"].is_number()) + { + m_plate_index = j_pre["print"]["plate_idx"].get(); + } + else if (j_pre["print"]["plate_idx"].is_string()) + { + try + { + m_plate_index = std::stoi(j_pre["print"]["plate_idx"].get()); + } + catch (...) { BOOST_LOG_TRIVIAL(error) << "parse_json: failed to convert plate_idx to int"; } } } } @@ -3493,12 +3574,14 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ message_delay.push_back(std::make_tuple(message_type, t_utc, delay)); } else + { last_utc_time = last_update_time; + } if (Slic3r::get_logging_level() < level_string_to_boost("trace")) { - BOOST_LOG_TRIVIAL(info) << "parse_json: dev_id=" << dev_id << ", origin playload=" << j_pre.dump(0); + BOOST_LOG_TRIVIAL(info) << "parse_json: dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id) << ", origin playload=" << QDTCrossTalk::Crosstalk_JsonLog(j_pre); } else { - BOOST_LOG_TRIVIAL(trace) << "parse_json: dev_id=" << dev_id << ", tunnel is=" << tunnel << ", merged playload=" << j.dump(0); + BOOST_LOG_TRIVIAL(trace) << "parse_json: dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id) << ", tunnel is=" << tunnel << ", merged playload=" << QDTCrossTalk::Crosstalk_JsonLog(j); } // Parse version info first, as if version arrive or change, 'print' need parse again with new compatible settings @@ -3816,9 +3899,20 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj["command"].get() == "ams_change_filament") { if (jj.contains("errno")) { if (jj["errno"].is_number()) { - if (jj["errno"].get() == -2) { - wxString text = _L("The current chamber temperature or the target chamber temperature exceeds 45\u2103.In order to avoid extruder clogging,low temperature filament(PLA/PETG/TPU) is not allowed to be loaded."); - GUI::wxGetApp().push_notification(this, text); + if (jj.contains("soft_temp")) { + int soft_temp = jj["soft_temp"].get(); + if (jj["errno"].get() == -2) { + wxString text = wxString::Format(_L("The chamber temperature is too high, which may cause the filament to soften. Please wait until the chamber temperature drops below %d\u2103. You may open the front door or enable fans to cool down."), soft_temp); + GUI::wxGetApp().push_notification(this, text); + } else if (jj["errno"].get() == -4) { + wxString text = wxString::Format(_L("AMS temperature is too high, which may cause the filament to soften. Please wait until the AMS temperature drops below %d\u2103."), soft_temp); + GUI::wxGetApp().push_notification(this, text); + } + } else { + if (jj["errno"].get() == -2) { + wxString text = _L("The current chamber temperature or the target chamber temperature exceeds 45\u2103.In order to avoid extruder clogging,low temperature filament(PLA/PETG/TPU) is not allowed to be loaded."); + GUI::wxGetApp().push_notification(this, text); + } } } } @@ -3960,7 +4054,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ online_rfid = false; } } - std::string str = jj.dump(); + if (jj["online"].contains("version")) { online_version = jj["online"]["version"].get(); } @@ -4492,7 +4586,49 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ try { if (jj.contains("xcam")) { if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { - if (jj["xcam"].contains("printing_monitor")) { + + if (jj["xcam"].contains("cfg")) { + xcam_disable_ai_detection_display = true; + // std::string cfg = jj["xcam"]["cfg"].get(); + + int cfg = jj["xcam"]["cfg"].get(); + xcam_spaghetti_detection = get_flag_bits(cfg,7); + switch (get_flag_bits(cfg, 8, 2)) { + case 0: xcam_spaghetti_detection_sensitivity = "low"; break; + case 1: xcam_spaghetti_detection_sensitivity = "medium"; break; + case 2: xcam_spaghetti_detection_sensitivity = "high"; break; + default: break; + } + + xcam_purgechutepileup_detection = get_flag_bits(cfg, 10); + switch (get_flag_bits(cfg, 11, 2)) { + + case 0: xcam_purgechutepileup_detection_sensitivity = "low"; break; + case 1: xcam_purgechutepileup_detection_sensitivity = "medium"; break; + case 2: xcam_purgechutepileup_detection_sensitivity = "high"; break; + default: break; + } + + xcam_nozzleclumping_detection = get_flag_bits(cfg, 13); + switch (get_flag_bits(cfg, 14, 2)) { + + case 0: xcam_nozzleclumping_detection_sensitivity = "low"; break; + case 1: xcam_nozzleclumping_detection_sensitivity = "medium"; break; + case 2: xcam_nozzleclumping_detection_sensitivity = "high"; break; + default: break; + } + + xcam_airprinting_detection = get_flag_bits(cfg, 16); + switch (get_flag_bits(cfg, 17, 2)) { + + case 0: xcam_airprinting_detection_sensitivity = "low"; break; + case 1: xcam_airprinting_detection_sensitivity = "medium"; break; + case 2: xcam_airprinting_detection_sensitivity = "high"; break; + default: break; + } + + } + else if (jj["xcam"].contains("printing_monitor")) { // new protocol xcam_ai_monitoring = jj["xcam"]["printing_monitor"].get(); } else { @@ -4505,9 +4641,11 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } + if (jj["xcam"].contains("halt_print_sensitivity")) { xcam_ai_monitoring_sensitivity = jj["xcam"]["halt_print_sensitivity"].get(); } + } if (time(nullptr) - xcam_first_layer_hold_start > HOLD_TIME_3SEC) { @@ -4565,14 +4703,13 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ int ams_status = jj["ams_status"].get(); this->_parse_ams_status(ams_status); } - std::string str_j = jj.dump(); + if (jj.contains("cali_version")) { cali_version = jj["cali_version"].get(); } else { cali_version = -1; } - std::string str = jj.dump(); } catch (...) { ; @@ -4937,8 +5074,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } - std::string temp = tray_it->dump(); - if (tray_it->contains("cali_idx")) { curr_tray->cali_idx = (*tray_it)["cali_idx"].get(); } @@ -5031,8 +5166,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } catch (...) {} #pragma endregion } else if (jj["command"].get() == "gcode_line") { - //ack of gcode_line - BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of gcode_line = " << j.dump(4); if (m_agent && is_studio_cmd(sequence_id)) { json t; t["dev_id"] = this->dev_id; @@ -5041,8 +5174,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ m_agent->track_event("ack_cmd_gcode_line", t.dump()); } } else if (jj["command"].get() == "project_prepare") { - //ack of project file - BOOST_LOG_TRIVIAL(info) << "parse_json, ack of project_prepare = " << j.dump(4); if (m_agent) { if (jj.contains("job_id")) { this->job_id_ = JsonValParser::get_longlong_val(jj["job_id"]); @@ -5050,8 +5181,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } else if (jj["command"].get() == "project_file") { - //ack of project file - BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of project_file = " << j.dump(4); if (m_agent) { json t; t["dev_id"] = this->dev_id; @@ -5226,10 +5355,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } -#ifdef CALI_DEBUG - std::string str = jj.dump(); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_set: " << str; -#endif int ams_id = -1; int tray_id = -1; int curr_tray_id = -1; @@ -5279,10 +5404,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } -#ifdef CALI_DEBUG - std::string str = jj.dump(); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_sel: " << str; -#endif int ams_id = -1; int slot_id = -1; int tray_id = -1; @@ -5340,9 +5461,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } else if (jj["command"].get() == "extrusion_cali_get") { - std::string str = jj.dump(); if (request_tab_from_qds) { - BOOST_LOG_TRIVIAL(info) << "qds extrusion_cali_get: " << str; request_tab_from_qds = false; reset_pa_cali_history_result(); bool is_succeed = true; @@ -5411,12 +5530,10 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } // notify cali history to update } else { - BOOST_LOG_TRIVIAL(info) << "printer extrusion_cali_get: " << str; + BOOST_LOG_TRIVIAL(info) << "printer extrusion_cali_get: "; } } else if (jj["command"].get() == "extrusion_cali_get_result") { - std::string str = jj.dump(); - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_get_result: " << str; reset_pa_cali_result(); bool is_succeed = true; if (jj.contains("result") && jj.contains("reason")) { @@ -5508,10 +5625,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ get_flow_calib_result = true; if (jj.contains("filaments") && jj["filaments"].is_array()) { try { -#ifdef CALI_DEBUG - std::string str = jj.dump(); - BOOST_LOG_TRIVIAL(info) << "flowrate_get_result: " << str; -#endif for (auto it = jj["filaments"].begin(); it != jj["filaments"].end(); it++) { FlowRatioCalibResult flow_ratio_calib_result; flow_ratio_calib_result.tray_id = (*it)["tray_id"].get(); @@ -5616,8 +5729,11 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ parse_state_changed_event(); } } - catch (...) { - BOOST_LOG_TRIVIAL(trace) << "parse_json failed! dev_id=" << this->dev_id <<", payload = " << payload; + catch (const nlohmann::json::exception& e) { + // Handle JSON parsing exceptions if necessary + BOOST_LOG_TRIVIAL(trace) << "parse_json failed! dev_id=" << QDTCrossTalk::Crosstalk_DevId(this->dev_id) <<", ewhat = " << e.what(); + } catch (...) { + BOOST_LOG_TRIVIAL(trace) << "parse_json failed! dev_id=" << QDTCrossTalk::Crosstalk_DevId(this->dev_id); } std::chrono::system_clock::time_point clock_stop = std::chrono::system_clock::now(); @@ -5664,7 +5780,7 @@ int MachineObject::publish_gcode(std::string gcode_str) m_agent->track_event("cmd_gcode_line", t.dump()); } - return publish_json(j.dump(), 0); + return publish_json(j); } QDTSubTask* MachineObject::get_subtask() @@ -5828,10 +5944,12 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil if (!m_agent) return; if (!slice_info) return; + if (!get_slice_info_thread) return;/*STUDIO-12264*/ if (get_slice_info_thread->interruption_requested()) { return;} if (plate_idx >= 0) { plate_index = plate_idx; + this->m_plate_index = plate_idx; } else { std::string subtask_json; @@ -5878,7 +5996,10 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil slice_info->filaments_info.push_back(f); } } + + #if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(trace) << "task_info: thumbnail url=" << slice_info->thumbnail_url; + #endif } } } @@ -5894,8 +6015,7 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil BOOST_LOG_TRIVIAL(error) << "task_info: get subtask id failed!"; } } - - this->m_plate_index = plate_index; + // this->m_plate_index = plate_index; }); } } @@ -6008,6 +6128,7 @@ std::string MachineObject::get_string_from_fantype(int type) void MachineObject::nt_condition_local_tunnel() { + return; int full_msg_count_limit = 2; if (!nt_try_local_tunnel && nt_cloud_full_msg_count == full_msg_count_limit) { connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); @@ -6171,6 +6292,12 @@ AmsTray MachineObject::parse_vt_tray(json vtray) else { vt_tray.color = ""; } + if (vtray.contains("ctype")) { + vt_tray.ctype = vtray["ctype"].get(); + } + else { + vt_tray.ctype = 1; + } if (vtray.contains("nozzle_temp_max")) vt_tray.nozzle_temp_max = vtray["nozzle_temp_max"].get(); else @@ -6194,11 +6321,13 @@ AmsTray MachineObject::parse_vt_tray(json vtray) vt_tray.cali_idx = -1; vt_tray.cols.clear(); if (vtray.contains("cols")) { - if (vtray.is_array()) { - for (auto it = vtray.begin(); it != vtray.end(); it++) { + if (vtray["cols"].is_array()) { + for (auto it = vtray["cols"].begin(); it != vtray["cols"].end(); it++) { vt_tray.cols.push_back(it.value().get()); } } + } else { + vt_tray.cols.push_back(vt_tray.color); } if (vtray.contains("remain")) { @@ -6393,6 +6522,17 @@ void MachineObject::parse_new_info(json print) is_support_internal_timelapse = get_flag_bits(fun, 28); is_support_command_homing = get_flag_bits(fun, 32); is_support_brtc = get_flag_bits(fun, 31); + m_support_mqtt_axis_control = get_flag_bits(fun, 38); + m_support_mqtt_bet_ctrl = get_flag_bits(fun, 39); + + is_support_spaghetti_detection = get_flag_bits(fun, 42); + is_support_purgechutepileup_detection = get_flag_bits(fun, 43); + is_support_nozzleclumping_detection = get_flag_bits(fun, 44); + is_support_airprinting_detection = get_flag_bits(fun, 45); + + m_air_duct_data.m_support_cooling_filter = get_flag_bits(fun, 46); + is_support_ext_change_assist = get_flag_bits(fun, 48); + is_support_partskip = get_flag_bits(fun, 49); } /*aux*/ @@ -6424,9 +6564,9 @@ void MachineObject::parse_new_info(json print) m_air_duct_data.modes.clear(); m_air_duct_data.parts.clear(); - m_air_duct_data.curren_mode = device["airduct"]["modeCur"].get(); - const json& airduct = device["airduct"]; + if (airduct.contains("modeCur")) { m_air_duct_data.curren_mode = airduct["modeCur"].get();} + if (airduct.contains("subMode")) { m_air_duct_data.m_sub_mode = airduct["subMode"].get(); } if (airduct.contains("modeList") && airduct["modeList"].is_array()) { auto list = airduct["modeList"].get>(); @@ -6450,6 +6590,7 @@ void MachineObject::parse_new_info(json print) } } + if (AIR_DUCT(mode.id) == AIR_DUCT::AIR_DUCT_EXHAUST) { continue; } /*STUDIO-12796*/ m_air_duct_data.modes[mode.id] = mode; } } @@ -6823,6 +6964,7 @@ void MachineObject::check_ams_filament_valid() auto &filament_list = data.filament_list; auto &checked_filament = data.checked_filament; for (const auto &[slot_id, curr_tray] : ams->trayList) { + if (curr_tray->setting_id.size() == 8 && curr_tray->setting_id[0] == 'P' && filament_list.find(curr_tray->setting_id) == filament_list.end()) { if (checked_filament.find(curr_tray->setting_id) == checked_filament.end()) { need_checked_filament_id[nozzle_diameter_str].insert(curr_tray->setting_id); @@ -6966,7 +7108,7 @@ void MachineObject::command_set_door_open_check(DoorOpenCheckState state) default: assert(0); return; } - if (publish_json(j.dump()) == 0) + if (publish_json(j) == 0) { xcam_door_open_check = state; xcam_door_open_check_start_time = time(nullptr); @@ -6983,7 +7125,7 @@ void MachineObject::command_set_save_remote_print_file_to_storage(bool save) j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["system"]["config"] = save ? true : false; - if (publish_json(j.dump()) == 0) + if (publish_json(j) == 0) { xcam__save_remote_print_file_to_storage = save; xcam__save_remote_print_file_to_storage_start_time = time(nullptr); @@ -6991,6 +7133,23 @@ void MachineObject::command_set_save_remote_print_file_to_storage(bool save) } } +wxString MachineObject::get_nozzle_replace_url() const +{ + const wxString& strLanguage = GUI::wxGetApp().app_config->get("language"); + const wxString& lan_code = strLanguage.BeforeFirst('_'); + + const json& link_map = DeviceManager::get_json_from_config(printer_type, "print", "nozzle_replace_wiki"); + if (link_map.contains(lan_code.ToStdString())) { + return link_map[lan_code.ToStdString()].get(); + } + + if (link_map.contains("en")){ + return link_map["en"].get(); + }/*retry with en*/ + + return "https://wiki.qidi3d.com/"; +} + bool DeviceManager::EnableMultiMachine = false; bool DeviceManager::key_field_only = false; @@ -7118,7 +7277,6 @@ void DeviceManager::check_pushing() void DeviceManager::on_machine_alive(std::string json_str) { try { - //BOOST_LOG_TRIVIAL(trace) << "DeviceManager::SsdpDiscovery, json" << json_str; json j = json::parse(json_str); std::string dev_name = j["dev_name"].get(); std::string dev_id = j["dev_id"].get(); @@ -7166,7 +7324,12 @@ void DeviceManager::on_machine_alive(std::string json_str) it->second->bind_sec_link = sec_link; it->second->dev_connection_type = connect_type; it->second->bind_ssdp_version = ssdp_version; - BOOST_LOG_TRIVIAL(trace) << "DeviceManager::SsdpDiscovery, update userMachineList json" << json_str; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " UpdateUserMachineInfo" + << ", dev_id= " << QDTCrossTalk::Crosstalk_DevId(dev_id) + << ", ip = " << QDTCrossTalk::Crosstalk_DevIP(dev_ip) + << ", printer_name= " << QDTCrossTalk::Crosstalk_DevName(dev_name) + << ", con_type= " << connect_type << ", signal= " << printer_signal + << ", bind_state= " << bind_state; } } @@ -7179,12 +7342,12 @@ void DeviceManager::on_machine_alive(std::string json_str) if (obj->dev_ip.compare(dev_ip) != 0) { if ( connection_name.empty() ) { - BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << Slic3r::GUI::wxGetApp().format_IP(obj->dev_ip) << " to " << Slic3r::GUI::wxGetApp().format_IP(dev_ip); + BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << QDTCrossTalk::Crosstalk_DevIP(obj->dev_ip) << " to " << QDTCrossTalk::Crosstalk_DevIP(dev_ip); obj->dev_ip = dev_ip; } else { if ( obj->dev_connection_name.empty() || obj->dev_connection_name.compare(connection_name) == 0) { - BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << Slic3r::GUI::wxGetApp().format_IP(obj->dev_ip) << " to " << Slic3r::GUI::wxGetApp().format_IP(dev_ip) << " connection_name is " << connection_name; + BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << QDTCrossTalk::Crosstalk_DevIP(obj->dev_ip) << " to " << QDTCrossTalk::Crosstalk_DevIP(dev_ip) << " connection_name is " << connection_name; if(obj->dev_connection_name.empty()){obj->dev_connection_name = connection_name;} obj->dev_ip = dev_ip; } @@ -7200,20 +7363,41 @@ void DeviceManager::on_machine_alive(std::string json_str) obj->bind_ssdp_version != ssdp_version || obj->printer_type != MachineObject::parse_printer_type(printer_type_str)) { + if (obj->dev_connection_type != connect_type || + obj->bind_state != bind_state || + obj->bind_sec_link != sec_link || + obj->bind_ssdp_version != ssdp_version || + obj->printer_type != MachineObject::parse_printer_type(printer_type_str)) + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " UpdateLocalMachineInfo" + << ", dev_id= " << QDTCrossTalk::Crosstalk_DevId(dev_id) + << ", ip = " << QDTCrossTalk::Crosstalk_DevIP(dev_ip) + << ", printer_name= " << QDTCrossTalk::Crosstalk_DevName(dev_name) + << ", con_type= " << connect_type << ", signal= " << printer_signal + << ", bind_state= " << bind_state; + } + else + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " UpdateLocalMachineInfo_WIFI" + << ", dev_id= " << QDTCrossTalk::Crosstalk_DevId(dev_id) + << ", ip = " << QDTCrossTalk::Crosstalk_DevIP(dev_ip) + << ", printer_name= " << QDTCrossTalk::Crosstalk_DevName(dev_name) + << ", con_type= " << connect_type << ", signal= " << printer_signal + << ", bind_state= " << bind_state; + } + obj->wifi_signal = printer_signal; obj->dev_connection_type = connect_type; obj->bind_state = bind_state; obj->bind_sec_link = sec_link; obj->bind_ssdp_version = ssdp_version; obj->printer_type = MachineObject::parse_printer_type(printer_type_str); - BOOST_LOG_TRIVIAL(trace) << "DeviceManager::SsdpDiscovery, update localMachineList json" << json_str; } // U0 firmware if (obj->dev_connection_type.empty() && obj->bind_state.empty()) obj->bind_state = "free"; - //BOOST_LOG_TRIVIAL(debug) << "SsdpDiscovery:: Update Machine Info, printer_sn = " << dev_id << ", signal = " << printer_signal; obj->last_alive = Slic3r::Utils::get_current_time_utc(); obj->m_is_online = true; @@ -7246,9 +7430,9 @@ void DeviceManager::on_machine_alive(std::string json_str) Slic3r::GUI::wxGetApp().app_config->set_str("ip_address", obj->dev_id, obj->dev_ip); Slic3r::GUI::wxGetApp().app_config->save(); }*/ - BOOST_LOG_TRIVIAL(info) << "SsdpDiscovery::New Machine, ip= " << Slic3r::GUI::wxGetApp().format_IP(dev_ip) << ", printer_name= " << dev_name - << ", printer_type= " << printer_type_str << ", con_type= " - << connect_type <<", signal= " << printer_signal << ", bind_state= " << bind_state; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " New Machine, dev_id= " << QDTCrossTalk::Crosstalk_DevId(dev_id) + << ", ip = " << QDTCrossTalk::Crosstalk_DevIP(dev_ip) <<", printer_name = " << QDTCrossTalk::Crosstalk_DevName(dev_name) + << ", con_type= " << connect_type <<", signal= " << printer_signal << ", bind_state= " << bind_state; } } catch (...) { @@ -7261,13 +7445,22 @@ MachineObject* DeviceManager::insert_local_device(std::string dev_name, std::str MachineObject* obj; obj = new MachineObject(m_agent, dev_name, dev_id, dev_ip); obj->printer_type = MachineObject::parse_printer_type("C11"); - obj->dev_connection_type = connection_type; - obj->bind_state = bind_state; + obj->dev_connection_type = connection_type == "farm" ? "lan":connection_type; + obj->bind_state = connection_type == "farm" ? "free":bind_state; obj->bind_sec_link = "secure"; obj->bind_ssdp_version = version; obj->m_is_online = true; obj->set_access_code(access_code, false); obj->set_user_access_code(access_code, false); + + + auto it = localMachineList.find(dev_id); + if (it != localMachineList.end()) { + localMachineList[dev_id] = obj; + } else { + localMachineList.insert(std::make_pair(dev_id, obj)); + } + return obj; } @@ -7401,7 +7594,7 @@ void DeviceManager::clean_user_info() bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnect) { - BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id; + BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << QDTCrossTalk::Crosstalk_DevId(dev_id); auto my_machine_list = get_my_machine_list(); auto it = my_machine_list.find(dev_id); @@ -7412,8 +7605,6 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec if (last_selected->second->connection_type() == "lan") { if (last_selected->second->is_connecting() && !need_disconnect) return false; - - if (!need_disconnect) {m_agent->disconnect_printer(); } } } @@ -7431,7 +7622,6 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec } else { // lan mode printer reconnect printer if (m_agent) { - if (!need_disconnect) {m_agent->disconnect_printer();} it->second->reset(); #if !QDT_RELEASE_TO_PUBLIC it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); @@ -7461,7 +7651,6 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec #else it->second->connect(it->second->local_use_ssl_for_mqtt); #endif - m_agent->set_user_selected_machine(dev_id); it->second->set_lan_mode_connection_state(true); } } @@ -7491,28 +7680,6 @@ MachineObject* DeviceManager::get_selected_machine() return nullptr; } -void DeviceManager::add_user_subscribe() -{ - /* user machine */ - std::vector dev_list; - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - dev_list.push_back(it->first); - BOOST_LOG_TRIVIAL(trace) << "add_user_subscribe: " << it->first; - } - m_agent->add_subscribe(dev_list); -} - -void DeviceManager::del_user_subscribe() -{ - /* user machine */ - std::vector dev_list; - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - dev_list.push_back(it->first); - BOOST_LOG_TRIVIAL(trace) << "del_user_subscribe: " << it->first; - } - m_agent->del_subscribe(dev_list); -} - void DeviceManager::subscribe_device_list(std::vector dev_list) { std::vector unsub_list; @@ -7520,7 +7687,7 @@ void DeviceManager::subscribe_device_list(std::vector dev_list) for (auto& it : subscribe_list_cache) { if (it != selected_machine) { unsub_list.push_back(it); - BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: unsub dev id = " << it; + BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: unsub dev id = " << QDTCrossTalk::Crosstalk_DevId(it); } } BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: unsub_list size = " << unsub_list.size(); @@ -7530,7 +7697,7 @@ void DeviceManager::subscribe_device_list(std::vector dev_list) } for (auto& it : dev_list) { subscribe_list_cache.push_back(it); - BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: sub dev id = " << it; + BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: sub dev id = " << QDTCrossTalk::Crosstalk_DevId(it); } BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: sub_list size = " << subscribe_list_cache.size(); if (!unsub_list.empty()) @@ -7553,6 +7720,7 @@ std::map DeviceManager::get_my_machine_list() for (auto it = localMachineList.begin(); it != localMachineList.end(); it++) { if (!it->second) continue; + if (it->second->has_access_right() && it->second->is_avaliable() && it->second->is_lan_mode_printer()) { // remove redundant in userMachineList if (result.find(it->first) == result.end()) { @@ -7893,16 +8061,38 @@ bool DeviceManager::load_filaments_blacklist_config() return true; } else { - BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = " << config_file; + BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = filaments_blacklist.json"; } } catch (...) { - BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = " << config_file; + BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = filaments_blacklist.json"; return false; } return true; } +string DeviceManager::get_fan_text(const std::string& type_str, const std::string& key) +{ + std::vector filaments; + std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json"; + boost::nowide::ifstream json_file(config_file.c_str()); + try + { + json jj; + if (json_file.is_open()) { + json_file >> jj; + if (jj.contains("00.00.00.00")) { + json const& printer = jj["00.00.00.00"]; + if (printer.contains("fan") && printer["fan"].contains(key)) { + return printer["fan"][key].get(); + } + } + } + } + catch (...) {} + return string(); +} + bool DeviceManager::is_virtual_slot(int ams_id) { if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) @@ -7947,30 +8137,23 @@ void DeviceManager::OnSelectedMachineLost() { GUI::wxGetApp().sidebar().load_ams_list(string(), nullptr); } -// moved from tao.wang and zhimin.zeng -void check_filaments_for_ams_slot(std::string model_id, - std::string tag_vendor, - std::string tag_type, - int ams_id, - int slot_id, - std::string tag_name, - bool& in_blacklist, - std::string& ac, - wxString& info) + +void check_filaments(std::string model_id, + std::string tag_vendor, + std::string tag_type, + int ams_id, + int slot_id, + std::string tag_name, + bool& in_blacklist, + std::string& ac, + wxString& info, + wxString& wiki_url) { if (tag_name.empty()) { tag_name = DeviceManager::get_filament_name_from_ams(ams_id, slot_id); } - std::unordered_map blacklist_prompt = - { - {"TPU: not supported", _L("TPU is not supported by Box.")}, - {"PVA: flexible", _L("Damp PVA will become flexible and get stuck inside Box,please take care to dry it before use.")}, - {"CF/GF: hard and brittle", _L("CF/GF filaments are hard and brittle, It's easy to break or get stuck in Box, please use with caution.")}, - {"PLA-Glow", _L("The rough surface of PLA Glow can accelerate wear on the Box system, particularly on the internal components of the Box Lite.")} - }; - in_blacklist = false; std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower); @@ -7983,6 +8166,7 @@ void check_filaments_for_ams_slot(std::string model_id, std::string type = filament_item.contains("type") ? filament_item["type"].get() : ""; std::string type_suffix = filament_item.contains("type_suffix") ? filament_item["type_suffix"].get() : ""; std::string name = filament_item.contains("name") ? filament_item["name"].get() : ""; + std::string slot = filament_item.contains("slot") ? filament_item["slot"].get() : ""; std::vector model_ids = filament_item.contains("model_id") ? filament_item["model_id"].get>() : std::vector(); std::string action = filament_item.contains("action") ? filament_item["action"].get() : ""; std::string description = filament_item.contains("description") ? filament_item["description"].get() : ""; @@ -8016,14 +8200,37 @@ void check_filaments_for_ams_slot(std::string model_id, std::transform(name.begin(), name.end(), name.begin(), ::tolower); if (!name.empty() && (name != tag_name)) { continue;} + // check loc + if (!slot.empty()) { + bool is_virtual_slot = DeviceManager::is_virtual_slot(ams_id); + bool check_virtual_slot = (slot == "ext"); + bool check_ams_slot = (slot == "ams"); + if (is_virtual_slot && !check_virtual_slot) { + continue; + } else if (!is_virtual_slot && !check_ams_slot) { + continue; + } + } + in_blacklist = true; ac = action; - info = blacklist_prompt[description]; + info = _L(description); + wiki_url = filament_item.contains("wiki") ? filament_item["wiki"].get() : ""; return; + + // Using in description + L("TPU is not supported by AMS."); + L("Damp PVA will become flexible and get stuck inside AMS,please take care to dry it before use."); + L("The rough surface of PLA Glow can accelerate wear on the AMS system, particularly on the internal components of the AMS Lite."); + L("CF/GF filaments are hard and brittle, It's easy to break or get stuck in AMS, please use with caution."); + L("PPS-CF is brittle and could break in bended PTFE tube above Toolhead."); + L("PPA-CF is brittle and could break in bended PTFE tube above Toolhead."); } } } + + void DeviceManager::check_filaments_in_blacklist(std::string model_id, std::string tag_vendor, std::string tag_type, @@ -8035,17 +8242,23 @@ void DeviceManager::check_filaments_in_blacklist(std::string model_id, std::string &ac, wxString &info) { - if (ams_id < 0 || slot_id < 0) { + wxString wiki_url; + check_filaments_in_blacklist_url(model_id, tag_vendor, tag_type, filament_id, ams_id, slot_id, tag_name, in_blacklist, ac, info, wiki_url); +} + +void DeviceManager::check_filaments_in_blacklist_url(std::string model_id, std::string tag_vendor, std::string tag_type, const std::string& filament_id, int ams_id, int slot_id, std::string tag_name, bool& in_blacklist, std::string& ac, wxString& info, wxString& wiki_url) +{ + if (ams_id < 0 || slot_id < 0) + { return; } - if (!check_filaments_printable(tag_vendor, tag_type, filament_id, ams_id, in_blacklist, ac, info)) { + if (!check_filaments_printable(tag_vendor, tag_type, filament_id, ams_id, in_blacklist, ac, info)) + { return; } - if (!DeviceManager::is_virtual_slot(ams_id)) { - check_filaments_for_ams_slot(model_id, tag_vendor, tag_type, ams_id, slot_id, tag_name, in_blacklist, ac, info); - } + check_filaments(model_id, tag_vendor, tag_type, ams_id, slot_id, tag_name, in_blacklist, ac, info, wiki_url); } std::string DeviceManager::load_gcode(std::string type_str, std::string gcode_file) @@ -8060,7 +8273,7 @@ std::string DeviceManager::load_gcode(std::string type_str, std::string gcode_fi return gcode_str.str(); } } catch(...) { - BOOST_LOG_TRIVIAL(error) << "load gcode file failed, file = " << gcode_file << ", path = " << gcode_full_path; + BOOST_LOG_TRIVIAL(error) << "load gcode file failed, file = " << gcode_file; } diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 720ffaa..b860a87 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -250,6 +250,11 @@ struct AirMode // If the fan is off, it cannot be controlled and is displayed as off std::vector off; // If the fan is not off or ctrl, it will be displayed as auto + +public: + bool operator ==(const AirMode& other) const { + return (id == other.id) && (ctrl == other.ctrl) && (off == other.off); + }; }; struct AirParts @@ -260,6 +265,11 @@ struct AirParts int state{ 0 };// 100% int range_start{ 0 };// 100% int range_end{ 0 };// 100% + +public: + bool operator ==(const AirParts& other) const { + return (type == other.type) && (id == other.id) && (func == other.func) && (state == other.state) && (range_start == other.range_start) && (range_end == other.range_end); + }; }; struct AirDuctData @@ -267,6 +277,22 @@ struct AirDuctData int curren_mode{ 0 }; std::unordered_map modes; std::vector parts; + + int m_sub_mode = -1;// the submode of airduct, for cooling: 0-filter, 1-cooling + bool m_support_cooling_filter = false;// support switch filter on cooling mode or not + +public: + bool operator ==(const AirDuctData& other) const { + return (curren_mode == other.curren_mode) && (modes == other.modes) && (parts == other.parts) && + (m_sub_mode == other.m_sub_mode) && (m_support_cooling_filter == other.m_support_cooling_filter); + }; + + bool operator !=(const AirDuctData& other) const { + return !(operator==(other)); + }; + + bool IsSupportCoolingFilter() const { return m_support_cooling_filter;} + bool IsCoolingFilerOn() const { return m_sub_mode == 0;} }; struct RatingInfo { @@ -484,7 +510,6 @@ enum AIR_DUCT { AIR_DUCT_HEATING_INTERNAL_FILT, AIR_DUCT_EXHAUST, AIR_DUCT_FULL_COOLING, - AIR_DUCT_NUM, AIR_DUCT_INIT = 0xFF //Initial mode, only used within mc }; @@ -668,6 +693,7 @@ public: //PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN; std::string printer_type; /* model_id */ + std::string get_show_printer_type() const; PrinterSeries get_printer_series() const; PrinterArch get_printer_arch() const; std::string get_printer_ams_type() const; @@ -771,6 +797,7 @@ public: AmsTray *get_ams_tray(std::string ams_id, std::string tray_id); std::string get_filament_id(std::string ams_id, std::string tray_id) const; + std::string get_filament_type(const std::string& ams_id, const std::string& tray_id) const; // parse amsStatusMain and ams_status_sub void _parse_ams_status(int ams_status); @@ -819,6 +846,7 @@ public: [[nodiscard]] bool is_nozzle_flow_type_supported() const { return is_enable_np; }; [[nodiscard]] NozzleFlowType get_nozzle_flow_type(int extruder_id) const; [[nodiscard]] Extder get_current_extruder() const; + [[nodiscard]] wxString get_nozzle_replace_url() const; //new fan data AirDuctData m_air_duct_data; @@ -1033,9 +1061,21 @@ public: int nozzle_setting_hold_count = 0; + //refine printer bool xcam_ai_monitoring{ false }; + bool xcam_disable_ai_detection_display{false}; + bool xcam_spaghetti_detection{false}; + bool xcam_purgechutepileup_detection{false}; + bool xcam_nozzleclumping_detection{false}; + bool xcam_airprinting_detection{false}; + time_t xcam_ai_monitoring_hold_start = 0; std::string xcam_ai_monitoring_sensitivity; + std::string xcam_spaghetti_detection_sensitivity; + std::string xcam_purgechutepileup_detection_sensitivity; + std::string xcam_nozzleclumping_detection_sensitivity; + std::string xcam_airprinting_detection_sensitivity; + bool xcam_buildplate_marker_detector{ false }; time_t xcam_buildplate_marker_hold_start = 0; bool xcam_auto_recovery_step_loss{ false }; @@ -1047,6 +1087,9 @@ public: int nozzle_selected_count = 0; bool flag_update_nozzle = {true}; + // part skip + std::vector m_partskip_ids; + /*target from Studio-SwitchBoard, default to INVALID_NOZZLE_ID if no switching control from PC*/ int targ_nozzle_id_from_pc = INVALID_NOZZLE_ID; @@ -1055,7 +1098,7 @@ public: bool is_support_extrusion_cali{false}; bool is_support_first_layer_inspect{false}; bool is_support_ai_monitoring {false}; - bool is_support_lidar_calibration {false}; + bool is_support_lidar_calibration {false};// the lidar calibration for 3D Studio bool is_support_build_plate_marker_detect{false}; PlateMakerDectect m_plate_maker_detect_type{ POS_CHECK }; @@ -1096,6 +1139,14 @@ public: bool is_support_internal_timelapse { false };// fun[28], support timelapse without SD card bool is_support_command_homing { false };// fun[32] bool is_support_brtc{false}; // fun[31], support tcp and upload protocol + bool is_support_ext_change_assist{false}; + bool is_support_partskip{false}; + + // refine printer function options + bool is_support_spaghetti_detection{false}; + bool is_support_purgechutepileup_detection{false}; + bool is_support_nozzleclumping_detection{false}; + bool is_support_airprinting_detection{false}; bool installed_upgrade_kit{false}; int bed_temperature_limit = -1; @@ -1199,9 +1250,10 @@ public: int command_go_home2(); int command_control_fan(int fan_type, int val); // Old protocol int command_control_fan_new(int fan_id, int val, const CommandCallBack &cb); // New protocol - int command_control_air_duct(int mode_id, const CommandCallBack& cb); + int command_control_air_duct(int mode_id, int submode, const CommandCallBack& cb); int command_task_abort(); /* cancelled the job_id */ + int command_task_partskip(std::vector part_ids); int command_task_cancel(std::string job_id); int command_task_pause(); int command_task_resume(); @@ -1213,7 +1265,9 @@ public: int command_stop_buzzer(); /* temp*/ + bool m_support_mqtt_bet_ctrl = false; int command_set_bed(int temp); + int command_set_nozzle(int temp); int command_set_nozzle_new(int nozzle_id, int temp); int command_set_chamber(int temp); @@ -1253,6 +1307,7 @@ public: int command_nozzle_blob_detect(bool nozzle_blob_detect); // axis string is X, Y, Z, E + bool m_support_mqtt_axis_control = false; int command_axis_control(std::string axis, double unit = 1.0f, double input_val = 1.0f, int speed = 3000); int command_extruder_control(int nozzle_id, double val); @@ -1281,7 +1336,14 @@ public: int command_ipcam_timelapse(bool on_off); int command_ipcam_resolution_set(std::string resolution); int command_xcam_control(std::string module_name, bool on_off, std::string lvl = ""); + + //refine printer int command_xcam_control_ai_monitoring(bool on_off, std::string lvl); + int command_xcam_control_spaghetti_detection(bool on_off, std::string lvl); + int command_xcam_control_purgechutepileup_detection(bool on_off, std::string lvl); + int command_xcam_control_nozzleclumping_detection(bool on_off, std::string lvl); + int command_xcam_control_airprinting_detection(bool on_off, std::string lvl); + int command_xcam_control_first_layer_inspector(bool on_off, bool print_halt); int command_xcam_control_buildplate_marker_detector(bool on_off); int command_xcam_control_auto_recovery_step_loss(bool on_off); @@ -1319,7 +1381,8 @@ public: /* Msg for display MsgFn */ typedef std::function MsgFn; - int publish_json(std::string json_str, int qos = 0, int flag = 0); + int publish_json(const json& json_item, int qos = 0, int flag = 0) ; + int publish_json(const std::string& json_str, int qos = 0, int flag = 0) = delete; int cloud_publish_json(std::string json_str, int qos = 0, int flag = 0); int local_publish_json(std::string json_str, int qos = 0, int flag = 0); int parse_json(std::string tunnel, std::string payload, bool key_filed_only = false); @@ -1452,8 +1515,6 @@ public: bool set_selected_machine(std::string dev_id, bool need_disconnect = false); MachineObject* get_selected_machine(); - void add_user_subscribe(); - void del_user_subscribe(); void subscribe_device_list(std::vector dev_list); @@ -1505,6 +1566,32 @@ public: return T(); } + static json get_json_from_config(const std::string& type_str, const std::string& key1, const std::string& key2 = std::string()) { + std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json"; + boost::nowide::ifstream json_file(config_file.c_str()); + try { + json jj; + if (json_file.is_open()) { + json_file >> jj; + if (jj.contains("00.00.00.00")) { + json const& printer = jj["00.00.00.00"]; + if (printer.contains(key1)) { + json const& key1_item = printer[key1]; + if (key2.empty()) { + return key1_item; + } + + if (key1_item.contains(key2)) { + return key1_item[key2]; + } + } + } + } + } + catch (...) {} + return json(); + } + static std::string parse_printer_type(std::string type_str); static std::string get_printer_display_name(std::string type_str); static std::string get_printer_thumbnail_img(std::string type_str); @@ -1518,10 +1605,14 @@ public: static bool get_printer_is_enclosed(std::string type_str); static bool get_printer_can_set_nozzle(std::string type_str);// can set nozzle from studio static bool load_filaments_blacklist_config(); + + static string get_fan_text(const std::string& type_str, const std::string& key); + static std::vector get_resolution_supported(std::string type_str); static std::vector get_compatible_machine(std::string type_str); static std::vector get_unsupport_auto_cali_filaments(std::string type_str); static void check_filaments_in_blacklist(std::string model_id, std::string tag_vendor, std::string tag_type, const std::string& filament_id, int ams_id, int slot_id, std::string tag_name, bool &in_blacklist, std::string &ac, wxString &info); + static void check_filaments_in_blacklist_url(std::string model_id, std::string tag_vendor, std::string tag_type, const std::string& filament_id, int ams_id, int slot_id, std::string tag_name, bool& in_blacklist, std::string& ac, wxString& info, wxString& wiki_url); static boost::bimaps::bimap get_all_model_id_with_name(); static std::string load_gcode(std::string type_str, std::string gcode_file); static bool is_virtual_slot(int ams_id); diff --git a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp index 93d188e..c075485 100644 --- a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp +++ b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp @@ -151,7 +151,23 @@ void uiAmsPercentHumidityDryPopup::UpdateContents() if (m_left_dry_time > 0) { - const wxString& time_str = wxString::Format(_L("%d : %d"), m_left_dry_time / 60, m_left_dry_time % 60); + wxString display_hour_str; + int left_hours = m_left_dry_time / 60; + if (left_hours < 10) { + display_hour_str = wxString::Format("0%d", left_hours); + } else { + display_hour_str = wxString::Format("%d", left_hours); + } + + wxString display_min_str; + int left_minutes = m_left_dry_time % 60; + if (left_minutes < 10) { + display_min_str = wxString::Format("0%d", left_minutes); + } else { + display_min_str = wxString::Format("%d", left_minutes); + } + + const wxString& time_str = wxString::Format("%s : %s", display_hour_str, display_min_str); left_dry_time_label->SetLabel(time_str); } else diff --git a/src/slic3r/GUI/EncodedFilament.cpp b/src/slic3r/GUI/EncodedFilament.cpp new file mode 100644 index 0000000..3a486bb --- /dev/null +++ b/src/slic3r/GUI/EncodedFilament.cpp @@ -0,0 +1,217 @@ +#include "EncodedFilament.hpp" + +#include "GUI_App.hpp" + +namespace Slic3r +{ + +static wxString _ColourToString(const wxColour& color) +{ + return wxString::Format("#%02X%02X%02X%02X", color.Red(), color.Green(), color.Blue(), color.Alpha()); +} + +FilamentColorCodeQuery::FilamentColorCodeQuery() +{ + m_fila_id2colors_map = new std::unordered_map; + m_fila_path = data_dir() + "/system/QDT/filament/filaments_color_codes.json"; + LoadFromLocal(); +} + + +FilamentColorCodeQuery::~FilamentColorCodeQuery() +{ + for (auto& pair : *m_fila_id2colors_map) { delete pair.second; } + + delete m_fila_id2colors_map; + m_fila_id2colors_map = nullptr; +} + +FilamentColorCodes* FilamentColorCodeQuery::GetFilaInfoMap(const wxString& fila_id) const +{ + const auto& iter = m_fila_id2colors_map->find(fila_id); + return (iter != m_fila_id2colors_map->end()) ? iter->second : nullptr; +} + +Slic3r::FilamentColorCode* FilamentColorCodeQuery::GetFilaInfo(const wxString& fila_id, const FilamentColor& colors) const +{ + FilamentColorCodes* color_info_map = GetFilaInfoMap(fila_id); + +#if 0 + if (color_info_map && !color_info_map->GetColorCode(colors)) + { + wxString clr_strs; + for (const auto& clr : colors.m_colors) + { + clr_strs += " "; + clr_strs += _ColourToString(clr); + } + + BOOST_LOG_TRIVIAL(warning) << "FilamentColorCodeQuery::GetFilaInfo: No color code found for " << fila_id << " with color type " << (int)colors.m_color_type << "colors" << clr_strs; + color_info_map->Debug(" "); + } +#endif + + return color_info_map ? color_info_map->GetColorCode(colors) : nullptr; +} + +wxString FilamentColorCodeQuery::GetFilaColorName(const wxString& fila_id, const FilamentColor& colors) const +{ + FilamentColorCode* color_info = GetFilaInfo(fila_id, colors); + return (color_info) ? color_info->GetFilaColorName() : wxString(); +} + +void FilamentColorCodeQuery::LoadFromLocal() +{ + std::ifstream json_file(encode_path(m_fila_path.c_str())); + try + { + if (json_file.is_open()) + { + const json& json_content = json::parse(json_file); + if (!json_content.contains("data")) { return; } + + const json& json_data = json_content["data"]; + for (const auto& json_data_item : json_data) + { + const wxString& fila_id = json_data_item.contains("fila_id") ? json_data_item["fila_id"].get() : wxString(); + const wxString& fila_type = json_data_item.contains("fila_type") ? json_data_item["fila_type"].get() : wxString(); + const wxString& fila_color_code = json_data_item.contains("fila_color_code") ? json_data_item["fila_color_code"].get() : wxString(); + + FilamentColor fila_color; + if (json_data_item.contains("fila_color")) + { + const auto& fila_color_strs = json_data_item["fila_color"].get>(); + for (const auto& color_str : fila_color_strs) { + if (color_str.size() > 3) /* Skip the value like "#0"*/{ + fila_color.m_colors.emplace(wxColour(color_str)); + } + } + } + + if (fila_color.m_colors.empty()) { + BOOST_LOG_TRIVIAL(warning) << "FilamentColorCodeQuery::LoadFromLocal: No colors found for fila_color_code: " << fila_color_code; + continue; // Skip if no colors are defined + }; + + const wxString& fila_color_type = json_data_item.contains("fila_color_type") ? wxString::FromUTF8(json_data_item["fila_color_type"].get()) : wxString(); + if (fila_color_type == wxString::FromUTF8("单色")) { + fila_color.m_color_type = FilamentColor::ColorType::SINGLE_CLR; + } else if (fila_color_type == wxString::FromUTF8("多拼色")) { + fila_color.m_color_type = FilamentColor::ColorType::MULTI_CLR; + } else if (fila_color_type == wxString::FromUTF8("渐变色")) + { + fila_color.m_color_type = FilamentColor::ColorType::GRADIENT_CLR; + }; + + std::unordered_map fila_color_names; + if (json_data_item.contains("fila_color_name")) + { + const json& color_names_json = json_data_item["fila_color_name"]; + for (const auto& color_name_item : color_names_json.items()) + { + const wxString& lang_code = wxString::FromUTF8(color_name_item.key()); + const wxString& color_name = wxString::FromUTF8(color_name_item.value().get()); + fila_color_names[lang_code] = color_name; + } + } + + CreateFilaCode(fila_id, fila_type, fila_color_code, std::move(fila_color), std::move(fila_color_names)); + } + } + } + catch (...) + { + assert(0 && "FilamentColorCodeQuery::LoadFromLocal failed"); + BOOST_LOG_TRIVIAL(error) << "FilamentColorCodeQuery::LoadFromLocal failed"; + } +} + +void FilamentColorCodeQuery::CreateFilaCode(const wxString& fila_id, + const wxString& fila_type, + const wxString& fila_color_code, + FilamentColor&& fila_color, + std::unordered_map&& fila_color_names) +{ + FilamentColorCodes* color_codes = GetFilaInfoMap(fila_id); + if (!color_codes) + { + color_codes = new FilamentColorCodes(fila_id, fila_type); + (*m_fila_id2colors_map)[fila_id] = color_codes; + } + + FilamentColorCode* color_code = new FilamentColorCode(fila_color_code, color_codes, std::move(fila_color), std::move(fila_color_names)); + color_codes->AddColorCode(color_code); +} +// End of class EncodedFilamentQuery + + +wxString FilamentColorCode::GetFilaColorName() const +{ + const wxString& strLanguage = Slic3r::GUI::wxGetApp().app_config->get("language"); + const wxString& lang_code = strLanguage.BeforeFirst('_'); + auto it = m_fila_color_names.find(lang_code); + if (it != m_fila_color_names.end() && !it->second.empty()) { return it->second; } + + it = m_fila_color_names.find("en");// retry with English as fallback + return (it != m_fila_color_names.end()) ? it->second : "Unknown"; +} + +FilamentColorCode::FilamentColorCode(const wxString& color_code, FilamentColorCodes* owner, FilamentColor&& color, std::unordered_map&& name_map) + : m_fila_color_code(color_code), + m_owner(owner), + m_fila_color(std::move(color)), + m_fila_color_names(std::move(name_map)) +{ +} + +void FilamentColorCode::Debug(const char* prefix) +{ + BOOST_LOG_TRIVIAL(debug) << prefix << "Fila Color Code: " << m_fila_color_code + << ", Colors: " << m_fila_color.ColorCount() + << ", Type: " << static_cast(m_fila_color.m_color_type); + for (const auto& color : m_fila_color.m_colors) { BOOST_LOG_TRIVIAL(debug) << prefix << " Color: " << _ColourToString(color); } + //for (const auto& name_pair : m_fila_color_names) { BOOST_LOG_TRIVIAL(debug) << prefix << " Color Name [" << name_pair.first << "]: " << name_pair.second;} +} + +FilamentColorCodes::FilamentColorCodes(const wxString& fila_id, const wxString& fila_type) + : m_fila_id(fila_id), m_fila_type(fila_type) +{ + m_fila_colors_map = new FilamentColor2CodeMap; +} + +FilamentColorCodes::~FilamentColorCodes() +{ + for (auto iter : *m_fila_colors_map) { delete iter.second; } + + m_fila_colors_map->clear(); + delete m_fila_colors_map; +} + +Slic3r::FilamentColorCode* FilamentColorCodes::GetColorCode(const FilamentColor& colors) const +{ + const auto& it = m_fila_colors_map->find(colors); + return (it != m_fila_colors_map->end()) ? it->second : nullptr; +} + +void FilamentColorCodes::AddColorCode(FilamentColorCode* code) +{ + m_fila_colors_map->emplace(code->GetFilaColor(), code); +} + +void FilamentColorCodes::Debug(const char* prefix) +{ + BOOST_LOG_TRIVIAL(debug) << prefix << "Fila ID: " << m_fila_id << ", Type: " << m_fila_type; + + auto iter = m_fila_colors_map->begin(); + while (iter != m_fila_colors_map->end()) + { + iter->second->Debug(prefix); + iter++; + } + + BOOST_LOG_TRIVIAL(debug) << prefix << "End"; +} + + + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/EncodedFilament.hpp b/src/slic3r/GUI/EncodedFilament.hpp new file mode 100644 index 0000000..d65b000 --- /dev/null +++ b/src/slic3r/GUI/EncodedFilament.hpp @@ -0,0 +1,227 @@ +#ifndef slic3r_ENCODED_FILAMENT_hpp_ +#define slic3r_ENCODED_FILAMENT_hpp_ + +#include +#include +#include +#include + +#include +#include + +#include + +namespace Slic3r +{ + +//Previous definitions +class FilamentColorCode; +class FilamentColorCodes; +class FilamentColorCodeQuery; + +// Represents a color in HSV format +struct ColourHSV +{ + double h, s, v; +}; + +inline ColourHSV wxColourToHSV(const wxColour& c) +{ + double r = c.Red() / 255.0; + double g = c.Green() / 255.0; + double b = c.Blue() / 255.0; + + double maxc = std::max({ r, g, b }); + double minc = std::min({ r, g, b }); + double delta = maxc - minc; + + double h = 0, s = 0, v = maxc; + if (delta > 0.00001) { + if (maxc == r) { + h = 60.0 * (fmod(((g - b) / delta), 6.0)); + } else if (maxc == g) { + h = 60.0 * (((b - r) / delta) + 2.0); + } else { + h = 60.0 * (((r - g) / delta) + 4.0); + } + + if (h < 0) h += 360.0; + s = delta / maxc; + } else { + h = 0; + s = 0; + } + return { h, s, v }; +} + +// FilamentColorSorter +struct wxColorSorter +{ + std::size_t operator()(const wxColour& lhs_it, const wxColour& rhs_it) const noexcept { + ColourHSV ha = wxColourToHSV(lhs_it); + ColourHSV hb = wxColourToHSV(rhs_it); + if (ha.h != hb.h) return ha.h < hb.h; + if (ha.s != hb.s) return ha.s < hb.s; + if (ha.v != hb.v) return ha.v < hb.v; + if (lhs_it.Alpha() != rhs_it.Alpha()) return lhs_it.Alpha() < rhs_it.Alpha(); + return false; + } +}; + +struct FilamentColor +{ + enum class ColorType : char + { + SINGLE_CLR = 0, // single color filament + MULTI_CLR, // multi-color filament + GRADIENT_CLR, // gradient filament + }; + + ColorType m_color_type = ColorType::SINGLE_CLR; // default to single color + std::set m_colors; + +public: + size_t ColorCount() const noexcept { return m_colors.size(); } + + void EndSet(int ctype) + { + if (m_colors.size() < 2) + { + m_color_type = ColorType::SINGLE_CLR; + } + else + { + if (ctype == 0) + { + m_color_type = ColorType::GRADIENT_CLR; + } + else + { + m_color_type = ColorType::MULTI_CLR; + } + } + } + +public: + bool operator<(const FilamentColor& other) const { + if (ColorCount() != other.ColorCount()) { return ColorCount() < other.ColorCount(); }; + if (m_color_type != other.m_color_type) { return m_color_type < other.m_color_type; } + if (m_colors == other.m_colors) { return false;} + + // Compare colors in HSV format + auto lhs_it = m_colors.begin(); + auto rhs_it = other.m_colors.begin(); + while ((lhs_it != m_colors.end())) + { + ColourHSV ha = wxColourToHSV(*lhs_it); + ColourHSV hb = wxColourToHSV(*rhs_it); + if (ha.h != hb.h) return ha.h < hb.h; + if (ha.s != hb.s) return ha.s < hb.s; + if (ha.v != hb.v) return ha.v < hb.v; + + int lhs_alpha = lhs_it->Alpha(); + int rhs_alpha = rhs_it->Alpha(); + if (lhs_alpha != rhs_alpha) return lhs_alpha < rhs_alpha; + + lhs_it++; + rhs_it++; + } + + return false; + } +}; + +// Compare function for EncodedFilaColor +struct EncodedFilaColorEqual +{ + bool operator()(const FilamentColor& lhs, const FilamentColor& rhs) const noexcept { return lhs < rhs; } +}; +using FilamentColor2CodeMap = std::map; + + +// FilamentColorCodeQuery class is used to query filament color codes and their associated information +class FilamentColorCodeQuery +{ +public: + FilamentColorCodeQuery(); + virtual ~FilamentColorCodeQuery(); + +public: + FilamentColorCodes* GetFilaInfoMap(const wxString& fila_id) const; + wxString GetFilaColorName(const wxString& fila_id, const FilamentColor& colors) const; + +private: + FilamentColorCode* GetFilaInfo(const wxString& fila_id, const FilamentColor& colors) const; + +protected: + void LoadFromLocal(); + +public: + void CreateFilaCode(const wxString& fila_id, + const wxString& fila_type, + const wxString& fila_color_code, + FilamentColor&& fila_color, + std::unordered_map&& fila_color_names); + +private: + /* loaded info*/ + std::string m_fila_path; + + std::unordered_map* m_fila_id2colors_map; // +}; + +// EncodedFilaColorsInfo class holds a mapping of filament codes to specific filamet type +class FilamentColorCodes +{ +public: + FilamentColorCodes(const wxString& fila_id, const wxString& fila_type); + virtual ~FilamentColorCodes(); + +public: + wxString GetFilaCode() const { return m_fila_id; } + wxString GetFilaType() const { return m_fila_type; } + + FilamentColor2CodeMap* GetFilamentColor2CodeMap() const { return m_fila_colors_map; } + FilamentColorCode* GetColorCode(const FilamentColor& colors) const; + + void Debug(const char* prefix); + +public: + void AddColorCode(FilamentColorCode* code); + +private: + wxString m_fila_id;//eg. 54600 + wxString m_fila_type;//eg. PEBA 90A + FilamentColor2CodeMap* m_fila_colors_map; // key is the color set, value is the info +}; + +// The EncodedFilaColorInfo class holds information about a specific filament color +class FilamentColorCode +{ +public: + FilamentColorCode() = delete; + FilamentColorCode(const wxString& color_code, FilamentColorCodes* owner, FilamentColor&& color, std::unordered_map&& name_map); + ~FilamentColorCode() {}; + +public: + wxString GetFilaCode() const { return m_owner->GetFilaCode(); } + wxString GetFilaType() const { return m_owner->GetFilaType(); } + + + wxString GetFilaColorCode() const { return m_fila_color_code; } // eg. Q01B00 + FilamentColor GetFilaColor() const { return m_fila_color; } + wxString GetFilaColorName() const; + + void Debug(const char* prefix); + +private: + FilamentColorCodes* m_owner; + + /* color info*/ + wxString m_fila_color_code; // eg. Q01B00 + FilamentColor m_fila_color; + std::unordered_map m_fila_color_names; // eg. en -> Red +}; + +} +#endif \ No newline at end of file diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 35a13b0..f8a41f6 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1215,7 +1215,9 @@ void Choice::register_dynamic_list(std::string const &optname, DynamicList *list void DynamicList::update() { - for (auto c : m_choices) apply_on(c); + for (auto c : m_choices) { + apply_on(c); + } } void DynamicList::add_choice(Choice *choice) @@ -1520,7 +1522,8 @@ void Choice::set_value(const boost::any& value, bool change_event) if (m_opt_id.compare("host_type") == 0 && val != 0 && m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType val--; - 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" || m_opt_id == "curr_bed_type") + 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" || m_opt_id == "curr_bed_type" || m_opt_id == "locked_skin_infill_pattern" || m_opt_id == "locked_skeleton_infill_pattern") { std::string key; const t_config_enum_values& map_names = *m_opt.enum_keys_map; @@ -1607,8 +1610,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" || m_opt_id == "curr_bed_type") { + 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" || m_opt_id == "curr_bed_type" || m_opt_id == "locked_skin_infill_pattern" || + m_opt_id == "locked_skeleton_infill_pattern") { const std::string& key = m_opt.enum_values[field->GetSelection()]; m_value = int(m_opt.enum_keys_map->at(key)); } diff --git a/src/slic3r/GUI/FilamentBitmapUtils.cpp b/src/slic3r/GUI/FilamentBitmapUtils.cpp new file mode 100644 index 0000000..4f4b9f8 --- /dev/null +++ b/src/slic3r/GUI/FilamentBitmapUtils.cpp @@ -0,0 +1,184 @@ +#include +#include +#include +#include + +#include "EncodedFilament.hpp" + +namespace Slic3r { namespace GUI { + +// Helper struct to hold bitmap and DC +struct BitmapDC { + wxBitmap bitmap; + wxMemoryDC dc; + + BitmapDC(const wxSize& size) : bitmap(size), dc(bitmap) { + // Don't set white background - let the color patterns fill the entire area + dc.SetPen(*wxTRANSPARENT_PEN); + } +}; + +static BitmapDC init_bitmap_dc(const wxSize& size) { + return BitmapDC(size); +} + +// Sort colors by HSV values (primarily by hue, then saturation, then value) +static void sort_colors_by_hsv(std::vector& colors) { + if (colors.size() < 2) return; + std::sort(colors.begin(), colors.end(), + [](const wxColour& a, const wxColour& b) { + ColourHSV ha = wxColourToHSV(a); + ColourHSV hb = wxColourToHSV(b); + if (ha.h != hb.h) return ha.h < hb.h; + if (ha.s != hb.s) return ha.s < hb.s; + return ha.v < hb.v; + }); +} + +static wxBitmap create_single_filament_bitmap(const wxColour& color, const wxSize& size) +{ + BitmapDC bdc = init_bitmap_dc(size); + if (!bdc.dc.IsOk()) return wxNullBitmap; + + bdc.dc.SetBrush(wxBrush(color)); + bdc.dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); + + // Add gray border for light colors (similar to wxExtensions.cpp logic) + if (color.Red() > 224 && color.Blue() > 224 && color.Green() > 224) { + bdc.dc.SetPen(*wxGREY_PEN); + bdc.dc.SetBrush(*wxTRANSPARENT_BRUSH); + bdc.dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); + } + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + +static wxBitmap create_dual_filament_bitmap(const wxColour& color1, const wxColour& color2, const wxSize& size) +{ + BitmapDC bdc = init_bitmap_dc(size); + + int half_width = size.GetWidth() / 2; + + bdc.dc.SetBrush(wxBrush(color1)); + bdc.dc.DrawRectangle(0, 0, half_width, size.GetHeight()); + + bdc.dc.SetBrush(wxBrush(color2)); + bdc.dc.DrawRectangle(half_width, 0, size.GetWidth() - half_width, size.GetHeight()); + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + +static wxBitmap create_triple_filament_bitmap(const std::vector& colors, const wxSize& size) +{ + BitmapDC bdc = init_bitmap_dc(size); + + int third_width = size.GetWidth() / 3; + int remaining_width = size.GetWidth() - (third_width * 2); + + // Draw three vertical sections + bdc.dc.SetBrush(wxBrush(colors[0])); + bdc.dc.DrawRectangle(0, 0, third_width, size.GetHeight()); + + bdc.dc.SetBrush(wxBrush(colors[1])); + bdc.dc.DrawRectangle(third_width, 0, third_width, size.GetHeight()); + + bdc.dc.SetBrush(wxBrush(colors[2])); + bdc.dc.DrawRectangle(third_width * 2, 0, remaining_width, size.GetHeight()); + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + +static wxBitmap create_quadruple_filament_bitmap(const std::vector& colors, const wxSize& size) +{ + BitmapDC bdc = init_bitmap_dc(size); + + int half_width = (size.GetWidth() + 1) / 2; + int half_height = (size.GetHeight() + 1) / 2; + + const int rects[4][4] = { + {0, 0, half_width, half_height}, // Top left + {half_width, 0, size.GetWidth() - half_width, half_height}, // Top right + {0, half_height, half_width, size.GetHeight() - half_height}, // Bottom left + {half_width, half_height, size.GetWidth() - half_width, size.GetHeight() - half_height} // Bottom right + }; + + for (int i = 0; i < 4; i++) { + bdc.dc.SetBrush(wxBrush(colors[i])); + bdc.dc.DrawRectangle(rects[i][0], rects[i][1], rects[i][2], rects[i][3]); + } + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + +static wxBitmap create_gradient_filament_bitmap(const std::vector& colors, const wxSize& size) +{ + BitmapDC bdc = init_bitmap_dc(size); + + if (colors.size() == 1) { + return create_single_filament_bitmap(colors[0], size); + } + + // use segment gradient, make transition more natural + wxDC& dc = bdc.dc; + int total_width = size.GetWidth(); + int height = size.GetHeight(); + + // calculate segment count + int segment_count = colors.size() - 1; + double segment_width = (double)total_width / segment_count; + + int left = 0; + for (int i = 0; i < segment_count; i++) { + int current_width = (int)segment_width; + + // handle last segment, ensure fully filled + if (i == segment_count - 1) { + current_width = total_width - left; + } + + // avoid width exceed boundary + if (left + current_width > total_width) { + current_width = total_width - left; + } + + if (current_width > 0) { + auto rect = wxRect(left, 0, current_width, height); + dc.GradientFillLinear(rect, colors[i], colors[i + 1], wxEAST); + left += current_width; + } + } + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + +wxBitmap create_filament_bitmap(const std::vector& colors, const wxSize& size, bool force_gradient) +{ + if (colors.empty()) return wxNullBitmap; + + // Make a copy to sort without modifying original + std::vector sorted_colors = colors; + + // Sort colors by HSV when there are 2 or more colors + if (sorted_colors.size() >= 2) { + sort_colors_by_hsv(sorted_colors); + } + + if (force_gradient && sorted_colors.size() >= 2) { + return create_gradient_filament_bitmap(sorted_colors, size); + } + + switch (sorted_colors.size()) { + case 1: return create_single_filament_bitmap(sorted_colors[0], size); + case 2: return create_dual_filament_bitmap(sorted_colors[0], sorted_colors[1], size); + case 3: return create_triple_filament_bitmap(sorted_colors, size); + case 4: return create_quadruple_filament_bitmap(sorted_colors, size); + default: return create_gradient_filament_bitmap(sorted_colors, size); + } +} + +}} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/FilamentBitmapUtils.hpp b/src/slic3r/GUI/FilamentBitmapUtils.hpp new file mode 100644 index 0000000..b949522 --- /dev/null +++ b/src/slic3r/GUI/FilamentBitmapUtils.hpp @@ -0,0 +1,26 @@ +#ifndef slic3r_GUI_FilamentBitmapUtils_hpp_ +#define slic3r_GUI_FilamentBitmapUtils_hpp_ + +#include +#include +#include + +namespace Slic3r { namespace GUI { + +enum class FilamentRenderMode { + Single, + Dual, + Triple, + Quadruple, + Gradient +}; + +// Create a colour swatch bitmap. The render mode is chosen automatically from the +// number of colours unless force_gradient is true. +wxBitmap create_filament_bitmap(const std::vector& colors, + const wxSize& size, + bool force_gradient = false); + +}} // namespace Slic3r::GUI + +#endif // slic3r_GUI_FilamentBitmapUtils_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/FilamentMapDialog.cpp b/src/slic3r/GUI/FilamentMapDialog.cpp index 9396296..2a28218 100644 --- a/src/slic3r/GUI/FilamentMapDialog.cpp +++ b/src/slic3r/GUI/FilamentMapDialog.cpp @@ -116,7 +116,7 @@ static const StateColor btn_bg_blue(std::pair(wxColour(40, 90, 22 static const StateColor btn_bd_blue(std::pair(wxColour(68, 121, 251), StateColor::Normal)); -static const StateColor btn_text_green(std::pair(wxColour(255, 255, 254), StateColor::Normal)); +static const StateColor btn_text_blue(std::pair(wxColour(255, 255, 254), StateColor::Normal)); static const StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), @@ -222,7 +222,7 @@ FilamentMapDialog::FilamentMapDialog(wxWindow *parent, m_ok_btn->SetBackgroundColor(btn_bg_blue); m_ok_btn->SetBorderColor(btn_bd_blue); - m_ok_btn->SetTextColor(btn_text_green); + m_ok_btn->SetTextColor(btn_text_blue); m_cancel_btn->SetBackgroundColor(btn_bg_white); m_cancel_btn->SetBorderColor(btn_bd_white); m_cancel_btn->SetTextColor(btn_text_white); diff --git a/src/slic3r/GUI/FilamentPickerDialog.cpp b/src/slic3r/GUI/FilamentPickerDialog.cpp new file mode 100644 index 0000000..e8aeec4 --- /dev/null +++ b/src/slic3r/GUI/FilamentPickerDialog.cpp @@ -0,0 +1,733 @@ +#include "FilamentPickerDialog.hpp" +#include "GUI.hpp" +#include "I18N.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" +#include "EncodedFilament.hpp" +#include "Widgets/Label.hpp" +#include "Widgets/Button.hpp" +#include "Widgets/StateColor.hpp" +#include "wxExtensions.hpp" +#include +#include +#include +#include + +#define COLOR_DEMO_SIZE wxSize(FromDIP(50), FromDIP(50)) +#define COLOR_BTN_BITMAP_SIZE wxSize(FromDIP(24), FromDIP(24)) +#define COLOR_BTN_SIZE wxSize(FromDIP(30), FromDIP(30)) +#define GRID_GAP FromDIP(2) +#define COLS 9 // fixed column count +#define MAX_VISIBLE_ROWS 7 // max rows before scrollbar appears + +namespace Slic3r { namespace GUI { + +wxColour FilamentPickerDialog::GetSelectedColour() const +{ + if (!m_color_demo) return wxNullColour; + return m_color_demo->GetBackgroundColour(); +} + +void FilamentPickerDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + // Handle DPI change + CreateShapedBitmap(); + SetWindowShape(); + Refresh(); + Layout(); +} + +FilamentPickerDialog::FilamentPickerDialog(wxWindow *parent, const wxString& fila_id, const FilamentColor& fila_color, const std::string& fila_type) + : DPIDialog(parent ? parent : wxGetApp().mainframe, + wxID_ANY, + _L("Select Filament"), + wxDefaultPosition, + wxDefaultSize, + wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_SHAPED) +{ + SetBackgroundColour(wxColour(255, 255, 255)); + + m_color_query = new FilamentColorCodeQuery(); + m_is_data_loaded = LoadFilamentData(fila_id); + m_cur_filament_color = fila_color; + wxString color_name = m_color_query->GetFilaColorName(fila_id, fila_color); + m_cur_color_name = new wxString(color_name); + + wxBoxSizer *container_sizer = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + + // Preview panel (always present) + wxBoxSizer *preview_sizer = CreatePreviewPanel(fila_color, fila_type); + main_sizer->AddSpacer(FromDIP(4)); + main_sizer->Add(preview_sizer, 0, wxEXPAND, 0); + main_sizer->AddSpacer(FromDIP(12)); + + wxBoxSizer *line_sizer = CreateSeparatorLine(); + main_sizer->Add(line_sizer, 0, wxEXPAND, 0); + + // If caller passed an initial colour, reflect it in preview box. + if (m_is_data_loaded) { + // Colour grid with all filaments + wxScrolledWindow* color_grid = CreateColorGrid(); + main_sizer->Add(color_grid, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(8)); + } + + // "More colours" button (always present) + CreateMoreInfoButton(); + main_sizer->Add(m_more_btn, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(8)); + main_sizer->AddSpacer(FromDIP(8)); + + // OK / Cancel buttons + wxBoxSizer* btn_sizer = CreateButtonPanel(); + main_sizer->Add(btn_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(10)); + container_sizer->Add(main_sizer, 1, wxEXPAND | wxALL, FromDIP(16)); + + SetSizer(container_sizer); + Layout(); + container_sizer->Fit(this); + + // Position the dialog relative to the parent window + if (GetParent()) { + // Align the dialog with the sidebar + auto& sidebar = wxGetApp().sidebar(); + wxPoint sidebar_pos = sidebar.GetScreenPosition(); + wxSize sidebar_size = sidebar.GetSize(); + + wxPoint new_pos( + sidebar_pos.x + sidebar_size.GetWidth() + FromDIP(10), + sidebar_pos.y + FromDIP(80) + ); + SetPosition(new_pos); + } else { + Centre(wxBOTH); // If no parent window, center the dialog + } + + // Create shaped window after sizing + CreateShapedBitmap(); +#ifndef __WXGTK__ + // Windows and macOS can set shape immediately + SetWindowShape(); +#endif +#ifdef __WXGTK__ + // GTK platform needs to wait for window creation + Bind(wxEVT_CREATE, &FilamentPickerDialog::OnWindowCreate, this); +#endif + + wxGetApp().UpdateDlgDarkUI(this); + Layout(); + // Set window transparency + SetTransparent(255); + BindEvents(); +} + +FilamentPickerDialog::~FilamentPickerDialog() +{ + delete m_color_query; + m_color_query = nullptr; + + delete m_cur_color_name; + m_cur_color_name = nullptr; +} + +void FilamentPickerDialog::CreateShapedBitmap() +{ + wxSize size = GetSize(); + if (size.GetWidth() <= 0 || size.GetHeight() <= 0) { + return; + } + + // Create a bitmap with alpha channel + m_shape_bmp.Create(size.GetWidth(), size.GetHeight(), 32); + + wxMemoryDC dc; + dc.SelectObject(m_shape_bmp); + + dc.SetBackground(wxBrush(wxColour(0, 0, 0))); + dc.Clear(); + + // Draw main white shape on top, positioned to let shadow show through + dc.SetBrush(wxBrush(wxColour(255, 255, 255, 255))); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRoundedRectangle(0, 0, + size.GetWidth(), + size.GetHeight(), + FromDIP(m_corner_radius)); + + dc.SelectObject(wxNullBitmap); +} + +void FilamentPickerDialog::SetWindowShape() +{ + if (!m_shape_bmp.IsOk()) { + return; + } + + // Create a region from the bitmap using magenta as transparent mask color + wxRegion region(m_shape_bmp, wxColour(0, 0, 0)); + + if (region.IsOk()) { + SetShape(region); + } +} + +bool FilamentPickerDialog::LoadFilamentData(const wxString& fila_id) +{ + m_cur_color_codes = m_color_query->GetFilaInfoMap(fila_id); + + if (!m_cur_color_codes) { + BOOST_LOG_TRIVIAL(warning) << "No color codes found for filament ID: " << fila_id.ToStdString(); + return false; + } + + FilamentColor2CodeMap* color_map = m_cur_color_codes->GetFilamentColor2CodeMap(); + if (!color_map) { + BOOST_LOG_TRIVIAL(warning) << "No color map found for filament ID: " << fila_id.ToStdString(); + return false; + } + + BOOST_LOG_TRIVIAL(info) << "Successfully loaded " << color_map->size() << " color variants for filament " << fila_id.ToStdString(); + return !color_map->empty(); +} + +wxBoxSizer* FilamentPickerDialog::CreatePreviewPanel(const FilamentColor& fila_color, const std::string& fila_type) +{ + wxBoxSizer *preview_sizer = new wxBoxSizer(wxHORIZONTAL); + + // Create color preview bitmap + CreateColorBitmap(fila_color); + preview_sizer->Add(m_color_demo, 0, wxALIGN_CENTER_VERTICAL, 0); + preview_sizer->AddSpacer(FromDIP(12)); + + // Create info labels section + wxBoxSizer *label_sizer = CreateInfoSection(); + SetupLabelsContent(fila_color, fila_type); + preview_sizer->Add(label_sizer, 1, wxALIGN_CENTER_VERTICAL, 0); + + return preview_sizer; +} + +void FilamentPickerDialog::CreateColorBitmap(const FilamentColor &fila_color) +{ + m_color_demo = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, COLOR_DEMO_SIZE, 0); + + // Generate bitmap content + if (fila_color.ColorCount() > 0) { + std::vector wx_colors(fila_color.m_colors.begin(), fila_color.m_colors.end()); + wxBitmap init_bmp = create_filament_bitmap(wx_colors, COLOR_DEMO_SIZE, + fila_color.m_color_type == FilamentColor::ColorType::GRADIENT_CLR); + m_color_demo->SetBitmap(init_bmp); + } + else{ + std::vector wx_colors; + wx_colors.push_back(wxNullColour); + wxBitmap init_bmp = create_filament_bitmap(wx_colors, COLOR_DEMO_SIZE, false); + m_color_demo->SetBitmap(init_bmp); + } +} + +wxBoxSizer* FilamentPickerDialog::CreateInfoSection() +{ + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + + // Create the container box + wxStaticBox *info_box = new wxStaticBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition); + info_box->SetSize(wxSize(FromDIP(240), FromDIP(24))); + info_box->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE)); + wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer(info_box, wxHORIZONTAL); + + // Create labels with ellipsize style for text overflow + m_label_preview_color = new wxStaticText(this, wxID_ANY, _L("Custom Color"), + wxDefaultPosition, wxDefaultSize, + wxST_ELLIPSIZE_END); + m_label_preview_idx = new wxStaticText(this, wxID_ANY, _L(""), + wxDefaultPosition, wxDefaultSize); // No size limit, no ellipsis + m_label_preview_type = new wxStaticText(this, wxID_ANY, _L(""), + wxDefaultPosition, wxSize(FromDIP(220), FromDIP(16)), + wxST_ELLIPSIZE_END); + + // Set maximum width for color label to enable proper ellipsis behavior + m_label_preview_color->SetMaxSize(wxSize(FromDIP(160), -1)); + + // Setup fonts + wxFont bold_font = m_label_preview_color->GetFont(); + bold_font.SetWeight(wxFONTWEIGHT_BOLD); +#ifdef __WXMSW__ + bold_font.SetPointSize(FromDIP(8)); +#endif + m_label_preview_color->SetFont(bold_font); + m_label_preview_idx->SetFont(bold_font); + + m_label_preview_type->SetForegroundColour(wxColour(128, 128, 128)); + + // Layout with platform-specific spacing +#ifdef __WXMSW__ + int spacer = FromDIP(2), vPadding = FromDIP(0), gap1 = FromDIP(-6), gap2 = FromDIP(4); +#else + int spacer = FromDIP(0), vPadding = FromDIP(-1), gap1 = FromDIP(0), gap2 = FromDIP(2); +#endif + + box_sizer->AddSpacer(spacer); + box_sizer->Add(m_label_preview_color, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, vPadding); + box_sizer->AddSpacer(FromDIP(2)); + box_sizer->Add(m_label_preview_idx, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, vPadding); + box_sizer->AddSpacer(spacer); + + main_sizer->Add(box_sizer, 0, wxALIGN_CENTER_VERTICAL | wxTOP, gap1); + main_sizer->AddSpacer(gap2); + main_sizer->Add(m_label_preview_type, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(6)); + + return main_sizer; +} + +void FilamentPickerDialog::SetupLabelsContent(const FilamentColor &fila_color, const std::string &fila_type) +{ + m_label_preview_type->SetLabel(from_u8(fila_type)); + if (m_cur_color_name && !m_cur_color_name->IsEmpty()) { + m_label_preview_color->SetLabel(*m_cur_color_name); + + // Try to get additional color code information + if (m_cur_color_codes) { + FilamentColorCode *color_code = m_cur_color_codes->GetColorCode(fila_color); + if (color_code) { + m_label_preview_idx->SetLabel(wxString::Format("(%s)", color_code->GetFilaColorCode())); + } + } + } + else{ + if (fila_color.ColorCount() == 0){ + m_label_preview_color->SetLabel(_L("Null Color")); + } + else if (fila_color.ColorCount() == 1) { + m_label_preview_color->SetLabel(fila_color.m_colors.begin()->GetAsString(wxC2S_HTML_SYNTAX)); + } + else{ + m_label_preview_color->SetLabel(_L("Multiple Color")); + } + } +} + +wxBoxSizer* FilamentPickerDialog::CreateSeparatorLine() +{ + wxBoxSizer *line_sizer = new wxBoxSizer(wxHORIZONTAL); + wxPanel* separator_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(1))); + separator_line->SetBackgroundColour(wxColour(238,238,238)); + wxStaticText* line_text = new wxStaticText(this, wxID_ANY, _L("Official Filament"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL); + line_text->SetForegroundColour(wxColour(128, 128, 128)); + line_sizer->Add(line_text, 0, wxEXPAND, 0); + line_sizer->AddSpacer(FromDIP(8)); + line_sizer->Add(separator_line, 1, wxALIGN_CENTER_VERTICAL, 0); + return line_sizer; +} + +wxScrolledWindow* FilamentPickerDialog::CreateColorGrid() +{ + if (!m_cur_color_codes) return nullptr; + + FilamentColor2CodeMap* color_map = m_cur_color_codes->GetFilamentColor2CodeMap(); + if (!color_map) return nullptr; + + // Calculate required row count + int total_colors = color_map->size(); + int needed_rows = (total_colors + COLS - 1) / COLS; // round-up division + bool need_scroll = needed_rows > MAX_VISIBLE_ROWS; + + // Create a vertical-only scrolled window + wxScrolledWindow* scroll_win = new wxScrolledWindow( + this, + wxID_ANY, + wxDefaultPosition, + wxDefaultSize, + wxVSCROLL | wxNO_BORDER + ); + + wxGridSizer* grid_sizer = new wxGridSizer(needed_rows, COLS, GRID_GAP, GRID_GAP); + + if (!color_map->empty()) { + for (const auto& color_pair : *color_map) { + const FilamentColor& fila_color = color_pair.first; // color info + FilamentColorCode* color_code = color_pair.second; // color code + + if (!color_code) continue; + std::vector wx_colors(fila_color.m_colors.begin(), fila_color.m_colors.end()); + wxBitmap btn_bmp = create_filament_bitmap( + wx_colors, + COLOR_BTN_BITMAP_SIZE, + fila_color.m_color_type == FilamentColor::ColorType::GRADIENT_CLR + ); + + if (!btn_bmp.IsOk()) { + BOOST_LOG_TRIVIAL(error) << "Failed to create bitmap for filament " << color_code->GetFilaColorCode().ToStdString(); + continue; + } + + wxBitmapButton* btn = new wxBitmapButton( + scroll_win, + wxID_ANY, + btn_bmp, + wxDefaultPosition, + COLOR_BTN_SIZE, + wxBU_EXACTFIT | wxNO_BORDER + ); + + if (btn) { + // Remove any default background and borders + btn->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE)); + + // Set tooltip with filament information + wxString tooltip = wxString::Format("%s", color_code->GetFilaColorName()); + btn->SetToolTip(tooltip); + + // Check if this color matches the current color name and set as selected + bool is_matching_color = (m_cur_color_name && + !m_cur_color_name->IsEmpty() && + *m_cur_color_name == color_code->GetFilaColorName()); + + if (is_matching_color) { + m_cur_filament_color = color_code->GetFilaColor(); + m_cur_selected_btn = btn; + UpdatePreview(*color_code); + btn->Bind(wxEVT_PAINT, &FilamentPickerDialog::OnButtonPaint, this); + } + + // Bind click + btn->Bind(wxEVT_LEFT_DOWN, [this, btn, color_code](wxMouseEvent& evt) { + m_cur_filament_color = color_code->GetFilaColor(); + UpdatePreview(*color_code); + UpdateButtonStates(btn); + evt.Skip(); + }); + + // Hover highlight + btn->Bind(wxEVT_ENTER_WINDOW, [btn](wxMouseEvent& evt) { + evt.Skip(); + }); + + btn->Bind(wxEVT_LEAVE_WINDOW, [btn](wxMouseEvent& evt) { + evt.Skip(); + }); + + grid_sizer->Add(btn, 0, wxALL | wxALIGN_CENTER, FromDIP(1)); + } + } + } + + scroll_win->SetSizer(grid_sizer); + + if (need_scroll) { + int row_height = COLOR_BTN_SIZE.GetHeight() + FromDIP(2); + int col_width = COLOR_BTN_SIZE.GetWidth() + FromDIP(4); + + // Reserve space for vertical scrollbar so it doesn't overlay content + int scrollbar_width = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); + + // Set minimum visible area (including scrollbar width) + scroll_win->SetMinSize(wxSize(col_width * COLS + scrollbar_width, row_height * MAX_VISIBLE_ROWS)); + + // Let wxScrolledWindow calculate appropriate virtual size + scroll_win->FitInside(); + scroll_win->SetScrollRate(0, row_height); + } else { + scroll_win->FitInside(); + scroll_win->SetScrollRate(0, 0); + } + + return scroll_win; +} + +void FilamentPickerDialog::UpdatePreview(const FilamentColorCode& color_code) +{ + FilamentColor fila_color = color_code.GetFilaColor(); + + std::vector wx_colors(fila_color.m_colors.begin(), fila_color.m_colors.end()); + + // Update preview bitmap + wxBitmap bmp = create_filament_bitmap(wx_colors, COLOR_DEMO_SIZE, + fila_color.m_color_type == FilamentColor::ColorType::GRADIENT_CLR); + + if (bmp.IsOk()) { + BOOST_LOG_TRIVIAL(debug) << "Bitmap created successfully: " << bmp.GetWidth() << "x" << bmp.GetHeight(); + m_color_demo->SetBitmap(bmp); + if (!wx_colors.empty()) { + m_color_demo->SetBackgroundColour(wx_colors[0]); + } + m_color_demo->Refresh(); + } else { + BOOST_LOG_TRIVIAL(error) << "Failed to create bitmap"; + } + + // Update preview labels + m_label_preview_color->SetLabel(color_code.GetFilaColorName()); + m_label_preview_idx->SetLabel(wxString::Format("(%s)", color_code.GetFilaColorCode())); + Layout(); +} + +void FilamentPickerDialog::UpdateCustomColorPreview(const wxColour& custom_color) +{ + std::vector wx_colors = {custom_color}; + + // Update preview bitmap + wxBitmap bmp = create_filament_bitmap(wx_colors, COLOR_DEMO_SIZE, false); + + if (bmp.IsOk()) { + BOOST_LOG_TRIVIAL(debug) << "Custom color bitmap created successfully: " << bmp.GetWidth() << "x" << bmp.GetHeight(); + m_color_demo->SetBitmap(bmp); + m_color_demo->SetBackgroundColour(custom_color); + m_color_demo->Refresh(); + } else { + BOOST_LOG_TRIVIAL(error) << "Failed to create custom color bitmap"; + } + + // Update preview labels for custom color + m_label_preview_color->SetLabel(custom_color.GetAsString(wxC2S_HTML_SYNTAX)); + m_label_preview_idx->SetLabel(_L("")); + Layout(); +} + +void FilamentPickerDialog::UpdateButtonStates(wxBitmapButton* selected_btn) +{ + // Reset selected button appearance + if (m_cur_selected_btn) { + m_cur_selected_btn->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE)); + m_cur_selected_btn->Unbind(wxEVT_PAINT, &FilamentPickerDialog::OnButtonPaint, this); + m_cur_selected_btn->Refresh(); + } + + if (selected_btn) { + // Bind paint event to draw custom green border + selected_btn->Bind(wxEVT_PAINT, &FilamentPickerDialog::OnButtonPaint, this); + selected_btn->Refresh(); + } + + m_cur_selected_btn = selected_btn; +} + +void FilamentPickerDialog::CreateMoreInfoButton() +{ + m_more_btn = new Button(this, "+ " + _L("More Colors")); + m_more_btn->SetMinSize(wxSize(-1, FromDIP(36))); + + StateColor btn_bg( + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(wxColour(248, 248, 248), StateColor::Normal) + ); + + + m_more_btn->SetBackgroundColor(btn_bg); + m_more_btn->SetBorderStyle(wxPENSTYLE_SHORT_DASH); + m_more_btn->SetCornerRadius(FromDIP(0)); +} + +wxBoxSizer* FilamentPickerDialog::CreateButtonPanel() +{ + wxBoxSizer* btn_sizer = new wxBoxSizer(wxHORIZONTAL); + + // Add spacer to push buttons to the right + btn_sizer->AddStretchSpacer(); + + // standard button color style + //y + StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), + std::pair(wxColour(68, 121, 251), StateColor::Normal)); + + StateColor btn_bd_green( + std::pair(wxColour(0, 174, 66), StateColor::Normal) + ); + StateColor btn_text_blue( + std::pair(wxColour(255, 255, 254), StateColor::Normal) + ); + + StateColor btn_bg_white( + std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(wxColour(255, 255, 255), StateColor::Normal) + ); + StateColor btn_bd_white( + std::pair(wxColour(38, 46, 48), StateColor::Normal) + ); + StateColor btn_text_white( + std::pair(wxColour(38, 46, 48), StateColor::Normal) + ); + + // Create Cancel button using project's Button class + m_cancel_btn = new Button(this, _L("Cancel"), "", 0, 0, wxID_CANCEL); + m_cancel_btn->SetMinSize(wxSize(FromDIP(55), FromDIP(24))); + m_cancel_btn->SetCornerRadius(FromDIP(12)); + m_cancel_btn->SetBackgroundColor(btn_bg_white); + m_cancel_btn->SetBorderColor(btn_bd_white); + m_cancel_btn->SetTextColor(btn_text_white); + btn_sizer->Add(m_cancel_btn, 0, wxEXPAND, 0); + btn_sizer->AddSpacer(FromDIP(10)); + + // Create OK button using project's Button class + m_ok_btn = new Button(this, _L("OK"), "", 0, 0, wxID_OK); + m_ok_btn->SetMinSize(wxSize(FromDIP(55), FromDIP(24))); + m_ok_btn->SetCornerRadius(FromDIP(12)); + m_ok_btn->SetBackgroundColor(btn_bg_blue); + m_ok_btn->SetBorderColor(btn_bd_green); + m_ok_btn->SetTextColor(btn_text_blue); + m_ok_btn->SetFocus(); + btn_sizer->Add(m_ok_btn, 0, wxEXPAND, 0); + + return btn_sizer; +} + +wxColourData FilamentPickerDialog::GetSingleColorData() +{ + wxColourData data; + data.SetChooseFull(true); + if (m_cur_filament_color.ColorCount() > 0) { + data.SetColour(*m_cur_filament_color.m_colors.begin()); + } + return data; +} + +void FilamentPickerDialog::BindEvents() +{ + // Bind mouse events + Bind(wxEVT_LEFT_DOWN, &FilamentPickerDialog::OnMouseLeftDown, this); + Bind(wxEVT_MOTION, &FilamentPickerDialog::OnMouseMove, this); + Bind(wxEVT_LEFT_UP, &FilamentPickerDialog::OnMouseLeftUp, this); + + // Add safety event handlers to ensure mouse capture is released + Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& event) { + if (HasCapture()) { + ReleaseMouse(); + } + event.Skip(); + }); + + Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) { + if (HasCapture()) { + ReleaseMouse(); + } + event.Skip(); + }); + + // Bind more colors button event + if (m_more_btn) { + m_more_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + wxColourData original_data = GetSingleColorData(); + wxColourData result = show_sys_picker_dialog(this, original_data); + + // Check if user actually selected a different color + if (result.GetColour() != original_data.GetColour()) { + wxColour selected_color = result.GetColour(); + + // Update m_current_filament_color with the selected color + m_cur_filament_color.m_colors.clear(); + m_cur_filament_color.m_colors.insert(selected_color); + m_cur_filament_color.m_color_type = FilamentColor::ColorType::SINGLE_CLR; + + // Update preview + UpdateCustomColorPreview(selected_color); + + // Clear currently selected button since custom color selected + UpdateButtonStates(nullptr); + } + }); + } + + // Bind OK button event + if (m_ok_btn) { + m_ok_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + EndModal(wxID_OK); + }); + } + + // Bind Cancel button event + if (m_cancel_btn) { + m_cancel_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + EndModal(wxID_CANCEL); + }); + } +} + +#ifdef __WXGTK__ +void FilamentPickerDialog::OnWindowCreate(wxWindowCreateEvent& event) +{ + // GTK platform needs to wait for window creation + SetWindowShape(); +} +#endif + +void FilamentPickerDialog::OnMouseLeftDown(wxMouseEvent& event) +{ + // Only allow dragging from empty areas (not from buttons or other controls) + wxWindow* hit_window = wxFindWindowAtPoint(ClientToScreen(event.GetPosition())); + if (hit_window && hit_window != this) { + // Click was on a child control, don't drag + event.Skip(); + return; + } + + // Release any existing capture first + if (HasCapture()) { + ReleaseMouse(); + } + + CaptureMouse(); + wxPoint pt = ClientToScreen(event.GetPosition()); + wxPoint origin = GetPosition(); + int dx = pt.x - origin.x; + int dy = pt.y - origin.y; + m_drag_delta = wxPoint(dx, dy); + + // Don't skip the event for dragging to work properly +} + +void FilamentPickerDialog::OnMouseMove(wxMouseEvent& event) +{ + wxPoint pt = event.GetPosition(); + + if (event.Dragging() && event.LeftIsDown() && HasCapture()) { + wxPoint pos = ClientToScreen(pt); + Move(wxPoint(pos.x - m_drag_delta.x, pos.y - m_drag_delta.y)); + } + + event.Skip(); +} + +void FilamentPickerDialog::OnMouseLeftUp(wxMouseEvent& event) +{ + if (HasCapture()) { + ReleaseMouse(); + } + + event.Skip(); +} + +void FilamentPickerDialog::OnButtonPaint(wxPaintEvent& event) +{ + wxWindow* button = dynamic_cast(event.GetEventObject()); + if (!button) { + event.Skip(); + return; + } + + // Create paint DC and let default painting happen first + wxPaintDC dc(button); + + //Clear the button with white background + dc.SetBrush(wxBrush(*wxTRANSPARENT_BRUSH)); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(0, 0, COLOR_BTN_SIZE.GetWidth(), COLOR_BTN_SIZE.GetHeight()); + + // Draw the bitmap in the center + wxBitmapButton* bmpBtn = dynamic_cast(button); + if (bmpBtn && bmpBtn->GetBitmap().IsOk()) { + wxBitmap bmp = bmpBtn->GetBitmap(); + int x = (COLOR_BTN_SIZE.GetWidth() - COLOR_BTN_BITMAP_SIZE.GetWidth()) / 2; + int y = (COLOR_BTN_SIZE.GetHeight() - COLOR_BTN_BITMAP_SIZE.GetHeight()) / 2; + dc.DrawBitmap(bmp, x, y, true); + } + + // Draw the green border + dc.SetPen(wxPen(wxColour("#00AE42"), 2)); // Green pen, 2px thick + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(1, 1, COLOR_BTN_SIZE.GetWidth() - 1, COLOR_BTN_SIZE.GetHeight() - 1); +} + +}} // namespace Slic3r::GUI + diff --git a/src/slic3r/GUI/FilamentPickerDialog.hpp b/src/slic3r/GUI/FilamentPickerDialog.hpp new file mode 100644 index 0000000..89c934e --- /dev/null +++ b/src/slic3r/GUI/FilamentPickerDialog.hpp @@ -0,0 +1,97 @@ +#ifndef slic3r_GUI_FilamentPickerDialog_hpp_ +#define slic3r_GUI_FilamentPickerDialog_hpp_ + +#include "GUI_App.hpp" +#include "GUI.hpp" +#include "GUI_Utils.hpp" +#include "FilamentBitmapUtils.hpp" +#include "Widgets/Button.hpp" +#include "EncodedFilament.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace Slic3r { namespace GUI { + +class FilamentPickerDialog : public DPIDialog +{ +public: + FilamentPickerDialog(wxWindow *parent, const wxString &fila_id, const FilamentColor &fila_color, const std::string &fila_type); + virtual ~FilamentPickerDialog(); + + // Public interface methods + bool IsDataLoaded() const { return m_is_data_loaded; } + wxColour GetSelectedColour() const; + const FilamentColor& GetSelectedFilamentColor() const { return m_cur_filament_color; } + +protected: + void on_dpi_changed(const wxRect &suggested_rect) override; + + // Event handlers +#ifdef __WXGTK__ + void OnWindowCreate(wxWindowCreateEvent& event); +#endif + void OnMouseLeftDown(wxMouseEvent& event); + void OnMouseMove(wxMouseEvent& event); + void OnMouseLeftUp(wxMouseEvent& event); + void OnButtonPaint(wxPaintEvent& event); + +private: + // UI creation methods + wxBoxSizer* CreatePreviewPanel(const FilamentColor& fila_color, const std::string& fila_type); + wxScrolledWindow* CreateColorGrid(); + wxBoxSizer* CreateSeparatorLine(); + void CreateMoreInfoButton(); + wxBoxSizer* CreateButtonPanel(); + void BindEvents(); + + // Preview panel helper methods + void CreateColorBitmap(const FilamentColor& fila_color); + wxBoxSizer* CreateInfoSection(); + void SetupLabelsContent(const FilamentColor& fila_color, const std::string& fila_type); + + // UI update methods + void UpdatePreview(const FilamentColorCode& filament); + void UpdateCustomColorPreview(const wxColour& custom_color); + void UpdateButtonStates(wxBitmapButton* selected_btn); + + // Shaped window methods + void SetWindowShape(); + void CreateShapedBitmap(); + + // Data loading + bool LoadFilamentData(const wxString& fila_id); + wxColourData GetSingleColorData(); + + // UI elements + wxStaticBitmap* m_color_demo{nullptr}; + wxStaticText* m_label_preview_color{nullptr}; + wxStaticText* m_label_preview_idx{nullptr}; + wxStaticText* m_label_preview_type{nullptr}; + Button* m_more_btn{nullptr}; + Button* m_ok_btn{nullptr}; + Button* m_cancel_btn{nullptr}; + + // Data members + bool m_is_data_loaded{false}; + wxString *m_cur_color_name{nullptr}; + FilamentColorCodeQuery* m_color_query{nullptr}; + FilamentColorCodes* m_cur_color_codes{nullptr}; + wxBitmapButton* m_cur_selected_btn{nullptr}; + FilamentColor m_cur_filament_color; + + // Shaped window members + wxBitmap m_shape_bmp; + int m_corner_radius{8}; + + // Mouse drag members + wxPoint m_drag_delta; +}; + +}} // namespace Slic3r::GUI + +#endif diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 13aa19a..234634f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -547,11 +547,11 @@ void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& fil try { m_file.open(boost::filesystem::path(m_filename)); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": mapping file " << m_filename; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": mapping file " << PathSanitizer::sanitize(m_filename); } catch (...) { - BOOST_LOG_TRIVIAL(error) << "Unable to map file " << m_filename << ". Cannot show G-code window."; + BOOST_LOG_TRIVIAL(error) << "Unable to map file " << PathSanitizer::sanitize(m_filename) << ". Cannot show G-code window."; reset(); } } @@ -632,7 +632,7 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f } catch (...) { - BOOST_LOG_TRIVIAL(error) << "Error while loading from file " << m_filename << ". Cannot show G-code window."; + BOOST_LOG_TRIVIAL(error) << "Error while loading from file " << PathSanitizer::sanitize(m_filename) << ". Cannot show G-code window."; return; } *const_cast(&m_selected_line_id) = curr_line_id; @@ -721,7 +721,7 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file() //QDS: add log to trace the gcode file issue if (m_file.is_open()) { m_file.close(); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << m_filename; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << PathSanitizer::sanitize(m_filename); } } //QDS: GUI refactor: move to the right @@ -1007,7 +1007,9 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr } //QDS: add logs - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": gcode result %1%, new id %2%, gcode file %3% ") % (&gcode_result) % m_last_result_id % gcode_result.filename; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ + << boost::format(": gcode result %1%, new id %2%, gcode file %3% ") % (&gcode_result) % m_last_result_id % + PathSanitizer::sanitize(gcode_result.filename); // release gpu memory, if used reset(); @@ -1960,7 +1962,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const FILE* fp = boost::nowide::fopen(mat_filename.string().c_str(), "w"); if (fp == nullptr) { - BOOST_LOG_TRIVIAL(error) << "GCodeViewer::export_toolpaths_to_obj: Couldn't open " << mat_filename.string().c_str() << " for writing"; + BOOST_LOG_TRIVIAL(error) << "GCodeViewer::export_toolpaths_to_obj: Couldn't open " << PathSanitizer::sanitize(mat_filename) << " for writing"; return; } @@ -1980,7 +1982,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // save geometry file fp = boost::nowide::fopen(filename, "w"); if (fp == nullptr) { - BOOST_LOG_TRIVIAL(error) << "GCodeViewer::export_toolpaths_to_obj: Couldn't open " << filename << " for writing"; + BOOST_LOG_TRIVIAL(error) << "GCodeViewer::export_toolpaths_to_obj: Couldn't open " << PathSanitizer::sanitize(filename) << " for writing"; return; } @@ -4268,7 +4270,8 @@ void GCodeViewer::render_all_plates_stats(const std::vectorget("use_inches") == "1"; float window_padding = 4.0f * m_scale; const float icon_size = ImGui::GetTextLineHeight() * 0.7; - std::map offsets; + std::map fil_table_offsets; + std::map time_est_table_offsets; std::map model_volume_of_extruders_all_plates; // map std::map flushed_volume_of_extruders_all_plates; // map std::map wipe_tower_volume_of_extruders_all_plates; // map @@ -4465,7 +4468,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector> title_offsets; for (int i = 0; i < offsets_.size(); i++) { title_offsets.push_back({ title_columns[i].first, offsets_[i] }); - offsets[title_columns[i].first] = offsets_[i]; + fil_table_offsets[title_columns[i].first] = offsets_[i]; } append_headers(title_offsets); } @@ -4476,7 +4479,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector> columns_offsets; - columns_offsets.push_back({ std::to_string(it->first + 1), offsets[_u8L("Filament")]}); + columns_offsets.push_back({ std::to_string(it->first + 1), fil_table_offsets[_u8L("Filament")] }); char buf[64]; @@ -4487,31 +4490,31 @@ void GCodeViewer::render_all_plates_stats(const std::vector 0) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", column_sum_m, column_sum_g / unit_conver); - columns_offsets.push_back({ buf, offsets[_u8L("Total")] }); + columns_offsets.push_back({ buf, fil_table_offsets[_u8L("Total")] }); } append_item(true, filament_colors[it->first], columns_offsets); @@ -4531,7 +4534,7 @@ void GCodeViewer::render_all_plates_stats(const std::vectorDrawList->AddLine(separator.Min, ImVec2(separator.Max.x, separator.Min.y), ImGui::GetColorU32(ImGuiCol_Separator)); std::vector> columns_offsets; - columns_offsets.push_back({_u8L("Total"), offsets[_u8L("Filament")]}); + columns_offsets.push_back({ _u8L("Total"), fil_table_offsets[_u8L("Filament")] }); double total_model_used_filament_m = 0; double total_model_used_filament_g = 0; double total_support_used_filament_m = 0; @@ -4551,7 +4554,7 @@ void GCodeViewer::render_all_plates_stats(const std::vector 0) { ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_support_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m, (total_model_used_filament_g + total_support_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g) / unit_conver); - columns_offsets.push_back({buf, offsets[_u8L("Total")]}); + columns_offsets.push_back({ buf, fil_table_offsets[_u8L("Total")] }); } append_item(false, m_tools.m_tool_colors[0], columns_offsets); } @@ -4599,6 +4602,28 @@ void GCodeViewer::render_all_plates_stats(const std::vector time_labels; + std::vector time_values; + std::vector>> time_columns; + + for (auto it = plate_time.begin(); it != plate_time.end(); it++) { + time_labels.push_back(_u8L("Plate") + " " + std::to_string(it->first + 1)); + time_values.push_back(short_time(get_time_dhms(it->second))); + } + if (plate_time.size() > 1) { + time_labels.push_back(_u8L("Total")); + time_values.push_back(short_time(get_time_dhms(total_time_all_plates))); + } + + time_columns.push_back({_u8L("Plate"), time_labels}); + time_columns.push_back({_u8L("Time"), time_values}); + + auto time_offsets = calculate_offsets(time_columns); + for (int i = 0; i < time_offsets.size(); i++) { time_est_table_offsets[time_columns[i].first] = time_offsets[i]; } + } + ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1)); ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); @@ -4606,8 +4631,8 @@ void GCodeViewer::render_all_plates_stats(const std::vector> columns_offsets; - columns_offsets.push_back({ _u8L("Plate") + " " + std::to_string(it->first + 1), offsets[_u8L("Filament")]}); - columns_offsets.push_back({ short_time(get_time_dhms(it->second)), offsets[_u8L("Model")] }); + columns_offsets.push_back({_u8L("Plate") + " " + std::to_string(it->first + 1), time_est_table_offsets[_u8L("Plate")]}); + columns_offsets.push_back({short_time(get_time_dhms(it->second)), time_est_table_offsets[_u8L("Time")]}); append_item(false, m_tools.m_tool_colors[0], columns_offsets); } @@ -4620,8 +4645,8 @@ void GCodeViewer::render_all_plates_stats(const std::vectorDrawList->AddLine(separator.Min, ImVec2(separator.Max.x, separator.Min.y), ImGui::GetColorU32(ImGuiCol_Separator)); std::vector> columns_offsets; - columns_offsets.push_back({ _u8L("Total"), offsets[_u8L("Filament")] }); - columns_offsets.push_back({ short_time(get_time_dhms(total_time_all_plates)), offsets[_u8L("Model")] }); + columns_offsets.push_back({_u8L("Total"), time_est_table_offsets[_u8L("Plate")]}); + columns_offsets.push_back({short_time(get_time_dhms(total_time_all_plates)), time_est_table_offsets[_u8L("Time")]}); append_item(false, m_tools.m_tool_colors[0], columns_offsets); } } @@ -6197,9 +6222,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv imgui.text(prepare_str + ":"); ImGui::SameLine(max_len); if (timelapse_time != 0.0f) - imgui.text(short_time(get_time_dhms(time_mode.prepare_time)) + " + " + short_time(get_time_dhms(timelapse_time))); + //y68 + imgui.text(short_time(get_time_dhms(time_mode.prepare_time + 600.0f)) + " + " + short_time(get_time_dhms(timelapse_time))); else - imgui.text(short_time(get_time_dhms(time_mode.prepare_time))); + imgui.text(short_time(get_time_dhms(time_mode.prepare_time + 600.0f))); } ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); @@ -6210,7 +6236,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::SameLine(); imgui.text(total_str + ":"); ImGui::SameLine(max_len); - imgui.text(short_time(get_time_dhms(time_mode.time))); + imgui.text(short_time(get_time_dhms(time_mode.time + 600.0f))); //y68 auto show_mode_button = [this, &imgui, can_show_mode_button](const wxString& label, PrintEstimatedStatistics::ETimeMode mode) { if (can_show_mode_button(mode)) { diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e6256dd..0277968 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -29,6 +29,7 @@ #include "slic3r/GUI/BitmapCache.hpp" #include "slic3r/Utils/MacDarkMode.hpp" +#include "GLToolbar.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" #include "GUI_Colors.hpp" @@ -157,6 +158,11 @@ std::string& get_right_extruder_unprintable_text() { return right_unprintable_text; } +std::string& get_nozzle_filament_incompatible_text() { + static std::string nozzle_filament_incompatible_text; + return nozzle_filament_incompatible_text; +} + static std::string format_number(float value) { std::ostringstream oss; @@ -284,7 +290,13 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv ImGuiWrapper& imgui = *wxGetApp().imgui(); const Size& cnv_size = canvas.get_canvas_size(); float zoom = (float) canvas.get_active_camera().get_zoom(); - float left_pos = canvas.m_main_toolbar.get_item("layersediting")->render_left_pos; + const auto& p_main_toolbar = canvas.get_main_toolbar(); + float left_pos = 0.0f; + float main_toolbar_height = 0.0f; + if (p_main_toolbar) { + left_pos = p_main_toolbar->get_item("layersediting")->render_rect[0]; + main_toolbar_height = p_main_toolbar->get_height(); + } float x = 0.5 * cnv_size.get_width() + left_pos * zoom; const auto canvas_width = cnv_size.get_width(); @@ -298,7 +310,7 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv } x = std::max(x, 0.0f); - imgui.set_next_window_pos(x, canvas.m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f); + imgui.set_next_window_pos(x, main_toolbar_height, ImGuiCond_Always, 0.0f, 0.0f); imgui.push_toolbar_style(canvas.get_scale()); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f * canvas.get_scale(), 4.0f * canvas.get_scale())); @@ -380,7 +392,10 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv ImGui::Separator(); - float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + canvas.m_main_toolbar.get_height(); + float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight(); + if (p_main_toolbar) { + get_cur_y += p_main_toolbar->get_height(); + } std::map captions_texts = { {_L("Left mouse button:") ,_L("Add detail")}, {_L("Right mouse button:"), _L("Remove detail")}, @@ -1310,9 +1325,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed) , m_retina_helper(nullptr) #endif , m_in_render(false) - , m_main_toolbar(GLToolbar::Normal, "Main") - , m_separator_toolbar(GLToolbar::Normal, "Separator") - , m_assemble_view_toolbar(GLToolbar::Normal, "Assembly_View") , m_return_toolbar() , m_canvas_type(ECanvasType::CanvasView3D) , m_gizmos(*this) @@ -1433,7 +1445,7 @@ bool GLCanvas3D::init() glsafe(::glEnable(GL_MULTISAMPLE)); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": before m_layers_editing init"; - if (m_main_toolbar.is_enabled()) + if (m_canvas_type == ECanvasType::CanvasView3D) m_layers_editing.init(); // on linux the gl context is not valid until the canvas is not shown on screen @@ -1495,23 +1507,15 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) { if (reinit) { // reset svg _switch_toolbars_icon_filename(); - m_gizmos.switch_gizmos_icon_filename(); - // set dirty to re-generate icon texture - m_separator_toolbar.set_icon_dirty(); - m_main_toolbar.set_icon_dirty(); + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + p_main_toolbar->set_icon_dirty(); + } wxGetApp().plater()->get_collapse_toolbar().set_icon_dirty(); - m_assemble_view_toolbar.set_icon_dirty(); - m_gizmos.set_icon_dirty(); } } if (m_canvas_type == CanvasAssembleView) { m_gizmos.on_change_color_mode(is_dark); - if (reinit) { - // reset svg - m_gizmos.switch_gizmos_icon_filename(); - // set dirty to re-generate icon texture - m_gizmos.set_icon_dirty(); - } } } @@ -1800,10 +1804,8 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject vol->force_native_color = false; vol->force_neutral_color = false; } else { - const GLGizmosManager& gm = get_gizmos_manager(); - auto gizmo_type = gm.get_current_type(); - if ( (gizmo_type == GLGizmosManager::FdmSupports - || gizmo_type == GLGizmosManager::Seam) + auto gizmo_type = m_gizmos.get_current_type(); + if (m_gizmos.is_paint_gizmo() && ! vol->is_modifier) vol->force_neutral_color = true; else if (gizmo_type == GLGizmosManager::BrimEars) @@ -1869,6 +1871,16 @@ void GLCanvas3D::set_model(Model* model) m_selection.set_model(m_model); } +const Selection& GLCanvas3D::get_selection() const +{ + return m_selection; +} + +Selection& GLCanvas3D::get_selection() +{ + return m_selection; +} + void GLCanvas3D::bed_shape_changed() { refresh_camera_scene_box(); @@ -1922,6 +1934,9 @@ BoundingBoxf3 GLCanvas3D::volumes_bounding_box(bool limit_to_expand_plate) const const auto v_bb = volume->transformed_bounding_box(); if (is_limit && !expand_part_plate_list_box.overlap(v_bb)) continue; + if (v_bb.max_size() > 100000) {//unit::mm more than 100m + continue; + } bb.merge(v_bb); } } @@ -2037,7 +2052,11 @@ void GLCanvas3D::enable_selection(bool enable) void GLCanvas3D::enable_main_toolbar(bool enable) { - m_main_toolbar.set_enabled(enable); + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return; + } + p_main_toolbar->set_enabled(enable); } void GLCanvas3D::reset_select_plate_toolbar_selection() { @@ -2052,26 +2071,11 @@ void GLCanvas3D::enable_select_plate_toolbar(bool enable) m_sel_plate_toolbar.set_enabled(enable); } -void GLCanvas3D::clear_select_plate_toolbar_render_flag() -{ - m_sel_plate_toolbar.is_render_finish = false; -} - -void GLCanvas3D::enable_assemble_view_toolbar(bool enable) -{ - m_assemble_view_toolbar.set_enabled(enable); -} - void GLCanvas3D::enable_return_toolbar(bool enable) { m_return_toolbar.set_enabled(enable); } -void GLCanvas3D::enable_separator_toolbar(bool enable) -{ - m_separator_toolbar.set_enabled(enable); -} - void GLCanvas3D::enable_dynamic_background(bool enable) { m_dynamic_background_enabled = enable; @@ -2155,10 +2159,13 @@ int GLCanvas3D::get_main_toolbar_offset() const { const float cnv_width = get_canvas_size().get_width(); const float collapse_toolbar_width = get_collapse_toolbar_width() * 2; - const float gizmo_width = m_gizmos.get_scaled_total_width(); - const float assemble_width = m_assemble_view_toolbar.get_width(); - const float separator_width = m_separator_toolbar.get_width(); - const float toolbar_total_width = m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width + collapse_toolbar_width; + + float main_toolbar_width = 0.0f; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + main_toolbar_width = p_main_toolbar->get_width(); + } + const float toolbar_total_width = main_toolbar_width + collapse_toolbar_width; if (cnv_width < toolbar_total_width) { return is_collapse_toolbar_on_left() ? collapse_toolbar_width : 0; @@ -2172,6 +2179,33 @@ float GLCanvas3D::get_main_toolbar_left(int cnv_width,float inv_zoom) const { return (-0.5f * cnv_width + get_main_toolbar_offset()) * inv_zoom; } +int GLCanvas3D::get_main_toolbar_height() const +{ + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return 0; + } + return p_main_toolbar->get_height(); +} + +int GLCanvas3D::get_main_toolbar_width() const +{ + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return 0; + } + return p_main_toolbar->get_width(); +} + +float GLCanvas3D::get_main_toolbar_scale() const +{ + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return 1.0f; + } + return p_main_toolbar->get_scale(); +} + bool GLCanvas3D::is_collapse_toolbar_on_left() const { auto state = wxGetApp().plater()->get_sidebar_docking_state(); @@ -2231,7 +2265,7 @@ void GLCanvas3D::render(bool only_init) if (m_canvas_type == ECanvasType::CanvasView3D && m_gizmos.get_current_type() == GLGizmosManager::Undefined) { enable_return_toolbar(false); } - if (!m_main_toolbar.is_enabled()) + if (m_canvas_type == ECanvasType::CanvasPreview) m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle); if (! m_bed.build_volume().valid()) { @@ -2299,6 +2333,13 @@ void GLCanvas3D::render(bool only_init) return; } + if (m_main_toolbar) { + if (m_canvas_type == ECanvasType::CanvasView3D) { + const auto toolbar_style = p_ogl_manager->get_toolbar_rendering_style(); + m_main_toolbar->set_rendering_mode(static_cast(toolbar_style)); + } + } + auto& ogl_manager = *p_ogl_manager; ogl_manager.set_viewport_size(viewport[2], viewport[3]); @@ -2322,6 +2363,9 @@ void GLCanvas3D::render(bool only_init) if (!ogl_manager.are_framebuffers_supported()) { picking_effect = EPickingEffect::StencilOutline; // use stencil outline as framebuffer not supported yet. } + if (!m_gizmos.is_allow_show_volume_highlight_outline()) { + picking_effect = EPickingEffect::Disabled; + } } const bool off_screen_rendering_enabled = ogl_manager.is_fxaa_enabled(); @@ -2351,7 +2395,7 @@ void GLCanvas3D::render(bool only_init) bool only_current = false, only_body = false, show_axes = true, no_partplate = false; bool show_grid = true; GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type(); - if (!m_main_toolbar.is_enabled() || m_gizmos.is_show_only_active_plate()) { + if (m_canvas_type != CanvasView3D || m_gizmos.is_show_only_active_plate()) { //only_body = true; if (m_gizmos.get_object_located_outside_plate()) { no_partplate = true; @@ -2359,8 +2403,13 @@ void GLCanvas3D::render(bool only_init) else { only_current = true; } - } - else if ((gizmo_type == GLGizmosManager::FdmSupports) || (gizmo_type == GLGizmosManager::Seam) || (gizmo_type == GLGizmosManager::MmuSegmentation)) + } else if (m_gizmos.get_current_type() == GLGizmosManager::EType::Text) { + if (m_gizmos.is_only_text_volume()) { + only_current = false; + } else { + only_current = true; + } + } else if (m_gizmos.is_paint_gizmo()) no_partplate = true; else if (gizmo_type == GLGizmosManager::BrimEars && !camera.is_looking_downward()) show_grid = false; @@ -2370,18 +2419,22 @@ void GLCanvas3D::render(bool only_init) bool b_with_stencil_outline = !m_gizmos.is_running() && (EPickingEffect::StencilOutline == picking_effect); if (m_canvas_type == ECanvasType::CanvasView3D) { //QDS: add outline logic - _render_objects(GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); + _render_objects(m_volumes,GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); + if (!m_paint_outline_volumes.empty()) { + _render_objects(m_paint_outline_volumes, GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline,true); + } _render_sla_slices(); _render_selection(); if (!no_partplate) _render_bed(!camera.is_looking_downward(), show_axes); if (!no_partplate) //QDS: add outline logic _render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid); - _render_objects(GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline); + _render_objects(m_volumes, GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline); + _render_objects(m_paint_outline_volumes, GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline, true); } /* preview render */ else if (m_canvas_type == ECanvasType::CanvasPreview && m_render_preview) { - _render_objects(GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); + _render_objects(m_volumes, GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); _render_sla_slices(); _render_selection(); _render_bed(!camera.is_looking_downward(), show_axes); @@ -2395,13 +2448,13 @@ void GLCanvas3D::render(bool only_init) if (m_show_world_axes) { m_axes.render(); } - _render_objects(GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); + _render_objects(m_volumes, GLVolumeCollection::ERenderType::Opaque, b_with_stencil_outline); //_render_bed(!camera.is_looking_downward(), show_axes); _render_plane(); //QDS: add outline logic insteadof selection under assemble view //_render_selection(); // QDS: add outline logic - _render_objects(GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline); + _render_objects(m_volumes, GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline); } if (m_picking_enabled && EPickingEffect::Silhouette == picking_effect) { @@ -2478,12 +2531,12 @@ void GLCanvas3D::render(bool only_init) if (tooltip.empty()) tooltip = m_gizmos.get_tooltip(); - if (tooltip.empty()) - tooltip = m_main_toolbar.get_tooltip(); - - //QDS: GUI refactor: GLToolbar - if (tooltip.empty()) - tooltip = m_assemble_view_toolbar.get_tooltip(); + if (tooltip.empty()) { + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + tooltip = p_main_toolbar->get_tooltip(); + } + } if (tooltip.empty()) tooltip = wxGetApp().plater()->get_collapse_toolbar().get_tooltip(); @@ -2597,11 +2650,6 @@ void GLCanvas3D::remove_curr_plate_all() m_dirty = true; } -void GLCanvas3D::update_plate_thumbnails() -{ - _update_imgui_select_plate_toolbar(); -} - void GLCanvas3D::select_all() { if (!m_gizmos.is_allow_select_all()) { @@ -3209,6 +3257,30 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re /*!print->is_step_done(psWipeTower)*/ true, brim_width, m_initialized); int volume_idx_wipe_tower_old = volume_idxs_wipe_tower_old[plate_id]; if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new; + + //y68 + // update wipe_tower pos + { + bool need_update = false; + if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) { + x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin; + } + else if (x < margin + plate_bbox_x_min_local_coord) { + x = margin + plate_bbox_x_min_local_coord; + } + + if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) { + y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin; + } + else if (y < margin) { + y = margin; + } + } + ConfigOptionFloat wt_x_opt(x); + ConfigOptionFloat wt_y_opt(y); + + dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0); + dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0); } } else { auto tower_bottom = current_print->wipe_tower_data().wipe_tower_mesh_data->bottom; @@ -3281,15 +3353,19 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re //if (printer_technology != ptSLA || !contained_min_one) // _set_warning_notification(EWarning::SlaSupportsOutside, false); - bool tpu_valid = cur_plate->check_tpu_printable_status(wxGetApp().preset_bundle->full_config(), wxGetApp().preset_bundle->get_used_tpu_filaments(cur_plate->get_extruders(true))); + auto full_config_temp = wxGetApp().preset_bundle->full_config(); + bool tpu_valid = cur_plate->check_tpu_printable_status(full_config_temp, wxGetApp().preset_bundle->get_used_tpu_filaments(cur_plate->get_extruders(true))); _set_warning_notification(EWarning::TPUPrintableError, !tpu_valid); - bool filament_printable = cur_plate->check_filament_printable(wxGetApp().preset_bundle->full_config(), filament_printable_error_msg); + bool filament_printable = cur_plate->check_filament_printable(full_config_temp, filament_printable_error_msg); _set_warning_notification(EWarning::FilamentPrintableError, !filament_printable); - bool mix_pla_and_petg = cur_plate->check_mixture_of_pla_and_petg(wxGetApp().preset_bundle->full_config()); + bool mix_pla_and_petg = cur_plate->check_mixture_of_pla_and_petg(full_config_temp); _set_warning_notification(EWarning::MixUsePLAAndPETG, !mix_pla_and_petg); + bool filament_nozzle_compatible = cur_plate->check_compatible_of_nozzle_and_filament(full_config_temp, wxGetApp().preset_bundle->filament_presets, get_nozzle_filament_incompatible_text()); + _set_warning_notification(EWarning::NozzleFilamentIncompatible, !filament_nozzle_compatible); + bool model_fits = contained_min_one && !m_model->objects.empty() && !partlyOut && object_results.filaments.empty() && tpu_valid && filament_printable; post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, model_fits)); ppl.get_curr_plate()->update_slice_ready_status(model_fits); @@ -3307,6 +3383,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re _set_warning_notification(EWarning::PrimeTowerOutside, false); _set_warning_notification(EWarning::MultiExtruderPrintableError,false); _set_warning_notification(EWarning::MultiExtruderHeightOutside,false); + _set_warning_notification(EWarning::NozzleFilamentIncompatible,false); + post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } } @@ -3551,9 +3629,10 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) if (!m_initialized) return; - m_dirty |= m_main_toolbar.update_items_state(); - //QDS: GUI refactor: GLToolbar - m_dirty |= m_assemble_view_toolbar.update_items_state(); + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + m_dirty |= p_main_toolbar->update_items_state(); + } // QDS //m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); m_dirty |= wxGetApp().plater()->sidebar().get_update_3d_state(); @@ -3561,7 +3640,6 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) wxGetApp().plater()->sidebar().cancel_update_3d_state(); } m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state(); - _update_imgui_select_plate_toolbar(); bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(get_active_camera()); m_dirty |= mouse3d_controller_applied; m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this); @@ -3637,6 +3715,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); return; } + case 'z': + case 'Z': + case WXK_CONTROL_Z: { + if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) { + post_event(SimpleEvent(EVT_GLCANVAS_REDO)); + } + return; + } } } // CTRL is pressed @@ -3745,6 +3831,16 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case WXK_CONTROL_E: #endif /* __APPLE__ */ { m_labels.show(!m_labels.is_shown()); m_dirty = true; break; } +#ifdef __APPLE__ + case 'W': + case 'w': +#else /* __APPLE__ */ + case WXK_CONTROL_W: +#endif /* __APPLE__ */ + { + wxGetApp().plater()->reset_window_layout(); + break; + } case '0': { select_view("plate"); zoom_to_bed(); @@ -4044,6 +4140,9 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) evt.ShiftDown() && evt.AltDown() && keyCode == WXK_RETURN) { wxGetApp().plater()->toggle_show_wireframe(); m_dirty = true; + } else if ((evt.ShiftDown() && evt.ControlDown() && keyCode == 'T')) { + wxGetApp().plater()->toggle_text_cs(); + m_dirty = true; } else if ((evt.ShiftDown() && evt.ControlDown() && keyCode == 'L')) { wxGetApp().plater()->toggle_non_manifold_edges(); m_dirty = true; @@ -4425,6 +4524,29 @@ void GLCanvas3D::schedule_extra_frame(int miliseconds) } } +int GLCanvas3D::get_main_toolbar_item_id(const std::string& name) const +{ + if (!m_main_toolbar) { + return -1; + } + return m_main_toolbar->get_item_id(name); +} + +void GLCanvas3D::force_main_toolbar_left_action(int item_id) +{ + if (!m_main_toolbar) { + return; + } + + m_dirty |= m_main_toolbar->update_items_state(); + m_main_toolbar->force_left_action(item_id, *this); +} + +void GLCanvas3D::force_main_toolbar_right_action(int item_id) +{ + m_main_toolbar->force_right_action(item_id, *this); +} + #ifndef NDEBUG // #define SLIC3R_DEBUG_MOUSE_EVENTS #endif @@ -4562,21 +4684,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif /* SLIC3R_DEBUG_MOUSE_EVENTS */ } - if (m_main_toolbar.on_mouse(evt, *this)) { - if (m_main_toolbar.is_any_item_pressed()) - m_gizmos.reset_all_states(); - if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) - mouse_up_cleanup(); - m_mouse.set_start_position_3D_as_invalid(); - return; - } - - //QDS: GUI refactor: GLToolbar - if (m_assemble_view_toolbar.on_mouse(evt, *this)) { - if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) - mouse_up_cleanup(); - m_mouse.set_start_position_3D_as_invalid(); - return; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + if (p_main_toolbar->on_mouse(evt, *this)) { + if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) + mouse_up_cleanup(); + m_mouse.set_start_position_3D_as_invalid(); + return; + } } if (wxGetApp().plater()->get_collapse_toolbar().on_mouse(evt, *this)) { @@ -4623,7 +4738,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) wxMouseEvent evt2 = evt; evt2.SetEventType(wxEVT_MOTION); evt2.SetLeftDown(false); - m_main_toolbar.on_mouse(evt2, *this); + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + p_main_toolbar->on_mouse(evt2, *this); + } } if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) @@ -4733,9 +4851,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_selection.set_volume_selection_mode(evt.AltDown() ? Selection::Volume : Selection::Instance); if (evt.LeftDown() && evt.ShiftDown() && m_picking_enabled && m_layers_editing.state != LayersEditing::Editing) { if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports - && m_gizmos.get_current_type() != GLGizmosManager::FdmSupports - && m_gizmos.get_current_type() != GLGizmosManager::Seam - && m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) { + && !m_gizmos.is_paint_gizmo()) { m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect); m_dirty = true; } @@ -4814,7 +4930,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } } else if (evt.Dragging() && evt.LeftIsDown() && m_mouse.drag.move_volume_idx != -1 && m_layers_editing.state == LayersEditing::Unknown) { - if (m_canvas_type != ECanvasType::CanvasAssembleView) { + if (m_canvas_type != ECanvasType::CanvasAssembleView && m_gizmos.is_allow_drag_volume()) { if (!m_mouse.drag.move_requires_threshold) { m_mouse.dragging = true; Vec3d cur_pos = m_mouse.drag.start_position_3D; @@ -4885,8 +5001,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // if dragging over blank area with left button, rotate if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) { const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.); - if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports || - m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) { + if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.is_paint_gizmo()) { //QDS rotate around target Camera& camera = get_active_camera(); Vec3d rotate_target = Vec3d::Zero(); @@ -4916,13 +5031,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) camera.recover_from_free_camera(); //QDS modify rotation - //if (m_gizmos.get_current_type() == GLGizmosManager::FdmSupports - // || m_gizmos.get_current_type() == GLGizmosManager::Seam - // || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) { - // //camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target); - // //camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, rotate_target); - //} - //else if (evt.ControlDown() || evt.CmdDown()) { if ((m_rotation_center.x() == 0.f) && (m_rotation_center.y() == 0.f) && (m_rotation_center.z() == 0.f)) { auto canvas_w = float(get_canvas_size().get_width()); @@ -5123,6 +5231,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (type == GLGizmosManager::EType::Text) m_gizmos.open_gizmo(GLGizmosManager::EType::Text); // close text wxGetApp().obj_list()->update_selections(); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Edit existed text by double click"); m_gizmos.open_gizmo(GLGizmosManager::EType::Text); return; } @@ -5134,10 +5243,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) }*/ else if(hover_volume->emboss_shape.has_value()){ m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id}); - if (type == GLGizmosManager::EType::Svg) - m_gizmos.open_gizmo(GLGizmosManager::EType::Svg);// close svg wxGetApp().obj_list()->update_selections(); - m_gizmos.open_gizmo(GLGizmosManager::EType::Svg); + if (m_main_toolbar) { + const auto svg_item_name = GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Svg); + if (!m_main_toolbar->is_item_pressed(svg_item_name)) { + force_main_toolbar_left_action(get_main_toolbar_item_id(svg_item_name)); + } + } return; } } @@ -5175,11 +5287,6 @@ void GLCanvas3D::force_set_focus() { void GLCanvas3D::on_set_focus(wxFocusEvent& evt) { m_tooltip_enabled = false; - if (m_canvas_type == ECanvasType::CanvasPreview) { - // update thumbnails and update plate toolbar - wxGetApp().plater()->update_all_plate_thumbnails(); - _update_imgui_select_plate_toolbar(); - } _refresh_if_shown_on_screen(); m_tooltip_enabled = true; } @@ -6080,9 +6187,19 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa #if QDS_TOOLBAR_ON_TOP const float x = left * float(get_active_camera().get_zoom()) + 0.5f * canvas_w; ImGuiWrapper::push_toolbar_style(get_scale()); - imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); + float main_toolbar_height = 0.0f; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + main_toolbar_height = p_main_toolbar->get_height(); + } + imgui->set_next_window_pos(x, main_toolbar_height, ImGuiCond_Always, 0.5f, 0.0f); #else - const float x = canvas_w - m_main_toolbar.get_width(); + float main_toolbar_width = 0.0f; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + main_toolbar_width = p_main_toolbar->get_width(); + } + const float x = canvas_w - main_toolbar_width; const float y = 0.5f * canvas_h - top * float(get_active_camera().get_zoom()); imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f); #endif @@ -6153,7 +6270,7 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa } //QDS: GUI refactor: adjust main toolbar position -bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, float top) +bool GLCanvas3D::_render_arrange_menu(float left, float toolbar_height) { ImGuiWrapper *imgui = wxGetApp().imgui(); @@ -6164,12 +6281,16 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo //now change to left_up as {0,0}, and top is 0, bottom is canvas_h #if QDS_TOOLBAR_ON_TOP float zoom = (float)get_active_camera().get_zoom(); - float left_pos = m_main_toolbar.get_item("arrange")->render_left_pos; - const float x = 0.5 * canvas_w + left_pos * zoom; - imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f); + const float x = 0.5 * canvas_w + left * zoom; + imgui->set_next_window_pos(x, toolbar_height, ImGuiCond_Always, 0.0f, 0.0f); #else - const float x = canvas_w - m_main_toolbar.get_width(); + float main_toolbar_width = 0.0f; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + main_toolbar_width = p_main_toolbar->get_width(); + } + const float x = canvas_w - main_toolbar_width; const float y = 0.5f * canvas_h - top * float(get_active_camera().get_zoom()); imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f); #endif @@ -6509,61 +6630,24 @@ void GLCanvas3D::_switch_toolbars_icon_filename() background_data.top = 16; background_data.right = 16; background_data.bottom = 16; - m_main_toolbar.init(background_data); - m_assemble_view_toolbar.init(background_data); - m_separator_toolbar.init(background_data); + + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + p_main_toolbar->init(background_data); + p_main_toolbar->set_dark_mode_enabled(m_is_dark); + } + wxGetApp().plater()->get_collapse_toolbar().init(background_data); - // main toolbar - { - GLToolbarItem* item; - item = m_main_toolbar.get_item("add"); - item->set_icon_filename(m_is_dark ? "toolbar_open_dark.svg" : "toolbar_open.svg"); - - item = m_main_toolbar.get_item("addplate"); - item->set_icon_filename(m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg"); - - item = m_main_toolbar.get_item("orient"); - item->set_icon_filename(m_is_dark ? "toolbar_orient_dark.svg" : "toolbar_orient.svg"); - - item = m_main_toolbar.get_item("addplate"); - item->set_icon_filename(m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg"); - - item = m_main_toolbar.get_item("arrange"); - item->set_icon_filename(m_is_dark ? "toolbar_arrange_dark.svg" : "toolbar_arrange.svg"); - - item = m_main_toolbar.get_item("splitobjects"); - item->set_icon_filename(m_is_dark ? "split_objects_dark.svg" : "split_objects.svg"); - - item = m_main_toolbar.get_item("splitvolumes"); - item->set_icon_filename(m_is_dark ? "split_parts_dark.svg" : "split_parts.svg"); - - item = m_main_toolbar.get_item("layersediting"); - item->set_icon_filename(m_is_dark ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg"); - } - - // assemble view toolbar - { - GLToolbarItem* item; - item = m_assemble_view_toolbar.get_item("assembly_view"); - item->set_icon_filename(m_is_dark ? "toolbar_assemble_dark.svg" : "toolbar_assemble.svg"); - } } bool GLCanvas3D::_init_toolbars() { if (!_init_main_toolbar()) return false; - //QDS: GUI refractor - if (!_init_assemble_view_toolbar()) - return false; - if (!_init_return_toolbar()) return false; - if (!_init_separator_toolbar()) - return false; - if (!_init_select_plate_toolbar()) return false; @@ -6581,9 +6665,21 @@ bool GLCanvas3D::_init_toolbars() //QDS: GUI refactor: GLToolbar bool GLCanvas3D::_init_main_toolbar() { - if (!m_main_toolbar.is_enabled()) + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return false; + } + if (!p_main_toolbar->is_enabled()) return true; + if (m_canvas_type == ECanvasType::CanvasAssembleView) { + m_main_toolbar->set_position_mode(ToolbarLayout::EPositionMode::Custom); + } + else { + m_main_toolbar->set_position_mode(ToolbarLayout::EPositionMode::TopMiddle); + } + m_main_toolbar->set_collapsed_offset(8); // by design from UX + BackgroundTexture::Metadata background_data; background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; background_data.left = 16; @@ -6591,12 +6687,15 @@ bool GLCanvas3D::_init_main_toolbar() background_data.right = 16; background_data.bottom = 16; - if (!m_main_toolbar.init(background_data)) + if (!p_main_toolbar->init(background_data)) { // unable to init the toolbar texture, disable it - m_main_toolbar.set_enabled(false); + p_main_toolbar->set_enabled(false); return true; } + + p_main_toolbar->set_dark_mode_enabled(m_is_dark); + // init arrow BackgroundTexture::Metadata arrow_data; arrow_data.filename = "toolbar_arrow.svg"; @@ -6604,166 +6703,278 @@ bool GLCanvas3D::_init_main_toolbar() arrow_data.top = 0; arrow_data.right = 0; arrow_data.bottom = 0; - if (!m_main_toolbar.init_arrow(arrow_data)) + if (!p_main_toolbar->init_arrow(arrow_data)) { BOOST_LOG_TRIVIAL(error) << "Main toolbar failed to load arrow texture."; } - // m_gizmos is created at constructor, thus we can init arrow here. - if (!m_gizmos.init_arrow(arrow_data)) - { - BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture."; - } - m_main_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); + p_main_toolbar->set_layout_type(ToolbarLayout::EType::Horizontal); //QDS: main toolbar is at the top and left, we don't need the rounded-corner effect at the right side and the top side - m_main_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right); - m_main_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); - m_main_toolbar.set_border(5.0f); - m_main_toolbar.set_separator_size(5); - m_main_toolbar.set_gap_size(4); + p_main_toolbar->set_horizontal_orientation(ToolbarLayout::HO_Right); + p_main_toolbar->set_vertical_orientation(ToolbarLayout::VO_Top); + p_main_toolbar->set_border(5.0f); + p_main_toolbar->set_separator_size(5); + p_main_toolbar->set_gap_size(4); - m_main_toolbar.del_all_item(); + p_main_toolbar->del_all_item(); + uint8_t sprite_id = 0; GLToolbarItem::Data item; - item.name = "add"; - item.icon_filename = m_is_dark ? "toolbar_open_dark.svg" : "toolbar_open.svg"; - item.tooltip = _utf8(L("Add")) + " [" + GUI::shortkey_ctrl_prefix() + "I]"; - item.sprite_id = 0; - item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); }; - item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_model(); }; - if (!m_main_toolbar.add_item(item)) - return false; + if (m_canvas_type == ECanvasType::CanvasView3D) { + item.name = "add"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "toolbar_open_dark.svg" : "toolbar_open.svg"; + }; + item.tooltip = _utf8(L("Add")) + " [" + GUI::shortkey_ctrl_prefix() + "I]"; + item.sprite_id = sprite_id++; + item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); }; + item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_model(); }; + if (!p_main_toolbar->add_item(item)) + return false; - item.name = "addplate"; - item.icon_filename = m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg"; - item.tooltip = _utf8(L("Add plate")); - item.sprite_id++; - item.continuous_click = true; - item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD_PLATE)); }; - item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_plate(); }; - if (!m_main_toolbar.add_item(item)) - return false; + item.name = "addplate"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg"; + }; + item.tooltip = _utf8(L("Add plate")); + item.sprite_id = sprite_id++; + item.continuous_click = true; + item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD_PLATE)); }; + item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_plate(); }; + if (!p_main_toolbar->add_item(item)) + return false; + + item.name = "orient"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "toolbar_orient_dark.svg" : "toolbar_orient.svg"; + }; + item.tooltip = _utf8(L("Auto orient")); + item.sprite_id = sprite_id++; + item.left.render_callback = nullptr; + item.enabling_callback = []()->bool { return wxGetApp().plater()->can_do_ui_job(); }; + item.left.toggable = false; // allow right mouse click + //QDS: GUI refactor: adjust the main toolbar position + item.left.action_callback = [this]() { + if (m_canvas != nullptr) + { + wxGetApp().plater()->set_prepare_state(Job::PREPARE_STATE_DEFAULT); + wxGetApp().plater()->orient(); + //QDS do not show orient menu + //_render_orient_menu(left, right, bottom, top); + NetworkAgent* agent = GUI::wxGetApp().getAgent(); + if (agent) agent->track_update_property("auto_orient", std::to_string(++auto_orient_count)); + } + }; + if (!p_main_toolbar->add_item(item)) + return false; + + item.name = "arrange"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "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 = sprite_id++; + 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_do_ui_job(); }; + item.left.toggable = true; + //QDS: GUI refactor: adjust the main toolbar position + item.left.render_callback = [this](float left, float right, float bottom, float top, float toolbar_height) { + if (m_canvas != nullptr) + { + _render_arrange_menu(left, toolbar_height); + //_render_arrange_menu(0.5f * (left + right)); + } + }; + if (!p_main_toolbar->add_item(item)) + return false; + + GLToolbarItem::Data layers_editing_item; + layers_editing_item.name = "layersediting"; + layers_editing_item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg"; + }; + layers_editing_item.tooltip = _utf8(L("Variable layer height")); + layers_editing_item.additional_tooltip = _u8L("Please select single object."); + layers_editing_item.sprite_id = sprite_id++; + layers_editing_item.left.action_callback = [this]()->void{ + 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)); + } + }; + layers_editing_item.right.action_callback = [this]()->void { + enable_layers_editing(false); + }; + layers_editing_item.visibility_callback = [this, &p_main_toolbar]()->bool { + bool res = current_printer_technology() == ptFFF; + // turns off if changing printer technology + if (!res && p_main_toolbar->is_item_visible("layersediting") && p_main_toolbar->is_item_pressed("layersediting")) + force_main_toolbar_left_action(get_main_toolbar_item_id("layersediting")); + + return res; + }; + layers_editing_item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); }; + layers_editing_item.left.toggable = true; + if (!p_main_toolbar->add_item(layers_editing_item)) + return false; - item.name = "orient"; - item.icon_filename = m_is_dark ? "toolbar_orient_dark.svg" : "toolbar_orient.svg"; - item.tooltip = _utf8(L("Auto orient")); - item.sprite_id++; - item.left.render_callback = nullptr; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_do_ui_job(); }; - item.left.toggable = false; // allow right mouse click - //QDS: GUI refactor: adjust the main toolbar position - item.left.action_callback = [this]() { - if (m_canvas != nullptr) { - wxGetApp().plater()->set_prepare_state(Job::PREPARE_STATE_DEFAULT); - wxGetApp().plater()->orient(); - //QDS do not show orient menu - //_render_orient_menu(left, right, bottom, top); - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) agent->track_update_property("auto_orient", std::to_string(++auto_orient_count)); + GLToolbarItem::Data sperate_item; + sperate_item.name = "seperator2"; + sperate_item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return "seperator.svg"; + }; + sperate_item.sprite_id = sprite_id++; + sperate_item.left.action_callback = [this]() {}; + sperate_item.visibility_callback = []()->bool { return true; }; + sperate_item.enabling_callback = []()->bool { return true; }; + if (!p_main_toolbar->add_item(sperate_item, GLToolbarItem::EType::SeparatorLine)) + return false; } - }; - if (!m_main_toolbar.add_item(item)) - return false; + } - item.name = "arrange"; - 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 = [this]() { - if (m_canvas != nullptr) { - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) agent->track_update_property("auto_arrange", std::to_string(++auto_arrange_count)); + const auto do_add_other_items = [this](uint8_t& sprite_id)->void { + if (m_canvas_type == ECanvasType::CanvasView3D) { + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return; + } + GLToolbarItem::Data item; + item.name = "splitobjects"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "split_objects_dark.svg" : "split_objects.svg"; + }; + item.tooltip = _utf8(L("Split to objects")); + item.additional_tooltip = _u8L("Please select single object.") + "\n" + + _u8L("And it is valid when there are at least two parts in object or stl has at least two meshes."); + item.sprite_id = sprite_id++; + item.left.render_callback = nullptr; + 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.left.toggable = false; + item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); }; + p_main_toolbar->add_item(item); + + item.name = "splitvolumes"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "split_parts_dark.svg" : "split_parts.svg"; + }; + item.tooltip = _utf8(L("Split to parts")); + item.additional_tooltip = _u8L("Please select single object.") + "\n" + + _u8L("And it is valid when importing an stl with at least two meshes."); + item.sprite_id = sprite_id++; + 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(); }; + p_main_toolbar->add_item(item); } }; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_do_ui_job(); }; - item.left.toggable = true; - //QDS: GUI refactor: adjust the main toolbar position - item.left.render_callback = [this](float left, float right, float bottom, float top) { - if (m_canvas != nullptr) + + if (m_gizmos.is_enabled()) { + m_gizmos.add_toolbar_items(p_main_toolbar, sprite_id, do_add_other_items); + } + else if (m_canvas_type == ECanvasType::CanvasView3D) { + do_add_other_items(sprite_id); + } + + if (m_canvas_type == ECanvasType::CanvasView3D) { + + GLToolbarItem::Data more_item; + more_item.name = "More"; + more_item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "more_dark.svg" : "more.svg"; + }; + more_item.tooltip = _utf8(L("Click to Extend")); + more_item.on_hover = [this]()->std::string { + if (m_main_toolbar) { + if (m_main_toolbar->is_collapsed()) { + return _utf8(L("Click to Extend")); + } + else { + return _utf8(L("Click to Collapse")); + } + } + return ""; + }; + more_item.sprite_id = sprite_id++; + more_item.visible = false; + more_item.left.action_callback = [this]()->void{}; + more_item.visibility_callback = [this]()->bool { + if (m_main_toolbar) { + return m_main_toolbar->needs_collapsed(); + } + return false; + }; + more_item.enabling_callback = []()->bool { return true; }; + more_item.b_collapsible = false; + more_item.b_collapse_button = true; + more_item.continuous_click = true; + if (!p_main_toolbar->add_item(more_item)) + return false; + { - _render_arrange_menu(left, right, bottom, top); - //_render_arrange_menu(0.5f * (left + right)); + GLToolbarItem::Data sperate_item; + sperate_item.name = "seperator1"; + sperate_item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return "seperator.svg"; + }; + sperate_item.sprite_id = sprite_id++; + sperate_item.left.action_callback = [this]() {}; + sperate_item.visibility_callback = []()->bool { return true; }; + sperate_item.enabling_callback = []()->bool { return true; }; + sperate_item.b_collapsible = false; + if (!p_main_toolbar->add_item(sperate_item, GLToolbarItem::EType::SeparatorLine)) + return false; } - }; - if (!m_main_toolbar.add_item(item)) - return false; - item.right.toggable = false; - item.right.render_callback = GLToolbarItem::Default_Render_Callback; - - if (!m_main_toolbar.add_separator()) - return false; - - item.name = "splitobjects"; - item.icon_filename = m_is_dark ? "split_objects_dark.svg" : "split_objects.svg"; - item.tooltip = _utf8(L("Split to objects")); - item.additional_tooltip = _u8L("Please select single object.") + "\n"+ - _u8L("And it is valid when there are at least two parts in object or stl has at least two meshes."); - 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)); - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) agent->track_update_property("split_to_objects", std::to_string(++split_to_objects_count)); + { + GLToolbarItem::Data item; + item.name = "assembly_view"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return is_dark_mode ? "toolbar_assemble_dark.svg" : "toolbar_assemble.svg"; + }; + item.tooltip = _utf8(L("Assembly View")); + item.sprite_id = sprite_id++; + item.left.toggable = false; + 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("assembly_view", std::to_string(++assembly_view_count)); + } + }; + item.left.render_callback = GLToolbarItem::Default_Render_Callback; + item.visible = true; + item.visibility_callback = [this]()->bool { return true; }; + item.enabling_callback = [this]()->bool { + return wxGetApp().plater()->has_assmeble_view(); + }; + item.b_collapsible = false; + if (!p_main_toolbar->add_item(item)) + return false; } - }; - item.visibility_callback = GLToolbarItem::Default_Visibility_Callback; - item.left.toggable = false; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); }; - if (!m_main_toolbar.add_item(item)) - return false; - - item.name = "splitvolumes"; - item.icon_filename = m_is_dark ? "split_parts_dark.svg" : "split_parts.svg"; - item.tooltip = _utf8(L("Split to parts")); - item.additional_tooltip = _u8L("Please select single object.")+ "\n" + - _u8L("And it is valid when importing an stl with at least two meshes."); - item.sprite_id++; - 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)) - return false; - - item.name = "layersediting"; - 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.additional_tooltip = _u8L("Please select single object."); - item.sprite_id++; - 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.right.action_callback = [this]() { - if (m_canvas != nullptr) { - wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); - } - }; - item.visibility_callback = [this]()->bool { - bool res = current_printer_technology() == ptFFF; - // turns off if changing printer technology - if (!res && m_main_toolbar.is_item_visible("layersediting") && m_main_toolbar.is_item_pressed("layersediting")) - force_main_toolbar_left_action(get_main_toolbar_item_id("layersediting")); - - return res; - }; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); }; - item.left.toggable = true; - if (!m_main_toolbar.add_item(item)) - return false; + } + p_main_toolbar->update_items_state(); return true; } @@ -6792,13 +7003,28 @@ void GLCanvas3D::_update_select_plate_toolbar_stats_item(bool force_selected) { bool GLCanvas3D::_update_imgui_select_plate_toolbar() { bool result = true; - if (!m_sel_plate_toolbar.is_enabled() || m_sel_plate_toolbar.is_render_finish) return false; + if (!m_sel_plate_toolbar.is_enabled()) { + return false; + } + + const auto& p_plater = wxGetApp().plater(); + if (!p_plater) { + return false; + } + + if (!p_plater->is_plate_toolbar_image_dirty()) { + return false; + } + + if (!p_plater->is_gcode_3mf()) { + p_plater->update_all_plate_thumbnails(true); + } _update_select_plate_toolbar_stats_item(); m_sel_plate_toolbar.del_all_item(); - PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list(); + PartPlateList& plate_list = p_plater->get_partplate_list(); for (int i = 0; i < plate_list.get_plate_count(); i++) { IMToolbarItem* item = new IMToolbarItem(); PartPlate* plate = plate_list.get_plate(i); @@ -6811,69 +7037,11 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar() } m_sel_plate_toolbar.m_items.push_back(item); } - + p_plater->clear_plate_toolbar_image_dirty(); m_sel_plate_toolbar.is_display_scrollbar = false; return result; } -//QDS: GUI refactor -//init the assemble view toolbar on the top -bool GLCanvas3D::_init_assemble_view_toolbar() -{ - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": enter, m_assemble_view_toolbar.is_enabled=" << m_assemble_view_toolbar.is_enabled() << "\n"; - if (!m_assemble_view_toolbar.is_enabled()) - return true; - - BackgroundTexture::Metadata background_data; - background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; - background_data.left = 16; - background_data.top = 16; - background_data.right = 16; - background_data.bottom = 16; - - if (!m_assemble_view_toolbar.init(background_data)) - { - // unable to init the toolbar texture, disable it - m_assemble_view_toolbar.set_enabled(false); - return true; - } - - m_assemble_view_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); - //QDS: assemble toolbar is at the top and right, we don't need the rounded-corner effect at the left side and the top side - m_assemble_view_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left); - m_assemble_view_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); - m_assemble_view_toolbar.set_border(5.0f); - m_assemble_view_toolbar.set_separator_size(10); - m_assemble_view_toolbar.set_gap_size(4); - - m_assemble_view_toolbar.del_all_item(); - - GLToolbarItem::Data item; - item.name = "assembly_view"; - item.icon_filename = m_is_dark ? "toolbar_assemble_dark.svg" : "toolbar_assemble.svg"; - 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)); 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("assembly_view", std::to_string(++assembly_view_count)); - } - }; - item.left.render_callback = GLToolbarItem::Default_Render_Callback; - item.visible = true; - item.visibility_callback = [this]()->bool { return true; }; - item.enabling_callback = [this]()->bool { - return wxGetApp().plater()->has_assmeble_view(); - }; - if (!m_assemble_view_toolbar.add_item(item)) - return false; - - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Finished Successfully\n"; - return true; -} - bool GLCanvas3D::_init_return_toolbar() { if (!m_return_toolbar.is_enabled()) @@ -6882,47 +7050,6 @@ bool GLCanvas3D::_init_return_toolbar() return m_return_toolbar.init(); } -bool GLCanvas3D::_init_separator_toolbar() -{ - if (!m_separator_toolbar.is_enabled()) - return true; - - BackgroundTexture::Metadata background_data; - background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; - background_data.left = 0; - background_data.top = 0; - background_data.right = 0; - background_data.bottom = 0; - - if (!m_separator_toolbar.init(background_data)) - { - // unable to init the toolbar texture, disable it - m_separator_toolbar.set_enabled(false); - return true; - } - - m_separator_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); - //QDS: assemble toolbar is at the top and right, we don't need the rounded-corner effect at the left side and the top side - m_separator_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left); - m_separator_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); - m_separator_toolbar.set_border(5.0f); - - m_separator_toolbar.del_all_item(); - - GLToolbarItem::Data sperate_item; - sperate_item.name = "start_seperator"; - sperate_item.icon_filename = "seperator.svg"; - sperate_item.sprite_id = 0; - sperate_item.left.action_callback = [this]() {}; - sperate_item.visibility_callback = []()->bool { return true; }; - sperate_item.enabling_callback = []()->bool { return false; }; - if (!m_separator_toolbar.add_item(sperate_item)) - return false; - - return true; -} - - // QDS #if 0 bool GLCanvas3D::_init_view_toolbar() @@ -7013,7 +7140,7 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_be bb.merge(wxGetApp().plater()->get_partplate_list().get_bounding_box()); } - if (!m_main_toolbar.is_enabled()) { + if (m_canvas_type == CanvasPreview) { const BoundingBoxf3& toolpath_bb = m_gcode_viewer.get_max_bounding_box(); if (toolpath_bb.max_size() > 0.f) bb.merge(toolpath_bb); @@ -7107,10 +7234,7 @@ void GLCanvas3D::_picking_pass() glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); //QDS: only render plate in view 3D - bool is_paint_gizmo=(m_gizmos.get_current_type() == GLGizmosManager::EType::FdmSupports || - m_gizmos.get_current_type() == GLGizmosManager::EType::MmuSegmentation || - m_gizmos.get_current_type() == GLGizmosManager::EType::Seam); - if (m_canvas_type == ECanvasType::CanvasView3D && !is_paint_gizmo) { + if (m_canvas_type == ECanvasType::CanvasView3D && !m_gizmos.is_paint_gizmo()) { _render_plates_for_picking(); } @@ -7366,17 +7490,11 @@ void GLCanvas3D::_render_bed(bool bottom, bool show_axes) scale_factor = m_retina_helper->get_scale_factor(); #endif // ENABLE_RETINA_GL - /* - bool show_texture = ! bottom || - (m_gizmos.get_current_type() != GLGizmosManager::FdmSupports - && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports - && m_gizmos.get_current_type() != GLGizmosManager::Hollow - && m_gizmos.get_current_type() != GLGizmosManager::Seam - && m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation); - */ //bool show_texture = true; //QDS set axes mode - m_bed.set_axes_mode(m_main_toolbar.is_enabled() && !m_gizmos.is_show_only_active_plate()); + const auto& p_main_toolbar = get_main_toolbar(); + bool b_main_toolbar_enabled = p_main_toolbar && p_main_toolbar->is_enabled(); + m_bed.set_axes_mode(b_main_toolbar_enabled && !m_gizmos.is_show_only_active_plate()); m_bed.render(*this, bottom, scale_factor, show_axes); } @@ -7407,16 +7525,16 @@ void GLCanvas3D::_render_plane() const } //QDS: add outline drawing logic -void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with_outline) +void GLCanvas3D::_render_objects(GLVolumeCollection &cur_volumes, GLVolumeCollection::ERenderType type, bool with_outline, bool in_paint_gizmo) { - if (m_volumes.empty()) + if (cur_volumes.empty()) return; glsafe(::glEnable(GL_DEPTH_TEST)); m_camera_clipping_plane = m_gizmos.get_clipping_plane(); - if (m_picking_enabled) + if (m_picking_enabled && !in_paint_gizmo) // Update the layer editing selection to the first object selected, update the current object maximum Z. m_layers_editing.select_object(*m_model, this->is_layers_editing_enabled() ? m_selection.get_object_idx() : -1); @@ -7424,13 +7542,13 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with switch (build_volume.type()) { case BuildVolume::Type::Rectangle: { const BoundingBox3Base bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon); - m_volumes.set_print_volume({ 0, // Rectangle + cur_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: { - m_volumes.set_print_volume({ 1, // Circle + cur_volumes.set_print_volume({1, // Circle { unscaled(build_volume.circle().center.x()), unscaled(build_volume.circle().center.y()), unscaled(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f }, { 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } }); break; @@ -7438,38 +7556,38 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with default: case BuildVolume::Type::Convex: case BuildVolume::Type::Custom: { - m_volumes.set_print_volume({ static_cast(type), + cur_volumes.set_print_volume({static_cast(type), { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX }, { -FLT_MAX, FLT_MAX } } ); } } if (m_requires_check_outside_state) { - m_volumes.check_outside_state(build_volume, nullptr, nullptr, *m_model); + cur_volumes.check_outside_state(build_volume, nullptr, nullptr, *m_model); m_requires_check_outside_state = false; } } if (m_use_clipping_planes) - m_volumes.set_z_range(-m_clipping_planes[0].get_data()[3], m_clipping_planes[1].get_data()[3]); + cur_volumes.set_z_range(-m_clipping_planes[0].get_data()[3], m_clipping_planes[1].get_data()[3]); else - m_volumes.set_z_range(-FLT_MAX, FLT_MAX); + cur_volumes.set_z_range(-FLT_MAX, FLT_MAX); GLGizmosManager& gm = get_gizmos_manager(); GLGizmoBase* current_gizmo = gm.get_current(); if (m_canvas_type == CanvasAssembleView) { - m_volumes.set_clipping_plane(m_gizmos.get_assemble_view_clipping_plane().get_data()); + cur_volumes.set_clipping_plane(m_gizmos.get_assemble_view_clipping_plane().get_data()); } else if (current_gizmo && !current_gizmo->apply_clipping_plane()) { - m_volumes.set_clipping_plane(ClippingPlane::ClipsNothing().get_data()); + cur_volumes.set_clipping_plane(ClippingPlane::ClipsNothing().get_data()); } else { - m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); + cur_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); } if (m_canvas_type == CanvasAssembleView) - m_volumes.set_show_sinking_contours(false); + cur_volumes.set_show_sinking_contours(false); else - m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances()); + cur_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances()); const auto& shader = wxGetApp().get_shader("gouraud"); ECanvasType canvas_type = this->m_canvas_type; @@ -7492,16 +7610,24 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with case GLVolumeCollection::ERenderType::Opaque: { const GLGizmosManager& gm = get_gizmos_manager(); - if (dynamic_cast(gm.get_current()) == nullptr) - { - if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f) && GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + if (in_paint_gizmo) { + cur_volumes.render( + render_pipeline_stage, type, m_picking_enabled, camera, colors, *m_model, + [this](const GLVolume &volume) { + return true; + }, + with_outline, body_color, partly_inside_enable, nullptr); + } + if (dynamic_cast(gm.get_current()) == nullptr){ + if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f) && + GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { int object_id = m_layers_editing.last_object_id; - m_volumes.render( + cur_volumes.render( render_pipeline_stage, type, false, camera, colors, *m_model,[object_id](const GLVolume &volume) { // Which volume to paint without the layer height profile shader? return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); }); - m_layers_editing.render_volumes(*this, m_volumes); + m_layers_editing.render_volumes(*this, cur_volumes); } else { /*if (wxGetApp().plater()->is_wireframe_enabled()) { @@ -7512,7 +7638,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with }*/ //QDS:add assemble view related logic // do not cull backfaces to show broken geometry, if any - m_volumes.render( + cur_volumes.render( render_pipeline_stage, type, m_picking_enabled, camera, colors, *m_model,[this, canvas_type](const GLVolume &volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { @@ -7548,17 +7674,25 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with shader->set_uniform("show_wireframe", false); }*/ //QDS:add assemble view related logic - m_volumes.render( - render_pipeline_stage, type, false, camera, colors,*m_model, - [this, canvas_type](const GLVolume &volume) { - if (canvas_type == ECanvasType::CanvasAssembleView) { - return !volume.is_modifier; - } - else { - return true; - } - }, - with_outline, body_color, partly_inside_enable, printable_height_option ? &printable_height_option->values : nullptr); + if (in_paint_gizmo) { + cur_volumes.render( + render_pipeline_stage, type, false, camera, colors, *m_model, + [this, canvas_type](const GLVolume &volume) { + return true; + }, + with_outline, body_color, partly_inside_enable, nullptr); + } else { + cur_volumes.render( + render_pipeline_stage, type, false, camera, colors, *m_model, + [this, canvas_type](const GLVolume &volume) { + if (canvas_type == ECanvasType::CanvasAssembleView) { + return !volume.is_modifier; + } else { + return true; + } + }, + with_outline, body_color, partly_inside_enable, printable_height_option ? &printable_height_option->values : nullptr); + } if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0 && GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { const GLGizmosManager& gm = get_gizmos_manager(); wxGetApp().unbind_shader(); @@ -7566,7 +7700,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with wxGetApp().bind_shader(shader); } if (m_canvas_type == CanvasView3D && m_gizmos.is_paint_gizmo()) { - m_volumes.only_render_sinking( + cur_volumes.only_render_sinking( render_pipeline_stage, type, false, camera, colors, *m_model, [this, canvas_type](const GLVolume &volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { @@ -7675,7 +7809,13 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() return; } - float scale = wxGetApp().toolbar_icon_scale(); + float scale = 1.0f; + + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + const bool auto_scale = p_main_toolbar->get_rendering_mode() == GLToolbar::EToolbarRenderingMode::Auto; + scale = wxGetApp().toolbar_icon_scale(auto_scale); + } Size cnv_size = get_canvas_size(); //QDS: GUI refactor: GLToolbar @@ -7687,9 +7827,9 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() #if ENABLE_RETINA_GL const float sc = m_retina_helper->get_scale_factor() * scale; //QDS: GUI refactor: GLToolbar - m_main_toolbar.set_scale(sc); - m_assemble_view_toolbar.set_scale(sc); - m_separator_toolbar.set_scale(sc); + if (p_main_toolbar) { + p_main_toolbar->set_scale(sc); + } collapse_toolbar.set_scale(sc); size *= m_retina_helper->get_scale_factor(); @@ -7697,9 +7837,9 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() m_notification->set_scale(sc); #else //QDS: GUI refactor: GLToolbar - m_main_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size * scale); - m_assemble_view_toolbar.set_icons_size(size); - m_separator_toolbar.set_icons_size(size); + if (p_main_toolbar) { + p_main_toolbar->set_icons_size(size); + } collapse_toolbar.set_icons_size(wxGetApp().plater()->get_collapse_toolbar_size()); #endif // ENABLE_RETINA_GL // Update collapse toolbar @@ -7709,13 +7849,18 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() #if QDS_TOOLBAR_ON_TOP float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : GLToolbar::Default_Icons_Size; - float top_tb_width = m_main_toolbar.get_width() + m_gizmos.get_scaled_total_width() + m_assemble_view_toolbar.get_width() + m_separator_toolbar.get_width() + collapse_toolbar_width; - int items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt() + m_separator_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt(); + float top_tb_width = collapse_toolbar_width; + int items_cnt = collapse_toolbar.get_visible_items_cnt(); + if (p_main_toolbar) { + top_tb_width += p_main_toolbar->get_width(); + items_cnt += p_main_toolbar->get_visible_items_cnt(); + } + float noitems_width = top_tb_width - size * items_cnt; // width of separators and borders in top toolbars // calculate scale needed for items in all top toolbars #ifdef __WINDOWS__ - cnv_size.set_width(cnv_size.get_width() + m_separator_toolbar.get_width() + collapse_toolbar_width); + cnv_size.set_width(cnv_size.get_width() + collapse_toolbar_width); #endif float new_h_scale = (cnv_size.get_width() - noitems_width) / (items_cnt * GLToolbar::Default_Icons_Size); @@ -7737,7 +7882,9 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() //items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + 3; // +3 means a place for top and view toolbars and separators in gizmos toolbar // calculate scale needed for items in the gizmos toolbar - items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt(); + if (p_main_toolbar) { + items_cnt += p_main_toolbar->get_visible_items_cnt(); + } float new_v_scale = cnv_size.get_height() / (items_cnt * GLGizmosManager::Default_Icons_Size); #endif @@ -7752,52 +7899,13 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() void GLCanvas3D::_render_overlays() { - glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_DEPTH_TEST)); _check_and_update_toolbar_icon_scale(); _render_assemble_control(); - // main toolbar and undoredo toolbar need to be both updated before rendering because both their sizes are needed - // to correctly place them -#if ENABLE_RETINA_GL - const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(/*true*/); - //QDS: GUI refactor: GLToolbar - m_main_toolbar.set_scale(scale); - m_assemble_view_toolbar.set_scale(scale); - m_separator_toolbar.set_scale(scale); - wxGetApp().plater()->get_collapse_toolbar().set_scale(scale); - m_gizmos.set_overlay_scale(scale); -#else - // QDS adjust display scale - const float size = int(GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale(/*true*/)); - const float gizmo_size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale()); - //const float size = int(GLToolbar::Default_Icons_Size); - //const float gizmo_size = int(GLGizmosManager::Default_Icons_Size); - - //QDS: GUI refactor: GLToolbar - m_main_toolbar.set_icons_size(gizmo_size); - m_assemble_view_toolbar.set_icons_size(gizmo_size); - m_separator_toolbar.set_icons_size(gizmo_size); - wxGetApp().plater()->get_collapse_toolbar().set_icons_size(wxGetApp().plater()->get_collapse_toolbar_size()); - m_gizmos.set_overlay_icon_size(gizmo_size); -#endif // ENABLE_RETINA_GL - - _render_separator_toolbar_right(); - _render_separator_toolbar_left(); - _render_main_toolbar(); - _render_collapse_toolbar(); - _render_assemble_view_toolbar(); - //QDS: GUI refactor: GLToolbar - _render_imgui_select_plate_toolbar(); - _render_return_toolbar(); - // QDS - //_render_view_toolbar(); - _render_paint_toolbar(); - - //QDS: GUI refactor: GLToolbar - //move gizmos behind of main - _render_gizmos_overlay(); + _render_toolbar(); if (m_layers_editing.last_object_id >= 0 && m_layers_editing.object_max_z() > 0.0f) m_layers_editing.render_overlay(*this); @@ -7976,54 +8084,40 @@ void GLCanvas3D::_render_current_gizmo() const m_gizmos.render_current_gizmo(); } -//QDS: GUI refactor: GLToolbar adjust -//move the size calc to GLCanvas -void GLCanvas3D::_render_gizmos_overlay() -{ -/*#if ENABLE_RETINA_GL -// m_gizmos.set_overlay_scale(m_retina_helper->get_scale_factor()); - const float scale = m_retina_helper->get_scale_factor()*wxGetApp().toolbar_icon_scale(); - m_gizmos.set_overlay_scale(scale); //! #ys_FIXME_experiment -#else -// m_gizmos.set_overlay_scale(m_canvas->GetContentScaleFactor()); -// m_gizmos.set_overlay_scale(wxGetApp().em_unit()*0.1f); - const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale()); - m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment -#endif /* __WXMSW__ */ - m_gizmos.render_overlay(); - - if (m_gizmo_highlighter.m_render_arrow) - { - m_gizmos.render_arrow(*this, m_gizmo_highlighter.m_gizmo_type); - } -} - //QDS: GUI refactor: GLToolbar adjust //when rendering, {0, 0} is at the center, left-up is -0.5, 0.5, right-up is 0.5, -0.5 void GLCanvas3D::_render_main_toolbar() { - if (!m_main_toolbar.is_enabled()) + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return; + } + if (!p_main_toolbar->is_enabled()) return; - Size cnv_size = get_canvas_size(); - float inv_zoom = (float)get_active_camera().get_inv_zoom(); + const auto& t_camera = get_active_camera(); -#if QDS_TOOLBAR_ON_TOP - float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float left = get_main_toolbar_left(cnv_size.get_width(),inv_zoom); -#else - float gizmo_height = m_gizmos.get_scaled_total_height(); - float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); - float main_toolbar_height = (float)m_main_toolbar.get_height(); - float assemble_height = m_assemble_view_toolbar.get_height(); - float top = 0.5f * (main_toolbar_height + gizmo_height + assemble_height) * inv_zoom; - float left = (0.5f * (float)cnv_size.get_width() - m_main_toolbar.get_width()) * inv_zoom; - //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": top %1%, main_toolbar_height %2%, space_height %3% gizmo_height %4%") % top % main_toolbar_height % space_height % gizmo_height; -#endif - m_main_toolbar.set_position(top, left); - m_main_toolbar.render(*this); + if (m_canvas_type == ECanvasType::CanvasAssembleView) { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + float top = 0.5f * (float)t_viewport[3] * inv_zoom; + float left = 0.5f * m_paint_toolbar_width * inv_zoom; + p_main_toolbar->set_position(top, left); + } + else { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + float left = get_main_toolbar_left(t_viewport[2], inv_zoom); + if (is_collapse_toolbar_on_left()) { + p_main_toolbar->set_offset(get_collapse_toolbar_width() * 2.0f); + } + else { + p_main_toolbar->set_offset(0.0f); + } + } + p_main_toolbar->render(t_camera); if (m_toolbar_highlighter.m_render_arrow){ - m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item); + p_main_toolbar->render_arrow(m_toolbar_highlighter.m_toolbar_item); } } @@ -8037,6 +8131,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() return; } + _update_imgui_select_plate_toolbar(); + IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item; PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list(); @@ -8373,36 +8469,6 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() } imgui.end(); - m_sel_plate_toolbar.is_render_finish = true; -} - -//QDS: GUI refactor: GLToolbar adjust -//when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-up -void GLCanvas3D::_render_assemble_view_toolbar() const -{ - if (!m_assemble_view_toolbar.is_enabled()) - return; - - Size cnv_size = get_canvas_size(); - float inv_zoom = (float)get_active_camera().get_inv_zoom(); - -#if QDS_TOOLBAR_ON_TOP - const float separator_width = m_separator_toolbar.get_width(); - float gizmo_width = m_gizmos.get_scaled_total_width(); - float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); - float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width) * inv_zoom; -#else - float gizmo_height = m_gizmos.get_scaled_total_height(); - //float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); - float main_toolbar_height = (float)m_main_toolbar.get_height(); - float assemble_height = (float)m_assemble_view_toolbar.get_height(); - float top = 0.5f * (assemble_height - main_toolbar_height - gizmo_height) * inv_zoom; - float left = (0.5f * (float)cnv_size.get_width() - m_assemble_view_toolbar.get_width()) * inv_zoom; - //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": top %1%, main_toolbar_height %2%, space_height %3% gizmo_height %4%") % top % main_toolbar_height % space_height % gizmo_height; -#endif - m_assemble_view_toolbar.set_position(top, left); - m_assemble_view_toolbar.render(*this); } void GLCanvas3D::_render_return_toolbar() @@ -8425,12 +8491,19 @@ void GLCanvas3D::_render_return_toolbar() {//solve ui overlap issue if (m_canvas_type == ECanvasType::CanvasView3D) { float zoom = (float) get_active_camera().get_zoom(); - float left_pos = m_main_toolbar.get_item("add")->render_left_pos; + float left_pos = 0.0f; + const auto& p_main_toolbar = get_main_toolbar(); + if (p_main_toolbar) { + left_pos = p_main_toolbar->get_item("add")->render_rect[0]; + } const float toolbar_x = 0.5 * canvas_w + left_pos * zoom; const float margin = 5; if (toolbar_x < window_width + margin * 3) { window_pos_x = 5.0f; - window_pos_y = m_main_toolbar.get_height() + 2.0f; + window_pos_y = 2.0f; + if (p_main_toolbar) { + window_pos_y += p_main_toolbar->get_height(); + } } } } @@ -8471,7 +8544,11 @@ void GLCanvas3D::_render_return_toolbar() wxGetApp().plater()->get_view3D_canvas3D()->reload_scene(true); { GLCanvas3D * view_3d = wxGetApp().plater()->get_view3D_canvas3D(); - GLToolbarItem * assembly_item = view_3d->m_assemble_view_toolbar.get_item("assembly_view"); + const auto& p_main_toolbar = view_3d->get_main_toolbar(); + if (!p_main_toolbar) { + return; + } + std::shared_ptr assembly_item = p_main_toolbar->get_item("assembly_view"); std::chrono::system_clock::time_point end = std::chrono::system_clock::now(); std::chrono::duration duration = std::chrono::duration_cast>(end - assembly_item->get_start_time_point()); int times = duration.count(); @@ -8549,43 +8626,6 @@ void GLCanvas3D::_render_fit_camera_toolbar() imgui.end(); } -void GLCanvas3D::_render_separator_toolbar_right() const -{ - if (!m_separator_toolbar.is_enabled()) - return; - - Size cnv_size = get_canvas_size(); - float inv_zoom = (float)get_active_camera().get_inv_zoom(); - - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; - float gizmo_width = m_gizmos.get_scaled_total_width(); - float assemble_width = m_assemble_view_toolbar.get_width(); - float separator_width = m_separator_toolbar.get_width(); - float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); - float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + 0.5 * separator_width) * inv_zoom; - - m_separator_toolbar.set_position(top, left); - m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); -} - -void GLCanvas3D::_render_separator_toolbar_left() const -{ - if (!m_separator_toolbar.is_enabled()) - return; - - Size cnv_size = get_canvas_size(); - float inv_zoom = (float)get_active_camera().get_inv_zoom(); - float separator_width = m_separator_toolbar.get_width(); - float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); - float left = main_toolbar_left + (m_main_toolbar.get_width()) * inv_zoom; - - m_separator_toolbar.set_position(top, left); - m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); -} - void GLCanvas3D::_render_collapse_toolbar() const { auto & plater = *wxGetApp().plater(); @@ -8595,15 +8635,8 @@ void GLCanvas3D::_render_collapse_toolbar() const } GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - Size cnv_size = get_canvas_size(); - float inv_zoom = (float)get_active_camera().get_inv_zoom(); - - float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - //float left = (0.5f * (float)cnv_size.get_width() - (float)collapse_toolbar.get_width() - band) * inv_zoom; - float left = -0.5f * (float)cnv_size.get_width() * inv_zoom; - - collapse_toolbar.set_position(top, left); - collapse_toolbar.render(*this); + const auto& t_camera = get_active_camera(); + collapse_toolbar.render(t_camera); } //QDS reander assemble toolbar @@ -10012,9 +10045,10 @@ void GLCanvas3D::_render_silhouette_effect() const Transform3d& projection_matrix = camera.get_projection_matrix(); const Matrix4d view_proj = projection_matrix.matrix() * view_matrix.matrix(); p_silhouette_shader->set_uniform("u_view_projection_matrix", view_proj); - _render_objects(GLVolumeCollection::ERenderType::Opaque, false); - _render_objects(GLVolumeCollection::ERenderType::Transparent, false); - + _render_objects(m_volumes,GLVolumeCollection::ERenderType::Opaque, false); + _render_objects(m_volumes, GLVolumeCollection::ERenderType::Transparent, false); + _render_objects(m_paint_outline_volumes, GLVolumeCollection::ERenderType::Opaque, false,true); + _render_objects(m_paint_outline_volumes, GLVolumeCollection::ERenderType::Transparent, false, true); wxGetApp().unbind_shader(); // QDS: end render silhouette @@ -10442,6 +10476,27 @@ void GLCanvas3D::_append_to_frame_callback(const FrameCallback& cb) m_frame_callback_list.emplace_back(cb); } +void GLCanvas3D::_render_toolbar() +{ + _render_main_toolbar(); + _render_collapse_toolbar(); + + //QDS: GUI refactor: GLToolbar + _render_imgui_select_plate_toolbar(); + _render_return_toolbar(); + // QDS + //_render_view_toolbar(); + _render_paint_toolbar(); +} + +const std::shared_ptr& GLCanvas3D::get_main_toolbar() const +{ + if (!m_main_toolbar) { + m_main_toolbar = std::make_shared(GLToolbar::EType::Normal, "Main"); + } + return m_main_toolbar; +} + void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, const std::shared_ptr& shader, @@ -10852,6 +10907,10 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) error = ErrorType::ASSEMBLY_WARNNING; break; } + case EWarning::NozzleFilamentIncompatible: { + text = _u8L(get_nozzle_filament_incompatible_text()); + break; + } } //QDS: this may happened when exit the app, plater is null if (!wxGetApp().plater()) @@ -10869,13 +10928,22 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) wxString region = L"en"; if (language.find("zh") == 0) region = L"zh"; - wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.qiditech.com/%s/filament-acc/filament/h2d-pla-and-petg-mutual-support", region)); + //y68 + wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.qidi3d.com/%s/Memo/Filament-Guide", region)); return false; }); } else notification_manager.close_slicing_customize_error_notification(NotificationType::QDTMixUsePLAAndPETG, NotificationLevel::WarningNotificationLevel); } + else if (warning == EWarning::NozzleFilamentIncompatible){ + if(state){ + notification_manager.push_slicing_customize_error_notification(NotificationType::QDTNozzleFilamentIncompatible, NotificationLevel::WarningNotificationLevel, text); + } + else{ + notification_manager.close_slicing_customize_error_notification(NotificationType::QDTNozzleFilamentIncompatible, NotificationLevel::WarningNotificationLevel); + } + } else { if (state) notification_manager.push_plater_warning_notification(text); @@ -11076,8 +11144,12 @@ void GLCanvas3D::_update_selection_from_hover() bool GLCanvas3D::_deactivate_arrange_menu() { - if (m_main_toolbar.is_item_pressed("arrange")) { - m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("arrange"), *this); + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return false; + } + if (p_main_toolbar->is_item_pressed("arrange")) { + p_main_toolbar->force_right_action(p_main_toolbar->get_item_id("arrange"), *this); return true; } @@ -11087,8 +11159,12 @@ bool GLCanvas3D::_deactivate_arrange_menu() //QDS: add deactivate orient menu bool GLCanvas3D::_deactivate_orient_menu() { - if (m_main_toolbar.is_item_pressed("orient")) { - m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("orient"), *this); + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return false; + } + if (p_main_toolbar->is_item_pressed("orient")) { + p_main_toolbar->force_right_action(p_main_toolbar->get_item_id("orient"), *this); return true; } @@ -11098,8 +11174,12 @@ bool GLCanvas3D::_deactivate_orient_menu() //QDS: add deactivate layersediting menu bool GLCanvas3D::_deactivate_layersediting_menu() { - if (m_main_toolbar.is_item_pressed("layersediting")) { - m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("layersediting"), *this); + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return false; + } + if (p_main_toolbar->is_item_pressed("layersediting")) { + p_main_toolbar->force_right_action(p_main_toolbar->get_item_id("layersediting"), *this); return true; } @@ -11119,7 +11199,11 @@ bool GLCanvas3D::_deactivate_collapse_toolbar_items() void GLCanvas3D::highlight_toolbar_item(const std::string& item_name) { - GLToolbarItem* item = m_main_toolbar.get_item(item_name); + const auto& p_main_toolbar = get_main_toolbar(); + if (!p_main_toolbar) { + return; + } + std::shared_ptr item = p_main_toolbar->get_item(item_name); if (!item || !item->is_visible()) return; m_toolbar_highlighter.init(item, this); @@ -11194,7 +11278,7 @@ void GLCanvas3D::ToolbarHighlighter::set_timer_owner(wxEvtHandler* owner, int ti m_timer.SetOwner(owner, timerid); } -void GLCanvas3D::ToolbarHighlighter::init(GLToolbarItem* toolbar_item, GLCanvas3D* canvas) +void GLCanvas3D::ToolbarHighlighter::init(const std::shared_ptr& toolbar_item, GLCanvas3D* canvas) { if (m_timer.IsRunning()) invalidate(); @@ -11211,22 +11295,23 @@ void GLCanvas3D::ToolbarHighlighter::invalidate() { m_timer.Stop(); - if (m_toolbar_item) { - m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::NotHighlighted); + if (const auto& p_toolbar_item = m_toolbar_item.lock()) { + p_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::NotHighlighted); } - m_toolbar_item = nullptr; + m_toolbar_item.reset(); m_blink_counter = 0; m_render_arrow = false; } void GLCanvas3D::ToolbarHighlighter::blink() { - if (m_toolbar_item) { - char state = m_toolbar_item->get_highlight(); + const auto& p_toolbar_item = m_toolbar_item.lock(); + if (p_toolbar_item) { + char state = p_toolbar_item->get_highlight(); if (state != (char)GLToolbarItem::EHighlightState::HighlightedShown) - m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedShown); + p_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedShown); else - m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedHidden); + p_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedHidden); m_render_arrow = !m_render_arrow; m_canvas->set_as_dirty(); @@ -11321,6 +11406,15 @@ ModelVolume *get_model_volume(const GLVolume &v, const ModelObject& object) { return object.volumes[volume_idx]; } +ModelVolume *get_selected_model_volume(const GLCanvas3D &canvas) +{ + auto gl_volume = get_selected_gl_volume(canvas); + if (gl_volume) { + return get_model_volume(*gl_volume, canvas.get_model()->objects); + } + return nullptr; +} + ModelVolume *get_model_volume(const GLVolume &v, const ModelObjectPtrs &objects) { if (v.object_idx() < 0) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a46128d..ca7ce00 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -8,7 +8,6 @@ #include #include -#include "GLToolbar.hpp" #include "Event.hpp" #include "Selection.hpp" #include "Gizmos/GLGizmosManager.hpp" @@ -59,6 +58,9 @@ namespace CustomGCode { struct Item; } namespace GUI { class PartPlateList; +class OpenGLManager; +class GLToolbar; +class GLToolbarItem; #if ENABLE_RETINA_GL class RetinaHelper; @@ -407,6 +409,7 @@ class GLCanvas3D FilamentUnPrintableOnFirstLayer, MixUsePLAAndPETG, PrimeTowerOutside, + NozzleFilamentIncompatible, AsemblyInvalid // for asembly view only }; @@ -564,6 +567,7 @@ public: int GetHoverId(); void set_ignore_left_up() { m_mouse.ignore_left_up = true; } + GLVolumeCollection &get_paint_outline_volumes() { return m_paint_outline_volumes; } private: bool m_is_dark = false; @@ -583,10 +587,8 @@ private: Mouse m_mouse; GLGizmosManager m_gizmos; //QDS: GUI refactor: GLToolbar - mutable GLToolbar m_main_toolbar; - mutable GLToolbar m_separator_toolbar; + mutable std::shared_ptr m_main_toolbar{ nullptr }; mutable IMToolbar m_sel_plate_toolbar; - mutable GLToolbar m_assemble_view_toolbar; mutable IMReturnToolbar m_return_toolbar; mutable Vec2i m_fit_camrea_button_pos = {128, 5}; mutable float m_sc{1}; @@ -604,6 +606,7 @@ private: bool m_extra_frame_requested; bool m_event_handlers_bound{ false }; + GLVolumeCollection m_paint_outline_volumes; GLVolumeCollection m_volumes; GCodeViewer m_gcode_viewer; @@ -747,11 +750,11 @@ public: struct ToolbarHighlighter { void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY); - void init(GLToolbarItem* toolbar_item, GLCanvas3D* canvas); + void init(const std::shared_ptr& toolbar_item, GLCanvas3D* canvas); void blink(); void invalidate(); bool m_render_arrow{ false }; - GLToolbarItem* m_toolbar_item{ nullptr }; + std::weak_ptr m_toolbar_item; private: GLCanvas3D* m_canvas{ nullptr }; int m_blink_counter{ 0 }; @@ -830,8 +833,8 @@ public: const Model* get_model() const { return m_model; } Model& get_ref_model() const { return *m_model; } - const Selection& get_selection() const { return m_selection; } - Selection& get_selection() { return m_selection; } + const Selection& get_selection() const; + Selection& get_selection(); const GLGizmosManager& get_gizmos_manager() const { return m_gizmos; } GLGizmosManager& get_gizmos_manager() { return m_gizmos; } @@ -854,6 +857,9 @@ public: bool get_use_clipping_planes() const { return m_use_clipping_planes; } const std::array &get_clipping_planes() const { return m_clipping_planes; }; + void set_use_color_clip_plane(bool use) { m_volumes.set_use_color_clip_plane(use); } + void set_color_clip_plane(const Vec3d &cp_normal, double offset) { m_volumes.set_color_clip_plane(cp_normal, offset); } + void set_color_clip_plane_colors(const std::array &colors) { m_volumes.set_color_clip_plane_colors(colors); } void set_color_by(const std::string& value); @@ -886,10 +892,7 @@ public: void _update_select_plate_toolbar_stats_item(bool force_selected = false); void reset_select_plate_toolbar_selection(); void enable_select_plate_toolbar(bool enable); - void clear_select_plate_toolbar_render_flag(); - void enable_assemble_view_toolbar(bool enable); void enable_return_toolbar(bool enable); - void enable_separator_toolbar(bool enable); void enable_dynamic_background(bool enable); void enable_labels(bool enable) { m_labels.enable(enable); } void enable_slope(bool enable) { m_slope.enable(enable); } @@ -907,13 +910,10 @@ public: //QDS: GUI refactor: GLToolbar&&gizmo int get_main_toolbar_offset() const; float get_main_toolbar_left(int cnv_width,float inv_zoom) const; - int get_main_toolbar_height() const { return m_main_toolbar.get_height(); } - int get_main_toolbar_width() const { return m_main_toolbar.get_width(); } - float get_assemble_view_toolbar_width() const { return m_assemble_view_toolbar.get_width(); } - float get_assemble_view_toolbar_height() const { return m_assemble_view_toolbar.get_height(); } + int get_main_toolbar_height() const; + int get_main_toolbar_width() const; + float get_main_toolbar_scale() const; float get_assembly_paint_toolbar_width() const { return m_paint_toolbar_width; } - float get_separator_toolbar_width() const { return m_separator_toolbar.get_width(); } - float get_separator_toolbar_height() const { return m_separator_toolbar.get_height(); } bool is_collapse_toolbar_on_left() const; float get_collapse_toolbar_width() const; float get_collapse_toolbar_height() const; @@ -967,7 +967,6 @@ public: void select_curr_plate_all(); void select_object_from_idx(std::vector& object_idxs); void remove_curr_plate_all(); - void update_plate_thumbnails(); void select_all(); void deselect_all(); @@ -1101,9 +1100,9 @@ public: void schedule_extra_frame(int miliseconds); - int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); } - void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); } - void force_main_toolbar_right_action(int item_id) { m_main_toolbar.force_right_action(item_id, *this); } + int get_main_toolbar_item_id(const std::string& name) const; + void force_main_toolbar_left_action(int item_id); + void force_main_toolbar_right_action(int item_id); bool has_toolpaths_to_export() const; void export_toolpaths_to_obj(const char* filename) const; @@ -1188,9 +1187,7 @@ private: bool _init_main_toolbar(); bool _init_select_plate_toolbar(); bool _update_imgui_select_plate_toolbar(); - bool _init_assemble_view_toolbar(); bool _init_return_toolbar(); - bool _init_separator_toolbar(); // QDS //bool _init_view_toolbar(); bool _init_collapse_toolbar(); @@ -1215,7 +1212,7 @@ private: void _render_platelist(bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true) const; void _render_plates_for_picking() const; //QDS: add outline drawing logic - void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline = true); + void _render_objects(GLVolumeCollection& cur_volumes, GLVolumeCollection::ERenderType type, bool with_outline = true,bool in_paint_gizmo = false); //QDS: GUI refactor: add canvas size as parameters void _render_gcode(int canvas_width, int canvas_height); //QDS: render a plane for assemble @@ -1230,14 +1227,10 @@ private: void _render_style_editor(); void _render_volumes_for_picking() const; void _render_current_gizmo() const; - void _render_gizmos_overlay(); void _render_main_toolbar(); void _render_imgui_select_plate_toolbar(); - void _render_assemble_view_toolbar() const; void _render_return_toolbar(); void _render_fit_camera_toolbar(); - void _render_separator_toolbar_right() const; - void _render_separator_toolbar_left() const; void _render_collapse_toolbar() const; // QDS //void _render_view_toolbar() const; @@ -1252,7 +1245,7 @@ private: void _render_selection_sidebar_hints() const; //QDS: GUI refactor: adjust main toolbar position bool _render_orient_menu(float left, float right, float bottom, float top); - bool _render_arrange_menu(float left, float right, float bottom, float top); + bool _render_arrange_menu(float left, float toolbar_height); void _render_3d_navigator(); bool can_show_3d_navigator(); void _update_volumes_hover_state(); @@ -1316,6 +1309,11 @@ private: void _init_unit_cube(); void _append_to_frame_callback(const FrameCallback& cb); + + void _render_toolbar(); + + const std::shared_ptr& get_main_toolbar() const; + static bool is_volume_in_plate_boundingbox(const GLVolume &v, int plate_idx, const BoundingBoxf3 &plate_build_volume); static void _init_fullscreen_mesh(); @@ -1334,6 +1332,7 @@ const ModelVolume *get_model_volume(const GLVolume &v, const Model &model); ModelVolume *get_model_volume(const ObjectID &volume_id, const ModelObjectPtrs &objects); ModelVolume *get_model_volume(const GLVolume &v, const ModelObjectPtrs &objects); ModelVolume *get_model_volume(const GLVolume &v, const ModelObject &object); +ModelVolume *get_selected_model_volume(const GLCanvas3D &canvas); GLVolume *get_first_hovered_gl_volume(const GLCanvas3D &canvas); GLVolume *get_selected_gl_volume(const GLCanvas3D &canvas); diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index a0c16b0..2c1ecf8 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -383,6 +383,16 @@ bool GLShaderProgram::set_uniform(const char* name, const ColorRGB& value) const return false; } +bool GLShaderProgram::set_uniform(const char *name, const ColorRGBA &value) const +{ + int id = get_uniform_location(name); + if (id >= 0) { + glsafe(::glUniform4fv(id, 1, static_cast(value.data()))); + return true; + } + return false; +} + int GLShaderProgram::get_attrib_location(const char* name) const { assert(m_id > 0); diff --git a/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp index d48eba8..71eddea 100644 --- a/src/slic3r/GUI/GLShader.hpp +++ b/src/slic3r/GUI/GLShader.hpp @@ -9,7 +9,7 @@ namespace Slic3r { class ColorRGB; - +class ColorRGBA; class GLShaderProgram { friend class GLShadersManager; @@ -63,7 +63,7 @@ public: bool set_uniform(const char* name, const Vec3f& value) const; bool set_uniform(const char* name, const Vec3d& value) const; bool set_uniform(const char* name, const ColorRGB& value) const; - + bool set_uniform(const char *name, const ColorRGBA& value) const; // returns -1 if not found int get_attrib_location(const char* name) const; // returns -1 if not found diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 400e39c..8a86aae 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -18,7 +18,7 @@ #include #include #include - +#include "FileHelp.hpp" #define STB_DXT_IMPLEMENTATION #include "stb_dxt/stb_dxt.h" @@ -171,12 +171,13 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, EC bool GLTexture::load_from_svg_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px) { reset(); - - if (!boost::filesystem::exists(filename)) + auto svg_file = filename; + Utils::slash_to_back_slash(svg_file); + if (!boost::filesystem::exists(svg_file)) return false; - if (boost::algorithm::iends_with(filename, ".svg")) - return load_from_svg(filename, use_mipmaps, compress, apply_anisotropy, max_size_px); + if (boost::algorithm::iends_with(svg_file, ".svg")) + return load_from_svg(svg_file, use_mipmaps, compress, apply_anisotropy, max_size_px); else return false; } @@ -1074,5 +1075,14 @@ GLModel& GLTexture::get_model_for_render_image() return s_model_for_render_image; } +BackgroundTexture::Metadata::Metadata() + : filename("") + , left(0) + , right(0) + , top(0) + , bottom(0) +{ +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index ff9f3c4..b49f575 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -152,6 +152,28 @@ namespace GUI { friend class Compressor; }; + struct BackgroundTexture + { + struct Metadata + { + // path of the file containing the background texture + std::string filename; + // size of the left edge, in pixels + unsigned int left; + // size of the right edge, in pixels + unsigned int right; + // size of the top edge, in pixels + unsigned int top; + // size of the bottom edge, in pixels + unsigned int bottom; + + Metadata(); + }; + + GLTexture texture; + Metadata metadata; + }; + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index fdcb61c..c7d49bb 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -35,6 +35,7 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_MULTI_APP, SimpleEvent); + wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); @@ -62,7 +63,7 @@ wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_ASSEMBLE, SimpleEvent); const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){}; const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; }; const GLToolbarItem::EnablingCallback GLToolbarItem::Default_Enabling_Callback = []()->bool { return true; }; -const GLToolbarItem::RenderCallback GLToolbarItem::Default_Render_Callback = [](float, float, float, float){}; +const GLToolbarItem::RenderCallback GLToolbarItem::Default_Render_Callback = [](float, float, float, float, float){}; GLToolbarItem::Data::Option::Option() : toggable(false) @@ -73,7 +74,6 @@ GLToolbarItem::Data::Option::Option() GLToolbarItem::Data::Data() : name("") - , icon_filename("") , tooltip("") , additional_tooltip("") , sprite_id(-1) @@ -89,6 +89,66 @@ GLToolbarItem::Data::Data() { } +const GLToolbarItem::Data& GLToolbarItem::get_data() const +{ + return m_data; +} + +void GLToolbarItem::set_visible(bool visible) +{ + m_data.visible = visible; +} + +GLToolbarItem::EType GLToolbarItem::get_type() const +{ + return m_type; +} + +bool GLToolbarItem::is_inside(const Vec2d& scaled_mouse_pos) const +{ + bool inside = (render_rect[0] <= (float)scaled_mouse_pos(0)) + && ((float)scaled_mouse_pos(0) <= render_rect[1]) + && (render_rect[2] <= (float)scaled_mouse_pos(1)) + && ((float)scaled_mouse_pos(1) <= render_rect[3]); + return inside; +} + +bool GLToolbarItem::is_collapsible() const +{ + return m_data.b_collapsible; +} + +bool GLToolbarItem::is_collapse_button() const +{ + return m_data.b_collapse_button; +} + +void GLToolbarItem::set_collapsed(bool value) +{ + if (!is_collapsible()) { + return; + } + m_data.b_collapsed = value; +} + +bool GLToolbarItem::is_collapsed() const +{ + if (!is_collapsible()) { + return false; + } + return m_data.b_collapsed; +} + +bool GLToolbarItem::recheck_pressed() const +{ + bool rt = false; + if (m_data.pressed_recheck_callback) { + const bool recheck_rt = m_data.pressed_recheck_callback(); + rt = (is_pressed() != recheck_rt); + } + return rt; +} + GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data) : m_type(type) , m_state(Normal) @@ -96,7 +156,6 @@ GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Dat , m_last_action_type(Undefined) , m_highlight_state(NotHighlighted) { - render_left_pos = 0.0f; } void GLToolbarItem::set_state(EState state) @@ -136,6 +195,47 @@ void GLToolbarItem::set_state(EState state) m_state = state; } +std::string GLToolbarItem::get_icon_filename(bool is_dark_mode) const +{ + if (m_data.icon_filename_callback) { + return m_data.icon_filename_callback(is_dark_mode); + } + return ""; +} + +void GLToolbarItem::set_last_action_type(GLToolbarItem::EActionType type) +{ + m_last_action_type = type; +} + +void GLToolbarItem::do_left_action() +{ + m_last_action_type = Left; + m_data.left.action_callback(); +} + +void GLToolbarItem::do_right_action() +{ + m_last_action_type = Right; + m_data.right.action_callback(); +} + +bool GLToolbarItem::is_visible() const +{ + bool rt = m_data.visible; + return rt; +} + +bool GLToolbarItem::toggle_disable_others() const +{ + return m_data.b_toggle_disable_others; +} + +bool GLToolbarItem::toggle_affectable() const +{ + return m_data.b_toggle_affectable; +} + bool GLToolbarItem::update_visibility() { bool visible = m_data.visibility_callback(); @@ -157,8 +257,11 @@ bool GLToolbarItem::update_enabled_state() } //QDS: GUI refactor: GLToolbar -void GLToolbarItem::render_text(float left, float right, float bottom, float top) const +void GLToolbarItem::render_text() const { + if (is_collapsed()) { + return; + } float tex_width = (float)m_data.text_texture.get_width(); float tex_height = (float)m_data.text_texture.get_height(); //float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; @@ -169,7 +272,7 @@ void GLToolbarItem::render_text(float left, float right, float bottom, float top float internal_top_uv = 0.0f; float internal_bottom_uv = (float)m_data.text_texture.m_original_height / tex_height; - GLTexture::render_sub_texture(m_data.text_texture.get_id(), left, right, bottom, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + GLTexture::render_sub_texture(m_data.text_texture.get_id(), render_rect[0], render_rect[1], render_rect[2], render_rect[3], {{internal_left_uv, internal_bottom_uv}, {internal_right_uv, internal_bottom_uv}, {internal_right_uv, internal_top_uv}, {internal_left_uv, internal_top_uv}}); } //QDS: GUI refactor: GLToolbar @@ -209,9 +312,9 @@ int GLToolbarItem::generate_image_texture() return ret; } -void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const +void GLToolbarItem::render(unsigned int tex_id, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size, float toolbar_height, bool b_flip_v) const { - auto uvs = [this](unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) -> GLTexture::Quad_UVs + auto uvs = [this](unsigned int tex_width, unsigned int tex_height, unsigned int icon_size, bool b_flip_v) -> GLTexture::Quad_UVs { assert((tex_width != 0) && (tex_height != 0)); GLTexture::Quad_UVs ret; @@ -229,6 +332,10 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b float right = left + du - u_offset; float top = v_offset + (float)m_data.sprite_id * dv; float bottom = top + dv - v_offset; + + if (b_flip_v) { + std::swap(top, bottom); + } ret.left_top = { left, top }; ret.left_bottom = { left, bottom }; ret.right_bottom = { right, bottom }; @@ -236,14 +343,22 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b return ret; }; - GLTexture::render_sub_texture(tex_id, left, right, bottom, top, uvs(tex_width, tex_height, icon_size)); + float* t_render_rect = render_rect; + if (is_visible()) { + if (!is_collapsed()) { + GLTexture::render_sub_texture(tex_id, render_rect[0], render_rect[1], render_rect[2], render_rect[3], uvs(tex_width, tex_height, icon_size, b_flip_v)); + } + else if (override_render_rect) { + t_render_rect = override_render_rect; + } + } if (is_pressed()) { if ((m_last_action_type == Left) && m_data.left.can_render()) - m_data.left.render_callback(left, right, bottom, top); + m_data.left.render_callback(t_render_rect[0], t_render_rect[1], t_render_rect[2], t_render_rect[3], toolbar_height); else if ((m_last_action_type == Right) && m_data.right.can_render()) - m_data.right.render_callback(left, right, bottom, top); + m_data.right.render_callback(t_render_rect[0], t_render_rect[1], t_render_rect[2], t_render_rect[3], toolbar_height); } } @@ -252,40 +367,36 @@ void GLToolbarItem::render_image(unsigned int tex_id, float left, float right, f GLTexture::Quad_UVs image_uvs = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } }; //GLTexture::Quad_UVs image_uvs = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } }; - GLTexture::render_sub_texture(tex_id, left, right, bottom, top, image_uvs); + if (is_visible()) { + GLTexture::render_sub_texture(tex_id, left, right, bottom, top, image_uvs); + } if (is_pressed()) { if ((m_last_action_type == Left) && m_data.left.can_render()) - m_data.left.render_callback(left, right, bottom, top); + m_data.left.render_callback(left, right, bottom, top, 0.0f); else if ((m_last_action_type == Right) && m_data.right.can_render()) - m_data.right.render_callback(left, right, bottom, top); + m_data.right.render_callback(left, right, bottom, top, 0.0f); } } -BackgroundTexture::Metadata::Metadata() - : filename("") - , left(0) - , right(0) - , top(0) - , bottom(0) -{ -} - const float GLToolbar::Default_Icons_Size = 40.0f; -GLToolbar::Layout::Layout() +ToolbarLayout::ToolbarLayout() : type(Horizontal) , horizontal_orientation(HO_Center) , vertical_orientation(VO_Center) + , position_mode(EPositionMode::TopMiddle) + , offset(0.0f) , top(0.0f) , left(0.0f) , border(0.0f) , separator_size(0.0f) , gap_size(0.0f) - , icons_size(Default_Icons_Size) + , icons_size(GLToolbar::Default_Icons_Size) , scale(1.0f) , width(0.0f) , height(0.0f) + , collapsed_offset(0.0f) , dirty(true) { } @@ -293,18 +404,12 @@ GLToolbar::Layout::Layout() GLToolbar::GLToolbar(GLToolbar::EType type, const std::string& name) : m_type(type) , m_name(name) - , m_enabled(false) - , m_icons_texture_dirty(true) , m_pressed_toggable_id(-1) { } GLToolbar::~GLToolbar() { - for (GLToolbarItem* item : m_items) - { - delete item; - } } bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture) @@ -338,17 +443,53 @@ bool GLToolbar::init_arrow(const BackgroundTexture::Metadata& arrow_texture) return res; } -GLToolbar::Layout::EType GLToolbar::get_layout_type() const +const ToolbarLayout& GLToolbar::get_layout() const { - return m_layout.type; + if (m_layout.dirty) { + calc_layout(); + } + return m_layout; } -void GLToolbar::set_layout_type(GLToolbar::Layout::EType type) +void GLToolbar::set_layout_type(ToolbarLayout::EType type) { + if (m_layout.type == type) { + return; + } m_layout.type = type; m_layout.dirty = true; } +ToolbarLayout::EHorizontalOrientation GLToolbar::get_horizontal_orientation() const +{ + return m_layout.horizontal_orientation; +} + +void GLToolbar::set_horizontal_orientation(ToolbarLayout::EHorizontalOrientation orientation) +{ + m_layout.horizontal_orientation = orientation; +} + +ToolbarLayout::EVerticalOrientation GLToolbar::get_vertical_orientation() const +{ + return m_layout.vertical_orientation; +} + +void GLToolbar::set_vertical_orientation(ToolbarLayout::EVerticalOrientation orientation) +{ + m_layout.vertical_orientation = orientation; +} + +void GLToolbar::set_position_mode(ToolbarLayout::EPositionMode t_position_mode) +{ + m_layout.position_mode = t_position_mode; +} + +void GLToolbar::set_offset(float offset) +{ + m_layout.offset = offset; +} + void GLToolbar::set_position(float top, float left) { m_layout.top = top; @@ -375,12 +516,12 @@ void GLToolbar::set_gap_size(float size) void GLToolbar::set_icons_size(float size) { - if (m_layout.icons_size != size) - { - m_layout.icons_size = size; - m_layout.dirty = true; - m_icons_texture_dirty = true; + if (abs(m_layout.icons_size - size) < 1e-6f) { + return; } + m_layout.icons_size = size; + m_layout.dirty = true; + m_icons_texture_dirty = true; } void GLToolbar::set_text_size(float size) @@ -401,42 +542,32 @@ void GLToolbar::set_scale(float scale) } } -//QDS: GUI refactor: GLToolbar -bool GLToolbar::add_item(const GLToolbarItem::Data& data, GLToolbarItem::EType type) +float GLToolbar::get_scale() const { - GLToolbarItem* item = new GLToolbarItem(type, data); - if (item == nullptr) - return false; - - m_items.push_back(item); - m_layout.dirty = true; - return true; + return m_layout.scale; } -bool GLToolbar::del_all_item() +void GLToolbar::set_icon_dirty() { - for (int i = 0; i < m_items.size(); i++) { - delete m_items[i]; - m_items[i] = nullptr; - } - m_items.clear(); - m_layout.dirty = true; - return true; + m_icons_texture_dirty = true; } -bool GLToolbar::add_separator() +bool GLToolbar::is_enabled() const { - GLToolbarItem::Data data; - GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, data); - if (item == nullptr) - return false; - - m_items.push_back(item); - m_layout.dirty = true; - return true; + return m_enabled; } -float GLToolbar::get_width() +void GLToolbar::set_enabled(bool enable) +{ + m_enabled = enable; +} + +float GLToolbar::get_icons_size() const +{ + return m_layout.icons_size; +} + +float GLToolbar::get_width() const { if (m_layout.dirty) calc_layout(); @@ -444,7 +575,7 @@ float GLToolbar::get_width() return m_layout.width; } -float GLToolbar::get_height() +float GLToolbar::get_height() const { if (m_layout.dirty) calc_layout(); @@ -452,12 +583,36 @@ float GLToolbar::get_height() return m_layout.height; } +bool GLToolbar::add_item(const GLToolbarItem::Data& data, GLToolbarItem::EType type) +{ + const auto item = std::make_shared(type, data); + m_items.emplace_back(item); + m_layout.dirty = true; + return true; +} + +bool GLToolbar::add_separator() +{ + GLToolbarItem::Data data; + const auto item = std::make_shared(GLToolbarItem::Separator, data); + m_items.push_back(item); + m_layout.dirty = true; + return true; +} + +bool GLToolbar::del_all_item() +{ + m_items.clear(); + m_layout.dirty = true; + return true; +} + void GLToolbar::select_item(const std::string& name) { if (is_item_disabled(name)) return; - for (GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (!item->is_disabled()) { @@ -469,7 +624,7 @@ void GLToolbar::select_item(const std::string& name) bool GLToolbar::is_item_pressed(const std::string& name) const { - for (const GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (item->get_name() == name) return item->is_pressed(); @@ -480,7 +635,7 @@ bool GLToolbar::is_item_pressed(const std::string& name) const bool GLToolbar::is_item_disabled(const std::string& name) const { - for (const GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (item->get_name() == name) return item->is_disabled(); @@ -491,7 +646,7 @@ bool GLToolbar::is_item_disabled(const std::string& name) const bool GLToolbar::is_item_visible(const std::string& name) const { - for (const GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (item->get_name() == name) return item->is_visible(); @@ -502,7 +657,7 @@ bool GLToolbar::is_item_visible(const std::string& name) const bool GLToolbar::is_any_item_pressed() const { - for (const GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (item->is_pressed()) return true; @@ -526,25 +681,41 @@ std::string GLToolbar::get_tooltip() const { std::string tooltip; - for (GLToolbarItem* item : m_items) + for (const auto& item : m_items) { + if (item->is_collapsed()) { + continue; + } if (item->is_hovered()) { - tooltip = item->get_tooltip(); - if (!item->is_enabled()) - { - const std::string& additional_tooltip = item->get_additional_tooltip(); - if (!additional_tooltip.empty()) - tooltip += ":\n" + additional_tooltip; - + const auto t_item_data = item->get_data(); + if (t_item_data.on_hover) { + tooltip = t_item_data.on_hover(); break; } + else { + tooltip = item->get_tooltip(); + if (!item->is_enabled()) + { + const std::string& additional_tooltip = item->get_additional_tooltip(); + if (!additional_tooltip.empty()) + tooltip += ":\n" + additional_tooltip; + + break; + } + } } } return tooltip; } +void GLToolbar::set_tooltip(int item_id, const std::string& text) +{ + if (0 <= item_id && item_id < (int)m_items.size()) + m_items[item_id]->set_tooltip(text); +} + void GLToolbar::get_additional_tooltip(int item_id, std::string& text) { if (0 <= item_id && item_id < (int)m_items.size()) @@ -562,10 +733,290 @@ void GLToolbar::set_additional_tooltip(int item_id, const std::string& text) m_items[item_id]->set_additional_tooltip(text); } -void GLToolbar::set_tooltip(int item_id, const std::string& text) +int GLToolbar::get_visible_items_cnt() const { - if (0 <= item_id && item_id < (int)m_items.size()) - m_items[item_id]->set_tooltip(text); + int cnt = 0; + for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + if (m_items[i]->is_visible() && !m_items[i]->is_separator()) + cnt++; + + return cnt; +} + +const std::shared_ptr& GLToolbar::get_item(const std::string& item_name) const +{ + if (m_enabled) + { + for (const auto& item : m_items) + { + if (item->get_name() == item_name) + { + return item; + } + } + } + static std::shared_ptr s_empty{ nullptr }; + return s_empty; +} + +void GLToolbar::calc_layout() const +{ + switch (m_layout.type) + { + default: + case ToolbarLayout::EType::Horizontal: + { + m_layout.width = get_width_horizontal(); + m_layout.height = get_height_horizontal(); + break; + } + case ToolbarLayout::EType::Vertical: + { + m_layout.width = get_width_vertical(); + m_layout.height = get_height_vertical(); + break; + } + } + + m_layout.dirty = false; +} + +const std::shared_ptr& GLToolbar::get_renderer() const +{ + if (!m_p_renderer || m_p_renderer->get_mode() != m_rendering_mode) { + switch (m_rendering_mode) { + case EToolbarRenderingMode::KeepSize: + m_p_renderer = std::make_shared(); + break; + case EToolbarRenderingMode::Auto: + default: + m_p_renderer = std::make_shared(); + break; + } + for (const auto& p_item : m_items) { + p_item->set_collapsed(false); + } + } + return m_p_renderer; +} + +float GLToolbar::get_width_horizontal() const +{ + float size = 2.0f * m_layout.border; + for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + { + if (!m_items[i]->is_visible()) + continue; + + if (m_items[i]->is_separator()) + size += m_layout.separator_size; + else if (m_items[i]->get_type() == GLToolbarItem::EType::SeparatorLine) { + size += ((float)m_layout.icons_size * 0.5f); + } + else + { + size += (float)m_layout.icons_size; + if (m_items[i]->is_action_with_text()) + size += m_items[i]->get_extra_size_ratio() * m_layout.icons_size; + if (m_items[i]->is_action_with_text_image()) + size += m_layout.text_size; + } + + if (i < m_items.size() - 1) { + size += m_layout.gap_size; + } + } + + return size * m_layout.scale; +} + +float GLToolbar::get_width_vertical() const +{ + float max_extra_text_size = 0.0; + for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + { + if (m_items[i]->is_action_with_text()) + { + float temp_size = m_items[i]->get_extra_size_ratio() * m_layout.icons_size; + + max_extra_text_size = (temp_size > max_extra_text_size) ? temp_size : max_extra_text_size; + } + + if (m_items[i]->is_action_with_text_image()) + { + max_extra_text_size = m_layout.text_size; + } + } + + return (2.0f * m_layout.border + m_layout.icons_size + max_extra_text_size) * m_layout.scale; +} + +float GLToolbar::get_height_horizontal() const +{ + return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale; +} + +float GLToolbar::get_height_vertical() const +{ + return get_main_size(); +} + +float GLToolbar::get_main_size() const +{ + float size = 2.0f * m_layout.border; + for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + { + if (!m_items[i]->is_visible()) + continue; + + if (m_items[i]->is_separator()) + size += m_layout.separator_size; + else + size += (float)m_layout.icons_size; + } + + if (m_items.size() > 1) + size += ((float)m_items.size() - 1.0f) * m_layout.gap_size; + + return size * m_layout.scale; +} + +bool GLToolbar::generate_icons_texture() const +{ + std::string path = resources_dir() + "/images/"; + std::vector filenames; + for (const auto& item : m_items) { + const std::string icon_filename = item->get_icon_filename(m_b_dark_mode_enabled); + if (!icon_filename.empty()) + filenames.push_back(path + icon_filename); + } + + std::vector> states; + //1: white only, 2: gray only, 0 : normal + //true/false: apply background or not + if (m_type == Normal) { + states.push_back({ 1, false }); // Normal + states.push_back({ 0, false }); // Pressed + states.push_back({ 2, false }); // Disabled + states.push_back({ 0, false }); // Hover + states.push_back({ 0, false }); // HoverPressed + states.push_back({ 2, false }); // HoverDisabled + states.push_back({ 0, false }); // HighlightedShown + states.push_back({ 2, false }); // HighlightedHidden + } + else { + states.push_back({ 1, false }); // Normal + states.push_back({ 0, true }); // Pressed + states.push_back({ 2, false }); // Disabled + states.push_back({ 0, false }); // Hover + states.push_back({ 1, true }); // HoverPressed + states.push_back({ 1, false }); // HoverDisabled + states.push_back({ 0, false }); // HighlightedShown + states.push_back({ 1, false }); // HighlightedHidden + } + + unsigned int sprite_size_px = (unsigned int)(m_layout.icons_size * m_layout.scale); + // // force even size + // if (sprite_size_px % 2 != 0) + // sprite_size_px += 1; + + bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, sprite_size_px, false); + if (res) + m_icons_texture_dirty = false; + + return res; +} + +bool GLToolbar::update_items_visibility() +{ + bool ret = false; + + for (const auto& item : m_items) { + ret |= item->update_visibility(); + } + + if (ret) + m_layout.dirty = true; + + // updates separators visibility to avoid having two of them consecutive + bool any_item_visible = false; + for (const auto& item : m_items) { + if (!item->is_separator()) + any_item_visible |= item->is_visible(); + else { + item->set_visible(any_item_visible); + any_item_visible = false; + } + } + + return ret; +} + +bool GLToolbar::update_items_enabled_state() +{ + bool ret = false; + + for (int i = 0; i < (int)m_items.size(); ++i) + { + const auto& item = m_items[i]; + ret |= item->update_enabled_state(); + if ((m_pressed_toggable_id != -1) && (m_pressed_toggable_id != i)) { + const auto& pressed_item = m_items[m_pressed_toggable_id]; + if (pressed_item->toggle_disable_others()) { + if (item->is_enabled() && item->toggle_affectable()) { + ret = true; + item->set_state(GLToolbarItem::Disabled); + } + } + } + } + + if (ret) + m_layout.dirty = true; + + return ret; +} + +bool GLToolbar::update_items_pressed_state() +{ + bool ret = false; + + for (int i = 0; i < (int)m_items.size(); ++i) + { + const auto& item = m_items[i]; + if (!item) { + continue; + } + + if (!item->recheck_pressed()) { + continue; + } + ret = true; + if (item->is_pressed()) { + item->set_state(GLToolbarItem::EState::Normal); + } + else { + item->set_state(GLToolbarItem::EState::Pressed); + m_pressed_toggable_id = i; + item->set_last_action_type(GLToolbarItem::EActionType::Left); + set_collapsed(); + } + } + + return ret; +} + +void GLToolbar::render(const Camera& t_camera) +{ + if (!m_enabled || m_items.empty()) + return; + + const auto& p_renderer = get_renderer(); + + if (!p_renderer) { + return; + } + p_renderer->render(*this, t_camera); } bool GLToolbar::update_items_state() @@ -573,29 +1024,102 @@ bool GLToolbar::update_items_state() bool ret = false; ret |= update_items_visibility(); ret |= update_items_enabled_state(); + ret |= update_items_pressed_state(); if (!is_any_item_pressed()) m_pressed_toggable_id = -1; return ret; } -void GLToolbar::render(const GLCanvas3D& parent,GLToolbarItem::EType type) +void GLToolbar::set_dark_mode_enabled(bool is_enabled) { - if (!m_enabled || m_items.empty()) + if (m_b_dark_mode_enabled == is_enabled) { return; - - if (m_icons_texture_dirty) - generate_icons_texture(); - - switch (m_layout.type) - { - default: - case Layout::Horizontal: { render_horizontal(parent,type); break; } - case Layout::Vertical: { render_vertical(parent); break; } } + + m_b_dark_mode_enabled = is_enabled; + set_icon_dirty(); } +const std::vector>& GLToolbar::get_items() const +{ + return m_items; +} +const GLTexture& GLToolbar::get_icon_texture() const +{ + if (m_icons_texture_dirty) { + generate_icons_texture(); + } + return m_icons_texture; +} + +const BackgroundTexture& GLToolbar::get_background_texture() const +{ + return m_background_texture; +} + +const BackgroundTexture& GLToolbar::get_arrow_texture() const +{ + return m_arrow_texture; +} + +bool GLToolbar::needs_collapsed() const +{ + const auto& p_renderer = get_renderer(); + if (!p_renderer) { + return false; + } + return p_renderer->needs_collapsed(); +} + +void GLToolbar::toggle_collapsed() +{ + m_b_collapsed = !m_b_collapsed; +} + +void GLToolbar::set_collapsed() +{ + m_b_collapsed = true; +} + +bool GLToolbar::is_collapsed() const +{ + return m_b_collapsed; +} + +void GLToolbar::set_collapsed_offset(uint32_t offset_in_pixel) +{ + m_layout.collapsed_offset = offset_in_pixel; + m_layout.dirty = true; +} + +uint32_t GLToolbar::get_collapsed_offset() +{ + return m_layout.collapsed_offset; +} + +GLToolbar::EToolbarRenderingMode GLToolbar::get_rendering_mode() +{ + return m_rendering_mode; +} + +void GLToolbar::set_rendering_mode(EToolbarRenderingMode mode) +{ + m_rendering_mode = mode; +} + +void GLToolbar::render_arrow(const std::weak_ptr& highlighted_item) +{ + if (!m_enabled || m_items.empty()) { + return; + } + const auto& p_renderer = get_renderer(); + if (!p_renderer) { + return; + } + p_renderer->render_arrow(*this, highlighted_item); +} bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) { @@ -657,11 +1181,25 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) m_mouse_capture.left = true; m_mouse_capture.parent = &parent; processed = true; - if (item_id != -2 && !m_items[item_id]->is_separator() && !m_items[item_id]->is_disabled() && - (m_pressed_toggable_id == -1 || m_items[item_id]->get_last_action_type() == GLToolbarItem::Left)) { + bool rt = item_id != -2 && !m_items[item_id]->is_separator() && !m_items[item_id]->is_disabled() && + (m_pressed_toggable_id == -1 + || m_items[item_id]->get_last_action_type() == GLToolbarItem::Left); + if (!rt) { + if (item_id >= 0 && item_id < m_items.size()) { + rt = !m_items[item_id]->toggle_affectable(); + } + } + if (!rt) { + if (m_pressed_toggable_id >= 0 && m_pressed_toggable_id < m_items.size()) { + rt = !m_items[m_pressed_toggable_id]->toggle_disable_others(); + } + } + if (rt) { // mouse is inside an icon do_action(GLToolbarItem::Left, item_id, parent, true); parent.set_as_dirty(); + evt.StopPropagation(); + processed = true; } } else if (evt.MiddleDown()) { @@ -677,6 +1215,8 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) // mouse is inside an icon do_action(GLToolbarItem::Right, item_id, parent, true); parent.set_as_dirty(); + evt.StopPropagation(); + processed = true; } } } @@ -684,179 +1224,80 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) return processed; } -void GLToolbar::calc_layout() -{ - switch (m_layout.type) - { - default: - case Layout::Horizontal: - { - m_layout.width = get_width_horizontal(); - m_layout.height = get_height_horizontal(); - break; - } - case Layout::Vertical: - { - m_layout.width = get_width_vertical(); - m_layout.height = get_height_vertical(); - break; - } - } - - m_layout.dirty = false; -} - -//QDS: GUI refactor: GLToolbar -float GLToolbar::get_width_horizontal() const -{ - float size = 2.0f * m_layout.border; - for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) - { - if (!m_items[i]->is_visible()) - continue; - - if (m_items[i]->is_separator()) - size += m_layout.separator_size; - else - { - size += (float)m_layout.icons_size; - if (m_items[i]->is_action_with_text()) - size += m_items[i]->get_extra_size_ratio() * m_layout.icons_size; - if (m_items[i]->is_action_with_text_image()) - size += m_layout.text_size; - } - } - - if (m_items.size() > 1) - size += ((float)m_items.size() - 1.0f) * m_layout.gap_size; - - return size * m_layout.scale; -} - -//QDS: GUI refactor: GLToolbar -float GLToolbar::get_width_vertical() const -{ - float max_extra_text_size = 0.0; - for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) - { - if (m_items[i]->is_action_with_text()) - { - float temp_size = m_items[i]->get_extra_size_ratio() * m_layout.icons_size; - - max_extra_text_size = (temp_size > max_extra_text_size) ? temp_size : max_extra_text_size; - } - - if (m_items[i]->is_action_with_text_image()) - { - max_extra_text_size = m_layout.text_size; - } - } - - return (2.0f * m_layout.border + m_layout.icons_size + max_extra_text_size) * m_layout.scale; -} - -float GLToolbar::get_height_horizontal() const -{ - return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale; -} - -float GLToolbar::get_height_vertical() const -{ - return get_main_size(); -} - -float GLToolbar::get_main_size() const -{ - float size = 2.0f * m_layout.border; - for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) - { - if (!m_items[i]->is_visible()) - continue; - - if (m_items[i]->is_separator()) - size += m_layout.separator_size; - else - size += (float)m_layout.icons_size; - } - - if (m_items.size() > 1) - size += ((float)m_items.size() - 1.0f) * m_layout.gap_size; - - return size * m_layout.scale; -} - -int GLToolbar::get_visible_items_cnt() const -{ - int cnt = 0; - for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) - if (m_items[i]->is_visible() && !m_items[i]->is_separator()) - cnt++; - - return cnt; -} - void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover) { - if ((m_pressed_toggable_id == -1) || (m_pressed_toggable_id == item_id)) - { - if ((0 <= item_id) && (item_id < (int)m_items.size())) - { - GLToolbarItem* item = m_items[item_id]; - if ((item != nullptr) && !item->is_separator() && !item->is_disabled() && (!check_hover || item->is_hovered())) - { - if (((type == GLToolbarItem::Right) && item->is_right_toggable()) || - ((type == GLToolbarItem::Left) && item->is_left_toggable())) - { - GLToolbarItem::EState state = item->get_state(); - if (state == GLToolbarItem::Hover) - item->set_state(GLToolbarItem::HoverPressed); - else if (state == GLToolbarItem::HoverPressed) - item->set_state(GLToolbarItem::Hover); - else if (state == GLToolbarItem::Pressed) - item->set_state(GLToolbarItem::Normal); - else if (state == GLToolbarItem::Normal) - item->set_state(GLToolbarItem::Pressed); - - m_pressed_toggable_id = item->is_pressed() ? item_id : -1; - item->reset_last_action_type(); - - parent.render(); - switch (type) - { - default: - case GLToolbarItem::Left: { item->do_left_action(); break; } - case GLToolbarItem::Right: { item->do_right_action(); break; } - } - } - else - { - if (m_type == Radio) - select_item(item->get_name()); - else - item->set_state(item->is_hovered() ? GLToolbarItem::HoverPressed : GLToolbarItem::Pressed); - - item->reset_last_action_type(); - parent.render(); - switch (type) - { - default: - case GLToolbarItem::Left: { item->do_left_action(); break; } - case GLToolbarItem::Right: { item->do_right_action(); break; } - } - if (item->get_continuous_click_flag()) { - item->set_state(GLToolbarItem::Hover); - parent.render(); - } - else if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled) && !item->get_continuous_click_flag()) - { - // the item may get disabled during the action, if not, set it back to normal state - item->set_state(GLToolbarItem::Normal); - parent.render(); - } - } - } - } + if (item_id < 0 || item_id >= (int)m_items.size()) { + return; } + const auto& item = m_items[item_id]; + if (!item || item->is_separator() || item->is_disabled() || (check_hover && !item->is_hovered())) { + return; + } + + auto do_item_action = [this](GLToolbarItem::EActionType type, const std::shared_ptr& item, int item_id, GLCanvas3D& parent)->void { + if (((type == GLToolbarItem::Right) && item->is_right_toggable()) || + ((type == GLToolbarItem::Left) && item->is_left_toggable())) + { + GLToolbarItem::EState state = item->get_state(); + if (state == GLToolbarItem::Hover) + item->set_state(GLToolbarItem::HoverPressed); + else if (state == GLToolbarItem::HoverPressed) + item->set_state(GLToolbarItem::Hover); + else if (state == GLToolbarItem::Pressed) + item->set_state(GLToolbarItem::Normal); + else if (state == GLToolbarItem::Normal) + item->set_state(GLToolbarItem::Pressed); + + m_pressed_toggable_id = item->is_pressed() ? item_id : -1; + item->reset_last_action_type(); + + switch (type) + { + default: + case GLToolbarItem::Left: { item->do_left_action(); break; } + case GLToolbarItem::Right: { item->do_right_action(); break; } + } + + parent.set_as_dirty(); + } + else + { + if (m_type == Radio) + select_item(item->get_name()); + else + item->set_state(item->is_hovered() ? GLToolbarItem::HoverPressed : GLToolbarItem::Pressed); + + item->reset_last_action_type(); + switch (type) + { + default: + case GLToolbarItem::Left: { item->do_left_action(); break; } + case GLToolbarItem::Right: { item->do_right_action(); break; } + } + if (item->get_continuous_click_flag()) { + item->set_state(GLToolbarItem::Hover); + } + else if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled) && !item->get_continuous_click_flag()) + { + // the item may get disabled during the action, if not, set it back to normal state + item->set_state(GLToolbarItem::Normal); + } + + parent.set_as_dirty(); + } + + if (item->is_collapse_button()) { + toggle_collapsed(); + } + else { + set_collapsed(); + } + }; + if ((m_pressed_toggable_id != -1) && (m_pressed_toggable_id != item_id)) + { + do_item_action(type, m_items[m_pressed_toggable_id], m_pressed_toggable_id, parent); + } + do_item_action(type, item, item_id, parent); } void GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent) @@ -864,793 +1305,111 @@ void GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent) if (!m_enabled) return; - switch (m_layout.type) - { - default: - case Layout::Horizontal: { update_hover_state_horizontal(mouse_pos, parent); break; } - case Layout::Vertical: { update_hover_state_vertical(mouse_pos, parent); break; } - } -} - -void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent) -{ - // NB: mouse_pos is already scaled appropriately - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = m_layout.scale * inv_zoom; - Size cnv_size = parent.get_canvas_size(); Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - - float separator_stride = scaled_separator_size + scaled_gap_size; - float icon_stride = scaled_icons_size + scaled_gap_size; - - float left = m_layout.left + scaled_border; - float top = m_layout.top - scaled_border; - - for (GLToolbarItem* item : m_items) + for (const auto& item : m_items) { if (!item->is_visible()) continue; - if (item->is_separator()) - left += separator_stride; - else - { - float right = left + scaled_icons_size; - float bottom = top - scaled_icons_size; - - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - right += scaled_icons_size * item->get_extra_size_ratio(); - GLToolbarItem::EState state = item->get_state(); - bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); - - switch (state) - { - case GLToolbarItem::Normal: - { - if (inside) - { - item->set_state(GLToolbarItem::Hover); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Hover: - { - if (!inside) - { - item->set_state(GLToolbarItem::Normal); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Pressed: - { - if (inside) - { - item->set_state(GLToolbarItem::HoverPressed); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::HoverPressed: - { - if (!inside) - { - item->set_state(GLToolbarItem::Pressed); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Disabled: - { - if (inside) - { - item->set_state(GLToolbarItem::HoverDisabled); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::HoverDisabled: - { - if (!inside) - { - item->set_state(GLToolbarItem::Disabled); - parent.set_as_dirty(); - } - - break; - } - default: - { - break; - } - } - - left += icon_stride; - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - left += scaled_icons_size * item->get_extra_size_ratio(); - } - } -} - -void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent) -{ - // NB: mouse_pos is already scaled appropriately - - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = m_layout.scale * inv_zoom; - - Size cnv_size = parent.get_canvas_size(); - Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - float separator_stride = scaled_separator_size + scaled_gap_size; - float icon_stride = scaled_icons_size + scaled_gap_size; - - float left = m_layout.left + scaled_border; - float top = m_layout.top - scaled_border; - - for (GLToolbarItem* item : m_items) - { - if (!item->is_visible()) + if (item->is_separator()) { continue; + } - if (item->is_separator()) - top -= separator_stride; - else + if (item->get_type() == GLToolbarItem::EType::SeparatorLine) { + continue; + } + bool inside = item->is_inside(scaled_mouse_pos); + GLToolbarItem::EState state = item->get_state(); + switch (state) { - float right = left + scaled_icons_size; - float bottom = top - scaled_icons_size; - - if (item->is_action_with_text_image()) - right += m_layout.text_size * factor; - - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - right += scaled_icons_size * item->get_extra_size_ratio(); - - GLToolbarItem::EState state = item->get_state(); - bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); - - switch (state) + case GLToolbarItem::Normal: + { + if (inside) { - case GLToolbarItem::Normal: - { - if (inside) - { - item->set_state(GLToolbarItem::Hover); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Hover: - { - if (!inside) - { - item->set_state(GLToolbarItem::Normal); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Pressed: - { - if (inside) - { - item->set_state(GLToolbarItem::HoverPressed); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::HoverPressed: - { - if (!inside) - { - item->set_state(GLToolbarItem::Pressed); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::Disabled: - { - if (inside) - { - item->set_state(GLToolbarItem::HoverDisabled); - parent.set_as_dirty(); - } - - break; - } - case GLToolbarItem::HoverDisabled: - { - if (!inside) - { - item->set_state(GLToolbarItem::Disabled); - parent.set_as_dirty(); - } - - break; - } - default: - { - break; - } + item->set_state(GLToolbarItem::Hover); + parent.set_as_dirty(); } - top -= icon_stride; + break; + } + case GLToolbarItem::Hover: + { + if (!inside) + { + item->set_state(GLToolbarItem::Normal); + parent.set_as_dirty(); + } + + break; + } + case GLToolbarItem::Pressed: + { + if (inside) + { + item->set_state(GLToolbarItem::HoverPressed); + parent.set_as_dirty(); + } + + break; + } + case GLToolbarItem::HoverPressed: + { + if (!inside) + { + item->set_state(GLToolbarItem::Pressed); + parent.set_as_dirty(); + } + + break; + } + case GLToolbarItem::Disabled: + { + if (inside) + { + item->set_state(GLToolbarItem::HoverDisabled); + parent.set_as_dirty(); + } + + break; + } + case GLToolbarItem::HoverDisabled: + { + if (!inside) + { + item->set_state(GLToolbarItem::Disabled); + parent.set_as_dirty(); + } + + break; + } + default: + { + break; + } } } } -GLToolbarItem* GLToolbar::get_item(const std::string& item_name) -{ - if (!m_enabled) - return nullptr; - - for (GLToolbarItem* item : m_items) - { - if (item->get_name() == item_name) - { - return item; - } - } - return nullptr; -} - int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const { if (!m_enabled) return -1; - switch (m_layout.type) - { - default: - case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); } - case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); } - } -} - -int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const -{ - // NB: mouse_pos is already scaled appropriately - - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = m_layout.scale * inv_zoom; - - Size cnv_size = parent.get_canvas_size(); - Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - - float left = m_layout.left + scaled_border; - float top = m_layout.top - scaled_border; - - - for (size_t id=0; idis_visible()) + for (size_t i = 0; i < m_items.size(); ++i) { + if (m_items[i]->is_collapsed()) { continue; - - if (item->is_separator()) - { - float right = left + scaled_separator_size; - float bottom = top - scaled_icons_size; - - // mouse inside the separator - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return id; - - left = right; - right += scaled_gap_size; - - if (id < m_items.size() - 1) - { - // mouse inside the gap - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return -2; - } - - left = right; } - else - { - float right = left + scaled_icons_size; - float bottom = top - scaled_icons_size; - - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - right += scaled_icons_size * item->get_extra_size_ratio(); - - // mouse inside the icon - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return id; - - left = right; - right += scaled_gap_size; - - if (id < m_items.size() - 1) - { - // mouse inside the gap - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return -2; - } - - left = right; + if (m_items[i]->is_hovered()) { + return i; } } return -1; } -int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const -{ - // NB: mouse_pos is already scaled appropriately - - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = m_layout.scale * inv_zoom; - - Size cnv_size = parent.get_canvas_size(); - Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - - float left = m_layout.left + scaled_border; - float top = m_layout.top - scaled_border; - - for (size_t id=0; idis_visible()) - continue; - - if (item->is_separator()) - { - float right = left + scaled_icons_size; - float bottom = top - scaled_separator_size; - - // mouse inside the separator - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return id; - - top = bottom; - bottom -= scaled_gap_size; - - if (id < m_items.size() - 1) - { - // mouse inside the gap - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return -2; - } - - top = bottom; - } - else - { - float right = left + scaled_icons_size; - float bottom = top - scaled_icons_size; - - if (item->is_action_with_text_image()) - right += m_layout.text_size * factor; - - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - right += scaled_icons_size * item->get_extra_size_ratio(); - - // mouse inside the icon - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return id; - - top = bottom; - bottom -= scaled_gap_size; - - if (id < m_items.size() - 1) - { - // mouse inside the gap - if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) - return -2; - } - - top = bottom; - } - } - - return -1; -} - -void GLToolbar::render_background(float left, float top, float right, float bottom, float border) const -{ - unsigned int tex_id = m_background_texture.texture.get_id(); - float tex_width = (float)m_background_texture.texture.get_width(); - float tex_height = (float)m_background_texture.texture.get_height(); - if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0)) - { - float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; - float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; - - float internal_left = left + border; - float internal_right = right - border; - float internal_top = top - border; - float internal_bottom = bottom + border; - - float left_uv = 0.0f; - float right_uv = 1.0f; - float top_uv = 1.0f; - float bottom_uv = 0.0f; - - float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width; - float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width; - float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height; - float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height; - - // top-left corner - if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Top)) - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { left_uv, internal_top_uv }, { internal_left_uv, internal_top_uv }, { internal_left_uv, top_uv }, { left_uv, top_uv } }); - - // top edge - if (m_layout.vertical_orientation == Layout::VO_Top) - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } }); - - // top-right corner - if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Top)) - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } }); - - // center-left edge - if (m_layout.horizontal_orientation == Layout::HO_Left) - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { left_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv }, { internal_left_uv, internal_top_uv }, { left_uv, internal_top_uv } }); - - // center - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - // center-right edge - if (m_layout.horizontal_orientation == Layout::HO_Right) - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } }); - - // bottom-left corner - if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Bottom)) - GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { left_uv, bottom_uv }, { internal_left_uv, bottom_uv }, { internal_left_uv, internal_bottom_uv }, { left_uv, internal_bottom_uv } }); - - // bottom edge - if (m_layout.vertical_orientation == Layout::VO_Bottom) - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); - - // bottom-right corner - if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Bottom)) - GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - else - GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } }); - } -} - -void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item) -{ - // arrow texture not initialized - if (m_arrow_texture.texture.get_id() == 0) - return; - - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = inv_zoom * m_layout.scale; - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float border = m_layout.border * factor; - - float separator_stride = scaled_separator_size + scaled_gap_size; - float icon_stride = scaled_icons_size + scaled_gap_size; - - float left = m_layout.left; - float top = m_layout.top - icon_stride; - - bool found = false; - for (const GLToolbarItem* item : m_items) { - if (!item->is_visible()) - continue; - - if (item->is_separator()) - left += separator_stride; - else { - if (item->get_name() == highlighted_item->get_name()) { - found = true; - break; - } - left += icon_stride; - } - } - if (!found) - return; - - left += border; - top -= separator_stride; - float right = left + scaled_icons_size; - - unsigned int tex_id = m_arrow_texture.texture.get_id(); - // arrow width and height - float arr_tex_width = (float)m_arrow_texture.texture.get_width(); - float arr_tex_height = (float)m_arrow_texture.texture.get_height(); - if ((tex_id != 0) && (arr_tex_width > 0) && (arr_tex_height > 0)) { - float inv_tex_width = (arr_tex_width != 0.0f) ? 1.0f / arr_tex_width : 0.0f; - float inv_tex_height = (arr_tex_height != 0.0f) ? 1.0f / arr_tex_height : 0.0f; - - float internal_left = left + border - scaled_icons_size * 1.5f; // add scaled_icons_size for huge arrow - float internal_right = right - border + scaled_icons_size * 1.5f; - float internal_top = top - border; - // bottom is not moving and should be calculated from arrow texture sides ratio - float arrow_sides_ratio = (float)m_arrow_texture.texture.get_height() / (float)m_arrow_texture.texture.get_width(); - float internal_bottom = internal_top - (internal_right - internal_left) * arrow_sides_ratio ; - - float internal_left_uv = (float)m_arrow_texture.metadata.left * inv_tex_width; - float internal_right_uv = 1.0f - (float)m_arrow_texture.metadata.right * inv_tex_width; - float internal_top_uv = 1.0f - (float)m_arrow_texture.metadata.top * inv_tex_height; - float internal_bottom_uv = (float)m_arrow_texture.metadata.bottom * inv_tex_height; - - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); - } -} - -void GLToolbar::render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType type) -{ - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = inv_zoom * m_layout.scale; - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - float scaled_width = get_width() * inv_zoom; - float scaled_height = get_height() * inv_zoom; - - float separator_stride = scaled_separator_size + scaled_gap_size; - float icon_stride = scaled_icons_size + scaled_gap_size; - - float left = m_layout.left; - float top = m_layout.top; - float right = left + scaled_width; - if (type == GLToolbarItem::SeparatorLine) - right = left + scaled_width * 0.5; - float bottom = top - scaled_height; - - render_background(left, top, right, bottom, scaled_border); - - left += scaled_border; - top -= scaled_border; - - // renders icons - for (const GLToolbarItem* item : m_items) - { - if (!item->is_visible()) - continue; - - if (item->is_separator()) - left += separator_stride; - else - { - //QDS GUI refactor - item->render_left_pos = left; - if (!item->is_action_with_text_image()) { - unsigned int tex_id = m_icons_texture.get_id(); - int tex_width = m_icons_texture.get_width(); - int tex_height = m_icons_texture.get_height(); - if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) - return; - item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); - } - //QDS: GUI refactor: GLToolbar - if (item->is_action_with_text()) - { - float scaled_text_size = item->get_extra_size_ratio() * scaled_icons_size; - item->render_text(left + scaled_icons_size, left + scaled_icons_size + scaled_text_size, top - scaled_icons_size, top); - left += scaled_text_size; - } - left += icon_stride; - } - } -} - -void GLToolbar::render_vertical(const GLCanvas3D& parent) -{ - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float factor = inv_zoom * m_layout.scale; - - float scaled_icons_size = m_layout.icons_size * factor; - float scaled_separator_size = m_layout.separator_size * factor; - float scaled_gap_size = m_layout.gap_size * factor; - float scaled_border = m_layout.border * factor; - float scaled_width = get_width() * inv_zoom; - float scaled_height = get_height() * inv_zoom; - - float separator_stride = scaled_separator_size + scaled_gap_size; - float icon_stride = scaled_icons_size + scaled_gap_size; - - float left = m_layout.left; - float top = m_layout.top; - float right = left + scaled_width; - float bottom = top - scaled_height; - - render_background(left, top, right, bottom, scaled_border); - - left += scaled_border; - top -= scaled_border; - - // renders icons - for (const GLToolbarItem* item : m_items) { - if (!item->is_visible()) - continue; - - if (item->is_separator()) - top -= separator_stride; - else { - unsigned int tex_id; - int tex_width, tex_height; - if (item->is_action_with_text_image()) { - float scaled_text_size = m_layout.text_size * factor; - float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; - float scaled_text_border = 2.5 * factor; - float scaled_text_height = scaled_icons_size / 2.0f; - item->render_text(left, left + scaled_text_size, top - scaled_text_border - scaled_text_height, top - scaled_text_border); - - float image_left = left + scaled_text_size; - tex_id = item->m_data.image_texture.get_id(); - tex_width = item->m_data.image_texture.get_width(); - tex_height = item->m_data.image_texture.get_height(); - if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) - return; - item->render_image(tex_id, image_left, image_left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); - } - else { - tex_id = m_icons_texture.get_id(); - tex_width = m_icons_texture.get_width(); - tex_height = m_icons_texture.get_height(); - if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) - return; - item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale)); - //QDS: GUI refactor: GLToolbar - } - if (item->is_action_with_text()) - { - float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; - float scaled_text_height = scaled_icons_size; - item->render_text(left + scaled_icons_size, left + scaled_icons_size + scaled_text_width, top - scaled_text_height, top); - } - top -= icon_stride; - } - } -} - -bool GLToolbar::generate_icons_texture() -{ - std::string path = resources_dir() + "/images/"; - std::vector filenames; - for (GLToolbarItem* item : m_items) { - const std::string& icon_filename = item->get_icon_filename(); - if (!icon_filename.empty()) - filenames.push_back(path + icon_filename); - } - - std::vector> states; - //1: white only, 2: gray only, 0 : normal - //true/false: apply background or not - if (m_type == Normal) { - states.push_back({ 1, false }); // Normal - states.push_back({ 0, false }); // Pressed - states.push_back({ 2, false }); // Disabled - states.push_back({ 0, false }); // Hover - states.push_back({ 0, false }); // HoverPressed - states.push_back({ 2, false }); // HoverDisabled - states.push_back({ 0, false }); // HighlightedShown - states.push_back({ 2, false }); // HighlightedHidden - } - else { - states.push_back({ 1, false }); // Normal - states.push_back({ 0, true }); // Pressed - states.push_back({ 2, false }); // Disabled - states.push_back({ 0, false }); // Hover - states.push_back({ 1, true }); // HoverPressed - states.push_back({ 1, false }); // HoverDisabled - states.push_back({ 0, false }); // HighlightedShown - states.push_back({ 1, false }); // HighlightedHidden - } - - unsigned int sprite_size_px = (unsigned int)(m_layout.icons_size * m_layout.scale); -// // force even size -// if (sprite_size_px % 2 != 0) -// sprite_size_px += 1; - - bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, sprite_size_px, false); - if (res) - m_icons_texture_dirty = false; - - return res; -} - -bool GLToolbar::update_items_visibility() -{ - bool ret = false; - - for (GLToolbarItem* item : m_items) { - ret |= item->update_visibility(); - } - - if (ret) - m_layout.dirty = true; - - // updates separators visibility to avoid having two of them consecutive - bool any_item_visible = false; - for (GLToolbarItem* item : m_items) { - if (!item->is_separator()) - any_item_visible |= item->is_visible(); - else { - item->set_visible(any_item_visible); - any_item_visible = false; - } - } - - return ret; -} - -bool GLToolbar::update_items_enabled_state() -{ - bool ret = false; - - for (int i = 0; i < (int)m_items.size(); ++i) - { - GLToolbarItem* item = m_items[i]; - ret |= item->update_enabled_state(); - if (item->is_enabled() && (m_pressed_toggable_id != -1) && (m_pressed_toggable_id != i)) - { - ret = true; - item->set_state(GLToolbarItem::Disabled); - } - } - - if (ret) - m_layout.dirty = true; - - return ret; -} - //QDS: GUI refactor: GLToolbar int GLToolbar::generate_button_text_textures(wxFont& font) { @@ -1658,7 +1417,7 @@ int GLToolbar::generate_button_text_textures(wxFont& font) for (int i = 0; i < (int)m_items.size(); ++i) { - GLToolbarItem* item = m_items[i]; + const auto& item = m_items[i]; if (item->is_action_with_text()) { @@ -1679,7 +1438,7 @@ int GLToolbar::generate_image_textures() int ret = 0; for (int i = 0; i < (int)m_items.size(); ++i) { - GLToolbarItem* item = m_items[i]; + const auto& item = m_items[i]; if (item->is_action_with_text_image()) { ret |= item->generate_image_texture(); } @@ -1693,5 +1452,930 @@ float GLToolbar::get_scaled_icon_size() return m_layout.icons_size * m_layout.scale; } +ToolbarRenderer::ToolbarRenderer() +{ +} + +ToolbarRenderer::~ToolbarRenderer() +{ +} + +bool ToolbarRenderer::needs_collapsed() const +{ + return false; +} + +ToolbarAutoSizeRenderer::ToolbarAutoSizeRenderer() +{ +} + +ToolbarAutoSizeRenderer::~ToolbarAutoSizeRenderer() +{ +} + +void ToolbarAutoSizeRenderer::render(const GLToolbar& t_toolbar, const Camera& t_camera) +{ + const auto& t_layout = t_toolbar.get_layout(); + switch (t_layout.type) + { + default: + case ToolbarLayout::EType::Horizontal: { render_horizontal(t_toolbar, t_camera); break; } + case ToolbarLayout::EType::Vertical: { render_vertical(t_toolbar, t_camera); break; } + } +} + +GLToolbar::EToolbarRenderingMode ToolbarAutoSizeRenderer::get_mode() const +{ + return GLToolbar::EToolbarRenderingMode::Auto; +} + +void ToolbarAutoSizeRenderer::render_horizontal(const GLToolbar& t_toolbar, const Camera& t_camera) +{ + const auto& t_layout = t_toolbar.get_layout(); + float inv_zoom = (float)t_camera.get_inv_zoom(); + float factor = inv_zoom * t_layout.scale; + + float scaled_icons_size = t_layout.icons_size * factor; + float scaled_separator_size = t_layout.separator_size * factor; + float scaled_gap_size = t_layout.gap_size * factor; + float scaled_border = t_layout.border * factor; + float scaled_width = t_toolbar.get_width() * inv_zoom; + float scaled_height = t_toolbar.get_height() * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = 0.0f; + float top = 0.0f; + calculate_position(t_toolbar, t_camera, left, top); + float right = left + scaled_width; + float bottom = top - scaled_height; + + render_background(t_toolbar, left, top, right, bottom, scaled_border); + + left += scaled_border; + top -= scaled_border; + + // renders icons + const auto& t_items = t_toolbar.get_items(); + const auto& t_icon_texture = t_toolbar.get_icon_texture(); + for (const auto& item : t_items) + { + if (!item->is_visible()) + continue; + + if (item->is_separator()) + left += separator_stride; + else + { + if (!item->is_action_with_text_image()) { + unsigned int tex_id = t_icon_texture.get_id(); + int tex_width = t_icon_texture.get_width(); + int tex_height = t_icon_texture.get_height(); + if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) + return; + item->render_rect[0] = left; + item->render_rect[1] = left + scaled_icons_size; + item->render_rect[2] = top - scaled_icons_size; + item->render_rect[3] = top; + item->render(tex_id, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(t_layout.icons_size * t_layout.scale), t_toolbar.get_height()); + } + //QDS: GUI refactor: GLToolbar + if (item->is_action_with_text()) + { + float scaled_text_size = item->get_extra_size_ratio() * scaled_icons_size; + item->render_rect[0] = left + scaled_icons_size; + item->render_rect[1] = left + scaled_icons_size + scaled_text_size; + item->render_rect[2] = top - scaled_icons_size; + item->render_rect[3] = top; + item->render_text(); + left += scaled_text_size; + } + if (item->get_type() == GLToolbarItem::EType::SeparatorLine) { + left += (icon_stride - 0.5f * scaled_icons_size); + } + else { + left += icon_stride; + } + } + } +} + +void ToolbarAutoSizeRenderer::render_vertical(const GLToolbar& t_toolbar, const Camera& t_camera) +{ + const auto& t_layout = t_toolbar.get_layout(); + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float factor = inv_zoom * t_layout.scale; + + float scaled_icons_size = t_layout.icons_size * factor; + float scaled_separator_size = t_layout.separator_size * factor; + float scaled_gap_size = t_layout.gap_size * factor; + float scaled_border = t_layout.border * factor; + float scaled_width = t_toolbar.get_width() * inv_zoom; + float scaled_height = t_toolbar.get_height() * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = 0.0f; + float top = 0.0f; + calculate_position(t_toolbar, t_camera, left, top); + float right = left + scaled_width; + float bottom = top - scaled_height; + + render_background(t_toolbar, left, top, right, bottom, scaled_border); + + left += scaled_border; + top -= scaled_border; + + // renders icons + const auto& t_items = t_toolbar.get_items(); + const auto& t_icon_texture = t_toolbar.get_icon_texture(); + for (const auto& item : t_items) { + if (!item->is_visible()) + continue; + + if (item->is_separator()) + top -= separator_stride; + else { + unsigned int tex_id; + int tex_width, tex_height; + if (item->is_action_with_text_image()) { + float scaled_text_size = t_layout.text_size * factor; + float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; + float scaled_text_border = 2.5 * factor; + float scaled_text_height = scaled_icons_size / 2.0f; + item->render_rect[0] = left; + item->render_rect[1] = left + scaled_text_size; + item->render_rect[2] = top - scaled_text_border - scaled_text_height; + item->render_rect[3] = top - scaled_text_border; + item->render_text(); + + float image_left = left + scaled_text_size; + const auto& item_data = item->get_data(); + tex_id = item_data.image_texture.get_id(); + tex_width = item_data.image_texture.get_width(); + tex_height = item_data.image_texture.get_height(); + if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) + return; + item->render_image(tex_id, image_left, image_left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(t_layout.icons_size * t_layout.scale)); + } + else { + tex_id = t_icon_texture.get_id(); + tex_width = t_icon_texture.get_width(); + tex_height = t_icon_texture.get_height(); + if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) + return; + item->render_rect[0] = left; + item->render_rect[1] = left + scaled_icons_size; + item->render_rect[2] = top - scaled_icons_size; + item->render_rect[3] = top; + item->render(tex_id, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(t_layout.icons_size * t_layout.scale), t_toolbar.get_width()); + //QDS: GUI refactor: GLToolbar + } + if (item->is_action_with_text()) + { + float scaled_text_width = item->get_extra_size_ratio() * scaled_icons_size; + float scaled_text_height = scaled_icons_size; + + item->render_rect[0] = left + scaled_icons_size; + item->render_rect[1] = left + scaled_icons_size + scaled_text_width; + item->render_rect[2] = top - scaled_text_height; + item->render_rect[3] = top; + item->render_text(); + } + top -= icon_stride; + if (item->get_type() == GLToolbarItem::EType::SeparatorLine) { + top -= (icon_stride - 0.5f * scaled_icons_size); + } + else { + top -= icon_stride; + } + } + } +} + +void ToolbarAutoSizeRenderer::render_background(const GLToolbar& t_toolbar, float left, float top, float right, float bottom, float border) const +{ + const auto& t_background_texture = t_toolbar.get_background_texture(); + unsigned int tex_id = t_background_texture.texture.get_id(); + float tex_width = (float)t_background_texture.texture.get_width(); + float tex_height = (float)t_background_texture.texture.get_height(); + if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0)) + { + float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; + float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; + + float internal_left = left + border; + float internal_right = right - border; + float internal_top = top - border; + float internal_bottom = bottom + border; + + float left_uv = 0.0f; + float right_uv = 1.0f; + float top_uv = 1.0f; + float bottom_uv = 0.0f; + + float internal_left_uv = (float)t_background_texture.metadata.left * inv_tex_width; + float internal_right_uv = 1.0f - (float)t_background_texture.metadata.right * inv_tex_width; + float internal_top_uv = 1.0f - (float)t_background_texture.metadata.top * inv_tex_height; + float internal_bottom_uv = (float)t_background_texture.metadata.bottom * inv_tex_height; + + const auto& t_layout = t_toolbar.get_layout(); + // top-left corner + if ((t_layout.horizontal_orientation == ToolbarLayout::HO_Left) || (t_layout.vertical_orientation == ToolbarLayout::VO_Top)) + GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { left_uv, internal_top_uv }, { internal_left_uv, internal_top_uv }, { internal_left_uv, top_uv }, { left_uv, top_uv } }); + + // top edge + if (t_layout.vertical_orientation == ToolbarLayout::VO_Top) + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } }); + + // top-right corner + if ((t_layout.horizontal_orientation == ToolbarLayout::HO_Right) || (t_layout.vertical_orientation == ToolbarLayout::VO_Top)) + GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } }); + + // center-left edge + if (t_layout.horizontal_orientation == ToolbarLayout::HO_Left) + GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { left_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv }, { internal_left_uv, internal_top_uv }, { left_uv, internal_top_uv } }); + + // center + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + + // center-right edge + if (t_layout.horizontal_orientation == ToolbarLayout::HO_Right) + GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } }); + + // bottom-left corner + if ((t_layout.horizontal_orientation == ToolbarLayout::HO_Left) || (t_layout.vertical_orientation == ToolbarLayout::VO_Bottom)) + GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { left_uv, bottom_uv }, { internal_left_uv, bottom_uv }, { internal_left_uv, internal_bottom_uv }, { left_uv, internal_bottom_uv } }); + + // bottom edge + if (t_layout.vertical_orientation == ToolbarLayout::VO_Bottom) + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); + + // bottom-right corner + if ((t_layout.horizontal_orientation == ToolbarLayout::HO_Right) || (t_layout.vertical_orientation == ToolbarLayout::VO_Bottom)) + GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); + else + GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } }); + } +} + +void ToolbarAutoSizeRenderer::calculate_position(const GLToolbar& t_toolbar, const Camera& t_camera, float& left, float& top) +{ + const auto& t_layout = t_toolbar.get_layout(); + switch (t_layout.position_mode) { + case ToolbarLayout::EPositionMode::TopLeft: + { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + top = 0.5f * (float)t_viewport[3] * inv_zoom; + left = -0.5f * (float)t_viewport[2] * inv_zoom; + + break; + } + case ToolbarLayout::EPositionMode::TopMiddle: + { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + const auto cnv_width = t_viewport[2]; + const auto cnv_height = t_viewport[3]; + top = 0.5f * (float)cnv_height * inv_zoom; + left = -0.5f * (float)cnv_width * inv_zoom; + const auto final_width = t_toolbar.get_width() + t_layout.offset; + if (cnv_width < final_width) { + left += (t_layout.offset * inv_zoom); + } + else { + const float offset = (cnv_width - final_width) / 2.f; + left += (offset + t_layout.offset) * inv_zoom; + } + + break; + } + case ToolbarLayout::EPositionMode::Custom: + default: + { + left = t_layout.left; + top = t_layout.top; + break; + } + } +} + +void ToolbarAutoSizeRenderer::render_arrow(const GLToolbar& t_toolbar, const std::weak_ptr& highlighted_item) +{ + const auto p_item = highlighted_item.lock(); + if (!p_item) { + return; + } + const auto& t_arrow_texture = t_toolbar.get_arrow_texture(); + // arrow texture not initialized + if (t_arrow_texture.texture.get_id() == 0) + return; + + const auto& t_layout = t_toolbar.get_layout(); + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float factor = inv_zoom * t_layout.scale; + + float scaled_icons_size = t_layout.icons_size * factor; + float scaled_separator_size = t_layout.separator_size * factor; + float scaled_gap_size = t_layout.gap_size * factor; + float border = t_layout.border * factor; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = t_layout.left; + float top = t_layout.top - icon_stride; + + bool found = false; + const auto& t_items = t_toolbar.get_items(); + for (const auto& item : t_items) { + if (!item->is_visible()) + continue; + + if (item->is_separator()) + left += separator_stride; + else { + if (item->get_name() == p_item->get_name()) { + found = true; + break; + } + if (item->get_type() == GLToolbarItem::EType::SeparatorLine) { + left += (icon_stride - 0.5f * scaled_icons_size); + } + else { + left += icon_stride; + } + } + } + if (!found) + return; + + left += border; + top -= separator_stride; + float right = left + scaled_icons_size; + + unsigned int tex_id = t_arrow_texture.texture.get_id(); + // arrow width and height + float arr_tex_width = (float)t_arrow_texture.texture.get_width(); + float arr_tex_height = (float)t_arrow_texture.texture.get_height(); + if ((tex_id != 0) && (arr_tex_width > 0) && (arr_tex_height > 0)) { + float inv_tex_width = (arr_tex_width != 0.0f) ? 1.0f / arr_tex_width : 0.0f; + float inv_tex_height = (arr_tex_height != 0.0f) ? 1.0f / arr_tex_height : 0.0f; + + float internal_left = left + border - scaled_icons_size * 1.5f; // add scaled_icons_size for huge arrow + float internal_right = right - border + scaled_icons_size * 1.5f; + float internal_top = top - border; + // bottom is not moving and should be calculated from arrow texture sides ratio + float arrow_sides_ratio = (float)t_arrow_texture.texture.get_height() / (float)t_arrow_texture.texture.get_width(); + float internal_bottom = internal_top - (internal_right - internal_left) * arrow_sides_ratio; + + float internal_left_uv = (float)t_arrow_texture.metadata.left * inv_tex_width; + float internal_right_uv = 1.0f - (float)t_arrow_texture.metadata.right * inv_tex_width; + float internal_top_uv = 1.0f - (float)t_arrow_texture.metadata.top * inv_tex_height; + float internal_bottom_uv = (float)t_arrow_texture.metadata.bottom * inv_tex_height; + + GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); + } +} + +ToolbarKeepSizeRenderer::ToolbarKeepSizeRenderer() +{ +} + +ToolbarKeepSizeRenderer::~ToolbarKeepSizeRenderer() +{ +} + +void ToolbarKeepSizeRenderer::render(const GLToolbar& t_toolbar, const Camera& t_camera) +{ + const auto& t_layout = t_toolbar.get_layout(); + + const auto& t_viewport = t_camera.get_viewport(); + const auto canvas_width = t_viewport[2]; + const auto canvas_height = t_viewport[3]; + + const auto toolbar_width = t_toolbar.get_width(); + const auto toolbar_height = t_toolbar.get_height(); + const auto toolbar_offset = t_layout.offset >= canvas_width ? 0.0f : t_layout.offset; + + float final_toolbar_width = toolbar_width; + float final_toolbar_height = toolbar_height; + + const auto final_canvas_width = canvas_width - toolbar_offset; + + float collapse_width = 0.0f; + recalculate_item_pos(t_toolbar, t_camera, final_toolbar_width, final_toolbar_height, collapse_width); + + if (t_toolbar.is_collapsed()) { + final_toolbar_height = toolbar_height; + } + float inv_zoom = (float)t_camera.get_inv_zoom(); + float factor = inv_zoom * t_layout.scale; + float scaled_border = t_layout.border * factor; + + float left = 0.0f; + float top = 0.0f; + calculate_position(t_toolbar, t_camera, final_toolbar_width, final_toolbar_height, left, top); + + if (t_layout.collapsed_offset < 1e-6f || t_toolbar.is_collapsed()) { + float scaled_width = final_toolbar_width * inv_zoom; + float scaled_height = final_toolbar_height * inv_zoom; + float right = left + scaled_width; + float bottom = top - scaled_height; + + render_background(t_toolbar, left, top, right, bottom, scaled_border); + } + else { + float scaled_width = final_toolbar_width * inv_zoom; + float scaled_height = toolbar_height * inv_zoom; + float right = left + scaled_width; + float bottom = top - scaled_height; + + render_background(t_toolbar, left, top, right, bottom, scaled_border); + + const auto others_height = final_toolbar_height - toolbar_height; + if (others_height > 1e-6f) { + scaled_width = collapse_width * inv_zoom; + right = left + scaled_width; + top = bottom - t_layout.collapsed_offset * factor; + scaled_height = others_height * inv_zoom; + bottom = top - scaled_height; + render_background(t_toolbar, left, top, right, bottom, scaled_border); + } + } + + // renders icons + const auto& t_icon_texture = t_toolbar.get_icon_texture(); + unsigned int tex_id = t_icon_texture.get_id(); + int tex_width = t_icon_texture.get_width(); + int tex_height = t_icon_texture.get_height(); + if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0)) + return; + + const auto& t_items = t_toolbar.get_items(); + for (size_t i = 0; i < t_items.size(); ++i) { + const auto& current_item = t_items[i]; + current_item->override_render_rect = m_p_override_render_rect; + if (current_item->is_action() || current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + const bool b_filp_v = !t_toolbar.is_collapsed() && current_item->is_collapse_button(); + current_item->render(tex_id, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(t_layout.icons_size * t_layout.scale), t_toolbar.get_height(), b_filp_v); + } + //QDS: GUI refactor: GLToolbar + if (current_item->is_action_with_text()) + { + current_item->render_text(); + } + } +} + +GLToolbar::EToolbarRenderingMode ToolbarKeepSizeRenderer::get_mode() const +{ + return GLToolbar::EToolbarRenderingMode::KeepSize; +} + +void ToolbarKeepSizeRenderer::render_arrow(const GLToolbar& t_toolbar, const std::weak_ptr& highlighted_item) +{ +} + +bool ToolbarKeepSizeRenderer::needs_collapsed() const +{ + return m_b_needs_collapsed; +} + +void ToolbarKeepSizeRenderer::render_horizontal(const GLToolbar& t_toolbar) +{ +} + +void ToolbarKeepSizeRenderer::render_vertical(const GLToolbar& t_toolbar) +{ +} + +void ToolbarKeepSizeRenderer::render_background(const GLToolbar& t_toolbar, float left, float top, float right, float bottom, float border) const +{ + const auto& t_background_texture = t_toolbar.get_background_texture(); + unsigned int tex_id = t_background_texture.texture.get_id(); + if (tex_id < 0) { + return; + } + + float tex_width = (float)t_background_texture.texture.get_width(); + if (tex_width <= 0) { + return; + } + + float tex_height = (float)t_background_texture.texture.get_height(); + if (tex_height <= 0) { + return; + } + + float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; + float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; + + float internal_left = left + border; + float internal_right = right - border; + float internal_top = top - border; + float internal_bottom = bottom + border; + + float left_uv = 0.0f; + float right_uv = 1.0f; + float top_uv = 1.0f; + float bottom_uv = 0.0f; + + float internal_left_uv = (float)t_background_texture.metadata.left * inv_tex_width; + float internal_right_uv = 1.0f - (float)t_background_texture.metadata.right * inv_tex_width; + float internal_top_uv = 1.0f - (float)t_background_texture.metadata.top * inv_tex_height; + float internal_bottom_uv = (float)t_background_texture.metadata.bottom * inv_tex_height; + + const auto& t_layout = t_toolbar.get_layout(); + GLTexture::render_sub_texture(tex_id, left, right, bottom, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); +} + +void ToolbarKeepSizeRenderer::calculate_position(const GLToolbar& t_toolbar, const Camera& t_camera, float toolbar_width, float toolbar_height, float& left, float& top) +{ + const auto& t_layout = t_toolbar.get_layout(); + switch (t_layout.position_mode) { + case ToolbarLayout::EPositionMode::TopLeft: + { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + top = 0.5f * (float)t_viewport[3] * inv_zoom; + left = -0.5f * (float)t_viewport[2] * inv_zoom; + + break; + } + case ToolbarLayout::EPositionMode::TopMiddle: + { + float inv_zoom = (float)t_camera.get_inv_zoom(); + const auto& t_viewport = t_camera.get_viewport(); + const auto cnv_width = t_viewport[2]; + const auto cnv_height = t_viewport[3]; + top = 0.5f * (float)cnv_height * inv_zoom; + left = -0.5f * (float)cnv_width * inv_zoom; + const auto final_width = toolbar_width + t_layout.offset; + if (cnv_width < final_width) { + left += (t_layout.offset * inv_zoom); + } + else { + const float offset = (cnv_width - final_width) / 2.f; + left += (offset + t_layout.offset) * inv_zoom; + } + + break; + } + case ToolbarLayout::EPositionMode::Custom: + default: + { + left = t_layout.left; + top = t_layout.top; + break; + } + } +} + +void ToolbarKeepSizeRenderer::recalculate_item_pos(const GLToolbar& t_toolbar, const Camera& t_camera, float& final_toolbar_width, float& final_toolbar_height, float& collapse_width) +{ + const auto& t_layout = t_toolbar.get_layout(); + + const auto& t_viewport = t_camera.get_viewport(); + const auto canvas_width = t_viewport[2]; + const auto canvas_height = t_viewport[3]; + + const auto toolbar_width = t_toolbar.get_width(); + const auto toolbar_height = t_toolbar.get_height(); + const auto toolbar_offset = t_layout.offset >= canvas_width ? 0.0f : t_layout.offset; + + const auto final_canvas_width = canvas_width - toolbar_offset; + + m_b_needs_collapsed = false; + const auto& t_items = t_toolbar.get_items(); + m_indices_to_draw.clear(); + + float total_collapse_item_width = 2.0f * t_layout.border; + for (size_t i = 0; i < t_items.size(); ++i) + { + const auto& current_item = t_items[i]; + + if (!current_item) { + continue; + } + + if (!current_item->is_visible()) + continue; + + current_item->set_collapsed(false); + m_indices_to_draw.emplace_back(i); + } + + float collapse_button_width = 0.0f; + + if (final_canvas_width - toolbar_width < 1e-6f) { + float current_width = 2.0f * t_layout.border; + float uncollapsible_width = 2.0f * t_layout.border; + std::vector t_other_visible_indices; + std::vector t_uncollapsible_indices; + t_other_visible_indices.reserve(10); + t_uncollapsible_indices.reserve(10); + for (size_t i = 0; i < m_indices_to_draw.size(); ++i) + { + const auto& current_index = m_indices_to_draw[i]; + const auto& current_item = t_items[current_index]; + + if (!current_item) { + continue; + } + + if (!current_item->is_visible()) + continue; + + if (current_item->is_collapsible()) { + t_other_visible_indices.emplace_back(i); + } + else { + t_uncollapsible_indices.emplace_back(i); + float item_width = 0.0f; + if (current_item->is_separator()) + item_width += t_layout.separator_size; + else if (current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + item_width += ((float)t_layout.icons_size * 0.5f); + } + else + { + item_width += (float)t_layout.icons_size; + if (current_item->is_action_with_text()) + item_width += current_item->get_extra_size_ratio() * t_layout.icons_size; + if (current_item->is_action_with_text_image()) + item_width += t_layout.text_size; + } + + if (i < m_indices_to_draw.size() - 1) { + item_width += t_layout.gap_size; + } + + if (current_item->is_collapse_button()) { + collapse_button_width = item_width; + continue; + } + + uncollapsible_width += item_width; + } + } + + current_width = uncollapsible_width; + size_t final_index = 0; + + if (current_width * t_layout.scale - final_canvas_width < 1e-6f) { + for (; final_index < t_other_visible_indices.size(); ++final_index) { + const auto& item_index = m_indices_to_draw[t_other_visible_indices[final_index]]; + const auto& current_item = t_items[item_index]; + float item_width = 0.0f; + if (current_item->is_separator()) + item_width += t_layout.separator_size; + else if (current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + item_width += ((float)t_layout.icons_size * 0.5f); + } + else + { + item_width += (float)t_layout.icons_size; + if (current_item->is_action_with_text()) + item_width += current_item->get_extra_size_ratio() * t_layout.icons_size; + if (current_item->is_action_with_text_image()) + item_width += t_layout.text_size; + } + + if (item_index < m_indices_to_draw.size() - 1) { + item_width += t_layout.gap_size; + } + + if ((current_width + item_width) * t_layout.scale - final_canvas_width > 1e-6f) { + break; + } + current_width += item_width; + } + } + + if (final_index < t_other_visible_indices.size()) { + current_width = std::max(GLToolbar::Default_Icons_Size + 2.0f * t_layout.border, current_width + collapse_button_width); + + final_toolbar_width = current_width * t_layout.scale; + while (final_canvas_width - final_toolbar_width < 1e-6f) { + if (final_index < 1) { + break; + } + const auto item_index = m_indices_to_draw[t_other_visible_indices[final_index]]; + float item_width = 0.0f; + const auto& current_item = t_items[item_index]; + if (current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + item_width += ((float)t_layout.icons_size * 0.5f); + item_width += t_layout.gap_size; + } + else if (current_item->is_separator()) { + item_width += t_layout.separator_size; + item_width += t_layout.gap_size; + } + else + { + item_width += (float)t_layout.icons_size; + if (current_item->is_action_with_text()) + item_width += current_item->get_extra_size_ratio() * t_layout.icons_size; + if (current_item->is_action_with_text_image()) + item_width += t_layout.text_size; + item_width += t_layout.gap_size; + } + + final_toolbar_width = final_toolbar_width - (item_width * t_layout.scale); + + --final_index; + } + m_b_needs_collapsed = true; + } + + if (m_b_needs_collapsed) { + if (final_index < t_other_visible_indices.size()) { + std::vector temp_indices; + temp_indices.reserve(m_indices_to_draw.size()); + for (size_t i = 0; i < final_index; ++i) { + const auto item_index = m_indices_to_draw[t_other_visible_indices[i]]; + temp_indices.emplace_back(item_index); + } + for (size_t i = 0; i < t_uncollapsible_indices.size(); ++i) { + const auto item_index = m_indices_to_draw[t_uncollapsible_indices[i]]; + temp_indices.emplace_back(item_index); + } + for (size_t i = final_index; i < t_other_visible_indices.size(); ++i) { + const auto item_index = m_indices_to_draw[t_other_visible_indices[i]]; + const auto& p_item = t_items[item_index]; + temp_indices.emplace_back(item_index); + p_item->set_collapsed(t_toolbar.is_collapsed()); + + if (p_item->is_separator()) { + total_collapse_item_width += t_layout.separator_size; + total_collapse_item_width += t_layout.gap_size; + } + else if (p_item->is_action() || p_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + if (p_item->is_action()) { + total_collapse_item_width += (float)t_layout.icons_size; + total_collapse_item_width += t_layout.gap_size; + } + else { + total_collapse_item_width += ((float)t_layout.icons_size * 0.5f); + total_collapse_item_width += t_layout.gap_size; + } + } + else if (p_item->is_action_with_text()) + { + total_collapse_item_width += p_item->get_extra_size_ratio() * t_layout.icons_size; + total_collapse_item_width += t_layout.gap_size; + } + } + m_indices_to_draw = std::move(temp_indices); + } + } + } + + float inv_zoom = (float)t_camera.get_inv_zoom(); + float factor = inv_zoom * t_layout.scale; + float scaled_icons_size = t_layout.icons_size * factor; + float scaled_separator_size = t_layout.separator_size * factor; + float scaled_gap_size = t_layout.gap_size * factor; + float scaled_border = t_layout.border * factor; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = 0.0f; + float top = 0.0f; + calculate_position(t_toolbar, t_camera, final_toolbar_width, final_toolbar_height, left, top); + + left += scaled_border; + top -= scaled_border; + + float temp_left = left; + float temp_top = top; + float temp_width = 2.0f * t_layout.border; + bool line_start = true; + final_toolbar_height = 0; + + bool offset_flag = true; + collapse_width = 0.0f; + bool b_needs_to_double_check_collapse_width = true; + m_p_override_render_rect = nullptr; + std::vector temp_indices; + temp_indices.reserve(m_indices_to_draw.size()); + for (size_t i = 0; i < m_indices_to_draw.size(); ++i) { + const auto& current_item = t_items[m_indices_to_draw[i]]; + + if (line_start && (current_item->get_type() == GLToolbarItem::EType::SeparatorLine || current_item->is_separator())) { + continue; + } + + if (current_item->is_separator()) { + temp_left += separator_stride; + temp_width += t_layout.separator_size; + temp_width += t_layout.gap_size; + continue; + } + + if (current_item->is_action() || current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + if (current_item->is_action()) { + temp_width += (float)t_layout.icons_size; + temp_width += t_layout.gap_size; + } + else { + temp_width += ((float)t_layout.icons_size * 0.5f); + temp_width += t_layout.gap_size; + } + current_item->render_rect[0] = temp_left; + current_item->render_rect[1] = temp_left + scaled_icons_size; + current_item->render_rect[2] = temp_top - scaled_icons_size; + current_item->render_rect[3] = temp_top; + } + //QDS: GUI refactor: GLToolbar + if (current_item->is_action_with_text()) + { + float scaled_text_size = current_item->get_extra_size_ratio() * scaled_icons_size; + current_item->render_rect[0] = temp_left + scaled_icons_size; + current_item->render_rect[1] = temp_left + scaled_icons_size + scaled_text_size; + current_item->render_rect[2] = temp_top - scaled_icons_size; + current_item->render_rect[3] = temp_top; + temp_left += scaled_text_size; + temp_width += current_item->get_extra_size_ratio() * t_layout.icons_size; + temp_width += t_layout.gap_size; + } + if (current_item->get_type() == GLToolbarItem::EType::SeparatorLine) { + temp_left += (icon_stride - 0.5f * scaled_icons_size); + } + else { + temp_left += icon_stride; + } + + if (line_start) { + final_toolbar_height += toolbar_height; + } + + if (current_item->is_collapse_button()) { + collapse_width = temp_width; + if (total_collapse_item_width < collapse_width) { + collapse_width = total_collapse_item_width; + } + else { + collapse_width = (total_collapse_item_width) / 2.0f + GLToolbar::Default_Icons_Size; + } + collapse_width = std::min(collapse_width * t_layout.scale, final_toolbar_width); + } + + temp_indices.emplace_back(m_indices_to_draw[i]); + + line_start = false; + + bool new_line = false; + if (offset_flag) { + new_line = final_toolbar_width - temp_width * t_layout.scale < GLToolbar::Default_Icons_Size * t_layout.scale; + } + else { + new_line = collapse_width - temp_width * t_layout.scale < GLToolbar::Default_Icons_Size * t_layout.scale; + } + if (new_line) { + temp_left = left; + temp_top -= toolbar_height * inv_zoom; + if (offset_flag) { + temp_top -= t_layout.collapsed_offset * factor; + offset_flag = false; + } + else { + if (b_needs_to_double_check_collapse_width) { + b_needs_to_double_check_collapse_width = false; + collapse_width = temp_width * t_layout.scale; + } + } + temp_width = 2.0f * t_layout.border; + line_start = true; + } + + if (current_item->is_collapse_button()) { + m_p_override_render_rect = current_item->render_rect; + } + } + m_indices_to_draw.clear(); + m_indices_to_draw = std::move(temp_indices); + +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index a58ceaa..bda6f14 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -16,7 +16,7 @@ namespace Slic3r { namespace GUI { class GLCanvas3D; - +struct Camera; //QDS: GUI refactor: GLToolbar wxDECLARE_EVENT(EVT_GLTOOLBAR_OPEN_PROJECT, SimpleEvent); @@ -36,6 +36,7 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_MULTI_APP, SimpleEvent); + wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); @@ -67,7 +68,10 @@ public: typedef std::function ActionCallback; typedef std::function VisibilityCallback; typedef std::function EnablingCallback; - typedef std::function RenderCallback; + typedef std::function RenderCallback; + using OnHoverCallback = std::function; + using IconFilenameCallback = std::function; + using PressedRecheckCallback = std::function; enum EType : unsigned char { @@ -121,7 +125,6 @@ public: }; std::string name; - std::string icon_filename; std::string tooltip; std::string additional_tooltip; //QDS: GUI refactor: GLToolbar @@ -142,13 +145,19 @@ public: bool continuous_click{false}; VisibilityCallback visibility_callback; EnablingCallback enabling_callback; - + OnHoverCallback on_hover = nullptr; + IconFilenameCallback icon_filename_callback = nullptr; + PressedRecheckCallback pressed_recheck_callback = nullptr; + bool b_toggle_disable_others{ true }; + bool b_toggle_affectable{ true }; + bool b_collapsible{ true }; + bool b_collapse_button{ false }; + bool b_collapsed{ false }; Data(); //QDS: GUI refactor: GLToolbar Data(const GLToolbarItem::Data& data) { name = data.name; - icon_filename = data.icon_filename; tooltip = data.tooltip; additional_tooltip = data.additional_tooltip; button_text = data.button_text; @@ -163,6 +172,14 @@ public: image_data = data.image_data; image_width = data.image_width; image_height = data.image_height; + on_hover = data.on_hover; + icon_filename_callback = data.icon_filename_callback; + pressed_recheck_callback = data.pressed_recheck_callback; + b_toggle_disable_others = data.b_toggle_disable_others; + b_toggle_affectable = data.b_toggle_affectable; + b_collapsible = data.b_collapsible; + b_collapse_button = data.b_collapse_button; + b_collapsed = data.b_collapsed; } }; @@ -181,8 +198,8 @@ private: public: - // remember left position for rendering menu - mutable float render_left_pos; + mutable float render_rect[4]{ 0.0f }; // left, right, bottom, top + mutable float* override_render_rect{ nullptr }; std::chrono::system_clock::time_point get_start_time_point() const { return start; } @@ -195,22 +212,23 @@ public: void set_highlight(EHighlightState state) { m_highlight_state = state; } const std::string& get_name() const { return m_data.name; } - const std::string& get_icon_filename() const { return m_data.icon_filename; } - void set_icon_filename(const std::string& filename) { m_data.icon_filename = filename; } + std::string get_icon_filename(bool is_dark_mode) const; const std::string& get_tooltip() const { return m_data.tooltip; } const std::string& get_additional_tooltip() const { return m_data.additional_tooltip; } void set_additional_tooltip(const std::string& text) { m_data.additional_tooltip = text; } void set_tooltip(const std::string& text) { m_data.tooltip = text; } - - void do_left_action() { m_last_action_type = Left; m_data.left.action_callback(); } - void do_right_action() { m_last_action_type = Right; m_data.right.action_callback(); } + void set_last_action_type(GLToolbarItem::EActionType type); + void do_left_action(); + void do_right_action(); bool is_enabled() const { return (m_state != Disabled) && (m_state != HoverDisabled); } bool is_disabled() const { return (m_state == Disabled) || (m_state == HoverDisabled); } bool is_hovered() const { return (m_state == Hover) || (m_state == HoverPressed) || (m_state == HoverDisabled); } bool is_pressed() const { return (m_state == Pressed) || (m_state == HoverPressed); } - bool is_visible() const { return m_data.visible; } + bool is_visible() const; bool is_separator() const { return m_type == Separator; } + bool toggle_disable_others() const; + bool toggle_affectable() const; bool is_left_toggable() const { return m_data.left.toggable; } bool is_right_toggable() const { return m_data.right.toggable; } @@ -235,45 +253,95 @@ public: void set_button_text(const std::string& text) { m_data.button_text = text; } float get_extra_size_ratio() const { return m_data.extra_size_ratio; } void set_extra_size_ratio(const float ratio) { m_data.extra_size_ratio = ratio; } - void render_text(float left, float right, float bottom, float top) const; + void render_text() const; int generate_texture(wxFont& font); int generate_image_texture(); - void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const; + void render(unsigned int tex_id, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size, float toolbar_height, bool b_flip_v = false) const; void render_image(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const; -private: - void set_visible(bool visible) { m_data.visible = visible; } - friend class GLToolbar; + const GLToolbarItem::Data& get_data() const; + + void set_visible(bool visible); + + GLToolbarItem::EType get_type() const; + + bool is_inside(const Vec2d& mouse_pos) const; + + bool is_collapsible() const; + + bool is_collapse_button() const; + + void set_collapsed(bool value); + + bool is_collapsed() const; + + bool recheck_pressed() const; }; -struct BackgroundTexture +struct ToolbarLayout { - struct Metadata + enum EType : unsigned char { - // path of the file containing the background texture - std::string filename; - // size of the left edge, in pixels - unsigned int left; - // size of the right edge, in pixels - unsigned int right; - // size of the top edge, in pixels - unsigned int top; - // size of the bottom edge, in pixels - unsigned int bottom; - - Metadata(); + Horizontal, + Vertical, + Num_Types }; - GLTexture texture; - Metadata metadata; + enum EHorizontalOrientation : unsigned char + { + HO_Left, + HO_Center, + HO_Right, + Num_Horizontal_Orientations + }; + + enum EVerticalOrientation : unsigned char + { + VO_Top, + VO_Center, + VO_Bottom, + Num_Vertical_Orientations + }; + + enum EPositionMode : uint8_t + { + TopLeft, + TopMiddle, + Custom + }; + + EType type; + EHorizontalOrientation horizontal_orientation; + EVerticalOrientation vertical_orientation; + EPositionMode position_mode; + float offset; + float top; + float left; + float border; + float separator_size; + float gap_size; + float icons_size; + float text_size; + float image_width; + float image_height; + float scale; + float collapsed_offset; + + float width; + float height; + bool dirty; + + ToolbarLayout(); }; +class ToolbarRenderer; + class GLToolbar { public: static const float Default_Icons_Size; - +public: enum EType : unsigned char { Normal, @@ -281,68 +349,160 @@ public: Num_Types }; - struct Layout + enum EToolbarRenderingMode : uint8_t { - enum EType : unsigned char - { - Horizontal, - Vertical, - Num_Types - }; - - enum EHorizontalOrientation : unsigned char - { - HO_Left, - HO_Center, - HO_Right, - Num_Horizontal_Orientations - }; - - enum EVerticalOrientation : unsigned char - { - VO_Top, - VO_Center, - VO_Bottom, - Num_Vertical_Orientations - }; - - EType type; - EHorizontalOrientation horizontal_orientation; - EVerticalOrientation vertical_orientation; - float top; - float left; - float border; - float separator_size; - float gap_size; - float icons_size; - float text_size; - float image_width; - float image_height; - float scale; - - float width; - float height; - bool dirty; - - Layout(); + KeepSize, + Auto }; -private: - typedef std::vector ItemsList; + GLToolbar(GLToolbar::EType type, const std::string& name); + virtual ~GLToolbar(); + + bool init(const BackgroundTexture::Metadata& background_texture); + + bool init_arrow(const BackgroundTexture::Metadata& arrow_texture); + + const ToolbarLayout& get_layout() const; + + void set_layout_type(ToolbarLayout::EType type); + + ToolbarLayout::EHorizontalOrientation get_horizontal_orientation() const; + void set_horizontal_orientation(ToolbarLayout::EHorizontalOrientation orientation); + + ToolbarLayout::EVerticalOrientation get_vertical_orientation() const; + void set_vertical_orientation(ToolbarLayout::EVerticalOrientation orientation); + + void set_position_mode(ToolbarLayout::EPositionMode t_position_mode); + void set_offset(float offset); + void set_position(float top, float left); + void set_border(float border); + void set_separator_size(float size); + void set_gap_size(float size); + void set_icons_size(float size); + void set_text_size(float size); + void set_scale(float scale); + float get_scale() const; + + void set_icon_dirty(); + + bool is_enabled() const; + void set_enabled(bool enable); + + float get_icons_size() const; + float get_width() const; + float get_height() const; + + //QDS: GUI refactor: GLToolbar + bool add_item(const GLToolbarItem::Data& data, GLToolbarItem::EType type = GLToolbarItem::Action); + bool add_separator(); + bool del_all_item(); + + void select_item(const std::string& name); + + bool is_item_pressed(const std::string& name) const; + bool is_item_disabled(const std::string& name) const; + bool is_item_visible(const std::string& name) const; + + bool is_any_item_pressed() const; + + unsigned int get_items_count() const { return (unsigned int)m_items.size(); } + int get_item_id(const std::string& name) const; + + std::string get_tooltip() const; + void set_tooltip(int item_id, const std::string& text); + + void get_additional_tooltip(int item_id, std::string& text); + void set_additional_tooltip(int item_id, const std::string& text); + int get_visible_items_cnt() const; + + // get item pointer for highlighter timer + const std::shared_ptr& get_item(const std::string& item_name) const; + + void render(const Camera& t_camera); + + // returns true if any item changed its state + bool update_items_state(); + + void set_dark_mode_enabled(bool is_enabled); + + const std::vector>& get_items() const; + + const GLTexture& get_icon_texture() const; + const BackgroundTexture& get_background_texture() const; + const BackgroundTexture& get_arrow_texture() const; + + bool needs_collapsed() const; + + void toggle_collapsed(); + void set_collapsed(); + + bool is_collapsed() const; + + void set_collapsed_offset(uint32_t offset_in_pixel); + uint32_t get_collapsed_offset(); + + GLToolbar::EToolbarRenderingMode get_rendering_mode(); + void set_rendering_mode(GLToolbar::EToolbarRenderingMode mode); + + void force_left_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Left, item_id, parent, false); } + void force_right_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Right, item_id, parent, false); } + + void render_arrow(const std::weak_ptr& highlighted_item); + + bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent); + + //QDS: GUI refactor: GLToolbar + int generate_button_text_textures(wxFont& font); + int generate_image_textures(); + float get_scaled_icon_size(); + +protected: + void calc_layout() const; + const std::shared_ptr& get_renderer() const; + +private: + float get_width_horizontal() const; + float get_width_vertical() const; + float get_height_horizontal() const; + float get_height_vertical() const; + float get_main_size() const; + bool generate_icons_texture() const; + + // returns true if any item changed its state + bool update_items_visibility(); + // returns true if any item changed its state + bool update_items_enabled_state(); + + bool update_items_pressed_state(); + + void do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover); + void update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent); + // returns the id of the item under the given mouse position or -1 if none + int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; + +private: + mutable ToolbarLayout m_layout; + mutable bool m_icons_texture_dirty{ true }; + mutable GLTexture m_icons_texture; + bool m_enabled{ false }; + GLToolbar::EType m_type{ GLToolbar::EType::Normal }; + std::string m_name{}; + std::vector> m_items; - EType m_type; - std::string m_name; - bool m_enabled; - GLTexture m_icons_texture; - bool m_icons_texture_dirty; - mutable GLTexture m_images_texture; - mutable bool m_images_texture_dirty; BackgroundTexture m_background_texture; BackgroundTexture m_arrow_texture; - Layout m_layout; - ItemsList m_items; + int m_pressed_toggable_id{ -1 }; + bool m_b_dark_mode_enabled{ false }; + mutable std::shared_ptr m_p_renderer{ nullptr }; + + bool m_b_collapsed{ true }; + + EToolbarRenderingMode m_rendering_mode{ EToolbarRenderingMode::Auto }; + + mutable GLTexture m_images_texture; + mutable bool m_images_texture_dirty; struct MouseCapture { bool left; @@ -357,106 +517,67 @@ private: }; MouseCapture m_mouse_capture; - int m_pressed_toggable_id; +}; +class ToolbarRenderer +{ public: - GLToolbar(EType type, const std::string& name); - ~GLToolbar(); + explicit ToolbarRenderer(); + ~ToolbarRenderer(); - bool init(const BackgroundTexture::Metadata& background_texture); + virtual void render(const GLToolbar& t_toolbar, const Camera& t_camera) = 0; - bool init_arrow(const BackgroundTexture::Metadata& arrow_texture); + virtual GLToolbar::EToolbarRenderingMode get_mode() const = 0; - Layout::EType get_layout_type() const; - void set_layout_type(Layout::EType type); - void set_icon_dirty() { m_icons_texture_dirty = true; } - Layout::EHorizontalOrientation get_horizontal_orientation() const { return m_layout.horizontal_orientation; } - void set_horizontal_orientation(Layout::EHorizontalOrientation orientation) { m_layout.horizontal_orientation = orientation; } - Layout::EVerticalOrientation get_vertical_orientation() const { return m_layout.vertical_orientation; } - void set_vertical_orientation(Layout::EVerticalOrientation orientation) { m_layout.vertical_orientation = orientation; } + virtual void render_arrow(const GLToolbar& t_toolbar, const std::weak_ptr& highlighted_item) = 0; - void set_position(float top, float left); - void set_border(float border); - void set_separator_size(float size); - void set_gap_size(float size); - void set_icons_size(float size); - void set_text_size(float size); - void set_scale(float scale); + virtual bool needs_collapsed() const; +}; - bool is_enabled() const { return m_enabled; } - void set_enabled(bool enable) { m_enabled = enable; } +class ToolbarAutoSizeRenderer : public ToolbarRenderer +{ +public: + explicit ToolbarAutoSizeRenderer(); + ~ToolbarAutoSizeRenderer(); - //QDS: GUI refactor: GLToolbar - bool add_item(const GLToolbarItem::Data& data, GLToolbarItem::EType type = GLToolbarItem::Action); - bool add_separator(); - bool del_all_item(); + void render(const GLToolbar& t_toolbar, const Camera& t_camera) override; - float get_icons_size() { return m_layout.icons_size; } - float get_width(); - float get_height(); + GLToolbar::EToolbarRenderingMode get_mode() const override; - void select_item(const std::string& name); - - bool is_item_pressed(const std::string& name) const; - bool is_item_disabled(const std::string& name) const; - bool is_item_visible(const std::string& name) const; - - bool is_any_item_pressed() const; - - unsigned int get_items_count() const { return (unsigned int)m_items.size(); } - int get_item_id(const std::string& name) const; - - void force_left_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Left, item_id, parent, false); } - void force_right_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Right, item_id, parent, false); } - - std::string get_tooltip() const; - - void get_additional_tooltip(int item_id, std::string& text); - void set_additional_tooltip(int item_id, const std::string& text); - void set_tooltip(int item_id, const std::string& text); - int get_visible_items_cnt() const; - - // returns true if any item changed its state - bool update_items_state(); - - void render(const GLCanvas3D& parent,GLToolbarItem::EType type = GLToolbarItem::Action); - void render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item); - - bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent); - // get item pointer for highlighter timer - GLToolbarItem* get_item(const std::string& item_name); - - //QDS: GUI refactor: GLToolbar - int generate_button_text_textures(wxFont& font); - int generate_image_textures(); - float get_scaled_icon_size(); + void render_arrow(const GLToolbar& t_toolbar, const std::weak_ptr& highlighted_item) override; private: - void calc_layout(); - float get_width_horizontal() const; - float get_width_vertical() const; - float get_height_horizontal() const; - float get_height_vertical() const; - float get_main_size() const; - void do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover); - void update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent); - void update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent); - void update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent); - // returns the id of the item under the given mouse position or -1 if none - int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; - int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; - int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; + void render_horizontal(const GLToolbar& t_toolbar, const Camera& t_camera); + void render_vertical(const GLToolbar& t_toolbar, const Camera& t_camera); + void render_background(const GLToolbar& t_toolbar, float left, float top, float right, float bottom, float border) const; + void calculate_position(const GLToolbar& t_toolbar, const Camera& t_camera, float& left, float& top); +}; - void render_background(float left, float top, float right, float bottom, float border) const; - void render_horizontal(const GLCanvas3D& parent,GLToolbarItem::EType type); - void render_vertical(const GLCanvas3D& parent); +class ToolbarKeepSizeRenderer : public ToolbarRenderer +{ +public: + explicit ToolbarKeepSizeRenderer(); + ~ToolbarKeepSizeRenderer(); - bool generate_icons_texture(); + void render(const GLToolbar& t_toolbar, const Camera& t_camera) override; - // returns true if any item changed its state - bool update_items_visibility(); - // returns true if any item changed its state - bool update_items_enabled_state(); + GLToolbar::EToolbarRenderingMode get_mode() const override; + + void render_arrow(const GLToolbar& t_toolbar, const std::weak_ptr& highlighted_item) override; + + bool needs_collapsed() const override; + +private: + void render_horizontal(const GLToolbar& t_toolbar); + void render_vertical(const GLToolbar& t_toolbar); + void render_background(const GLToolbar& t_toolbar, float left, float top, float right, float bottom, float border) const; + void calculate_position(const GLToolbar& t_toolbar, const Camera& t_camera, float toolbar_width, float toolbar_height, float& left, float& top); + void recalculate_item_pos(const GLToolbar& t_toolbar, const Camera& t_camera, float& final_toolbar_width, float& final_toolbar_height, float& collapse_width); + +private: + bool m_b_needs_collapsed{ false }; + std::vector m_indices_to_draw; + float* m_p_override_render_rect{ nullptr }; }; } // namespace GUI diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 5164db6..14626a7 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -68,6 +68,7 @@ #include "MainFrame.hpp" #include "Plater.hpp" #include "GLCanvas3D.hpp" +#include "EncodedFilament.hpp" #include "../Utils/PresetUpdater.hpp" #include "../Utils/PrintHost.hpp" @@ -105,6 +106,7 @@ #include "PrivacyUpdateDialog.hpp" #include "ModelMall.hpp" #include "HintNotification.hpp" +#include "QDTUtil.hpp" //#ifdef WIN32 //#include "BaseException.h" @@ -1343,7 +1345,7 @@ void GUI_App::post_init() if(!m_networking_need_update && m_agent) { m_agent->set_on_ssdp_msg_fn( [this](std::string json_str) { - if (m_is_closing) { + if (is_closing()) { return; } GUI::wxGetApp().CallAfter([this, json_str] { @@ -1451,7 +1453,7 @@ void GUI_App::shutdown() } if (m_is_recreating_gui) return; - m_is_closing = true; + set_closing(true); BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown exit"; } @@ -1763,11 +1765,11 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP //auto plugin_folder = boost::filesystem::path(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()) / "plugins"; auto backup_folder = plugin_folder/"backup"; if (!boost::filesystem::exists(plugin_folder)) { - BOOST_LOG_TRIVIAL(info) << "[install_plugin] will create directory "<status())) { ++file_count; } } for (fs::directory_iterator it(dir_path); it != fs::directory_iterator(); ++it) { - BOOST_LOG_TRIVIAL(info) << " current path:" << it->path().string(); + BOOST_LOG_TRIVIAL(trace) << " current path:" << PathSanitizer::sanitize(it->path().string()); if (it->path().string() == backup_folder) { continue; } auto dest_path = backup_folder.string() + "/" + it->path().filename().string(); if (fs::is_regular_file(it->status())) { - BOOST_LOG_TRIVIAL(info) << " copy file:" << it->path().string() << "," << it->path().filename(); + BOOST_LOG_TRIVIAL(trace) << " copy file:" << PathSanitizer::sanitize(it->path().string()) << "," << it->path().filename(); try { if (pro_fn) { pro_fn(InstallStatusNormal, 50 + file_index / file_count, cancel); } file_index++; @@ -1887,7 +1889,7 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP BOOST_LOG_TRIVIAL(error) << "Copying to backup failed: " << e.what(); } } else { - BOOST_LOG_TRIVIAL(info) << " copy framework:" << it->path().string() << "," << it->path().filename(); + BOOST_LOG_TRIVIAL(trace) << " copy framework:" << it->path().string() << "," << it->path().filename(); copy_framework(it->path().string(), dest_path); } } @@ -1910,7 +1912,7 @@ void GUI_App::restart_networking() init_networking_callbacks(); m_agent->set_on_ssdp_msg_fn( [this](std::string json_str) { - if (m_is_closing) { + if (is_closing()) { return; } GUI::wxGetApp().CallAfter([this, json_str] { @@ -1954,11 +1956,11 @@ void GUI_App::remove_old_networking_plugins() auto plugin_folder = data_dir_path / "plugins"; //auto plugin_folder = boost::filesystem::path(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()) / "plugins"; if (boost::filesystem::exists(plugin_folder)) { - BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the directory "<set_on_server_connected_fn([this](int return_code, int reason_code) { - if (m_is_closing) { + if (is_closing()) { return; } if (return_code == 5) { @@ -2051,7 +2053,7 @@ void GUI_App::init_networking_callbacks() return; } GUI::wxGetApp().CallAfter([this] { - if (m_is_closing) + if (is_closing()) return; BOOST_LOG_TRIVIAL(trace) << "static: server connected"; m_agent->set_user_selected_machine(m_agent->get_user_selected_machine()); @@ -2062,7 +2064,6 @@ void GUI_App::init_networking_callbacks() m_agent->set_user_selected_machine(m_agent->get_user_selected_machine()); //subscribe device if (m_agent->is_user_login()) { - m_agent->start_device_subscribe(); /*disconnect lan*/ DeviceManager* dev = this->getDeviceManager(); @@ -2090,11 +2091,11 @@ void GUI_App::init_networking_callbacks() }); m_agent->set_on_printer_connected_fn([this](std::string dev_id) { - if (m_is_closing) { + if (is_closing()) { return; } GUI::wxGetApp().CallAfter([this, dev_id] { - if (m_is_closing) + if (is_closing()) return; bool tunnel = boost::algorithm::starts_with(dev_id, "tunnel/"); /* request_pushing */ @@ -2133,11 +2134,11 @@ void GUI_App::init_networking_callbacks() m_agent->set_on_local_connect_fn( [this](int state, std::string dev_id, std::string msg) { - if (m_is_closing) { + if (is_closing()) { return; } CallAfter([this, state, dev_id, msg] { - if (m_is_closing) { + if (is_closing()) { return; } /* request_pushing */ @@ -2204,11 +2205,11 @@ void GUI_App::init_networking_callbacks() ); auto message_arrive_fn = [this](std::string dev_id, std::string msg) { - if (m_is_closing) { + if (is_closing()) { return; } CallAfter([this, dev_id, msg] { - if (m_is_closing) + if (is_closing()) return; this->process_network_msg(dev_id, msg); @@ -2238,11 +2239,11 @@ void GUI_App::init_networking_callbacks() m_agent->set_on_message_fn(message_arrive_fn); auto user_message_arrive_fn = [this](std::string user_id, std::string msg) { - if (m_is_closing) { + if (is_closing()) { return; } CallAfter([this, user_id, msg] { - if (m_is_closing) + if (is_closing()) return; //check user @@ -2257,11 +2258,11 @@ void GUI_App::init_networking_callbacks() auto lan_message_arrive_fn = [this](std::string dev_id, std::string msg) { - if (m_is_closing) { + if (is_closing()) { return; } CallAfter([this, dev_id, msg] { - if (m_is_closing) + if (is_closing()) return; this->process_network_msg(dev_id, msg); @@ -2562,7 +2563,7 @@ void GUI_App::on_start_subscribe_again(std::string dev_id) if ( (dev_id == obj->dev_id) && obj->is_connecting() && obj->subscribe_counter > 0) { obj->subscribe_counter--; if(wxGetApp().getAgent()) wxGetApp().getAgent()->set_user_selected_machine(dev_id); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": dev_id=" << obj->dev_id; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": dev_id=" << QDTCrossTalk::Crosstalk_DevId(obj->dev_id); } }); start_subscribe_timer->Start(5000, wxTIMER_ONE_SHOT); @@ -2589,7 +2590,7 @@ std::string GUI_App::get_local_models_path() void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) { - BOOST_LOG_TRIVIAL(debug) << "init wx instance checker " << name << " "<< path; + BOOST_LOG_TRIVIAL(debug) << "init wx instance checker " << name << " " << PathSanitizer::sanitize(path); m_single_instance_checker = std::make_unique(boost::nowide::widen(name), boost::nowide::widen(path)); } @@ -2798,7 +2799,11 @@ bool GUI_App::on_init_inner() } #endif - BOOST_LOG_TRIVIAL(info) << boost::format("gui mode, Current QIDIStudio Version %1%")%SLIC3R_VERSION; + BOOST_LOG_TRIVIAL(info) << boost::format("gui mode, Current QIDIStudio Version %1%")%SLIC3R_VERSION << ", BuildTime " << SLIC3R_BUILD_TIME; + +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << boost::format("Build Version %1%")%SLIC3R_COMPILE_VERSION; +#endif BOOST_LOG_TRIVIAL(info) << get_system_info(); #if defined(__WINDOWS__) @@ -3288,11 +3293,11 @@ void GUI_App::copy_network_if_available() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": checking network_library from ota directory"; if (!boost::filesystem::exists(plugin_folder)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": create directory " << plugin_folder.string(); + //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": create directory " << plugin_folder.string(); boost::filesystem::create_directory(plugin_folder); } if (!boost::filesystem::exists(cache_folder)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": can not found ota plugins directory " << cache_folder.string(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": can not found ota plugins directory "; app_config->set("update_network_plugin", "false"); return; } @@ -3315,7 +3320,7 @@ void GUI_App::copy_network_if_available() static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; fs::permissions(dest_path, perms); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Copying network library from" << file_path << " to " << dest_path << " successfully."; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Copying network library successfully."; } } @@ -3832,7 +3837,7 @@ wxSize GUI_App::get_min_size() const return wxSize(std::max(1000, 76*m_em_unit), std::max(600, 49 * m_em_unit)); } -float GUI_App::toolbar_icon_scale(const bool is_limited/* = false*/) const +float GUI_App::toolbar_icon_scale(bool auto_scale, const bool is_limited/* = false*/) const { #ifdef __APPLE__ const float icon_sc = 1.0f; // for Retina display will be used its own scale @@ -3840,7 +3845,9 @@ float GUI_App::toolbar_icon_scale(const bool is_limited/* = false*/) const const float icon_sc = m_em_unit * 0.1f; #endif // __APPLE__ - //return icon_sc; + if (!auto_scale) { + return icon_sc; + } const std::string& auto_val = app_config->get("toolkit_size"); @@ -4404,7 +4411,7 @@ int GUI_App::request_user_unbind(std::string dev_id) int result = -1; if (m_agent) { result = m_agent->unbind(dev_id); - BOOST_LOG_TRIVIAL(info) << "request_user_unbind, dev_id = " << dev_id << ", result = " << result; + BOOST_LOG_TRIVIAL(info) << "request_user_unbind, dev_id = " << QDTCrossTalk::Crosstalk_DevId(dev_id) << ", result = " << result; return result; } return result; @@ -4638,9 +4645,28 @@ std::string GUI_App::handle_web_request(std::string cmd) } else if (command_str.compare("homepage_makerlab_open") == 0) { if (root.get_child_optional("url") != boost::none) { - std::string strUrl = root.get_optional("url").value(); + if(wxGetApp().is_user_login()) { + std::string strUrl = root.get_optional("url").value(); - if (mainframe && mainframe->m_webview) { mainframe->m_webview->OpenOneMakerlab(strUrl); } + if (mainframe && mainframe->m_webview) { mainframe->m_webview->OpenOneMakerlab(strUrl); } + }else { + //Check Plugin + bool bValid = is_compatibility_version(); + if (!bValid) { + CallAfter([this] { handle_web_request("{\"sequence_id\":1,\"command\":\"homepage_need_networkplugin\"}"); + }); + return ""; + } + CallAfter([this] { + this->request_login(true); + }); + } + + } + } + else if (command_str.compare("update_plugin_installtip") == 0) { + if (mainframe) { + mainframe->refresh_plugin_tips(); } } //y @@ -5679,7 +5705,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) // }); // }; // cancelFn = [this, dlg]() { - // return m_is_closing || dlg->WasCanceled(); + // return is_closing() || dlg->WasCanceled(); // }; // finishFn = [this, userid = m_agent->get_user_id(), dlg, t = std::weak_ptr(m_user_sync_token)](bool ok) { // CallAfter([=]{ @@ -5694,12 +5720,16 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) // if (ok && m_agent && t.lock() == m_user_sync_token && userid == m_agent->get_user_id()) reload_settings(); // }); // }; + // cancelFn = [this]() { + // return is_closing(); + // }; // } // m_sync_update_thread = Slic3r::create_thread( // [this, progressFn, cancelFn, finishFn, t = std::weak_ptr(m_user_sync_token)] { // // get setting list, update setting list // std::string version = preset_bundle->get_vendor_profile_version(PresetBundle::QDT_BUNDLE).to_string(); + // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " start sync user preset, m_is_closing = " << m_is_closing; // int ret = m_agent->get_setting_list2(version, [this](auto info) { // auto type = info[QDT_JSON_KEY_TYPE]; // auto name = info[QDT_JSON_KEY_NAME]; @@ -5718,6 +5748,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) // return true; // } // }, progressFn, cancelFn); + // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " get_setting_list2 ret = " << ret << " m_is_closing = " << m_is_closing; // finishFn(ret == 0); // int count = 0, sync_count = 0; @@ -5762,7 +5793,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) // if (total_count == 0) { // CallAfter([this] { - // if (!m_is_closing) + // if (!is_closing()) // plater()->get_notification_manager()->close_notification_of_type(NotificationType::QDTUserPresetExceedLimit); // }); // } @@ -5801,7 +5832,7 @@ void GUI_App::stop_sync_user_preset() m_user_sync_token.reset(); if (m_sync_update_thread.joinable()) { - if (m_is_closing) + if (is_closing()) m_sync_update_thread.join(); else m_sync_update_thread.detach(); @@ -6029,13 +6060,27 @@ bool GUI_App::load_language(wxString language, bool initial) // There is a static list of lookup path prefixes in wxWidgets. Add ours. wxFileTranslationsLoader::AddCatalogLookupPathPrefix(from_u8(localization_dir())); // Get the active language from PrusaSlicer.ini, or empty string if the key does not exist. + language = app_config->get("language"); + + /* erase the unsupported language in config files*/ + { + wxLanguage cur_lang = wxLANGUAGE_UNKNOWN; + auto cur_lang_info = wxLocale::FindLanguageInfo(language); + if (cur_lang_info) { cur_lang = static_cast (cur_lang_info->Language);} + if (std::find(s_supported_languages.begin(), s_supported_languages.end(), cur_lang) == s_supported_languages.end()) + { + app_config->set("language", ""); + language = app_config->get("language"); + } + } + if (! language.empty()) BOOST_LOG_TRIVIAL(info) << boost::format("language provided by QIDIStudio.conf: %1%") % language; else { // Get the system language. const wxLanguage lang_system = wxLanguage(wxLocale::GetSystemLanguage()); - if (lang_system != wxLANGUAGE_UNKNOWN) { + if (std::find(s_supported_languages.begin(), s_supported_languages.end(), lang_system) != s_supported_languages.end()) { m_language_info_system = wxLocale::GetLanguageInfo(lang_system); #ifdef __WXMSW__ WCHAR wszLanguagesBuffer[LOCALE_NAME_MAX_LENGTH]; @@ -6263,6 +6308,7 @@ void GUI_App::update_mode() sidebar().update_mode(); //QDS: GUI refactor + mainframe->update_calibration_button_status(); if (mainframe->m_param_panel) mainframe->m_param_panel->update_mode(); if (mainframe->m_param_dialog) @@ -6895,7 +6941,9 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames) void GUI_App::MacOpenURL(const wxString& url) { +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << "get mac url " << url; +#endif if (!url.empty() && boost::starts_with(url, "qidistudioopen://")) { auto input_str_arr = split_str(url.ToStdString(), "qidistudioopen://"); @@ -6907,7 +6955,11 @@ void GUI_App::MacOpenURL(const wxString& url) } std::string download_file_url = url_decode(download_origin_url); + +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << download_file_url; +#endif + if (!download_file_url.empty() && (boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://"))) { if (m_post_initialized) { @@ -7582,6 +7634,17 @@ const ColorRGB& GUI_App::get_picking_color() const return m_picking_color; } + +FilamentColorCodeQuery* GUI_App::get_filament_color_code_query() +{ + if (!m_filament_color_code_query) + { + m_filament_color_code_query = new FilamentColorCodeQuery(); + } + + return m_filament_color_code_query; +} + bool GUI_App::open_browser_with_warning_dialog(const wxString& url, int flags/* = 0*/) { return wxLaunchDefaultBrowser(url, flags); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 0ff693e..dbb42ff 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,7 @@ struct wxLanguageInfo; namespace Slic3r { class AppConfig; +class FilamentColorCodeQuery; class PresetBundle; class PresetUpdater; class ModelObject; @@ -300,7 +302,7 @@ private: size_t m_instance_hash_int; //QDS - bool m_is_closing {false}; + std::atomic m_is_closing {false}; Slic3r::DeviceManager* m_device_manager { nullptr }; Slic3r::UserManager* m_user_manager { nullptr }; Slic3r::TaskManager* m_task_manager { nullptr }; @@ -319,6 +321,7 @@ private: VersionInfo privacy_version_info; static std::string version_display; HMSQuery *hms_query { nullptr }; + FilamentColorCodeQuery* m_filament_color_code_query{ nullptr }; boost::thread m_sync_update_thread; std::shared_ptr m_user_sync_token; @@ -359,11 +362,15 @@ public: Slic3r::TaskManager* getTaskManager() { return m_task_manager; } HMSQuery* get_hms_query() { return hms_query; } NetworkAgent* getAgent() { return m_agent; } + FilamentColorCodeQuery* get_filament_color_code_query(); 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() ? "QIDIStudio" : "QIDIStudio-gcodeviewer"; } + bool is_closing() const { return m_is_closing.load(std::memory_order_acquire); } + void set_closing(bool closing) { m_is_closing.store(closing, std::memory_order_release); } + bool show_3d_navigator() const { return app_config->get_bool("show_3d_navigator"); } void toggle_show_3d_navigator() const { app_config->set_bool("show_3d_navigator", !show_3d_navigator()); } @@ -443,7 +450,7 @@ public: int em_unit() const { return m_em_unit; } bool tabs_as_menu() const; wxSize get_min_size() const; - float toolbar_icon_scale(const bool is_limited = false) const; + float toolbar_icon_scale(bool auto_scale, const bool is_limited = false) const; void set_auto_toolbar_icon_scale(float scale) const; void check_printer_presets(); @@ -769,6 +776,26 @@ bool is_support_filament(int extruder_id); bool is_soluble_filament(int extruder_id); // check if the filament for model is in the list bool has_filaments(const std::vector& model_filaments); + +static std::vector s_supported_languages = { + wxLANGUAGE_ENGLISH, + wxLANGUAGE_CHINESE_SIMPLIFIED, + wxLANGUAGE_GERMAN, + wxLANGUAGE_FRENCH, + wxLANGUAGE_SPANISH, + wxLANGUAGE_SWEDISH, + wxLANGUAGE_DUTCH, + wxLANGUAGE_HUNGARIAN, + wxLANGUAGE_JAPANESE, + wxLANGUAGE_ITALIAN, + wxLANGUAGE_KOREAN, + wxLANGUAGE_RUSSIAN, + wxLANGUAGE_CZECH, + wxLANGUAGE_UKRAINIAN, + wxLANGUAGE_PORTUGUESE_BRAZILIAN, + wxLANGUAGE_TURKISH, + wxLANGUAGE_POLISH +}; } // namespace GUI } // Slic3r diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index ee015a8..441f834 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -107,7 +107,8 @@ std::map> SettingsFactory::PART_CAT }}, { 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_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10}, {"overhang_totally_speed", "",11}, - {"bridge_speed", "",12}, {"gap_infill_speed", "",13} + {"bridge_speed", "",12}, {"gap_infill_speed", "",13}, {"enable_height_slowdown", "", 14}, {"slowdown_start_height", "", 15}, {"slowdown_start_speed", "", 16}, {"slowdown_start_acc", "", 17}, + {"slowdown_end_height", "", 18}, {"slowdown_end_speed", "", 19}, {"slowdown_end_acc", "", 20} }} }; @@ -255,7 +256,7 @@ std::map SettingsFactory::CATEGORY_ICON = { L("Shell") , "blank_14" }, { L("Infill") , "blank_14" }, { L("Ironing") , "blank_14" }, - { L("Fuzzy Skin") , "menu_fuzzy_skin" }, + { L("Fuzzy Skin") , "fuzzy_skin" }, { L("Support") , "support" }, { L("Speed") , "blank_14" }, { L("Extruders") , "blank_14" }, @@ -501,15 +502,19 @@ void MenuFactory::append_menu_item_delete_all_cutter(wxMenu *menu) void MenuFactory::append_menu_item_edit_text(wxMenu *menu) { -#ifdef __WINDOWS__ + wxString name = _L("Edit Text"); + if (menu != &m_text_part_menu) { + const int menu_item_id = menu->FindItem(name); + if (menu_item_id != wxNOT_FOUND) + menu->Destroy(menu_item_id); + if (plater() == nullptr) + return; + if (!plater()->can_edit_text()) + return; + } append_menu_item( menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr, []() { return plater()->can_edit_text(); }, m_parent); -#else - append_menu_item( - menu, wxID_ANY, _L("Edit Text"), "", [](wxCommandEvent &) { plater()->edit_text(); }, "", nullptr, - []() { return plater()->can_edit_text(); }, m_parent); -#endif } void MenuFactory::append_menu_item_edit_svg(wxMenu *menu) @@ -528,15 +533,26 @@ void MenuFactory::append_menu_item_edit_svg(wxMenu *menu) if (menu != &m_svg_part_menu) { const int menu_item_id = menu->FindItem(name); - if (menu_item_id != wxNOT_FOUND) menu->Destroy(menu_item_id); + if (menu_item_id != wxNOT_FOUND) + menu->Destroy(menu_item_id); if (!can_edit_svg()) return; } wxString description = _L("Change SVG source file, projection, size, ..."); std::string icon = "svg_part"; auto open_svg = [](const wxCommandEvent &) { - GLGizmosManager &mng = plater()->get_view3D_canvas3D()->get_gizmos_manager(); - if (mng.get_current_type() == GLGizmosManager::Svg) mng.open_gizmo(GLGizmosManager::Svg); // close() and reopen - move to be visible + const auto& p_plater = plater(); + if (!p_plater) { + return; + } + const auto& p_canvas = p_plater->get_current_canvas3D(); + if (!p_canvas) { + return; + } + GLGizmosManager &mng = p_canvas->get_gizmos_manager(); + if (mng.get_current_type() == GLGizmosManager::Svg) { + mng.open_gizmo(GLGizmosManager::Svg); // close() and reopen - move to be visible + } mng.open_gizmo(GLGizmosManager::Svg); }; append_menu_item(menu, wxID_ANY, name, description, open_svg, icon, nullptr, can_edit_svg, m_parent); @@ -1498,6 +1514,7 @@ void MenuFactory::init(wxWindow* parent) //create_object_menu(); create_sla_object_menu(); //create_part_menu(); + create_text_part_menu(); create_svg_part_menu(); create_qdt_object_menu(); create_qdt_part_menu(); @@ -1533,6 +1550,7 @@ wxMenu* MenuFactory::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_edit_text(&m_object_menu); append_menu_item_edit_svg(&m_object_menu); append_menu_item_change_filament(&m_object_menu); { @@ -1546,7 +1564,7 @@ wxMenu* MenuFactory::sla_object_menu() { append_menu_items_convert_unit(&m_sla_object_menu); append_menu_item_settings(&m_sla_object_menu); - //append_menu_item_edit_text(&m_sla_object_menu); + append_menu_item_edit_text(&m_sla_object_menu); append_menu_item_edit_svg(&m_object_menu); //update_menu_items_instance_manipulation(mtObjectSLA); return &m_sla_object_menu; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b3a6c5c..258542d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -4,6 +4,7 @@ #include "GUI_Factories.hpp" //#include "GUI_ObjectLayers.hpp" #include "GUI_App.hpp" +#include "GLToolbar.hpp" #include "I18N.hpp" #include "Plater.hpp" #include "BitmapComboBox.hpp" @@ -211,7 +212,7 @@ ObjectList::ObjectList(wxWindow* parent) : { // Accelerators // wxAcceleratorEntry entries[25]; - wxAcceleratorEntry entries[26]; + wxAcceleratorEntry entries[27]; int index = 0; entries[index++].Set(wxACCEL_CTRL, (int)'C', wxID_COPY); entries[index++].Set(wxACCEL_CTRL, (int)'X', wxID_CUT); @@ -220,6 +221,7 @@ ObjectList::ObjectList(wxWindow* parent) : entries[index++].Set(wxACCEL_CTRL, (int)'A', wxID_SELECTALL); entries[index++].Set(wxACCEL_CTRL, (int)'Z', wxID_UNDO); entries[index++].Set(wxACCEL_CTRL, (int)'Y', wxID_REDO); + entries[index++].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int)'Z', wxID_REDO); entries[index++].Set(wxACCEL_NORMAL, WXK_BACK, wxID_DELETE); //entries[index++].Set(wxACCEL_NORMAL, int('+'), wxID_ADD); //entries[index++].Set(wxACCEL_NORMAL, WXK_NUMPAD_ADD, wxID_ADD); @@ -234,7 +236,7 @@ ObjectList::ObjectList(wxWindow* parent) : numbers_cnt++; // index++; } - wxAcceleratorTable accel(26, entries); + wxAcceleratorTable accel(27, entries); SetAcceleratorTable(accel); this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->copy(); }, wxID_COPY); @@ -374,6 +376,7 @@ void ObjectList::create_objects_ctrl() m_columns_width[colPrint] = 3; m_columns_width[colFilament] = 5; m_columns_width[colSupportPaint] = 3; + m_columns_width[colFuzzySkin] = 3; m_columns_width[colSinking] = 3; m_columns_width[colColorPaint] = 3; m_columns_width[colEditing] = 3; @@ -418,6 +421,7 @@ void ObjectList::create_objects_ctrl() // QDS AppendBitmapColumn(" ", colSupportPaint, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colSupportPaint] * em, wxALIGN_CENTER_HORIZONTAL, 0); + AppendBitmapColumn(" ", colFuzzySkin, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colFuzzySkin] * em, wxALIGN_CENTER_HORIZONTAL, 0); AppendBitmapColumn(" ", colColorPaint, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colColorPaint] * em, wxALIGN_CENTER_HORIZONTAL, 0); AppendBitmapColumn(" ", colSinking, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colSinking] * em, @@ -600,6 +604,10 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (node->HasSupportPainting()) tooltip = _(L("Click the icon to edit support painting of the object")); + } else if (col->GetModelColumn() == (unsigned int) colFuzzySkin) { + if (node->HasFuzzySkinPainting()) + tooltip = _(L("Click the icon to edit fuzzy skin painting of the object")); + } else if (col->GetModelColumn() == (unsigned int)colColorPaint) { if (node->HasColorPainting()) @@ -1016,6 +1024,12 @@ void ObjectList::set_support_paint_hidden(const bool hide) const update_name_column_width(); } +void GUI::ObjectList::set_fuzzy_skin_paint_hidden(const bool hide) const +{ + GetColumn(colFuzzySkin)->SetHidden(hide); + update_name_column_width(); +} + void GUI::ObjectList::set_sinking_hidden(const bool hide) const { GetColumn(colSinking)->SetHidden(hide); @@ -1447,6 +1461,17 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me else gizmos_mgr.reset_all_states(); } + } else if (col_num == colFuzzySkin) { + if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) { + ObjectDataViewModelNode *node = (ObjectDataViewModelNode *) item.GetID(); + if (node && node->HasFuzzySkinPainting()) { + GLGizmosManager &gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); + if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FuzzySkin) + gizmos_mgr.open_gizmo(GLGizmosManager::EType::FuzzySkin); + else + gizmos_mgr.reset_all_states(); + } + } } else if (col_num == colColorPaint) { if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) { @@ -1543,9 +1568,13 @@ void ObjectList::show_context_menu(const bool evt_context_menu) get_selected_item_indexes(obj_idx, vol_idx, item); if (obj_idx < 0 || vol_idx < 0) return; const ModelVolume *volume = object(obj_idx)->volumes[vol_idx]; - - menu = volume->is_svg() ? plater->svg_part_menu() : // ORCA fixes missing "Edit SVG" item for Add/Negative/Modifier SVG objects in object list - plater->part_menu(); + if (volume->is_text()) { + menu = plater->text_part_menu(); + } else if (volume->is_svg()) { + menu = plater->svg_part_menu(); + } else { + menu = plater->part_menu(); + } } else { menu = type & itPlate ? plater->plate_menu() : @@ -2364,8 +2393,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode // First (any) GLVolume of the selected instance. They all share the same instance matrix. const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); // Transform the new modifier to be aligned with the print bed. - const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); - new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb)); + new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse()); + const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); // Set the modifier position. auto offset = (type_name == "Slab") ? // Slab: Lift to print bed @@ -2486,10 +2515,10 @@ void GUI::ObjectList::add_new_model_object_from_old_object() { new_object->config.set_key_value("extruder", new ConfigOptionInt(min_extruder)); new_object->invalidate_bounding_box(); new_object->instances[0]->set_transformation(mo->instances[0]->get_transformation()); - // BBS: backup + // QDS: backup Slic3r::save_object_mesh(*new_object); new_object->ensure_on_bed(); - // BBS init assmeble transformation + // QDS init assmeble transformation new_object->get_model()->set_assembly_pos(new_object); object_idxs.push_back(model.objects.size() - 1); paste_objects_into_list(object_idxs); @@ -2739,7 +2768,12 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type) for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes) mv->supported_facets.reset(); break; - + case InfoItemType::FuzzySkin: + cnv->get_gizmos_manager().reset_all_states(); + Plater::TakeSnapshot(plater, "Remove fuzzy skin painting"); + for (ModelVolume *mv : (*m_objects)[obj_idx]->volumes) + mv->fuzzy_skin_facets.reset(); + break; // QDS: remove CustomSeam case InfoItemType::MmuSegmentation: cnv->get_gizmos_manager().reset_all_states(); @@ -3154,7 +3188,9 @@ void ObjectList::merge(bool to_multipart_object) auto option = new_volume->config.option("extruder"); if (!option) { auto opt = object->config.option("extruder"); - if (opt) { new_volume->config.set_key_value("extruder", new ConfigOptionInt(opt->getInt())); } + if (opt) { + new_volume->config.set_key_value("extruder", new ConfigOptionInt(opt->getInt())); + } } new_volume->mmu_segmentation_facets.assign(std::move(volume->mmu_segmentation_facets)); } @@ -3402,6 +3438,9 @@ bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& vo auto obj_idx = get_selected_obj_idx(); if (!item || obj_idx < 0) return false; + if (m_objects->size() <= obj_idx) { + return false; + } const auto volume_id = m_objects_model->GetVolumeIdByItem(item); const bool split_part = m_objects_model->GetItemType(item) == itVolume; @@ -3432,6 +3471,9 @@ bool ObjectList::is_splittable(bool to_objects) auto obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return false; + if (m_objects->size() <= obj_idx) { + return false; + } if ((*m_objects)[obj_idx]->volumes.size() > 1) return true; return (*m_objects)[obj_idx]->volumes[0]->is_splittable(); @@ -3707,24 +3749,25 @@ void ObjectList::part_selection_changed() if (type == itInfo) { InfoItemType info_type = m_objects_model->GetInfoItemType(item); - switch (info_type) - { - case InfoItemType::CustomSupports: - // QDS: remove CustomSeam - //case InfoItemType::CustomSeam: - case InfoItemType::MmuSegmentation: - { - GLGizmosManager::EType gizmo_type = info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports : - /*info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam :*/ - GLGizmosManager::EType::MmuSegmentation; - GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); - if (gizmos_mgr.get_current_type() != gizmo_type) - gizmos_mgr.open_gizmo(gizmo_type); - break; + GLGizmosManager::EType gizmo_type = GLGizmosManager::EType::Undefined; + switch (info_type){ + case InfoItemType::CustomSupports: { + gizmo_type = GLGizmosManager::EType::FdmSupports; + break; + } + case InfoItemType::FuzzySkin: { + gizmo_type = GLGizmosManager::EType::FuzzySkin; + break; + } + case InfoItemType::MmuSegmentation:{ + gizmo_type = GLGizmosManager::EType::MmuSegmentation; + break; + } + default: { break; } } - // QDS: remove Sinking - //case InfoItemType::Sinking: { break; } - default: { break; } + GLGizmosManager &gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); + if (gizmos_mgr.get_current_type() != gizmo_type) { + gizmos_mgr.open_gizmo(gizmo_type); } } else { // QDS: select object to edit config @@ -3990,7 +4033,19 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray *selectio m_objects_model->SetSupportPaintState(true, item_obj,true); } } - + { + bool shows = m_objects_model->IsFuzzySkinPainted(item_obj); + bool should_show = printer_technology() == ptFFF && + std::any_of(model_object->volumes.begin(), model_object->volumes.end(), [](const ModelVolume *mv) { return !mv->fuzzy_skin_facets.empty(); }); + if (shows && !should_show) { + m_objects_model->SetFuzzySkinPaintState(false, item_obj); + } else if (!shows && should_show) { + m_objects_model->SetFuzzySkinPaintState(true, item_obj); + } + if (color_mode_changed && shows) { + m_objects_model->SetFuzzySkinPaintState(true, item_obj, true); + } + } { bool shows = m_objects_model->IsColorPainted(item_obj); bool should_show = printer_technology() == ptFFF @@ -4045,7 +4100,26 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray *selectio this->set_support_paint_hidden(false); } } + { + bool shows = this->GetColumn(colFuzzySkin)->IsShown(); + bool should_show = false; + for (ModelObject *mo : *m_objects) { + for (ModelVolume *mv : mo->volumes) { + if (!mv->fuzzy_skin_facets.empty()) { + should_show = true; + break; + } + } + if (should_show) + break; + } + if (shows && !should_show) { + this->set_fuzzy_skin_paint_hidden(true); + } else if (!shows && should_show) { + this->set_fuzzy_skin_paint_hidden(false); + } + } { bool shows = this->GetColumn(colColorPaint)->IsShown(); bool should_show = false; @@ -5941,6 +6015,9 @@ void ObjectList::fix_through_netfabb() void ObjectList::simplify() { auto plater = wxGetApp().plater(); + if (!plater) { + return; + } GLGizmosManager& gizmos_mgr = plater->get_view3D_canvas3D()->get_gizmos_manager(); // Do not simplify when a gizmo is open. There might be issues with updates @@ -5984,6 +6061,7 @@ void ObjectList::msw_rescale() GetColumn(colFilament)->SetWidth( 5 * em); // QDS GetColumn(colSupportPaint)->SetWidth(3 * em); + GetColumn(colFuzzySkin)->SetWidth(3 * em); GetColumn(colColorPaint)->SetWidth(3 * em); GetColumn(colSinking)->SetWidth(3 * em); GetColumn(colEditing )->SetWidth( 3 * em); @@ -6041,12 +6119,17 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event) event.Veto(); // Not edit with NSTableView's text auto col = event.GetColumn(); auto item = event.GetItem(); - if (col == colPrint) { + const auto p_plater = wxGetApp().plater(); + if (col == colHeight) { + enable_layers_editing(); + return; + } + else if (col == colPrint) { toggle_printable_state(); return; } else if (col == colSupportPaint) { ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); - if (node->HasSupportPainting()) { + if (node && node->HasSupportPainting()) { GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FdmSupports) gizmos_mgr.open_gizmo(GLGizmosManager::EType::FdmSupports); @@ -6054,10 +6137,20 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event) gizmos_mgr.reset_all_states(); } return; + } else if (col == colFuzzySkin) { + ObjectDataViewModelNode *node = (ObjectDataViewModelNode *) item.GetID(); + if (node && node->HasFuzzySkinPainting()) { + GLGizmosManager &gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); + if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FuzzySkin) + gizmos_mgr.open_gizmo(GLGizmosManager::EType::FuzzySkin); + else + gizmos_mgr.reset_all_states(); + } + return; } else if (col == colColorPaint) { ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); - if (node->HasColorPainting()) { + if (node && 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); @@ -6439,11 +6532,6 @@ ModelObject* ObjectList::object(const int obj_idx) const return (*m_objects)[obj_idx]; } -bool ObjectList::has_paint_on_segmentation() -{ - return m_objects_model->HasInfoItem(InfoItemType::MmuSegmentation); -} - void ObjectList::apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object, bool need_update_assemble_matrix) { const Geometry::Transformation &instance_transformation = model_object->instances[0]->get_transformation(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 4ce78d6..c89c8f1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -231,6 +231,7 @@ public: // QDS void set_color_paint_hidden(const bool hide) const; void set_support_paint_hidden(const bool hide) const; + void set_fuzzy_skin_paint_hidden(const bool hide) const; void set_sinking_hidden(const bool hide) const; // update extruder in current config @@ -455,8 +456,6 @@ public: void set_extruder_for_selected_items(const int extruder); wxDataViewItemArray reorder_volumes_and_get_selection(int obj_idx, std::function add_to_selection = nullptr); void apply_volumes_order(); - bool has_paint_on_segmentation(); - // QDS void on_plate_added(PartPlate* part_plate); void on_plate_deleted(int plate_index); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index bedc0d9..4e6876d 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -109,8 +109,6 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig m_canvas->enable_return_toolbar(true); //QDS: GUI refactor: GLToolbar m_canvas->enable_select_plate_toolbar(false); - m_canvas->enable_assemble_view_toolbar(true); - m_canvas->enable_separator_toolbar(true); m_canvas->enable_labels(true); m_canvas->enable_slope(true); @@ -303,7 +301,6 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) if (wxGetApp().is_editor()) { m_canvas->enable_select_plate_toolbar(true); } - m_canvas->enable_assemble_view_toolbar(false); // sizer, m_canvas_widget m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_layers_slider_from_canvas, this); @@ -855,13 +852,11 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint m_canvas->set_config(config); m_canvas->enable_gizmos(true); m_canvas->enable_selection(true); - m_canvas->enable_main_toolbar(false); + m_canvas->enable_main_toolbar(true); m_canvas->enable_labels(false); m_canvas->enable_slope(false); //QDS: GUI refactor: GLToolbar - m_canvas->enable_assemble_view_toolbar(false); m_canvas->enable_return_toolbar(true); - m_canvas->enable_separator_toolbar(false); //m_canvas->set_show_world_axes(true);//wait for GitHub users to see if they have this requirement // QDS: set volume_selection_mode to Volume //same to 3d //m_canvas->get_selection().set_volume_selection_mode(Selection::Instance); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 5580722..3a2e935 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -100,8 +100,8 @@ const double GLGizmoAdvancedCut::Margin = 20.0; const std::array GLGizmoAdvancedCut::GrabberColor = { 1.0, 1.0, 0.0, 1.0 }; const std::array GLGizmoAdvancedCut::GrabberHoverColor = { 0.7, 0.7, 0.0, 1.0}; -GLGizmoAdvancedCut::GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoRotate3D(parent, icon_filename, sprite_id, nullptr) +GLGizmoAdvancedCut::GLGizmoAdvancedCut(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoRotate3D(parent, sprite_id, nullptr) , m_movement(0.0) , m_buffered_movement(0.0) , m_keep_upper(true) @@ -171,10 +171,11 @@ bool GLGizmoAdvancedCut::gizmo_event(SLAGizmoEventType action, const Vec2d &mous else if (action == SLAGizmoEventType::RightDown) { if (!m_connectors_editing && m_cut_mode == CutMode::cutPlanar) { //&& control_down // Check the internal part raycasters. - if (m_part_selection && m_part_selection->valid()) { - m_part_selection->toggle_selection(mouse_position); - check_and_update_connectors_state(); // after a contour is deactivated, its connectors are inside the object - } + if (m_part_selection && !m_part_selection->valid()) + process_contours(); + m_part_selection->toggle_selection(mouse_position); + check_and_update_connectors_state(); // after a contour is deactivated, its connectors are inside the object + return true; } if (m_hover_id < c_connectors_group_id) @@ -438,6 +439,11 @@ BoundingBoxf3 GLGizmoAdvancedCut::get_bounding_box() const return t_aabb; } +std::string GLGizmoAdvancedCut::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_cut_dark.svg" : "toolbar_cut.svg"; +} + bool GLGizmoAdvancedCut::on_init() { if (!GLGizmoRotate3D::on_init()) @@ -475,6 +481,14 @@ std::string GLGizmoAdvancedCut::on_get_name() const } } +void GLGizmoAdvancedCut::apply_color_clip_plane_colors() +{ + if (CutMode(m_cut_mode) == CutMode::cutTongueAndGroove) + m_parent.set_color_clip_plane_colors({CUT_PLANE_DEF_COLOR, CUT_PLANE_DEF_COLOR}); + else + m_parent.set_color_clip_plane_colors({UPPER_PART_COLOR, LOWER_PART_COLOR}); +} + void GLGizmoAdvancedCut::on_load(cereal::BinaryInputArchive &ar) { size_t mode; @@ -530,7 +544,6 @@ void GLGizmoAdvancedCut::data_changed(bool is_serializing) update_bb(); if (auto oc = m_c->object_clipper()) { oc->set_behaviour(m_connectors_editing, m_connectors_editing, double(m_contour_width)); - reset_cut_by_contours(); } } } @@ -541,6 +554,7 @@ void GLGizmoAdvancedCut::on_set_state() // Reset m_cut_z on gizmo activation if (get_state() == On) { + m_parent.set_use_color_clip_plane(true); const Selection &selection = m_parent.get_selection(); if (selection.is_empty()) {//check selection again close(); @@ -568,6 +582,7 @@ void GLGizmoAdvancedCut::on_set_state() oc->release(); } m_selected.clear(); + m_parent.set_use_color_clip_plane(false); m_c->selection_info()->set_use_shift(false); // Make sure that the part selection data are released when the gizmo is closed. @@ -611,7 +626,6 @@ CommonGizmosDataID GLGizmoAdvancedCut::on_get_requirements() const { return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::InstancesHider) - | int(CommonGizmosDataID::Raycaster) | int(CommonGizmosDataID::ObjectClipper)); } @@ -757,7 +771,9 @@ void GLGizmoAdvancedCut::on_render() if (m_part_selection) { if (!m_connectors_editing) { - if (m_is_dragging == false) { m_part_selection->part_render(nullptr,nullptr); } + if (m_is_dragging == false) { + m_part_selection->part_render(nullptr,nullptr); + } } else { m_part_selection->part_render(&m_plane_center, &m_plane_normal); } @@ -776,8 +792,8 @@ void GLGizmoAdvancedCut::on_render_for_picking() const Camera& camera = wxGetApp().plater()->get_picking_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& projection_matrix = camera.get_projection_matrix(); + glsafe(::glDisable(GL_DEPTH_TEST)); if (!m_connectors_editing) { - glsafe(::glDisable(GL_DEPTH_TEST)); std::array color; // pick plane { @@ -810,7 +826,6 @@ void GLGizmoAdvancedCut::on_render_for_picking() } } else { - glsafe(::glEnable(GL_DEPTH_TEST)); auto inst_id = m_c->selection_info()->get_active_instance(); if (inst_id < 0) return; @@ -955,7 +970,7 @@ static void check_objects_after_cut(const ModelObjectPtrs &objects) } } -void synchronize_model_after_cut(Model &model, const CutObjectBase &cut_id) + void synchronize_model_after_cut(Model &model, const CutObjectBase &cut_id) { for (ModelObject *obj : model.objects) if (obj->is_cut() && obj->cut_id.has_same_id(cut_id) && !obj->cut_id.is_equal(cut_id)) obj->cut_id.copy(cut_id); @@ -1202,6 +1217,7 @@ void GLGizmoAdvancedCut::update_clipper() double offset = normal.dot(m_plane_center); double dist = normal.dot(beg); + m_parent.set_color_clip_plane(normal, offset); if (!is_looking_forward()) { // recalculate normal and offset for clipping plane, if camera is looking downward to cut plane normal = m_rotate_matrix * (-1. * Vec3d::UnitZ()); @@ -1325,7 +1341,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() m_grabber_model.render_geometry(); } - m_move_x_grabber.center = m_plane_center + m_plane_x_direction * Offset; + m_move_x_grabber.center = m_plane_center + m_plane_x_direction * radius; if (is_render_x_grabber) { Transform3d model_matrix{ Transform3d::Identity() }; @@ -1341,23 +1357,28 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() } } - bool hover = (m_hover_id == get_group_id()); - std::array render_color; - if (hover) { - render_color = GrabberHoverColor; - } else - render_color = GrabberColor; - // QDS set to fixed size grabber // float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); GLModel &cube_z = m_move_z_grabber.get_cube(); + const auto get_render_color = [this](unsigned int id)->std::array { + bool hover = (m_hover_id == id); + std::array render_color; + if (hover) { + render_color = GrabberHoverColor; + } + else + render_color = GrabberColor; + return render_color; + }; + if (is_render_z_grabber) { Vec3d t_z_dir = m_move_z_grabber.center - m_plane_center; const auto scale_z = t_z_dir.stableNorm(); const Vec3d target_z = m_plane_center + scale_z * t_z_dir.normalized(); Transform3d cube_mat_z = Geometry::translation_transform(target_z) * m_rotate_matrix * Geometry::scale_transform(fullsize); // m_move_z_grabber.m_matrix = cube_mat_z; + std::array render_color = get_render_color(c_cube_z_move_id); render_glmodel(cube_z, render_color, view_matrix * m_move_z_grabber.m_matrix, projection_matrix); } @@ -1368,6 +1389,8 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() const Vec3d target_x = m_plane_center + scale_x * t_x_dir.normalized(); Transform3d cube_mat_x = Geometry::translation_transform(target_x) * m_rotate_matrix * Geometry::scale_transform(fullsize); // m_move_x_grabber.m_matrix = cube_mat_x; + + std::array render_color = get_render_color(c_cube_x_move_id); render_glmodel(cube_x, render_color, view_matrix * m_move_x_grabber.m_matrix, projection_matrix); } // Should be placed at last, because GLGizmoRotate3D clears depth buffer @@ -1530,6 +1553,7 @@ void GLGizmoAdvancedCut::render_cut_line() { glsafe(::glEnable(GL_LINE_STIPPLE)); } + glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); @@ -1778,6 +1802,7 @@ void GLGizmoAdvancedCut::switch_to_mode(CutMode new_mode) { if (m_cut_mode == CutMode::cutTongueAndGroove) { m_cut_to_parts = false;//into Groove function,cancel m_cut_to_parts } + apply_color_clip_plane_colors(); if (auto oc = m_c->object_clipper()) { m_contour_width = m_cut_mode == CutMode::cutTongueAndGroove ? 0.f : 0.4f; oc->set_behaviour(m_connectors_editing, m_connectors_editing, double(m_contour_width)); // for debug @@ -1842,6 +1867,13 @@ bool GLGizmoAdvancedCut::has_valid_groove() const return false; const Transform3d cp_matrix = Geometry::translation_transform(m_plane_center) * m_rotate_matrix; + if (!m_c->raycaster()) { + if (!m_c->selection_info()) { + m_c->update(get_requirements()); + } + wxBusyCursor wait; + m_c->raycaster_ptr()->update(); + } for (size_t id = 0; id < m_groove_vertices.size(); id += 2) { const Vec3d beg = cp_matrix * m_groove_vertices[id]; @@ -1880,7 +1912,7 @@ void GLGizmoAdvancedCut::reset_cut_by_contours() return; process_contours(); } else { - process_contours(); + toggle_model_objects_visibility(); } } @@ -1929,6 +1961,7 @@ void GLGizmoAdvancedCut::render_flip_plane_button(bool disable_pred /*=false*/) ImGui::PopStyleColor(); } + void GLGizmoAdvancedCut::toggle_model_objects_visibility(bool show_in_3d) { if (m_part_selection && m_part_selection->valid() && show_in_3d == false && (m_is_dragging == false || m_connectors_editing)) // QDT @@ -1941,6 +1974,9 @@ void GLGizmoAdvancedCut::toggle_model_objects_visibility(bool show_in_3d) if (idx < 0) { return; } + if (idx >= model_objects.size()) { + return; + } m_parent.toggle_model_objects_visibility(true, model_objects[idx], selection.get_instance_idx()); } } @@ -1985,7 +2021,7 @@ void GLGizmoAdvancedCut::update_bb() else set_center_pos(m_bb_center); reset_cut_by_contours(); - + apply_color_clip_plane_colors(); m_contour_width = m_cut_mode == CutMode::cutTongueAndGroove ? 0.f : 0.4f; m_radius = box.radius(); @@ -2160,8 +2196,17 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b unit_size = vec_max + ImGui::GetStyle().FramePadding.x * 2.0f; } - CutConnectors &connectors = m_c->selection_info()->model_object()->cut_connectors; - const bool has_connectors = !connectors.empty(); + bool has_connectors = false; + if (m_c) { + const auto& p_selection_info = m_c->selection_info(); + if (p_selection_info) { + const auto& p_model_object = p_selection_info->model_object(); + if (p_model_object) { + const auto& t_commectors = p_model_object->cut_connectors; + has_connectors = !t_commectors.empty(); + } + } + } m_imgui->disabled_begin(has_connectors); if (render_cut_mode_combo(caption_size + 1 * space_size, 4 * unit_size + 0.5 * space_size)) { @@ -2352,7 +2397,7 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(x, get_cur_y); - float f_scale = m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::SameLine(); @@ -2370,7 +2415,19 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b void GLGizmoAdvancedCut::init_connectors_input_window_data() { - CutConnectors &connectors = m_c->selection_info()->model_object()->cut_connectors; + if (!m_c) { + return; + } + const auto p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + if (!p_model_object) { + return; + } + + CutConnectors &connectors = p_model_object->cut_connectors; float connectors_cap = m_imgui->calc_text_size(_L("Connectors")).x; float type_cap = m_imgui->calc_text_size(_L("Type")).x; @@ -2438,7 +2495,18 @@ void GLGizmoAdvancedCut::init_connectors_input_window_data() void GLGizmoAdvancedCut::render_connectors_input_window(float x, float y, float bottom_limit) { - CutConnectors &connectors = m_c->selection_info()->model_object()->cut_connectors; + if (!m_c) { + return; + } + const auto p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + if (!p_model_object) { + return; + } + CutConnectors &connectors = p_model_object->cut_connectors; // update when change input window m_imgui->set_requires_extra_frame(); @@ -2525,7 +2593,7 @@ void GLGizmoAdvancedCut::render_connectors_input_window(float x, float y, float float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(x, get_cur_y); - float f_scale = m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::SameLine(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index 7e04c76..d70ece0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -208,9 +208,9 @@ private: //GLSelectionRectangle m_selection_rectangle; public: - GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoAdvancedCut(GLCanvas3D& parent, unsigned int sprite_id); - bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down) override; bool on_key(const wxKeyEvent &evt) override; double get_movement() const { return m_movement; } @@ -228,6 +228,9 @@ public: BoundingBoxf3 get_bounding_box() const override; + std::string get_icon_filename(bool b_dark_mode) const override; + bool wants_enter_leave_snapshots() const override { return true; } + protected: virtual bool on_init(); virtual void on_load(cereal::BinaryInputArchive &ar) override; @@ -235,6 +238,7 @@ protected: virtual void data_changed(bool is_serializing) override; virtual std::string on_get_name() const; virtual std::string on_get_name_str() override { return "Cut"; } + void apply_color_clip_plane_colors(); virtual void on_set_state(); void close(); virtual bool on_is_activable() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp index a955a12..e371628 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAssembly.cpp @@ -21,12 +21,17 @@ namespace Slic3r { namespace GUI { -GLGizmoAssembly::GLGizmoAssembly(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : - GLGizmoMeasure(parent, icon_filename, sprite_id) +GLGizmoAssembly::GLGizmoAssembly(GLCanvas3D& parent, unsigned int sprite_id) : + GLGizmoMeasure(parent, sprite_id) { m_measure_mode = EMeasureMode::ONLY_ASSEMBLY; } +std::string GLGizmoAssembly::get_icon_filename(bool is_dark_mode) const +{ + return is_dark_mode ? "toolbar_assembly_dark.svg" : "toolbar_assembly.svg"; +} + bool GLGizmoAssembly::on_init() { GLGizmoMeasure::on_init(); m_shortcut_key = WXK_CONTROL_Y; @@ -50,7 +55,6 @@ std::string GLGizmoAssembly::on_get_name() const bool GLGizmoAssembly::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - //1.9.5 if (selection.is_wipe_tower()) { return false; } @@ -118,7 +122,7 @@ void GLGizmoAssembly::on_render_input_window(float x, float y, float bottom_limi } show_tooltip_information(caption_max, x, get_cur_y); - float f_scale =m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::PopStyleVar(2); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAssembly.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAssembly.hpp index 4804af9..9c3d75d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAssembly.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAssembly.hpp @@ -10,7 +10,7 @@ class GLGizmoAssembly : public GLGizmoMeasure { public: - GLGizmoAssembly(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoAssembly(GLCanvas3D& parent, unsigned int sprite_id); /// /// Apply rotation on select plane /// @@ -23,9 +23,12 @@ public: bool wants_enter_leave_snapshots() const override { return true; } std::string get_gizmo_entering_text() const override { return _u8L("Entering Assembly gizmo"); } std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Assembly gizmo"); } + + std::string get_icon_filename(bool is_dark_mode) const override; protected: bool on_init() override; std::string on_get_name() const override; + virtual std::string on_get_name_str() override { return "Assembly"; } bool on_is_activable() const override; //void on_render() override; //void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 6739734..516cf5d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -138,7 +138,6 @@ void GLGizmoBase::Grabber::render(const std::array& render_color, bool //float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); //float fullsize = get_grabber_size(); - const_cast(&cube)->set_color(-1, render_color); const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); @@ -227,7 +226,7 @@ bool GLGizmoBase::render_combo(const std::string &label, const std::vectorset_uniform("view_model_matrix", view_model_matrix * model_matrix); m_cross_mark.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); m_cross_mark.render_geometry(); + glsafe(::glEnable(GL_DEPTH_TEST)); + wxGetApp().unbind_shader(); +} +void GLGizmoBase::render_lines(const std::vector &points) +{ + if (!m_lines_mark.is_initialized()) { + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Lines; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3; + + for (int i = 1; i < points.size(); i++) { + Vec3f p0 = points[i - 1].cast(); + Vec3f p1 = points[i].cast(); + geo.add_vertex(p0); + geo.add_vertex(p1); + geo.add_line(i - 1, i); + } + m_lines_mark.init_from(std::move(geo)); + } + const auto &p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) return; + + wxGetApp().bind_shader(p_flat_shader); + + const Camera &camera = wxGetApp().plater()->get_camera(); + const auto & view_matrix = camera.get_view_matrix(); + const auto & proj_matrix = camera.get_projection_matrix(); + + const auto view_model_matrix = view_matrix; + glsafe(::glDisable(GL_DEPTH_TEST)); + + const auto &ogl_manager = wxGetApp().get_opengl_manager(); + if (ogl_manager) { ogl_manager->set_line_width(2.0f); } + + Transform3d model_matrix{Transform3d::Identity()}; + + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + m_lines_mark.set_color({1.0f, 1.0f, 0.0f, 1.0f}); + m_lines_mark.render_geometry(); + glsafe(::glEnable(GL_DEPTH_TEST)); wxGetApp().unbind_shader(); } @@ -288,12 +331,11 @@ float GLGizmoBase::get_grabber_size() return grabber_size; } -GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id) +GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, unsigned int sprite_id) : m_parent(parent) , m_group_id(-1) , m_state(Off) , m_shortcut_key(0) - , m_icon_filename(icon_filename) , m_sprite_id(sprite_id) , m_hover_id(-1) , m_dragging(false) @@ -347,10 +389,6 @@ void GLGizmoBase::set_state(EState state) on_set_state(); } -void GLGizmoBase::set_icon_filename(const std::string &filename) { - m_icon_filename = filename; -} - bool GLGizmoBase::on_key(const wxKeyEvent& key_event) { return false; @@ -686,7 +724,12 @@ Transform3d GLGizmoBase::get_corss_mask_model_matrix(ECrossMaskType type, const void GLGizmoBase::render_input_window(float x, float y, float bottom_limit) { - on_render_input_window(x, y, bottom_limit); + auto canvas_w = float(m_parent.get_canvas_size().get_width()); + auto canvas_h = float(m_parent.get_canvas_size().get_height()); + float zoom = (float)m_parent.get_active_camera().get_zoom(); + const float final_x = 0.5 * canvas_w + x * zoom; + + on_render_input_window(final_x, y, bottom_limit); if (m_first_input_window_render) { // for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame // so, we forces another frame rendering the first time the imgui window is shown @@ -702,6 +745,11 @@ BoundingBoxf3 GLGizmoBase::get_bounding_box() const return t_aabb; } +bool GLGizmoBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) +{ + return false; +} + void GLGizmoBase::render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, const Transform3d& projection_matrix, bool for_picking, float emission_factor) { const auto& shader = wxGetApp().get_shader(for_picking ? "flat" : "gouraud_light"); @@ -735,7 +783,10 @@ std::string GLGizmoBase::get_name(bool include_shortcut) const return out; } - +void GLGizmoBase::set_serializing(bool is_serializing) +{ + m_is_serializing = is_serializing; +} // Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components // were not interpolated by alpha blending or multi sampling. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index fec5131..bd797a0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/3DScene.hpp" +#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include @@ -13,6 +14,7 @@ #include #include +#include #define ENABLE_FIXED_GRABBER 1 @@ -28,7 +30,6 @@ namespace GUI { #define MAX_NUM 9999.99 #define MAX_SIZE "9999.99" - class ImGuiWrapper; class GLCanvas3D; enum class CommonGizmosDataID; @@ -61,6 +62,7 @@ public: static void update_render_colors(); static void load_render_colors(); + struct Grabber { static const float SizeFactor; @@ -119,7 +121,6 @@ protected: int m_group_id; EState m_state; int m_shortcut_key; - std::string m_icon_filename; unsigned int m_sprite_id; int m_hover_id; enum GripperType { @@ -150,8 +151,10 @@ protected: mutable GLModel m_cylinder; GLModel m_sphere; GLModel m_cross_mark; + GLModel m_lines_mark; bool m_is_dark_mode = false; + bool m_is_serializing = false; std::chrono::system_clock::time_point start; enum DoubleShowType { @@ -175,12 +178,12 @@ protected: DoubleShowType show_type = DoubleShowType::Normal); bool render_combo(const std::string &label, const std::vector &lines, size_t &selection_idx, float label_width, float item_width); - void render_cross_mark(const Transform3d& matrix, const Vec3f& target); + void render_cross_mark(const Transform3d& matrix, const Vec3f& target,bool single =false); + void render_lines(const std::vector &points); static float get_grabber_size(); public: GLGizmoBase(GLCanvas3D& parent, - const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoBase() {} @@ -196,11 +199,10 @@ public: EState get_state() const { return m_state; } void set_state(EState state); + void set_serializing(bool is_serializing); int get_shortcut_key() const { return m_shortcut_key; } - const std::string& get_icon_filename() const { return m_icon_filename; } - - void set_icon_filename(const std::string& filename); + virtual std::string get_icon_filename(bool b_dark_mode) const = 0; bool is_activable() const { return on_is_activable(); } bool is_selectable() const { return on_is_selectable(); } @@ -249,6 +251,8 @@ public: virtual BoundingBoxf3 get_bounding_box() const; + virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + static void render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, const Transform3d& projection_matrix, bool for_picking = false, float emission_factor = 0.0f); protected: float last_input_window_width = 0; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp index 20aac31..a40d501 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp @@ -31,7 +31,7 @@ static ModelVolume *get_model_volume(const Selection &selection, Model &model) return obj->volumes[cid.volume_id]; } -GLGizmoBrimEars::GLGizmoBrimEars(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) {} +GLGizmoBrimEars::GLGizmoBrimEars(GLCanvas3D &parent, unsigned int sprite_id) : GLGizmoBase(parent, sprite_id) {} bool GLGizmoBrimEars::on_init() { @@ -286,6 +286,11 @@ void GLGizmoBrimEars::data_changed(bool is_serializing) set_brim_data(); } +std::string GLGizmoBrimEars::get_icon_filename(bool is_dark_mode) const +{ + return is_dark_mode ? "toolbar_brimears_dark.svg" : "toolbar_brimears.svg"; +} + void GLGizmoBrimEars::set_brim_data() { if (!m_c->selection_info()) return; @@ -531,7 +536,15 @@ void GLGizmoBrimEars::on_render_input_window(float x, float y, float bottom_limi static float last_y = 0.0f; static float last_h = 0.0f; - ModelObject *mo = m_c->selection_info()->model_object(); + if (!m_c) { + return; + } + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + + ModelObject *mo = p_selection_info->model_object(); if (!mo) return; @@ -640,7 +653,7 @@ void GLGizmoBrimEars::on_render_input_window(float x, float y, float bottom_limi // ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); - float f_scale = m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); if (m_imgui->button(m_desc["auto_generate"])) { auto_generate(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp index abe4037..4f8481b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp @@ -72,10 +72,10 @@ private: }; public: - GLGizmoBrimEars(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoBrimEars(GLCanvas3D& parent, unsigned int sprite_id); virtual ~GLGizmoBrimEars() = default; void data_changed(bool is_serializing) override; - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; void delete_selected_points(); void update_model_object(); //ClippingPlane get_sla_clipping_plane() const; @@ -86,6 +86,8 @@ public: std::string get_gizmo_entering_text() const override { return "Entering Brim Ears"; } std::string get_gizmo_leaving_text() const override { return "Leaving Brim Ears"; } + std::string get_icon_filename(bool is_dark_mode) const override; + private: void set_brim_data(); bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp index cb63ff4..8914d55 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp @@ -30,6 +30,11 @@ std::string GLGizmoFaceDetector::on_get_name() const return (_L("Face recognition") + " [P]").ToUTF8().data(); } +std::string GLGizmoFaceDetector::get_icon_filename(bool is_dark_mode) const +{ + return "face recognition.svg"; +} + void GLGizmoFaceDetector::on_render() { if (m_model.is_initialized()) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp index 7906f30..b43b92c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp @@ -11,9 +11,10 @@ namespace GUI { class GLGizmoFaceDetector : public GLGizmoBase { public: - GLGizmoFaceDetector(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) {} + GLGizmoFaceDetector(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) {} + std::string get_icon_filename(bool is_dark_mode) const override; protected: void on_render() override; void on_render_for_picking() override {} diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 51dd57f..8bde014 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -22,8 +22,8 @@ namespace Slic3r::GUI { -GLGizmoFdmSupports::GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoPainterBase(parent, icon_filename, sprite_id), m_current_tool(ImGui::CircleButtonIcon) +GLGizmoFdmSupports::GLGizmoFdmSupports(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoPainterBase(parent, sprite_id), m_current_tool(ImGui::CircleButtonIcon) { m_tool_type = ToolType::BRUSH; m_cursor_type = TriangleSelector::CursorType::CIRCLE; @@ -163,6 +163,11 @@ bool GLGizmoFdmSupports::on_key_down_select_tool_type(int keyCode) { return true; } +std::string GLGizmoFdmSupports::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_support_dark.svg" : "toolbar_support.svg"; +} + // QDS void GLGizmoFdmSupports::render_triangles(const Selection& selection) const { @@ -226,7 +231,15 @@ void GLGizmoFdmSupports::on_set_state() void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit) { init_print_instance(); - if (! m_c->selection_info()->model_object()) + if (!m_c) { + return; + } + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + if (!p_model_object) return; m_imgui_start_pos[0] = x; m_imgui_start_pos[1] = y; @@ -471,7 +484,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); - float f_scale =m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::SameLine(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index 881bc60..92c4801 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -13,7 +13,7 @@ namespace Slic3r::GUI { class GLGizmoFdmSupports : public GLGizmoPainterBase { public: - GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoFdmSupports(GLCanvas3D& parent, unsigned int sprite_id); void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; @@ -27,6 +27,8 @@ public: //QDS bool on_key_down_select_tool_type(int keyCode); + std::string get_icon_filename(bool b_dark_mode) const override; + protected: void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 29790ca..20f0e08 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -17,8 +17,8 @@ namespace Slic3r { namespace GUI { -GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) , m_normal(Vec3d::Zero()) , m_starting_center(Vec3d::Zero()) { @@ -92,7 +92,6 @@ void GLGizmoFlatten::on_render_input_window(float x, float y, float bottom_limit ImGuiWrapper::pop_toolbar_style(); } - std::string GLGizmoFlatten::on_get_name() const { if (!on_is_activable() && m_state == EState::Off) { @@ -216,19 +215,20 @@ void GLGizmoFlatten::on_render() if (m_last_hit_facet != m_hit_facet) { m_last_hit_facet = m_hit_facet; m_one_tri_model.reset(); - auto mv = mo->volumes[m_rr.mesh_id]; - auto world_tran = (mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix()).cast(); - auto &vertices = mv->mesh().its.vertices; - auto &cur_faces = mv->mesh().its.indices; + const auto& mv = mo->volumes[m_rr.mesh_id]; + const auto world_tran = (mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix()).cast(); + const auto& vertices = mv->mesh().its.vertices; + const auto& cur_faces = mv->mesh().its.indices; if (m_hit_facet < cur_faces.size()) { - auto v0 = world_tran * vertices[cur_faces[m_hit_facet][0]] + m_rr.normal * 0.05; - auto v1 = world_tran * vertices[cur_faces[m_hit_facet][1]] + m_rr.normal * 0.05; - auto v2 = world_tran * vertices[cur_faces[m_hit_facet][2]] + m_rr.normal * 0.05; indexed_triangle_set temp_its; - temp_its.indices.push_back({0, 1, 2}); - temp_its.vertices.push_back(v0); - temp_its.vertices.push_back(v1); - temp_its.vertices.push_back(v2); + const auto normal_bias = m_rr.normal * 0.05f; + for (int i = 0; i < 3; ++i) { + const auto& mesh_v = vertices[cur_faces[m_hit_facet][i]]; + auto v = world_tran * Vec4f(mesh_v[0], mesh_v[1], mesh_v[2], 1.0f); + v /= (abs(v[3]) > 1e-6f ? v[3] : 1e-6f); + temp_its.vertices.push_back({ v[0] + normal_bias[0], v[1] + normal_bias[1], v[2] + normal_bias[2] }); + } + temp_its.indices.push_back({ 0, 1, 2 }); m_one_tri_model.init_from(temp_its); } } @@ -250,7 +250,7 @@ void GLGizmoFlatten::on_render() void GLGizmoFlatten::on_render_for_picking() { - const auto& p_flat_shader = wxGetApp().get_shader("flat"); + const auto& p_flat_shader = wxGetApp().get_shader("flat"); if (!p_flat_shader) { return; } @@ -591,5 +591,10 @@ void GLGizmoFlatten::data_changed(bool is_serializing) } } +std::string GLGizmoFlatten::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_flatten_dark.svg" : "toolbar_flatten.svg"; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index cd21e8b..85c0f08 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -45,10 +45,11 @@ private: FlattenType m_faltten_type{FlattenType::Default}; public: - GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id); Vec3d get_flattening_normal() const; void data_changed(bool is_serializing) override; + std::string get_icon_filename(bool b_dark_mode) const override; protected: virtual bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp new file mode 100644 index 0000000..794be57 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp @@ -0,0 +1,550 @@ +#include "GLGizmoFuzzySkin.hpp" + +#include "libslic3r/Model.hpp" +//QDS +#include "libslic3r/Layer.hpp" +#include "libslic3r/Thread.hpp" + +//#include "slic3r/GUI/3DScene.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/ImGuiWrapper.hpp" +#include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/GUI_ObjectList.hpp" +#include "slic3r/GUI/format.hpp" +#include "slic3r/GUI/GUI.hpp" +#include "slic3r/Utils/UndoRedo.hpp" + + +#include + +#include + +namespace Slic3r::GUI { + +GLGizmoFuzzySkin::GLGizmoFuzzySkin(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoPainterBase(parent, sprite_id), m_current_tool(ImGui::CircleButtonIcon) +{ + m_tool_type = ToolType::BRUSH; + m_cursor_type = TriangleSelector::CursorType::CIRCLE; +} + +void GLGizmoFuzzySkin::data_changed(bool is_serializing) { + set_painter_gizmo_data(m_parent.get_selection()); +} + +void GLGizmoFuzzySkin::on_shutdown() +{ + //QDS + //wait the thread + if (m_thread.joinable()) { + Print *print = m_print_instance.print_object->print(); + if (print) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "cancel the print"; + print->cancel(); + } + //join the thread + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "try to join thread for 2000 ms"; + auto ret = m_thread.try_join_for(boost::chrono::milliseconds(2000)); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "join thread returns "<object_clipper()->render_cut(); + m_c->instances_hider()->render_cut(); + render_cursor(); + + glsafe(::glDisable(GL_BLEND)); +} + +// QDS +bool GLGizmoFuzzySkin::on_key_down_select_tool_type(int keyCode) { + switch (keyCode) + { + case 'F': + m_current_tool = ImGui::FillButtonIcon; + break; + case 'S': + m_current_tool = ImGui::SphereButtonIcon; + break; + case 'C': + m_current_tool = ImGui::CircleButtonIcon; + break; + case 'T': + m_current_tool = ImGui::TriangleButtonIcon; break; + default: + return false; + break; + } + return true; +} + +std::string GLGizmoFuzzySkin::get_icon_filename(bool is_dark_mode) const +{ + return is_dark_mode ? "toolbar_fuzzyskin_dark.svg" : "toolbar_fuzzyskin.svg"; +} + +// QDS +void GLGizmoFuzzySkin::render_triangles(const Selection& selection) const +{ + ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); + const auto & shader = wxGetApp().get_shader("mm_gouraud"); + if (!shader) return; + wxGetApp().bind_shader(shader); + shader->set_uniform("clipping_plane", clp_data.clp_dataf); + shader->set_uniform("z_range", clp_data.z_range); + shader->set_uniform("slope.actived", m_parent.is_using_slope()); + ScopeGuard guard([shader]() { + if (shader) wxGetApp().unbind_shader(); + }); + + // QDS: to improve the random white pixel issue + glsafe(::glDisable(GL_CULL_FACE)); + + const ModelObject *mo = m_c->selection_info()->model_object(); + int mesh_id = -1; + for (const ModelVolume *mv : mo->volumes) { + if (!mv->is_model_part()) continue; + + ++mesh_id; + + Transform3d trafo_matrix; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix(); + trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + } else { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix(); + } + + bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; + if (is_left_handed) glsafe(::glFrontFace(GL_CW)); + + const Camera & camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d) matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + shader->set_uniform("volume_world_matrix", trafo_matrix); + shader->set_uniform("volume_mirrored", is_left_handed); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); + + if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); + } +} + +void GLGizmoFuzzySkin::on_set_state() +{ + GLGizmoPainterBase::on_set_state(); + + if (get_state() == On) { + + } + else if (get_state() == Off) { + ModelObject* mo = m_c->selection_info()->model_object(); + if (mo) Slic3r::save_object_mesh(*mo); + } +} + +void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_limit) +{ + if (!m_c) { + return; + } + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + if (!p_model_object) { + return; + } + m_imgui_start_pos[0] = x; + m_imgui_start_pos[1] = y; + // QDS + wchar_t old_tool = m_current_tool; + + + const float approx_height = m_imgui->scaled(23.f); + y = std::min(y, bottom_limit - approx_height); + + GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f); + + //QDS + ImGuiWrapper::push_toolbar_style(m_parent.get_scale()); + GizmoImguiBegin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); + + // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: + const float space_size = m_imgui->get_style_scaling() * 8; + const float clipping_slider_left = m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f); + const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.5f); + const float reset_button_slider_left = m_imgui->calc_text_size(m_desc.at("reset_direction")).x + m_imgui->scaled(1.5f) + ImGui::GetStyle().FramePadding.x * 2; + const float remove_btn_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.5f); + const float smart_fill_angle_txt_width = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f); + const float buttons_width = remove_btn_width + m_imgui->scaled(1.5f); + const float empty_button_width = m_imgui->calc_button_size("").x; + + const float minimal_slider_width = m_imgui->scaled(4.f); + + float caption_max = 0.f; + float total_text_max = 0.f; + for (const auto &t : std::array{"add_fuzzyskin", "remove", "cursor_size", "clipping_of_view", "smart_fill_angle"}) { + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x); + total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x); + } + total_text_max += caption_max + m_imgui->scaled(1.f); + caption_max += m_imgui->scaled(1.f); + + const float sliders_left_width = std::max(smart_fill_angle_txt_width, std::max(reset_button_slider_left, std::max(cursor_slider_left, clipping_slider_left))); + const float slider_icon_width = m_imgui->get_slider_icon_size().x; + const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; + + const float sliders_width = m_imgui->scaled(7.0f); + const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_left_width + sliders_width - space_size; + + float drag_pos_times = 0.7; + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("tool_type")); + std::array tool_ids = {ImGui::CircleButtonIcon, ImGui::SphereButtonIcon, ImGui::TriangleButtonIcon, ImGui::FillButtonIcon}; + std::array icons; + if (m_is_dark_mode) + icons = {ImGui::CircleButtonDarkIcon, ImGui::SphereButtonDarkIcon, ImGui::TriangleButtonDarkIcon, ImGui::FillButtonDarkIcon}; + else + icons = tool_ids; + + std::array tool_tips = {_L("Circle"), _L("Sphere"), _L("Triangle"), _L("Fill")}; + for (int i = 0; i < tool_ids.size(); i++) { + std::string str_label = std::string("##"); + std::wstring btn_name = icons[i] + boost::nowide::widen(str_label); + + if (i != 0) ImGui::SameLine((empty_button_width + m_imgui->scaled(1.75f)) * i + m_imgui->scaled(1.3f)); + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0); + if (m_current_tool == tool_ids[i]) { + ImGui::PushStyleColor(ImGuiCol_Button, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); // r, g, b, a + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0); + } + bool btn_clicked = ImGui::Button(into_u8(btn_name).c_str()); + if (m_current_tool == tool_ids[i]) + { + ImGui::PopStyleColor(4); + ImGui::PopStyleVar(2); + } + ImGui::PopStyleVar(1); + + if (btn_clicked && m_current_tool != tool_ids[i]) { + m_current_tool = tool_ids[i]; + for (auto& triangle_selector : m_triangle_selectors) { + triangle_selector->seed_fill_unselect_all_triangles(); + triangle_selector->request_update_render_data(); + } + } + + if (ImGui::IsItemHovered()) { + m_imgui->tooltip(tool_tips[i], max_tooltip_width); + } + } + + ImGui::Separator(); + + if (m_current_tool != old_tool) + this->tool_changed(old_tool, m_current_tool); + + ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1)); + + if (m_current_tool == ImGui::CircleButtonIcon) { + m_cursor_type = TriangleSelector::CursorType::CIRCLE; + m_tool_type = ToolType::BRUSH; + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("cursor_size")); + ImGui::SameLine(sliders_left_width); + ImGui::PushItemWidth(sliders_width); + m_imgui->qdt_slider_float_style("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true); + ImGui::SameLine(drag_left_width); + ImGui::PushItemWidth(1.5 * slider_icon_width); + ImGui::QDTDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f"); + } else if (m_current_tool == ImGui::SphereButtonIcon) { + m_cursor_type = TriangleSelector::CursorType::SPHERE; + m_tool_type = ToolType::BRUSH; + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("cursor_size")); + ImGui::SameLine(sliders_left_width); + ImGui::PushItemWidth(sliders_width); + m_imgui->qdt_slider_float_style("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true); + ImGui::SameLine(drag_left_width); + ImGui::PushItemWidth(1.5 * slider_icon_width); + ImGui::QDTDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f"); + } else if (m_current_tool == ImGui::FillButtonIcon) { + m_cursor_type = TriangleSelector::CursorType::POINTER; + m_tool_type = ToolType::SMART_FILL; + + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("smart_fill_angle")); + std::string format_str = std::string("%.f") + I18N::translate_utf8("", "Face angle threshold, placed after the number with no whitespace in between."); + ImGui::SameLine(sliders_left_width); + ImGui::PushItemWidth(sliders_width); + if (m_imgui->qdt_slider_float_style("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true)) + for (auto& triangle_selector : m_triangle_selectors) { + triangle_selector->seed_fill_unselect_all_triangles(); + triangle_selector->request_update_render_data(); + } + ImGui::SameLine(drag_left_width); + ImGui::PushItemWidth(1.5 * slider_icon_width); + ImGui::QDTDragFloat("##smart_fill_angle_input", &m_smart_fill_angle, 0.05f, 0.0f, 0.0f, "%.2f"); + } else if (m_current_tool == ImGui::TriangleButtonIcon) { + m_cursor_type = TriangleSelector::CursorType::POINTER; + m_tool_type = ToolType::BRUSH; + } + + //ImGui::AlignTextToFramePadding(); + + if (m_current_tool != ImGui::GapFillIcon) { + ImGui::Separator(); + if (m_c->object_clipper()->get_position() == 0.f) { + ImGui::AlignTextToFramePadding(); + m_imgui->text(m_desc.at("clipping_of_view")); + } + else { + if (m_imgui->button(m_desc.at("reset_direction"))) { + wxGetApp().CallAfter([this]() { + m_c->object_clipper()->set_position(-1., false); + }); + } + } + + auto clp_dist = float(m_c->object_clipper()->get_position()); + ImGui::SameLine(sliders_left_width); + ImGui::PushItemWidth(sliders_width); + bool b_qdt_slider_float = m_imgui->qdt_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true); + + ImGui::SameLine(drag_left_width); + ImGui::PushItemWidth(1.5 * slider_icon_width); + bool b_drag_input = ImGui::QDTDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f"); + + if (b_qdt_slider_float || b_drag_input) m_c->object_clipper()->set_position(clp_dist, true); + } + + ImGui::Separator(); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); + float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; + show_tooltip_information(caption_max, x, get_cur_y); + + float f_scale = m_parent.get_main_toolbar_scale(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); + + ImGui::SameLine(); + + if (m_imgui->button(m_desc.at("remove_all"))) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Reset selection", UndoRedo::SnapshotType::GizmoAction); + ModelObject * mo = m_c->selection_info()->model_object(); + int idx = -1; + for (ModelVolume *mv : mo->volumes) + if (mv->is_model_part()) { + ++idx; + m_triangle_selectors[idx]->reset(); + m_triangle_selectors[idx]->request_update_render_data(true); + } + + update_model_object(); + m_parent.set_as_dirty(); + } + ImGui::PopStyleVar(2); + m_imgui_end_pos[0] = m_imgui_start_pos[0] + ImGui::GetWindowWidth(); + m_imgui_end_pos[1] = m_imgui_start_pos[1] + ImGui::GetWindowHeight(); + GizmoImguiEnd(); + + // QDS + ImGuiWrapper::pop_toolbar_style(); +} + +void GLGizmoFuzzySkin::tool_changed(wchar_t old_tool, wchar_t new_tool) +{ + if ((old_tool == ImGui::GapFillIcon && new_tool == ImGui::GapFillIcon) || + (old_tool != ImGui::GapFillIcon && new_tool != ImGui::GapFillIcon)) + return; + + for (auto& selector_ptr : m_triangle_selectors) { + TriangleSelectorPatch* tsp = dynamic_cast(selector_ptr.get()); + tsp->set_filter_state(new_tool == ImGui::GapFillIcon); + } +} + +void GLGizmoFuzzySkin::show_tooltip_information(float caption_max, float x, float y) +{ + ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP); + ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER); + + caption_max += m_imgui->calc_text_size(": ").x + 15.f; + + float font_size = ImGui::GetFontSize(); + ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 0, ImGui::GetStyle().FramePadding.y }); + ImGui::ImageButton3(normal_id, hover_id, button_size); + + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip2(ImVec2(x, y)); + auto draw_text_with_caption = [this, &caption_max](const wxString &caption, const wxString &text) { + // QDS + m_imgui->text_colored(ImGuiWrapper::COL_ACTIVE, caption); + ImGui::SameLine(caption_max); + m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text); + }; + + std::vector tip_items; + switch (m_tool_type) { + case ToolType::BRUSH: + tip_items = {"add_fuzzyskin", "remove", "cursor_size", "clipping_of_view"}; + break; + case ToolType::BUCKET_FILL: + break; + case ToolType::SMART_FILL: + tip_items = {"add_fuzzyskin", "remove", "smart_fill_angle", "clipping_of_view"}; + break; + default: + break; + } + for (const auto &t : tip_items) + draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t)); + + ImGui::EndTooltip(); + } + ImGui::PopStyleVar(2); +} + +//QDS: remove const +void GLGizmoFuzzySkin::update_model_object() +{ + bool updated = false; + ModelObject* mo = m_c->selection_info()->model_object(); + int idx = -1; + for (ModelVolume* mv : mo->volumes) { + if (! mv->is_model_part()) + continue; + ++idx; + updated |= mv->fuzzy_skin_facets.set(*m_triangle_selectors[idx].get()); + } + + if (updated) { + const ModelObjectPtrs& mos = wxGetApp().model().objects; + wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin()); + + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + } +} + +//QDS +void GLGizmoFuzzySkin::update_from_model_object(bool first_update) +{ + wxBusyCursor wait; + + const ModelObject* mo = m_c->selection_info()->model_object(); + m_triangle_selectors.clear(); + //QDS: add timestamp logic + m_volume_timestamps.clear(); + + int volume_id = -1; + std::vector> ebt_colors; + ebt_colors.push_back(GLVolume::NEUTRAL_COLOR); + ebt_colors.push_back(TriangleSelectorGUI::enforcers_color); + ebt_colors.push_back(TriangleSelectorGUI::blockers_color); + for (const ModelVolume* mv : mo->volumes) { + if (! mv->is_model_part()) + continue; + + ++volume_id; + + // This mesh does not account for the possible Z up SLA offset. + const TriangleMesh* mesh = &mv->mesh(); + m_triangle_selectors.emplace_back(std::make_unique(*mesh, ebt_colors)); + // Reset of TriangleSelector is done inside TriangleSelectorGUI's constructor, so we don't need it to perform it again in deserialize(). + m_triangle_selectors.back()->deserialize(mv->fuzzy_skin_facets.get_data(), false); + m_triangle_selectors.back()->request_update_render_data(); + m_triangle_selectors.back()->set_wireframe_needed(true); + //QDS: add timestamp logic + m_volume_timestamps.emplace_back(mv->fuzzy_skin_facets.timestamp()); + } +} + +PainterGizmoType GLGizmoFuzzySkin::get_painter_type() const +{ + return PainterGizmoType::FUZZY_SKIN; +} + +wxString GLGizmoFuzzySkin::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const +{ + // QDS remove _L() + wxString action_name; + if (shift_down) + action_name = ("Unselect all"); + else { + if (button_down == Button::Left) + action_name = ("Add fuzzy skin"); + else + action_name = ("Remove fuzzy skin"); + } + return action_name; +} + +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp new file mode 100644 index 0000000..d4580c5 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp @@ -0,0 +1,82 @@ +#ifndef slic3r_GLGizmoFuzzySkin_hpp_ +#define slic3r_GLGizmoFuzzySkin_hpp_ + +#include "GLGizmoPainterBase.hpp" +//QDS +#include "libslic3r/Print.hpp" +#include "libslic3r/ObjectID.hpp" + +#include + +namespace Slic3r::GUI { + +class GLGizmoFuzzySkin : public GLGizmoPainterBase +{ +public: + GLGizmoFuzzySkin(GLCanvas3D& parent, unsigned int sprite_id); + void data_changed(bool is_serializing) override; + void render_painter_gizmo() const override; + + //QDS: add edit state + enum EditState { + state_idle = 0, + state_generating = 1, + state_ready + }; + + //QDS + bool on_key_down_select_tool_type(int keyCode); + + std::string get_icon_filename(bool is_dark_mode) const override; + +protected: + void on_render_input_window(float x, float y, float bottom_limit) override; + std::string on_get_name() const override; + std::string on_get_name_str() override { return "FuzzySkin Painting"; } + + // QDS + void render_triangles(const Selection& selection) const override; + void on_set_state() override; + void show_tooltip_information(float caption_max, float x, float y); + wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + + std::string get_gizmo_entering_text() const override { return "Entering Paint-on supports"; } + std::string get_gizmo_leaving_text() const override { return "Leaving Paint-on supports"; } + std::string get_action_snapshot_name() override { return "Paint-on supports editing"; } + EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType::FUZZY_SKIN; } + EnforcerBlockerType get_right_button_state_type() const override; + // QDS + wchar_t m_current_tool = 0; + +private: + bool on_init() override; + + //QDS: remove const + void update_model_object() override; + //QDS: add logic to distinguish the first_time_update and later_update + void update_from_model_object(bool first_update) override; + void tool_changed(wchar_t old_tool, wchar_t new_tool); + void on_opening() override {} + void on_shutdown() override; + PainterGizmoType get_painter_type() const override; + + bool m_volume_valid = false; + + bool m_is_tree_support = false; + bool m_cancel = false; + size_t m_object_id; + std::vector m_volume_timestamps; + PrintInstance m_print_instance; + mutable EditState m_edit_state; + //thread + boost::thread m_thread; + // Mutex and condition variable to synchronize m_thread with the UI thread. + std::mutex m_mutex; + int m_generate_count; + + // This map holds all translated description texts, so they can be easily referenced during layout calculations + // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. + std::map m_desc; +}; +} // namespace Slic3r::GUI +#endif // slic3r_GLGizmoFuzzySkin_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index aa41848..de51d19 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -17,13 +17,18 @@ namespace Slic3r { namespace GUI { -GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) { m_vbo_cylinder.init_from(its_make_cylinder(1., 1.)); } +std::string GLGizmoHollow::get_icon_filename(bool is_dark_mode) const +{ + return "hollow.svg"; +} + bool GLGizmoHollow::on_init() { m_shortcut_key = WXK_CONTROL_H; @@ -456,7 +461,16 @@ GLGizmoHollow::get_config_options(const std::vector& keys) const void GLGizmoHollow::on_render_input_window(float x, float y, float bottom_limit) { - ModelObject* mo = m_c->selection_info()->model_object(); + if (!m_c) { + return; + } + + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + + ModelObject* mo = p_selection_info->model_object(); if (! mo) return; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index cc9c144..ea41816 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -27,15 +27,17 @@ private: public: - GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoHollow(GLCanvas3D& parent, unsigned int sprite_id); virtual ~GLGizmoHollow() = default; void set_sla_support_data(ModelObject* model_object, const Selection& selection); - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); - void delete_selected_points(); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; + void delete_selected_points(); bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); } + std::string get_icon_filename(bool is_dark_mode) const override; + private: bool on_init() override; void on_update(const UpdateData& data) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 02bc52a..337602b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -176,8 +176,8 @@ void TransformHelper::update(const std::array &viewport) TransformHelper::Cache TransformHelper::s_cache = { { 0, 0, 0, 0 }, Matrix4d::Identity(), Transform3d::Identity() }; -GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) -: GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, unsigned int sprite_id) +: GLGizmoBase(parent, sprite_id) { auto sphere_geometry = smooth_sphere(16, 7.5f); m_sphere = std::make_shared(); @@ -442,6 +442,11 @@ bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_po return true; } +std::string GLGizmoMeasure::get_icon_filename(bool is_dark_mode) const +{ + return is_dark_mode ? "toolbar_measure_dark.svg" : "toolbar_measure.svg"; +} + bool GLGizmoMeasure::on_init() { m_shortcut_key = WXK_CONTROL_U; @@ -495,7 +500,6 @@ std::string GLGizmoMeasure::on_get_name() const bool GLGizmoMeasure::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - //1.9.5 if (selection.is_wipe_tower()) { return false; } @@ -680,8 +684,10 @@ void GLGizmoMeasure::on_render() } if (m_measure_mode == EMeasureMode::ONLY_ASSEMBLY) { if (m_assembly_mode == AssemblyMode::FACE_FACE) { - if (curr_feature->get_type() != Measure::SurfaceFeatureType::Plane) { - curr_feature.reset(); + if (curr_feature.has_value()) { + if (curr_feature->get_type() != Measure::SurfaceFeatureType::Plane) { + curr_feature.reset(); + } } } else if (m_assembly_mode == AssemblyMode::POINT_POINT) { if (!(curr_feature->get_type() == Measure::SurfaceFeatureType::Point || @@ -815,7 +821,7 @@ void GLGizmoMeasure::on_render() glsafe(::glEnable(GL_DEPTH_TEST)); glDisable(GL_BLEND); auto render_feature = - [this, view_matrix, projection_matrix](const Measure::SurfaceFeature &feature, const std::vector &colors, + [this, view_matrix, projection_matrix](const Measure::SurfaceFeature &feature, const std::vector &colors, float inv_zoom, bool hover, bool update_raycasters_transform,int featura_index = -1) { switch (feature.get_type()) { @@ -1896,16 +1902,16 @@ void GLGizmoMeasure::show_distance_xyz_ui() if (m_measure_mode == EMeasureMode::ONLY_MEASURE) { m_imgui->text(_u8L("Measure")); } - auto add_measure_row_to_table = [this](const std::string &col_1, const ImVec4 &col_1_color, const std::string &col_2, const ImVec4 &col_2_color) { + auto add_measure_row_to_table = [this](const std::string &col_1, const ImVec4 &col_1_color, const std::string &col_2, const std::string &unit, const ImVec4 &col_2_color) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); m_imgui->text_colored(col_1_color, col_1); ImGui::TableSetColumnIndex(1); - m_imgui->text_colored(col_2_color, col_2); + m_imgui->text_colored(col_2_color, col_2 + unit); ImGui::TableSetColumnIndex(2); if (m_imgui->image_button(m_is_dark_mode ? ImGui::ClipboardBtnDarkIcon : ImGui::ClipboardBtnIcon, _L("Copy to clipboard"))) { wxTheClipboard->Open(); - wxTheClipboard->SetData(new wxTextDataObject(wxString((col_1 + ": " + col_2).c_str(), wxConvUTF8))); + wxTheClipboard->SetData(new wxTextDataObject(wxString(col_2.c_str(), wxConvUTF8))); wxTheClipboard->Close(); } }; @@ -1962,7 +1968,7 @@ void GLGizmoMeasure::show_distance_xyz_ui() if (measure.angle.has_value() && m_measure_mode == EMeasureMode::ONLY_MEASURE) { ImGui::PushID("ClipboardAngle"); - add_measure_row_to_table(_u8L("Angle"), ImGuiWrapper::COL_QIDI, format_double(Geometry::rad2deg(measure.angle->angle)) + "°", + add_measure_row_to_table(_u8L("Angle"), ImGuiWrapper::COL_QIDI, format_double(Geometry::rad2deg(measure.angle->angle)),"°", ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); @@ -1975,7 +1981,7 @@ void GLGizmoMeasure::show_distance_xyz_ui() double distance = measure.distance_infinite->dist; if (m_use_inches) distance = GizmoObjectManipulation::mm_to_in * distance; ImGui::PushID("ClipboardDistanceInfinite"); - add_measure_row_to_table(show_strict ? _u8L("Perpendicular distance") : _u8L("Distance"), ImGuiWrapper::COL_QIDI, format_double(distance) + m_units, + add_measure_row_to_table(show_strict ? _u8L("Perpendicular distance") : _u8L("Distance"), ImGuiWrapper::COL_QIDI, format_double(distance), m_units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); @@ -1988,7 +1994,7 @@ void GLGizmoMeasure::show_distance_xyz_ui() if (m_use_inches) distance = GizmoObjectManipulation::mm_to_in * distance; ImGui::PushID("ClipboardDistanceStrict"); - add_measure_row_to_table(_u8L("Direct distance"), ImGuiWrapper::COL_QIDI, format_double(distance) + m_units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); + add_measure_row_to_table(_u8L("Direct distance"), ImGuiWrapper::COL_QIDI, format_double(distance), m_units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); } @@ -1997,7 +2003,7 @@ void GLGizmoMeasure::show_distance_xyz_ui() if (m_use_inches) distance = GizmoObjectManipulation::mm_to_in * distance; if (measure.distance_xyz->norm() > EPSILON) { ImGui::PushID("ClipboardDistanceXYZ"); - add_measure_row_to_table(_u8L("Distance XYZ"), ImGuiWrapper::COL_QIDI, format_vec3(distance), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + add_measure_row_to_table(_u8L("Distance XYZ"), ImGuiWrapper::COL_QIDI, format_vec3(distance), m_units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index b8140cb..9b9c745 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -217,7 +217,7 @@ protected: #endif // ENABLE_MEASURE_GIZMO_DEBUG public: - GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoMeasure(GLCanvas3D& parent, unsigned int sprite_id); /// /// Apply rotation on select plane /// @@ -227,16 +227,19 @@ public: void data_changed(bool is_serializing) override; - virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; bool wants_enter_leave_snapshots() const override { return true; } std::string get_gizmo_entering_text() const override { return _u8L("Entering Measure gizmo"); } std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Measure gizmo"); } //std::string get_action_snapshot_name() const override { return _u8L("Measure gizmo editing"); } + std::string get_icon_filename(bool is_dark_mode) const override; + protected: bool on_init() override; std::string on_get_name() const override; + virtual std::string on_get_name_str() override { return "Measure"; } bool on_is_activable() const override; void on_render() override; void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp index c2bbd96..b6a0d54 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.cpp @@ -21,8 +21,8 @@ namespace GUI { static const std::string warning_text_common = _u8L("Unable to perform boolean operation on selected parts"); static const std::string warning_text_intersection = _u8L("Performed boolean intersection fails because the selected parts have no intersection"); -GLGizmoMeshBoolean::GLGizmoMeshBoolean(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoMeshBoolean::GLGizmoMeshBoolean(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) { } @@ -113,6 +113,11 @@ bool GLGizmoMeshBoolean::gizmo_event(SLAGizmoEventType action, const Vec2d& mous return true; } +std::string GLGizmoMeshBoolean::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg"; +} + bool GLGizmoMeshBoolean::on_init() { m_shortcut_key = WXK_CONTROL_B; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp index 0dcf2e7..2b113ac 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp @@ -38,7 +38,7 @@ struct VolumeInfo { class GLGizmoMeshBoolean : public GLGizmoBase { public: - GLGizmoMeshBoolean(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoMeshBoolean(GLCanvas3D& parent, unsigned int sprite_id); ~GLGizmoMeshBoolean(); void set_enable(bool enable) { m_enable = enable; } @@ -47,7 +47,9 @@ public: void set_src_volume(ModelVolume* mv); void set_tool_volume(ModelVolume* mv); - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; + + std::string get_icon_filename(bool b_dark_mode) const override; protected: virtual bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 928ca5c..333f5d5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -62,6 +62,18 @@ bool GLGizmoMmuSegmentation::on_is_activable() const return !selection.is_empty() && (selection.is_single_full_instance() || selection.is_any_volume()); } +void GLGizmoMmuSegmentation::on_load(cereal::BinaryInputArchive &ar) +{ + GLGizmoPainterBase::on_load(ar); + ar(m_selected_extruder_idx); +} + +void GLGizmoMmuSegmentation::on_save(cereal::BinaryOutputArchive &ar) const +{ + GLGizmoPainterBase::on_save(ar); + ar(m_selected_extruder_idx); +} + static std::vector get_extruder_id_for_volumes(const ModelObject &model_object) { std::vector extruders_idx; @@ -104,6 +116,7 @@ bool GLGizmoMmuSegmentation::on_init() m_desc["erase"] = _L("Erase"); m_desc["shortcut_key_caption"] = _L("Key 1~9"); m_desc["shortcut_key"] = _L("Choose filament"); + m_desc["same_color_connection"] = _L("Connected same color"); m_desc["edge_detection"] = _L("Edge detection"); m_desc["gap_area_caption"] = ctrl + _L("Mouse wheel"); m_desc["gap_area"] = _L("Gap area"); @@ -137,9 +150,10 @@ bool GLGizmoMmuSegmentation::on_init() return true; } -GLGizmoMmuSegmentation::GLGizmoMmuSegmentation(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoPainterBase(parent, icon_filename, sprite_id), m_current_tool(ImGui::CircleButtonIcon) +GLGizmoMmuSegmentation::GLGizmoMmuSegmentation(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoPainterBase(parent, sprite_id) { + m_current_tool =ImGui::CircleButtonIcon; } void GLGizmoMmuSegmentation::data_changed(bool is_serializing) { @@ -278,11 +292,67 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const shader->set_uniform("volume_world_matrix", trafo_matrix); shader->set_uniform("volume_mirrored", is_left_handed); - m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix, m_tool_type != ToolType::BUCKET_FILL); + //add selected glvolume for BucketFillType::SameColor ,because no paint_contour + if (m_tool_type == ToolType::BUCKET_FILL) { + auto temp_patch = dynamic_cast(m_triangle_selectors[mesh_id].get()); + int state = -1; + auto its = m_triangle_selectors[mesh_id]->get_seed_fill_mesh(state); + TriangleMesh mesh(its); + if (m_rr.mesh_id == mesh_id && !(state == m_last_hit_state && m_last_hit_state_faces == mesh.facets_count() && (m_last_hit_its_center - mesh.bounding_box().center()).norm() > 0.01)) { + m_last_hit_state = state; + m_last_hit_state_faces = mesh.facets_count(); + m_last_hit_its_center =mesh.bounding_box().center(); + if (!m_parent.get_paint_outline_volumes().empty()) { m_parent.get_paint_outline_volumes().clear(); } + if (temp_patch && !m_triangle_selectors[mesh_id]->get_paint_contour_has_data()) { + auto colors =temp_patch->get_ebt_colors(); + auto triangles = temp_patch->get_triangles(); + if (triangles.size() > 0 && state >= 0) { + if (state < colors.size()) { + auto color = colors[state]; + m_parent.get_paint_outline_volumes().volumes.emplace_back(new GLVolume(color)); + auto& v = m_parent.get_paint_outline_volumes().volumes.back(); + + init_selected_glvolume(*v, mesh, Geometry::Transformation(trafo_matrix)); + } + } + } + } + } + if (m_rr.mesh_id < 0 || m_tool_type != ToolType::BUCKET_FILL) { + clear_parent_paint_outline_volumes(); + } if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } + if (m_tool_type == ToolType::BUCKET_FILL) { + mesh_id = -1; + for (const ModelVolume *mv : mo->volumes) { + if (!mv->is_model_part()) continue; + + ++mesh_id; + if (mesh_id != m_rr.mesh_id) { continue; } + Transform3d trafo_matrix; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix(); + trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + } else { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix(); + } + + bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; + if (is_left_handed) glsafe(::glFrontFace(GL_CW)); + + const Camera & camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + + m_triangle_selectors[mesh_id]->render_paint_contour(trafo_matrix,true); + + if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); + } + } } // QDS @@ -323,6 +393,11 @@ bool GLGizmoMmuSegmentation::on_key_down_select_tool_type(int keyCode) { return true; } +std::string GLGizmoMmuSegmentation::get_icon_filename(bool is_dark_mode) const +{ + return is_dark_mode ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg"; +} + static void render_extruders_combo(const std::string &label, const std::vector &extruders, const std::vector> &extruders_colors, @@ -425,7 +500,17 @@ void GLGizmoMmuSegmentation::show_tooltip_information(float caption_max, float x void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bottom_limit) { - if (!m_c->selection_info()->model_object()) return; + if (!m_c) { + return; + } + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + if (!p_model_object) { + return; + } const float approx_height = m_imgui->scaled(22.0f); y = std::min(y, bottom_limit - approx_height); @@ -480,7 +565,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, buttons_width); window_width = std::max(window_width, max_filament_items_per_line * filament_item_width + m_imgui->scaled(0.5f)); - + window_width = std::max(window_width, m_imgui->calc_button_size(m_desc["same_color_connection"]).x + m_imgui->calc_button_size("edge_detection").x + m_imgui->scaled(2.5f)); const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_width - space_size; @@ -492,7 +577,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott float color_button = ImGui::GetCursorPos().y; - float textbox_width = 1.5 * slider_icon_width; + float textbox_width = 1.5 * slider_icon_width; SliderInputLayout slider_input_layout = {clipping_slider_left, sliders_width, drag_left_width + circle_max_width, textbox_width}; if (wxGetApp().plater()->is_show_non_manifold_edges()) { m_imgui->text(_L("hit face") + ":" + std::to_string(m_rr.facet)); @@ -703,10 +788,25 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott } else if (m_current_tool == ImGui::FillButtonIcon) { m_cursor_type = TriangleSelector::CursorType::POINTER; - m_imgui->qdt_checkbox(m_desc["edge_detection"], m_detect_geometry_edge); + bool is_same_color = m_bucket_fill_mode == BucketFillType::SameColor; + ImGuiWrapper::push_radio_style(); + if (ImGui::RadioButton(m_desc["same_color_connection"].ToUTF8().data(), is_same_color)) { + m_bucket_fill_mode = BucketFillType::SameColor; + m_smart_fill_angle = -1;// set to negative value to disable edge detection + } + ImGui::SameLine(); + bool is_detect_geometry_edge = m_bucket_fill_mode == BucketFillType::EdgeDetect; + if (ImGui::RadioButton(m_desc["edge_detection"].ToUTF8().data(), is_detect_geometry_edge)) { + m_bucket_fill_mode = BucketFillType::EdgeDetect; + m_smart_fill_angle = m_last_edge_detection_smart_fill_angle; + } + ImGuiWrapper::pop_radio_style(); m_tool_type = ToolType::BUCKET_FILL; - if (m_detect_geometry_edge) { + if (is_detect_geometry_edge) { + if (m_last_edge_detection_smart_fill_angle != m_smart_fill_angle) { + m_last_edge_detection_smart_fill_angle = m_smart_fill_angle; + } ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc["smart_fill_angle"]); std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Face angle threshold," @@ -721,9 +821,6 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::SameLine(drag_left_width + sliders_left_width); ImGui::PushItemWidth(1.5 * slider_icon_width); ImGui::QDTDragFloat("##smart_fill_angle_input", &m_smart_fill_angle, 0.05f, 0.0f, 0.0f, "%.2f"); - } else { - // set to negative value to disable edge detection - m_smart_fill_angle = -1.f; } ImGui::Separator(); if (m_c->object_clipper()->get_position() == 0.f) { @@ -810,8 +907,6 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_vertical_only = vertical_only; if (m_vertical_only) { m_horizontal_only = false; - m_is_front_view = true; - change_camera_view_angle(m_front_view_radian); } } @@ -851,7 +946,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); - float f_scale =m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::SameLine(); @@ -1021,8 +1116,12 @@ void GLGizmoMmuSegmentation::on_set_state() m_selected_extruder_idx = 1; } m_non_manifold_edges_model.reset(); + m_bucket_fill_mode = BucketFillType::SameColor; + m_smart_fill_angle = -1; } else if (get_state() == Off) { + clear_parent_paint_outline_volumes(); + ModelObject* mo = m_c->selection_info()->model_object(); if (mo) Slic3r::save_object_mesh(*mo); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE)); @@ -1043,6 +1142,16 @@ wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GL return action_name; } +void GLGizmoMmuSegmentation::clear_parent_paint_outline_volumes() const +{ + m_last_hit_state = -1; + m_last_hit_state_faces = -1; + m_last_hit_its_center = Vec3d::Zero(); + if (!m_parent.get_paint_outline_volumes().empty()) { + m_parent.get_paint_outline_volumes().clear(); + } +} + void GLMmSegmentationGizmo3DScene::release_geometry() { if (this->vertices_VBO_id) { glsafe(::glDeleteBuffers(1, &this->vertices_VBO_id)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index e2c8d6f..8423a76 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -64,12 +64,11 @@ public: class GLGizmoMmuSegmentation : public GLGizmoPainterBase { public: - GLGizmoMmuSegmentation(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoMmuSegmentation(GLCanvas3D& parent, unsigned int sprite_id); ~GLGizmoMmuSegmentation() override = default; void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; void render_non_manifold_edges() const; - void render_triangles(const Selection& selection) const override; // TriangleSelector::serialization/deserialization has a limit to store 19 different states. @@ -84,6 +83,8 @@ public: bool on_number_key_down(int number); bool on_key_down_select_tool_type(int keyCode); + std::string get_icon_filename(bool is_dark_mode) const override; + protected: // QDS void set_painter_gizmo_data(const Selection &selection) override; @@ -99,9 +100,11 @@ protected: void show_tooltip_information(float caption_max, float x, float y); bool on_is_selectable() const override; bool on_is_activable() const override; - + void on_load(cereal::BinaryInputArchive &ar) override; + void on_save(cereal::BinaryOutputArchive &ar) const override; wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + void clear_parent_paint_outline_volumes() const; std::string get_gizmo_entering_text() const override { return "Entering color painting"; } std::string get_gizmo_leaving_text() const override { return "Leaving color painting"; } std::string get_action_snapshot_name() override { return "Color painting editing"; } @@ -112,9 +115,6 @@ protected: std::vector m_volumes_extruder_idxs; // QDS - wchar_t m_current_tool = 0; - bool m_detect_geometry_edge = true; - static const constexpr float CursorRadiusMin = 0.1f; // cannot be zero private: diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 688e8e3..79863d9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -22,8 +22,8 @@ const double GLGizmoMove3D::Offset = 10.0; #endif //QDS: GUI refactor: add obj manipulation -GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) + : GLGizmoBase(parent, sprite_id) , m_displacement(Vec3d::Zero()) , m_snap_step(1.0) , m_starting_drag_position(Vec3d::Zero()) @@ -115,6 +115,11 @@ BoundingBoxf3 GLGizmoMove3D::get_bounding_box() const return t_aabb; } +std::string GLGizmoMove3D::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_move_dark.svg" : "toolbar_move.svg"; +} + bool GLGizmoMove3D::on_init() { for (int i = 0; i < 3; ++i) { @@ -336,22 +341,21 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const { double projection = 0.0; - Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; - double len_starting_vec = starting_vec.norm(); - if (len_starting_vec != 0.0) { - Vec3d mouse_dir = data.mouse_ray.unit_vector(); - // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position - // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form - // in our case plane normal and ray direction are the same (orthogonal view) - // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; - // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting_drag_position; + Vec3d mouse_dir = data.mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; - projection = inters_vec.norm(); - const double sign = inters_vec.dot(starting_vec) > 1e-6f ? 1.0f : -1.0f; - - projection = projection * sign; + if (m_hover_id == 0) { + projection = inters.x() - m_starting_drag_position.x(); + } + else if (m_hover_id == 1) { + projection = inters.y() - m_starting_drag_position.y(); + } + else if (m_hover_id == 2) { + projection = inters.z() - m_starting_drag_position.z(); } if (wxGetKeyState(WXK_SHIFT)) @@ -363,7 +367,6 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const { double size = get_grabber_size() * 0.75;//0.75 for arrow show - std::array color = m_grabbers[axis].color; if (!picking && m_hover_id != -1) { if (m_hover_id == axis) { @@ -376,7 +379,6 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box return; wxGetApp().bind_shader(shader); - const_cast(&m_vbo_cone)->set_color(-1, color); const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index baee695..8a39f44 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -41,7 +41,7 @@ class GLGizmoMove3D : public GLGizmoBase public: //QDS: add obj manipulation logic //GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); + GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); virtual ~GLGizmoMove3D() = default; double get_snap_step(double step) const { return m_snap_step; } @@ -53,6 +53,8 @@ public: void data_changed(bool is_serializing) override; BoundingBoxf3 get_bounding_box() const override; + std::string get_icon_filename(bool b_dark_mode) const override; + protected: virtual bool on_init() override; virtual std::string on_get_name() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index f0a172b..e14efa6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -23,8 +23,8 @@ namespace Slic3r::GUI { -GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) { // Make sphere and save it into a vertex buffer. m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.)); @@ -127,6 +127,20 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const } } +void GLGizmoPainterBase::init_selected_glvolume(GLVolume &v,const TriangleMesh &mesh, const Geometry::Transformation &world_transformation) const +{ + v.force_native_color = true; + v.selected = true; + v.set_render_color(); +#if ENABLE_SMOOTH_NORMALS + v.indexed_vertex_array->load_mesh(mesh, true); +#else + v.indexed_vertex_array->load_mesh(mesh); +#endif // ENABLE_SMOOTH_NORMALS + v.indexed_vertex_array->finalize_geometry(true); + v.set_instance_transformation(world_transformation); + v.set_convex_hull(mesh.convex_hull_3d()); +} void GLGizmoPainterBase::render_cursor() const { @@ -1224,16 +1238,24 @@ void GLGizmoPainterBase::on_set_state() -void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive&) +void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive &ar) { // We should update the gizmo from current ModelObject, but it is not // possible at this point. That would require having updated selection and // common gizmos data, which is not done at this point. Instead, save // a flag to do the update in set_painter_gizmo_data, which will be called // soon after. + ar(m_tool_type, m_current_tool, m_cursor_type, m_cursor_radius, m_cursor_height, m_lock_x_for_height_bottom, m_smart_fill_angle, m_bucket_fill_mode, + TriangleSelectorPatch::gap_area); m_schedule_update = true; } +void GLGizmoPainterBase::on_save(cereal::BinaryOutputArchive &ar) const +{ + ar(m_tool_type, m_current_tool,m_cursor_type, m_cursor_radius, m_cursor_height, m_lock_x_for_height_bottom, + m_smart_fill_angle, m_bucket_fill_mode, TriangleSelectorPatch::gap_area); +} + TriangleSelector::ClippingPlane GLGizmoPainterBase::get_clipping_plane_in_volume_coordinates(const Transform3d &trafo) const { const ::Slic3r::GUI::ClippingPlane *const clipping_plane = m_c->object_clipper()->get_clipping_plane(); if (clipping_plane == nullptr || !clipping_plane->is_active()) @@ -1271,7 +1293,7 @@ std::array TriangleSelectorGUI::get_seed_fill_color(const std::arrayget_camera(); contour_shader->set_uniform("view_model_matrix", camera.get_view_matrix() * matrix); contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - + if (clear_depth){ + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + } glsafe(::glDepthFunc(GL_LEQUAL)); m_paint_contour.render_geometry(); glsafe(::glDepthFunc(GL_LESS)); @@ -1423,7 +1449,12 @@ bool TrianglePatch::is_fragment() const float TriangleSelectorPatch::gap_area = TriangleSelectorPatch::GapAreaMin; bool TriangleSelectorPatch::exist_gap_area = false; -void TriangleSelectorPatch::render(ImGuiWrapper* imgui, const Transform3d& matrix) +TriangleSelectorPatch::TriangleSelectorPatch(const TriangleMesh &mesh, const std::vector> ebt_colors, float edge_limit): TriangleSelectorGUI(mesh, edge_limit), m_ebt_colors(ebt_colors) +{ +} + + +void TriangleSelectorPatch::render(ImGuiWrapper *imgui, const Transform3d &matrix, bool render_paint_contour_at_same_time) { if (m_update_render_data) update_render_data(); @@ -1471,7 +1502,9 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui, const Transform3d& matri ScopeGuard guard_mm_gouraud([shader]() { wxGetApp().bind_shader(shader); }); wxGetApp().unbind_shader(); - render_paint_contour(matrix); + if (render_paint_contour_at_same_time) { + render_paint_contour(matrix); + } m_update_render_data = false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 6fc1a09..fc8186f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -19,10 +19,10 @@ namespace Slic3r::GUI { enum class SLAGizmoEventType : unsigned char; class ClippingPlane; struct Camera; -class GLGizmoMmuSegmentation; enum class PainterGizmoType { FDM_SUPPORTS, + FUZZY_SKIN, SEAM, MMU_SEGMENTATION }; @@ -71,10 +71,11 @@ public: // Render current selection. Transformation matrices are supposed // to be already set. - virtual void render(ImGuiWrapper *imgui, const Transform3d& matrix); + virtual void render(ImGuiWrapper *imgui, const Transform3d &matrix, bool render_paint_contour_at_same_time = true); + void render_paint_contour(const Transform3d &matrix, bool clear_depth = false); void set_wireframe_needed(bool need_wireframe) { m_need_wireframe = need_wireframe; } bool get_wireframe_needed() { return m_need_wireframe; } - + bool get_paint_contour_has_data() { return m_paint_contour.is_initialized(); } // QDS void request_update_render_data(bool paint_changed = false) { @@ -94,7 +95,6 @@ public: protected: void update_paint_contour(); - void render_paint_contour(const Transform3d& matrix); protected: bool m_update_render_data = false; @@ -131,13 +131,12 @@ struct TrianglePatch { class TriangleSelectorPatch : public TriangleSelectorGUI { public: - explicit TriangleSelectorPatch(const TriangleMesh& mesh, const std::vector> ebt_colors, float edge_limit = 0.6f) - : TriangleSelectorGUI(mesh, edge_limit), m_ebt_colors(ebt_colors) {} + explicit TriangleSelectorPatch(const TriangleMesh &mesh, const std::vector> ebt_colors, float edge_limit = 0.6f); virtual ~TriangleSelectorPatch() = default; // Render current selection. Transformation matrices are supposed // to be already set. - void render(ImGuiWrapper* imgui, const Transform3d& matrix) override; + void render(ImGuiWrapper *imgui, const Transform3d &matrix, bool render_paint_contour_at_same_time) override; // TriangleSelector.m_triangles => m_gizmo_scene.triangle_patches void update_triangles_per_type(); // m_gizmo_scene.triangle_patches => TriangleSelector.m_triangles @@ -145,6 +144,7 @@ public: void update_triangles_per_patch(); void set_ebt_colors(const std::vector> ebt_colors) { m_ebt_colors = ebt_colors; } + const std::vector> &get_ebt_colors() const { return m_ebt_colors; } void set_filter_state(bool is_filter_state); constexpr static float GapAreaMin = 0.f; @@ -220,9 +220,9 @@ private: void on_render() override {} void on_render_for_picking() override {} public: - GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoPainterBase(GLCanvas3D& parent, unsigned int sprite_id); ~GLGizmoPainterBase() override = default; - virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; // Following function renders the triangles and cursor. Having this separated // from usual on_render method allows to render them before transparent @@ -243,6 +243,7 @@ public: protected: virtual void set_painter_gizmo_data(const Selection &selection); virtual void render_triangles(const Selection& selection) const; + void init_selected_glvolume(GLVolume &v, const TriangleMesh &mesh, const Geometry::Transformation &world_transformation) const; void render_cursor() const; void render_cursor_circle() const; void render_cursor_sphere(const Transform3d& trafo) const; @@ -301,8 +302,15 @@ protected: bool m_triangle_splitting_enabled = true; ToolType m_tool_type = ToolType::BRUSH; - float m_smart_fill_angle = 30.f; - + wchar_t m_current_tool = 0; + mutable int m_last_hit_state = -1; + mutable int m_last_hit_state_faces = -1; + mutable Vec3d m_last_hit_its_center = Vec3d::Zero(); + const float DEFAULT_FILL_ANGLE = 30.f; + float m_smart_fill_angle = DEFAULT_FILL_ANGLE; + float m_last_edge_detection_smart_fill_angle = DEFAULT_FILL_ANGLE; + enum class BucketFillType { SameColor, EdgeDetect }; + BucketFillType m_bucket_fill_mode = BucketFillType::SameColor; bool m_paint_on_overhangs_only = false; float m_highlight_by_angle_threshold_deg = 0.f; @@ -336,6 +344,18 @@ protected: TriangleSelector::ClippingPlane get_clipping_plane_in_volume_coordinates(const Transform3d &trafo) const; void change_camera_view_angle(float front_view_radian); + // Following cache holds result of a raycast query. The queries are asked + // during rendering the sphere cursor and painting, this saves repeated + // raycasts when the mouse position is the same as before. + struct RaycastResult + { + Vec2d mouse_position; + int mesh_id; + Vec3f hit; + size_t facet; + }; + mutable GLGizmoPainterBase::RaycastResult m_rr; + mutable bool m_lock_x_for_height_bottom{false}; private: std::vector> get_projected_mouse_positions(const Vec2d &mouse_position, double resolution, const std::vector &trafo_matrices) const; @@ -355,16 +375,7 @@ protected: Button m_button_down = Button::None; EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) - // Following cache holds result of a raycast query. The queries are asked - // during rendering the sphere cursor and painting, this saves repeated - // raycasts when the mouse position is the same as before. - struct RaycastResult { - Vec2d mouse_position; - int mesh_id; - Vec3f hit; - size_t facet; - }; - mutable RaycastResult m_rr; + // QDS struct CutContours @@ -385,7 +396,6 @@ protected: mutable bool m_is_set_height_start_z_by_imgui{false}; mutable Vec2i m_height_start_pos{0, 0}; mutable float m_x_for_height_input{-1}; - mutable bool m_lock_x_for_height_bottom{false}; mutable Vec2f m_height_range_input_all_size; mutable bool m_is_cursor_in_imgui{false}; BoundingBoxf3 bounding_box() const; @@ -403,13 +413,12 @@ protected: bool on_is_activable() const override; bool on_is_selectable() const override; void on_load(cereal::BinaryInputArchive& ar) override; - void on_save(cereal::BinaryOutputArchive& ar) const override {} + void on_save(cereal::BinaryOutputArchive &ar) const override; CommonGizmosDataID on_get_requirements() const override; bool wants_enter_leave_snapshots() const override { return true; } virtual wxString handle_snapshot_action_name(bool shift_down, Button button_down) const = 0; bool is_mouse_hit_in_imgui()const; - friend class ::Slic3r::GUI::GLGizmoMmuSegmentation; mutable Vec2i m_imgui_start_pos{0, 0}; mutable Vec2i m_imgui_end_pos{0, 0}; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index cc94229..92668af 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -29,7 +29,7 @@ const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) - : GLGizmoBase(parent, "", -1) + : GLGizmoBase(parent, -1) , m_axis(axis) , m_angle(0.0) , m_center(0.0, 0.0, 0.0) @@ -42,7 +42,7 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) } GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other) - : GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id) + : GLGizmoBase(other.m_parent, other.m_sprite_id) , m_axis(other.m_axis) , m_angle(other.m_angle) , m_center(other.m_center) @@ -157,12 +157,12 @@ void GLGizmoRotate::on_render() const auto& shader = wxGetApp().get_shader("flat"); if (shader) { wxGetApp().bind_shader(shader); + const Camera& camera = wxGetApp().plater()->get_camera(); Transform3d redius_scale_matrix; Geometry::scale_transform(redius_scale_matrix, { radius, radius, radius }); Transform3d view_model_matrix = camera.get_view_matrix() * m_base_model_matrix * redius_scale_matrix; - shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); @@ -448,7 +448,6 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick Geometry::assemble_transform(center, Vec3d(-0.5 * PI, 0.0, m_angle)) * Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size)); - shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); m_cone.render_geometry(); @@ -493,7 +492,6 @@ Transform3d GLGizmoRotate::transform_to_local(const Selection &selection) const return m_orient_matrix * ret; - } Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const @@ -580,9 +578,14 @@ BoundingBoxf3 GLGizmoRotate::get_bounding_box() const return t_aabb; } +std::string GLGizmoRotate::get_icon_filename(bool b_dark_mode) const +{ + return ""; +} + //QDS: GUI refactor: add obj manipulation -GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) + : GLGizmoBase(parent, sprite_id) //QDS: GUI refactor: add obj manipulation , m_object_manipulation(obj_manipulation) { @@ -622,6 +625,11 @@ BoundingBoxf3 GLGizmoRotate3D::get_bounding_box() const return t_aabb; } +std::string GLGizmoRotate3D::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_rotate_dark.svg" : "toolbar_rotate.svg"; +} + bool GLGizmoRotate3D::on_init() { for (GLGizmoRotate& g : m_gizmos) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 8ff5161..85a83ca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -77,6 +77,8 @@ public: void set_custom_tran(const Transform3d &tran); BoundingBoxf3 get_bounding_box() const override; + std::string get_icon_filename(bool b_dark_mode) const override; + protected: bool on_init() override; std::string on_get_name() const override { return ""; } @@ -115,7 +117,7 @@ protected: public: //QDS: add obj manipulation logic //GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); + GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); } void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); } @@ -139,6 +141,8 @@ public: BoundingBoxf3 get_bounding_box() const override; + std::string get_icon_filename(bool b_dark_mode) const override; + protected: bool on_init() override; std::string on_get_name() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp index e322db8..733c992 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp @@ -210,7 +210,7 @@ std::string volume_name(const EmbossShape &shape) // QDS: GUI refactor: add obj manipulation GLGizmoSVG::GLGizmoSVG(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, "tool_bar_svg.svg", sprite_id) //"toolbar_cut.svg" no use + : GLGizmoBase(parent, sprite_id) , m_gui_cfg(nullptr) , m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis) { @@ -476,6 +476,11 @@ bool GLGizmoSVG::is_svg(const ModelVolume &volume) { return volume.emboss_shape.has_value() && volume.emboss_shape->svg_file.has_value(); } +bool GLGizmoSVG::on_is_selectable() const +{ + return true; +} + bool GLGizmoSVG::on_init() { m_rotate_gizmo.init(); @@ -493,11 +498,18 @@ std::string GLGizmoSVG::on_get_name() const bool GLGizmoSVG::on_is_activable() const { - const Selection &selection = m_parent.get_selection(); - if (selection.is_empty()) { - return true; + const Selection &t_selection = m_parent.get_selection(); + if (t_selection.is_empty()) { + return false; } - return !selection.is_any_connector();//maybe is negitive volume or modifier volume + if (t_selection.is_any_connector()) { + return false;//maybe is negitive volume or modifier volume + } + + if (!t_selection.has_emboss_shape()) { + return false; + } + return true; } void GLGizmoSVG::on_set_state() { @@ -1337,6 +1349,7 @@ void GLGizmoSVG::draw_window() draw_mirroring(); //draw_face_the_camera(); + if (!m_volume->is_the_only_one_part()) { ImGui::Separator(); draw_model_type(); @@ -1361,12 +1374,19 @@ void GLGizmoSVG::draw_preview() ImTextureID id = (void *) static_cast(m_texture.id); unsigned window_width = static_cast(ImGui::GetWindowSize().x - 2 * ImGui::GetStyle().WindowPadding.x); - if (m_texture.width > window_width && window_width > 0) { - m_texture.width = window_width; - } - if (m_texture.height > m_texture.width) { - m_texture.height = m_texture.width; + if (window_width > 0) { + if (m_texture.width > window_width) { + float scale = window_width / (float) m_texture.width; + m_texture.height = scale * m_texture.height; + m_texture.width = window_width; + } + if (m_texture.height > window_width) { + float scale = window_width / (float) m_texture.height; + m_texture.width = scale * m_texture.width; + m_texture.height = window_width; + } } + ImVec2 s(m_texture.width, m_texture.height); //std::optional spacing; @@ -1400,7 +1420,7 @@ void GLGizmoSVG::draw_preview() /* if (spacing.has_value()) ImGui::SetCursorPosY(ImGui::GetCursorPosY() + *spacing);*/ - } + } } void GLGizmoSVG::draw_filename() @@ -1409,7 +1429,7 @@ void GLGizmoSVG::draw_filename() const EmbossShape::SvgFile &svg = *es.svg_file; if (m_filename_preview.empty()) { // create filename preview - if (!svg.path.empty()) { + if (!svg.path.empty() && boost::filesystem::exists(svg.path)) { m_filename_preview = get_file_name(svg.path); } else if (!svg.path_in_3mf.empty()) { m_filename_preview = get_file_name(svg.path_in_3mf); @@ -1447,7 +1467,7 @@ void GLGizmoSVG::draw_filename() is_hovered |= ImGui::IsItemHovered(); if (is_hovered) { - wxString tooltip = GUI::format_wxstr(_L("SVG file path is \"%1%\""), svg.path); + wxString tooltip = GUI::format_wxstr(_L("SVG file path is \"%1%\""), boost::filesystem::exists(svg.path) ? svg.path : svg.path_in_3mf); m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width); } @@ -1940,7 +1960,8 @@ void GLGizmoSVG::draw_mirroring() m_parent.do_mirror(L("Set Mirror")); // Mirror is ignoring keep up !! - if (m_keep_up) m_angle = calc_angle(selection); + if (m_keep_up) + m_angle = calc_angle(selection); volume_transformation_changed(); @@ -2214,6 +2235,11 @@ BoundingBoxf3 GLGizmoSVG::get_bounding_box() const return t_aabb; } +std::string GLGizmoSVG::get_icon_filename(bool is_dark_mode) const +{ + return "tool_bar_svg.svg"; +} + void GLGizmoSVG::update_single_mesh_pick(GLVolume *v) { if (m_mesh_raycaster_map.find(v) != m_mesh_raycaster_map.end()) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.hpp index 1fc1068..c089df4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.hpp @@ -35,7 +35,7 @@ public: void on_set_hover_id() override { m_rotate_gizmo.set_hover_id(m_hover_id); } void on_enable_grabber(unsigned int id) override; void on_disable_grabber(unsigned int id) override; - + bool wants_enter_leave_snapshots() const override { return true; } /// /// Create new text without given position /// @@ -63,11 +63,13 @@ public: void register_single_mesh_pick(); void update_single_mesh_pick(GLVolume *v); - bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down) override; BoundingBoxf3 get_bounding_box() const override; + std::string get_icon_filename(bool is_dark_mode) const override; + protected: - bool on_is_selectable() const override { return false; } + bool on_is_selectable() const override; virtual bool on_init() override; virtual std::string on_get_name() const override; std::string on_get_name_str() override { return "Move"; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 37ede46..e0c30ef 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -23,8 +23,8 @@ Vec3d GetIntersectionOfRayAndPlane(Vec3d ray_position, Vec3d ray_dir, Vec3d plan } //QDS: GUI refactor: add obj manipulation -GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation) + : GLGizmoBase(parent, sprite_id) , m_scale(Vec3d::Ones()) , m_offset(Vec3d::Zero()) , m_snap_step(0.05) @@ -141,6 +141,11 @@ bool GLGizmoScale3D::on_key(const wxKeyEvent& key_event) return b_processed; } +std::string GLGizmoScale3D::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_scale_dark.svg" : "toolbar_scale.svg"; +} + bool GLGizmoScale3D::on_init() { for (int i = 0; i < 10; ++i) @@ -244,6 +249,7 @@ void GLGizmoScale3D::update_grabbers_data() const Vec3d box_half_size = 0.5 * m_bounding_box.size(); bool b_asymmetric_scalling = is_asymmetric_scalling_enabled(); + bool single_instance = selection.is_single_full_instance(); bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); @@ -252,20 +258,17 @@ void GLGizmoScale3D::update_grabbers_data() m_grabbers[0].color = (b_asymmetric_scalling && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; m_grabbers[1].center = Vec3d(box_half_size.x(), 0.0, -box_half_size.z()); m_grabbers[1].color = (b_asymmetric_scalling && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; - // y axis m_grabbers[2].center = Vec3d(0.0, -(box_half_size.y()), -box_half_size.z()); m_grabbers[2].color = (b_asymmetric_scalling && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; m_grabbers[3].center = Vec3d(0.0, box_half_size.y(), -box_half_size.z()); m_grabbers[3].color = (b_asymmetric_scalling && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; - // z axis do not show 4 m_grabbers[4].center = Vec3d(0.0, 0.0, -(box_half_size.z())); m_grabbers[4].enabled = false; m_grabbers[5].center = Vec3d(0.0, 0.0, box_half_size.z()); m_grabbers[5].color = (b_asymmetric_scalling && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; - // uniform m_grabbers[6].center = Vec3d(-box_half_size.x(), -box_half_size.y(), -box_half_size.z()); m_grabbers[6].color = (b_asymmetric_scalling && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL; @@ -290,6 +293,7 @@ void GLGizmoScale3D::update_grabbers_data() } } + void GLGizmoScale3D::change_cs_by_selection() { int obejct_idx, volume_idx; ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index cd7e3d7..103ab55 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -55,7 +55,7 @@ class GLGizmoScale3D : public GLGizmoBase public: //QDS: add obj manipulation logic //GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); + GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation); double get_snap_step(double step) const { return m_snap_step; } void set_snap_step(double step) { m_snap_step = step; } @@ -71,6 +71,8 @@ public: BoundingBoxf3 get_bounding_box() const override; bool on_key(const wxKeyEvent& key_event) override; + + std::string get_icon_filename(bool b_dark_mode) const override; protected: virtual bool on_init() override; virtual std::string on_get_name() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index afcc7c1..37524f4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -49,8 +49,8 @@ bool GLGizmoSeam::on_init() return true; } -GLGizmoSeam::GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoPainterBase(parent, icon_filename, sprite_id), m_current_tool(ImGui::CircleButtonIcon) +GLGizmoSeam::GLGizmoSeam(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoPainterBase(parent, sprite_id), m_current_tool(ImGui::CircleButtonIcon) { } @@ -104,6 +104,11 @@ bool GLGizmoSeam::on_key_down_select_tool_type(int keyCode) { return true; } +std::string GLGizmoSeam::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_seam_dark.svg" : "toolbar_seam.svg"; +} + void GLGizmoSeam::render_triangles(const Selection& selection) const { ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); @@ -191,7 +196,16 @@ void GLGizmoSeam::tool_changed(wchar_t old_tool, wchar_t new_tool) void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) { - if (! m_c->selection_info()->model_object()) + if (!m_c) { + return; + } + const auto& p_selection_info = m_c->selection_info(); + if (!p_selection_info) { + return; + } + const auto& p_model_object = p_selection_info->model_object(); + + if (!p_model_object) return; m_imgui_start_pos[0] = x; m_imgui_start_pos[1] = y; @@ -362,7 +376,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); - float f_scale =m_parent.get_gizmos_manager().get_layout_scale(); + float f_scale = m_parent.get_main_toolbar_scale(); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); ImGui::SameLine(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index de232ff..39779db 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -8,13 +8,15 @@ namespace Slic3r::GUI { class GLGizmoSeam : public GLGizmoPainterBase { public: - GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoSeam(GLCanvas3D& parent, unsigned int sprite_id); void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; //QDS bool on_key_down_select_tool_type(int keyCode); + std::string get_icon_filename(bool b_dark_mode) const override; + protected: // QDS void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 43be0f1..b8eb97c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -56,10 +56,8 @@ static ModelVolume* get_model_volume(const Selection& selection, Model& model) return obj->volumes[cid.volume_id]; } -GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent, - const std::string &icon_filename, - unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, -1) +GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) , m_volume(nullptr) , m_show_wireframe(false) , m_move_to_center(false) @@ -137,6 +135,11 @@ void GLGizmoSimplify::add_simplify_suggestion_notification( } } +std::string GLGizmoSimplify::get_icon_filename(bool is_dark_mode) const +{ + return "reduce_triangles.svg"; +} + std::string GLGizmoSimplify::on_get_name() const { if (!on_is_activable()) { @@ -630,8 +633,15 @@ void GLGizmoSimplify::init_model(const indexed_triangle_set& its) m_glmodel.reset(); m_glmodel.init_from(its); m_parent.toggle_model_objects_visibility(true); // selected volume may have changed - m_parent.toggle_model_objects_visibility(false, m_c->selection_info()->model_object(), - m_c->selection_info()->get_active_instance(), m_volume); + if (m_c) { + const auto& p_selection_info = m_c->selection_info(); + if (p_selection_info) { + const auto& p_model_object = p_selection_info->model_object(); + const auto& active_instance = p_selection_info->get_active_instance(); + m_parent.toggle_model_objects_visibility(false, p_model_object, + active_instance, m_volume); + } + } if (const Selection&sel = m_parent.get_selection(); sel.get_volume_idxs().size() == 1) m_glmodel.set_color(-1, sel.get_volume(*sel.get_volume_idxs().begin())->color); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index be667e4..c9979d8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -17,9 +17,9 @@ namespace GUI { class NotificationManager; // for simplify suggestion class GLGizmoSimplify: public GLGizmoBase -{ +{ public: - GLGizmoSimplify(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoSimplify(GLCanvas3D& parent, unsigned int sprite_id); virtual ~GLGizmoSimplify(); bool on_esc_key_down(); static void add_simplify_suggestion_notification( @@ -27,6 +27,8 @@ public: const std::vector & objects, NotificationManager & manager); + std::string get_icon_filename(bool is_dark_mode) const override; + protected: virtual std::string on_get_name() const override; virtual std::string on_get_name_str() override { return "Simplify"; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 1f7f0f9..55c5fdf 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -26,12 +26,17 @@ namespace Slic3r { namespace GUI { -GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) { } +std::string GLGizmoSlaSupports::get_icon_filename(bool is_dark_mode) const +{ + return "sla_supports.svg"; +} + bool GLGizmoSlaSupports::on_init() { m_shortcut_key = WXK_CONTROL_L; @@ -178,7 +183,6 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. const Transform3d support_matrix = Geometry::assemble_transform(support_point.pos.cast()) * instance_scaling_matrix_inverse; - if (vol->is_left_handed()) glFrontFace(GL_CW); @@ -191,6 +195,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast()); + Eigen::AngleAxisd aa(q); const double cone_radius = 0.25; // mm const double cone_height = 0.75; @@ -251,7 +256,6 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glFrontFace(GL_CCW); } } - } bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 3c9871f..35964ba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -55,10 +55,10 @@ private: }; public: - GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id); virtual ~GLGizmoSlaSupports() = default; void set_sla_support_data(ModelObject* model_object, const Selection& selection); - bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override; void delete_selected_points(bool force = false); //ClippingPlane get_sla_clipping_plane() const; @@ -71,6 +71,8 @@ public: std::string get_gizmo_entering_text() const override { return "Entering SLA support points"; } std::string get_gizmo_leaving_text() const override { return "Leaving SLA support points"; } + std::string get_icon_filename(bool is_dark_mode) const override; + private: bool on_init() override; void on_update(const UpdateData& data) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 8fc87b5..694f47e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -7,11 +7,25 @@ #include "slic3r/GUI/ImGuiWrapper.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/MsgDialog.hpp" +#include "slic3r/GUI/format.hpp" #include "libslic3r/Geometry/ConvexHull.hpp" #include "libslic3r/Model.hpp" - +#include "libslic3r/Timer.hpp" #include "libslic3r/Shape/TextShape.hpp" +#include "slic3r/Utils/WxFontUtils.hpp" +#include "slic3r/GUI/Jobs/CreateFontNameImageJob.hpp" +#include "slic3r/GUI/Jobs/NotificationProgressIndicator.hpp" +#include "slic3r/Utils/UndoRedo.hpp" + +#include +#include +#include +#include +#include // detection of change DPI +#include +#include #include #include @@ -19,182 +33,398 @@ #include +#include "imgui/imgui_stdlib.h" // using std::string for inputs #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include #include "libslic3r/SVG.hpp" #include -#include "wx/fontenum.h" -#include "FontUtils.hpp" +#include "../ParamsPanel.hpp" +using namespace Slic3r; +using namespace Slic3r::GUI; +using namespace Slic3r::GUI::Emboss; +using namespace Slic3r::Emboss; +static std::size_t hash_value(wxString const &s) +{ + boost::hash hasher; + return hasher(s.ToStdString()); +} + +// increase number when change struct FacenamesSerializer +constexpr std::uint32_t FACENAMES_VERSION = 1; +struct FacenamesSerializer +{ + // hash number for unsorted vector of installed font into system + size_t hash = 0; + // assumption that is loadable + std::vector good; + // Can't load for some reason + std::vector bad; +}; +template void save(Archive &archive, wxString const &d) +{ + auto data = into_u8(d); + archive(data); +} +template void load(Archive &archive, wxString &d) +{ + std::string s; + archive(s); + d = from_u8(s); +} +template void serialize(Archive &ar, FacenamesSerializer &t, const std::uint32_t version) +{ + // When performing a load, the version associated with the class + // is whatever it was when that data was originally serialized + // When we save, we'll use the version that is defined in the macro + if (version != FACENAMES_VERSION) { + throw Slic3r::IOError("Version of hints.cereal is higher than current version."); + return; + } + ar(t.hash, t.good, t.bad); +} +CEREAL_CLASS_VERSION(FacenamesSerializer, FACENAMES_VERSION); // register class version namespace Slic3r { namespace GUI { +namespace Text { +template struct Limit +{ + // Limitation for view slider range in GUI + MinMax gui; + // Real limits for setting exacts values + MinMax values; +}; +static const struct Limits +{ + MinMax emboss{0.01, 1e4}; // in mm + MinMax size_in_mm{1.0f, 1000.f}; // in mm + Limit boldness{{-.1f, .1f}, {-5e5f, 5e5f}}; // in font points + Limit skew{{-1.f, 1.f}, {-100.f, 100.f}}; // ration without unit + MinMax char_gap{-20000, 20000}; // in font points + MinMax line_gap{-20000, 20000}; // in font points + // distance text object from surface + MinMax angle{-180.f, 180.f}; // in degrees +} limits; +enum class IconType : unsigned { + rename = 0, + warning, + undo, + save, + add, + erase, + /* + italic, + unitalic, + bold, + unbold, + system_selector, + open_file, + lock, + lock_bold, + unlock, + unlock_bold, + align_horizontal_left, + align_horizontal_center, + align_horizontal_right, + align_vertical_top, + align_vertical_center, + align_vertical_bottom,*/ + // automatic calc of icon's count + _count +}; +// Define rendered version of icon +enum class IconState : unsigned { activable = 0, hovered /*1*/, disabled /*2*/ }; +// selector for icon by enum +const IconManager::Icon &get_icon(const IconManager::VIcons &icons, IconType type, IconState state); -static const double PI = 3.141592653589793238; -static const wxColour FONT_TEXTURE_BG = wxColour(0, 0, 0, 0); +struct CurGuiCfg +{ + // Detect invalid config values when change monitor DPI + double screen_scale; + bool dark_mode = false; + + // Zero means it is calculated in init function + float height_of_volume_type_selector = 0.f; + float input_width = 0.f; + float delete_pos_x = 0.f; + float max_style_name_width = 0.f; + unsigned int icon_width = 0; + float max_tooltip_width = 0.f; + + // maximal width and height of style image + Vec2i32 max_style_image_size = Vec2i32(0, 0); + + float indent = 0.f; + float input_offset = 0.f; + float advanced_input_offset = 0.f; + float lock_offset = 0.f; + + ImVec2 text_size; + + // maximal size of face name image + Vec2i32 face_name_size = Vec2i32(0, 0); + float face_name_texture_offset_x = 0.f; + + // maximal texture generate jobs running at once + unsigned int max_count_opened_font_files = 10; + + // Only translations needed for calc GUI size + struct Translations + { + std::string font; + std::string height; + std::string depth; + + // advanced + std::string use_surface; + std::string per_glyph; + std::string alignment; + std::string char_gap; + std::string line_gap; + std::string boldness; + std::string skew_ration; + std::string from_surface; + std::string rotation; + }; + Translations translations; +}; +CurGuiCfg create_gui_configuration(); +} +using namespace Text; +IconManager::VIcons init_text_icons(IconManager &mng, const CurGuiCfg &cfg)//init_icons +{ + mng.release(); + + ImVec2 size(cfg.icon_width, cfg.icon_width); + // icon order has to match the enum IconType + std::vector filenames{ + "edit_button.svg", + "obj_warning.svg", // exclamation // ORCA: use obj_warning instead exclamation. exclamation is not compatible with low res + "text_undo.svg", // reset_value + "text_save.svg", // save + "add_copies.svg", + "delete2.svg", + //"text_refresh.svg", // refresh + //"text_open.svg", // changhe_file + //"text_bake.svg", // bake + + //"text_obj_warning.svg", // exclamation // ORCA: use obj_warning instead exclamation. exclamation is not compatible with low res + //"text_lock_closed.svg", // lock + //"text_lock_open.svg", // unlock + //"text_reflection_x.svg", // reflection_x + //"text_reflection_y.svg", // reflection_y + }; + + assert(filenames.size() == static_cast(IconType::_count)); + std::string path = resources_dir() + "/images/"; + for (std::string &filename : filenames) + filename = path + filename; + + auto type = IconManager::RasterType::color_wite_gray; + return mng.init(filenames, size, type); +} +bool is_text_empty(std::string_view text) { return text.empty() || text.find_first_not_of(" \n\t\r") == std::string::npos; } +struct GLGizmoText::GuiCfg : public Text::CurGuiCfg +{}; + +static const wxColour FONT_TEXTURE_BG = wxColour(0, 0, 0, 0); static const wxColour FONT_TEXTURE_FG = *wxWHITE; static const int FONT_SIZE = 12; static const float SELECTABLE_INNER_OFFSET = 8.0f; -static const wxFontEncoding font_encoding = wxFontEncoding::wxFONTENCODING_SYSTEM; const std::array TEXT_GRABBER_COLOR = {1.0, 1.0, 0.0, 1.0}; const std::array TEXT_GRABBER_HOVER_COLOR = {0.7, 0.7, 0.0, 1.0}; -#ifdef DEBUG_TEXT std::string formatFloat(float val) { std::stringstream ss; ss << std::fixed << std::setprecision(2) << val; return ss.str(); } -#endif -std::vector init_face_names() + +bool draw_button(const IconManager::VIcons &icons, IconType type, bool disable = false); +struct FaceName { - std::vector valid_font_names; - wxArrayString facenames = wxFontEnumerator::GetFacenames(font_encoding); - std::vector bad_fonts; + wxString wx_name; + std::string name_truncated = ""; + size_t texture_index = 0; + // State for generation of texture + // when start generate create share pointers + std::shared_ptr> cancel = nullptr; + // R/W only on main thread - finalize of job + std::shared_ptr is_created = nullptr; +}; +// Implementation of forwarded struct +// Keep sorted list of loadable face names +struct CurFacenames +{ + // flag to keep need of enumeration fonts from OS + // false .. wants new enumeration check by Hash + // true .. already enumerated(During opened combo box) + bool is_init = false; - BOOST_LOG_TRIVIAL(info) << "init_fonts_names start"; + bool has_truncated_names = false; - // validation lambda - auto is_valid_font = [coding = font_encoding, bad = bad_fonts](const wxString &name) { - if (name.empty()) - return false; + // data of can_load() faces + std::vector faces = {}; + std::vector faces_names = {}; + // Sorter set of Non valid face names in OS + std::vector bad = {}; - // vertical font start with @, we will filter it out - // Not sure if it is only in Windows so filtering is on all platforms - if (name[0] == '@') - return false; + // Configuration of font encoding + static const wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM; - // previously detected bad font - auto it = std::lower_bound(bad.begin(), bad.end(), name); - if (it != bad.end() && *it == name) - return false; + // Identify if preview texture exists + GLuint texture_id = 0; - wxFont wx_font(wxFontInfo().FaceName(name).Encoding(coding)); - // Faster chech if wx_font is loadable but not 100% - // names could contain not loadable font - if (!wx_font.IsOk()) - return false; + // protection for open too much font files together + // Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load + // /usr/share/icons/Yaru/48x48/status/image-missing.png: Error opening file /usr/share/icons/Yaru/48x48/status/image-missing.png: Too + // many open files (g-io-error-quark, 31) This variable must exist until no CreateFontImageJob is running + unsigned int count_opened_font_files = 0; - if (!can_load(wx_font)) - return false; + // Configuration for texture height + const int count_cached_textures = 32; + // index for new generated texture index(must be lower than count_cached_textures) + size_t texture_index = 0; + + // hash created from enumerated font from OS + // check when new font was installed + size_t hash = 0; + + // filtration pattern + // std::string search = ""; + // std::vector hide; // result of filtration +}; +struct GLGizmoText::Facenames : public CurFacenames +{}; + +bool store(const CurFacenames &facenames); +bool load(CurFacenames &facenames,const std::vector& delete_bad_font_list); +void init_face_names(CurFacenames &face_names); +void init_truncated_names(CurFacenames &face_names, float max_width); +std::optional get_installed_face_name(const std::optional &face_name_opt, CurFacenames &face_names); +void draw_font_preview(FaceName &face, const std::string &text, CurFacenames &faces, const CurGuiCfg &cfg, bool is_visible); +void init_text_lines(TextLinesModel &text_lines, const Selection &selection, /* const*/ StyleManager &style_manager, unsigned count_lines = 0); +class TextDataBase : public DataBase +{ +public: + TextDataBase(DataBase &&parent, const FontFileWithCache &font_file, TextConfiguration &&text_configuration, const EmbossProjection &projection) + : DataBase(std::move(parent)), m_font_file(font_file) /* copy */, m_text_configuration(std::move(text_configuration)) + { + assert(m_font_file.has_value()); + shape.projection = projection; // copy + + const FontProp &fp = m_text_configuration.style.prop; + const FontFile &ff = *m_font_file.font_file; + shape.scale = get_text_shape_scale(fp, ff); + } + // Create shape from text + font configuration + EmbossShape &create_shape() override; + void write(ModelVolume &volume) const override; + TextConfiguration get_text_configuration() override { + return m_text_configuration; + } + /// + /// Used only with text for embossing per glyph. + /// Create text lines only for new added volume to object + /// otherwise textline is already setted before + /// + /// Embossed volume final transformation in object + /// Volumes to be sliced to text lines + /// True on succes otherwise False(Per glyph shoud be disabled) + //bool create_text_lines(const Transform3d &tr, const ModelVolumePtrs &vols) override; + +private: + // Keep pointer on Data of font (glyph shapes) + FontFileWithCache m_font_file; + // font item is not used for create object + TextConfiguration m_text_configuration; +}; + +void TextDataBase::write(ModelVolume &volume) const +{ + //DataBase::write(volume); + volume.set_text_configuration(m_text_configuration);// volume.text_configuration = m_text_configuration; // copy + // Fix for object: stored attribute that volume is embossed per glyph when it is object + if (m_text_configuration.style.prop.per_glyph && volume.is_the_only_one_part()) { + volume.get_text_configuration().style.prop.per_glyph = false; + } +} +void GLGizmoText::calculate_scale() +{ + Transform3d to_world = m_parent.get_selection().get_first_volume()->world_matrix(); + auto to_world_linear = to_world.linear(); + auto calc = [&to_world_linear](const Vec3d &axe, std::optional &scale) -> bool { + Vec3d axe_world = to_world_linear * axe; + double norm_sq = axe_world.squaredNorm(); + if (is_approx(norm_sq, 1.)) { + if (scale.has_value()) + scale.reset(); + else + return false; + } else { + scale = sqrt(norm_sq); + } return true; }; - std::sort(facenames.begin(), facenames.end()); - for (const wxString &name : facenames) { - if (is_valid_font(name)) { - valid_font_names.push_back(name.ToStdString()); - } - else { - bad_fonts.emplace_back(name); - } - } - assert(std::is_sorted(bad_fonts.begin(), bad_fonts.end())); + bool exist_change = calc(Vec3d::UnitY(), m_scale_height); + exist_change |= calc(Vec3d::UnitZ(), m_scale_depth); - BOOST_LOG_TRIVIAL(info) << "init_fonts_names end"; - - return valid_font_names; + // Change of scale has to change font imgui font size + if (exist_change) + m_style_manager.clear_imgui_font(); } - -class Line_3D -{ -public: - Line_3D(Vec3d i_a, Vec3d i_b) : a(i_a), b(i_b) {} - - double length() { return (b - a).cast().norm(); } - - Vec3d vector() - { - Vec3d new_vec = b - a; - new_vec.normalize(); - return new_vec; - } - - void reverse() { std::swap(this->a, this->b); } - - Vec3d a; - Vec3d b; -}; - -class Polygon_3D -{ -public: - Polygon_3D(const std::vector &points) : m_points(points) {} - - std::vector get_lines() - { - std::vector lines; - lines.reserve(m_points.size()); - if (m_points.size() > 2) { - for (int i = 0; i < m_points.size() - 1; ++i) { lines.push_back(Line_3D(m_points[i], m_points[i + 1])); } - lines.push_back(Line_3D(m_points.back(), m_points.front())); - } - return lines; - } - std::vector m_points; -}; - -// for debug -void export_regions_to_svg(const Point &point, const Polygons &polylines) -{ - std::string path = "D:/svg_profiles/text_poly.svg"; - //BoundingBox bbox = get_extents(polylines); - SVG svg(path.c_str()); - svg.draw(polylines, "green"); - svg.draw(point, "red", 5e6); -} - -int preNUm(unsigned char byte) -{ - unsigned char mask = 0x80; - int num = 0; - for (int i = 0; i < 8; i++) { - if ((byte & mask) == mask) { - mask = mask >> 1; - num++; - } else { - break; - } - } - return num; -} - -// https://www.jianshu.com/p/a83d398e3606 -bool get_utf8_sub_strings(char *data, int len, std::vector &out_strs) -{ - out_strs.clear(); - std::string str = std::string(data); - - int num = 0; - int i = 0; - while (i < len) { - if ((data[i] & 0x80) == 0x00) { - out_strs.emplace_back(str.substr(i, 1)); - i++; - continue; - } else if ((num = preNUm(data[i])) > 2) { - int start = i; - i++; - for (int j = 0; j < num - 1; j++) { - if ((data[i] & 0xc0) != 0x80) { return false; } - i++; - } - out_strs.emplace_back(str.substr(start, i - start)); - } else { - return false; - } - } - return true; -} - /////////////////////// -/// GLGizmoText start -GLGizmoText::GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +class StyleNameEditDialog : public DPIDialog { +public: + StyleNameEditDialog(wxWindow * parent, + Emboss::StyleManager &style_manager, + wxWindowID id = wxID_ANY, + const wxString &title = wxEmptyString, + const wxPoint & pos = wxDefaultPosition, + const wxSize & size = wxDefaultSize, + long style = wxCLOSE_BOX | wxCAPTION); + + ~StyleNameEditDialog(); + void on_dpi_changed(const wxRect &suggested_rect) override; + + wxString get_name() const; + void set_name(const wxString &name); + void on_edit_text(wxCommandEvent &event); + void add_tip_label(); + +private: + bool check_empty_or_iillegal_character(const std::string &name); + +private: + Button * m_button_ok{nullptr}; + Button * m_button_cancel{nullptr}; + TextInput *m_name{nullptr}; + Label * m_tip{nullptr}; + bool m_add_tip{false}; + wxPanel * m_row_panel{nullptr}; + Emboss::StyleManager &m_style_manager; + wxFlexGridSizer * m_top_sizer{nullptr}; +}; +/// GLGizmoText start + +GLGizmoText::GLGizmoText(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id), + m_face_names(std::make_unique()), + m_style_manager(m_imgui->get_glyph_ranges(), create_default_styles), + m_gui_cfg(nullptr), m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis) +{ + m_rotate_gizmo.set_group_id(0); + m_rotate_gizmo.set_force_local_coordinate(true); + + if (GUI::wxGetApp().app_config->get_bool("support_backup_fonts")) { + Slic3r::GUI::BackupFonts::generate_backup_fonts(); + } } GLGizmoText::~GLGizmoText() @@ -210,11 +440,19 @@ GLGizmoText::~GLGizmoText() bool GLGizmoText::on_init() { + m_rotate_gizmo.init(); + ColorRGBA gray_color(.6f, .6f, .6f, .3f); + m_rotate_gizmo.set_highlight_color(gray_color.get_data()); + // Set rotation gizmo upwardrotate + m_rotate_gizmo.set_angle(PI / 2); + m_init_texture = false; - m_avail_font_names = init_face_names(); - - m_thread = std::thread(&GLGizmoText::update_font_status, this); + m_style_manager.init(wxGetApp().app_config); + Emboss::StyleManager::Style &style = m_style_manager.get_style(); + std::optional installed_name = get_installed_face_name(style.prop.face_name, *m_face_names); + //m_avail_font_names = init_face_names();//todo + //m_thread = std::thread(&GLGizmoText::update_font_status, this); //m_avail_font_names = init_occt_fonts(); //update_font_texture(); m_scale = m_imgui->get_font_size(); @@ -222,9 +460,6 @@ bool GLGizmoText::on_init() reset_text_info(); - m_desc["rotate_text_caption"] = _L("Shift + Mouse move up or down"); - m_desc["rotate_text"] = _L("Rotate text"); - return true; } @@ -282,17 +517,113 @@ BoundingBoxf3 GLGizmoText::bounding_box() const const Selection::IndicesList &idxs = selection.get_volume_idxs(); for (unsigned int i : idxs) { const GLVolume *volume = selection.get_volume(i); - if (!volume->is_modifier) ret.merge(volume->transformed_convex_hull_bounding_box()); + if (!volume->is_modifier) + ret.merge(volume->transformed_convex_hull_bounding_box()); } return ret; } +#define SYSTEM_STYLE_MAX 6 +EmbossStyles GLGizmoText::create_default_styles() +{ + wxFontEnumerator::InvalidateCache(); + wxArrayString facenames = wxFontEnumerator::GetFacenames(CurFacenames::encoding); + + wxFont wx_font_normal = *wxNORMAL_FONT; +#ifdef __APPLE__ + // Set normal font to helvetica when possible + for (const wxString &facename : facenames) { + if (facename.IsSameAs("Helvetica")) { + wx_font_normal = wxFont(wxFontInfo().FaceName(facename).Encoding(Facenames::encoding)); + break; + } + } +#endif // __APPLE__ + + // https://docs.wxwidgets.org/3.0/classwx_font.html + // Predefined objects/pointers: wxNullFont, wxNORMAL_FONT, wxSMALL_FONT, wxITALIC_FONT, wxSWISS_FONT + EmbossStyles styles = { +#ifdef __APPLE__ + WxFontUtils::create_emboss_style(wx_font_normal, _u8L("Recommend")), // v2.0 version + WxFontUtils::create_emboss_style(wx_font_normal, _u8L("Old version")), // for 1.10 and 1.9 and old version +#else + WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("Recommend")), //v2.0 version + WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("Old version")), // for 1.10 and 1.9 and old version +#endif + }; + + // Not all predefined font for wx must be valid TTF, but at least one style must be loadable + styles.erase(std::remove_if(styles.begin(), styles.end(), + [](const EmbossStyle &style) { + wxFont wx_font = WxFontUtils::create_wxFont(style); + + // check that face name is setabled + if (style.prop.face_name.has_value()) { + wxString face_name = wxString::FromUTF8(style.prop.face_name->c_str()); + wxFont wx_font_temp; + if (!wx_font_temp.SetFaceName(face_name)) + return true; + } + + // Check that exsit valid TrueType Font for wx font + return WxFontUtils::create_font_file(wx_font) == nullptr; + }), + styles.end()); + + // exist some valid style? + if (!styles.empty()) + return styles; + + // No valid style in defult list + // at least one style must contain loadable font + wxFont wx_font; + for (const wxString &face : facenames) { + wx_font = wxFont(face); + if (WxFontUtils::create_font_file(wx_font) != nullptr) + break; + wx_font = wxFont(); // NotOk + } + + if (wx_font.IsOk()) { + // use first alphabetic sorted installed font + styles.push_back(WxFontUtils::create_emboss_style(wx_font, _u8L("First font"))); + } else { + // On current OS is not installed any correct TTF font + // use font packed with Slic3r + std::string font_path = Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf"; + styles.push_back(EmbossStyle{_u8L("Default font"), font_path, EmbossStyle::Type::file_path}); + } + return styles; +} + +bool GLGizmoText::select_facename(const wxString &facename, bool update_text) +{ + if (!wxFontEnumerator::IsValidFacename(facename)) + return false; + // Select font + wxFont wx_font(wxFontInfo().FaceName(facename).Encoding(CurFacenames::encoding)); + if (!wx_font.IsOk()) + return false; +#ifdef USE_PIXEL_SIZE_IN_WX_FONT + // wx font could change source file by size of font + int point_size = static_cast(m_style_manager.get_font_prop().size_in_mm); + wx_font.SetPointSize(point_size); +#endif // USE_PIXEL_SIZE_IN_WX_FONT + if (!m_style_manager.set_wx_font(wx_font)) + return false; + if (update_text) { + process(); + } + return true; +} bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down) { std::string text = std::string(m_text); if (text.empty()) return true; - + if (m_object_idx < 0) { + return true; + } const Selection &selection = m_parent.get_selection(); auto mo = selection.get_model()->objects[m_object_idx]; if (mo == nullptr) @@ -302,110 +633,38 @@ bool GLGizmoText::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_posit const Camera & camera = wxGetApp().plater()->get_camera(); if (action == SLAGizmoEventType::Moving) { - if (shift_down && !alt_down && !control_down) { - float angle = m_rotate_angle + 0.5 * (m_mouse_position - mouse_position).y(); - if (angle == 0) - return true; - - while (angle < 0) - angle += 360; - - while (angle >= 360) - angle -= 360; - - m_rotate_angle = angle; - m_shift_down = true; - m_need_update_text = true; - } else { - m_shift_down = false; - m_origin_mouse_position = mouse_position; - } m_mouse_position = mouse_position; } else if (action == SLAGizmoEventType::LeftDown) { + if (is_only_text_case()) { + return false; + } if (!selection.is_empty() && get_hover_id() != -1) { start_dragging(); return true; } - if (m_is_modify) - return true; - - Plater *plater = wxGetApp().plater(); - if (!plater || m_thickness <= 0) - return true; - - ModelObject *model_object = selection.get_model()->objects[m_object_idx]; - if (m_preview_text_volume_id > 0) { - model_object->delete_volume(m_preview_text_volume_id); - plater->update(); - m_preview_text_volume_id = -1; - } - - // Precalculate transformations of individual meshes. - std::vector trafo_matrices; - for (const ModelVolume *mv : mo->volumes) { - if (mv->is_model_part()) { trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); } - } - - Vec3f normal = Vec3f::Zero(); - Vec3f hit = Vec3f::Zero(); - size_t facet = 0; - Vec3f closest_hit = Vec3f::Zero(); - Vec3f closest_normal = Vec3f::Zero(); - double closest_hit_squared_distance = std::numeric_limits::max(); - int closest_hit_mesh_id = -1; - - // Cast a ray on all meshes, pick the closest hit and save it for the respective mesh - for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) { - MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh()); - - if (mesh_raycaster.unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal, - m_c->object_clipper()->get_clipping_plane(), &facet)) { - // In case this hit is clipped, skip it. - if (is_mesh_point_clipped(hit.cast(), trafo_matrices[mesh_id])) - continue; - - // Is this hit the closest to the camera so far? - double hit_squared_distance = (camera.get_position() - trafo_matrices[mesh_id] * hit.cast()).squaredNorm(); - if (hit_squared_distance < closest_hit_squared_distance) { - closest_hit_squared_distance = hit_squared_distance; - closest_hit_mesh_id = mesh_id; - closest_hit = hit; - closest_normal = normal; - } - } - } - - if (closest_hit == Vec3f::Zero() && closest_normal == Vec3f::Zero()) - return true; - - m_rr = {mouse_position, closest_hit_mesh_id, closest_hit, closest_normal};//left down - - generate_text_volume(false); - m_is_modify = true; - plater->update(); } - return true; } void GLGizmoText::on_set_state() { + m_rotate_gizmo.set_state(GLGizmoBase::m_state); if (m_state == EState::On) { + m_text_tran_in_object.reset(); + m_style_manager.get_style().angle = 0; + m_last_text_mv = nullptr; - m_need_fix = false; m_show_text_normal_reset_tip = false; - load_init_text(); + load_init_text(true); if (m_last_text_mv) { m_reedit_text = true; - m_need_fix = true; m_load_text_tran_in_object = m_text_tran_in_object; if (m_really_use_surface_calc) { m_show_warning_regenerated = true; - m_need_fix = false; use_fix_normal_position(); - } else if (m_fix_old_tran_flag && m_font_version == "") { + } else if (m_fix_old_tran_flag && (m_font_version == "" || m_font_version == "1.0")) { m_show_warning_old_tran = false; auto offset = m_text_tran_in_object.get_offset(); auto rotation = m_text_tran_in_object.get_rotation(); @@ -421,24 +680,37 @@ void GLGizmoText::on_set_state() count += has_mirror ? 1 : 0; Geometry::Transformation expert_text_tran_in_world; - generate_text_tran_in_world(m_fix_text_normal_in_world.cast(), m_text_position_in_world, m_rotate_angle, expert_text_tran_in_world); - auto temp_expert_text_tran_in_object = m_object_cs_to_world_tran.inverse() * expert_text_tran_in_world.get_matrix(); + generate_text_tran_in_world(m_fix_text_normal_in_world.cast(), m_fix_text_position_in_world, m_rotate_angle, expert_text_tran_in_world); + auto temp_expert_text_tran_in_object = m_model_object_in_world_tran.get_matrix().inverse() * expert_text_tran_in_world.get_matrix(); Geometry::Transformation expert_text_tran_in_object(temp_expert_text_tran_in_object); - expert_text_tran_in_object.set_offset(m_text_tran_in_object.get_offset()); if (count >= 2) { m_show_warning_old_tran = true; } if (m_is_version1_10_xoy) { auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {0.5 * M_PI, 0.0, 0.0}); - m_load_text_tran_in_object.set_from_transform(m_load_text_tran_in_object.get_matrix() * rotate_tran); - m_load_text_tran_in_object.set_offset(m_load_text_tran_in_object.get_offset() + Vec3d(0, 1.65, 0)); // for size 16 + m_text_tran_in_object.set_from_transform(m_load_text_tran_in_object.get_matrix() * rotate_tran); + m_text_tran_in_object.set_offset(m_load_text_tran_in_object.get_offset() + Vec3d(0, 1.65, 0)); // for size 16 + + m_text_normal_in_world = m_fix_text_normal_in_world; + update_cut_plane_dir(); + return; + } else if (m_is_version1_8_yoz) {//Box+172x125x30_All_Bases + const Selection &selection = m_parent.get_selection(); + m_style_manager.get_style().angle = calc_angle(selection); + + auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {0.0, 0.0, 0.5 * M_PI}); + m_text_tran_in_object.set_from_transform(m_load_text_tran_in_object.get_matrix() * rotate_tran); + update_cut_plane_dir(); + m_text_tran_in_object.set_offset(expert_text_tran_in_object.get_offset()); return; } //go on if (has_rotation && m_show_warning_old_tran == false) { m_show_warning_lost_rotate = true; - m_need_fix = false; + if (m_is_version1_9_xoz) { + expert_text_tran_in_object.set_rotation(rotation); + } use_fix_normal_position(); } //not need set set_rotation//has_rotation @@ -448,50 +720,695 @@ void GLGizmoText::on_set_state() if (has_mirror) { expert_text_tran_in_object.set_mirror(mirror); } - m_load_text_tran_in_object.set_from_transform(expert_text_tran_in_object.get_matrix()); - if (m_is_version1_9_xoz) { - m_load_text_tran_in_object.set_offset(m_load_text_tran_in_object.get_offset()); - } + m_text_tran_in_object.set_from_transform(expert_text_tran_in_object.get_matrix()); + update_cut_plane_dir(); } } } else if (m_state == EState::Off) { ImGui::FocusWindow(nullptr);//exit cursor + m_trafo_matrices.clear(); m_reedit_text = false; m_fix_old_tran_flag = false; + m_warning_font = false; close_warning_flag_after_close_or_drag(); reset_text_info(); - delete_temp_preview_text_volume(); + m_parent.use_slope(false); m_parent.toggle_model_objects_visibility(true); + + m_style_manager.store_styles_to_app_config(false); } } -void GLGizmoText::check_text_type(bool is_surface_text, bool is_keep_horizontal) { - if (is_surface_text && is_keep_horizontal) { - m_text_type = TextType::SURFACE_HORIZONAL; - } else if (is_surface_text) { - m_text_type = TextType::SURFACE; - } else if (is_keep_horizontal) { - m_text_type = TextType::HORIZONAL; - } else { - m_text_type = TextType::HORIZONAL; +void GLGizmoText::load_old_font() { + const int old_font_index = 1; + const StyleManager::Style &style = m_style_manager.get_styles()[old_font_index]; + // create copy to be able do fix transformation only when successfully load style + if (m_style_manager.load_style(old_font_index)) { + if (m_italic && m_thickness) { + m_style_manager.get_font_prop().size_in_mm = m_font_size * 0.92; + } + else if (m_italic){ + m_style_manager.get_font_prop().size_in_mm = m_font_size * 0.98; + } + else if (m_thickness) { + m_style_manager.get_font_prop().size_in_mm = m_font_size * 0.93; + } else { + m_style_manager.get_font_prop().size_in_mm = m_font_size * 1.0; + } + wxString font_name(m_font_name); + bool update_text = !m_is_serializing ? true : false; + if (!select_facename(font_name, update_text)) { + wxString font_name("Arial"); + select_facename(font_name, update_text); + } } } +wxString FindLastName(const wxString &input) +{ + int lastSemicolonPos = input.Find(';', true); + if (lastSemicolonPos == wxNOT_FOUND) { return input; } + return input.Mid(lastSemicolonPos + 1); +} + +void GLGizmoText::draw_style_list(float caption_size) +{ + if (!m_style_manager.is_active_font()) + return; + + const StyleManager::Style *stored_style = nullptr; + bool is_stored = m_style_manager.exist_stored_style(); + if (is_stored) + stored_style = m_style_manager.get_stored_style(); + const StyleManager::Style ¤t_style = m_style_manager.get_style(); + + bool is_changed = true; + if (stored_style) { + wxString path0((*stored_style).path.c_str(), wxConvUTF8); + wxString path1(current_style.path.c_str(), wxConvUTF8); + auto stored_font_name = FindLastName(path0); + auto current_font_name = FindLastName(path1); + is_changed = !(*stored_style == current_style && stored_font_name == current_font_name); + } + bool is_modified = is_stored && is_changed; + const float &max_style_name_width = m_gui_cfg->max_style_name_width; + std::string &trunc_name = m_style_manager.get_truncated_name(); + m_style_name = m_style_manager.get_truncated_name(); + if (trunc_name.empty()) { + // generate trunc name + std::string current_name = current_style.name; + ImGuiWrapper::escape_double_hash(current_name); + trunc_name = ImGuiWrapper::trunc(current_name, max_style_name_width); + } + ImGui::AlignTextToFramePadding(); + std::string title = _u8L("Style"); + if (m_style_manager.exist_stored_style()) + ImGui::Text("%s", title.c_str()); + else + ImGui::TextColored(ImGuiWrapper::COL_QIDI, "%s", title.c_str()); + if (ImGui::IsItemHovered()) { + m_imgui->tooltip(_u8L("Save the parameters of the current text tool as a style for easy subsequent use."), m_gui_cfg->max_tooltip_width); + } + ImGui::SameLine(caption_size); + ImGui::PushItemWidth(m_gui_cfg->input_width); + auto add_text_modify = [&is_modified](const std::string &name) { + if (!is_modified) + return name; + return name + Preset::suffix_modified(); + }; + std::optional selected_style_index; + std::string tooltip = ""; + ImGuiWrapper::push_combo_style(m_parent.get_scale()); + if (ImGui::QDTBeginCombo("##style_selector", add_text_modify(trunc_name).c_str())) { + m_style_manager.init_style_images(m_gui_cfg->max_style_image_size, m_text); + m_style_manager.init_trunc_names(max_style_name_width); + std::optional> swap_indexes; + const StyleManager::Styles & styles = m_style_manager.get_styles(); + for (const StyleManager::Style &style : styles) { + size_t index = &style - &styles.front(); + const std::string &actual_style_name = style.name; + ImGui::PushID(actual_style_name.c_str()); + bool is_selected = (index == m_style_manager.get_style_index()); + + float select_height = static_cast(m_gui_cfg->max_style_image_size.y()); + ImVec2 select_size(0.f, select_height); // 0,0 --> calculate in draw + const std::optional &img = style.image; + // allow click delete button + ImGuiSelectableFlags_ flags = ImGuiSelectableFlags_AllowItemOverlap; + if (ImGui::QDTSelectable(style.truncated_name.c_str(), is_selected, flags, select_size)) { + selected_style_index = index; + }/* else if (ImGui::IsItemHovered()) + tooltip = actual_style_name;*/ + + // reorder items + if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) { + if (ImGui::GetMouseDragDelta(0).y < 0.f) { + if (index > 0) swap_indexes = {index, index - 1}; + } else if ((index + 1) < styles.size()) + swap_indexes = {index, index + 1}; + if (swap_indexes.has_value()) ImGui::ResetMouseDragDelta(); + } + + // draw style name + if (img.has_value()) { + ImGui::SameLine(max_style_name_width); + ImVec4 tint_color = ImGui::GetStyleColorVec4(ImGuiCol_Text); + ImGui::Image(img->texture_id, img->tex_size, img->uv0, img->uv1, tint_color); + } + + ImGui::PopID(); + } + if (swap_indexes.has_value()) + m_style_manager.swap(swap_indexes->first, swap_indexes->second); + ImGui::EndCombo(); + } else { + // do not keep in memory style images when no combo box open + m_style_manager.free_style_images(); + if (ImGui::IsItemHovered()) { + std::string style_name = add_text_modify(current_style.name); + tooltip = is_modified ? GUI::format(_L("Modified style \"%1%\""), current_style.name) : GUI::format(_L("Current style is \"%1%\""), current_style.name); + } + } + ImGuiWrapper::pop_combo_style(); + if (!tooltip.empty()) + m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width); + + // Check whether user wants lose actual style modification + if (selected_style_index.has_value() && is_modified) { + const std::string &style_name = m_style_manager.get_styles()[*selected_style_index].name; + wxString message = GUI::format_wxstr(_L("Changing style to \"%1%\" will discard current style modification.\n\nWould you like to continue anyway?"), style_name); + MessageDialog not_loaded_style_message(nullptr, message, _L("Warning"), wxICON_WARNING | wxYES | wxNO); + if (not_loaded_style_message.ShowModal() != wxID_YES) + selected_style_index.reset(); + } + + // selected style from combo box + if (selected_style_index.has_value()) { + const StyleManager::Style &style = m_style_manager.get_styles()[*selected_style_index]; + // create copy to be able do fix transformation only when successfully load style + StyleManager::Style cur_s = current_style; // copy + StyleManager::Style new_s = style; // copy + if (m_style_manager.load_style(*selected_style_index)) { + m_bold = m_style_manager.get_font_prop().boldness > 0;//for update_italic + m_italic = m_style_manager.get_font_prop().skew > 0;//for update_boldness + process(true);//, fix_transformation(cur_s, new_s, m_parent)//todo + } else { + wxString title = _L("Not valid style."); + wxString message = GUI::format_wxstr(_L("Style \"%1%\" can't be used and will be removed from a list."), style.name); + MessageDialog not_loaded_style_message(nullptr, message, title, wxOK); + not_loaded_style_message.ShowModal(); + m_style_manager.erase(*selected_style_index); + } + } + + /*ImGui::SameLine(); + draw_style_rename_button();*/ + + ImGui::SameLine(); + draw_style_save_button(is_modified); + + ImGui::SameLine(); + draw_style_add_button(is_modified); + + // delete button + ImGui::SameLine(); + draw_delete_style_button(); +} + +void GLGizmoText::draw_style_save_button(bool is_modified) +{ + if (draw_button(m_icons, IconType::save, !is_modified)) { + // save styles to app config + m_style_manager.store_styles_to_app_config(); + } else if (ImGui::IsItemHovered()) { + std::string tooltip; + if (!m_style_manager.exist_stored_style()) { + tooltip = _u8L("First Add style to list."); + } else if (is_modified) { + tooltip = GUI::format(_L("Save %1% style"), m_style_manager.get_style().name); + } + if (!tooltip.empty()) { + m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width); + } + } +} + +bool draw_text_clickable(const IconManager::VIcons &icons, IconType type) +{ + return clickable(get_icon(icons, type, IconState::activable), get_icon(icons, type, IconState::hovered)); +} + +bool reset_text_button(const IconManager::VIcons &icons,int pos =-1) +{ + ImGui::SameLine(pos == -1 ? ImGui::GetStyle().WindowPadding.x : pos); + // from GLGizmoCut + // std::string label_id = "neco"; + // std::string btn_label; + // btn_label += ImGui::RevertButton; + // return ImGui::Button((btn_label + "##" + label_id).c_str()); + return draw_text_clickable(icons, IconType::undo); +} + +void GLGizmoText::draw_style_save_as_popup() +{ + ImGuiWrapper::text_colored(ImGuiWrapper::COL_WINDOW_BG_DARK, _u8L("New name of style") + ": "); + //use name inside of volume configuration as temporary new name + + std::string& new_name = m_style_new_name; // text_volume->get_text_configuration()->style.name;//QDS modify + bool is_unique = m_style_manager.is_unique_style_name(new_name); + bool allow_change = false; + if (new_name.empty()) { + ImGuiWrapper::text_colored(ImGuiWrapper::COL_WINDOW_BG_DARK, _u8L("Name can't be empty.")); + } else if (!is_unique) { + ImGuiWrapper::text_colored(ImGuiWrapper::COL_WINDOW_BG_DARK, _u8L("Name has to be unique.")); + } else { + allow_change = true; + } + + bool save_style = false; + ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue; + if (ImGui::InputText("##save as style", &new_name, flags)) + save_style = true; + if (m_imgui->button(_L("OK"), ImVec2(0.f, 0.f), allow_change)) + save_style = true; + + ImGui::SameLine(); + if (ImGui::Button(_u8L("Cancel").c_str())) { + // write original name to volume TextConfiguration + //new_name = m_style_manager.get_style().name; + ImGui::CloseCurrentPopup(); + } + + if (save_style && allow_change) { + m_style_manager.add_style(new_name); + m_style_manager.store_styles_to_app_config(); + ImGui::CloseCurrentPopup(); + } +} + +void GLGizmoText::draw_style_add_button(bool is_modified) +{ + bool only_add_style = !m_style_manager.exist_stored_style(); + bool can_add = true; + //auto text_volume = m_last_text_mv; // m_volume + if (only_add_style)//&& text_volume->get_text_configuration().has_value() && text_volume->get_text_configuration()->style.type != WxFontUtils::get_current_type() + can_add = false; + + std::string title = _u8L("Save as new style"); + const char *popup_id = title.c_str(); + // save as new style + ImGui::SameLine(); + if (draw_button(m_icons, IconType::add, !can_add)) { + if (!m_style_manager.exist_stored_style()) { + m_style_manager.store_styles_to_app_config(wxGetApp().app_config); + } else { + if (is_modified) { + MessageDialog msg(wxGetApp().plater(), _L("The current style has been modified but not saved. Do you want to save it?"), _L("Save current style"), + wxICON_WARNING | wxOK | wxCANCEL); + auto result = msg.ShowModal(); + if (result == wxID_OK) { + m_style_manager.store_styles_to_app_config(); + } + } + StyleNameEditDialog dlg(wxGetApp().plater(), m_style_manager, wxID_ANY, _L("Add new style")); + //m_is_adding_new_style = 5; // about 100 ms,for delay to avoid deselect_all(); + auto result = dlg.ShowModal(); + if (result == wxID_YES) { + wxString style_name = dlg.get_name(); + m_style_manager.add_style(style_name.utf8_string()); + m_style_manager.store_styles_to_app_config(); + } + } + } else if (ImGui::IsItemHovered()) { + if (!can_add) { + m_imgui->tooltip(_u8L("Only valid font can be added to style"), m_gui_cfg->max_tooltip_width); + } else if (only_add_style) { + m_imgui->tooltip(_u8L("Add style to my list"), m_gui_cfg->max_tooltip_width); + } else { + m_imgui->tooltip(_u8L("Add new style"), m_gui_cfg->max_tooltip_width); + } + } +} + +void GLGizmoText::draw_delete_style_button() +{ + bool is_stored = m_style_manager.exist_stored_style(); + bool is_last = m_style_manager.get_styles().size() == 1; + bool can_delete = is_stored && !is_last; + if (draw_button(m_icons, IconType::erase, !can_delete)) { + std::string style_name = m_style_manager.get_style().name; // copy + wxString dialog_title = _L("Remove style"); + size_t next_style_index = std::numeric_limits::max(); + Plater * plater = wxGetApp().plater(); + bool exist_change = false; + while (true) { + // NOTE: can't use previous loaded activ index -> erase could change index + size_t active_index = m_style_manager.get_style_index(); + next_style_index = (active_index > 0) ? active_index - 1 : active_index + 1; + + if (next_style_index >= m_style_manager.get_styles().size()) { + MessageDialog msg(plater, _L("Can't remove the last existing style."), dialog_title, wxICON_ERROR | wxOK); + msg.ShowModal(); + break; + } + + // IMPROVE: add function can_load? + // clean unactivable styles + if (!m_style_manager.load_style(next_style_index)) { + m_style_manager.erase(next_style_index); + exist_change = true; + continue; + } + + wxString message = GUI::format_wxstr(_L("Are you sure you want to permanently remove the \"%1%\" style?"), style_name); + MessageDialog msg(plater, message, dialog_title, wxICON_WARNING | wxYES | wxNO); + if (msg.ShowModal() == wxID_YES) { + // delete style + m_style_manager.erase(active_index); + exist_change = true; + process(); + } else { + // load back style + m_style_manager.load_style(active_index); + } + break; + } + if (exist_change) m_style_manager.store_styles_to_app_config(wxGetApp().app_config); + } + + if (ImGui::IsItemHovered()) { + const std::string &style_name = m_style_manager.get_style().name; + std::string tooltip; + if (can_delete) + tooltip = GUI::format(_L("Delete \"%1%\" style."), style_name); + else if (is_last) + tooltip = GUI::format(_L("Can't delete \"%1%\". It is last style."), style_name); + else /*if(!is_stored)*/ + tooltip = GUI::format(_L("Can't delete temporary style \"%1%\"."), style_name); + m_imgui->tooltip(tooltip, m_gui_cfg->max_tooltip_width); + } +} + +void GLGizmoText::update_boldness() +{ + std::optional &boldness = m_style_manager.get_font_prop().boldness; + if (m_bold) { + set_default_boldness(boldness); + } else { + boldness = 0.0f; + } +} + +void GLGizmoText::update_italic() +{ + std::optional &skew = m_style_manager.get_font_prop().skew; + if (m_italic) { + skew = 0.2f; + } else { + skew = 0.0f; + } +} + +void GLGizmoText::set_default_boldness(std::optional &boldness) +{ + const FontFile & ff = *m_style_manager.get_font_file_with_cache().font_file; + const FontProp & fp = m_style_manager.get_font_prop(); + const FontFile::Info &font_info = get_font_info(ff, fp); + boldness = font_info.ascent / 4.f; +} + +void GLGizmoText::draw_model_type(int caption_width) +{ + ImGui::AlignTextToFramePadding(); + auto text_volume = m_last_text_mv; // m_volume + bool is_last_solid_part = text_volume->is_the_only_one_part(); + std::string title = _u8L("Operation"); + if (is_last_solid_part) { + ImVec4 color{.5f, .5f, .5f, 1.f}; + m_imgui->text_colored(color, title.c_str()); + } else { + ImGui::Text("%s", title.c_str()); + } + + std::optional new_type; + ModelVolumeType modifier = ModelVolumeType::PARAMETER_MODIFIER; + ModelVolumeType negative = ModelVolumeType::NEGATIVE_VOLUME; + ModelVolumeType part = ModelVolumeType::MODEL_PART; + ModelVolumeType type = text_volume->type(); + ImGui::SameLine(caption_width); + // TRN EmbossOperation + ImGuiWrapper::push_radio_style(); + if (ImGui::RadioButton(_u8L("Part").c_str(), type == part)) + new_type = part; + else if (ImGui::IsItemHovered()) + m_imgui->tooltip(_L("Click to change text into object part."), m_gui_cfg->max_tooltip_width); + ImGui::SameLine(); + + auto last_solid_part_hint = _L("You can't change a type of the last solid part of the object."); + if (ImGui::RadioButton(_CTX_utf8(L_CONTEXT("Cut", "EmbossOperation"), "EmbossOperation").c_str(), type == negative)) + new_type = negative; + else if (ImGui::IsItemHovered()) { + if (is_last_solid_part) + m_imgui->tooltip(last_solid_part_hint, m_gui_cfg->max_tooltip_width); + else if (type != negative) + m_imgui->tooltip(_L("Click to change part type into negative volume."), m_gui_cfg->max_tooltip_width); + } + + // In simple mode are not modifiers + if (wxGetApp().plater()->printer_technology() != ptSLA) { + ImGui::SameLine(); + if (ImGui::RadioButton(_u8L("Modifier").c_str(), type == modifier)) + new_type = modifier; + else if (ImGui::IsItemHovered()) { + if (is_last_solid_part) + m_imgui->tooltip(last_solid_part_hint, m_gui_cfg->max_tooltip_width); + else if (type != modifier) + m_imgui->tooltip(_L("Click to change part type into modifier."), m_gui_cfg->max_tooltip_width); + } + } + ImGuiWrapper::pop_radio_style(); + + if (text_volume != nullptr && new_type.has_value() && !is_last_solid_part) { + GUI_App & app = wxGetApp(); + Plater * plater = app.plater(); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Change Text Type", UndoRedo::SnapshotType::GizmoAction); + + text_volume->set_type(*new_type); + + bool is_volume_move_inside = (type == part); + bool is_volume_move_outside = (*new_type == part); + // Update volume position when switch (from part) or (into part) + if ((is_volume_move_inside || is_volume_move_outside)) process(); + + // inspiration in ObjectList::change_part_type() + // how to view correct side panel with objects + ObjectList * obj_list = app.obj_list(); + wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(obj_list->get_selected_obj_idx(), + [volume = text_volume](const ModelVolume *vol) { return vol == volume; }); + if (!sel.IsEmpty()) obj_list->select_item(sel.front()); + + // NOTE: on linux, function reorder_volumes_and_get_selection call GLCanvas3D::reload_scene(refresh_immediately = false) + // which discard m_volume pointer and set it to nullptr also selection is cleared so gizmo is automaticaly closed + auto &mng = m_parent.get_gizmos_manager(); + if (mng.get_current_type() != GLGizmosManager::Text) { + mng.open_gizmo(GLGizmosManager::Text);//Operation like NEGATIVE_VOLUME + } + } +} + +void GLGizmoText::draw_surround_type(int caption_width) +{ + if ((!m_last_text_mv) ||m_last_text_mv->is_the_only_one_part()) { + return; + } + auto label_width = caption_width; + float cur_cap = m_imgui->calc_text_size(_L("Surround projection by char")).x; + auto item_width = cur_cap * 1.2 + ImGui::GetStyle().FramePadding.x * 18.0f; + ImGui::AlignTextToFramePadding(); + size_t selection_idx = int(m_surface_type); + std::vector modes = {_u8L("Not surround") , _u8L("Surround surface"), _u8L("Surround") + "+" + _u8L("Horizonal")}; + if (m_rr.mesh_id < 0) { + modes.erase(modes.begin() + 2); + modes.erase(modes.begin() + 1); + m_surface_type = TextInfo::TextType ::HORIZONAL; + selection_idx = int(m_surface_type); + } + else { + modes.push_back(_u8L("Surround projection by char")); + } + bool is_changed = false; + + ImGuiWrapper::push_combo_style(m_parent.get_scale()); + if (render_combo(_u8L("Mode"), modes, selection_idx, label_width, item_width)) { + switch_text_type((TextInfo::TextType) selection_idx); + } + ImGuiWrapper::pop_combo_style(); +} + +void GLGizmoText::update_style_angle(ModelVolume *text_volume, float init_angle_degree, float roate_angle) +{ + double angle_rad = Geometry::deg2rad(roate_angle); + Geometry::to_range_pi_pi(angle_rad); + + if (text_volume) { + double diff_angle = angle_rad - Geometry::deg2rad(init_angle_degree); + + do_local_z_rotate(m_parent.get_selection(), diff_angle); + + const Selection &selection = m_parent.get_selection(); + const GLVolume * gl_volume = get_selected_gl_volume(selection); + // m_text_tran_in_object.set_from_transform(gl_volume->get_volume_transformation().get_matrix()); + // m_need_update_text = true; + // calc angle after rotation + m_style_manager.get_style().angle = calc_angle(m_parent.get_selection()); + } else { + m_style_manager.get_style().angle = angle_rad; + } +} + +void GLGizmoText::draw_rotation(int caption_size, int slider_width, int drag_left_width, int slider_icon_width) +{ + auto text_volume = m_last_text_mv; + if (!text_volume) { + return; + } + ImGui::AlignTextToFramePadding(); + m_imgui->text(_L("Angle")); + // Reset button + bool is_reseted = false; + if (abs(m_rotate_angle) > 0.01) { + if (reset_text_button(m_icons, m_gui_cfg->input_offset - m_gui_cfg->icon_width) && text_volume) { + do_local_z_rotate(m_parent.get_selection(), Geometry::deg2rad(-m_rotate_angle)); + m_rotate_angle = 0; + // recalculate for surface cut + /*if (m_volume->emboss_shape->projection.use_surface) + process_job();*/ + is_reseted = true; + } else if (ImGui::IsItemHovered()) { + m_imgui->tooltip(_L("Reset rotation"), m_gui_cfg->max_tooltip_width); + } + } + ImGui::SameLine(caption_size); + ImGui::PushItemWidth(slider_width); + + float angle_degree = get_angle_from_current_style(); + m_rotate_angle = angle_degree; + if (m_imgui->qdt_slider_float_style("##angle", &m_rotate_angle, -180.f, 180.f, "%.2f", 1.0f, true ,_L("Rotate the text counterclockwise."))) { + update_style_angle(text_volume, angle_degree, m_rotate_angle); + } + ImGui::SameLine(drag_left_width); + ImGui::PushItemWidth(1.5 * slider_icon_width); + bool set_rotate_angle_flag = false; + if (ImGui::QDTDragFloat("##angle_input", &m_rotate_angle, 0.05f, -180.f, 180.f, "%.2f")) { + set_rotate_angle_flag = true; + update_style_angle(text_volume, angle_degree, m_rotate_angle); + } + + bool is_stop_sliding = m_imgui->get_last_slider_status().deactivated_after_edit; + if (text_volume) { // Apply rotation on model (backend) + if (is_stop_sliding || is_reseted || set_rotate_angle_flag) { + m_need_update_tran = true; + m_parent.do_rotate(""); + const Selection &selection = m_parent.get_selection(); + const GLVolume * gl_volume = get_selected_gl_volume(selection); + m_text_tran_in_object.set_from_transform(gl_volume->get_volume_transformation().get_matrix()); // on_stop_dragging//rotate//set m_text_tran_in_object + volume_transformation_changed(); + } + } + + // Keep up - lock button icon + /*if (!text_volume->is_the_only_one_part()) { + ImGui::SameLine(m_gui_cfg->lock_offset); + const IconManager::Icon &icon = get_icon(m_icons, m_keep_up ? IconType::lock : IconType::unlock, IconState::activable); + const IconManager::Icon &icon_hover = get_icon(m_icons, m_keep_up ? IconType::lock : IconType::unlock, IconState::hovered); + if (button(icon, icon_hover, icon)) m_keep_up = !m_keep_up; + if (ImGui::IsItemHovered()) { + m_imgui->tooltip(_L("Lock/unlock rotation angle when dragging above the surface."), m_gui_cfg->max_tooltip_width); + } + }*/ +} + +std::unique_ptr GLGizmoText::create_emboss_data_base( + const std::string &text, Emboss::StyleManager &style_manager, const Selection &selection, ModelVolumeType type, std::shared_ptr> &cancel) +{ + // create volume_name + std::string volume_name = text; // copy + // contain_enter? + if (volume_name.find('\n') != std::string::npos) + // change enters to space + std::replace(volume_name.begin(), volume_name.end(), '\n', ' '); + + if (!style_manager.is_active_font()) { + style_manager.load_valid_style(); + assert(style_manager.is_active_font()); + if (!style_manager.is_active_font()) return {}; // no active font in style, should never happend !!! + } + + StyleManager::Style &style = style_manager.get_style(); // copy + // actualize font path - during changes in gui it could be corrupted + // volume must store valid path + assert(style_manager.get_wx_font().IsOk()); + assert(style.path.compare(WxFontUtils::store_wxFont(style_manager.get_wx_font())) == 0); + + bool is_outside = (type == ModelVolumeType::MODEL_PART); + + // Cancel previous Job, when it is in process + // worker.cancel(); --> Use less in this case I want cancel only previous EmbossJob no other jobs + // Cancel only EmbossUpdateJob no others + if (cancel != nullptr) + cancel->store(true); + // create new shared ptr to cancel new job + cancel = std::make_shared>(false); + + DataBase base(volume_name, cancel); + style.projection.depth = m_thickness; // QDS add + style.projection.embeded_depth = m_embeded_depth; // QDS add + base.is_outside = is_outside; + // base.text_lines = text_lines.get_lines(); + base.from_surface = style.distance; + + FontFileWithCache &font = style_manager.get_font_file_with_cache(); + TextConfiguration tc{static_cast(style), text}; + auto td_ptr = std::make_unique(std::move(base), font, std::move(tc), style.projection); + return td_ptr; +} + +bool GLGizmoText::process(bool make_snapshot, std::optional volume_transformation, bool update_text) +{ + auto text_volume = m_last_text_mv;//m_volume + //if (text_volume == nullptr) // m_volume + // return false; + // without text there is nothing to emboss + if (is_text_empty(m_text)) + return false; + // exist loaded font file? + if (!m_style_manager.is_active_font()) + return false; + update_boldness(); + update_italic(); + if (update_text) { + m_need_update_text = true; + } + //if (!start_update_volume(std::move(data), *m_volume, selection, m_raycast_manager)) + // return false; + // notification is removed befor object is changed by job + //remove_notification_not_valid_font(); + return true; +} + +ModelVolume *GLGizmoText::get_text_is_dragging() +{ + auto mv = get_selected_model_volume(m_parent); + if (mv && mv->is_text() && get_is_dragging()) { + return mv; + } + return nullptr; +} + +bool GLGizmoText::get_is_dragging() { + return m_dragging; +} + +bool GLGizmoText::get_selection_is_text() +{ + auto mv = get_selected_model_volume(m_parent); + if (mv && mv->is_text()) { + return true; + } + return false; +} + void GLGizmoText::generate_text_tran_in_world(const Vec3d &text_normal_in_world, const Vec3d &text_position_in_world,float rotate_degree, Geometry::Transformation &cur_tran) { - Vec3d temp_normal = text_normal_in_world; - Vec3d cut_plane_in_world = Vec3d::UnitY(); - double epson = 1e-6; - if (!(abs(temp_normal.x()) <= epson && abs(temp_normal.y()) <= epson && abs(temp_normal.z()) > epson)) { // temp_normal != Vec3d::UnitZ() - Vec3d v_plane = temp_normal.cross(Vec3d::UnitZ()); - cut_plane_in_world = v_plane.cross(temp_normal); - } + Vec3d temp_normal = text_normal_in_world.normalized(); + Vec3d cut_plane_in_world = Slic3r::Emboss::suggest_up(text_normal_in_world, UP_LIMIT); + Vec3d z_dir = text_normal_in_world; Vec3d y_dir = cut_plane_in_world; Vec3d x_dir_world = y_dir.cross(z_dir); - if (m_text_type == TextType::SURFACE_HORIZONAL && text_normal_in_world != Vec3d::UnitZ()) { + if (m_surface_type == TextInfo::TextType::SURFACE_HORIZONAL && text_normal_in_world != Vec3d::UnitZ()) { y_dir = Vec3d::UnitZ(); x_dir_world = y_dir.cross(z_dir); z_dir = x_dir_world.cross(y_dir); @@ -502,96 +1419,389 @@ void GLGizmoText::generate_text_tran_in_world(const Vec3d &text_normal_in_world, cur_tran.set_matrix(temp_tran.get_matrix() * rotate_trans.get_matrix()); } +bool GLGizmoText::on_shortcut_key() { + reset_text_info(); + Selection &selection = m_parent.get_selection(); + m_text = "Text"; + m_is_direct_create_text = selection.is_empty(); + auto mv = get_selected_model_volume(m_parent); + if (mv && mv->is_text()) {//not need to generate text,to edit text + Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Edit existed text"); + return false; + } + if (process(false, std::nullopt, false)) { + CreateTextInput temp_input_info; + DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, selection, ModelVolumeType::MODEL_PART, m_job_cancel); + temp_input_info.base = std::move(base); + temp_input_info.text_info = get_text_info(); + if (m_is_direct_create_text) { + auto job = std::make_unique(std::move(temp_input_info)); + auto &worker = wxGetApp().plater()->get_ui_job_worker(); + queue_job(worker, std::move(job)); + } else { + int object_idx = selection.get_object_idx(); + Size s = m_parent.get_canvas_size(); + Vec2d screen_center(s.get_width() / 2., s.get_height() / 2.); + const ModelObjectPtrs & objects = selection.get_model()->objects; + m_object_idx = object_idx; + Vec2d coor; + const Camera &camera = wxGetApp().plater()->get_camera(); + auto finde_gl_volume = find_glvoloume_render_screen_cs(selection, screen_center, camera, objects, &coor); + if (finde_gl_volume != nullptr && object_idx >= 0) { + int temp_object_idx; + auto mo = selection.get_selected_single_object(temp_object_idx); + update_trafo_matrices(); + m_c->update(get_requirements()); + if (m_trafo_matrices.size() > 0 && update_raycast_cache(coor, camera, m_trafo_matrices,false) && m_rr.mesh_id >= 0) { + auto hit_pos = m_trafo_matrices[m_rr.mesh_id] * m_rr.hit.cast(); + Geometry::Transformation tran(m_trafo_matrices[m_rr.mesh_id]); + auto hit_normal = (tran.get_matrix_no_offset() * m_rr.normal.cast()).normalized(); + Transform3d surface_trmat = create_transformation_onto_surface(hit_pos, hit_normal, UP_LIMIT); + mv = mo->volumes[m_rr.mesh_id]; + if (mv) { + auto instance = mo->instances[m_parent.get_selection().get_instance_idx()]; + Transform3d transform = instance->get_matrix().inverse() * surface_trmat; + + m_text_tran_in_object.set_from_transform(transform); + m_text_position_in_world = hit_pos; + m_text_normal_in_world = hit_normal.cast(); + m_need_update_text = true; + m_volume_idx = -1; + if (generate_text_volume()) { // first on surface + return true; + } + } + } else { + ModelObject * mo = objects[object_idx]; + BoundingBoxf3 instance_bb; + size_t instance_index = selection.get_instance_idx(); + instance_bb = mo->instance_bounding_box(instance_index); + // Vec3d volume_size = volume->mesh().bounding_box().size(); + // Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed. + Vec3d offset_tr(0, -instance_bb.size().y() / 2.f - 2.f, -instance_bb.size().z() / 2.f); // lay on bed + auto mo_tran = mo->instances[instance_index]->get_transformation(); + + m_text_tran_in_object.reset(); + m_text_tran_in_object.set_offset(offset_tr); + m_text_position_in_world = mo_tran.get_matrix() * offset_tr; + m_text_normal_in_world = Vec3f::UnitZ(); + m_need_update_text = true; + m_volume_idx = -1; + m_surface_type = TextInfo::TextType ::HORIZONAL; + if (generate_text_volume()) { // first on surface + return true; + } + } + } + m_is_direct_create_text = true; + auto job = std::make_unique(std::move(temp_input_info)); + auto &worker = wxGetApp().plater()->get_ui_job_worker(); + queue_job(worker, std::move(job)); + } + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "check error"; + } + return true; +} + +bool GLGizmoText::is_only_text_case() const { + return m_last_text_mv && m_last_text_mv->is_the_only_one_part(); +} + +void GLGizmoText::close() +{ + auto &mng = m_parent.get_gizmos_manager(); + if (mng.get_current_type() == GLGizmosManager::Text) + mng.open_gizmo(GLGizmosManager::Text); +} + +std::string GLGizmoText::get_icon_filename(bool b_dark_mode) const +{ + return b_dark_mode ? "toolbar_text_dark.svg" : "toolbar_text.svg"; +} + void GLGizmoText::use_fix_normal_position() { m_text_normal_in_world = m_fix_text_normal_in_world; m_text_position_in_world = m_fix_text_position_in_world; } -void GLGizmoText::load_init_text() +void GLGizmoText::load_init_text(bool first_open_text) { Plater *plater = wxGetApp().plater(); - if (m_parent.get_selection().is_single_volume() || m_parent.get_selection().is_single_modifier()) { - ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(m_object_idx, m_volume_idx); + Selection &selection = m_parent.get_selection(); + + if (selection.is_single_full_instance() || selection.is_single_full_object()) { + const GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); + int object_idx = gl_volume->object_idx(); + if (get_selection_is_text()) { + m_object_idx = object_idx; + m_volume_idx = gl_volume->volume_idx(); + } else { + if (object_idx != m_object_idx || (object_idx == m_object_idx && m_volume_idx != -1)) { + m_object_idx = object_idx; + m_volume_idx = -1; + reset_text_info(); + } + } + } else if (selection.is_single_volume_or_modifier()) { + int object_idx, volume_idx; + ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(object_idx, volume_idx); + if ((object_idx != m_object_idx || (object_idx == m_object_idx && volume_idx != m_volume_idx)) && model_volume) { + m_volume_idx = volume_idx; + m_object_idx = object_idx; + } + } + + if (selection.is_single_volume_or_modifier() || selection.is_single_full_object()) { + auto model_volume = get_selected_model_volume(m_parent); if (model_volume) { TextInfo text_info = model_volume->get_text_info(); - if (!text_info.m_text.empty()) { - if (m_last_text_mv == model_volume) { - m_last_text_mv = model_volume; + if (model_volume->is_text()) { + if (m_last_text_mv == model_volume && !m_is_serializing) { return; } - if (plater) { + m_last_text_mv = model_volume; + m_is_direct_create_text = is_only_text_case(); + if (!m_is_serializing && plater && first_open_text && !is_old_text_info(model_volume->get_text_info())) { plater->take_snapshot("enter Text"); } auto box = model_volume->get_mesh_shared_ptr()->bounding_box(); + auto box_size = box.size(); auto valid_z = text_info.m_embeded_depth + text_info.m_thickness; - auto text_height = get_text_height(text_info.m_text); - m_really_use_surface_calc = true; - int index = -1; - for (size_t i = 0; i < 3; i++) { - if (abs(box.size()[i] - valid_z) < 0.1) { - m_really_use_surface_calc = false; - index = i; - break; - } - } - if (abs(box.size()[1] - text_height) > 0.1) { - m_fix_old_tran_flag = true; - } - m_last_text_mv = model_volume; load_from_text_info(text_info); - m_text_volume_tran = model_volume->get_matrix(); - m_text_tran_in_object.set_matrix(m_text_volume_tran); + + auto text_volume_tran = model_volume->get_matrix(); + m_text_tran_in_object.set_matrix(text_volume_tran); // load text int temp_object_idx; - auto mo = m_parent.get_selection().get_selected_single_object(temp_object_idx); - const ModelInstance *mi = mo->instances[m_parent.get_selection().get_instance_idx()]; - m_object_cs_to_world_tran = mi->get_transformation().get_matrix(); - auto world_tran = m_object_cs_to_world_tran * m_text_volume_tran; + auto mo = m_parent.get_selection().get_selected_single_object(temp_object_idx); + const ModelInstance *mi = mo->instances[m_parent.get_selection().get_instance_idx()]; + m_model_object_in_world_tran = mi->get_transformation(); + auto world_tran = m_model_object_in_world_tran.get_matrix() * text_volume_tran; m_text_tran_in_world.set_matrix(world_tran); m_text_position_in_world = m_text_tran_in_world.get_offset(); m_text_normal_in_world = m_text_tran_in_world.get_matrix().linear().col(2).cast(); - { - TriangleMesh text_attach_mesh(mo->volumes[m_rr.mesh_id]->mesh()); - text_attach_mesh.transform(mo->volumes[m_rr.mesh_id]->get_matrix()); - MeshRaycaster temp_ray_caster(text_attach_mesh); - Vec3f local_center = m_text_tran_in_object.get_offset().cast();//(m_text_tran_in_object.get_matrix() * box.center()).cast(); // - Vec3f temp_normal; - Vec3f closest_pt = temp_ray_caster.get_closest_point(local_center, &temp_normal); - m_fix_text_position_in_world = m_object_cs_to_world_tran * closest_pt.cast(); - m_fix_text_normal_in_world = (mi->get_transformation().get_matrix_no_offset().cast() * temp_normal).normalized(); - int face_id; - Vec3f direction = m_text_tran_in_world.get_matrix().linear().col(2).cast(); - if (index == 2 && abs(box.size()[1] - text_height) < 0.1) { - m_is_version1_9_xoz = true; - m_fix_old_tran_flag = true; + m_cut_plane_dir_in_world = m_text_tran_in_world.get_matrix().linear().col(1); // for horizonal text + {//recovery style + auto temp_angle = calc_angle(selection); + calculate_scale(); + + auto & tc = text_info.text_configuration; + const EmbossStyle & style = tc.style; + std::optional installed_name = get_installed_face_name(style.prop.face_name, *m_face_names); + + wxFont wx_font; + // load wxFont from same OS when font name is installed + if (style.type == WxFontUtils::get_current_type() && installed_name.has_value()) { wx_font = WxFontUtils::load_wxFont(style.path); } + // Flag that is selected same font + bool is_exact_font = true; + // Different OS or try found on same OS + if (!wx_font.IsOk()) { + is_exact_font = false; + // Try create similar wx font by FontFamily + wx_font = WxFontUtils::create_wxFont(style); + if (installed_name.has_value() && !installed_name->empty()) is_exact_font = wx_font.SetFaceName(*installed_name); + // Have to use some wxFont + if (!wx_font.IsOk()) wx_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); } - if (index == 1 && abs(box.size()[2] - text_height) < 0.1) {//for 1.10 version, xoy plane cut,just fix - m_is_version1_10_xoy = true; - direction = m_text_tran_in_world.get_matrix().linear().col(1).cast(); - if (!temp_ray_caster.get_closest_point_and_normal(local_center, direction, &closest_pt, &temp_normal, &face_id)) { - m_show_warning_error_mesh = true; + + const auto & styles = m_style_manager.get_styles(); + auto has_same_name = [&name = style.name](const StyleManager::Style &style_item) { return style_item.name == name; }; + StyleManager::Style style_{style}; // copy + style_.projection.depth = m_thickness; + style_.projection.embeded_depth = m_embeded_depth; + style_.prop.char_gap = m_text_gap; + style_.prop.size_in_mm = m_font_size; + if (temp_angle.has_value()) { style_.angle = temp_angle; } + if (auto it = std::find_if(styles.begin(), styles.end(), has_same_name); it == styles.end()) { + // style was not found + m_style_manager.load_style(style_, wx_font); + if (m_style_manager.get_styles().size() >= 2) { + auto default_style_index = 1; // + m_style_manager.load_style(default_style_index); } - } - else if (!temp_ray_caster.get_closest_point_and_normal(local_center, -direction, &closest_pt, &temp_normal, &face_id)) { - if (!temp_ray_caster.get_closest_point_and_normal(local_center, direction, &closest_pt, &temp_normal, &face_id)) { - m_show_warning_error_mesh = true; + } else { + // style name is in styles list + size_t style_index = it - styles.begin(); + if (!m_style_manager.load_style(style_index)) { + // can`t load stored style + m_style_manager.erase(style_index); + m_style_manager.load_style(style_, wx_font); + } else { + // stored style is loaded, now set modification of style + m_style_manager.get_style() = style_; + m_style_manager.set_wx_font(wx_font); } } } - // m_rr.mesh_id - m_need_update_text = false; - m_is_modify = true; + if (m_is_serializing) { // undo redo + m_style_manager.get_style().angle = calc_angle(selection); + m_rotate_angle = get_angle_from_current_style(); + m_rr.normal =Vec3f::Zero(); + update_text_tran_in_model_object(true); + return; + } + float old_text_height =0; + int old_index = -1; + if (is_old_text_info(text_info)) { + try { + old_text_height = get_text_height(text_info.m_text); // old text + } catch (const std::exception &) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " error:get_text_height"; + } + if (is_only_text_case()) { + m_really_use_surface_calc = false; + } else { + m_really_use_surface_calc = true; + } + for (size_t i = 0; i < 3; i++) { + if (abs(box_size[i] - valid_z) < 0.1) { + m_really_use_surface_calc = false; + old_index = i; + break; + } + } + if (abs(box.size()[1] - old_text_height) > 0.1) { + m_fix_old_tran_flag = true; + } + } + if (first_open_text && !is_only_text_case()) { + auto valid_mesh_id = 0; + Vec3f closest_normal; + Vec3f closest_pt; + float min_dist = 1e6; + Vec3f local_center = m_text_tran_in_object.get_offset().cast(); //(m_text_tran_in_object.get_matrix() * box.center()).cast(); + for (int i = 0; i < mo->volumes.size(); i++) { + auto mv = mo->volumes[i]; + if (mv == model_volume || !filter_model_volume(mv)) { + continue; + } + TriangleMesh text_attach_mesh(mv->mesh()); + text_attach_mesh.transform(mv->get_matrix()); + MeshRaycaster temp_ray_caster(text_attach_mesh); + Vec3f temp_normal; + Vec3f temp_closest_pt = temp_ray_caster.get_closest_point(local_center, &temp_normal); + auto dist = (temp_closest_pt - local_center).norm(); + if (min_dist > dist) { + min_dist = dist; + closest_pt = temp_closest_pt; + valid_mesh_id = i; + closest_normal = temp_normal; + } + } + if (min_dist < 1.0f) { + if (m_rr.mesh_id != valid_mesh_id) { + m_rr.mesh_id = valid_mesh_id; + } + if (m_trafo_matrices.empty()) { + update_trafo_matrices(); + } + auto mv = mo->volumes[m_rr.mesh_id]; + TriangleMesh text_attach_mesh(mv->mesh()); + text_attach_mesh.transform(mv->get_matrix()); + MeshRaycaster temp_ray_caster(text_attach_mesh); + + m_fix_text_position_in_world = m_model_object_in_world_tran.get_matrix() * closest_pt.cast(); + m_fix_text_normal_in_world = (mi->get_transformation().get_matrix_no_offset().cast() * closest_normal).normalized(); + if (is_old_text_info(text_info)) { + int face_id; + Vec3f direction = m_text_tran_in_world.get_matrix().linear().col(2).cast(); + if (old_index == 2 && abs(box_size[1] - old_text_height) < 0.1) { + m_is_version1_9_xoz = true; + m_fix_old_tran_flag = true; + } else if (old_index == 2 && abs(box_size[0] - old_text_height) < 0.1) { + m_is_version1_8_yoz = true; + m_fix_old_tran_flag = true; + } else if (old_index == 1 && abs(box_size[2] - old_text_height) < 0.1) { // for 1.10 version, xoy plane cut,just fix + m_is_version1_10_xoy = true; + m_fix_old_tran_flag = true; + direction = m_text_tran_in_world.get_matrix().linear().col(1).cast(); + if (!temp_ray_caster.get_closest_point_and_normal(local_center, direction, &closest_pt, &closest_normal, &face_id)) { + m_show_warning_error_mesh = true; + } + } else if (!temp_ray_caster.get_closest_point_and_normal(local_center, -direction, &closest_pt, &closest_normal, &face_id)) { + if (!temp_ray_caster.get_closest_point_and_normal(local_center, direction, &closest_pt, &closest_normal, &face_id)) { + m_show_warning_error_mesh = true; + } + } + } + } else { + m_surface_type = TextInfo::TextType::HORIZONAL; + } + } + if (!m_font_name.empty()) {//font version 1.10 and before + m_need_update_text = false; + } + return; } } } + if (!m_is_serializing && m_last_text_mv == nullptr) { + close(); + } } void GLGizmoText::data_changed(bool is_serializing) { - load_init_text(); + m_is_serializing = is_serializing; + load_init_text(false); + m_is_serializing = false; + if (is_only_text_case()) { + m_parent.get_gizmos_manager().set_object_located_outside_plate(true); + } else { + m_parent.get_gizmos_manager().check_object_located_outside_plate(); + } + + if (wxGetApp().plater()->is_show_text_cs()) { + m_lines_mark.reset(); + } +} + +void GLGizmoText::on_set_hover_id() +{ + m_rotate_gizmo.set_hover_id(m_hover_id); +} + +void GLGizmoText::on_enable_grabber(unsigned int id) { + m_rotate_gizmo.enable_grabber(0); +} + +void GLGizmoText::on_disable_grabber(unsigned int id) { + m_rotate_gizmo.disable_grabber(0); +} + +bool GLGizmoText::on_mouse(const wxMouseEvent &mouse_event) +{ + if (m_last_text_mv == nullptr) + return false; + if (m_hover_id != m_move_cube_id) { + if (on_mouse_for_rotation(mouse_event)) + return true; + } + return false; +} + +bool GLGizmoText::on_mouse_for_rotation(const wxMouseEvent &mouse_event) +{ + if (mouse_event.Moving()) + return false; + + bool used = use_grabbers(mouse_event); + if (!m_dragging) + return used; + + if (mouse_event.Dragging()){//m_angle means current angle + std::optional &angle_opt = m_style_manager.get_style().angle; + dragging_rotate_gizmo(m_rotate_gizmo.get_angle(), angle_opt, m_rotate_start_angle, m_parent.get_selection()); + } + + return used; } CommonGizmosDataID GLGizmoText::on_get_requirements() const { + if (m_is_direct_create_text) { + return CommonGizmosDataID(0); + } return CommonGizmosDataID( int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::InstancesHider) @@ -610,102 +1820,63 @@ std::string GLGizmoText::on_get_name() const bool GLGizmoText::on_is_activable() const { - // This is assumed in GLCanvas3D::do_rotate, do not change this - // without updating that function too. - if (m_parent.get_selection().is_single_full_instance()) - return true; - - int obejct_idx, volume_idx; - ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx); - if (model_volume) - return !model_volume->get_text_info().m_text.empty(); - - return false; + const Selection &selection = m_parent.get_selection(); + if (selection.is_wipe_tower() || selection.is_any_connector()) + return false; + return true; } void GLGizmoText::on_render() { - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glEnable(GL_DEPTH_TEST)); - - std::string text = std::string(m_text); - if (text.empty()) { - delete_temp_preview_text_volume(); - return; - } - + if (m_text.empty()) { return; } + if (m_object_idx < 0) { return; } + Plater *plater = wxGetApp().plater(); + if (!plater) return; ModelObject *mo = nullptr; const Selection &selection = m_parent.get_selection(); - mo = selection.get_model()->objects[m_object_idx]; + const auto p_model = selection.get_model(); + if (p_model) { + if (m_object_idx < p_model->objects.size()) { + mo = p_model->objects[m_object_idx]; + } + } if (mo == nullptr) { BOOST_LOG_TRIVIAL(info) << boost::format("Text: selected object is null"); return; } - - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera &camera = plater->get_camera(); const auto& projection_matrix = camera.get_projection_matrix(); const auto& view_matrix = camera.get_view_matrix(); // First check that the mouse pointer is on an object. const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - Plater *plater = wxGetApp().plater(); - if (!plater) - return; -#ifdef DEBUG_TEXT - if (m_text_normal_in_world.norm() > 0.1) { // debug - Geometry::Transformation tran(m_text_volume_tran); - if (tran.get_offset().norm() > 1) { - auto text_volume_tran_world = mi->get_transformation().get_matrix() * m_text_volume_tran; - render_cross_mark(text_volume_tran_world, Vec3f::Zero()); + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glEnable(GL_DEPTH_TEST)); + if (plater->is_show_text_cs()) { + if (m_text_normal_in_world.norm() > 0.1) { // debug + Geometry::Transformation tran(m_text_tran_in_object.get_matrix()); + if (tran.get_offset().norm() > 1) { + auto text_volume_tran_world = mi->get_transformation().get_matrix() * tran.get_matrix(); + render_cross_mark(text_volume_tran_world, Vec3f::Zero(),true); + } + render_lines(GenerateTextJob::debug_cut_points_in_world); } - - render_cross_mark(m_text_tran_in_world, Vec3f::Zero()); - - glsafe(::glLineWidth(2.0f)); - ::glBegin(GL_LINES); - glsafe(::glColor3f(1.0f, 0.0f, 0.0f)); - - for (size_t i = 1; i < m_cut_points_in_world.size(); i++) {//draw points - auto target0 = m_cut_points_in_world[i - 1].cast(); - auto target1 = m_cut_points_in_world[i].cast(); - glsafe(::glVertex3f(target0(0), target0(1), target0(2))); - glsafe(::glVertex3f(target1(0), target1(1), target1(2))); - } - glsafe(::glEnd()); } -#endif - if (!m_is_modify || m_shift_down) {//for temp text - // Precalculate transformations of individual meshes. - std::vector trafo_matrices; - for (const ModelVolume *mv : mo->volumes) { - if (mv->is_model_part()) - trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); + if (m_last_text_mv) { + if (is_only_text_case()) {//drag in parent + if ((m_text_position_in_world - mi->get_transformation().get_offset()).norm() > 0.01) { + m_text_position_in_world = mi->get_transformation().get_offset(); + m_need_update_tran = true; + update_text_tran_in_model_object(false); + } } - // Raycast and return if there's no hit. - Vec2d mouse_pos; - if (m_shift_down) { - if (m_is_modify) - mouse_pos = m_rr.mouse_position; - else - mouse_pos = m_origin_mouse_position; + if (m_draging_cube) { + } else { + m_rotate_gizmo.set_custom_tran(m_text_tran_in_world.get_matrix()); + m_rotate_gizmo.render(); } - else { - mouse_pos = m_parent.get_local_mouse_position(); - } - - bool position_changed = update_raycast_cache(mouse_pos, camera, trafo_matrices); - - if (m_rr.mesh_id == -1) { - delete_temp_preview_text_volume(); - return; - } - - if (!position_changed && !m_need_update_text && !m_shift_down) - return; - update_text_pos_normal(); } - - if (m_is_modify) { + if (!is_only_text_case()) { update_text_pos_normal(); Geometry::Transformation tran;//= m_text_tran_in_world; { @@ -730,61 +1901,90 @@ void GLGizmoText::on_render() render_glmodel(m_move_grabber.get_cube(), render_color, view_matrix * cube_mat, projection_matrix); } - delete_temp_preview_text_volume(); - - if (m_is_modify && !m_need_update_text) - return; - - generate_text_volume(); - plater->update(); + if (m_need_update_text) { + if (generate_text_volume()) { + } + } } void GLGizmoText::on_render_for_picking() { glsafe(::glDisable(GL_DEPTH_TEST)); - const auto& shader = wxGetApp().get_shader("flat"); - if (shader == nullptr) - return; - wxGetApp().bind_shader(shader); - int obejct_idx, volume_idx; - ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx); - if (model_volume && !model_volume->get_text_info().m_text.empty()) { - const Selection &selection = m_parent.get_selection(); - auto mo = selection.get_model()->objects[m_object_idx]; - if (mo == nullptr) - return; - auto color = picking_color_component(m_move_cube_id); - m_move_grabber.color[0] = color[0]; - m_move_grabber.color[1] = color[1]; - m_move_grabber.color[2] = color[2]; - m_move_grabber.color[3] = color[3]; - m_move_grabber.render_for_picking(); + if (!m_draging_cube) { + m_rotate_gizmo.render_for_picking(); + } + if (!is_only_text_case()) { + const auto &shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) return; + wxGetApp().bind_shader(shader); + int obejct_idx, volume_idx; + ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx); + if (model_volume && !model_volume->get_text_info().m_text.empty()) { + const Selection &selection = m_parent.get_selection(); + auto mo = selection.get_model()->objects[m_object_idx]; + if (mo == nullptr) return; + auto color = picking_color_component(m_move_cube_id); + m_move_grabber.color[0] = color[0]; + m_move_grabber.color[1] = color[1]; + m_move_grabber.color[2] = color[2]; + m_move_grabber.color[3] = color[3]; + m_move_grabber.render_for_picking(); + } + wxGetApp().unbind_shader(); } - wxGetApp().unbind_shader(); } void GLGizmoText::on_start_dragging() { + if (m_hover_id < 0) { return; } + update_trafo_matrices(); + + if (m_hover_id == m_move_cube_id) { + m_draging_cube = true; + } else { + m_rotate_gizmo.start_dragging(); + } } void GLGizmoText::on_stop_dragging() { + m_draging_cube = false; + m_need_update_tran = true;//dragging + if (m_hover_id == m_move_cube_id) { + m_parent.do_move("");//replace by wxGetApp() .plater()->take_snapshot("Modify Text"); in EmbossJob.cpp + m_need_update_text = true; + } else { + m_rotate_gizmo.stop_dragging(); + // TODO: when start second rotatiton previous rotation rotate draggers + // This is fast fix for second try to rotate + // When fixing, move grabber above text (not on side) + m_rotate_gizmo.set_angle(PI / 2); + + // apply rotation + // TRN This is an item label in the undo-redo stack. + m_parent.do_rotate(""); + + const Selection &selection = m_parent.get_selection(); + const GLVolume * gl_volume = get_selected_gl_volume(selection); + m_text_tran_in_object.set_from_transform(gl_volume->get_volume_transformation().get_matrix());//on_stop_dragging//rotate//set m_text_tran_in_object + m_rotate_start_angle.reset(); + volume_transformation_changed(); + } } void GLGizmoText::on_update(const UpdateData &data) { - Vec2d mouse_pos = Vec2d(data.mouse_pos.x(), data.mouse_pos.y()); - const Selection &selection = m_parent.get_selection(); - auto mo = selection.get_model()->objects[m_object_idx]; - if (mo == nullptr) + if (m_hover_id == 0) { + m_rotate_gizmo.update(data); return; - const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - const Camera & camera = wxGetApp().plater()->get_camera(); - - std::vector trafo_matrices; - for (const ModelVolume *mv : mo->volumes) { - if (mv->is_model_part()) { trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); } } + if (!m_c) { return; } + if (!m_c->raycaster()) { + m_c->update(get_requirements()); + } + if (m_object_idx < 0) { return; } + Vec2d mouse_pos = Vec2d(data.mouse_pos.x(), data.mouse_pos.y()); + const Camera & camera = wxGetApp().plater()->get_camera(); Vec3f normal = Vec3f::Zero(); Vec3f hit = Vec3f::Zero(); @@ -793,19 +1993,16 @@ void GLGizmoText::on_update(const UpdateData &data) Vec3f closest_normal = Vec3f::Zero(); double closest_hit_squared_distance = std::numeric_limits::max(); int closest_hit_mesh_id = -1; - + auto & trafo_matrices = m_trafo_matrices; // Cast a ray on all meshes, pick the closest hit and save it for the respective mesh + const Selection &selection = m_parent.get_selection(); + auto mo = selection.get_model()->objects[m_object_idx]; for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) { - if (mesh_id == m_volume_idx) + if (!filter_model_volume(mo->volumes[mesh_id])) { continue; - - MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh()); - - if (mesh_raycaster.unproject_on_mesh(mouse_pos, trafo_matrices[mesh_id], camera, hit, normal, m_c->object_clipper()->get_clipping_plane(), - &facet)) { - // In case this hit is clipped, skip it. - if (is_mesh_point_clipped(hit.cast(), trafo_matrices[mesh_id])) continue; - + } + if (mesh_id < m_c->raycaster()->raycasters().size() && m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(mouse_pos, trafo_matrices[mesh_id], camera, hit, normal, + m_c->object_clipper()->get_clipping_plane(),&facet)) { // Is this hit the closest to the camera so far? double hit_squared_distance = (camera.get_position() - trafo_matrices[mesh_id] * hit.cast()).squaredNorm(); if (hit_squared_distance < closest_hit_squared_distance) { @@ -817,23 +2014,40 @@ void GLGizmoText::on_update(const UpdateData &data) } } - if (closest_hit == Vec3f::Zero() && closest_normal == Vec3f::Zero()) return; + if (closest_hit == Vec3f::Zero() && closest_normal == Vec3f::Zero()) { + m_parent.set_as_dirty(); + return; + } if (closest_hit_mesh_id != -1) { + bool is_last_attach = m_rr.mesh_id >= 0; m_rr = {mouse_pos, closest_hit_mesh_id, closest_hit, closest_normal};//on drag - m_need_fix = false; close_warning_flag_after_close_or_drag(); - m_need_update_text = true; + if (is_last_attach) { // surface drag + std::optional fix; + auto cur_world = m_model_object_in_world_tran.get_matrix() * m_text_tran_in_object.get_matrix(); + if (has_reflection(cur_world)) { + update_text_tran_in_model_object(true); + cur_world = m_model_object_in_world_tran.get_matrix() * m_text_tran_in_object.get_matrix(); + } + auto result = get_drag_volume_transformation(cur_world, m_text_normal_in_world.cast(), m_text_position_in_world, fix, + m_model_object_in_world_tran.get_matrix().inverse(), Geometry::deg2rad(m_rotate_angle)); + m_text_tran_in_object.set_from_transform(result); + auto gl_v = get_selected_gl_volume(m_parent); + gl_v->set_volume_transformation(m_text_tran_in_object.get_matrix()); + } else { + update_text_pos_normal(); + } } } -//B + void GLGizmoText::push_button_style(bool pressed) { if (m_is_dark_mode) { if (pressed) { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f)); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(68.f/ 255.f, 121 / 255.f, 251 / 255.f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 174 / 255.f, 66 / 255.f, 1.f)); } else { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(45.f / 255.f, 45.f / 255.f, 49.f / 255.f, 1.f)); @@ -847,7 +2061,7 @@ void GLGizmoText::push_button_style(bool pressed) { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f)); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(68.f /255.f, 121 / 255.f, 251 / 255.f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 174 / 255.f, 66 / 255.f, 1.f)); } else { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.f, 1.f, 1.f, 1.f)); @@ -868,11 +2082,10 @@ void GLGizmoText::push_combo_style(const float scale) { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale); ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG_DARK); - // y96 - ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.27f, 0.47f, 0.98f, 1.00f)); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.27f, 0.47f, 0.98f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG_DARK); ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f }); } @@ -880,11 +2093,10 @@ void GLGizmoText::push_combo_style(const float scale) { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale); ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG); - // y96 - ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.27f, 0.47f, 0.98f, 1.00f)); // y96 change color - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.27f, 0.47f, 0.98f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG); ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f }); } @@ -899,45 +2111,8 @@ void GLGizmoText::pop_combo_style() // QDS void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) { - if (!m_init_texture) { - update_font_texture(); - m_init_texture = true; - } - - if (m_imgui->get_font_size() != m_scale) { - m_scale = m_imgui->get_font_size(); - update_font_texture(); - } - if (m_textures.size() == 0) { - BOOST_LOG_TRIVIAL(info) << "GLGizmoText has no texture"; - return; - } - - const Selection &selection = m_parent.get_selection(); - if (selection.is_single_full_instance() || selection.is_single_full_object()) { - const GLVolume * gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); - int object_idx = gl_volume->object_idx(); - if (object_idx != m_object_idx || (object_idx == m_object_idx && m_volume_idx != -1)) { - m_object_idx = object_idx; - m_volume_idx = -1; - reset_text_info(); - } - } else if (selection.is_single_volume() || selection.is_single_modifier()) { - int object_idx, volume_idx; - ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(object_idx, volume_idx); - if ((object_idx != m_object_idx || (object_idx == m_object_idx && volume_idx != m_volume_idx)) - && model_volume) { - m_last_text_mv = model_volume; - TextInfo text_info = model_volume->get_text_info(); - load_from_text_info(text_info);//mouse click down - m_is_modify = true; - m_volume_idx = volume_idx; - m_object_idx = object_idx; - } - } - const float win_h = ImGui::GetWindowHeight(); - y = std::min(y, bottom_limit - win_h); + y = std::min(y, bottom_limit - win_h); GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f); static float last_y = 0.0f; @@ -945,44 +2120,84 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) const float currt_scale = m_parent.get_scale(); ImGuiWrapper::push_toolbar_style(currt_scale); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0,5.0) * currt_scale); + double screen_scale = wxDisplay(wxGetApp().plater()).GetScaleFactor(); + // Configuration creation + if (m_gui_cfg == nullptr || // Exist configuration - first run + m_gui_cfg->screen_scale != screen_scale || // change of DPI + m_gui_cfg->dark_mode != m_is_dark_mode // change of dark mode + ) { + // Create cache for gui offsets + auto cfg = Text::create_gui_configuration(); + cfg.screen_scale = screen_scale; + cfg.dark_mode = m_is_dark_mode; + + GuiCfg gui_cfg{std::move(cfg)}; + m_gui_cfg = std::make_unique(std::move(gui_cfg)); + + // change resolution regenerate icons + m_icons = init_text_icons(m_icon_manager, *m_gui_cfg); // init_icons();//todo + m_style_manager.clear_imgui_font(); + } + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0, 5.0) * currt_scale); ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 4.0f * currt_scale); GizmoImguiBegin("Text", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); -#ifdef DEBUG_TEXT - std::string world_hit = "world hit x:" + formatFloat(m_text_position_in_world[0]) + " y:" + formatFloat(m_text_position_in_world[1]) + - " z:" + formatFloat(m_text_position_in_world[2]); - std::string hit = "local hit x:" + formatFloat(m_rr.hit[0]) + " y:" + formatFloat(m_rr.hit[1]) + " z:" + formatFloat(m_rr.hit[2]); - std::string normal = "normal x:" + formatFloat(m_rr.normal[0]) + " y:" + formatFloat(m_rr.normal[1]) + " z:" + formatFloat(m_rr.normal[2]); - auto cut_dir = "cut_dir x:" + formatFloat(m_cut_plane_dir_in_world[0]) + " y:" + formatFloat(m_cut_plane_dir_in_world[1]) + " z:" + formatFloat(m_cut_plane_dir_in_world[2]); - auto fix_position_str = "fix position:" + formatFloat(m_fix_text_position_in_world[0]) + " y:" + formatFloat(m_fix_text_position_in_world[1]) + - " z:" + formatFloat(m_fix_text_position_in_world[2]); - auto fix_normal_str = "fix normal:" + formatFloat(m_fix_text_normal_in_world[0]) + " y:" + formatFloat(m_fix_text_normal_in_world[1]) + - " z:" + formatFloat(m_fix_text_normal_in_world[2]); - m_imgui->text(world_hit); - m_imgui->text(hit); - m_imgui->text(normal); - m_imgui->text(cut_dir); - m_imgui->text(fix_position_str); - m_imgui->text(fix_normal_str); +#if QDT_RELEASE_TO_PUBLIC == 0 + if (wxGetApp().plater()->is_show_text_cs()) { + std::string world_hit = "world hit x:" + formatFloat(m_text_position_in_world[0]) + " y:" + formatFloat(m_text_position_in_world[1]) +" z:" + formatFloat(m_text_position_in_world[2]); + std::string hit = "local hit x:" + formatFloat(m_rr.hit[0]) + " y:" + formatFloat(m_rr.hit[1]) + " z:" + formatFloat(m_rr.hit[2]); + std::string normal = "normal x:" + formatFloat(m_rr.normal[0]) + " y:" + formatFloat(m_rr.normal[1]) + " z:" + formatFloat(m_rr.normal[2]); + auto cut_dir = "cut_dir x:" + formatFloat(m_cut_plane_dir_in_world[0]) + " y:" + formatFloat(m_cut_plane_dir_in_world[1]) + + " z:" + formatFloat(m_cut_plane_dir_in_world[2]); + auto fix_position_str = "fix position:" + formatFloat(m_fix_text_position_in_world[0]) + " y:" + formatFloat(m_fix_text_position_in_world[1]) + + " z:" + formatFloat(m_fix_text_position_in_world[2]); + auto fix_normal_str = "fix normal:" + formatFloat(m_fix_text_normal_in_world[0]) + " y:" + formatFloat(m_fix_text_normal_in_world[1]) + + " z:" + formatFloat(m_fix_text_normal_in_world[2]); + m_imgui->text(world_hit); + if (!is_only_text_case()) { + m_imgui->text(hit); + m_imgui->text(normal); + } + m_imgui->text(cut_dir); + m_imgui->text(fix_position_str); + m_imgui->text(fix_normal_str); + m_imgui->text("calc tpye:" + std::to_string(m_show_calc_meshtod)); + if (m_normal_points.size() > 0) { + auto normal = m_normal_points[0]; + auto normal_str = "text normal:" + formatFloat(normal[0]) + " y:" + formatFloat(normal[1]) + " z:" + formatFloat(normal[2]); + m_imgui->text(normal_str); + } + auto tran_x_dir = m_text_tran_in_object.get_matrix().linear().col(0); + auto tran_y_dir = m_text_tran_in_object.get_matrix().linear().col(1); + auto tran_z_dir = m_text_tran_in_object.get_matrix().linear().col(2); + auto tran_pos = m_text_tran_in_object.get_matrix().linear().col(3); + auto tran_x_dir_str = "text tran_x_dir:" + formatFloat(tran_x_dir[0]) + " y:" + formatFloat(tran_x_dir[1]) + " z:" + formatFloat(tran_x_dir[2]); + m_imgui->text(tran_x_dir_str); + auto tran_y_dir_str = "text tran_y_dir:" + formatFloat(tran_y_dir[0]) + " y:" + formatFloat(tran_y_dir[1]) + " z:" + formatFloat(tran_y_dir[2]); + m_imgui->text(tran_y_dir_str); + auto tran_z_dir_str = "text tran_z_dir:" + formatFloat(tran_z_dir[0]) + " y:" + formatFloat(tran_z_dir[1]) + " z:" + formatFloat(tran_z_dir[2]); + m_imgui->text(tran_z_dir_str); + auto tran_pos_str = "text pos in_object:" + formatFloat(tran_pos[0]) + " y:" + formatFloat(tran_pos[1]) + " z:" + formatFloat(tran_pos[2]); + m_imgui->text(tran_pos_str); + } #endif - float space_size = m_imgui->get_style_scaling() * 8; - float font_cap = m_imgui->calc_text_size(_L("Font")).x; - float size_cap = m_imgui->calc_text_size(_L("Size")).x; + float space_size = m_imgui->get_style_scaling() * 8; + float font_cap = m_imgui->calc_text_size(_L("Font")).x; + float size_cap = m_imgui->calc_text_size(_L("Size")).x; float thickness_cap = m_imgui->calc_text_size(_L("Thickness")).x; - float input_cap = m_imgui->calc_text_size(_L("Input text")).x; - float depth_cap = m_imgui->calc_text_size(_L("Embeded")).x; - float caption_size = std::max(std::max(font_cap, size_cap), std::max(depth_cap, input_cap)) + space_size + ImGui::GetStyle().WindowPadding.x; + float input_cap = m_imgui->calc_text_size(_L("Input text")).x; + float caption_size = std::max(std::max(font_cap, size_cap), input_cap) + space_size + ImGui::GetStyle().WindowPadding.x; float input_text_size = m_imgui->scaled(10.0f); - float button_size = ImGui::GetFrameHeight(); + float button_size = ImGui::GetFrameHeight(); ImVec2 selectable_size(std::max((input_text_size + ImGui::GetFrameHeight() * 2), m_combo_width + SELECTABLE_INNER_OFFSET * currt_scale), m_combo_height); - float list_width = selectable_size.x + ImGui::GetStyle().ScrollbarSize + 2 * currt_scale; + float list_width = selectable_size.x + ImGui::GetStyle().ScrollbarSize + 2 * currt_scale; float input_size = list_width - button_size * 2 - ImGui::GetStyle().ItemSpacing.x * 4; - ImTextureID normal_B = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_B); - ImTextureID normal_T = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_T); + ImTextureID normal_B = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_B); + ImTextureID normal_T = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_T); ImTextureID normal_B_dark = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_B_DARK); ImTextureID normal_T_dark = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TEXT_T_DARK); @@ -990,77 +2205,49 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) if (last_h != win_h || last_y != y) { // ask canvas for another frame to render the window in the correct position m_imgui->set_requires_extra_frame(); - if (last_h != win_h) - last_h = win_h; - if (last_y != y) - last_y = y; + if (last_h != win_h) last_h = win_h; + if (last_y != y) last_y = y; } + if (m_gui_cfg && (int) m_gui_cfg->input_offset != (int) caption_size) { m_gui_cfg->input_offset = caption_size; } + ImGui::AlignTextToFramePadding(); + m_imgui->text(_L("Input text")); + ImGui::SameLine(caption_size); + ImGui::PushItemWidth(2 * m_gui_cfg->input_width); + draw_text_input(caption_size); ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Font")); ImGui::SameLine(caption_size); - ImGui::PushItemWidth(list_width); - push_combo_style(currt_scale); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * currt_scale); + ImGui::PushItemWidth(2 * m_gui_cfg->input_width); + draw_font_list(); - std::vector filtered_items_idx; - bool is_filtered = false; - if (m_imgui->qdt_combo_with_filter("##Combo_Font", m_font_names[m_curr_font_idx], m_font_names, &filtered_items_idx, &is_filtered, selectable_size.y)) { - int show_items_count = is_filtered ? filtered_items_idx.size() : m_textures.size(); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(SELECTABLE_INNER_OFFSET, 0)* currt_scale); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0); - for (int i = 0; i < show_items_count; i++) - { - int idx = is_filtered ? filtered_items_idx[i] : i; - const bool is_selected = (idx == m_curr_font_idx); - ImTextureID icon_id = (ImTextureID)(intptr_t)(m_textures[idx].texture->get_id()); - ImVec4 tint_color = ImGui::GetStyleColorVec4(ImGuiCol_Text); - if (ImGui::QDTImageSelectable(icon_id, selectable_size, { (float)m_textures[idx].w, (float)m_textures[idx].h }, m_textures[idx].hl, tint_color, { 0, 0 }, { 1, 1 }, is_selected)) - { - m_curr_font_idx = idx; - m_font_name = m_textures[m_curr_font_idx].font_name; - ImGui::CloseCurrentPopup(); - m_need_update_text = true; - } - if (is_selected) { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::PopStyleVar(3); - ImGui::EndListBox(); - ImGui::EndPopup(); - } - - ImGui::PopStyleVar(2); - pop_combo_style(); - ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Size")); - ImGui::SameLine(caption_size); - ImGui::PushItemWidth(input_size); - if (ImGui::InputFloat("###font_size", &m_font_size, 0.0f, 0.0f, "%.2f")) { - limit_value(m_font_size, m_font_size_min, m_font_size_max); - m_need_update_text = true; - } + draw_height(); ImGui::SameLine(); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * currt_scale); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {1.0f * currt_scale, 1.0f * currt_scale }); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {1.0f * currt_scale, 1.0f * currt_scale}); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 2.0f * currt_scale); push_button_style(m_bold); + bool exist_change = false; if (ImGui::ImageButton(m_is_dark_mode ? normal_B_dark : normal_B, {button_size - 2 * ImGui::GetStyle().FramePadding.x, button_size - 2 * ImGui::GetStyle().FramePadding.y})) { m_bold = !m_bold; - m_need_update_text = true; + // update_boldness(); in process(); + exist_change = true; } pop_button_style(); - ImGui::SameLine(); + auto temp_input_width = m_gui_cfg->input_width - ImGui::GetFrameHeight() * 1.6 * 2; // - space_size + ImGuiWindow *imgui_window = ImGui::GetCurrentWindow(); + auto cur_temp_x = imgui_window->DC.CursorPosPrevLine.x - imgui_window->Pos.x; + ImGui::SameLine(cur_temp_x); + ImGui::PushItemWidth(button_size); push_button_style(m_italic); if (ImGui::ImageButton(m_is_dark_mode ? normal_T_dark : normal_T, {button_size - 2 * ImGui::GetStyle().FramePadding.x, button_size - 2 * ImGui::GetStyle().FramePadding.y})) { m_italic = !m_italic; - m_need_update_text = true; + exist_change = true; + } + if (exist_change) { + m_style_manager.clear_glyphs_cache(); + process(); } pop_button_style(); ImGui::PopStyleVar(3); @@ -1068,12 +2255,34 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) ImGui::AlignTextToFramePadding(); m_imgui->text(_L("Thickness")); ImGui::SameLine(caption_size); - ImGui::PushItemWidth(list_width); + ImGui::PushItemWidth(temp_input_width); // 2 * m_gui_cfg->input_width float old_value = m_thickness; ImGui::InputFloat("###text_thickness", &m_thickness, 0.0f, 0.0f, "%.2f"); m_thickness = ImClamp(m_thickness, m_thickness_min, m_thickness_max); - if (old_value != m_thickness) - m_need_update_text = true; + if (old_value != m_thickness) { + process(); + } + auto full_width = caption_size + 2 * m_gui_cfg->input_width; + if (!is_only_text_case()) { + auto depth_x = caption_size + space_size * 2 + temp_input_width; + ImGui::SameLine(depth_x); + float depth_cap = m_imgui->calc_text_size(_L("Embeded depth")).x; + ImGui::PushItemWidth(depth_cap); + m_imgui->text(_L("Embeded depth")); + + auto depth_input_x = depth_x + depth_cap + space_size * 2; + ImGui::SameLine(depth_input_x); + + auto valid_width = full_width - depth_input_x; + ImGui::PushItemWidth(valid_width); + old_value = m_embeded_depth; + if (ImGui::InputFloat("###text_embeded_depth", &m_embeded_depth, 0.0f, 0.0f, "%.2f")) { + limit_value(m_embeded_depth, 0.0f, m_embeded_depth_max); + } + if (old_value != m_embeded_depth) { + process(); + } + } const float slider_icon_width = m_imgui->get_slider_icon_size().x; const float slider_width = list_width - 1.5 * slider_icon_width - space_size; @@ -1083,45 +2292,38 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) m_imgui->text(_L("Text Gap")); ImGui::SameLine(caption_size); ImGui::PushItemWidth(slider_width); - if (m_imgui->qdt_slider_float_style("##text_gap", &m_text_gap, -100, 100, "%.2f", 1.0f, true)) - m_need_update_text = true; - ImGui::SameLine(drag_left_width); - ImGui::PushItemWidth(1.5 * slider_icon_width); - if (ImGui::QDTDragFloat("##text_gap_input", &m_text_gap, 0.05f, 0.0f, 0.0f, "%.2f")) + if (m_imgui->qdt_slider_float_style("##text_gap", &m_text_gap, -10.f, 100.f, "%.2f", 1.0f, true)) m_need_update_text = true; - ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Angle")); - ImGui::SameLine(caption_size); - ImGui::PushItemWidth(slider_width); - if (m_imgui->qdt_slider_float_style("##angle", &m_rotate_angle, 0, 360, "%.2f", 1.0f, true)) - m_need_update_text = true; ImGui::SameLine(drag_left_width); ImGui::PushItemWidth(1.5 * slider_icon_width); - if (ImGui::QDTDragFloat("##angle_input", &m_rotate_angle, 0.05f, 0.0f, 0.0f, "%.2f")) + if (ImGui::QDTDragFloat("##text_gap_input", &m_text_gap, 0.05f, -10.f, 100.f, "%.2f")) m_need_update_text = true; - ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Embeded\r\ndepth")); - ImGui::SameLine(caption_size); - ImGui::PushItemWidth(list_width); - old_value = m_embeded_depth; - if (ImGui::InputFloat("###text_embeded_depth", &m_embeded_depth, 0.0f, 0.0f, "%.2f")) { - limit_value(m_embeded_depth, 0.0f, m_embeded_depth_max); + draw_rotation(caption_size, slider_width, drag_left_width, slider_icon_width); +#if QDT_RELEASE_TO_PUBLIC + if (GUI::wxGetApp().app_config->get("enable_text_styles") == "true") { + draw_style_list(caption_size); } - if (old_value != m_embeded_depth) - m_need_update_text = true; - - ImGui::AlignTextToFramePadding(); - m_imgui->text(_L("Input text")); - ImGui::SameLine(caption_size); - ImGui::PushItemWidth(list_width); - - if(ImGui::InputText("", m_text, sizeof(m_text))) - m_need_update_text = true; - std::string text = std::string(m_text); - if (text.empty() && m_is_modify) { - m_imgui->warning_text(_L("Warning:Input cannot be empty!")); +#else + draw_style_list(caption_size); +#endif + draw_surround_type(caption_size); + auto text_volume = m_last_text_mv; + if (text_volume && !text_volume->is_the_only_one_part()) { + ImGui::Separator(); + draw_model_type(caption_size); + } + //warnning + std::string text = m_text; + auto cur_world = m_model_object_in_world_tran.get_matrix() * m_text_tran_in_object.get_matrix(); + if (!is_only_text_case() && has_reflection(cur_world)) { + m_imgui->warning_text_wrapped(_L("Warning:There is a mirror in the text matrix, and dragging it will completely regenerate it."), full_width); + m_parent.request_extra_frame(); + } + if (m_warning_font) { + m_imgui->warning_text_wrapped(_L("Warning:Due to font upgrades,previous font may not necessarily be replaced successfully, and recommend you to modify the font."), full_width); + m_parent.request_extra_frame(); } if (m_show_warning_text_create_fail) { m_imgui->warning_text(_L("Warning:create text fail.")); @@ -1132,60 +2334,40 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) if (m_show_text_normal_reset_tip) { m_imgui->warning_text(_L("Warning:text normal has been reset.")); } - if (m_show_warning_regenerated) { - m_imgui->warning_text(_L("Warning:Because current text does indeed use surround algorithm,\nif continue to edit, text has to regenerated according to new location.")); - } + /* if (m_show_warning_regenerated && m_font_version != CUR_FONT_VERSION) { + m_imgui->warning_text_wrapped(_L("Warning:Because current text does indeed use surround algorithm,if continue to edit, text has to regenerated according to new location."), + full_width); + m_parent.request_extra_frame(); + }*/ if (m_show_warning_old_tran) { - m_imgui->warning_text(_L("Warning:old matrix has at least two parameters: mirroring, scaling, and rotation. \nIf you continue editing, it may not be correct. \nPlease dragging text or cancel using current pose, \nsave and reedit again.")); + m_imgui->warning_text_wrapped(_L("Warning:old matrix has at least two parameters: mirroring, scaling, and rotation. If you continue editing, it may not be correct. Please " + "dragging text or cancel using current pose, save and reedit again."), + full_width); + m_parent.request_extra_frame(); } if (m_show_warning_error_mesh) { - m_imgui->warning_text(_L("Error:Detecting an incorrect mesh id or an unknown error, \nregenerating text may result in incorrect outcomes.\nPlease drag text,save it then reedit it again.")); + m_imgui->warning_text_wrapped( + _L("Error:Detecting an incorrect mesh id or an unknown error, regenerating text may result in incorrect outcomes.Please drag text,save it then reedit it again."), + full_width); + m_parent.request_extra_frame(); } if (m_show_warning_lost_rotate) { - m_imgui->warning_text(_L("Warning:Due to functional upgrade, rotation information \ncannot be restored. Please drag or modify text,\n save it and reedit it will ok.")); + m_imgui->warning_text_wrapped( + _L("Warning:Due to functional upgrade, rotation information cannot be restored. Please drag or modify text,save it and reedit it will ok."), + full_width); + m_parent.request_extra_frame(); } - ImGui::Separator(); - if (m_need_fix && m_text_type > TextType::HORIZONAL) { - ImGui::AlignTextToFramePadding(); - ImGui::SameLine(caption_size); - ImGui::PushItemWidth(list_width); - ImGui::AlignTextToFramePadding(); - if (m_imgui->qdt_checkbox(_L("Use opened text pose"), m_use_current_pose)) { - m_need_update_text = true; - } + if (m_last_text_mv && m_rr.mesh_id < 0 && !is_only_text_case()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":"+ _L("Detected that text did not adhere to mesh surface. Please manually drag yellow square to mesh surface that needs to be adhered."), + full_width); + m_parent.request_extra_frame(); } + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(x, get_cur_y); - float f_scale = m_parent.get_gizmos_manager().get_layout_scale(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale)); - - ImGui::SameLine(caption_size); - ImGui::AlignTextToFramePadding(); - auto is_surface_text = m_text_type == TextType::SURFACE || m_text_type == TextType::SURFACE_HORIZONAL; - if (m_imgui->qdt_checkbox(_L("Surface"), is_surface_text)) { - m_need_update_text = true; - } - ImGui::SameLine(); - ImGui::AlignTextToFramePadding(); - auto is_keep_horizontal = m_text_type == TextType::HORIZONAL || m_text_type == TextType::SURFACE_HORIZONAL; - if (m_imgui->qdt_checkbox(_L("Horizontal text"), is_keep_horizontal)) { - m_need_update_text = true; - if (is_surface_text && is_keep_horizontal == false) { - update_text_normal_in_world(); - } - } - check_text_type(is_surface_text, is_keep_horizontal); - - //ImGui::SameLine(); - //ImGui::AlignTextToFramePadding(); - //m_imgui->text(_L("Status:")); - //float status_cap = m_imgui->calc_text_size(_L("Status:")).x + space_size + ImGui::GetStyle().WindowPadding.x; - //ImGui::SameLine(); - //m_imgui->text(m_is_modify ? _L("Modify") : _L("Add")); - - ImGui::PopStyleVar(2); + ImGui::PopStyleVar(1); #if 0 ImGuiIO& io = ImGui::GetIO(); @@ -1203,6 +2385,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoText::show_tooltip_information(float x, float y) { + if (m_desc.empty()) { return; } std::array info_array = std::array{"rotate_text"}; float caption_max = 0.f; for (const auto &t : info_array) { caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x); } @@ -1226,28 +2409,480 @@ void GLGizmoText::show_tooltip_information(float x, float y) m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text); }; - for (const auto &t : info_array) draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t)); + for (const auto &t : info_array) + draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t)); ImGui::EndTooltip(); } ImGui::PopStyleVar(2); } +bool GLGizmoText::set_height() +{ + float &value = m_style_manager.get_font_prop().size_in_mm; + // size can't be zero or negative + apply(value, Text::limits.size_in_mm); + auto text_volume = m_last_text_mv; + if (text_volume == nullptr) { + return false; + } + // only different value need process + //if (is_approx(value, text_volume->get_text_info().m_font_size_in_mm)) // m_volume->text_configuration->style.prop.size_in_mm + // return false; + /* if (m_style_manager.get_font_prop().per_glyph) + reinit_text_lines(m_text_lines.get_lines().size());*///todo + + return true; +} + +void GLGizmoText::draw_text_input(int caption_width) +{ + bool allow_multi_line = false; + bool support_backup_fonts = GUI::wxGetApp().app_config->get_bool("support_backup_fonts"); + auto create_range_text_prep = [&mng = m_style_manager, &text = m_text, &exist_unknown = m_text_contain_unknown_glyph, support_backup_fonts]() { + if (text.empty()) { return std::string(); } + auto &ff = mng.get_font_file_with_cache(); + assert(ff.has_value()); + const auto & cn = mng.get_font_prop().collection_number; + unsigned int font_index = (cn.has_value()) ? *cn : 0; + if (support_backup_fonts) { + std::vector> fonts; + fonts.emplace_back(ff.font_file); + for (int i = 0; i < Slic3r::GUI::BackupFonts::backup_fonts.size(); i++) { + if (Slic3r::GUI::BackupFonts::backup_fonts[i].has_value()) { + fonts.emplace_back(Slic3r::GUI::BackupFonts::backup_fonts[i].font_file); + } + } + return create_range_text(text, fonts, font_index, &exist_unknown); + } else { + return create_range_text(text, *ff.font_file, font_index, &exist_unknown); + } + }; + + double scale = 1.;//m_scale_height.has_value() ? *m_scale_height : + ImFont *imgui_font = m_style_manager.get_imgui_font(); + if (imgui_font == nullptr) { + // try create new imgui font + double screen_scale = wxDisplay(wxGetApp().plater()).GetScaleFactor(); + double imgui_scale = scale * screen_scale; + + m_style_manager.create_imgui_font(create_range_text_prep(), imgui_scale, support_backup_fonts); + imgui_font = m_style_manager.get_imgui_font(); + } + bool exist_font = imgui_font != nullptr && imgui_font->IsLoaded() && imgui_font->Scale > 0.f && imgui_font->ContainerAtlas != nullptr; + // NOTE: Symbol fonts doesn't have atlas + // when their glyph range is out of language character range + if (exist_font){ + ImGui::PushFont(imgui_font); + } + + // show warning about incorrectness view of font + std::string warning_tool_tip; + if (!exist_font) { + warning_tool_tip = _u8L("The text cannot be written using the selected font. Please try choosing a different font."); + } else { + auto append_warning = [&warning_tool_tip](std::string t) { + if (!warning_tool_tip.empty()) + warning_tool_tip += "\n"; + warning_tool_tip += t; + }; + if (is_text_empty(m_text)) {//QDS modify + append_warning(_u8L("Embossed text cannot contain only white spaces.")); + } + if (m_text_contain_unknown_glyph) { + append_warning(_u8L("Unsupported characters automatically switched to fallback font.")); + } + const FontProp &prop = m_style_manager.get_font_prop(); + /* if (prop.skew.has_value())//QDS modify + append_warning(_u8L("Text input doesn't show font skew.")); + if (prop.boldness.has_value()) + append_warning(_u8L("Text input doesn't show font boldness.")); + if (prop.line_gap.has_value()) + append_warning(_u8L("Text input doesn't show gap between lines."));*/ + auto &ff = m_style_manager.get_font_file_with_cache(); + /*float imgui_size = StyleManager::get_imgui_font_size(prop, *ff.font_file, scale); + if (imgui_size > StyleManager::max_imgui_font_size) + append_warning(_u8L("Too tall, diminished font height inside text input.")); + if (imgui_size < StyleManager::min_imgui_font_size) + append_warning(_u8L("Too small, enlarged font height inside text input."));*/ + bool is_multiline = m_text_lines.get_lines().size() > 1; + if (is_multiline && (prop.align.first == FontProp::HorizontalAlign::center || prop.align.first == FontProp::HorizontalAlign::right)) + append_warning(_u8L("Text doesn't show current horizontal alignment.")); + } + + // flag for extend font ranges if neccessary + // ranges can't be extend during font is activ(pushed) + std::string range_text; + ImVec2 input_size(2 * m_gui_cfg->input_width, m_gui_cfg->text_size.y); // 2 * m_gui_cfg->input_width - caption_width + const ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;// | ImGuiInputTextFlags_AutoSelectAll + if (ImGui::InputTextMultiline("##Text", &m_text, input_size, flags)) { + if (m_style_manager.get_font_prop().per_glyph) { + unsigned count_lines = get_count_lines(m_text); + //if (count_lines != m_text_lines.get_lines().size()) + // // Necesarry to initialize count by given number (differ from stored in volume at the moment) + // reinit_text_lines(count_lines); + } + if (m_last_text_mv ==nullptr) { + m_need_update_tran = false; + } + process(); + range_text = create_range_text_prep(); + } + + if (exist_font) + ImGui::PopFont(); + + // warning tooltip has to be with default font + if (!warning_tool_tip.empty() && ( !allow_multi_line ||(allow_multi_line && ImGui::GetCurrentWindow()->DC.ChildWindows.Data))) { + // Multiline input has hidden window for scrolling + float scrollbar_width, scrollbar_height; + const ImGuiStyle &style = ImGui::GetStyle(); + if (allow_multi_line) { + const ImGuiWindow *input = ImGui::GetCurrentWindow()->DC.ChildWindows.front(); + scrollbar_width = (input->ScrollbarY) ? style.ScrollbarSize : 0.f; + scrollbar_height = (input->ScrollbarX) ? style.ScrollbarSize : 0.f; + } else { + scrollbar_width = 4; + scrollbar_height = 2; + } + if (ImGui::IsItemHovered()) + m_imgui->tooltip(warning_tool_tip, m_gui_cfg->max_tooltip_width); + } + + // NOTE: must be after ImGui::font_pop() + // -> imgui_font has to be unused + // IMPROVE: only extend not clear + // Extend font ranges + if (!range_text.empty() && !ImGuiWrapper::contain_all_glyphs(imgui_font, range_text)) + m_style_manager.clear_imgui_font(); +} + +void GLGizmoText::draw_font_list() +{ + ImGuiWrapper::push_combo_style(m_gui_cfg->screen_scale); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * m_gui_cfg->screen_scale); + + wxString tooltip_name = ""; + + // Set partial + wxString actual_face_name; + if (m_style_manager.is_active_font()) { + const wxFont &wx_font = m_style_manager.get_wx_font(); + if (wx_font.IsOk()){ + actual_face_name = wx_font.GetFaceName(); + m_cur_font_name = actual_face_name; + m_font_name = actual_face_name.utf8_string(); + } + } + // name of actual selected font + const char *selected = (!actual_face_name.empty()) ? (const char *) actual_face_name.c_str() : " --- "; + + // Do not remove font face during enumeration + // When deletation of font appear this variable is set + std::optional del_index; + + ImGui::SetNextItemWidth(2 * m_gui_cfg->input_width); + std::vector filtered_items_idx; + bool is_filtered = false; + ImGuiStyle & style = ImGui::GetStyle(); + float old_scrollbar_size = style.ScrollbarSize; + style.ScrollbarSize = 16.f; + if (m_imgui->qdt_combo_with_filter("##Combo_Font", selected, m_face_names->faces_names, &filtered_items_idx, &is_filtered, m_imgui->scaled(32.f / 15.f))) { + bool set_selection_focus = false; + if (!m_face_names->is_init) { + init_face_names(*m_face_names); + set_selection_focus = true; + } + + if (!m_face_names->has_truncated_names) + init_truncated_names(*m_face_names, m_gui_cfg->input_width); + + if (m_face_names->texture_id == 0) + init_font_name_texture(); + + int show_items_count = is_filtered ? filtered_items_idx.size() : m_face_names->faces.size(); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0); + + for (int i = 0; i < show_items_count; i++) { + int idx = is_filtered ? filtered_items_idx[i] : i; + FaceName & face = m_face_names->faces[idx]; + const wxString &wx_face_name = face.wx_name; + + ImGui::PushID(idx); + ScopeGuard sg([]() { ImGui::PopID(); }); + bool is_selected = (actual_face_name == wx_face_name); + ImVec2 selectable_size(0, m_imgui->scaled(32.f / 15.f)); + ImGuiSelectableFlags flags = 0; + if (ImGui::QDTSelectable(face.name_truncated.c_str(), is_selected, flags, selectable_size)) { + if (!select_facename(wx_face_name,true)) { + del_index = idx; + MessageDialog(wxGetApp().plater(), GUI::format_wxstr(_L("Font \"%1%\" can't be selected."), wx_face_name)); + } else { + ImGui::CloseCurrentPopup(); + } + } + // tooltip as full name of font face + if (ImGui::IsItemHovered()) + tooltip_name = wx_face_name; + + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + + // on first draw set focus on selected font + if (set_selection_focus && is_selected) + ImGui::SetScrollHereY(); + draw_font_preview(face, m_text, *m_face_names, *m_gui_cfg, ImGui::IsItemVisible()); + } + ImGui::PopStyleVar(3); + ImGui::EndListBox(); + ImGui::EndPopup(); + } else if (m_face_names->is_init) { + // Just one after close combo box + // free texture and set id to zero + m_face_names->is_init = false; + // cancel all process for generation of texture + for (FaceName &face : m_face_names->faces) + if (face.cancel != nullptr) + face.cancel->store(true); + glsafe(::glDeleteTextures(1, &m_face_names->texture_id)); + m_face_names->texture_id = 0; + } + style.ScrollbarSize = old_scrollbar_size; + // delete unloadable face name when try to use + if (del_index.has_value()) { + auto face = m_face_names->faces.begin() + (*del_index); + std::vector &bad = m_face_names->bad; + // sorted insert into bad fonts + auto it = std::upper_bound(bad.begin(), bad.end(), face->wx_name); + bad.insert(it, face->wx_name); + m_face_names->faces.erase(face); + m_face_names->faces_names.erase(m_face_names->faces_names.begin() + (*del_index)); + // update cached file + store(*m_face_names); + } + +#ifdef ALLOW_ADD_FONT_BY_FILE + ImGui::SameLine(); + // select font file by file browser + if (draw_button(IconType::open_file)) { + if (choose_true_type_file()) { process(); } + } else if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Add file with font(.ttf, .ttc)"); +#endif // ALLOW_ADD_FONT_BY_FILE + +#ifdef ALLOW_ADD_FONT_BY_OS_SELECTOR + ImGui::SameLine(); + if (draw_button(IconType::system_selector)) { + if (choose_font_by_wxdialog()) { process(); } + } else if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Open dialog for choose from fonts."); +#endif // ALLOW_ADD_FONT_BY_OS_SELECTOR + + ImGui::PopStyleVar(2); + ImGuiWrapper::pop_combo_style(); + + if (!tooltip_name.IsEmpty()) + m_imgui->tooltip(tooltip_name, m_gui_cfg->max_tooltip_width); +} + +void GLGizmoText::draw_height(bool use_inch) +{ + float & value = m_style_manager.get_font_prop().size_in_mm; + const EmbossStyle *stored_style = m_style_manager.get_stored_style(); + const float * stored = (stored_style != nullptr) ? &stored_style->prop.size_in_mm : nullptr; + const char * size_format = use_inch ? "%.2f in" : "%.1f mm"; + const std::string revert_text_size = _u8L("Revert text size."); + const std::string &name = m_gui_cfg->translations.height; + if (rev_input_mm(name, value, stored, revert_text_size, 0.1f, 1.f, size_format, use_inch, m_scale_height)) { + if (set_height()) { + process(); + } + } +} + +//template<> +bool imgui_input(const char *label, float *v, float step, float step_fast, const char *format, ImGuiInputTextFlags flags) +{ + return ImGui::InputFloat(label, v, step, step_fast, format, flags); +} +//template<> +bool imgui_input(const char *label, double *v, double step, double step_fast, const char *format, ImGuiInputTextFlags flags) +{ + return ImGui::InputDouble(label, v, step, step_fast, format, flags); +} + +bool exist_change(const std::optional &value, const std::optional *default_value) +{ + if (default_value == nullptr) return false; + return !is_approx(value, *default_value); +} + +bool exist_change(const float &value, const float *default_value) +{ + if (default_value == nullptr) return false; + return !is_approx(value, *default_value); +} + +template +bool GLGizmoText::revertible(const std::string &name, T &value, const T *default_value, const std::string &undo_tooltip, float undo_offset, Draw draw) const +{ + ImGui::AlignTextToFramePadding(); + bool changed = exist_change(value, default_value); + if (changed || default_value == nullptr) + ImGuiWrapper::text_colored(ImGuiWrapper::COL_QIDI_CHANGE, name); + else + ImGuiWrapper::text(name); + + // render revert changes button + if (changed) { + ImGuiWindow *window = ImGui::GetCurrentWindow(); + float prev_x = window->DC.CursorPosPrevLine.x; + ImGui::SameLine(undo_offset); // change cursor postion + if (draw_button(m_icons, IconType::undo)) { + value = *default_value; + + // !! Fix to detect change of value after revert of float-slider + m_imgui->get_last_slider_status().deactivated_after_edit = true; + + return true; + } else if (ImGui::IsItemHovered()) + m_imgui->tooltip(undo_tooltip, m_gui_cfg->max_tooltip_width); + window->DC.CursorPosPrevLine.x = prev_x; // set back previous position + } + return draw(); +} + +template +bool GLGizmoText::rev_input( + const std::string &name, T &value, const T *default_value, const std::string &undo_tooltip, T step, T step_fast, const char *format, ImGuiInputTextFlags flags) const +{ + // draw offseted input + auto draw_offseted_input = [&offset = m_gui_cfg->input_offset, &width = m_gui_cfg->input_width, &name, &value, &step, &step_fast, format, flags]() { + ImGui::SameLine(offset); + ImGui::SetNextItemWidth(width); + return imgui_input(("##" + name).c_str(), &value, step, step_fast, format, flags); + }; + float undo_offset = m_gui_cfg->input_offset - m_gui_cfg->icon_width; // ImGui::GetStyle().WindowPadding.x;//todo + return revertible(name, value, default_value, undo_tooltip, undo_offset, draw_offseted_input); +} + +template +bool GLGizmoText::rev_input_mm(const std::string & name, + T & value, + const T * default_value_ptr, + const std::string & undo_tooltip, + T step, + T step_fast, + const char * format, + bool use_inch, + const std::optional &scale) const +{ + // _variable which temporary keep value + T value_ = value; + T default_value_; + if (use_inch) { + // calc value in inch + value_ *= GizmoObjectManipulation::mm_to_in; + if (default_value_ptr) { + default_value_ = GizmoObjectManipulation::mm_to_in * (*default_value_ptr); + default_value_ptr = &default_value_; + } + } + if (scale.has_value()) value_ *= *scale; + bool use_correction = use_inch || scale.has_value(); + if (rev_input(name, use_correction ? value_ : value, default_value_ptr, undo_tooltip, step, step_fast, format)) { + if (use_correction) { + value = value_; + if (use_inch) value *= GizmoObjectManipulation::in_to_mm; + if (scale.has_value()) value /= *scale; + } + return true; + } + return false; +} + +void GLGizmoText::draw_depth(bool use_inch) {} + +void GLGizmoText::init_font_name_texture() +{ + Timer t("init_font_name_texture"); + // check if already exists + GLuint &id = m_face_names->texture_id; + if (id != 0) return; + // create texture for font + GLenum target = GL_TEXTURE_2D; + glsafe(::glGenTextures(1, &id)); + glsafe(::glBindTexture(target, id)); + glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + const Vec2i32 & size = m_gui_cfg->face_name_size; + GLint w = size.x(), h = m_face_names->count_cached_textures * size.y(); + std::vector data(4 * w * h, {0}); + const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE; + const GLint level = 0, internal_format = GL_RGBA, border = 0; + glsafe(::glTexImage2D(target, level, internal_format, w, h, border, format, type, data.data())); + + // bind default texture + GLuint no_texture_id = 0; + glsafe(::glBindTexture(target, no_texture_id)); + + // clear info about creation of texture - no one is initialized yet + for (FaceName &face : m_face_names->faces) { + face.cancel = nullptr; + face.is_created = nullptr; + } +} + +void GLGizmoText::reinit_text_lines(unsigned count_lines) { + init_text_lines(m_text_lines, m_parent.get_selection(), m_style_manager, count_lines); +} + +bool GLGizmoText::check(ModelVolumeType volume_type) +{ + return volume_type == ModelVolumeType::MODEL_PART || volume_type == ModelVolumeType::NEGATIVE_VOLUME || volume_type == ModelVolumeType::PARAMETER_MODIFIER; +} + +bool GLGizmoText::init_create(ModelVolumeType volume_type) { // check valid volume type + if (!check(volume_type)) { + BOOST_LOG_TRIVIAL(error) << "Can't create embossed volume with this type: " << (int) volume_type; + return false; + } + if (!is_activable()) { + BOOST_LOG_TRIVIAL(error) << "Can't create text. Gizmo is not activabled."; + return false; + } + // Check can't be inside is_activable() cause crash + // steps to reproduce: start App -> key 't' -> key 'delete' + if (wxGetApp().obj_list()->has_selected_cut_object()) { + BOOST_LOG_TRIVIAL(error) << "Can't create text on cut object"; + return false; + } + m_style_manager.discard_style_changes(); + assert(!m_text_lines.is_init()); + m_text_lines.reset(); // remove not current text lines + // set default text + return true; +} + void GLGizmoText::reset_text_info() { - m_font_name = ""; - m_font_size = 16.f; - m_curr_font_idx = 0; - m_bold = true; - m_italic = false; - m_thickness = 2.f; - strcpy(m_text, m_font_name.c_str()); - m_embeded_depth = 0.f; - m_rotate_angle = 0; - m_text_gap = 0.f; - m_text_type = TextType::SURFACE; + m_object_idx = -1; + m_volume_idx = -1; + m_font_size = m_style_manager.get_font_prop().size_in_mm; + m_bold = m_style_manager.get_font_prop().boldness > 0; + m_italic = m_style_manager.get_font_prop().skew > 0; + m_thickness = m_style_manager.get_style().projection.depth; + m_text = ""; + m_embeded_depth = m_style_manager.get_style().projection.embeded_depth; + m_rotate_angle = get_angle_from_current_style(); + m_text_gap = m_style_manager.get_style().prop.char_gap.value_or(0); + m_surface_type = TextInfo::TextType::SURFACE; m_rr = RaycastResult(); - - m_is_modify = false; + m_last_text_mv = nullptr; } void GLGizmoText::update_text_pos_normal() { @@ -1263,11 +2898,9 @@ void GLGizmoText::update_text_pos_normal() { std::vector w_matrices; std::vector mv_trans; - for (const ModelVolume *mv : mo->volumes) { - if (mv->is_model_part()) { - w_matrices.emplace_back(Geometry::Transformation(mi->get_transformation().get_matrix() * mv->get_matrix())); - mv_trans.emplace_back(Geometry::Transformation(mv->get_matrix())); - } + for (ModelVolume *mv : mo->volumes) { + w_matrices.emplace_back(Geometry::Transformation(mi->get_transformation().get_matrix() * mv->get_matrix())); + mv_trans.emplace_back(Geometry::Transformation(mv->get_matrix())); } #ifdef DEBUG_TEXT_VALUE m_rr.hit = Vec3f(-0.58, -1.70, -12.8); @@ -1277,21 +2910,14 @@ void GLGizmoText::update_text_pos_normal() { m_text_normal_in_world = (w_matrices[m_rr.mesh_id].get_matrix_no_offset().cast() * m_rr.normal).normalized(); } -void GLGizmoText::update_font_status() -{ - std::unique_lock lock(m_mutex); - m_font_status.reserve(m_avail_font_names.size()); - for (std::string font_name : m_avail_font_names) { - if (!can_generate_text_shape(font_name)) { - m_font_status.emplace_back(false); - } - else { - m_font_status.emplace_back(true); - } +bool GLGizmoText::filter_model_volume(ModelVolume *mv) { + if (mv && mv->is_model_part() && !mv->is_text()) { + return true; } + return false; } -float GLGizmoText::get_text_height(const std::string &text) +float GLGizmoText::get_text_height(const std::string &text)//todo { std::wstring_convert> str_cnv; std::wstring ws = boost::nowide::widen(text); @@ -1330,6 +2956,7 @@ void GLGizmoText::close_warning_flag_after_close_or_drag() m_show_warning_lost_rotate = false; m_is_version1_10_xoy = false; m_is_version1_9_xoz = false; + m_is_version1_8_yoz = false; } void GLGizmoText::update_text_normal_in_world() @@ -1338,7 +2965,7 @@ void GLGizmoText::update_text_normal_in_world() auto mo = m_parent.get_selection().get_selected_single_object(temp_object_idx); if (mo && m_rr.mesh_id >= 0) { const ModelInstance *mi = mo->instances[m_parent.get_selection().get_instance_idx()]; - TriangleMesh text_attach_mesh(mo->volumes[m_rr.mesh_id]->mesh()); + TriangleMesh text_attach_mesh(mo->volumes[m_rr.mesh_id]->mesh()); text_attach_mesh.transform(mo->volumes[m_rr.mesh_id]->get_matrix()); MeshRaycaster temp_ray_caster(text_attach_mesh); Vec3f local_center = m_text_tran_in_object.get_offset().cast(); //(m_text_tran_in_object.get_matrix() * box.center()).cast(); // @@ -1351,53 +2978,14 @@ void GLGizmoText::update_text_normal_in_world() } } -bool GLGizmoText::update_text_positions(const std::vector& texts) +bool GLGizmoText::update_text_tran_in_model_object(bool rewrite_text_tran) { - std::vector text_lengths; - for (int i = 0; i < texts.size(); ++i) { - std::string alpha; - if (texts[i] == " ") { - alpha = "i"; - } else { - alpha = texts[i]; - } - TextResult text_result; - load_text_shape(alpha.c_str(), m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, text_result); - double half_x_length = text_result.text_width / 2; - text_lengths.emplace_back(half_x_length); - } - - int text_num = texts.size(); - m_position_points.clear(); - m_normal_points.clear(); - - const Selection &selection = m_parent.get_selection(); - auto mo = selection.get_model()->objects[m_object_idx]; - if (mo == nullptr) - return false; - - const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - m_model_object_in_world_tran = mi->get_transformation(); - // Precalculate transformations of individual meshes. - std::vector trafo_matrices; - std::vector rotate_trafo_matrices; - for (const ModelVolume *mv : mo->volumes) { - if (mv->is_model_part()) { - trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); - rotate_trafo_matrices.emplace_back(mi->get_transformation().get_matrix(true, false, true, true) * mv->get_matrix(true, false, true, true)); - } - } - - if (m_rr.mesh_id == -1) { + if (m_object_idx < 0 && !is_only_text_case()) { BOOST_LOG_TRIVIAL(info) << boost::format("Text: mrr_mesh_id is -1"); return false; } - - // mouse_position_world may is error after user modified - if (m_need_fix) { - if (m_text_normal_in_world.norm() < 0.1) { - m_show_text_normal_reset_tip = true; - } + if (m_text_normal_in_world.norm() < 0.1) { + m_show_text_normal_reset_tip = true; use_fix_normal_position(); } if (m_text_normal_in_world.norm() < 0.1) { @@ -1405,405 +2993,117 @@ bool GLGizmoText::update_text_positions(const std::vector& texts) BOOST_LOG_TRIVIAL(info) << "m_text_normal_in_object is error"; return false; } - m_show_text_normal_error = false; - auto mouse_position_world = m_text_position_in_world.cast(); - auto mouse_normal_world = m_text_normal_in_world.cast(); - - TriangleMesh slice_meshs; - int mesh_index = 0; - int volume_index = 0; - for (int i = 0; i < mo->volumes.size(); ++i) { - // skip the editing text volume - if (m_is_modify && m_volume_idx == i) - continue; - - ModelVolume *mv = mo->volumes[i]; - if (mv->is_model_part()) { - if (mesh_index == m_rr.mesh_id) { - volume_index = i; - } - TriangleMesh vol_mesh(mv->mesh()); - vol_mesh.transform(mv->get_matrix()); - slice_meshs.merge(vol_mesh); - mesh_index++; + m_show_text_normal_error = false; + if (!rewrite_text_tran) { + if (!m_need_update_tran) { + return true; } + m_need_update_tran = false; } - - ModelVolume* volume = mo->volumes[volume_index]; + const Selection &selection = m_parent.get_selection(); + auto mo = selection.get_model()->objects[m_object_idx]; + if (mo == nullptr) + return false; + const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; + m_model_object_in_world_tran = mi->get_transformation(); generate_text_tran_in_world(m_text_normal_in_world.cast(), m_text_position_in_world, m_rotate_angle, m_text_tran_in_world); - + if (m_fix_text_tran.has_value()) { + m_text_tran_in_world = m_text_tran_in_world * (m_fix_text_tran.value()); + } m_cut_plane_dir_in_world = m_text_tran_in_world.get_matrix().linear().col(1); m_text_normal_in_world = m_text_tran_in_world.get_matrix().linear().col(2).cast(); - // generate clip cs at click pos - auto text_position_in_object = mi->get_transformation().get_matrix().inverse() * m_text_position_in_world.cast(); - auto rotate_mat_inv = mi->get_transformation().get_matrix_no_offset().inverse(); - auto text_tran_in_object = mi->get_transformation().get_matrix().inverse() * m_text_tran_in_world.get_matrix(); // Geometry::generate_transform(cs_x_dir, cs_y_dir, cs_z_dir, text_position_in_object); // todo modify by m_text_tran_in_world - m_text_tran_in_object.set_matrix(text_tran_in_object); - m_text_cs_to_world_tran = mi->get_transformation().get_matrix() * m_text_tran_in_object.get_matrix(); - auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {-0.5 * M_PI, 0.0, 0.0}); - if (m_text_type == TextType::HORIZONAL || (m_need_fix && m_use_current_pose)) { - m_position_points.resize(text_num); - m_normal_points.resize(text_num); - - Vec3d pos_dir = m_cut_plane_dir_in_world.cross(mouse_normal_world); - pos_dir.normalize(); - if (text_num % 2 == 1) { - m_position_points[text_num / 2] = mouse_position_world; - for (int i = 0; i < text_num / 2; ++i) { - double left_gap = text_lengths[text_num / 2 - i - 1] + m_text_gap + text_lengths[text_num / 2 - i]; - if (left_gap < 0) - left_gap = 0; - - double right_gap = text_lengths[text_num / 2 + i + 1] + m_text_gap + text_lengths[text_num / 2 + i]; - if (right_gap < 0) - right_gap = 0; - - m_position_points[text_num / 2 - 1 - i] = m_position_points[text_num / 2 - i] - left_gap * pos_dir; - m_position_points[text_num / 2 + 1 + i] = m_position_points[text_num / 2 + i] + right_gap * pos_dir; - } - } else { - for (int i = 0; i < text_num / 2; ++i) { - double left_gap = i == 0 ? (text_lengths[text_num / 2 - i - 1] + m_text_gap / 2) : - (text_lengths[text_num / 2 - i - 1] + m_text_gap + text_lengths[text_num / 2 - i]); - if (left_gap < 0) - left_gap = 0; - - double right_gap = i == 0 ? (text_lengths[text_num / 2 + i] + m_text_gap / 2) : - (text_lengths[text_num / 2 + i] + m_text_gap + text_lengths[text_num / 2 + i - 1]); - if (right_gap < 0) - right_gap = 0; - - if (i == 0) { - m_position_points[text_num / 2 - 1 - i] = mouse_position_world - left_gap * pos_dir; - m_position_points[text_num / 2 + i] = mouse_position_world + right_gap * pos_dir; - continue; - } - - m_position_points[text_num / 2 - 1 - i] = m_position_points[text_num / 2 - i] - left_gap * pos_dir; - m_position_points[text_num / 2 + i] = m_position_points[text_num / 2 + i - 1] + right_gap * pos_dir; - } - } - - for (int i = 0; i < text_num; ++i) { - m_normal_points[i] = mouse_normal_world; - } - - return true; - } - - MeshSlicingParams slicing_params; - auto cut_tran = (m_text_tran_in_object.get_matrix() * rotate_tran); - slicing_params.trafo = cut_tran.inverse(); - // for debug - // its_write_obj(slice_meshs.its, "D:/debug_files/mesh.obj"); - // generate polygons - const Polygons temp_polys = slice_mesh(slice_meshs.its, 0, slicing_params); - Vec3d scale_click_pt(scale_(0), scale_(0), 0); - // for debug - // export_regions_to_svg(Point(scale_pt.x(), scale_pt.y()), temp_polys); - - Polygons polys = union_(temp_polys); - - auto point_in_line_rectange = [](const Line &line, const Point &point, double& distance) { - distance = line.distance_to(point); - return distance < line.length() / 2; - }; - - int index = 0; - double min_distance = 1e12; - Polygon hit_ploy; - for (const Polygon poly : polys) { - if (poly.points.size() == 0) - continue; - - Lines lines = poly.lines(); - for (int i = 0; i < lines.size(); ++i) { - Line line = lines[i]; - double distance = min_distance; - if (point_in_line_rectange(line, Point(scale_click_pt.x(), scale_click_pt.y()), distance)) { - if (distance < min_distance) { - min_distance = distance; - index = i; - hit_ploy = poly; - } - } - } - } - - if (hit_ploy.points.size() == 0) { - BOOST_LOG_TRIVIAL(info) << boost::format("Text: the hit polygon is null"); - return false; - } - - m_cut_points_in_world.clear(); - m_cut_points_in_world.reserve(hit_ploy.points.size()); - for (int i = 0; i < hit_ploy.points.size(); ++i) { - m_cut_points_in_world.emplace_back(m_text_cs_to_world_tran * rotate_tran * Vec3d(unscale_(hit_ploy.points[i].x()), unscale_(hit_ploy.points[i].y()), 0)); - } - - Polygon_3D new_polygon(m_cut_points_in_world); - m_position_points.resize(text_num); - if (text_num % 2 == 1) { - m_position_points[text_num / 2] = Vec3d(mouse_position_world.x(), mouse_position_world.y(), mouse_position_world.z()); - - std::vector lines = new_polygon.get_lines(); - Line_3D line = lines[index]; - { - int index1 = index; - double left_length = (mouse_position_world - line.a).cast().norm(); - int left_num = text_num / 2; - while (left_num > 0) { - double gap_length = (text_lengths[left_num] + m_text_gap + text_lengths[left_num - 1]); - if (gap_length < 0) - gap_length = 0; - - while (gap_length > left_length) { - gap_length -= left_length; - if (index1 == 0) - index1 = lines.size() - 1; - else - --index1; - left_length = lines[index1].length(); - } - - Vec3d direction = lines[index1].vector(); - direction.normalize(); - double distance_to_a = (left_length - gap_length); - Line_3D new_line = lines[index1]; - - double norm_value = direction.cast().norm(); - double deta_x = distance_to_a * direction.x() / norm_value; - double deta_y = distance_to_a * direction.y() / norm_value; - double deta_z = distance_to_a * direction.z() / norm_value; - Vec3d new_pos = new_line.a + Vec3d(deta_x, deta_y, deta_z); - left_num--; - m_position_points[left_num] = new_pos; - left_length = distance_to_a; - } - } - - { - int index2 = index; - double right_length = (line.b - mouse_position_world).cast().norm(); - int right_num = text_num / 2; - while (right_num > 0) { - double gap_length = (text_lengths[text_num - right_num] + m_text_gap + text_lengths[text_num - right_num - 1]); - if (gap_length < 0) - gap_length = 0; - - while (gap_length > right_length) { - gap_length -= right_length; - if (index2 == lines.size() - 1) - index2 = 0; - else - ++index2; - right_length = lines[index2].length(); - } - - Line_3D line2 = lines[index2]; - line2.reverse(); - Vec3d direction = line2.vector(); - direction.normalize(); - double distance_to_b = (right_length - gap_length); - Line_3D new_line = lines[index2]; - - double norm_value = direction.cast().norm(); - double deta_x = distance_to_b * direction.x() / norm_value; - double deta_y = distance_to_b * direction.y() / norm_value; - double deta_z = distance_to_b * direction.z() / norm_value; - Vec3d new_pos = new_line.b + Vec3d(deta_x, deta_y, deta_z); - m_position_points[text_num - right_num] = new_pos; - right_length = distance_to_b; - right_num--; - } - } - } - else { - for (int i = 0; i < text_num / 2; ++i) { - std::vector lines = new_polygon.get_lines(); - Line_3D line = lines[index]; - { - int index1 = index; - double left_length = (mouse_position_world - line.a).cast().norm(); - int left_num = text_num / 2; - for (int i = 0; i < text_num / 2; ++i) { - double gap_length = 0; - if (i == 0) { - gap_length = m_text_gap / 2 + text_lengths[text_num / 2 - 1 - i]; - } - else { - gap_length = text_lengths[text_num / 2 - i] + m_text_gap + text_lengths[text_num / 2 - 1 - i]; - } - if (gap_length < 0) - gap_length = 0; - - while (gap_length > left_length) { - gap_length -= left_length; - if (index1 == 0) - index1 = lines.size() - 1; - else - --index1; - left_length = lines[index1].length(); - } - - Vec3d direction = lines[index1].vector(); - direction.normalize(); - double distance_to_a = (left_length - gap_length); - Line_3D new_line = lines[index1]; - - double norm_value = direction.cast().norm(); - double deta_x = distance_to_a * direction.x() / norm_value; - double deta_y = distance_to_a * direction.y() / norm_value; - double deta_z = distance_to_a * direction.z() / norm_value; - Vec3d new_pos = new_line.a + Vec3d(deta_x, deta_y,deta_z); - - m_position_points[text_num / 2 - 1 - i] = new_pos; - left_length = distance_to_a; - } - } - - { - int index2 = index; - double right_length = (line.b - mouse_position_world).cast().norm(); - int right_num = text_num / 2; - double gap_length = 0; - for (int i = 0; i < text_num / 2; ++i) { - double gap_length = 0; - if (i == 0) { - gap_length = m_text_gap / 2 + text_lengths[text_num / 2 + i]; - } else { - gap_length = text_lengths[text_num / 2 + i] + m_text_gap + text_lengths[text_num / 2 + i - 1]; - } - if (gap_length < 0) - gap_length = 0; - - while (gap_length > right_length) { - gap_length -= right_length; - if (index2 == lines.size() - 1) - index2 = 0; - else - ++index2; - right_length = lines[index2].length(); - } - - Line_3D line2 = lines[index2]; - line2.reverse(); - Vec3d direction = line2.vector(); - direction.normalize(); - double distance_to_b = (right_length - gap_length); - Line_3D new_line = lines[index2]; - - double norm_value = direction.cast().norm(); - double deta_x = distance_to_b * direction.x() / norm_value; - double deta_y = distance_to_b * direction.y() / norm_value; - double deta_z = distance_to_b * direction.z() / norm_value; - Vec3d new_pos = new_line.b + Vec3d(deta_x, deta_y, deta_z); - m_position_points[text_num / 2 + i] = new_pos; - right_length = distance_to_b; - } - } - } - } - - TriangleMesh mesh = slice_meshs; - std::vector mesh_values(m_position_points.size(), 1e9); - m_normal_points.resize(m_position_points.size()); - auto point_in_triangle_delete_area = [](const Vec3d &point, const Vec3d &point0, const Vec3d &point1, const Vec3d &point2) { - Vec3d p0_p = point - point0; - Vec3d p0_p1 = point1 - point0; - Vec3d p0_p2 = point2 - point0; - Vec3d p_p0 = point0 - point; - Vec3d p_p1 = point1 - point; - Vec3d p_p2 = point2 - point; - - double s = p0_p1.cross(p0_p2).norm(); - double s0 = p_p0.cross(p_p1).norm(); - double s1 = p_p1.cross(p_p2).norm(); - double s2 = p_p2.cross(p_p0).norm(); - - return abs(s0 + s1 + s2 - s); - }; - bool is_mirrored =m_model_object_in_world_tran.is_left_handed(); - for (int i = 0; i < m_position_points.size(); ++i) { - for (auto indice : mesh.its.indices) { - stl_vertex stl_point0 = mesh.its.vertices[indice[0]]; - stl_vertex stl_point1 = mesh.its.vertices[indice[1]]; - stl_vertex stl_point2 = mesh.its.vertices[indice[2]]; - - Vec3d point0 = Vec3d(stl_point0[0], stl_point0[1], stl_point0[2]); - Vec3d point1 = Vec3d(stl_point1[0], stl_point1[1], stl_point1[2]); - Vec3d point2 = Vec3d(stl_point2[0], stl_point2[1], stl_point2[2]); - - point0 = mi->get_transformation().get_matrix() * point0; - point1 = mi->get_transformation().get_matrix() * point1; - point2 = mi->get_transformation().get_matrix() * point2; - - double abs_area = point_in_triangle_delete_area(m_position_points[i], point0, point1, point2); - if (mesh_values[i] > abs_area) { - mesh_values[i] = abs_area; - - Vec3d s1 = point1 - point0; - Vec3d s2 = point2 - point0; - m_normal_points[i] = s1.cross(s2); - m_normal_points[i].normalize(); - if(is_mirrored){ - m_normal_points[i] = -m_normal_points[i]; - } - } - } + auto text_tran_in_object = m_model_object_in_world_tran.get_matrix().inverse() * + m_text_tran_in_world.get_matrix(); // Geometry::generate_transform(cs_x_dir, cs_y_dir, cs_z_dir, text_position_in_object); // todo modify by m_text_tran_in_world + Geometry::Transformation text_tran_in_object_(text_tran_in_object); + if (rewrite_text_tran) { + m_text_tran_in_object.set_matrix(text_tran_in_object); // for preview } return true; } -TriangleMesh GLGizmoText::get_text_mesh(const char* text_str, const Vec3d &position, const Vec3d &normal, const Vec3d& text_up_dir) +void GLGizmoText::update_trafo_matrices() { - TextResult text_result; - load_text_shape(text_str, m_font_name.c_str(), m_font_size, m_thickness + m_embeded_depth, m_bold, m_italic, text_result); - TriangleMesh mesh = text_result.text_mesh; - - - mesh.translate(-text_result.text_width / 2, -m_font_size / 4, 0); - - double phi; - Vec3d rotation_axis; - Matrix3d rotation_matrix; - Geometry::rotation_from_two_vectors(Vec3d::UnitZ(), normal, rotation_axis, phi, &rotation_matrix); - mesh.rotate(phi, rotation_axis); - - auto project_on_plane = [](const Vec3d& dir, const Vec3d& plane_normal) -> Vec3d { - return dir - (plane_normal.dot(dir) * plane_normal.dot(plane_normal)) * plane_normal; - }; - - Vec3d old_text_dir = Vec3d::UnitY(); - old_text_dir = rotation_matrix * old_text_dir; - Vec3d new_text_dir = project_on_plane(text_up_dir, normal); - new_text_dir.normalize(); - Geometry::rotation_from_two_vectors(old_text_dir, new_text_dir, rotation_axis, phi, &rotation_matrix); - - if (abs(phi - PI) < EPSILON) - rotation_axis = normal; - - mesh.rotate(phi, rotation_axis); - - - Vec3d offset = position - m_embeded_depth * normal; - mesh.translate(offset.x(), offset.y(), offset.z()); - - return mesh;//mesh in object cs + m_trafo_matrices.clear(); + const Selection &selection = m_parent.get_selection(); + auto mo = selection.get_model()->objects[m_object_idx]; + if (mo == nullptr) + return; + const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; + for (ModelVolume *mv : mo->volumes) { + m_trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); + } } -bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector &trafo_matrices) +void GLGizmoText::update_cut_plane_dir() +{ + auto cur_world = m_model_object_in_world_tran.get_matrix() * m_text_tran_in_object.get_matrix(); + m_cut_plane_dir_in_world = cur_world.linear().col(1).normalized(); +} + +void GLGizmoText::switch_text_type(TextInfo::TextType type) +{ + m_need_update_tran = true; + m_need_update_text = true; + if (m_surface_type == TextInfo::TextType::SURFACE_HORIZONAL && type != TextInfo::TextType::SURFACE_HORIZONAL) { + update_text_normal_in_world(); + } + m_surface_type = type; + process(); +} + +float GLGizmoText::get_angle_from_current_style() +{ + StyleManager::Style ¤t_style = m_style_manager.get_style(); + float angle = current_style.angle.value_or(0.f); + float angle_deg = static_cast(angle * 180 / M_PI); + if (abs(angle_deg) < 0.0001) { + return 0.f; + } + return angle_deg; +} + +void GLGizmoText::volume_transformation_changed() +{ + auto text_volume = m_last_text_mv; + if (!text_volume) { + return; + } + m_need_update_text = true; + auto &tc = text_volume->get_text_info().text_configuration; + //const EmbossShape & es = *text_volume->emboss_shape; + + //bool per_glyph = tc.style.prop.per_glyph; + //if (per_glyph) init_text_lines(m_text_lines, m_parent.get_selection(), m_style_manager, m_text_lines.get_lines().size()); + + //bool use_surface = es.projection.use_surface; + + // Update surface by new position + //if (use_surface || per_glyph) + // process(); + //else { + // // inform slicing process that model changed + // // SLA supports, processing + // // ensure on bed + // wxGetApp().plater()->changed_object(*m_volume->get_object()); + //} + m_style_manager.get_style().angle = calc_angle(m_parent.get_selection()); + m_rotate_angle = get_angle_from_current_style(); + process(); + // Show correct value of height & depth inside of inputs + calculate_scale(); +} + + + +bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector &trafo_matrices, bool exclude_last) { if (m_rr.mouse_position == mouse_position) { return false; } - if (m_is_modify) - return false; - Vec3f normal = Vec3f::Zero(); Vec3f hit = Vec3f::Zero(); size_t facet = 0; @@ -1814,15 +3114,11 @@ bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera // Cast a ray on all meshes, pick the closest hit and save it for the respective mesh for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) { - if (m_preview_text_volume_id != -1 && mesh_id == int(trafo_matrices.size()) - 1) + if (exclude_last && mesh_id == int(trafo_matrices.size()) - 1) continue; - - if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal, m_c->object_clipper()->get_clipping_plane(), + if (mesh_id < m_c->raycaster()->raycasters().size()&& m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal, + m_c->object_clipper()->get_clipping_plane(), &facet)) { - // In case this hit is clipped, skip it. - if (is_mesh_point_clipped(hit.cast(), trafo_matrices[mesh_id])) - continue; - double hit_squared_distance = (camera.get_position() - trafo_matrices[mesh_id] * hit.cast()).squaredNorm(); if (hit_squared_distance < closest_hit_squared_distance) { closest_hit_squared_distance = hit_squared_distance; @@ -1837,133 +3133,110 @@ bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera return true; } -void GLGizmoText::generate_text_volume(bool is_temp) +bool GLGizmoText::generate_text_volume() { - std::string text = std::string(m_text); - if (text.empty()) - return; - - std::wstring_convert> str_cnv; - std::wstring ws = boost::nowide::widen(m_text); - std::vector alphas; - for (auto w : ws) { - alphas.push_back(str_cnv.to_bytes(w)); - } - - update_text_positions(alphas);//update m_model_object_in_world_tran - - if (m_position_points.size() == 0) - return; - auto inv_text_cs_in_object = (m_model_object_in_world_tran.get_matrix() * m_text_tran_in_object.get_matrix()).inverse(); - auto inv_text_cs_in_object_no_offset = (m_model_object_in_world_tran.get_matrix_no_offset() * m_text_tran_in_object.get_matrix_no_offset()).inverse(); - TriangleMesh mesh; - for (int i = 0; i < alphas.size(); ++i) { - auto position = inv_text_cs_in_object * m_position_points[i]; - auto normal = inv_text_cs_in_object_no_offset * m_normal_points[i]; - auto cut_plane_dir = inv_text_cs_in_object_no_offset * m_cut_plane_dir_in_world; - TriangleMesh sub_mesh = get_text_mesh(alphas[i].c_str(), position, normal, cut_plane_dir); - mesh.merge(sub_mesh); - } - if (mesh.empty()) - return; - auto center = mesh.bounding_box().center(); - if (abs(mesh.bounding_box().size()[2] - (m_embeded_depth + m_thickness)) < 0.01) { - mesh.translate(Vec3f(-center.x(), -center.y(), 0)); // align horizontal and vertical center - } - else { - mesh.translate(Vec3f(0, -center.y(), 0)); // align vertical center - } - + if (m_text.empty()) + return false; Plater *plater = wxGetApp().plater(); if (!plater) - return; + return false; + m_show_calc_meshtod = 0; + if (m_object_idx < 0) {//m_object_idx < 0 && !is_only_text_case() + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "error:m_object_idx < 0"; + return false; + } + if (auto text_mv = get_text_is_dragging()) { // moving or dragging; + m_show_calc_meshtod = 2; + update_text_tran_in_model_object(); + text_mv->set_transformation(m_text_tran_in_object.get_matrix()); + return true; + /* auto gl_v = get_selected_gl_volume(m_parent); + gl_v->set_volume_transformation(m_text_tran_in_object.get_matrix()); + return false;*/ + } + bool rewrite_text_tran = m_need_update_tran ? true : m_last_text_mv == nullptr; + if (!update_text_tran_in_model_object(rewrite_text_tran)) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " fail:update_text_tran_in_model_object"; + return false; + } + + const Selection & selection = m_parent.get_selection(); + Emboss::GenerateTextJob::InputInfo input_info; + auto text_volume = m_last_text_mv; + DataBasePtr base = create_emboss_data_base(m_text, m_style_manager, selection, text_volume == nullptr ? ModelVolumeType::MODEL_PART : text_volume->type(), + m_job_cancel); // m_text_lines + Emboss::DataUpdate data_update = {std::move(base), text_volume == nullptr ? -1 : text_volume->id(), false}; + m_ui_text_configuration = data_update.base->get_text_configuration(); + input_info.text_surface_type = m_surface_type; + input_info.is_outside = data_update.base->is_outside; + input_info.shape_scale = data_update.base->shape.scale; + input_info.m_data_update = std::move(data_update); + + input_info.m_text_tran_in_object = m_text_tran_in_object; + + input_info.m_volume_idx = m_volume_idx ; + input_info.first_generate = m_volume_idx < 0 ? true : false; + input_info.m_cut_points_in_world = m_cut_points_in_world; + input_info.m_text_tran_in_world = m_text_tran_in_world; + + input_info.m_text_position_in_world = m_text_position_in_world; + input_info.m_text_normal_in_world = m_text_normal_in_world; + input_info.m_text_gap = m_text_gap; + input_info.m_model_object_in_world_tran = m_model_object_in_world_tran; + input_info.m_position_points = m_position_points; + input_info.m_normal_points = m_normal_points; + input_info.m_embeded_depth = m_embeded_depth; + input_info.m_thickness = m_thickness; + input_info.m_cut_plane_dir_in_world = m_cut_plane_dir_in_world; + input_info.use_surface = m_surface_type == TextInfo::TextType::SURFACE_CHAR ? true : false; TextInfo text_info = get_text_info(); - const Selection &selection = m_parent.get_selection(); - ModelObject * model_object = selection.get_model()->objects[m_object_idx]; - int cur_volume_id; - if (m_is_modify && m_need_update_text) { - if (m_object_idx == -1 || m_volume_idx == -1) { - BOOST_LOG_TRIVIAL(error) << boost::format("Text: selected object_idx = %1%, volume_idx = %2%") % m_object_idx % m_volume_idx; - return; - } - if (!is_temp) { - plater->take_snapshot("Modify Text"); - } - text_info.m_font_version = CUR_FONT_VERSION; - ModelVolume * model_volume = model_object->volumes[m_volume_idx]; - ModelVolume * new_model_volume = model_object->add_volume(std::move(mesh),false); - if (m_need_fix && // m_reedit_text//m_need_fix - (m_text_type == TextType::HORIZONAL || (m_text_type > TextType::HORIZONAL && m_use_current_pose))) { - new_model_volume->set_transformation(m_load_text_tran_in_object.get_matrix()); - } - else { - new_model_volume->set_transformation(m_text_tran_in_object.get_matrix()); - } - new_model_volume->set_text_info(text_info); - new_model_volume->name = model_volume->name; - new_model_volume->set_type(model_volume->type()); - new_model_volume->config.apply(model_volume->config); - std::swap(model_object->volumes[m_volume_idx], model_object->volumes.back()); - model_object->delete_volume(model_object->volumes.size() - 1); - model_object->invalidate_bounding_box(); - plater->update(); - m_text_volume_tran = new_model_volume->get_matrix(); - } else { - if (!is_temp && m_need_update_text) - plater->take_snapshot("Add Text"); - ObjectList *obj_list = wxGetApp().obj_list(); - cur_volume_id = obj_list->add_text_part(mesh, "text_shape", text_info, m_text_tran_in_object.get_matrix(), is_temp); - m_preview_text_volume_id = is_temp ? cur_volume_id : -1; - if (cur_volume_id >= 0) { - m_show_warning_text_create_fail = false; - ModelVolume *text_model_volume = model_object->volumes[cur_volume_id]; - m_text_volume_tran = text_model_volume->get_matrix(); - } - else { - m_show_warning_text_create_fail = true; - } - } - m_need_update_text = false; + ModelObject *model_object = selection.get_model()->objects[m_object_idx]; + input_info.mo = model_object; + m_show_warning_lost_rotate = false; -} - -void GLGizmoText::delete_temp_preview_text_volume() -{ - const Selection &selection = m_parent.get_selection(); - if (m_preview_text_volume_id > 0) { - ModelObject *model_object = selection.get_model()->objects[m_object_idx]; - if (m_preview_text_volume_id < model_object->volumes.size()) { - Plater *plater = wxGetApp().plater(); - if (!plater) - return; - - model_object->delete_volume(m_preview_text_volume_id); - - plater->update(); - } - m_preview_text_volume_id = -1; + if (m_need_update_text) { + m_need_update_text = false; + input_info.text_info = text_info; + input_info.m_final_text_tran_in_object = m_text_tran_in_object; + auto job = std::make_unique(std::move(input_info)); + auto &worker = wxGetApp().plater()->get_ui_job_worker(); + queue_job(worker, std::move(job)); } + return true; } TextInfo GLGizmoText::get_text_info() { TextInfo text_info; + const wxFont &wx_font = m_style_manager.get_wx_font(); + if (wx_font.IsOk()) { + auto actual_face_name = wx_font.GetFaceName(); + m_cur_font_name = actual_face_name; + m_font_name = actual_face_name.utf8_string(); + } text_info.m_font_name = m_font_name; text_info.m_font_version = m_font_version; + text_info.text_configuration.style.name = m_style_name; + m_font_size = m_style_manager.get_font_prop().size_in_mm; text_info.m_font_size = m_font_size; - text_info.m_curr_font_idx = m_curr_font_idx; + text_info.m_curr_font_idx = -1; + m_bold = m_style_manager.get_font_prop().boldness > 0; + m_italic = m_style_manager.get_font_prop().skew > 0; text_info.m_bold = m_bold; text_info.m_italic = m_italic; + text_info.m_thickness = m_thickness; + text_info.m_embeded_depth = m_embeded_depth; + text_info.m_text = m_text; text_info.m_rr.mesh_id = m_rr.mesh_id; - text_info.m_embeded_depth = m_embeded_depth; text_info.m_rotate_angle = m_rotate_angle; text_info.m_text_gap = m_text_gap; - text_info.m_is_surface_text = m_text_type == TextType::SURFACE || m_text_type == TextType::SURFACE_HORIZONAL; - text_info.m_keep_horizontal = m_text_type == TextType::HORIZONAL || m_text_type == TextType::SURFACE_HORIZONAL; + text_info.m_surface_type = m_surface_type; + text_info.text_configuration = m_ui_text_configuration; + text_info.m_font_version = CUR_FONT_VERSION; return text_info; } @@ -1971,24 +3244,688 @@ void GLGizmoText::load_from_text_info(const TextInfo &text_info) { m_font_name = text_info.m_font_name; m_font_version = text_info.m_font_version; + m_style_name = text_info.text_configuration.style.name; m_font_size = text_info.m_font_size; - // from other user's computer may exist case:font library size is different - if (text_info.m_curr_font_idx < m_font_names.size()) { - m_curr_font_idx = text_info.m_curr_font_idx; - } - else { - m_curr_font_idx = 0; - } + m_bold = text_info.m_bold; m_italic = text_info.m_italic; m_thickness = text_info.m_thickness; - strcpy(m_text, text_info.m_text.c_str()); - m_rr.mesh_id = text_info.m_rr.mesh_id; + bool is_text_changed = m_text != text_info.m_text; + m_text = text_info.m_text; + m_rr.mesh_id = text_info.m_rr.mesh_id; m_embeded_depth = text_info.m_embeded_depth; - m_rotate_angle = text_info.m_rotate_angle; + double limit_angle = Geometry::deg2rad((double) text_info.m_rotate_angle); + Geometry::to_range_pi_pi(limit_angle); + m_rotate_angle = (float) Geometry::rad2deg(limit_angle); + m_text_gap = text_info.m_text_gap; - check_text_type(text_info.m_is_surface_text, text_info.m_keep_horizontal); + m_surface_type = (TextInfo::TextType) text_info.m_surface_type; + + if (is_old_text_info(text_info)) { // compatible with older versions + load_old_font(); + auto cur_text_info = const_cast(&text_info); + cur_text_info->text_configuration.style = m_style_manager.get_style(); + } + else { + m_style_manager.get_font_prop().size_in_mm = m_font_size;//m_font_size + wxString font_name = wxString::FromUTF8(m_font_name.c_str());//wxString(m_font_name.c_str(), wxConvUTF8); + select_facename(font_name,false); + } + update_boldness(); + update_italic(); + if (is_text_changed) { + process(true,std::nullopt,false); + } } +bool GLGizmoText::is_old_text_info(const TextInfo &text_info) +{ + auto cur_font_version = text_info.m_font_version; + bool is_old = cur_font_version.empty(); + if (!cur_font_version.empty()) { + float version = std::atof(cur_font_version.c_str()); + if (version < 2.0) { + is_old = true; + } + } + return is_old; +} + +std::string concat(std::vector data) +{ + std::stringstream ss; + for (const auto &d : data) ss << d.c_str() << ", "; + return ss.str(); +} +boost::filesystem::path get_fontlist_cache_path() { + return boost::filesystem::path(data_dir()) / "cache" / "fonts.cereal"; +} +bool store(const CurFacenames &facenames) +{ + std::string cache_path = get_fontlist_cache_path().string(); + boost::filesystem::path path(cache_path); + if (!boost::filesystem::exists(path.parent_path())) { boost::filesystem::create_directory(path.parent_path()); } + boost::nowide::ofstream file(cache_path, std::ios::binary); + ::cereal::BinaryOutputArchive archive(file); + std::vector good; + good.reserve(facenames.faces.size()); + for (const FaceName &face : facenames.faces) good.push_back(face.wx_name); + FacenamesSerializer data = {facenames.hash, good, facenames.bad}; + + assert(std::is_sorted(data.bad.begin(), data.bad.end())); + assert(std::is_sorted(data.good.begin(), data.good.end())); + try { + archive(data); + } catch (const std::exception &ex) { + BOOST_LOG_TRIVIAL(error) << "Failed to write fontlist cache - " << cache_path << ex.what(); + return false; + } + return true; +} +bool load(CurFacenames &facenames, const std::vector &delete_bad_font_list) +{ + boost::filesystem::path path = get_fontlist_cache_path(); + std::string path_str = path.string(); + if (!boost::filesystem::exists(path)) { + BOOST_LOG_TRIVIAL(warning) << "Fontlist cache - '" << PathSanitizer::sanitize(path_str) << "' does not exists."; + return false; + } + boost::nowide::ifstream file(path_str, std::ios::binary); + ::cereal::BinaryInputArchive archive(file); + + FacenamesSerializer data; + try { + archive(data); + } catch (const std::exception &ex) { + BOOST_LOG_TRIVIAL(error) << "Failed to load fontlist cache - '" << PathSanitizer::sanitize(path_str) << "'. Exception: " << ex.what(); + return false; + } + + assert(std::is_sorted(data.bad.begin(), data.bad.end())); + assert(std::is_sorted(data.good.begin(), data.good.end())); + + facenames.hash = data.hash; + facenames.faces.reserve(data.good.size()); + for (const wxString &face : data.good) { + bool is_find = std::find(delete_bad_font_list.begin(), delete_bad_font_list.end(), face) != delete_bad_font_list.end(); + if (is_find) { + continue; + } + facenames.faces.push_back({face}); + } + facenames.bad = data.bad; + + return true; +} + +// validation lambda +bool is_valid_font(const wxString &name, wxFontEncoding encoding, std::vector bad ) // face_names.encoding , face_names.bad +{ + if (name.empty()) + return false; + + // vertical font start with @, we will filter it out + // Not sure if it is only in Windows so filtering is on all platforms + if (name[0] == '@') return false; + + // previously detected bad font + auto it = std::lower_bound(bad.begin(), bad.end(), name); + if (it != bad.end() && *it == name) return false; + + wxFont wx_font(wxFontInfo().FaceName(name).Encoding(encoding)); + //* + // Faster chech if wx_font is loadable but not 100% + // names could contain not loadable font + if (!WxFontUtils::can_load(wx_font)) return false; + + /*/ + // Slow copy of font files to try load font + // After this all files are loadable + auto font_file = WxFontUtils::create_font_file(wx_font); + if (font_file == nullptr) + return false; // can't create font file + // */ + return true; +} + +bool draw_button(const IconManager::VIcons &icons, IconType type, bool disable) +{ + return Slic3r::GUI::button(get_icon(icons, type, IconState::activable), get_icon(icons, type, IconState::hovered), get_icon(icons, type, IconState::disabled), disable); +} + +void init_face_names(CurFacenames &face_names) +{ + Timer t("enumerate_fonts"); + if (face_names.is_init) return; + face_names.is_init = true; + + // to reload fonts from system, when install new one + wxFontEnumerator::InvalidateCache(); + std::vector delete_bad_font_list;//QDS +#ifdef _WIN32 + delete_bad_font_list = {"Symbol","Wingdings","Wingdings 2","Wingdings 3", "Webdings"}; +#endif + // try load cache + // Only not OS enumerated face has hash value 0 + if (face_names.hash == 0) { + load(face_names, delete_bad_font_list); + face_names.has_truncated_names = false; + } + + using namespace std::chrono; + steady_clock::time_point enumerate_start = steady_clock::now(); + ScopeGuard sg([&enumerate_start, &face_names = face_names]() { + steady_clock::time_point enumerate_end = steady_clock::now(); + long long enumerate_duration = duration_cast(enumerate_end - enumerate_start).count(); + BOOST_LOG_TRIVIAL(info) << "OS enumerate " << face_names.faces.size() << " fonts " + << "(+ " << face_names.bad.size() << " can't load " + << "= " << face_names.faces.size() + face_names.bad.size() << " fonts) " + << "in " << enumerate_duration << " ms\n" + << concat(face_names.bad); + }); + wxArrayString facenames = wxFontEnumerator::GetFacenames(face_names.encoding); + size_t hash = boost::hash_range(facenames.begin(), facenames.end()); + // Zero value is used as uninitialized hash + if (hash == 0) hash = 1; + // check if it is same as last time + if (face_names.hash == hash) { + if (face_names.faces_names.size() == 0) {//FIX by bbs + face_names.faces_names.clear(); + face_names.faces_names.reserve(face_names.faces.size()); + for (size_t i = 0; i < face_names.faces.size(); i++) { + auto cur = face_names.faces[i].wx_name.ToUTF8().data(); + face_names.faces_names.push_back(cur); + } + } + // no new installed font + BOOST_LOG_TRIVIAL(info) << "Same FontNames hash, cache is used. " + << "For clear cache delete file: " << PathSanitizer::sanitize(get_fontlist_cache_path()); + return; + } + + BOOST_LOG_TRIVIAL(info) << ((face_names.hash == 0) ? "FontName list is generate from scratch." : "Hash are different. Only previous bad fonts are used and set again as bad"); + face_names.hash = hash; + + face_names.faces.clear(); + face_names.faces_names.clear(); + face_names.bad.clear(); + face_names.faces.reserve(facenames.size()); + face_names.faces_names.reserve(facenames.size()); + std::sort(facenames.begin(), facenames.end()); + + for (const wxString& name : facenames) { + bool is_find = std::find(delete_bad_font_list.begin(), delete_bad_font_list.end(), name) != delete_bad_font_list.end(); + if (is_find) { + face_names.bad.push_back(name); + continue; + } + if (is_valid_font(name, face_names.encoding, face_names.bad)) { + face_names.faces.push_back({name}); + face_names.faces_names.push_back(name.utf8_string()); + } else { + face_names.bad.push_back(name); + } + } + assert(std::is_sorted(face_names.bad.begin(), face_names.bad.end())); + face_names.has_truncated_names = false; + store(face_names); +} +void init_truncated_names(CurFacenames& face_names, float max_width) { + for (FaceName &face : face_names.faces) { + std::string name_str(face.wx_name.ToUTF8().data()); + face.name_truncated = ImGuiWrapper::trunc(name_str, max_width); + } + face_names.has_truncated_names = true; +} + +std::optional get_installed_face_name(const std::optional& face_name_opt, CurFacenames& face_names) { + // Could exist OS without getter on face_name, + // but it is able to restore font from descriptor + // Soo default value must be TRUE + if (!face_name_opt.has_value()) + return wxString(); + + wxString face_name = wxString::FromUTF8(face_name_opt->c_str()); + + // search in enumerated fonts + // refresh list of installed font in the OS. + init_face_names(face_names); + face_names.is_init = false; + + auto cmp = [](const FaceName &fn, const wxString &wx_name) { return fn.wx_name < wx_name; }; + const std::vector &faces = face_names.faces; + // is font installed? + if (auto it = std::lower_bound(faces.begin(), faces.end(), face_name, cmp); it != faces.end() && it->wx_name == face_name) return face_name; + + const std::vector &bad = face_names.bad; + auto it_bad = std::lower_bound(bad.begin(), bad.end(), face_name); + if (it_bad == bad.end() || *it_bad != face_name) { + // check if wx allowed to set it up - another encoding of name + wxFontEnumerator::InvalidateCache(); + wxFont wx_font_; // temporary structure + if (wx_font_.SetFaceName(face_name) && WxFontUtils::create_font_file(wx_font_) != nullptr // can load TTF file? + ) { + return wxString(); + // QUESTION: add this name to allowed faces? + // Could create twin of font face name + // When not add it will be hard to select it again when change font + } + } + return {}; // not installed +} + +void draw_font_preview(FaceName& face, const std::string& text, CurFacenames& faces, const CurGuiCfg& cfg, bool is_visible) +{ + // Limit for opened font files at one moment + unsigned int &count_opened_fonts = faces.count_opened_font_files; + // Size of texture + ImVec2 size(cfg.face_name_size.x(), cfg.face_name_size.y()); + float count_cached_textures_f = static_cast(faces.count_cached_textures); + std::string state_text; + // uv0 and uv1 set to pixel 0,0 in texture + ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / count_cached_textures_f); + if (face.is_created != nullptr) { + // not created preview + if (*face.is_created) { + // Already created preview + size_t texture_index = face.texture_index; + uv0 = ImVec2(0.f, texture_index / count_cached_textures_f); + uv1 = ImVec2(1.f, (texture_index + 1) / count_cached_textures_f); + } else { + // Not finished preview + if (is_visible) { + // when not canceled still loading + state_text = (face.cancel->load()) ? " " + _u8L("No symbol") : " ... " + _u8L("Loading"); + } else { + // not finished and not visible cancel job + face.is_created = nullptr; + face.cancel->store(true); + } + } + } else if (is_visible && count_opened_fonts < cfg.max_count_opened_font_files) { + ++count_opened_fonts; + face.cancel = std::make_shared(false); + face.is_created = std::make_shared(false); + + const unsigned char gray_level = 5; + // format type and level must match to texture data + const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE; + const GLint level = 0; + // select next texture index + size_t texture_index = (faces.texture_index + 1) % faces.count_cached_textures; + + // set previous cach as deleted + for (FaceName &f : faces.faces) + if (f.texture_index == texture_index) { + if (f.cancel != nullptr) f.cancel->store(true); + f.is_created = nullptr; + } + + faces.texture_index = texture_index; + face.texture_index = texture_index; + + // render text to texture + FontImageData data{ + text, face.wx_name, faces.encoding, faces.texture_id, faces.texture_index, cfg.face_name_size, gray_level, format, type, level, &count_opened_fonts, + face.cancel, // copy + face.is_created // copy + }; + auto job = std::make_unique(std::move(data)); + auto &worker = wxGetApp().plater()->get_ui_job_worker(); + queue_job(worker, std::move(job)); + } else { + // cant start new thread at this moment so wait in queue + state_text = " ... " + _u8L("In queue"); + } + + if (!state_text.empty()) { + ImGui::SameLine(cfg.face_name_texture_offset_x); + ImGui::Text("%s", state_text.c_str()); + } + + ImGui::SameLine(cfg.face_name_texture_offset_x); + ImTextureID tex_id = (void *) (intptr_t) faces.texture_id; + ImVec4 tint_color = ImGui::GetStyleColorVec4(ImGuiCol_Text); + ImGui::Image(tex_id, size, uv0, uv1, tint_color); +} + +void init_text_lines(TextLinesModel &text_lines, const Selection &selection, /* const*/ StyleManager &style_manager, unsigned count_lines) +{ + text_lines.reset(); + if (selection.is_empty()) + return; + const GLVolume *gl_volume_ptr = selection.get_first_volume(); + if (gl_volume_ptr == nullptr) return; + const GLVolume & gl_volume = *gl_volume_ptr; + const ModelObjectPtrs &objects = selection.get_model()->objects; + const ModelVolume * mv_ptr = get_model_volume(gl_volume, objects); + if (mv_ptr == nullptr) return; + const ModelVolume &mv = *mv_ptr; + if (mv.is_the_only_one_part()) return; + + const std::optional &es_opt = mv.emboss_shape; + if (!es_opt.has_value()) return; + const EmbossShape &es = *es_opt; + + //const std::optional &tc_opt = mv.text_configuration; + //if (!tc_opt.has_value()) return; + //const TextConfiguration &tc = *tc_opt; + + //// calculate count lines when not set + //if (count_lines == 0) { + // count_lines = get_count_lines(tc.text); + // if (count_lines == 0) return; + //} + + //// prepare volumes to slice + //ModelVolumePtrs volumes = prepare_volumes_to_slice(mv); + + //// For interactivity during drag over surface it must be from gl_volume not volume. + //Transform3d mv_trafo = gl_volume.get_volume_transformation().get_matrix(); + //if (es.fix_3mf_tr.has_value()) + // mv_trafo = mv_trafo * (es.fix_3mf_tr->inverse()); + //text_lines.init(mv_trafo, volumes, style_manager, count_lines); +} + +const IconManager::Icon &Text::get_icon(const IconManager::VIcons &icons, Text::IconType type, Text::IconState state) { + return *icons[(unsigned) type][(unsigned) state]; +} +CurGuiCfg Text::create_gui_configuration() +{ + CurGuiCfg cfg; // initialize by default values; + + float line_height = ImGui::GetTextLineHeight(); + float line_height_with_spacing = ImGui::GetTextLineHeightWithSpacing(); + float space = line_height_with_spacing - line_height; + const ImGuiStyle &style = ImGui::GetStyle(); + + cfg.max_style_name_width = ImGui::CalcTextSize("Maximal font name, extended").x; + + cfg.icon_width = static_cast(std::ceil(line_height)); + // make size pair number + if (cfg.icon_width % 2 != 0) ++cfg.icon_width; + + cfg.delete_pos_x = cfg.max_style_name_width + space; + const float count_line_of_text = 3.f; + cfg.text_size = ImVec2(-FLT_MIN, line_height_with_spacing * count_line_of_text); + ImVec2 letter_m_size = ImGui::CalcTextSize("M"); + const float count_letter_M_in_input = 12.f; + cfg.input_width = letter_m_size.x * count_letter_M_in_input; + CurGuiCfg::Translations &tr = cfg.translations; + + // TRN - Input label. Be short as possible + // Select look of letter shape + tr.font = _u8L("Font"); + // TRN - Input label. Be short as possible + // Height of one text line - Font Ascent + tr.height = _u8L("Size"); + // TRN - Input label. Be short as possible + // Size in emboss direction + tr.depth = _u8L("Depth"); + + float max_text_width = std::max({ImGui::CalcTextSize(tr.font.c_str()).x, ImGui::CalcTextSize(tr.height.c_str()).x, ImGui::CalcTextSize(tr.depth.c_str()).x}); + cfg.indent = static_cast(cfg.icon_width); + cfg.input_offset = style.WindowPadding.x + cfg.indent + max_text_width + space; + + // TRN - Input label. Be short as possible + // Copy surface of model on surface of the embossed text + tr.use_surface = _u8L("Use surface"); + // TRN - Input label. Be short as possible + // Option to change projection on curved surface + // for each character(glyph) in text separately + tr.per_glyph = _u8L("Per glyph"); + // TRN - Input label. Be short as possible + // Align Top|Middle|Bottom and Left|Center|Right + tr.alignment = _u8L("Alignment"); + // TRN - Input label. Be short as possible + tr.char_gap = _u8L("Text gap"); + // TRN - Input label. Be short as possible + tr.line_gap = _u8L("Line gap"); + // TRN - Input label. Be short as possible + tr.boldness = _u8L("Boldness"); + + // TRN - Input label. Be short as possible + // Like Font italic + tr.skew_ration = _u8L("Skew ratio"); + + // TRN - Input label. Be short as possible + // Distance from model surface to be able + // move text as part fully into not flat surface + // move text as modifier fully out of not flat surface + tr.from_surface = _u8L("From surface"); + + // TRN - Input label. Be short as possible + // Angle between Y axis and text line direction. + tr.rotation = _u8L("Rotation"); + + + float max_advanced_text_width = std::max({ImGui::CalcTextSize(tr.use_surface.c_str()).x, ImGui::CalcTextSize(tr.per_glyph.c_str()).x, + ImGui::CalcTextSize(tr.alignment.c_str()).x, ImGui::CalcTextSize(tr.char_gap.c_str()).x, ImGui::CalcTextSize(tr.line_gap.c_str()).x, + ImGui::CalcTextSize(tr.boldness.c_str()).x, ImGui::CalcTextSize(tr.skew_ration.c_str()).x, + ImGui::CalcTextSize(tr.from_surface.c_str()).x, ImGui::CalcTextSize(tr.rotation.c_str()).x + cfg.icon_width + 2 * space, + }); + cfg.advanced_input_offset = max_advanced_text_width + 3 * space + cfg.indent; + + cfg.lock_offset = cfg.advanced_input_offset - (cfg.icon_width + space); + // calculate window size + float input_height = line_height_with_spacing + 2 * style.FramePadding.y; + float separator_height = 2 + style.FramePadding.y; + + // "Text is to object" + radio buttons + cfg.height_of_volume_type_selector = separator_height + line_height_with_spacing + input_height; + + int max_style_image_width = static_cast(std::round(cfg.max_style_name_width / 2 - 2 * style.FramePadding.x)); + int max_style_image_height = static_cast(std::round(input_height)); + cfg.max_style_image_size = Vec2i32(max_style_image_width, line_height); + cfg.face_name_size = Vec2i32(cfg.input_width, line_height_with_spacing); + cfg.face_name_texture_offset_x = cfg.face_name_size.x() + style.WindowPadding.x + space; + + cfg.max_tooltip_width = ImGui::GetFontSize() * 20.0f; + + return cfg; +} + +EmbossShape &TextDataBase::create_shape() +{ + if (!shape.shapes_with_ids.empty()) + return shape; + // create shape by configuration + const char * text = m_text_configuration.text.c_str(); + std::wstring text_w = boost::nowide::widen(text); + const FontProp &fp = m_text_configuration.style.prop; + auto was_canceled = [&c = cancel]() { return c->load(); }; + auto ft_fn = [](){ + return Slic3r::GUI::BackupFonts::backup_fonts; + }; + bool support_backup_fonts = GUI::wxGetApp().app_config->get_bool("support_backup_fonts"); + if (support_backup_fonts) { + text2vshapes(shape, m_font_file, text_w, fp, was_canceled, ft_fn); + } else { + text2vshapes(shape, m_font_file, text_w, fp, was_canceled); + } + return shape; +} + +StateColor ok_btn_bg(std::pair(wxColour(27, 136, 68), StateColor::Pressed), + std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(wxColour(0, 174, 66), StateColor::Normal)); +StateColor ok_btn_disable_bg(std::pair(wxColour(205, 201, 201), StateColor::Pressed), + std::pair(wxColour(205, 201, 201), StateColor::Hovered), + std::pair(wxColour(205, 201, 201), StateColor::Normal)); + +StyleNameEditDialog::StyleNameEditDialog( + wxWindow *parent, Emboss::StyleManager &style_manager, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) + : DPIDialog(parent, id, title, pos, size, style), m_style_manager(style_manager) +{ + std::string icon_path = (boost::format("%1%/images/QIDIStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + SetBackgroundColour(*wxWHITE); + wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL); + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(400), -1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); + + m_top_sizer = new wxFlexGridSizer(1, 2, FromDIP(5), 0); + //m_top_sizer->AddGrowableCol(0, 1); + m_top_sizer->SetFlexibleDirection(wxBOTH); + m_top_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + + //m_row_panel = new wxPanel(this); + auto empty_name_txt = new Label(this, ""); + + auto plate_name_txt = new Label(this, _L("Style name")); + plate_name_txt->SetFont(Label::Body_14); + int text_size = ImGuiWrapper::calc_text_size(_L("There is already a text style with the same name.")).x; + auto input_len = std::max(240, text_size - 30); + m_name = new TextInput(this, wxString::FromDouble(0.0), "", "", wxDefaultPosition, wxSize(FromDIP(input_len), -1), wxTE_PROCESS_ENTER); + m_name->GetTextCtrl()->SetValue(""); + m_name->GetTextCtrl()->Bind(wxEVT_TEXT, &StyleNameEditDialog::on_edit_text, this); + + m_top_sizer->Add(plate_name_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + m_top_sizer->Add(m_name, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + m_top_sizer->Add(empty_name_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + + m_name->GetTextCtrl()->SetMaxLength(20); + empty_name_txt->Hide(); + + m_sizer_main->Add(m_top_sizer, 0, wxEXPAND | wxALL, FromDIP(20)); + + auto sizer_button = new wxBoxSizer(wxHORIZONTAL); + StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + StateColor ok_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); + StateColor ok_btn_bd(std::pair(wxColour(0, 174, 66), StateColor::Normal)); + m_button_ok = new Button(this, _L("OK")); + m_button_ok->Enable(true); + m_button_ok->SetBackgroundColor(ok_btn_bg); + m_button_ok->SetBorderColor(ok_btn_bd); + m_button_ok->SetTextColor(ok_btn_text); + m_button_ok->SetFont(Label::Body_12); + m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_ok->SetCornerRadius(FromDIP(12)); + m_button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { + if (get_name().empty()) { + add_tip_label(); + if (m_tip) { + m_tip->SetLabel(_L("Name can't be empty.")); + } + m_button_ok->Enable(false); + m_button_ok->SetBackgroundColor(ok_btn_disable_bg); + return; + } + if (this->IsModal()) + EndModal(wxID_YES); + else + this->Close(); + e.StopPropagation(); + }); + m_button_cancel = new Button(this, _L("Cancel")); + m_button_cancel->SetBackgroundColor(btn_bg_white); + m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); + m_button_cancel->SetFont(Label::Body_12); + m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_cancel->SetCornerRadius(FromDIP(12)); + m_button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { + if (this->IsModal()) + EndModal(wxID_CANCEL); + else + this->Close(); + e.StopPropagation(); + }); + sizer_button->AddStretchSpacer(); + sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5)); + sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5)); + sizer_button->Add(FromDIP(30), 0, 0, 0); + + m_sizer_main->Add(sizer_button, 0, wxEXPAND | wxBOTTOM, FromDIP(20)); + + SetSizer(m_sizer_main); + Layout(); + m_sizer_main->Fit(this); + + CenterOnParent(); + + wxGetApp().UpdateDlgDarkUI(this); +} + +StyleNameEditDialog::~StyleNameEditDialog() {} + +void StyleNameEditDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_button_ok->Rescale(); + m_button_cancel->Rescale(); +} + +wxString StyleNameEditDialog::get_name() const { return m_name->GetTextCtrl()->GetValue(); } + +void StyleNameEditDialog::set_name(const wxString &name) +{ + m_name->GetTextCtrl()->SetValue(name); + m_name->GetTextCtrl()->SetFocus(); + m_name->GetTextCtrl()->SetInsertionPointEnd(); +} +#define StyleNameEditDialogHeight FromDIP(170) +#define StyleNameEditDialogHeight_BIG FromDIP(200) +void Slic3r::GUI::StyleNameEditDialog::on_edit_text(wxCommandEvent &event) +{ + add_tip_label(); + std::string new_name = m_name->GetTextCtrl()->GetValue().utf8_string(); + bool is_unique = m_style_manager.is_unique_style_name(new_name); + if (new_name.empty()) { + m_button_ok->Enable(false); + if (m_tip) { + m_tip->Show(); + m_tip->SetLabel(_L("Name can't be empty.")); + } + SetMinSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + SetMaxSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + } else if (!is_unique) { + m_button_ok->Enable(false); + m_tip->Show(); + m_tip->SetLabel(_L("There is already a text style with the same name.")); + SetMinSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + SetMaxSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + } else if (check_empty_or_iillegal_character(new_name)) { + m_button_ok->Enable(false); + m_tip->Show(); + m_tip->SetLabel(_L("There are spaces or illegal characters present.")); + SetMinSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + SetMaxSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + } else { + m_tip->SetLabel(""); + m_tip->Show(false); + m_button_ok->Enable(true); + SetMinSize(wxSize(-1, StyleNameEditDialogHeight)); + SetMaxSize(wxSize(-1, StyleNameEditDialogHeight)); + } + m_button_ok->SetBackgroundColor(m_button_ok->IsEnabled() ? ok_btn_bg : ok_btn_disable_bg); + Layout(); + Fit(); +} + +void Slic3r::GUI::StyleNameEditDialog::add_tip_label() +{ + if (!m_add_tip) { + m_add_tip = true; + m_tip = new Label(this, _L("Name can't be empty.")); + m_tip->SetForegroundColour(wxColour(241, 117, 78, 255)); + m_top_sizer->Add(m_tip, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + SetMinSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + SetMaxSize(wxSize(-1, StyleNameEditDialogHeight_BIG)); + Layout(); + Fit(); + } +} + +bool Slic3r::GUI::StyleNameEditDialog::check_empty_or_iillegal_character(const std::string &name) +{ + if (Plater::has_illegal_filename_characters(name)) { return true; } + if (name.find_first_of(' ') != std::string::npos) { return true; } + return false; +} } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp index f4d17b8..27c2c94 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp @@ -1,51 +1,59 @@ #ifndef slic3r_GLGizmoText_hpp_ #define slic3r_GLGizmoText_hpp_ -#include "GLGizmoBase.hpp" +#include "GLGizmoRotate.hpp" #include "slic3r/GUI/3DScene.hpp" +#include "slic3r/GUI/SurfaceDrag.hpp" #include "../GLTexture.hpp" #include "../Camera.hpp" #include "libslic3r/Model.hpp" - +#include "slic3r/GUI/IconManager.hpp" +#include "slic3r/Utils/EmbossStyleManager.hpp" +#include "slic3r/GUI/Jobs/EmbossJob.hpp" +#include "libslic3r/TextConfiguration.hpp" +#include "slic3r/GUI/TextLines.hpp" namespace Slic3r { enum class ModelVolumeType : int; class ModelVolume; namespace GUI { -//#define DEBUG_TEXT //#define DEBUG_TEXT_VALUE - +//search TextToDo enum class SLAGizmoEventType : unsigned char; -const std::string CUR_FONT_VERSION = "1.0"; +//1.0 mean v1.10 qidi version +//1.1 mean v2.0 v2.1 qidi version(202505) +//2.0 mean v2.2 qidi version(202507) +const std::string CUR_FONT_VERSION = "2.0"; class GLGizmoText : public GLGizmoBase { private: + bool m_is_direct_create_text = false; + std::vector m_trafo_matrices;//Need to correspond m_c->raycaster()->raycasters + int m_show_calc_meshtod = 0;//1 preview //2 draging std::vector m_avail_font_names; - char m_text[1024] = { 0 }; - std::string m_font_name; + std::string m_text{""}; + std::string m_font_name; + wxString m_cur_font_name; std::string m_font_version = CUR_FONT_VERSION; - float m_font_size = 16.f; + std::string m_style_name; + float m_font_size = 10.f; const float m_font_size_min = 3.f; const float m_font_size_max = 1000.f; - int m_curr_font_idx = 0; + bool m_warning_font = false; bool m_bold = true; bool m_italic = false; float m_thickness = 2.f; - const float m_thickness_min = 0.01f; + const float m_thickness_min = 0.1f; const float m_thickness_max = 1000.f; float m_embeded_depth = 0.f; const float m_embeded_depth_max = 1000.f; float m_rotate_angle = 0; float m_text_gap = 0.f; - enum TextType { - HORIZONAL, - SURFACE, - SURFACE_HORIZONAL - }; - TextType m_text_type{TextType ::SURFACE}; + TextConfiguration m_ui_text_configuration; + TextInfo::TextType m_surface_type{TextInfo::TextType ::SURFACE}; bool m_really_use_surface_calc = false; - bool m_use_current_pose = true; + bool m_draging_cube = false; mutable RaycastResult m_rr; float m_combo_height = 0.0f; @@ -54,7 +62,6 @@ private: Vec2d m_mouse_position = Vec2d::Zero(); Vec2d m_origin_mouse_position = Vec2d::Zero(); - bool m_shift_down = false; class TextureInfo { public: @@ -75,8 +82,8 @@ private: std::mutex m_mutex; std::thread m_thread; - bool m_is_modify = false; bool m_need_update_text = false; + bool m_need_update_tran = false; bool m_reedit_text = false; bool m_show_warning_text_create_fail = false; bool m_show_text_normal_error = false; @@ -88,21 +95,42 @@ private: bool m_fix_old_tran_flag = false; bool m_is_version1_10_xoy = false; bool m_is_version1_9_xoz = false; + bool m_is_version1_8_yoz = false; int m_object_idx = -1; int m_volume_idx = -1; + //font deal + struct Facenames; // forward declaration + std::unique_ptr m_face_names; + // Keep information about stored styles and loaded actual style to compare with + Emboss::StyleManager m_style_manager; + std::shared_ptr> m_job_cancel = nullptr; + // When open text loaded from .3mf it could be written with unknown font + bool m_is_unknown_font = false; + // Is open tree with advanced options + bool m_is_advanced_edit_style = false; + // True when m_text contain character unknown by selected font + bool m_text_contain_unknown_glyph = false; + std::string m_style_new_name = ""; + // For text on scaled objects + std::optional m_scale_height; + std::optional m_scale_depth; + void calculate_scale(); + std::optional m_scale_width; + TextLinesModel m_text_lines; + // drawing icons + IconManager m_icon_manager; + IconManager::VIcons m_icons; - int m_preview_text_volume_id = -1; Vec3d m_fix_text_position_in_world = Vec3d::Zero(); Vec3f m_fix_text_normal_in_world = Vec3f::Zero(); - bool m_need_fix; Vec3d m_text_position_in_world = Vec3d::Zero(); Vec3f m_text_normal_in_world = Vec3f::Zero(); Geometry::Transformation m_text_tran_in_object; Geometry::Transformation m_text_tran_in_world; Geometry::Transformation m_load_text_tran_in_object; Geometry::Transformation m_model_object_in_world_tran; - Transform3d m_text_cs_to_world_tran; - Transform3d m_object_cs_to_world_tran; + std::optional m_fix_text_tran; + Vec3d m_cut_plane_dir_in_world = Vec3d::UnitZ(); std::vector m_position_points; @@ -111,25 +139,38 @@ private: // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. std::map m_desc; - Transform3d m_text_volume_tran; - ModelVolume * m_last_text_mv; + ModelVolume * m_last_text_mv{nullptr}; // move gizmo Grabber m_move_grabber; const int m_move_cube_id = 1; - + // Rotation gizmo + GLGizmoRotate m_rotate_gizmo; + std::optional m_distance; + std::optional m_rotate_start_angle; // TRN - Title in Undo/Redo stack after move with SVG along emboss axe - From surface const std::string move_snapshot_name = "Text move"; + const std::string rotation_snapshot_name = "Text rotate"; public: - GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); + GLGizmoText(GLCanvas3D& parent, unsigned int sprite_id); ~GLGizmoText(); void update_font_texture(); - bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down); + bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down) override; bool is_mesh_point_clipped(const Vec3d &point, const Transform3d &trafo) const; BoundingBoxf3 bounding_box() const; + static EmbossStyles create_default_styles(); + bool select_facename(const wxString &facename,bool update_text ); + bool on_shortcut_key(); + bool is_only_text_case() const; + void close(); + + std::string get_icon_filename(bool b_dark_mode) const override; + virtual std::string get_gizmo_entering_text() const{return "Enter Text gizmo";} + virtual std::string get_gizmo_leaving_text() const{return "Leave Text gizmo";} + bool wants_enter_leave_snapshots() const override { return true; } protected: virtual bool on_init() override; @@ -147,34 +188,103 @@ protected: void pop_button_style(); virtual void on_set_state() override; virtual void data_changed(bool is_serializing) override; + void on_set_hover_id() override; + void on_enable_grabber(unsigned int id) override; + void on_disable_grabber(unsigned int id) override; + bool on_mouse(const wxMouseEvent &mouse_event) override; + bool on_mouse_for_rotation(const wxMouseEvent &mouse_event); virtual CommonGizmosDataID on_get_requirements() const override; virtual void on_render_input_window(float x, float y, float bottom_limit); void show_tooltip_information(float x, float y); private: - void check_text_type(bool is_surface_text,bool is_keep_horizontal); + bool set_height(); + //ui + void draw_text_input(int width); + void draw_font_list(); + void draw_height(bool use_inch = false); + void draw_depth(bool use_inch); + void init_font_name_texture(); + void reinit_text_lines(unsigned count_lines = 0); + bool check(ModelVolumeType volume_type); + bool init_create(ModelVolumeType volume_type); + + template + bool revertible(const std::string &name, T &value, const T *default_value, const std::string &undo_tooltip, float undo_offset, Draw draw) const; + template + bool rev_input( + const std::string &name, T &value, const T *default_value, const std::string &undo_tooltip, T step, T step_fast, const char *format, ImGuiInputTextFlags flags = 0) const; + template + bool rev_input_mm(const std::string & name, + T & value, + const T * default_value, + const std::string & undo_tooltip, + T step, + T step_fast, + const char * format, + bool use_inch, + const std::optional &scale) const; + void load_old_font(); + void draw_style_list(float caption_size); + void draw_style_save_button(bool is_modified); + void draw_style_save_as_popup(); + void draw_style_add_button(bool is_modified); + void draw_delete_style_button(); + void update_boldness(); + void update_italic(); + void set_default_boldness(std::optional &boldness); + void draw_model_type(int caption_width); + void draw_surround_type(int caption_width); + void draw_rotation(int caption_size, int slider_width, int drag_left_width, int slider_icon_width); + +private: // ui + struct GuiCfg; + std::unique_ptr m_gui_cfg; + +private: + std::unique_ptr create_emboss_data_base(const std::string & text, + Emboss::StyleManager & style_manager, + //TextLinesModel & text_lines,//todo + const Selection & selection, + ModelVolumeType type, + std::shared_ptr> &cancel); + bool process(bool make_snapshot = true, std::optional volume_transformation = std::nullopt, bool update_text =true); + + ModelVolume *get_text_is_dragging(); + bool get_is_dragging(); + bool get_selection_is_text(); + bool update_text_tran_in_model_object(bool rewrite_text_tran = false); + void update_trafo_matrices(); + void update_cut_plane_dir(); + void switch_text_type(TextInfo::TextType type); + float get_angle_from_current_style(); + void volume_transformation_changed(); + void update_style_angle(ModelVolume *text_volume, float init_angle_degree, float roate_angle); + +private: void generate_text_tran_in_world(const Vec3d &text_normal_in_world, const Vec3d &text_position_in_world, float rotate_degree, Geometry::Transformation &tran); void use_fix_normal_position(); - void load_init_text(); + void load_init_text(bool first_open_text = false); void update_text_pos_normal(); - void update_font_status(); + bool filter_model_volume(ModelVolume* mv); + //void update_font_status(); void reset_text_info(); + float get_text_height(const std::string &text); void close_warning_flag_after_close_or_drag(); void update_text_normal_in_world(); - bool update_text_positions(const std::vector& texts); - TriangleMesh get_text_mesh(const char* text_str, const Vec3d &position, const Vec3d &normal, const Vec3d &text_up_dir); + //bool update_text_positions(); - bool update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector &trafo_matrices); - void generate_text_volume(bool is_temp = true); - void delete_temp_preview_text_volume(); + bool update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector &trafo_matrices, bool exclude_last = true); + bool generate_text_volume(); TextInfo get_text_info(); void load_from_text_info(const TextInfo &text_info); + bool is_old_text_info(const TextInfo &text_info); }; } // namespace GUI } // namespace Slic3r -#endif // slic3r_GLGizmoText_hpp_ \ No newline at end of file +#endif // slic3r_GLGizmoText_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 6d4b3d2..4fef3e3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -138,14 +138,20 @@ void SelectionInfo::on_release() int SelectionInfo::get_active_instance() const { - const Selection& selection = get_pool()->get_canvas()->get_selection(); + const auto& p_pool = get_pool(); + if (!p_pool) { + return -1; + } + + const auto& p_canvas = p_pool->get_canvas(); + if (!p_canvas) { + return -1; + } + + const Selection& selection = p_canvas->get_selection(); return selection.get_instance_idx(); } - - - - void InstancesHider::on_update() { const ModelObject* mo = get_pool()->selection_info()->model_object(); @@ -181,7 +187,7 @@ void InstancesHider::on_update() for (const TriangleMesh* mesh : meshes) { m_clippers.emplace_back(new MeshClipper); m_clippers.back()->set_plane(ClippingPlane(-Vec3d::UnitZ(), z_min)); - m_clippers.back()->set_mesh(*mesh); + m_clippers.back()->set_mesh(mesh->its); } m_old_meshes = meshes; } @@ -379,29 +385,24 @@ void ObjectClipper::on_update() // which mesh should be cut? std::vector meshes; std::vector trafos; - bool force_clipper_regeneration = false; - std::unique_ptr mc; Geometry::Transformation mc_tr; - if (!mc && meshes.empty()) { + if (meshes.empty()) { for (const ModelVolume *mv : mo->volumes) { meshes.emplace_back(&mv->mesh()); trafos.emplace_back(mv->get_transformation()); } } - if (mc || force_clipper_regeneration || meshes != m_old_meshes) { + if (meshes != m_old_meshes) { m_clippers.clear(); for (size_t i = 0; i < meshes.size(); ++i) { m_clippers.emplace_back(new MeshClipper, trafos[i]); - auto tri_mesh = new TriangleMesh(meshes[i]->its); - m_clippers.back().first->set_mesh(*tri_mesh); + m_clippers.back().first->set_mesh(meshes[i]->its); } m_old_meshes = std::move(meshes); - if (mc) { m_clippers.emplace_back(std::move(mc), mc_tr); } - m_active_inst_bb_radius = mo->instance_bounding_box(get_pool()->selection_info()->get_active_instance()).radius(); } } @@ -434,6 +435,7 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectorget_sla_shift(); std::vector ignore_idxs_local = ignore_idxs ? *ignore_idxs : std::vector(); + double z_min; if (canvas->get_gizmos_manager().is_paint_gizmo()) { z_min = -FLT_MAX; @@ -481,9 +483,21 @@ void CommonGizmosDataObjects::ObjectClipper::set_behaviour(bool hide_clipped, bo void ObjectClipper::set_position(double pos, bool keep_normal, bool vertical_normal) { - const ModelObject *mo = get_pool()->selection_info()->model_object(); - int active_inst = get_pool()->selection_info()->get_active_instance(); - double z_shift = get_pool()->selection_info()->get_sla_shift(); + const auto p_pool = get_pool(); + if (!p_pool) { + return; + } + + const auto& p_selection_info = p_pool->selection_info(); + if (!p_selection_info) { + return; + } + const ModelObject* mo = p_selection_info->model_object(); + if (!mo) { + return; + } + int active_inst = p_selection_info->get_active_instance(); + double z_shift = p_selection_info->get_sla_shift(); if (active_inst < 0) { return; } @@ -494,8 +508,8 @@ void ObjectClipper::set_position(double pos, bool keep_normal, bool vertical_nor normal = (keep_normal && m_clp) ? m_clp->get_normal() : -wxGetApp().plater()->get_camera().get_dir_forward(); } Vec3d center; - if (get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { - const SelectionInfo *sel_info = get_pool()->selection_info(); + if (p_pool->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + const SelectionInfo *sel_info = p_selection_info; auto trafo = mo->instances[sel_info->get_active_instance()]->get_assemble_transformation(); auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); center = trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0); @@ -505,7 +519,7 @@ void ObjectClipper::set_position(double pos, bool keep_normal, bool vertical_nor float dist = normal.dot(center); if (pos < 0.) - pos = m_clp_ratio; + pos = 0.; m_clp_ratio = pos; m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius) - m_clp_ratio * 2 * m_active_inst_bb_radius))); @@ -594,7 +608,7 @@ void SupportsClipper::on_update() // The timestamp has changed. m_clipper.reset(new MeshClipper); // The mesh should already have the shared vertices calculated. - m_clipper->set_mesh(print_object->support_mesh()); + m_clipper->set_mesh(print_object->support_mesh().its); m_old_timestamp = timestamp; } } @@ -750,7 +764,7 @@ void ModelObjectsClipper::on_update() m_clippers.clear(); for (const TriangleMesh* mesh : meshes) { m_clippers.emplace_back(new MeshClipper); - m_clippers.back()->set_mesh(*mesh); + m_clippers.back()->set_mesh(mesh->its); } m_old_meshes = meshes; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 1bfa2e8..abcbeb9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/Plater.hpp" #include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/GUI/NotificationManager.hpp" +#include "slic3r/GUI/GLToolbar.hpp" #include "slic3r/GUI/Gizmos/GLGizmoMove.hpp" #include "slic3r/GUI/Gizmos/GLGizmoScale.hpp" @@ -22,6 +23,7 @@ #include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp" #include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp" #include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp" #include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp" #include "slic3r/GUI/Gizmos/GLGizmoText.hpp" #include "slic3r/GUI/Gizmos/GLGizmoSVG.hpp" @@ -46,9 +48,7 @@ const float GLGizmosManager::Default_Icons_Size = 64; GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) : m_parent(parent) , m_enabled(false) - , m_icons_texture_dirty(true) , m_current(Undefined) - , m_tooltip("") , m_serializing(false) //QDS: GUI refactor: add object manipulation in gizmo , m_object_manipulation(parent) @@ -76,169 +76,36 @@ std::vector GLGizmosManager::get_selectable_idxs() const return out; } -//QDS: GUI refactor: GLToolbar&&Gizmo adjust -//when judge the mouse position, {0, 0} is at the left-up corner, and no need to multiply camera_zoom -size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const -{ - if (! m_enabled) - return Undefined; - - float cnv_h = (float)m_parent.get_canvas_size().get_height(); - float height = get_scaled_total_height(); - float icons_size = m_layout.scaled_icons_size(); - float border = m_layout.scaled_border(); - - //QDS: GUI refactor: GLToolbar&&Gizmo adjust - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float width = get_scaled_total_width(); -#if QDS_TOOLBAR_ON_TOP - //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; - float top_x = 0; - if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { - top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width()); - } else { - const float separator_width = m_parent.get_separator_toolbar_width(); - - top_x = m_parent.get_main_toolbar_offset(); - top_x += m_parent.get_main_toolbar_width() + separator_width / 2 + border; - } - float top_y = 0; - float stride_x = m_layout.scaled_stride_x(); - - // is mouse vertically in the area? - //if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) { - if (((top_y + border) <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= (top_y + border + icons_size))) { - // which icon is it on? - int from_left = (float) mouse_pos(0) - top_x < 0 ? -1 : (int) ((float) mouse_pos(0) - top_x) / stride_x; - if (from_left < 0) - return Undefined; - // is it really on the icon or already past the border? - if ((float)mouse_pos(0) <= top_x + from_left * stride_x + icons_size) { - std::vector selectable = get_selectable_idxs(); - if (from_left < selectable.size()) - return selectable[from_left]; - } - } -#else - //float top_y = 0.5f * (cnv_h - height) + border; - float top_x = cnv_w - width; - float top_y = 0.5f * (cnv_h - height + m_parent.get_main_toolbar_height() - m_parent.get_assemble_view_toolbar_width()) + border; - float stride_y = m_layout.scaled_stride_y(); - - // is mouse horizontally in the area? - //if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) { - if (((top_x + border) <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= (top_x + border + icons_size))) { - // which icon is it on? - size_t from_top = (size_t)((float)mouse_pos(1) - top_y) / stride_y; - if (from_top < 0) - return Undefined; - // is it really on the icon or already past the border? - if ((float)mouse_pos(1) <= top_y + from_top * stride_y + icons_size) { - std::vector selectable = get_selectable_idxs(); - if (from_top < selectable.size()) - return selectable[from_top]; - } - } -#endif - - return Undefined; -} - -void GLGizmosManager::switch_gizmos_icon_filename() -{ - m_background_texture.metadata.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; - m_background_texture.metadata.left = 16; - m_background_texture.metadata.top = 16; - m_background_texture.metadata.right = 16; - m_background_texture.metadata.bottom = 16; - if (!m_background_texture.metadata.filename.empty()) - m_background_texture.texture.load_from_file(resources_dir() + "/images/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false); - - for (auto& gizmo : m_gizmos) { - gizmo->on_change_color_mode(m_is_dark); - switch (gizmo->get_sprite_id()) - { - case(EType::Move): - gizmo->set_icon_filename(m_is_dark ? "toolbar_move_dark.svg" : "toolbar_move.svg"); - break; - case(EType::Rotate): - gizmo->set_icon_filename(m_is_dark ? "toolbar_rotate_dark.svg" : "toolbar_rotate.svg"); - break; - case(EType::Scale): - gizmo->set_icon_filename(m_is_dark ? "toolbar_scale_dark.svg" : "toolbar_scale.svg"); - break; - case(EType::Flatten): - gizmo->set_icon_filename(m_is_dark ? "toolbar_flatten_dark.svg" : "toolbar_flatten.svg"); - break; - case(EType::Cut): - gizmo->set_icon_filename(m_is_dark ? "toolbar_cut_dark.svg" : "toolbar_cut.svg"); - break; - case(EType::FdmSupports): - gizmo->set_icon_filename(m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg"); - break; - case(EType::Seam): - gizmo->set_icon_filename(m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg"); - break; - case(EType::Text): - gizmo->set_icon_filename(m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg"); - break; - case(EType::MmuSegmentation): - gizmo->set_icon_filename(m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg"); - break; - case(EType::MeshBoolean): - gizmo->set_icon_filename(m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg"); - break; - case (EType::Measure): - gizmo->set_icon_filename(m_is_dark ? "toolbar_measure_dark.svg" : "toolbar_measure.svg"); - break; - case (EType::Assembly): - gizmo->set_icon_filename(m_is_dark ? "toolbar_assembly_dark.svg" : "toolbar_assembly.svg"); - break; - } - - } -} - bool GLGizmosManager::init() { if (!m_gizmos.empty()) return true; init_icon_textures(); - m_background_texture.metadata.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; - m_background_texture.metadata.left = 16; - m_background_texture.metadata.top = 16; - m_background_texture.metadata.right = 16; - m_background_texture.metadata.bottom = 16; - - if (!m_background_texture.metadata.filename.empty()) - { - if (!m_background_texture.texture.load_from_file(resources_dir() + "/images/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false)) - return false; - } - // Order of gizmos in the vector must match order in EType! //QDS: GUI refactor: add obj manipulation m_gizmos.clear(); unsigned int sprite_id = 0; - m_gizmos.emplace_back(new GLGizmoMove3D(m_parent, m_is_dark ? "toolbar_move_dark.svg" : "toolbar_move.svg", EType::Move, &m_object_manipulation)); - m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, m_is_dark ? "toolbar_rotate_dark.svg" : "toolbar_rotate.svg", EType::Rotate, &m_object_manipulation)); - m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, m_is_dark ? "toolbar_scale_dark.svg" : "toolbar_scale.svg", EType::Scale, &m_object_manipulation)); - m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, m_is_dark ? "toolbar_flatten_dark.svg" : "toolbar_flatten.svg", EType::Flatten)); - m_gizmos.emplace_back(new GLGizmoAdvancedCut(m_parent, m_is_dark ? "toolbar_cut_dark.svg" : "toolbar_cut.svg", EType::Cut)); - m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg", EType::MeshBoolean)); - m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg", EType::FdmSupports)); - m_gizmos.emplace_back(new GLGizmoSeam(m_parent, m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg", EType::Seam)); - m_gizmos.emplace_back(new GLGizmoText(m_parent, m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg", EType::Text)); + m_gizmos.emplace_back(new GLGizmoMove3D(m_parent, EType::Move, &m_object_manipulation)); + m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, EType::Rotate, &m_object_manipulation)); + m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, EType::Scale, &m_object_manipulation)); + m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, EType::Flatten)); + m_gizmos.emplace_back(new GLGizmoAdvancedCut(m_parent, EType::Cut)); + m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, EType::MeshBoolean)); + m_gizmos.emplace_back(new GLGizmoAssembly(m_parent, EType::Assembly)); + m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, EType::MmuSegmentation)); + m_gizmos.emplace_back(new GLGizmoText(m_parent, EType::Text)); m_gizmos.emplace_back(new GLGizmoSVG(m_parent, EType::Svg)); - m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg", EType::MmuSegmentation)); - m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, m_is_dark ? "toolbar_measure_dark.svg" : "toolbar_measure.svg", EType::Measure)); - m_gizmos.emplace_back(new GLGizmoAssembly(m_parent, m_is_dark ? "toolbar_assembly_dark.svg" : "toolbar_assembly.svg", EType::Assembly)); - m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, "reduce_triangles.svg", EType::Simplify)); - m_gizmos.emplace_back(new GLGizmoBrimEars(m_parent, m_is_dark ? "toolbar_brimears_dark.svg" : "toolbar_brimears.svg", EType::BrimEars)); - //m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", sprite_id++)); - //m_gizmos.emplace_back(new GLGizmoFaceDetector(m_parent, "face recognition.svg", sprite_id++)); - //m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++)); + m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, EType::FdmSupports)); + m_gizmos.emplace_back(new GLGizmoSeam(m_parent, EType::Seam)); + m_gizmos.emplace_back(new GLGizmoBrimEars(m_parent, EType::BrimEars)); + m_gizmos.emplace_back(new GLGizmoFuzzySkin(m_parent, EType::FuzzySkin)); + m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, EType::Measure)); + m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, EType::Simplify)); + + //m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, sprite_id++)); + //m_gizmos.emplace_back(new GLGizmoFaceDetector(m_parent, sprite_id++)); + //m_gizmos.emplace_back(new GLGizmoHollow(m_parent, sprite_id++)); m_common_gizmos_data.reset(new CommonGizmosDataPool(&m_parent)); if(!m_assemble_view_data) @@ -319,7 +186,7 @@ bool GLGizmosManager::init_icon_textures() else return false; - if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_B.svg", 20, 20, texture_id)) + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_B.svg", 20, 20, texture_id)) icon_list.insert(std::make_pair((int)IC_TEXT_B, texture_id)); else return false; @@ -342,45 +209,6 @@ bool GLGizmosManager::init_icon_textures() return true; } -float GLGizmosManager::get_layout_scale() -{ - return m_layout.scale; -} - -bool GLGizmosManager::init_arrow(const BackgroundTexture::Metadata& arrow_texture) -{ - if (m_arrow_texture.texture.get_id() != 0) - return true; - - std::string path = resources_dir() + "/images/"; - bool res = false; - - if (!arrow_texture.filename.empty()) - res = m_arrow_texture.texture.load_from_svg_file(path + arrow_texture.filename, false, false, false, 1000); - if (res) - m_arrow_texture.metadata = arrow_texture; - - return res; -} - -void GLGizmosManager::set_overlay_icon_size(float size) -{ - if (m_layout.icons_size != size) - { - m_layout.icons_size = size; - m_icons_texture_dirty = true; - } -} - -void GLGizmosManager::set_overlay_scale(float scale) -{ - if (m_layout.scale != scale) - { - m_layout.scale = scale; - m_icons_texture_dirty = true; - } -} - void GLGizmosManager::refresh_on_off_state() { if (m_serializing || m_current == Undefined || m_gizmos.empty()) @@ -402,7 +230,8 @@ void GLGizmosManager::reset_all_states() open_gizmo(current); activate_gizmo(Undefined); - m_hover = Undefined; + //do not clear hover state, as Emboss gizmo can be used without selection + //m_hover = Undefined; } bool GLGizmosManager::open_gizmo(EType type) @@ -469,9 +298,8 @@ void GLGizmosManager::update_data() { if (!m_enabled) return; - + wxBusyCursor wait; const Selection& selection = m_parent.get_selection(); - if (m_common_gizmos_data) { m_common_gizmos_data->update(get_current() ? get_current()->get_requirements() @@ -501,7 +329,7 @@ bool GLGizmosManager::is_running() const bool GLGizmosManager::handle_shortcut(int key) { - if (!m_enabled || m_parent.get_selection().is_empty()) + if (!m_enabled) return false; auto it = std::find_if(m_gizmos.begin(), m_gizmos.end(), @@ -514,6 +342,13 @@ bool GLGizmosManager::handle_shortcut(int key) if (it == m_gizmos.end()) return false; + // allowe open shortcut even when selection is empty + if (Text == it - m_gizmos.begin()) { + if (dynamic_cast(m_gizmos[Text].get())->on_shortcut_key()) { + return true; + } + } + EType gizmo_type = EType(it - m_gizmos.begin()); return open_gizmo(gizmo_type); } @@ -604,14 +439,13 @@ Vec3d GLGizmosManager::get_flattening_normal() const return dynamic_cast(m_gizmos[Flatten].get())->get_flattening_normal(); } -bool GLGizmosManager::is_gizmo_activable_when_single_full_instance() { +bool GLGizmosManager::is_gizmo_activable_when_single_full_instance() +{ if (get_current_type() == GLGizmosManager::EType::Flatten || get_current_type() == GLGizmosManager::EType::Cut || get_current_type() == GLGizmosManager::EType::MeshBoolean || get_current_type() == GLGizmosManager::EType::Text || - get_current_type() == GLGizmosManager::EType::Seam || - get_current_type() == GLGizmosManager::EType::FdmSupports || - get_current_type() == GLGizmosManager::EType::MmuSegmentation || + is_paint_gizmo() || get_current_type() == GLGizmosManager::EType::Simplify ) { return true; @@ -623,9 +457,7 @@ bool GLGizmosManager::is_gizmo_click_empty_not_exit() { if (get_current_type() == GLGizmosManager::EType::Cut || get_current_type() == GLGizmosManager::EType::MeshBoolean || - get_current_type() == GLGizmosManager::EType::Seam || - get_current_type() == GLGizmosManager::EType::FdmSupports || - get_current_type() == GLGizmosManager::EType::MmuSegmentation || + is_paint_gizmo() || get_current_type() == GLGizmosManager::EType::Measure || get_current_type() == GLGizmosManager::EType::Assembly) { return true; @@ -633,16 +465,23 @@ bool GLGizmosManager::is_gizmo_click_empty_not_exit() return false; } -bool GLGizmosManager::is_show_only_active_plate() -{ - if (get_current_type() == GLGizmosManager::EType::Cut || - get_current_type() == GLGizmosManager::EType::Text) { +bool GLGizmosManager::is_only_text_volume() const { + auto gizmo_text = dynamic_cast(get_current()); + if (gizmo_text->is_only_text_case()) { return true; } return false; } -bool GLGizmosManager::is_ban_move_glvolume() +bool GLGizmosManager::is_show_only_active_plate() const +{ + if (get_current_type() == GLGizmosManager::EType::Cut) { + return true; + } + return false; +} + +bool GLGizmosManager::is_ban_move_glvolume() const { auto current_type = get_current_type(); if (current_type == GLGizmosManager::EType::Undefined || @@ -654,8 +493,6 @@ bool GLGizmosManager::is_ban_move_glvolume() return true; } - -//1.9.5 bool GLGizmosManager::get_gizmo_active_condition(GLGizmosManager::EType type) { if (auto cur_gizmo = get_gizmo(type)) { return cur_gizmo->is_activable(); @@ -663,6 +500,13 @@ bool GLGizmosManager::get_gizmo_active_condition(GLGizmosManager::EType type) { return false; } +void GLGizmosManager::update_show_only_active_plate() +{ + if (is_show_only_active_plate()) { + check_object_located_outside_plate(); + } +} + void GLGizmosManager::check_object_located_outside_plate(bool change_plate) { PartPlateList &plate_list = wxGetApp().plater()->get_partplate_list(); @@ -702,42 +546,24 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p if (!m_enabled || m_gizmos.empty()) return false; - if (m_current == SlaSupports) - return dynamic_cast(m_gizmos[SlaSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Hollow) - return dynamic_cast(m_gizmos[Hollow].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == FdmSupports) - return dynamic_cast(m_gizmos[FdmSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Seam) - return dynamic_cast(m_gizmos[Seam].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == MmuSegmentation) - return dynamic_cast(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Text) - return dynamic_cast(m_gizmos[Text].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Svg) - return dynamic_cast(m_gizmos[Svg].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Measure) - return dynamic_cast(m_gizmos[Measure].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Assembly) - return dynamic_cast(m_gizmos[Assembly].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == Cut) - return dynamic_cast(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == MeshBoolean) - return dynamic_cast(m_gizmos[MeshBoolean].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else if (m_current == BrimEars) - return dynamic_cast(m_gizmos[BrimEars].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); - else - return false; + for (size_t i = 0; i < m_gizmos.size(); ++i) { + if (m_gizmos[i]->get_sprite_id() == static_cast(m_current)) { + return m_gizmos[i]->gizmo_event(action, mouse_position, shift_down, alt_down, control_down); + } + } + + return false; } bool GLGizmosManager::is_paint_gizmo() const { return m_current == EType::FdmSupports || + m_current == EType::FuzzySkin || m_current == EType::MmuSegmentation || m_current == EType::Seam; } -bool GLGizmosManager::is_allow_select_all() { +bool GLGizmosManager::is_allow_select_all() const { if (m_current == Undefined || m_current == EType::Move|| m_current == EType::Rotate || m_current == EType::Scale) { @@ -746,6 +572,27 @@ bool GLGizmosManager::is_allow_select_all() { return false; } +bool GLGizmosManager::is_allow_show_volume_highlight_outline() const +{ + if (m_current == EType::Cut) { + return false; + } + return true; +} + +bool GLGizmosManager::is_allow_drag_volume() const +{ + if (m_current == EType::Cut) { return false; } + return true; +} + +bool GLGizmosManager::is_allow_mouse_drag_selected() const +{ + if (m_current == Measure || m_current == Assembly) + return false; + return true; +} + ClippingPlane GLGizmosManager::get_clipping_plane() const { if (! m_common_gizmos_data @@ -816,22 +663,8 @@ void GLGizmosManager::render_current_gizmo_for_picking_pass() const m_gizmos[m_current]->render_for_picking(); } -void GLGizmosManager::render_overlay() -{ - if (!m_enabled) - return; - - if (m_icons_texture_dirty) - generate_icons_texture(); - - do_render_overlay(); -} - std::string GLGizmosManager::get_tooltip() const { - if (!m_tooltip.empty()) - return m_tooltip; - const GLGizmoBase* curr = get_current(); return (curr != nullptr) ? curr->get_tooltip() : ""; } @@ -840,7 +673,7 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt) { bool processed = false; - if (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == BrimEars) { + if (m_current == SlaSupports || m_current == Hollow || is_paint_gizmo() || m_current == BrimEars) { float rot = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta(); if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown() // QDS @@ -882,16 +715,10 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) } } else if (evt.Moving()) { - m_tooltip = update_hover_state(mouse_pos); - if (m_current == MmuSegmentation || m_current == FdmSupports || m_current == Text || m_current == BrimEars || m_current == Svg) - // QDS + if (is_paint_gizmo() ||m_current == Text || m_current == BrimEars || m_current == Svg) gizmo_event(SLAGizmoEventType::Moving, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()); } else if (evt.LeftUp()) { - if (m_mouse_capture.left) { - processed = true; - m_mouse_capture.left = false; - } - else if (is_dragging()) { + if (is_dragging()) { switch (m_current) { case Move: { wxGetApp().plater()->take_snapshot(_u8L("Tool-Move"), UndoRedo::SnapshotType::GizmoAction); @@ -924,35 +751,12 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) processed = true; } -// else -// return false; } else if (evt.MiddleUp()) { - if (m_mouse_capture.middle) { - processed = true; - m_mouse_capture.middle = false; - } - else - return false; } else if (evt.RightUp()) { - if (pending_right_up) { - pending_right_up = false; - return true; - } - if (m_mouse_capture.right) { - processed = true; - m_mouse_capture.right = false; - } -// else -// return false; } else if (evt.Dragging() && !is_dragging()) { - if (m_mouse_capture.any()) - // if the button down was done on this toolbar, prevent from dragging into the scene - processed = true; -// else -// return false; } else if (evt.Dragging() && is_dragging()) { if (!m_parent.get_wxglcanvas()->HasCapture()) @@ -1041,130 +845,89 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) processed = true; } - if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined) { - // mouse is outside the toolbar - m_tooltip.clear(); + if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) { + if ((m_current == SlaSupports || m_current == Hollow || m_current == Svg || is_paint_gizmo() || m_current == Text || m_current == Cut || m_current == MeshBoolean || + m_current == BrimEars) + && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown())) + // the gizmo got the event and took some action, there is no need to do anything more + processed = true; + else if (!selection.is_empty() && grabber_contains_mouse()) { + if (is_allow_mouse_drag_selected()) { - if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) { - if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Svg || - m_current == Seam || m_current == MmuSegmentation || m_current == Text || m_current == Cut || m_current == MeshBoolean || m_current == BrimEars) - && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown())) - // the gizmo got the event and took some action, there is no need to do anything more - processed = true; - else if (!selection.is_empty() && grabber_contains_mouse()) { - if (!(m_current == Measure || m_current == Assembly)) { + selection.start_dragging(); + start_dragging(); - selection.start_dragging(); - start_dragging(); + // Let the plater know that the dragging started + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); - // Let the plater know that the dragging started - m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); - - if (m_current == Flatten) { - // Rotate the object so the normal points downward: - m_parent.do_flatten(get_flattening_normal(), L("Tool-Lay on Face")); - // QDS - // wxGetApp().obj_manipul()->set_dirty(); - } - - m_parent.set_as_dirty(); + if (m_current == Flatten) { + // Rotate the object so the normal points downward: + m_parent.do_flatten(get_flattening_normal(), L("Tool-Lay on Face")); + // QDS + // wxGetApp().obj_manipul()->set_dirty(); } - processed = true; + + m_parent.set_as_dirty(); } - } - else if (evt.RightDown() && selected_object_idx != -1 && (m_current == SlaSupports || m_current == Hollow || m_current == BrimEars) - && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { - // we need to set the following right up as processed to avoid showing the context menu if the user release the mouse over the object - pending_right_up = true; - // event was taken care of by the SlaSupports gizmo processed = true; } - else if (evt.RightDown() && !control_down && selected_object_idx != -1 - && (m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut) - && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { - // event was taken care of by the FdmSupports / Seam / MMUPainting gizmo - processed = true; - } - else if (evt.Dragging() && m_parent.get_move_volume_id() != -1 - && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == BrimEars)) - // don't allow dragging objects with the Sla gizmo on - processed = true; - //1.9.5 - else if (evt.Dragging() && !control_down - && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut || m_current == BrimEars) - && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown())) { - // the gizmo got the event and took some action, no need to do anything more here - m_parent.set_as_dirty(); - processed = true; - } - else if (evt.Dragging() && control_down && (evt.LeftIsDown() || evt.RightIsDown())) { - // CTRL has been pressed while already dragging -> stop current action - if (evt.LeftIsDown()) - gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); - else if (evt.RightIsDown()) - gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); - } - else if (evt.LeftUp() - && (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == Cut || m_current == BrimEars) - && gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down) - && !m_parent.is_mouse_dragging()) { - // in case SLA/FDM gizmo is selected, we just pass the LeftUp event and stop processing - neither - // object moving or selecting is suppressed in that case - processed = true; - } else if (evt.LeftUp() && m_current == Svg && m_gizmos[m_current]->get_hover_id() != -1) { - // QDS - // wxGetApp().obj_manipul()->set_dirty(); - processed = true; - } - else if (evt.LeftUp() && m_current == Flatten && m_gizmos[m_current]->get_hover_id() != -1) { - // to avoid to loose the selection when user clicks an the white faces of a different object while the Flatten gizmo is active - selection.stop_dragging(); - // QDS - //wxGetApp().obj_manipul()->set_dirty(); - processed = true; - } - else if (evt.RightUp() && m_current != EType::Undefined && !m_parent.is_mouse_dragging() ) { - gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down); - processed = true; - } - else if (evt.LeftUp()) { - selection.stop_dragging(); - // QDS - //wxGetApp().obj_manipul()->set_dirty(); - } } - else { - // mouse inside toolbar - if (evt.LeftDown() || evt.LeftDClick()) { - m_mouse_capture.left = true; - m_mouse_capture.parent = &m_parent; - processed = true; - if (!selection.is_empty()) { - update_on_off_state(mouse_pos); - update_data(); - m_parent.set_as_dirty(); - try { - if ((int)m_hover >= 0 && (int)m_hover < m_gizmos.size()) { - std::string name = get_name_from_gizmo_etype(m_hover); - int count = m_gizmos[m_hover]->get_count(); - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) { - agent->track_update_property(name, std::to_string(count)); - } - } - } - catch (...) {} - } - } - else if (evt.MiddleDown()) { - m_mouse_capture.middle = true; - m_mouse_capture.parent = &m_parent; - } - else if (evt.RightDown()) { - m_mouse_capture.right = true; - m_mouse_capture.parent = &m_parent; - return true; - } + else if (evt.RightDown() && selected_object_idx != -1 && (m_current == SlaSupports || m_current == Hollow || m_current == BrimEars) + && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { + // we need to set the following right up as processed to avoid showing the context menu if the user release the mouse over the object + pending_right_up = true; + // event was taken care of by the SlaSupports gizmo + processed = true; + } + else if (evt.RightDown() && !control_down && selected_object_idx != -1 && (is_paint_gizmo() || m_current == Cut) + && gizmo_event(SLAGizmoEventType::RightDown, mouse_pos)) { + // event was taken care of by the paint_gizmo + processed = true; + } + else if (evt.Dragging() && m_parent.get_move_volume_id() != -1 && (m_current == SlaSupports || m_current == Hollow || is_paint_gizmo() || m_current == BrimEars)) + // don't allow dragging objects with the Sla gizmo on + processed = true; + else if (evt.Dragging() && !control_down && (m_current == SlaSupports || m_current == Hollow || is_paint_gizmo() || m_current == Cut || m_current == BrimEars) + && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown())) { + // the gizmo got the event and took some action, no need to do anything more here + m_parent.set_as_dirty(); + processed = true; + } + else if (evt.Dragging() && control_down && (evt.LeftIsDown() || evt.RightIsDown())) { + // CTRL has been pressed while already dragging -> stop current action + if (evt.LeftIsDown()) + gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); + else if (evt.RightIsDown()) + gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), true); + } + else if (evt.LeftUp() + && (m_current == SlaSupports || m_current == Hollow || is_paint_gizmo() || m_current == Cut || m_current == BrimEars) + && gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down) + && !m_parent.is_mouse_dragging()) { + // in case SLA/FDM gizmo is selected, we just pass the LeftUp event and stop processing - neither + // object moving or selecting is suppressed in that case + processed = true; + } + else if (evt.LeftUp() && m_current == Svg && m_gizmos[m_current]->get_hover_id() != -1) { + // QDS + // wxGetApp().obj_manipul()->set_dirty(); + processed = true; + } + else if (evt.LeftUp() && m_current == Flatten && m_gizmos[m_current]->get_hover_id() != -1) { + // to avoid to loose the selection when user clicks an the white faces of a different object while the Flatten gizmo is active + selection.stop_dragging(); + // QDS + //wxGetApp().obj_manipul()->set_dirty(); + processed = true; + } + else if (evt.RightUp() && m_current != EType::Undefined && !m_parent.is_mouse_dragging()) { + gizmo_event(SLAGizmoEventType::RightUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), control_down); + processed = true; + } + else if (evt.LeftUp()) { + selection.stop_dragging(); + // QDS + //wxGetApp().obj_manipul()->set_dirty(); } return processed; @@ -1223,24 +986,6 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt) } break; } - //case WXK_RETURN: - //{ - // if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::ApplyChanges)) - // processed = true; - - // break; - //} - - //case 'r' : - //case 'R' : - //{ - //if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && gizmo_event(SLAGizmoEventType::ResetClippingPlane)) - // processed = true; - - //break; - //} - - //case WXK_BACK: case WXK_DELETE: { if ((m_current == Cut || m_current == Measure || m_current == Assembly || m_current == BrimEars) && gizmo_event(SLAGizmoEventType::Delete)) @@ -1426,10 +1171,19 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) } } } + } else if (m_current == FuzzySkin) { + GLGizmoFuzzySkin *fuzzy_skin = dynamic_cast(get_current()); + if (fuzzy_skin != nullptr && (keyCode == 'F' || keyCode == 'S' || keyCode == 'C' || keyCode == 'T')) { + processed = fuzzy_skin->on_key_down_select_tool_type(keyCode); + } + if (processed) { + // force extra frame to automatically update window size + wxGetApp().imgui()->set_requires_extra_frame(); + } } else if (m_current == FdmSupports) { GLGizmoFdmSupports* fdm_support = dynamic_cast(get_current()); - if (fdm_support != nullptr && keyCode == 'F' || keyCode == 'S' || keyCode == 'C' || keyCode == 'G') { + if (fdm_support != nullptr && (keyCode == 'F' || keyCode == 'S' || keyCode == 'C' || keyCode == 'G')) { processed = fdm_support->on_key_down_select_tool_type(keyCode); } if (processed) { @@ -1439,7 +1193,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt) } else if (m_current == Seam) { GLGizmoSeam* seam = dynamic_cast(get_current()); - if (seam != nullptr && keyCode == 'S' || keyCode == 'C') { + if (seam != nullptr && (keyCode == 'S' || keyCode == 'C')) { processed = seam->on_key_down_select_tool_type(keyCode); } if (processed) { @@ -1490,258 +1244,121 @@ BoundingBoxf3 GLGizmosManager::get_bounding_box() const return t_aabb; } -void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border) const +void GLGizmosManager::add_toolbar_items(const std::shared_ptr& p_toolbar, uint8_t& sprite_id, const std::function& p_callback) { - unsigned int tex_id = m_background_texture.texture.get_id(); - float tex_width = (float)m_background_texture.texture.get_width(); - float tex_height = (float)m_background_texture.texture.get_height(); - if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0)) - { - //QDS: GUI refactor: remove the corners of gizmo - float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; - float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; - - float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width; - float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width; - float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height; - float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height; - - GLTexture::render_sub_texture(tex_id, left, right, bottom, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - /* - float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; - float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; - - float internal_left = left + border; - float internal_right = right - border; - float internal_top = top - border; - float internal_bottom = bottom + border; - - // float left_uv = 0.0f; - float right_uv = 1.0f; - float top_uv = 1.0f; - float bottom_uv = 0.0f; - - float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width; - float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width; - float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height; - float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height; - - // top-left corner - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - // top edge - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } }); - - // top-right corner - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } }); - - // center-left edge - GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - // center - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - // center-right edge - GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } }); - - // bottom-left corner - GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } }); - - // bottom edge - GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } }); - - // bottom-right corner - GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } }); - */ + if (!p_toolbar) { + return; + } + + if (m_gizmos.empty()) { + return; } -} -void GLGizmosManager::render_arrow(const GLCanvas3D& parent, EType highlighted_type) const -{ std::vector selectable_idxs = get_selectable_idxs(); - if (selectable_idxs.empty()) - return; - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - float height = get_scaled_total_height(); - float zoomed_border = m_layout.scaled_border() * inv_zoom; - float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom; - float zoomed_top_y = (0.5f * height) * inv_zoom; - zoomed_top_x += zoomed_border; - zoomed_top_y -= zoomed_border; - float icons_size = m_layout.scaled_icons_size(); - float zoomed_icons_size = icons_size * inv_zoom; - float zoomed_stride_y = m_layout.scaled_stride_y() * inv_zoom; - for (size_t idx : selectable_idxs) + + auto p_gizmo_manager = this; + for (size_t i = 0; i < m_gizmos.size(); ++i) { - if (idx == highlighted_type) { - int tex_width = m_icons_texture.get_width(); - int tex_height = m_icons_texture.get_height(); - unsigned int tex_id = m_arrow_texture.texture.get_id(); - float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f; - float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f; - - float internal_left_uv = (float)m_arrow_texture.metadata.left * inv_tex_width; - float internal_right_uv = 1.0f - (float)m_arrow_texture.metadata.right * inv_tex_width; - float internal_top_uv = 1.0f - (float)m_arrow_texture.metadata.top * inv_tex_height; - float internal_bottom_uv = (float)m_arrow_texture.metadata.bottom * inv_tex_height; - - float arrow_sides_ratio = (float)m_arrow_texture.texture.get_height() / (float)m_arrow_texture.texture.get_width(); - - GLTexture::render_sub_texture(tex_id, zoomed_top_x + zoomed_icons_size * 1.2f, zoomed_top_x + zoomed_icons_size * 1.2f + zoomed_icons_size * 2.2f * arrow_sides_ratio, zoomed_top_y - zoomed_icons_size * 1.6f , zoomed_top_y + zoomed_icons_size * 0.6f, { { internal_left_uv, internal_bottom_uv }, { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, internal_bottom_uv } }); - break; + const auto idx = i; + if (!m_gizmos[idx]) { + continue; } - zoomed_top_y -= zoomed_stride_y; + + if (m_gizmos[idx]->get_sprite_id() == (unsigned int)EType::Measure) { + p_callback(sprite_id); + } + + GLToolbarItem::Data item; + + item.name = convert_gizmo_type_to_string(static_cast(m_gizmos[idx]->get_sprite_id())); + item.icon_filename_callback = [p_gizmo_manager, idx](bool is_dark_mode)->std::string { + return p_gizmo_manager->m_gizmos[idx]->get_icon_filename(is_dark_mode); + }; + item.tooltip = ""; + item.sprite_id = sprite_id++; + const auto t_type = m_gizmos[idx]->get_sprite_id(); + item.left.action_callback = [p_gizmo_manager, t_type]() { + p_gizmo_manager->on_click(t_type); + }; + item.enabling_callback = [p_gizmo_manager, idx]()->bool { + return p_gizmo_manager->m_gizmos[idx]->is_activable(); + }; + item.on_hover = [p_gizmo_manager, idx]()->std::string { + return p_gizmo_manager->on_hover(idx); + }; + item.left.toggable = true; + item.b_toggle_disable_others = false; + item.b_toggle_affectable = false; + item.left.render_callback = [p_gizmo_manager, idx](float left, float right, float bottom, float top, float toolbar_height) { + if (p_gizmo_manager->get_current_type() != idx) { + return; + } + float cnv_h = (float)p_gizmo_manager->m_parent.get_canvas_size().get_height(); + p_gizmo_manager->m_gizmos[idx]->render_input_window(left, toolbar_height, cnv_h); + }; + item.pressed_recheck_callback = [p_gizmo_manager, t_type]()->bool { + return p_gizmo_manager->m_current == t_type; + }; + const bool b_is_selectable = (std::find(selectable_idxs.begin(), selectable_idxs.end(), idx) != selectable_idxs.end()); + item.visibility_callback = [p_gizmo_manager, idx, b_is_selectable]()->bool { + bool rt = b_is_selectable; + if (idx == EType::Svg) { + rt = rt && (p_gizmo_manager->m_current == EType::Svg); + } + else if (idx == EType::Text) { + rt = rt && p_gizmo_manager->m_current != EType::Svg; + } + return rt; + }; + item.visible = b_is_selectable; + p_toolbar->add_item(item); } } -//QDS: GUI refactor: GLToolbar&&Gizmo adjust -//when rendering, {0, 0} is at the center, {-0.5, 0.5} at the left-top -void GLGizmosManager::do_render_overlay() const +std::string GLGizmosManager::convert_gizmo_type_to_string(Slic3r::GUI::GLGizmosManager::EType t_type) { - std::vector selectable_idxs = get_selectable_idxs(); - if (selectable_idxs.empty()) - return; - - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float cnv_h = (float)m_parent.get_canvas_size().get_height(); - float zoom = (float)wxGetApp().plater()->get_camera().get_zoom(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - - float height = get_scaled_total_height(); - float width = get_scaled_total_width(); - float zoomed_border = m_layout.scaled_border() * inv_zoom; - - float zoomed_top_x; - if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { - zoomed_top_x = 0.5f * m_parent.get_assembly_paint_toolbar_width() * inv_zoom; + switch (t_type) { + case Slic3r::GUI::GLGizmosManager::EType::Move: + return "Move"; + case Slic3r::GUI::GLGizmosManager::EType::Rotate: + return "Rotate"; + case Slic3r::GUI::GLGizmosManager::EType::Scale: + return "Scale"; + case Slic3r::GUI::GLGizmosManager::EType::Flatten: + return "Flatten"; + case Slic3r::GUI::GLGizmosManager::EType::Cut: + return "Cut"; + case Slic3r::GUI::GLGizmosManager::EType::MeshBoolean: + return "MeshBoolean"; + case Slic3r::GUI::GLGizmosManager::EType::FdmSupports: + return "FdmSupports"; + case Slic3r::GUI::GLGizmosManager::EType::Seam: + return "Seam"; + case Slic3r::GUI::GLGizmosManager::EType::Text: + return "Text"; + case Slic3r::GUI::GLGizmosManager::EType::Svg: + return "Svg"; + case Slic3r::GUI::GLGizmosManager::EType::MmuSegmentation: + return "Color Painting"; + case Slic3r::GUI::GLGizmosManager::EType::FuzzySkin: + return "FuzzySkin"; + case Slic3r::GUI::GLGizmosManager::EType::Measure: + return "Mesause"; + case Slic3r::GUI::GLGizmosManager::EType::Assembly: + return "Assembly"; + case Slic3r::GUI::GLGizmosManager::EType::Simplify: + return "Simplify"; + case Slic3r::GUI::GLGizmosManager::EType::BrimEars: + return "BrimEars"; + case Slic3r::GUI::GLGizmosManager::EType::SlaSupports: + return "SlaSupports"; + case Slic3r::GUI::GLGizmosManager::EType::Hollow: + return "Hollow"; + case Slic3r::GUI::GLGizmosManager::EType::Undefined: + return "Undefined"; + default: + return "Unknow"; } - else { - //QDS: GUI refactor: GLToolbar&&Gizmo adjust -#if QDS_TOOLBAR_ON_TOP - float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); - float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); - float collapse_width = (float)m_parent.get_collapse_toolbar_width(); - float separator_width = m_parent.get_separator_toolbar_width(); - //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); - //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; - - float main_toolbar_left = m_parent.get_main_toolbar_left(cnv_w, inv_zoom); - //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; - zoomed_top_x = main_toolbar_left + (main_toolbar_width + separator_width /2.f) * inv_zoom; - } - float zoomed_top_y = 0.5f * cnv_h * inv_zoom; -#else - //float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom; - //float zoomed_top_y = (0.5f * height) * inv_zoom; - float zoomed_top_x = (0.5f * cnv_w - width) * inv_zoom; - float main_toolbar_height = (float)m_parent.get_main_toolbar_height(); - float assemble_view_height = (float)m_parent.get_assemble_view_toolbar_height(); - //float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); - float zoomed_top_y = 0.5f * (height + assemble_view_height - main_toolbar_height) * inv_zoom; -#endif - //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": zoomed_top_y %1%, space_height %2%, main_toolbar_height %3% zoomed_top_x %4%") % zoomed_top_y % space_height % main_toolbar_height % zoomed_top_x; - - float zoomed_left = zoomed_top_x; - float zoomed_top = zoomed_top_y; - float zoomed_right = zoomed_left + width * inv_zoom; - float zoomed_bottom = zoomed_top - height * inv_zoom; - - render_background(zoomed_left, zoomed_top, zoomed_right, zoomed_bottom, zoomed_border); - - zoomed_top_x += zoomed_border; - zoomed_top_y -= zoomed_border; - - float icons_size = m_layout.scaled_icons_size(); - float zoomed_icons_size = icons_size * inv_zoom; - float zoomed_stride_y = m_layout.scaled_stride_y() * inv_zoom; - //QDS: GUI refactor: GLToolbar&&Gizmo adjust - float zoomed_stride_x = m_layout.scaled_stride_x() * inv_zoom; - - unsigned int icons_texture_id = m_icons_texture.get_id(); - int tex_width = m_icons_texture.get_width(); - int tex_height = m_icons_texture.get_height(); - - if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1)) - return; - - float du = (float)(tex_width - 1) / (6.0f * (float)tex_width); // 6 is the number of possible states if the icons - float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height); - - // tiles in the texture are spaced by 1 pixel - float u_offset = 1.0f / (float)tex_width; - float v_offset = 1.0f / (float)tex_height; - - bool is_render_current = false; - - for (size_t idx : selectable_idxs) - { - GLGizmoBase* gizmo = m_gizmos[idx].get(); - bool selected_svg = is_svg_selected((int)idx); - if (selected_svg) { - gizmo = m_gizmos[m_current].get(); - } - unsigned int sprite_id = gizmo->get_sprite_id(); - // higlighted state needs to be decided first so its highlighting in every other state - int icon_idx = (m_highlight.first == idx ? (m_highlight.second ? 4 : 5) : - (m_current == idx || selected_svg) ? 2 : - ((m_hover == idx) ? 1 : (gizmo->is_activable() ? 0 : 3))); - - float v_top = v_offset + sprite_id * dv; - float u_left = u_offset + icon_idx * du; - float v_bottom = v_top + dv - v_offset; - float u_right = u_left + du - u_offset; - - GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); - - if (idx == m_current// Orca: Show Svg dialog at the same place as emboss gizmo - || (selected_svg)) { - //QDS: GUI refactor: GLToolbar&&Gizmo adjust - //render_input_window uses a different coordination(imgui) - //1. no need to scale by camera zoom, set {0,0} at left-up corner for imgui -#if QDS_TOOLBAR_ON_TOP - //gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top); - m_gizmos[m_current]->render_input_window(0.5 * cnv_w + zoomed_top_x * zoom, height, cnv_h); - - is_render_current = true; -#else - float toolbar_top = cnv_h - wxGetApp().plater()->get_view_toolbar().get_height(); - //gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top); - gizmo->render_input_window(cnv_w - width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top); -#endif - } -#if QDS_TOOLBAR_ON_TOP - zoomed_top_x += zoomed_stride_x; -#else - zoomed_top_y -= zoomed_stride_y; -#endif - } - - // QDS simplify gizmo is not a selected gizmo and need to render input window - if (!is_render_current && m_current != Undefined) { - m_gizmos[m_current]->render_input_window(0.5 * cnv_w + zoomed_top_x * zoom, height, cnv_h); - } -} - -float GLGizmosManager::get_scaled_total_height() const -{ -//QDS: GUI refactor: to support top layout -#if QDS_TOOLBAR_ON_TOP - return 2.0f * m_layout.scaled_border() + m_layout.scaled_icons_size(); -#else - return m_layout.scale * (2.0f * m_layout.border + (float)get_selectable_idxs().size() * m_layout.stride_y() - m_layout.gap_y); -#endif -} - -float GLGizmosManager::get_scaled_total_width() const -{ -//QDS: GUI refactor: to support top layout -#if QDS_TOOLBAR_ON_TOP - return m_layout.scale * (2.0f * m_layout.border + (float)get_selectable_idxs().size() * m_layout.stride_x() - m_layout.gap_x); -#else - return 2.0f * m_layout.scaled_border() + m_layout.scaled_icons_size(); -#endif } GLGizmoBase* GLGizmosManager::get_current() const @@ -1756,10 +1373,11 @@ GLGizmoBase* GLGizmosManager::get_gizmo(GLGizmosManager::EType type) const GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& gizmo_name) const { + const auto is_dark_mode = m_parent.get_dark_mode_status(); std::vector selectable_idxs = get_selectable_idxs(); for (size_t idx = 0; idx < selectable_idxs.size(); ++idx) { - std::string filename = m_gizmos[selectable_idxs[idx]]->get_icon_filename(); + std::string filename = m_gizmos[selectable_idxs[idx]]->get_icon_filename(is_dark_mode); filename = filename.substr(0, filename.find_first_of('.')); if (filename == gizmo_name) return (GLGizmosManager::EType)selectable_idxs[idx]; @@ -1767,82 +1385,27 @@ GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& g return GLGizmosManager::EType::Undefined; } -bool GLGizmosManager::generate_icons_texture() const -{ - std::string path = resources_dir() + "/images/"; - std::vector filenames; - for (size_t idx=0; idxget_icon_filename(); - if (!icon_filename.empty()) - filenames.push_back(path + icon_filename); - } - } - - std::vector> states; - states.push_back(std::make_pair(1, false)); // Activable - states.push_back(std::make_pair(0, false)); // Hovered - states.push_back(std::make_pair(0, true)); // Selected - states.push_back(std::make_pair(2, false)); // Disabled - states.push_back(std::make_pair(0, false)); // HighlightedShown - states.push_back(std::make_pair(2, false)); // HighlightedHidden - - unsigned int sprite_size_px = (unsigned int)m_layout.scaled_icons_size(); -// // force even size -// if (sprite_size_px % 2 != 0) -// sprite_size_px += 1; - - bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, sprite_size_px, false); - if (res) - m_icons_texture_dirty = false; - - return res; -} - -void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos) +void GLGizmosManager::update_on_off_state(size_t idx) { if (!m_enabled) return; - - size_t idx = get_gizmo_idx_from_mouse(mouse_pos); + if (is_text_first_clicked(idx)) { // open text gizmo + GLGizmoBase *gizmo_text= m_gizmos[EType::Text].get(); + if (dynamic_cast(gizmo_text)->on_shortcut_key()) {//create text on mesh + return; + } + } if (is_svg_selected(idx)) {// close svg gizmo open_gizmo(EType::Svg); return; } - if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx) { + if (idx != Undefined && m_gizmos[idx]->is_activable()) { activate_gizmo(m_current == idx ? Undefined : (EType)idx); // QDS wxGetApp().obj_list()->select_object_item((EType) idx <= Scale || (EType) idx == Text); } } -std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos) -{ - std::string name = ""; - - if (!m_enabled) - return name; - - m_hover = Undefined; - - size_t idx = get_gizmo_idx_from_mouse(mouse_pos); - if (idx != Undefined) { - if (is_svg_selected(idx)) { - name = m_gizmos[m_current]->get_name(); - } - else { - name = m_gizmos[idx]->get_name(); - } - - if (m_gizmos[idx]->is_activable()) - m_hover = (EType)idx; - } - - return name; -} - bool GLGizmosManager::activate_gizmo(EType type) { if (m_gizmos.empty() || m_current == type) @@ -1878,10 +1441,20 @@ bool GLGizmosManager::activate_gizmo(EType type) //if (m_current == Text) { // wxGetApp().imgui()->load_fonts_texture(); //} + new_gizmo->set_serializing(m_serializing); new_gizmo->set_state(GLGizmoBase::On); - if (is_show_only_active_plate()) { - check_object_located_outside_plate(); + new_gizmo->set_serializing(false); + update_show_only_active_plate(); + + try { + if ((int)m_hover >= 0 && (int)m_hover < m_gizmos.size()) { + std::string name = convert_gizmo_type_to_string(m_hover); + int count = m_gizmos[m_hover]->get_count(); + NetworkAgent* agent = GUI::wxGetApp().getAgent(); + if (agent) { agent->track_update_property(name, std::to_string(count)); } + } } + catch (...) {} } return true; } @@ -1896,10 +1469,45 @@ bool GLGizmosManager::grabber_contains_mouse() const return (curr != nullptr) ? (curr->get_hover_id() != -1) : false; } +bool GLGizmosManager::is_text_first_clicked(int idx) const { + return m_current == Undefined && idx == Text; +} + bool GLGizmosManager::is_svg_selected(int idx) const { return m_current == Svg && idx == Text; } +std::string GLGizmosManager::on_hover(int idx) +{ + std::string t_name{}; + if (is_svg_selected(idx)) { + t_name = m_gizmos[m_current]->get_name(); + } + else { + t_name = m_gizmos[idx]->get_name(); + } + + if (m_gizmos[idx]->is_activable()) + m_hover = (EType)idx; + return t_name; +} + +void GLGizmosManager::on_click(int idx) +{ + Selection &selection = m_parent.get_selection(); + if (selection.is_empty()) { + if (is_text_first_clicked(idx)) { // open text gizmo + GLGizmoBase* gizmo_text = m_gizmos[EType::Text].get(); + dynamic_cast(gizmo_text)->on_shortcut_key();//direct create text on plate + return; + } + } + + update_on_off_state(idx); + update_data(); + m_parent.set_as_dirty(); +} + bool GLGizmosManager::is_in_editing_mode(bool error_notification) const { if (m_current == SlaSupports && dynamic_cast(get_current())->is_in_editing_mode()) { @@ -1910,6 +1518,7 @@ bool GLGizmosManager::is_in_editing_mode(bool error_notification) const } else { return false; } + } @@ -1929,33 +1538,9 @@ int GLGizmosManager::get_shortcut_key(GLGizmosManager::EType type) const return m_gizmos[type]->get_shortcut_key(); } -std::string get_name_from_gizmo_etype(GLGizmosManager::EType type) +void GLGizmosManager::set_highlight(EType gizmo, bool highlight_shown) { - switch (type) { - case GLGizmosManager::EType::Move: - return "Move"; - case GLGizmosManager::EType::Rotate: - return "Rotate"; - case GLGizmosManager::EType::Scale: - return "Scale"; - case GLGizmosManager::EType::Flatten: - return "Flatten"; - case GLGizmosManager::EType::Cut: - return "Cut"; - case GLGizmosManager::EType::MeshBoolean: - return "MeshBoolean"; - case GLGizmosManager::EType::FdmSupports: - return "FdmSupports"; - case GLGizmosManager::EType::Seam: - return "Seam"; - case GLGizmosManager::EType::Text: - return "Text"; - case GLGizmosManager::EType::MmuSegmentation: - return "Color Painting"; - default: - return ""; - } - return ""; + m_highlight = std::pair(gizmo, highlight_shown); } } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 95ab37d..b0ebe10 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -2,7 +2,6 @@ #define slic3r_GUI_GLGizmosManager_hpp_ #include "slic3r/GUI/GLTexture.hpp" -#include "slic3r/GUI/GLToolbar.hpp" #include "slic3r/GUI/Gizmos/GLGizmoBase.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" //QDS: GUI refactor: add object manipulation @@ -13,6 +12,8 @@ #include "wx/timer.h" #include +#include +#include //QDS: GUI refactor: to support top layout #define QDS_TOOLBAR_ON_TOP 1 @@ -31,6 +32,7 @@ enum class SLAGizmoEventType : unsigned char; class CommonGizmosDataPool; //QDS: GUI refactor: add object manipulation class GizmoObjectManipulation; +class GLToolbar; class Rect { float m_left; @@ -73,16 +75,16 @@ public: Flatten, Cut, MeshBoolean, - FdmSupports, - Seam, - // QDS + Assembly, + MmuSegmentation, Text, Svg, - MmuSegmentation, - Measure, - Assembly, - Simplify, + FdmSupports, + Seam, BrimEars, + FuzzySkin, + Measure, + Simplify, SlaSupports, // QDS //FaceRecognition, @@ -91,34 +93,10 @@ public: }; private: - struct Layout - { - float scale{ 1.0f }; - float icons_size{ Default_Icons_Size }; - float border{ 5.0f }; - float gap_y{ 5.0f }; - //QDS: GUI refactor: to support top layout - float gap_x{ 5.0f }; - float stride_x() const { return icons_size + gap_x;} - float scaled_gap_x() const { return scale * gap_x; } - float scaled_stride_x() const { return scale * stride_x(); } - - float stride_y() const { return icons_size + gap_y;} - - float scaled_icons_size() const { return scale * icons_size; } - float scaled_border() const { return scale * border; } - float scaled_gap_y() const { return scale * gap_y; } - float scaled_stride_y() const { return scale * stride_y(); } - }; GLCanvas3D& m_parent; bool m_enabled; std::vector> m_gizmos; - mutable GLTexture m_icons_texture; - mutable bool m_icons_texture_dirty; - BackgroundTexture m_background_texture; - BackgroundTexture m_arrow_texture; - Layout m_layout; EType m_current; EType m_hover; std::pair m_highlight; // bool true = higlightedShown, false = highlightedHidden @@ -127,25 +105,9 @@ private: GizmoObjectManipulation m_object_manipulation; std::vector get_selectable_idxs() const; - size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const; bool activate_gizmo(EType type); - struct MouseCapture - { - bool left; - bool middle; - bool right; - GLCanvas3D* parent; - - MouseCapture() { reset(); } - - bool any() const { return left || middle || right; } - void reset() { left = middle = right = false; parent = nullptr; } - }; - - MouseCapture m_mouse_capture; - std::string m_tooltip; bool m_serializing; std::unique_ptr m_common_gizmos_data; @@ -180,16 +142,10 @@ public: explicit GLGizmosManager(GLCanvas3D& parent); - void switch_gizmos_icon_filename(); - bool init(); bool init_icon_textures(); - float get_layout_scale(); - - bool init_arrow(const BackgroundTexture::Metadata& arrow_texture); - template void load(Archive& ar) { @@ -228,10 +184,6 @@ public: bool is_enabled() const { return m_enabled; } void set_enabled(bool enable) { m_enabled = enable; } - void set_icon_dirty() { m_icons_texture_dirty = true; } - void set_overlay_icon_size(float size); - void set_overlay_scale(float scale); - void refresh_on_off_state(); void reset_all_states(); bool is_serializing() const { return m_serializing; } @@ -285,14 +237,20 @@ public: bool is_gizmo_activable_when_single_full_instance(); bool is_gizmo_click_empty_not_exit(); - bool is_show_only_active_plate(); - bool is_ban_move_glvolume(); - bool get_gizmo_active_condition(GLGizmosManager::EType type); //1.9.5 + bool is_only_text_volume() const; + bool is_show_only_active_plate() const; + bool is_ban_move_glvolume() const; + bool get_gizmo_active_condition(GLGizmosManager::EType type); + void update_show_only_active_plate(); void check_object_located_outside_plate(bool change_plate =true); - bool get_object_located_outside_plate() { return m_object_located_outside_plate; } + void set_object_located_outside_plate(bool flag) { m_object_located_outside_plate = flag; } + bool get_object_located_outside_plate() const { return m_object_located_outside_plate; } bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); bool is_paint_gizmo()const; - bool is_allow_select_all(); + bool is_allow_select_all() const; + bool is_allow_show_volume_highlight_outline() const; + bool is_allow_drag_volume() const; + bool is_allow_mouse_drag_selected() const; ClippingPlane get_clipping_plane() const; ClippingPlane get_assemble_view_clipping_plane() const; bool wants_reslice_supports_on_undo() const; @@ -306,10 +264,6 @@ public: void render_painter_gizmo() const; void render_painter_assemble_view() const; - void render_overlay(); - - void render_arrow(const GLCanvas3D& parent, EType highlighted_type) const; - std::string get_tooltip() const; bool on_mouse(wxMouseEvent& evt); @@ -323,34 +277,29 @@ public: int get_shortcut_key(GLGizmosManager::EType) const; // To end highlight set gizmo = undefined - void set_highlight(EType gizmo, bool highlight_shown) { m_highlight = std::pair(gizmo, highlight_shown); } + void set_highlight(EType gizmo, bool highlight_shown); bool get_highlight_state() const { return m_highlight.second; } - //QDS: GUI refactor: GLToolbar adjust - float get_scaled_total_height() const; - float get_scaled_total_width() const; GizmoObjectManipulation& get_object_manipulation() { return m_object_manipulation; } bool get_uniform_scaling() const { return m_object_manipulation.get_uniform_scaling();} BoundingBoxf3 get_bounding_box() const; + void add_toolbar_items(const std::shared_ptr& p_toolbar, uint8_t& sprite_id, const std::function& p_callback); + + static std::string convert_gizmo_type_to_string(Slic3r::GUI::GLGizmosManager::EType t_type); private: - void render_background(float left, float top, float right, float bottom, float border) const; - void do_render_overlay() const; - - bool generate_icons_texture() const; - - void update_on_off_state(const Vec2d& mouse_pos); - std::string update_hover_state(const Vec2d& mouse_pos); + void update_on_off_state(size_t idx); bool grabber_contains_mouse() const; + bool is_text_first_clicked(int idx) const; bool is_svg_selected(int idx) const; + std::string on_hover(int idx); + void on_click(int idx); private: bool m_object_located_outside_plate{false}; }; -std::string get_name_from_gizmo_etype(GLGizmosManager::EType type); - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GuiTextShape.cpp b/src/slic3r/GUI/GuiTextShape.cpp new file mode 100644 index 0000000..10bf7ad --- /dev/null +++ b/src/slic3r/GUI/GuiTextShape.cpp @@ -0,0 +1,47 @@ +#include "GuiTextShape.hpp" +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "imgui/imstb_truetype.h" // stbtt_fontinfo +namespace Slic3r { + using namespace Emboss; + namespace GUI { + ExPolygons GuiTextShape::letter2shapes(wchar_t letter, Point &cursor, FontFileWithCache &font_with_cache, const FontProp &font_prop, fontinfo_opt &font_info_cache) + { + assert(font_with_cache.has_value()); + if (!font_with_cache.has_value()) return {}; + + Glyphs & cache = *font_with_cache.cache; + const FontFile &font = *font_with_cache.font_file; + + if (letter == '\n') { + cursor.x() = 0; + // 2d shape has opposit direction of y + cursor.y() -= get_line_height(font, font_prop); + return {}; + } + if (letter == '\t') { + // '\t' = 4*space => same as imgui + const int count_spaces = 4; + const Glyph *space = ::get_glyph(int(' '), font, font_prop, cache, font_info_cache); + if (space == nullptr) return {}; + cursor.x() += count_spaces * space->advance_width; + return {}; + } + if (letter == '\r') return {}; + + int unicode = static_cast(letter); + auto it = cache.find(unicode); + + // Create glyph from font file and cache it + const Glyph *glyph_ptr = (it != cache.end()) ? &it->second : get_glyph(unicode, font, font_prop, cache, font_info_cache); + if (glyph_ptr == nullptr) return {}; + + // move glyph to cursor position + ExPolygons expolygons = glyph_ptr->shape; // copy + for (ExPolygon &expolygon : expolygons) expolygon.translate(cursor); + + cursor.x() += glyph_ptr->advance_width; + return expolygons; +} +} // namespace GUI + +}; // namespace Slic3r diff --git a/src/slic3r/GUI/GuiTextShape.hpp b/src/slic3r/GUI/GuiTextShape.hpp new file mode 100644 index 0000000..4d989f0 --- /dev/null +++ b/src/slic3r/GUI/GuiTextShape.hpp @@ -0,0 +1,23 @@ +#ifndef slic3r_Text_Shape_hpp_ +#define slic3r_Text_Shape_hpp_ + +#include "libslic3r/TriangleMesh.hpp" +#include +#include +struct stbtt_fontinfo; +using fontinfo_opt = std::optional; +namespace Slic3r { + namespace GUI { + class GuiTextShape + { + public: + static ExPolygons letter2shapes(wchar_t letter, Point &cursor, FontFileWithCache &font_with_cache, const FontProp &font_prop, fontinfo_opt &font_info_cache); + + private: + }; + +} + +}; // namespace Slic3r + +#endif // slic3r_Text_Shape_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/HMS.cpp b/src/slic3r/GUI/HMS.cpp index c12f0f8..14a9e5d 100644 --- a/src/slic3r/GUI/HMS.cpp +++ b/src/slic3r/GUI/HMS.cpp @@ -76,7 +76,6 @@ int HMSQuery::download_hms_related(const std::string& hms_type, const std::strin bool to_save_local = false; json j; - BOOST_LOG_TRIVIAL(info) << "hms: download url = " << url; Slic3r::Http http = Slic3r::Http::get(url); http.on_complete([this, receive_json, hms_type, &to_save_local, &j, & local_version](std::string body, unsigned status) { try { diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index e9026c4..7f39d7b 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -83,7 +83,7 @@ namespace { { boost::filesystem::path path(boost::filesystem::path(data_dir()) / "user" / "hints.cereal"); if (!boost::filesystem::exists(path)) { - BOOST_LOG_TRIVIAL(warning) << "Failed to load to hints.cereal. File does not exists. " << path.string(); + BOOST_LOG_TRIVIAL(warning) << "Failed to load to hints.cereal. File does not exists. " << PathSanitizer::sanitize(path); return; } boost::nowide::ifstream file(path.string()); diff --git a/src/slic3r/GUI/IMSlider.cpp b/src/slic3r/GUI/IMSlider.cpp index 1211994..3ac7149 100644 --- a/src/slic3r/GUI/IMSlider.cpp +++ b/src/slic3r/GUI/IMSlider.cpp @@ -1153,8 +1153,8 @@ void IMSlider::render_input_custom_gcode(std::string custom_gcode) strcpy(m_custom_gcode, custom_gcode.c_str()); } const int text_height = 6; - - ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height)); + const ImGuiInputTextFlags flag = ImGuiInputTextFlags_Multiline; + ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height), flag); ImGui::NewLine(); ImGui::SameLine(ImGui::GetStyle().WindowPadding.x * 14); diff --git a/src/slic3r/GUI/IMToolbar.cpp b/src/slic3r/GUI/IMToolbar.cpp index 1dbfc9e..ab04873 100644 --- a/src/slic3r/GUI/IMToolbar.cpp +++ b/src/slic3r/GUI/IMToolbar.cpp @@ -61,8 +61,6 @@ void IMToolbar::del_stats_item() void IMToolbar::set_enabled(bool enable) { m_enabled = enable; - if (!m_enabled) - is_render_finish = false; } bool IMReturnToolbar::init() diff --git a/src/slic3r/GUI/IMToolbar.hpp b/src/slic3r/GUI/IMToolbar.hpp index add067d..03e51a2 100644 --- a/src/slic3r/GUI/IMToolbar.hpp +++ b/src/slic3r/GUI/IMToolbar.hpp @@ -49,7 +49,6 @@ public: float icon_height; bool is_display_scrollbar; bool show_stats_item{ false }; - bool is_render_finish{false}; IMToolbar() { icon_width = DEFAULT_TOOLBAR_BUTTON_WIDTH; icon_height = DEFAULT_TOOLBAR_BUTTON_HEIGHT; diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 920dc67..d986684 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -152,6 +152,7 @@ const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT; const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = ImGuiWrapper::COL_BUTTON_HOVERED; //QDS //B +const ImVec4 ImGuiWrapper::COL_WHITE = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); const ImVec4 ImGuiWrapper::COL_RED = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); const ImVec4 ImGuiWrapper::COL_GREEN = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); const ImVec4 ImGuiWrapper::COL_BLUE = ImVec4(0.0f, 0.0f, 1.0f, 1.0f); @@ -165,6 +166,7 @@ const ImVec4 ImGuiWrapper::COL_TITLE_BG = { 0.745f, 0.745f, 0.745f, 1.0 const ImVec4 ImGuiWrapper::COL_WINDOW_BG = { 1.000f, 1.000f, 1.000f, 1.0f }; const ImVec4 ImGuiWrapper::COL_WINDOW_BG_DARK = { 45 / 255.f, 45 / 255.f, 49 / 255.f, 1.f }; const ImVec4 ImGuiWrapper::COL_QIDI = {68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255, 1.0f}; +const ImVec4 ImGuiWrapper::COL_QIDI_CHANGE = {1.0f, 111.0 / 255.0f, 0.0f / 255, 1.0f}; int ImGuiWrapper::TOOLBAR_WINDOW_FLAGS = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove @@ -2947,6 +2949,10 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) 0.0f, 0.0f, 0.0f, 1.0f; shader->set_uniform("Texture", 0); shader->set_uniform("ProjMtx", ortho_projection); + + const uint8_t stage = 0; + shader->set_uniform("s_texture", stage); + // Will project scissor/clipping rectangles into framebuffer space const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) @@ -2994,6 +3000,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) // Apply scissor/clipping rectangle (Y is inverted in OpenGL) glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); // Bind texture, Draw + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); } @@ -3013,6 +3020,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glDisable(GL_SCISSOR_TEST)); glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_BLEND)); wxGetApp().unbind_shader(); diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 5298aa6..23bb73a 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -342,6 +342,7 @@ public: static const ImVec4 COL_BUTTON_ACTIVE; //QDS add more colors + static const ImVec4 COL_WHITE; static const ImVec4 COL_RED; static const ImVec4 COL_GREEN; static const ImVec4 COL_BLUE; @@ -355,6 +356,7 @@ public: static const ImVec4 COL_SEPARATOR; static const ImVec4 COL_SEPARATOR_DARK; static const ImVec4 COL_QIDI; + static const ImVec4 COL_QIDI_CHANGE; //QDS static void on_change_color_mode(bool is_dark); static void push_toolbar_style(const float scale); diff --git a/src/slic3r/GUI/ImageDPIFrame.cpp b/src/slic3r/GUI/ImageDPIFrame.cpp index 3c7f4a7..998ff44 100644 --- a/src/slic3r/GUI/ImageDPIFrame.cpp +++ b/src/slic3r/GUI/ImageDPIFrame.cpp @@ -81,6 +81,23 @@ void ImageDPIFrame::on_timer(wxTimerEvent &event) Raise(); } m_timer_count++; + }else{ + wxPoint mouse_pos = wxGetMousePosition(); + wxRect window_rect = GetScreenRect(); + + wxPoint center(window_rect.x + window_rect.width / 2, window_rect.y + window_rect.height / 2); + int half_width = window_rect.width / 2; + int half_height = window_rect.height / 2; + wxRect expanded_rect( + center.x - half_width * 2, + center.y - half_height * 2, + window_rect.width * 2, + window_rect.height * 2 + ); + + if (!expanded_rect.Contains(mouse_pos)) { + on_hide(); + } } } diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 83f774d..e5f3f80 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -194,7 +194,7 @@ void ArrangeJob::prepare_selected() { void ArrangeJob::prepare_all() { clear_input(); - PartPlateList& plate_list = m_plater->get_partplate_list(); + PartPlateList& plate_list = m_plater->get_partplate_list(); for (size_t i = 0; i < plate_list.get_plate_count(); i++) { PartPlate* plate = plate_list.get_plate(i); bool same_as_global_print_seq = true; @@ -798,7 +798,7 @@ void ArrangeJob::finalize() // Move the unprintable items to the last virtual bed. // Note ap.apply() moves relatively according to bed_idx, so we need to subtract the orignal bed_idx for (ArrangePolygon& ap : m_unprintable) { - ap.bed_idx = beds + 1; + ap.bed_idx = -1; plate_list.postprocess_arrange_polygon(ap, true); ap.apply(); @@ -836,6 +836,7 @@ void ArrangeJob::finalize() NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging canceled.")); } Job::finalize(); + m_plater->m_arrange_running.store(false); } diff --git a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp new file mode 100644 index 0000000..3e6d093 --- /dev/null +++ b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp @@ -0,0 +1,222 @@ +#include "CreateFontNameImageJob.hpp" + +// rasterization of ExPoly +#include "libslic3r/SLA/AGGRaster.hpp" + +#include "slic3r/Utils/WxFontUtils.hpp" +#include "slic3r/GUI/3DScene.hpp" // ::glsafe + +// ability to request new frame after finish rendering +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" + +#include "wx/fontenum.h" + +#include + +using namespace Slic3r; +using namespace Slic3r::GUI; + +const std::string CreateFontImageJob::default_text = "AaBbCc123"; + +CreateFontImageJob::CreateFontImageJob(FontImageData &&input) + : m_input(std::move(input)) +{ + assert(wxFontEnumerator::IsValidFacename(m_input.font_name)); + assert(m_input.gray_level > 0 && m_input.gray_level < 255); + assert(m_input.texture_id != 0); +} + +void CreateFontImageJob::process(Ctl &ctl) +{ + auto font_file_with_cache = Slic3r::GUI::BackupFonts::gener_font_with_cache(m_input.font_name, m_input.encoding); + if (!font_file_with_cache.has_value()) { + return; + } + // use only first line of text + std::string& text = m_input.text; + if (text.empty()) + text = default_text; // copy + + size_t enter_pos = text.find('\n'); + if (enter_pos < text.size()) { + // text start with enter + if (enter_pos == 0) + return; + // exist enter, soo delete all after enter + text = text.substr(0, enter_pos); + } + + std::function was_canceled = [&ctl, cancel = m_input.cancel]() -> bool { + if (ctl.was_canceled()) return true; + if (cancel->load()) return true; + return false; + }; + auto ft_fn = []() { + return Slic3r::GUI::BackupFonts::backup_fonts; + }; + FontProp fp; // create default font parameters + auto &ff = *font_file_with_cache.font_file; + double standard_scale = get_text_shape_scale(fp, ff); + bool support_backup_fonts = GUI::wxGetApp().app_config->get_bool("support_backup_fonts"); + EmbossShape emboss_shape; + ExPolygons shapes = support_backup_fonts ? Emboss::text2shapes(emboss_shape, font_file_with_cache, text.c_str(), fp, was_canceled, ft_fn, standard_scale): + Emboss::text2shapes(emboss_shape, font_file_with_cache, text.c_str(), fp, was_canceled); + m_input.generate_origin_text = true; + if (shapes.empty()) {// select some character from font e.g. default text + m_input.generate_origin_text = false; + shapes = Emboss::text2shapes(emboss_shape, font_file_with_cache, default_text.c_str(), fp, was_canceled, ft_fn, standard_scale); + } + + if (shapes.empty()) { + m_input.cancel->store(true); + return; + } + + // normalize height of font + BoundingBox bounding_box; + for (const ExPolygon &shape : shapes) + bounding_box.merge(BoundingBox(shape.contour.points)); + if (bounding_box.size().x() < 1 || bounding_box.size().y() < 1) { + m_input.cancel->store(true); + return; + } + double scale = m_input.size.y() / (double) bounding_box.size().y(); + BoundingBoxf bb2(bounding_box.min.cast(), + bounding_box.max.cast()); + bb2.scale(scale); + Vec2d size_f = bb2.size(); + m_tex_size = Point(std::ceil(size_f.x()), std::ceil(size_f.y())); + // crop image width + if (m_tex_size.x() > m_input.size.x()) + m_tex_size.x() = m_input.size.x(); + if (m_tex_size.y() > m_input.size.y()) + m_tex_size.y() = m_input.size.y(); + + // Set up result + unsigned bit_count = 4; // RGBA + m_result = std::vector(m_tex_size.x() * m_tex_size.y() * bit_count, {255}); + + sla::Resolution resolution(m_tex_size.x(), m_tex_size.y()); + double pixel_dim = SCALING_FACTOR / scale; + sla::PixelDim dim(pixel_dim, pixel_dim); + double gamma = 1.; + std::unique_ptr raster = sla::create_raster_grayscale_aa(resolution, dim, gamma); + for (ExPolygon &shape : shapes) + shape.translate(-bounding_box.min); + for (const ExPolygon &shape : shapes) + raster->draw(shape); + + // copy rastered data to pixels + sla::RasterEncoder encoder = + [&pix = m_result, w = m_tex_size.x(), h = m_tex_size.y(), + gray_level = m_input.gray_level] + (const void *ptr, size_t width, size_t height, size_t num_components) { + size_t size {static_cast(w*h)}; + const unsigned char *ptr2 = (const unsigned char *) ptr; + for (size_t x = 0; x < width; ++x) + for (size_t y = 0; y < height; ++y) { + size_t index = y*w + x; + assert(index < size); + if (index >= size) continue; + pix[3+4*index] = ptr2[y * width + x] / gray_level; + } + return sla::EncodedRaster(); + }; + raster->encode(encoder); +} + +void CreateFontImageJob::finalize(bool canceled, std::exception_ptr &) +{ + if (m_input.count_opened_font_files) + --(*m_input.count_opened_font_files); + if (canceled || m_input.cancel->load()) return; + + *m_input.is_created = true; + + // Exist result bitmap with preview? + // (not valid input. e.g. not loadable font) + if (m_result.empty()) { + // TODO: write text cannot load into texture + m_result = std::vector(m_tex_size.x() * m_tex_size.y() * 4, {255}); + } + + // upload texture on GPU + const GLenum target = GL_TEXTURE_2D; + glsafe(::glBindTexture(target, m_input.texture_id)); + + GLsizei w = m_tex_size.x(), h = m_tex_size.y(); + GLint xoffset = 0; // align to left + auto texture_w = m_input.size.x(); + GLint yoffset = m_input.size.y() * m_input.index; + // clear rest of texture + std::vector empty_data(texture_w * m_tex_size.y() * 4, {0}); + glsafe(::glTexSubImage2D(target, m_input.level, 0, yoffset, texture_w, h, m_input.format, m_input.type, empty_data.data())); + if (m_input.generate_origin_text) { // valid texture + glsafe(::glTexSubImage2D(target, m_input.level, xoffset, yoffset, w, h, m_input.format, m_input.type, m_result.data())); + } + // bind default texture + GLuint no_texture_id = 0; + glsafe(::glBindTexture(target, no_texture_id)); + + // show rendered texture + wxGetApp().plater()->canvas3D()->schedule_extra_frame(0); + + BOOST_LOG_TRIVIAL(info) + << "Generate Preview font('" << m_input.font_name << "' id:" << m_input.index << ") " + << "with text: '" << m_input.text << "' " + << "texture_size " << m_input.size.x() << " x " << m_input.size.y(); +} + +std::vector Slic3r::GUI::BackupFonts::backup_fonts; +void Slic3r::GUI::BackupFonts::generate_backup_fonts() { + auto language = wxGetApp().app_config->get("language"); + auto custom_back_font_name = wxGetApp().app_config->get("custom_back_font_name"); + if (backup_fonts.empty()) { + size_t idx = language.find('_'); + std::string lang = (idx == std::string::npos) ? language : language.substr(0, idx); + std::vector font_names; +#ifdef _WIN32 + font_names.emplace_back(wxString(L"宋体"));//chinese confirm + font_names.emplace_back(wxString::FromUTF8("MS Gothic")); // Japanese + font_names.emplace_back(wxString::FromUTF8("NanumGothic")); // Korean + font_names.emplace_back(wxString::FromUTF8("Arial")); // Arabic +#endif +#ifdef __APPLE__ + font_names.emplace_back(wxString::FromUTF8("Songti SC"));//chinese confirm + font_names.emplace_back(wxString::FromUTF8("SimSong")); // Japanese//mac special + font_names.emplace_back(wxString::FromUTF8("Nanum Gothic")); // Korean//mac need space + font_names.emplace_back(wxString::FromUTF8("Arial")); // Arabic +#endif +#ifdef __linux__ + font_names.emplace_back(wxString(L"宋体")); // chinese confirm + font_names.emplace_back(wxString::FromUTF8("MS Gothic")); // Japanese + font_names.emplace_back(wxString::FromUTF8("NanumGothic")); // Korean + font_names.emplace_back(wxString::FromUTF8("Arial")); // Arabic +#endif + if (!custom_back_font_name.empty()) { + font_names.emplace_back(wxString::FromUTF8(custom_back_font_name)); + } + for (int i = 0; i < font_names.size(); i++) { + backup_fonts.emplace_back(gener_font_with_cache(font_names[i], wxFontEncoding::wxFONTENCODING_SYSTEM)); + } + } +} + +Slic3r::Emboss::FontFileWithCache Slic3r::GUI::BackupFonts::gener_font_with_cache(const wxString &font_name, const wxFontEncoding &encoding) +{ + Emboss::FontFileWithCache font_file_with_cache; + if (!wxFontEnumerator::IsValidFacename(font_name)) + return font_file_with_cache; + // Select font + wxFont wx_font(wxFontInfo().FaceName(font_name).Encoding(encoding)); + if (!wx_font.IsOk()) return font_file_with_cache; + std::unique_ptr font_file = WxFontUtils::create_font_file(wx_font); + if (font_file == nullptr) + return font_file_with_cache; + + font_file_with_cache = Emboss::FontFileWithCache(std::move(font_file)); + return font_file_with_cache; +} + diff --git a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp new file mode 100644 index 0000000..190199e --- /dev/null +++ b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp @@ -0,0 +1,89 @@ +#ifndef slic3r_CreateFontNameImageJob_hpp_ +#define slic3r_CreateFontNameImageJob_hpp_ + +#include +#include +#include +#include +#include +#include "JobNew.hpp" +#include "libslic3r/Point.hpp" // Vec2i32 +#include "libslic3r/Emboss.hpp" +namespace Slic3r::GUI { + +/// +/// Keep data for rasterization of text by font face +/// +struct FontImageData +{ + // Text to rasterize + std::string text; + // Define font face + wxString font_name; + wxFontEncoding encoding; + // texture for copy result to + // texture MUST BE initialized + GLuint texture_id; + // Index of face name, define place in texture + size_t index; + // Height of each text + // And Limit for width + Vec2i32 size; // in px + + // bigger value create darker image + // divide value 255 + unsigned char gray_level = 5; + + // texture meta data + GLenum format = GL_ALPHA, type = GL_UNSIGNED_BYTE; + GLint level = 0; + + // prevent opening too much files + // it is decreased in finalize phase + unsigned int *count_opened_font_files = nullptr; + + std::shared_ptr> cancel = nullptr; + std::shared_ptr is_created = nullptr; + bool generate_origin_text = false; +}; +class BackupFonts +{ +public: + static void generate_backup_fonts(); + static Slic3r::Emboss::FontFileWithCache gener_font_with_cache(const wxString &font_name, const wxFontEncoding& encoding); + static std::vector backup_fonts; +}; + +/// +/// Create image for face name +/// +class CreateFontImageJob : public JobNew +{ + FontImageData m_input; + std::vector m_result; + Point m_tex_size; +public: + CreateFontImageJob(FontImageData &&input); + /// + /// Rasterize text into image (result) + /// + /// Check for cancelation + void process(Ctl &ctl) override; + + /// + /// Copy image data into OpenGL texture + /// + /// + /// + void finalize(bool canceled, std::exception_ptr &) override; + + /// + /// Text used for generate preview for empty text + /// and when no glyph for given m_input.text + /// + static const std::string default_text; +}; + +} // namespace Slic3r::GUI + +#endif // slic3r_CreateFontNameImageJob_hpp_ diff --git a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp new file mode 100644 index 0000000..2276f4f --- /dev/null +++ b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp @@ -0,0 +1,158 @@ +#include "CreateFontStyleImagesJob.hpp" +#include "CreateFontNameImageJob.hpp" +// rasterization of ExPoly +#include "libslic3r/SLA/AGGRaster.hpp" +#include "slic3r/GUI/3DScene.hpp" // ::glsafe + +// ability to request new frame after finish rendering +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" + +using namespace Slic3r; +using namespace Slic3r::Emboss; +using namespace Slic3r::GUI; +using namespace Slic3r::GUI::Emboss; + + +CreateFontStyleImagesJob::CreateFontStyleImagesJob(StyleManager::StyleImagesData &&input) + : m_input(std::move(input)), m_width(0), m_height(0) +{ + assert(m_input.result != nullptr); + assert(!m_input.styles.empty()); + assert(!m_input.text.empty()); + assert(m_input.max_size.x() > 1); + assert(m_input.max_size.y() > 1); + assert(m_input.ppm > 1e-5); +} + +void CreateFontStyleImagesJob::process(Ctl &ctl) +{ + // create shapes and calc size (bounding boxes) + std::vector name_shapes(m_input.styles.size()); + std::vector scales(m_input.styles.size()); + m_images = std::vector(m_input.styles.size()); + + auto was_canceled = []() { return false; }; + bool support_backup_fonts = GUI::wxGetApp().app_config->get_bool("support_backup_fonts"); + auto ft_fn = []() { return Slic3r::GUI::BackupFonts::backup_fonts; }; + for (auto &item : m_input.styles) { + size_t index = &item - &m_input.styles.front(); + ExPolygons &shapes = name_shapes[index]; + EmbossShape emboss_shape; + auto & ff = *item.font.font_file; + double standard_scale = get_text_shape_scale(item.prop, ff); + shapes = support_backup_fonts ? text2shapes(emboss_shape, item.font, m_input.text.c_str(), item.prop, was_canceled, ft_fn, standard_scale) + :text2shapes(emboss_shape, item.font, m_input.text.c_str(), item.prop, was_canceled); + // create image description + StyleManager::StyleImage &image = m_images[index]; + BoundingBox &bounding_box = image.bounding_box; + for (ExPolygon &shape : shapes) + bounding_box.merge(BoundingBox(shape.contour.points)); + for (ExPolygon &shape : shapes) shape.translate(-bounding_box.min); + + // calculate conversion from FontPoint to screen pixels by size of font + double scale = get_text_shape_scale(item.prop, *item.font.font_file) * m_input.ppm *0.5; + scales[index] = scale; + + //double scale = font_prop.size_in_mm * SCALING_FACTOR; + BoundingBoxf bb2(bounding_box.min.cast(), + bounding_box.max.cast()); + bb2.scale(scale); + image.tex_size.x = std::ceil(bb2.max.x() - bb2.min.x()); + image.tex_size.y = std::ceil(bb2.max.y() - bb2.min.y()); + + // crop image width + if (image.tex_size.x > m_input.max_size.x()) + image.tex_size.x = m_input.max_size.x(); + // crop image height + if (image.tex_size.y > m_input.max_size.y()) + image.tex_size.y = m_input.max_size.y(); + } + + // arrange bounding boxes + int offset_y = 0; + m_width = 0; + for (StyleManager::StyleImage &image : m_images) { + image.offset.y() = offset_y; + offset_y += image.tex_size.y+1; + if (m_width < image.tex_size.x) + m_width = image.tex_size.x; + } + m_height = offset_y; + for (StyleManager::StyleImage &image : m_images) { + const Point &o = image.offset; + const ImVec2 &s = image.tex_size; + image.uv0 = ImVec2(o.x() / (double) m_width, + o.y() / (double) m_height); + image.uv1 = ImVec2((o.x() + s.x) / (double) m_width, + (o.y() + s.y) / (double) m_height); + } + + // Set up result + m_pixels = std::vector(4 * m_width * m_height, {255}); + + // upload sub textures + for (StyleManager::StyleImage &image : m_images) { + sla::Resolution resolution(image.tex_size.x, image.tex_size.y); + size_t index = &image - &m_images.front(); + double pixel_dim = SCALING_FACTOR / scales[index]; + sla::PixelDim dim(pixel_dim, pixel_dim); + double gamma = 1.; + std::unique_ptr r = + sla::create_raster_grayscale_aa(resolution, dim, gamma); + for (const ExPolygon &shape : name_shapes[index]) r->draw(shape); + + // copy rastered data to pixels + sla::RasterEncoder encoder = [&offset = image.offset, &pix = m_pixels, w=m_width,h=m_height] + (const void *ptr, size_t width, size_t height, size_t num_components) { + // bigger value create darker image + unsigned char gray_level = 1; + size_t size {static_cast(w*h)}; + assert((offset.x() + width) <= (size_t)w); + assert((offset.y() + height) <= (size_t)h); + const unsigned char *ptr2 = (const unsigned char *) ptr; + for (size_t x = 0; x < width; ++x) + for (size_t y = 0; y < height; ++y) { + size_t index = (offset.y() + y)*w + offset.x() + x; + assert(index < size); + if (index >= size) continue; + pix[4*index+3] = ptr2[y * width + x] / gray_level; + } + return sla::EncodedRaster(); + }; + r->encode(encoder); + } +} + +void CreateFontStyleImagesJob::finalize(bool canceled, std::exception_ptr &) +{ + if (canceled) return; + // upload texture on GPU + GLuint tex_id; + GLenum target = GL_TEXTURE_2D, format = GL_RGBA, type = GL_UNSIGNED_BYTE; + GLint level = 0, border = 0; + glsafe(::glGenTextures(1, &tex_id)); + glsafe(::glBindTexture(target, tex_id)); + glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GLint w = m_width, h = m_height; + glsafe(::glTexImage2D(target, level, GL_RGBA, w, h, border, format, type, + (const void *) m_pixels.data())); + + // set up texture id + void *texture_id = (void *) (intptr_t) tex_id; + for (StyleManager::StyleImage &image : m_images) + image.texture_id = texture_id; + + // move to result + m_input.result->styles = std::move(m_input.styles); + m_input.result->images = std::move(m_images); + + // bind default texture + GLuint no_texture_id = 0; + glsafe(::glBindTexture(target, no_texture_id)); + + // show rendered texture + wxGetApp().plater()->canvas3D()->schedule_extra_frame(0); +} \ No newline at end of file diff --git a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp new file mode 100644 index 0000000..3941a65 --- /dev/null +++ b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp @@ -0,0 +1,36 @@ +#ifndef slic3r_CreateFontStyleImagesJob_hpp_ +#define slic3r_CreateFontStyleImagesJob_hpp_ + +#include +#include +#include +#include "slic3r/Utils/EmbossStyleManager.hpp" +#include "JobNew.hpp" + +namespace Slic3r::GUI::Emboss { + +/// +/// Create texture with name of styles written by its style +/// NOTE: Access to glyph cache is possible only from job +/// +class CreateFontStyleImagesJob : public JobNew +{ + StyleManager::StyleImagesData m_input; + + // Output data + // texture size + int m_width, m_height; + // texture data + std::vector m_pixels; + // descriptors of sub textures + std::vector m_images; + +public: + CreateFontStyleImagesJob(StyleManager::StyleImagesData &&input); + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &) override; +}; + +} // namespace Slic3r::GUI + +#endif // slic3r_CreateFontStyleImagesJob_hpp_ diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index 14e0cda..f72f2aa 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -3,6 +3,7 @@ #include #include // +#include #include #include // load_obj for default mesh #include // use surface cuts @@ -25,7 +26,7 @@ //#include "slic3r/GUI/3DScene.hpp" #include "slic3r/GUI/Jobs/Worker.hpp" #include "slic3r/Utils/UndoRedo.hpp" - +#include // #define EXECUTE_UPDATE_ON_MAIN_THREAD // debug execution on main thread using namespace Slic3r::Emboss; namespace Slic3r { @@ -45,8 +46,10 @@ public: bool was_canceled(const JobNew::Ctl &ctl, const DataBase &base) { - if (base.cancel->load()) return true; - return ctl.was_canceled(); + if (base.cancel->load()) + return true; + auto flag = ctl.was_canceled(); + return flag; } bool _finalize(bool canceled, std::exception_ptr &eptr, const DataBase &input) @@ -178,6 +181,45 @@ bool is_valid(ModelVolumeType volume_type) return false; } + +void recreate_model_volume(ModelObject *model_object, int volume_idx, const TriangleMesh &mesh, Geometry::Transformation &text_tran, TextInfo &text_info) +{ + wxGetApp() .plater()->take_snapshot("Modify Text"); + + ModelVolume *model_volume = model_object->volumes[volume_idx]; + ModelVolume *new_model_volume = model_object->add_volume(mesh, false); + new_model_volume->calculate_convex_hull(); + new_model_volume->set_transformation(text_tran.get_matrix()); + new_model_volume->set_text_info(text_info); + new_model_volume->name = model_volume->name; + new_model_volume->set_type(model_volume->type()); + new_model_volume->config.apply(model_volume->config); + std::swap(model_object->volumes[volume_idx], model_object->volumes.back()); + model_object->delete_volume(model_object->volumes.size() - 1); + model_object->invalidate_bounding_box(); + wxGetApp().plater()->update(); +} + +void create_text_volume(Slic3r::ModelObject *model_object, const TriangleMesh &mesh, Geometry::Transformation &text_tran, TextInfo &text_info) +{ + wxGetApp().plater()->take_snapshot("create_text_volume"); + + ModelVolume *new_model_volume = model_object->add_volume(mesh, false); + new_model_volume->calculate_convex_hull(); + new_model_volume->set_transformation(text_tran.get_matrix()); + new_model_volume->set_text_info(text_info); + if (model_object->config.option("extruder")) { + new_model_volume->config.set_key_value("extruder", new ConfigOptionInt(model_object->config.extruder())); + } else { + new_model_volume->config.set_key_value("extruder", new ConfigOptionInt(1)); + model_object->config.set_key_value("extruder", new ConfigOptionInt(1)); + } + new_model_volume->name = "text_shape"; + + model_object->invalidate_bounding_box(); + wxGetApp().plater()->update(); +} + bool check(unsigned char gizmo_type) { return gizmo_type == (unsigned char) GLGizmosManager::Svg; } bool check(const CreateVolumeParams &input) @@ -339,6 +381,7 @@ void UpdateJob::update_volume(ModelVolume *volume, TriangleMesh &&mesh, const Da // update volume volume->set_mesh(std::move(mesh)); + volume->calculate_convex_hull(); volume->set_new_unique_id(); volume->calculate_convex_hull(); @@ -467,12 +510,16 @@ void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr) // When cursor move and no one object is selected than // Manager::reset_all() So Gizmo could be closed before end of creation object GLCanvas3D * canvas = plater->get_view3D_canvas3D(); - GLGizmosManager &manager = canvas->get_gizmos_manager(); - if (manager.get_current_type() != m_input.gizmo_type) // GLGizmosManager::EType::svg - manager.open_gizmo(m_input.gizmo_type); + if (canvas) { + GLGizmosManager& manager = canvas->get_gizmos_manager(); + if (manager.get_current_type() != m_input.gizmo_type) { // GLGizmosManager::EType::svg + const auto svg_item_name = GLGizmosManager::convert_gizmo_type_to_string(static_cast(m_input.gizmo_type)); + canvas->force_main_toolbar_left_action(canvas->get_main_toolbar_item_id(svg_item_name)); + } - // redraw scene - canvas->reload_scene(true); + // redraw scene + canvas->reload_scene(true); + } } CreateSurfaceVolumeJob::CreateSurfaceVolumeJob(CreateSurfaceVolumeData &&input) : m_input(std::move(input)) {} @@ -495,7 +542,7 @@ CreateVolumeJob::CreateVolumeJob(DataCreateVolume &&input) : m_input(std::move(i void CreateVolumeJob::process(Ctl &ctl) { if (!check(m_input)) - throw std::runtime_error("Bad input data for EmbossCreateVolumeJob."); + throw JobException("Bad input data for EmbossCreateVolumeJob."); m_result = create_mesh(*m_input.base); } @@ -716,7 +763,7 @@ void create_volume( volume->calculate_convex_hull(); // set a default extruder value, since user can't add it manually - volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + volume->config.set_key_value("extruder", new ConfigOptionInt(1)); // do not allow model reload from disk volume->source.is_from_builtin_objects = true; @@ -799,10 +846,15 @@ OrthoProject3d create_emboss_projection(bool is_outside, float emboss, Transform } indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, const Transform3d &tr, const SurfaceVolumeData::ModelSources &sources, DataBase &input) +{ + return cut_surface_to_its(shapes, input.shape.scale, tr, sources, input); +} + +indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, float scale, const Transform3d &tr, const SurfaceVolumeData::ModelSources &sources, DataBase &input) { assert(!sources.empty()); BoundingBox bb = get_extents(shapes); - double shape_scale = input.shape.scale; + double shape_scale = scale; const SurfaceVolumeData::ModelSource *biggest = &sources.front(); @@ -828,7 +880,8 @@ indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, const Transfor s_to_itss[source_index] = its_index; itss.emplace_back(std::move(its)); } - if (itss.empty()) return {}; + if (itss.empty()) + return {}; Transform3d tr_inv = biggest->tr.inverse(); Transform3d cut_projection_tr = tr_inv * tr; @@ -837,8 +890,10 @@ indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, const Transfor BoundingBoxf3 mesh_bb = bounding_box(itss[itss_index]); for (const SurfaceVolumeData::ModelSource &s : sources) { itss_index = s_to_itss[&s - &sources.front()]; - if (itss_index == std::numeric_limits::max()) continue; - if (&s == biggest) continue; + if (itss_index == std::numeric_limits::max()) + continue; + if (&s == biggest) + continue; Transform3d tr = s.tr * tr_inv; bool fix_reflected = true; @@ -864,7 +919,8 @@ indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, const Transfor shapes_data = shapes; // copy for (ExPolygon &shape : shapes_data) { shape.contour.reverse(); - for (Slic3r::Polygon &hole : shape.holes) hole.reverse(); + for (Slic3r::Polygon &hole : shape.holes) + hole.reverse(); } shapes_ptr = &shapes_data; } @@ -1037,7 +1093,11 @@ const GLVolume *find_closest(const Selection &selection, const Vec2d &screen_cen double center_sq_distance = std::numeric_limits::max(); for (unsigned int id : indices) { const GLVolume *gl_volume = selection.get_volume(id); - if (const ModelVolume *volume = get_model_volume(*gl_volume, objects); volume == nullptr || !volume->is_model_part()) continue; + const ModelVolume *volume = get_model_volume(*gl_volume, objects); + if (volume == nullptr || !volume->is_model_part()) continue; + if (volume->is_text()) { + continue; + } Slic3r::Polygon hull = CameraUtils::create_hull2d(camera, *gl_volume); Vec2d c = hull.centroid().cast(); Vec2d d = c - screen_center; @@ -1198,6 +1258,767 @@ SurfaceVolumeData::ModelSources create_sources(const ModelVolumePtrs &volumes, s return result; } +const GLVolume *find_glvoloume_render_screen_cs(const Selection &selection, const Vec2d &screen_center, const Camera &camera, const ModelObjectPtrs &objects, Vec2d *closest_center) +{ + return find_closest(selection, screen_center, camera, objects, closest_center); } -} // namespace Slic3r::GUI -} // namespace Slic3r \ No newline at end of file + +ProjectTransform calc_project_tran(DataBase &input, double real_scale) +{ + double scale = real_scale; // 1e-6 + double depth = (input.shape.projection.depth + input.shape.projection.embeded_depth) / scale; + auto projectZ = std::make_unique(depth); + float offset = input.is_outside ? -SAFE_SURFACE_OFFSET : (SAFE_SURFACE_OFFSET - input.shape.projection.depth); + if (input.from_surface.has_value()) offset += *input.from_surface; + Transform3d tr = Eigen::Translation(0., 0., static_cast(offset)) * Eigen::Scaling(scale); + ProjectTransform project_tr(std::move(projectZ), tr); + return project_tr; +} + +void create_all_char_mesh(DataBase &input, std::vector &result, EmbossShape &shape) +{ + shape = input.create_shape();//this will call letter2shapes + if (shape.shapes_with_ids.empty()) + return; + result.clear(); + auto first_project_tr = calc_project_tran(input, input.shape.scale); + + TextConfiguration text_configuration = input.get_text_configuration(); + bool support_backup_fonts = std::any_of(shape.text_scales.begin(), shape.text_scales.end(), [](float x) { return x > 0; }); + const char *text = input.get_text_configuration().text.c_str(); + wxString input_text = wxString::FromUTF8(input.get_text_configuration().text); + wxRegEx re("^ +$"); + bool is_all_space = re.Matches(input_text); + if (is_all_space) { return; } + if (input_text.size() != shape.shapes_with_ids.size()) { + BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< "error: input_text.size() != shape.shapes_with_ids.size()"; + } + for (int i = 0; i < shape.shapes_with_ids.size(); i++) { + auto &temp_shape = shape.shapes_with_ids[i]; + if (input_text[i] == ' ') { + result.emplace_back(TriangleMesh()); + continue; + } + if (temp_shape.expoly.empty()) + continue; + if (support_backup_fonts) { + if (i < shape.text_scales.size() && shape.text_scales[i] > 0) { + auto temp_scale = shape.text_scales[i]; + + auto temp_project_tr = calc_project_tran(input, temp_scale); + TriangleMesh mesh(polygons2model(temp_shape.expoly, temp_project_tr)); + result.emplace_back(mesh); + } else { + TriangleMesh mesh(polygons2model(temp_shape.expoly, first_project_tr)); + result.emplace_back(mesh); + } + } else { + TriangleMesh mesh(polygons2model(temp_shape.expoly, first_project_tr)); + result.emplace_back(mesh); + } + } +} + +float get_single_char_width(const std::vector &chars_mesh_result) +{ + for (int i = 0; i < chars_mesh_result.size(); ++i) { + auto box = chars_mesh_result[i].bounding_box(); + auto box_size = box.size(); + auto half_x_length = box_size[0] / 2.0f; + if (half_x_length > 0.01) { + return half_x_length; + } + } + return 0.f; +} + +bool calc_text_lengths(std::vector &text_lengths, const std::vector &chars_mesh_result) +{ + text_lengths.clear(); + auto single_char_width = get_single_char_width(chars_mesh_result); + if (single_char_width < 0.01) { return false; } + for (int i = 0; i < chars_mesh_result.size(); ++i) { + auto box = chars_mesh_result[i].bounding_box(); + auto box_size = box.size(); + auto half_x_length = box_size[0] / 2.0f; + if (half_x_length < 0.01) { + text_lengths.emplace_back(single_char_width + 1); + } else { + text_lengths.emplace_back(half_x_length + 1); + } + } + return true; +} + +void calc_position_points(std::vector &position_points, std::vector &text_lengths, float text_gap, const Vec3d &temp_pos_dir) +{ + auto text_num = text_lengths.size(); + if (text_num == 0) { + throw JobException("calc_position_points fail."); + return; + } + if (position_points.size() != text_lengths.size()) { position_points.resize(text_num); } + auto pos_dir = temp_pos_dir.normalized(); + + if (text_num % 2 == 1) { + position_points[text_num / 2] = Vec3d::Zero(); + for (int i = 0; i < text_num / 2; ++i) { + double left_gap = text_lengths[text_num / 2 - i - 1] + text_gap + text_lengths[text_num / 2 - i]; + if (left_gap < 0) + left_gap = 0; + + double right_gap = text_lengths[text_num / 2 + i + 1] + text_gap + text_lengths[text_num / 2 + i]; + if (right_gap < 0) + right_gap = 0; + + position_points[text_num / 2 - 1 - i] = position_points[text_num / 2 - i] - left_gap * pos_dir; + position_points[text_num / 2 + 1 + i] = position_points[text_num / 2 + i] + right_gap * pos_dir; + } + } else { + for (int i = 0; i < text_num / 2; ++i) { + double left_gap = i == 0 ? (text_lengths[text_num / 2 - i - 1] + text_gap / 2) : (text_lengths[text_num / 2 - i - 1] + text_gap + text_lengths[text_num / 2 - i]); + if (left_gap < 0) + left_gap = 0; + + double right_gap = i == 0 ? (text_lengths[text_num / 2 + i] + text_gap / 2) : (text_lengths[text_num / 2 + i] + text_gap + text_lengths[text_num / 2 + i - 1]); + if (right_gap < 0) + right_gap = 0; + + if (i == 0) { + position_points[text_num / 2 - 1 - i] = Vec3d::Zero() - left_gap * pos_dir; + position_points[text_num / 2 + i] = Vec3d::Zero() + right_gap * pos_dir; + continue; + } + + position_points[text_num / 2 - 1 - i] = position_points[text_num / 2 - i] - left_gap * pos_dir; + position_points[text_num / 2 + i] = position_points[text_num / 2 + i - 1] + right_gap * pos_dir; + } + } +} + +GenerateTextJob::GenerateTextJob(InputInfo &&input) : m_input(std::move(input)) {} +std::vector GenerateTextJob::debug_cut_points_in_world; +void GenerateTextJob::process(Ctl &ctl) +{ + auto canceled = was_canceled(ctl, *m_input.m_data_update.base); + if (canceled) + return; + create_all_char_mesh(*m_input.m_data_update.base, m_input.m_chars_mesh_result, m_input.m_text_shape); + if (m_input.m_chars_mesh_result.empty()) { + return; + } + if (!update_text_positions(m_input)) { + throw JobException("update_text_positions fail."); + } + if (!generate_text_points(m_input)) + throw JobException("generate_text_volume fail."); + GenerateTextJob::debug_cut_points_in_world = m_input.m_cut_points_in_world; + if (m_input.use_surface) { + if (m_input.m_text_shape.shapes_with_ids.empty()) + throw JobException(_u8L("Font doesn't have any shape for given text.").c_str()); + } + generate_mesh_according_points(m_input); +} + +void GenerateTextJob::finalize(bool canceled, std::exception_ptr &eptr) +{ + if (canceled || eptr) + return; + if (m_input.first_generate) { + create_text_volume(m_input.mo, m_input.m_final_text_mesh, m_input.m_final_text_tran_in_object, m_input.text_info); + auto model_object = m_input.mo; + m_input.m_volume_idx; + auto volume_idx = model_object->volumes.size() - 1; + ModelVolume * model_volume = model_object->volumes[volume_idx]; + auto add_to_selection = [model_volume](const ModelVolume *vol) { return vol == model_volume; }; + ObjectList * obj_list = wxGetApp().obj_list(); + int object_idx = wxGetApp().plater()->get_selected_object_idx(); + wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(object_idx, add_to_selection); + if (!sel.IsEmpty()) { + obj_list->select_item(sel.front()); + } + + obj_list->selection_changed(); + + GLCanvas3D * canvas = wxGetApp().plater()->get_view3D_canvas3D(); + GLGizmosManager &manager = canvas->get_gizmos_manager(); + if (manager.get_current_type() != GLGizmosManager::EType::Text) { + manager.open_gizmo(GLGizmosManager::EType::Text); + } + } else { + recreate_model_volume(m_input.mo, m_input.m_volume_idx, m_input.m_final_text_mesh, m_input.m_final_text_tran_in_object, m_input.text_info); + } +} + +bool GenerateTextJob::update_text_positions(InputInfo &input_info) +{ + if (input_info.m_chars_mesh_result.size() == 0) { + input_info.m_position_points.clear(); + return false; + } + std::vector text_lengths; + if (!calc_text_lengths(text_lengths, input_info.m_chars_mesh_result)) { + return false; + } + int text_num = input_info.m_chars_mesh_result.size(); // FIX by BBS 20250109 + input_info.m_position_points.clear(); + input_info.m_normal_points.clear(); + /*auto mouse_position_world = m_text_position_in_world.cast(); + auto mouse_normal_world = m_text_normal_in_world.cast();*/ + input_info.m_position_points.resize(text_num); + input_info.m_normal_points.resize(text_num); + + input_info.text_lengths = text_lengths; + input_info.m_surface_type = GenerateTextJob::SurfaceType::None; + if (input_info.text_surface_type == TextInfo::TextType::HORIZONAL) { + input_info.use_surface = false; + Vec3d mouse_normal_world = input_info.m_text_normal_in_world.cast(); + Vec3d world_pos_dir = input_info.m_cut_plane_dir_in_world.cross(mouse_normal_world); + auto inv_ = (input_info.m_model_object_in_world_tran.get_matrix_no_offset() * input_info.m_text_tran_in_object.get_matrix_no_offset()).inverse(); + Vec3d pos_dir = Vec3d::UnitX(); + auto mouse_normal_local = inv_ * mouse_normal_world; + mouse_normal_local.normalize(); + + calc_position_points(input_info.m_position_points, text_lengths, input_info.m_text_gap, pos_dir); + + for (int i = 0; i < text_num; ++i) { + input_info.m_normal_points[i] = mouse_normal_local; + } + return true; + } + input_info.m_surface_type = GenerateTextJob::SurfaceType::Surface; + return true; +} + +bool GenerateTextJob::generate_text_points(InputInfo &input_info) +{ + if (input_info.m_surface_type == GenerateTextJob::SurfaceType::None) { + return true; + } + auto &m_text_tran_in_object = input_info.m_text_tran_in_object; + auto mo = input_info.mo; + auto &m_volume_idx = input_info.m_volume_idx; + auto &m_position_points = input_info.m_position_points; + auto &m_normal_points = input_info.m_normal_points; + auto &m_cut_points_in_world = input_info.m_cut_points_in_world; + std::vector m_cut_points_in_local; + auto &m_text_cs_to_world_tran = input_info.m_text_tran_in_world.get_matrix(); + auto &m_chars_mesh_result = input_info.m_chars_mesh_result; + auto &m_text_position_in_world = input_info.m_text_position_in_world; + auto &m_text_normal_in_world = input_info.m_text_normal_in_world; + auto &m_text_gap = input_info.m_text_gap; + auto &m_model_object_in_world_tran = input_info.m_model_object_in_world_tran; + auto &text_lengths = input_info.text_lengths; + //auto hit_mesh_id = input_info.hit_mesh_id;//m_rr.mesh_id + //calc + TriangleMesh slice_meshs; + int mesh_index = 0; + for (int i = 0; i < mo->volumes.size(); ++i) { + ModelVolume *mv = mo->volumes[i]; + if (m_volume_idx == i) { + continue; + } + if (mv->is_text()) { + continue; + } + if (mv->is_model_part()) { + TriangleMesh vol_mesh(mv->mesh()); + vol_mesh.transform(mv->get_matrix()); + slice_meshs.merge(vol_mesh); + mesh_index++; + } + } + auto text_tran_in_object = m_text_tran_in_object; // important + input_info.slice_mesh = slice_meshs; + auto rotate_tran = Geometry::assemble_transform(Vec3d::Zero(), {-0.5 * M_PI, 0.0, 0.0}); + MeshSlicingParams slicing_params; + auto cut_tran = (text_tran_in_object.get_matrix() * rotate_tran); + slicing_params.trafo = cut_tran.inverse(); + // for debug + // its_write_obj(slice_meshs.its, "D:/debug_files/mesh.obj"); + // generate polygons + const Polygons temp_polys = slice_mesh(slice_meshs.its, 0, slicing_params); + Vec3d scale_click_pt(scale_(0), scale_(0), 0); + // for debug + // export_regions_to_svg(Point(scale_pt.x(), scale_pt.y()), temp_polys); + Polygons polys = union_(temp_polys); + + auto point_in_line_rectange = [](const Line &line, const Point &point, double &distance) { + distance = line.distance_to(point); + return distance < line.length() / 2; + }; + + int index = 0; + double min_distance = 1e12; + Polygon hit_ploy; + for (const Polygon poly : polys) { + if (poly.points.size() == 0) + continue; + Lines lines = poly.lines(); + for (int i = 0; i < lines.size(); ++i) { + Line line = lines[i]; + double distance = min_distance; + if (point_in_line_rectange(line, Point(scale_click_pt.x(), scale_click_pt.y()), distance)) { + if (distance < min_distance) { + min_distance = distance; + index = i; + hit_ploy = poly; + } + } + } + } + + if (hit_ploy.points.size() == 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("Text: the hit polygon is null,") << "x:" << m_text_position_in_world.x() << ",y:" << m_text_position_in_world.y() + << ",z:" << m_text_position_in_world.z(); + throw JobException("The hit polygon is null,please try to regenerate after adjusting text position."); + return false; + } + int text_num = m_chars_mesh_result.size(); + + auto world_tran = m_model_object_in_world_tran * text_tran_in_object; + m_cut_points_in_world.clear(); + m_cut_points_in_world.reserve(hit_ploy.points.size()); + m_cut_points_in_local.clear(); + m_cut_points_in_local.reserve(hit_ploy.points.size()); + for (int i = 0; i < hit_ploy.points.size(); ++i) { + m_cut_points_in_local.emplace_back(rotate_tran * Vec3d(unscale_(hit_ploy.points[i].x()), unscale_(hit_ploy.points[i].y()), 0)); // m_text_cs_to_world_tran * + m_cut_points_in_world.emplace_back(world_tran.get_matrix() * m_cut_points_in_local.back()); + } + + Slic3r::Polygon_3D new_polygon(m_cut_points_in_local); + m_position_points.resize(text_num); + if (text_num % 2 == 1) { + m_position_points[text_num / 2] = Vec3d::Zero(); + std::vector lines = new_polygon.get_lines(); + Line_3D line = lines[index]; + auto min_dist = 1e6; + {// Find the nearest tangent point + for (int i = 0; i < lines.size(); i++) { + Line_3D temp_line = lines[i]; + Vec3d intersection_pt; + float proj_length; + auto pt = Vec3d::Zero(); + Linef3::get_point_projection_to_line(pt, temp_line.a, temp_line.vector(), intersection_pt, proj_length); + auto dist = (intersection_pt - pt).norm(); + if (min_dist > dist) { + min_dist = dist; + m_position_points[text_num / 2] = intersection_pt; + } + } + } + { + int index1 = index; + double left_length = (Vec3d::Zero() - line.a).cast().norm(); + int left_num = text_num / 2; + while (left_num > 0) { + double gap_length = (text_lengths[left_num] + m_text_gap + text_lengths[left_num - 1]); + if (gap_length < 0) gap_length = 0; + + while (gap_length > left_length) { + gap_length -= left_length; + if (index1 == 0) + index1 = lines.size() - 1; + else + --index1; + left_length = lines[index1].length(); + } + + Vec3d direction = lines[index1].vector(); + direction.normalize(); + double distance_to_a = (left_length - gap_length); + Line_3D new_line = lines[index1]; + + double norm_value = direction.cast().norm(); + double deta_x = distance_to_a * direction.x() / norm_value; + double deta_y = distance_to_a * direction.y() / norm_value; + double deta_z = distance_to_a * direction.z() / norm_value; + Vec3d new_pos = new_line.a + Vec3d(deta_x, deta_y, deta_z); + left_num--; + m_position_points[left_num] = new_pos; + left_length = distance_to_a; + } + } + + { + int index2 = index; + double right_length = (line.b - Vec3d::Zero()).cast().norm(); + int right_num = text_num / 2; + while (right_num > 0) { + double gap_length = (text_lengths[text_num - right_num] + m_text_gap + text_lengths[text_num - right_num - 1]); + if (gap_length < 0) gap_length = 0; + + while (gap_length > right_length) { + gap_length -= right_length; + if (index2 == lines.size() - 1) + index2 = 0; + else + ++index2; + right_length = lines[index2].length(); + } + + Line_3D line2 = lines[index2]; + line2.reverse(); + Vec3d direction = line2.vector(); + direction.normalize(); + double distance_to_b = (right_length - gap_length); + Line_3D new_line = lines[index2]; + + double norm_value = direction.cast().norm(); + double deta_x = distance_to_b * direction.x() / norm_value; + double deta_y = distance_to_b * direction.y() / norm_value; + double deta_z = distance_to_b * direction.z() / norm_value; + Vec3d new_pos = new_line.b + Vec3d(deta_x, deta_y, deta_z); + m_position_points[text_num - right_num] = new_pos; + right_length = distance_to_b; + right_num--; + } + } + } else { + for (int i = 0; i < text_num / 2; ++i) { + std::vector lines = new_polygon.get_lines(); + Line_3D line = lines[index]; + { + int index1 = index; + double left_length = (Vec3d::Zero() - line.a).cast().norm(); + int left_num = text_num / 2; + for (int i = 0; i < text_num / 2; ++i) { + double gap_length = 0; + if (i == 0) { + gap_length = m_text_gap / 2 + text_lengths[text_num / 2 - 1 - i]; + } else { + gap_length = text_lengths[text_num / 2 - i] + m_text_gap + text_lengths[text_num / 2 - 1 - i]; + } + if (gap_length < 0) gap_length = 0; + + while (gap_length > left_length) { + gap_length -= left_length; + if (index1 == 0) + index1 = lines.size() - 1; + else + --index1; + left_length = lines[index1].length(); + } + + Vec3d direction = lines[index1].vector(); + direction.normalize(); + double distance_to_a = (left_length - gap_length); + Line_3D new_line = lines[index1]; + + double norm_value = direction.cast().norm(); + double deta_x = distance_to_a * direction.x() / norm_value; + double deta_y = distance_to_a * direction.y() / norm_value; + double deta_z = distance_to_a * direction.z() / norm_value; + Vec3d new_pos = new_line.a + Vec3d(deta_x, deta_y, deta_z); + + m_position_points[text_num / 2 - 1 - i] = new_pos; + left_length = distance_to_a; + } + } + + { + int index2 = index; + double right_length = (line.b - Vec3d::Zero()).cast().norm(); + int right_num = text_num / 2; + double gap_length = 0; + for (int i = 0; i < text_num / 2; ++i) { + double gap_length = 0; + if (i == 0) { + gap_length = m_text_gap / 2 + text_lengths[text_num / 2 + i]; + } else { + gap_length = text_lengths[text_num / 2 + i] + m_text_gap + text_lengths[text_num / 2 + i - 1]; + } + if (gap_length < 0) gap_length = 0; + + while (gap_length > right_length) { + gap_length -= right_length; + if (index2 == lines.size() - 1) + index2 = 0; + else + ++index2; + right_length = lines[index2].length(); + } + + Line_3D line2 = lines[index2]; + line2.reverse(); + Vec3d direction = line2.vector(); + direction.normalize(); + double distance_to_b = (right_length - gap_length); + Line_3D new_line = lines[index2]; + + double norm_value = direction.cast().norm(); + double deta_x = distance_to_b * direction.x() / norm_value; + double deta_y = distance_to_b * direction.y() / norm_value; + double deta_z = distance_to_b * direction.z() / norm_value; + Vec3d new_pos = new_line.b + Vec3d(deta_x, deta_y, deta_z); + m_position_points[text_num / 2 + i] = new_pos; + right_length = distance_to_b; + } + } + } + } + + std::vector mesh_values(m_position_points.size(), 1e9); + m_normal_points.resize(m_position_points.size()); + auto point_in_triangle_delete_area = [](const Vec3d &point, const Vec3d &point0, const Vec3d &point1, const Vec3d &point2) { + Vec3d p0_p = point - point0; + Vec3d p0_p1 = point1 - point0; + Vec3d p0_p2 = point2 - point0; + Vec3d p_p0 = point0 - point; + Vec3d p_p1 = point1 - point; + Vec3d p_p2 = point2 - point; + + double s = p0_p1.cross(p0_p2).norm(); + double s0 = p_p0.cross(p_p1).norm(); + double s1 = p_p1.cross(p_p2).norm(); + double s2 = p_p2.cross(p_p0).norm(); + + return abs(s0 + s1 + s2 - s); + }; + bool is_mirrored = (m_model_object_in_world_tran * text_tran_in_object).is_left_handed(); + slice_meshs.transform(text_tran_in_object.get_matrix().inverse()); + TriangleMesh& mesh = slice_meshs; + std::vector debug_incides; + debug_incides.resize(m_position_points.size()); + for (int i = 0; i < m_position_points.size(); ++i) { + int debug_index = 0; + for (auto indice : mesh.its.indices) { + stl_vertex stl_point0 = mesh.its.vertices[indice[0]]; + stl_vertex stl_point1 = mesh.its.vertices[indice[1]]; + stl_vertex stl_point2 = mesh.its.vertices[indice[2]]; + + Vec3d point0 = stl_point0.cast(); + Vec3d point1 = stl_point1.cast(); + Vec3d point2 = stl_point2.cast(); + + double abs_area = point_in_triangle_delete_area(m_position_points[i], point0, point1, point2); + if (mesh_values[i] > abs_area) { + mesh_values[i] = abs_area; + debug_incides[i] = debug_index; + Vec3d s1 = point1 - point0; + Vec3d s2 = point2 - point0; + m_normal_points[i] = s1.cross(s2); + m_normal_points[i].normalize(); + if (is_mirrored) { + m_normal_points[i] = -m_normal_points[i]; + } + } + debug_index++; + } + } + return true; +} + + Geometry::Transformation GenerateTextJob::get_sub_mesh_tran(const Vec3d &position, const Vec3d &normal, const Vec3d &text_up_dir, float embeded_depth) +{ + double phi; + Vec3d rotation_axis; + Matrix3d rotation_matrix; + Geometry::rotation_from_two_vectors(Vec3d::UnitZ(), normal, rotation_axis, phi, &rotation_matrix); + Geometry::Transformation local_tran; + Transform3d temp_tran0(Transform3d::Identity()); + temp_tran0.rotate(Eigen::AngleAxisd(phi, rotation_axis.normalized())); + + auto project_on_plane = [](const Vec3d &dir, const Vec3d &plane_normal) -> Vec3d { return dir - (plane_normal.dot(dir) * plane_normal.dot(plane_normal)) * plane_normal; }; + + Vec3d old_text_dir = Vec3d::UnitY(); + old_text_dir = rotation_matrix * old_text_dir; + Vec3d new_text_dir = project_on_plane(text_up_dir, normal); + new_text_dir.normalize(); + Geometry::rotation_from_two_vectors(old_text_dir, new_text_dir, rotation_axis, phi, &rotation_matrix); + + if (abs(phi - PI) < EPSILON) + rotation_axis = normal; + + Transform3d temp_tran1(Transform3d::Identity()); + temp_tran1.rotate(Eigen::AngleAxisd(phi, rotation_axis.normalized())); + local_tran.set_matrix(temp_tran1 * temp_tran0); + + Vec3d offset = position - embeded_depth * normal; + local_tran.set_offset(offset); + return local_tran; +} + +void GenerateTextJob::get_text_mesh(TriangleMesh &result_mesh, std::vector &chars_mesh, int i, Geometry::Transformation &local_tran) +{ + if (chars_mesh.size() == 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("check error:get_text_mesh"); + } + TriangleMesh mesh = chars_mesh[i]; // m_cur_font_name + auto box = mesh.bounding_box(); + mesh.translate(-box.center().x(), 0, 0); + + mesh.transform(local_tran.get_matrix()); + result_mesh = mesh; // mesh in object cs +} + +void GenerateTextJob::get_text_mesh(TriangleMesh & result_mesh, + EmbossShape & text_shape, + BoundingBoxes & line_qds, + SurfaceVolumeData::ModelSources &input_ms_es, + DataBase & input_db, + int i, + Geometry::Transformation &mv_tran, + Geometry::Transformation &local_tran_to_object_cs, + TriangleMesh & slice_mesh) +{ + ExPolygons glyph_shape = text_shape.shapes_with_ids[i].expoly; + const BoundingBox &glyph_bb = line_qds[i]; + Point offset(-glyph_bb.center().x(), 0); + for (ExPolygon &s : glyph_shape) { + s.translate(offset); + } + auto modify = local_tran_to_object_cs.get_matrix(); + Transform3d tr = mv_tran.get_matrix() * modify; + float text_scale = input_db.shape.scale; + if (i < text_shape.text_scales.size() && text_shape.text_scales[i] > 0) { + text_scale = text_shape.text_scales[i]; + } + indexed_triangle_set glyph_its = cut_surface_to_its(glyph_shape, text_scale, tr, input_ms_es, input_db); + if (glyph_its.empty()) { + BOOST_LOG_TRIVIAL(info) << boost::format("check error:get_text_mesh"); + } + // move letter in volume on the right position + its_transform(glyph_its, modify); + + // Improve: union instead of merge + //its_merge(result, std::move(glyph_its)); + result_mesh = TriangleMesh(glyph_its); +} + +void GenerateTextJob::generate_mesh_according_points(InputInfo &input_info) +{ + auto &m_position_points = input_info.m_position_points; + auto &m_normal_points = input_info.m_normal_points; + auto &m_cut_plane_dir_in_world = input_info.m_cut_plane_dir_in_world; + auto &m_chars_mesh_result = input_info.m_chars_mesh_result; + auto &m_embeded_depth = input_info.m_embeded_depth; + auto &m_thickness = input_info.m_thickness; + auto &m_model_object_in_world_tran = input_info.m_model_object_in_world_tran; + auto &m_text_tran_in_object = input_info.m_text_tran_in_object; + auto &mesh = input_info.m_final_text_mesh; + mesh.clear(); + auto text_tran_in_object = m_text_tran_in_object; // important + auto inv_text_cs_in_object_no_offset = (m_model_object_in_world_tran.get_matrix_no_offset() * text_tran_in_object.get_matrix_no_offset()).inverse(); + + ExPolygons ex_polygons; + std::vector qds; + int line_idx = 0; + SurfaceVolumeData::ModelSources ms_es; + DataBase input_db("", std::make_shared>(false)); + if (input_info.use_surface) { + EmbossShape &es = input_info.m_text_shape; + if (es.shapes_with_ids.empty()) + throw JobException(_u8L("Font doesn't have any shape for given text.").c_str()); + size_t count_lines = 1; // input1.text_lines.size(); + qds = create_line_bounds(es.shapes_with_ids, count_lines); + if (qds.empty()) { + return; + } + SurfaceVolumeData::ModelSource ms; + ms.mesh = std::make_shared (input_info.slice_mesh); + if (ms.mesh->empty()) { + return; + } + ms_es.push_back(ms); + input_db.is_outside = input_info.is_outside; + input_db.shape.projection.depth = m_thickness + m_embeded_depth; + input_db.shape.scale = input_info.shape_scale; + } + auto cut_plane_dir = inv_text_cs_in_object_no_offset * m_cut_plane_dir_in_world; + for (int i = 0; i < m_position_points.size(); ++i) { + auto position = m_position_points[i]; + auto normal = m_normal_points[i]; + TriangleMesh sub_mesh; + auto local_tran = get_sub_mesh_tran(position, normal, cut_plane_dir, m_embeded_depth); + if (input_info.use_surface) { + get_text_mesh(sub_mesh, input_info.m_text_shape, qds[line_idx], ms_es, input_db, i, text_tran_in_object, local_tran, input_info.slice_mesh); + } + else { + get_text_mesh(sub_mesh, m_chars_mesh_result, i, local_tran); + } + mesh.merge(sub_mesh); + } + if (mesh.its.empty()){ + throw JobException(_u8L("Text mesh ie empty.").c_str()); + return; + } + //ASCENT_CENTER = 1 / 2.5;// mesh.translate(Vec3f(0, -center.y(), 0)); // align vertical center +} + +CreateObjectTextJob::CreateObjectTextJob(CreateTextInput &&input) : m_input(std::move(input)) {} + +void CreateObjectTextJob::process(Ctl &ctl) { + create_all_char_mesh(*m_input.base, m_input.m_chars_mesh_result, m_input.m_text_shape); + if (m_input.m_chars_mesh_result.empty()) { + return; + } + std::vector text_lengths; + calc_text_lengths(text_lengths, m_input.m_chars_mesh_result); + calc_position_points(m_input.m_position_points, text_lengths, m_input.text_info.m_text_gap, Vec3d(1, 0, 0)); +} + +void CreateObjectTextJob::finalize(bool canceled, std::exception_ptr &eptr) { + if (canceled || eptr) return; + if (m_input.m_position_points.empty()) + return create_message("Can't create empty object."); + + TriangleMesh final_mesh; + for (int i = 0; i < m_input.m_position_points.size();i++) { + TriangleMesh sub_mesh; + auto position = m_input.m_position_points[i]; + auto local_tran = GenerateTextJob::get_sub_mesh_tran(position, Vec3d::UnitZ(), Vec3d(0, 1, 0), m_input.text_info.m_embeded_depth); + GenerateTextJob::get_text_mesh(sub_mesh, m_input.m_chars_mesh_result, i, local_tran); + final_mesh.merge(sub_mesh); + } + + GUI_App &app = wxGetApp(); + Plater * plater = app.plater(); + plater->take_snapshot("Add text object on plate"); + auto center = plater->get_partplate_list().get_curr_plate()->get_bounding_box().center(); + Model &model = plater->model(); + { + // INFO: inspiration for create object is from ObjectList::load_mesh_object() + ModelObject *new_object = model.add_object(); + new_object->name = _u8L("Text"); + new_object->add_instance(); // each object should have at list one instance + new_object->invalidate_bounding_box(); + + ModelVolume *new_volume = new_object->add_volume(std::move(final_mesh), false); + new_volume->calculate_convex_hull(); + new_volume->name = _u8L("Text"); + // set a default extruder value, since user can't add it manually + new_volume->config.set_key_value("extruder", new ConfigOptionInt(1)); + m_input.text_info.m_surface_type = TextInfo::TextType ::HORIZONAL; + new_volume->set_text_info(m_input.text_info); + // write emboss data into volume + m_input.base->write(*new_volume); + + // set transformation + Slic3r::Geometry::Transformation tr; + tr.set_offset(center); + new_object->instances.front()->set_transformation(tr); + new_object->ensure_on_bed(); + + Slic3r::save_object_mesh(*new_object); + new_object->get_model()->set_assembly_pos(new_object); + // Actualize right panel and set inside of selection + app.obj_list()->paste_objects_into_list({model.objects.size() - 1}); + } +#ifdef _DEBUG + check_model_ids_validity(model); +#endif /* _DEBUG */ + + // When add new object selection is empty. + // When cursor move and no one object is selected than + // Manager::reset_all() So Gizmo could be closed before end of creation object + GLCanvas3D * canvas = plater->get_view3D_canvas3D(); + GLGizmosManager &manager = canvas->get_gizmos_manager(); + if (manager.get_current_type() != GLGizmosManager::EType::Text) + manager.open_gizmo(GLGizmosManager::EType::Text); + + // redraw scene + canvas->reload_scene(true); +} + +}}} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp index 0732726..21d1480 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.hpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp @@ -49,7 +49,7 @@ public: /// /// Data object for store emboss params virtual void write(ModelVolume &volume) const; - + virtual TextConfiguration get_text_configuration() { return {}; } // Define projection move // True (raised) .. move outside from surface (MODEL_PART) // False (engraved).. move into object (NEGATIVE_VOLUME) @@ -176,7 +176,7 @@ struct SurfaceVolumeData // source volumes std::shared_ptr mesh; // Transformation of volume inside of object - Transform3d tr; + Transform3d tr{Transform3d::Identity()}; }; using ModelSources = std::vector; ModelSources sources; @@ -261,6 +261,30 @@ public: void process(Ctl &ctl) override; void finalize(bool canceled, std::exception_ptr &eptr) override; }; +struct CreateTextInput +{ + std::vector m_chars_mesh_result; + EmbossShape m_text_shape; + TextInfo text_info; + DataBasePtr base; + + std::vector m_position_points; +}; + +class CreateObjectTextJob : public JobNew +{ + CreateTextInput m_input; +public: + explicit CreateObjectTextJob(CreateTextInput &&input); + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &eptr) override; +}; + +const GLVolume *find_glvoloume_render_screen_cs(const Selection &selection, const Vec2d &screen_center, const Camera &camera, const ModelObjectPtrs &objects, Vec2d *closest_center); +void create_all_char_mesh(DataBase &input, std::vector &result, EmbossShape &shape); +float get_single_char_width( const std::vector &chars_mesh_result); +bool calc_text_lengths(std::vector &text_lengths,const std::vector& chars_mesh_result); +void calc_position_points(std::vector &position_points, std::vector &text_lengths, float text_gap, const Vec3d &temp_pos_dir); struct Texture { @@ -304,6 +328,81 @@ public: void process(Ctl &ctl) override; void finalize(bool canceled, std::exception_ptr &eptr) override; }; + +void recreate_model_volume(Slic3r::ModelObject *model_object, int volume_idx, const TriangleMesh &mesh, Geometry::Transformation &text_tran, TextInfo &text_info); +void create_text_volume(Slic3r::ModelObject *model_object, const TriangleMesh &mesh, Geometry::Transformation &text_tran, TextInfo &text_info); +class GenerateTextJob : public JobNew +{ +public: + enum SurfaceType { + None, + Surface, + CharSurface, + }; + struct InputInfo + { + Geometry::Transformation m_text_tran_in_object; + Geometry::Transformation m_model_object_in_world_tran; + ModelObject * mo{nullptr}; + int m_volume_idx; + int hit_mesh_id; + std::vector m_position_points; + std::vector m_normal_points; + std::vector m_cut_points_in_world; + std::vector m_cut_points_in_local; + Geometry::Transformation m_text_tran_in_world; // Transform3d m_text_cs_to_world_tran; + //Transform3d m_object_cs_to_world_tran; + std::vector m_chars_mesh_result; + Vec3d m_text_position_in_world; + Vec3f m_text_normal_in_world; + float m_text_gap; + std::vector text_lengths; + + Vec3d m_cut_plane_dir_in_world; + float m_thickness = 2.f; + float m_embeded_depth = 0.f; + SurfaceType m_surface_type = SurfaceType::None; + TextInfo::TextType text_surface_type; + + TriangleMesh m_final_text_mesh; + Geometry::Transformation m_final_text_tran_in_object; + TextInfo text_info; + + TriangleMesh slice_mesh; + EmbossShape m_text_shape; + bool use_surface = false; + float shape_scale; + bool is_outside = true;//bool is_outside = (type == ModelVolumeType::MODEL_PART); + + bool first_generate = false; + Emboss::DataUpdate m_data_update; + + }; + static bool update_text_positions(InputInfo &input_info); + static bool generate_text_points(InputInfo &input_info); + static Geometry::Transformation get_sub_mesh_tran(const Vec3d &position, const Vec3d &normal, const Vec3d &text_up_dir, float embeded_depth); + static void get_text_mesh(TriangleMesh &result_mesh, std::vector &chars_mesh, int i, Geometry::Transformation& local_tran); + static void get_text_mesh(TriangleMesh & result_mesh, + EmbossShape & text_shape, + BoundingBoxes & line_qds, + SurfaceVolumeData::ModelSources& input_ms_es, + DataBase &input_db, + int i, + Geometry::Transformation &mv_tran, + Geometry::Transformation &local_tran_to_object_cs, + TriangleMesh & slice_mesh); + static void generate_mesh_according_points(InputInfo& input_info); + static std::vector debug_cut_points_in_world; + +public: + explicit GenerateTextJob(InputInfo &&input); + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &eptr) override; + +private: + InputInfo m_input; +}; + static bool check(unsigned char gizmo_type); static bool check(const DataBase &input, bool check_fontfile, bool use_surface = false); static bool check(const CreateVolumeParams &input); @@ -323,6 +422,7 @@ static TriangleMesh try_create_mesh(DataBase &input); static TriangleMesh create_mesh(DataBase &input); static std::vector create_meshs(DataBase &input); static indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, const Transform3d &tr, const SurfaceVolumeData::ModelSources &sources, DataBase &input); +static indexed_triangle_set cut_surface_to_its(const ExPolygons &shapes, float scale, const Transform3d &tr, const SurfaceVolumeData::ModelSources &sources, DataBase &input); static TriangleMesh cut_per_glyph_surface(DataBase &input1, const SurfaceVolumeData &input2); static TriangleMesh cut_surface(DataBase &input1, const SurfaceVolumeData &input2); static void _update_volume(TriangleMesh &&mesh, const DataUpdate &data, const Transform3d *tr = nullptr); diff --git a/src/slic3r/GUI/Jobs/PrintJob.cpp b/src/slic3r/GUI/Jobs/PrintJob.cpp index cadc474..d6ba4c7 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.cpp +++ b/src/slic3r/GUI/Jobs/PrintJob.cpp @@ -50,7 +50,6 @@ void PrintJob::prepare() if (&job_data) { std::string temp_file = Slic3r::resources_dir() + "/check_access_code.txt"; auto check_access_code_path = temp_file.c_str(); - BOOST_LOG_TRIVIAL(trace) << "sned_job: check_access_code_path = " << check_access_code_path; job_data._temp_path = fs::path(check_access_code_path); } @@ -140,7 +139,7 @@ wxString PrintJob::get_http_error_msg(unsigned int status, std::string body) ; } return wxEmptyString; -} +} void PrintJob::process() { @@ -256,6 +255,7 @@ void PrintJob::process() params.auto_bed_leveling = this->auto_bed_leveling; params.auto_flow_cali = this->auto_flow_cali; params.auto_offset_cali = this->auto_offset_cali; + params.task_ext_change_assist = this->task_ext_change_assist; if (m_print_type == "from_sdcard_view") { params.dst_file = m_dst_path; @@ -299,6 +299,7 @@ void PrintJob::process() std::regex pattern("_+"); params.project_name = std::regex_replace(mall_model_name, pattern, "_"); + params.project_name = truncate_string(params.project_name, 100); } catch (...) {} } @@ -356,8 +357,6 @@ void PrintJob::process() } } - - 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;} @@ -383,12 +382,12 @@ void PrintJob::process() bool is_try_lan_mode = false; bool is_try_lan_mode_failed = false; - auto update_fn = [this, + auto update_fn = [this, &is_try_lan_mode, &is_try_lan_mode_failed, - &msg, - &error_str, - &curr_percent, + &msg, + &error_str, + &curr_percent, &error_text, StagePercentPoint ](int stage, int code, std::string info) { @@ -471,7 +470,7 @@ void PrintJob::process() return was_canceled(); }; - + DeviceManager* dev = wxGetApp().getDeviceManager(); MachineObject* obj = dev->get_selected_machine(); @@ -593,7 +592,7 @@ void PrintJob::process() this->update_status(curr_percent, _L("Sending print job through cloud service")); result = m_agent->start_print(params, update_fn, cancel_fn, wait_fn); } - } + } } else { if (this->has_sdcard) { this->update_status(curr_percent, _L("Sending print job over LAN")); @@ -631,7 +630,7 @@ void PrintJob::process() if (result != QIDI_NETWORK_ERR_CANCELED) { this->show_error_info(msg_text, 0, "", ""); } - + BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result; } else { // wait for printer mqtt ready the same job id diff --git a/src/slic3r/GUI/Jobs/PrintJob.hpp b/src/slic3r/GUI/Jobs/PrintJob.hpp index 25609e3..75d8925 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.hpp +++ b/src/slic3r/GUI/Jobs/PrintJob.hpp @@ -73,7 +73,7 @@ public: bool m_is_calibration_task = false; 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; @@ -84,12 +84,13 @@ public: bool cloud_print_only { false }; bool has_sdcard { false }; bool task_use_ams { true }; + bool task_ext_change_assist { false }; int auto_bed_leveling{0}; int auto_flow_cali{0}; int auto_offset_cali{0}; - void set_print_config(std::string bed_type, bool bed_leveling, bool flow_cali, bool vabration_cali, bool record_timelapse, bool layer_inspect, + void set_print_config(std::string bed_type, bool bed_leveling, bool flow_cali, bool vabration_cali, bool record_timelapse, bool layer_inspect, bool ext_change_assist, int auto_bed_levelingt, int auto_flow_calit, int auto_offset_calit) @@ -100,10 +101,12 @@ public: task_vibration_cali = vabration_cali; task_record_timelapse = record_timelapse; task_layer_inspect = layer_inspect; + task_ext_change_assist = ext_change_assist; auto_bed_leveling = auto_bed_levelingt; auto_flow_cali = auto_flow_calit; auto_offset_cali = auto_offset_calit; + } int status_range() const override diff --git a/src/slic3r/GUI/Jobs/SendJob.cpp b/src/slic3r/GUI/Jobs/SendJob.cpp index 748400a..3215e67 100644 --- a/src/slic3r/GUI/Jobs/SendJob.cpp +++ b/src/slic3r/GUI/Jobs/SendJob.cpp @@ -40,7 +40,6 @@ void SendJob::prepare() if (&job_data) { std::string temp_file = Slic3r::resources_dir() + "/check_access_code.txt"; auto check_access_code_path = temp_file.c_str(); - BOOST_LOG_TRIVIAL(trace) << "sned_job: check_access_code_path = " << check_access_code_path; job_data._temp_path = fs::path(check_access_code_path); } } @@ -121,8 +120,8 @@ void SendJob::process() std::string http_body; - - + + // local print access params.dev_ip = m_dev_ip; params.username = "qdtp"; @@ -148,7 +147,7 @@ void SendJob::process() m_job_finished = true; return; } - + /* display info */ msg = _L("Sending gcode file over LAN"); @@ -316,7 +315,7 @@ void SendJob::process() else if (params.password.empty()) params.comments = "no_password"; - if (!params.password.empty() + if (!params.password.empty() && !params.dev_ip.empty() && this->has_sdcard) { // try to send local with record diff --git a/src/slic3r/GUI/Jobs/UpgradeNetworkJob.cpp b/src/slic3r/GUI/Jobs/UpgradeNetworkJob.cpp index 91330e3..5f7de83 100644 --- a/src/slic3r/GUI/Jobs/UpgradeNetworkJob.cpp +++ b/src/slic3r/GUI/Jobs/UpgradeNetworkJob.cpp @@ -62,7 +62,9 @@ void UpgradeNetworkJob::process() auto path_str = tmp_path.string() + wxString::Format(".%d%s", get_current_pid(), ".tmp").ToStdString(); tmp_path = fs::path(path_str); - BOOST_LOG_TRIVIAL(info) << "UpgradeNetworkJob: save netowrk_plugin to " << tmp_path.string(); +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << "UpgradeNetworkJob: save network_plugin to " << PathSanitizer::sanitize(tmp_path); +#endif auto cancel_fn = [this]() { return was_canceled(); diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index b73490b..e031442 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -254,6 +254,7 @@ void KBShortcutsDialog::fill_shortcuts() {ctrl + "A", L("Select all objects")}, {ctrl + L("Shift+D"), L("Delete all")}, {ctrl + "Z", L("Undo")}, + {ctrl + "Shift+Z", L("Redo")}, {ctrl + "Y", L("Redo")}, { "M", L("Gizmo move") }, { "S", L("Gizmo scale") }, @@ -287,6 +288,7 @@ void KBShortcutsDialog::fill_shortcuts() {ctrl + "A", L("Select all objects")}, {ctrl + "K", L("Clone selected")}, {ctrl + "Z", L("Undo")}, + {ctrl + "Shift+Z", L("Redo")}, {ctrl + "Y", L("Redo")}, {L("Space"), L("Select the object/part and press space to change the name")}, {L("Mouse click"), L("Select the object/part and mouse click to change the name")}, diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index f123dfa..56fbc1f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1,5 +1,5 @@ #include "MainFrame.hpp" - +#include "GLToolbar.hpp" #include #include #include @@ -26,6 +26,7 @@ #include "ProgressStatusBar.hpp" #include "3DScene.hpp" #include "ParamsDialog.hpp" +#include "UserPresetsDialog.hpp" #include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" #include "GUI_ObjectList.hpp" @@ -508,16 +509,20 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ j["split_to_objects"] = get_value("split_to_objects"); j["split_to_part"] = get_value("split_to_part"); j["custom_height"] = get_value("custom_height"); - j["move"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Move)); - j["rotate"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Rotate)); - j["scale"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Scale)); - j["flatten"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Flatten)); - j["cut"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Cut)); - j["meshboolean"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::MeshBoolean)); - j["custom_support"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::FdmSupports)); - j["custom_seam"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Seam)); - j["text_shape"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::Text)); - j["color_painting"] = get_value(get_name_from_gizmo_etype(GLGizmosManager::EType::MmuSegmentation)); + j["move"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Move)); + j["rotate"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Rotate)); + j["scale"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Scale)); + j["flatten"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Flatten)); + j["cut"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Cut)); + j["meshboolean"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::MeshBoolean)); + j["custom_support"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::FdmSupports)); + j["custom_fuzzyskin"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::FuzzySkin)); + j["custom_seam"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Seam)); + j["text_shape"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Text)); + j["measure"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Measure)); + j["assembly"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::Assembly)); + j["color_painting"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::MmuSegmentation)); + j["brimears"] = get_value(GLGizmosManager::convert_gizmo_type_to_string(GLGizmosManager::EType::BrimEars)); j["assembly_view"] = get_value("assembly_view"); agent->track_event("key_func", j.dump()); @@ -530,11 +535,15 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ j["scale_duration"] = get_value("Scale_duration"); j["flatten_duration"] = get_value("Lay on face_duration"); j["cut_duration"] = get_value("Cut_duration"); + j["brimears_duration"] = get_value("Brimears_duration"); j["meshboolean_duration"] = get_value("Mesh Boolean_duration"); j["custom_support_duration"] = get_value("Supports Painting_duration"); j["custom_seam_duration"] = get_value("Seam painting_duration"); j["text_shape_duration"] = get_value("Text shape_duration"); j["color_painting_duration"] = get_value("Color Painting_duration"); + j["fuzzyskin_painting_duration"] = get_value("FuzzySkin Painting_duration"); + j["assembly_duration"] = get_value("Assemble_duration"); + j["measure_duration"] = get_value("Measure_duration"); j["assembly_view_duration"] = get_value("assembly_view_duration"); agent->track_event("key_func_duration", j.dump()); @@ -2105,7 +2114,7 @@ wxBoxSizer* MainFrame::create_side_tools() /* Button * aux_btn = new Button(this, _L("Auxiliary")); - aux_btn->SetBackgroundColour(0x3B4446); + aux_btn->SetBackgroundColour("#3B4446"); aux_btn->Bind(wxEVT_BUTTON, [](auto e) { wxGetApp().sidebar().show_auxiliary_dialog(); }); @@ -2277,7 +2286,7 @@ void MainFrame::update_side_button_style() m_slice_btn->SetMinSize(wxSize(-1, FromDIP(24))); m_slice_btn->SetCornerRadius(FromDIP(12)); m_slice_btn->SetExtraSize(wxSize(FromDIP(38), FromDIP(10))); - m_slice_btn->SetBottomColour(wxColour(0x3B4446));*/ + m_slice_btn->SetBottomColour(wxColour("#3B4446"));*/ StateColor m_btn_bg_enable = StateColor( std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), @@ -2734,20 +2743,11 @@ void MainFrame::init_menubar_as_editor() // QDS wxMenu *import_menu = new wxMenu(); -#ifndef __APPLE__ append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\t" + ctrl + "I", _L("Load a model"), [this](wxCommandEvent&) { if (m_plater) { m_plater->add_file(); } }, "menu_import", nullptr, [this](){return can_add_models(); }, this); -#else - append_menu_item(import_menu, wxID_ANY, _L("Import 3MF/STL/STEP/SVG/OBJ/AMF") + dots + "\t" + ctrl + "I", _L("Load a model"), - [this](wxCommandEvent &) { - if (m_plater) { m_plater->add_file(); } - }, - "", nullptr, - [this](){return can_add_models(); }, this); -#endif append_menu_item(import_menu, wxID_ANY, _L("Import Configs") + dots /*+ "\tCtrl+I"*/, _L("Load configs"), [this](wxCommandEvent&) { load_config_file(); }, "menu_import", nullptr, [this](){return true; }, this); @@ -2780,7 +2780,7 @@ void MainFrame::init_menubar_as_editor() [this]() {return can_export_gcode(); }, this); append_menu_item(export_menu, wxID_ANY, _L("Export toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), - [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "", nullptr, + [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "menu_export_toolpaths", nullptr, [this]() {return can_export_toolpaths(); }, this); append_menu_item( @@ -2815,6 +2815,14 @@ void MainFrame::init_menubar_as_editor() // fileMenu->AppendSeparator(); + append_menu_item( + fileMenu, wxID_ANY, _L("Batch Preset Management"), wxString::Format(_L("Batch Preset Management")), + [this](wxCommandEvent &) { + UserPresetsDialog dlg(this); + dlg.ShowModal(); + }, + "", nullptr); + #ifndef __APPLE__ append_menu_item(fileMenu, wxID_EXIT, _L("Quit"), wxString::Format(_L("Quit")), [this](wxCommandEvent&) { Close(false); }, "menu_exit", nullptr); @@ -3063,6 +3071,11 @@ void MainFrame::init_menubar_as_editor() }, this, [this]() { return m_tabpanel->GetSelection() == TabPosition::tp3DEditor || m_tabpanel->GetSelection() == TabPosition::tpPreview; }, [this]() { return wxGetApp().show_3d_navigator(); }, this); + append_menu_item( + viewMenu, wxID_ANY, _L("Reset Window Layout") + "\t" + ctrl + "W", _L("Reset to default window layout"), + [this](wxCommandEvent &) { m_plater->reset_window_layout(); }, "", this, + [this]() { return (m_tabpanel->GetSelection() == TabPosition::tp3DEditor || m_tabpanel->GetSelection() == TabPosition::tpPreview) && m_plater->is_sidebar_enabled(); }, + this); viewMenu->AppendSeparator(); append_menu_check_item(viewMenu, wxID_ANY, _L("Show Labels") + "\t" + ctrl + "E", _L("Show object labels in 3D scene"), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); m_plater->get_current_canvas3D()->post_event(SimpleEvent(wxEVT_PAINT)); }, this, @@ -3630,6 +3643,16 @@ void MainFrame::update_menubar() const bool is_fff = plater()->printer_technology() == ptFFF; } +void MainFrame::update_calibration_button_status() +{ + Preset &printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); + bool isQDT = printer_preset.is_qdt_vendor_preset(wxGetApp().preset_bundle); + bool is_multi_extruder = wxGetApp().preset_bundle->get_printer_extruder_count() > 1; + // Show calibration Menu for QDT printers if Develop Mode is on. + bool show_calibration = (!isQDT || wxGetApp().app_config->get("developer_mode") == "true") && !is_multi_extruder; + wxGetApp().mainframe->show_calibration_button(show_calibration); +} + void MainFrame::reslice_now() { if (m_plater) @@ -3717,7 +3740,9 @@ void MainFrame::load_config_file() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " presets has been import,and size is" << cfiles.size(); NetworkAgent* agent = wxGetApp().getAgent(); if (agent) { +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " user is: " << agent->get_user_id(); +#endif } } wxGetApp().preset_bundle->update_compatible(PresetSelectCompatibleType::Always); @@ -4156,7 +4181,7 @@ void MainFrame::remove_recent_project(size_t file_id, wxString const &filename) void MainFrame::load_url(wxString url) { - BOOST_LOG_TRIVIAL(trace) << "load_url:" << url; + BOOST_LOG_TRIVIAL(trace) << "load_url"; auto evt = new wxCommandEvent(EVT_LOAD_URL, this->GetId()); evt->SetString(url); wxQueueEvent(this, evt); @@ -4164,7 +4189,7 @@ void MainFrame::load_url(wxString url) void MainFrame::load_printer_url(wxString url) { - BOOST_LOG_TRIVIAL(trace) << "load_printer_url:" << url; + BOOST_LOG_TRIVIAL(trace) << "load_printer_url"; auto evt = new wxCommandEvent(EVT_LOAD_PRINTER_URL, this->GetId()); evt->SetString(url); wxQueueEvent(this, evt); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 1883734..c7a4683 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -297,6 +297,7 @@ public: bool check_qdt_farm_client_installed(); void init_menubar_as_gcodeviewer(); void update_menubar(); + void update_calibration_button_status(); // Open item in menu by menu and item name (in actual language) void open_menubar_item(const wxString& menu_name,const wxString& item_name); #ifdef _WIN32 diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index ae99bdf..e28206c 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -326,7 +326,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj) json j; j["code"] = err; j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; + j["dev_ip"] = ""; NetworkAgent* agent = wxGetApp().getAgent(); if (status == PrinterFileSystem::Failed && err != 0) { j["result"] = "failed"; @@ -357,7 +357,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj) json j; j["code"] = result; j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; + j["dev_ip"] = ""; if (result > 1) { // download failed j["result"] = "failed"; @@ -521,7 +521,9 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr wfs) url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); url += "&cli_ver=" + std::string(SLIC3R_VERSION); } +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="}); +#endif CallAfter([=] { boost::shared_ptr fs(wfs.lock()); if (!fs || fs != m_image_grid->GetFileSystem()) return; diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index 61baf03..b239b3d 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -8,7 +8,8 @@ #include "MsgDialog.hpp" #include "DownloadProgressDialog.hpp" -#include +#include "slic3r/Utils/QDTUtil.hpp" + #include #include #include @@ -203,7 +204,7 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj) return; } m_machine = machine; - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine; + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << QDTCrossTalk::Crosstalk_DevId(m_machine); m_disable_lan = false; m_failed_retry = 0; m_last_failed_codes.clear(); @@ -315,7 +316,11 @@ void MediaPlayCtrl::Play() url += "&dev_ver=" + m_dev_ver; url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); url += "&cli_ver=" + std::string(SLIC3R_VERSION); + +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd}); +#endif + m_url = url; load(); m_button_play->SetIcon("media_stop"); @@ -365,11 +370,14 @@ void MediaPlayCtrl::Play() url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); url += "&cli_ver=" + std::string(SLIC3R_VERSION); } - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url, - {"?uid=", "authkey=", "passwd=", "license=", "token="}); + +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url, {"?uid=", "channel=", "authkey=", "passwd=", "license=", "token="}); +#endif + CallAfter([this, m, url] { if (m != m_machine) { - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m; + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << QDTCrossTalk::Crosstalk_DevId(m); return; } if (m_last_state == MEDIASTATE_IDLE) { @@ -446,7 +454,7 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2) json j; j["stage"] = last_state; j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; + j["dev_ip"] = ""; j["result"] = "failed"; j["user_triggered"] = m_user_triggered; j["failed_retry"] = m_failed_retry; @@ -469,7 +477,7 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2) if (last_state == wxMEDIASTATE_PLAYING && m_stat.size() == 4) { json j; j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; + j["dev_ip"] = ""; j["result"] = m_failed_code ? "failed" : "success"; j["tunnel"] = tunnel; j["code"] = m_failed_code; @@ -588,7 +596,11 @@ void MediaPlayCtrl::ToggleStream() url = "qidi:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp"; url += "&device=" + into_u8(m_machine); url += "&dev_ver=" + m_dev_ver; + +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd}); +#endif + std::string file_url = data_dir() + "/cameratools/url.txt"; boost::nowide::ofstream file(file_url); auto url2 = encode_path(url.c_str()); @@ -610,8 +622,11 @@ void MediaPlayCtrl::ToggleStream() url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); url += "&cli_ver=" + std::string(SLIC3R_VERSION); } - BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url, - {"?uid=", "authkey=", "passwd=", "license=", "token="}); + +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url,{"?uid=", "authkey=", "passwd=", "license=", "token="}); +#endif + CallAfter([this, m, url] { if (m != m_machine) return; if (url.empty() || !boost::algorithm::starts_with(url, "qidi:///")) { @@ -678,7 +693,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) json j; j["stage"] = std::to_string(m_last_state); j["dev_id"] = m_machine; - j["dev_ip"] = m_lan_ip; + j["dev_ip"] = ""; j["result"] = "success"; j["code"] = 0; auto tunnel = into_u8(wxURI(m_url).GetPath()).substr(1); @@ -775,7 +790,10 @@ void MediaPlayCtrl::media_proc() } wxString url = m_tasks.front(); if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "") { + +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << url; +#endif m_tasks.pop_front(); m_tasks.pop_front(); continue; @@ -834,7 +852,7 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install) file_url2 = wxURI(file_url2).BuildURI(); try { std::string configs; - boost::filesystem::load_string_file(file_ff_cfg, configs); + load_string_file(file_ff_cfg, configs); std::vector configss; boost::algorithm::split(configss, configs, boost::algorithm::is_any_of("\r\n")); configss.erase(std::remove(configss.begin(), configss.end(), std::string()), configss.end()); diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index baaaac3..d2e5496 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -46,23 +46,37 @@ void MeshClipper::set_limiting_plane(const ClippingPlane& plane) } } -void MeshClipper::set_mesh(const TriangleMesh& mesh) +void MeshClipper::set_mesh(const indexed_triangle_set &mesh) { - if (m_mesh != &mesh) { + if (m_mesh.get() != &mesh) { m_mesh = &mesh; - reset(); + m_result.reset(); } } -void MeshClipper::set_negative_mesh(const TriangleMesh& mesh) +void MeshClipper::set_mesh(AnyPtr &&ptr) { - if (m_negative_mesh != &mesh) { - m_negative_mesh = &mesh; - reset(); + if (m_mesh.get() != ptr.get()) { + m_mesh = std::move(ptr); + m_result.reset(); } } +void MeshClipper::set_negative_mesh(const indexed_triangle_set &mesh) +{ + if (m_negative_mesh.get() != &mesh) { + m_negative_mesh = &mesh; + m_result.reset(); + } +} +void MeshClipper::set_negative_mesh(AnyPtr &&ptr) +{ + if (m_negative_mesh.get() != ptr.get()) { + m_negative_mesh = std::move(ptr); + m_result.reset(); + } +} void MeshClipper::set_transformation(const Geometry::Transformation& trafo) { @@ -208,10 +222,10 @@ void MeshClipper::recalculate_triangles() // if (m_csgmesh.empty()) { if (m_mesh) { - expolys = union_ex(slice_mesh(m_mesh->its, height_mesh, slicing_params)); + expolys = union_ex(slice_mesh(*m_mesh, height_mesh, slicing_params)); } if (m_negative_mesh && !m_negative_mesh->empty()) { - const ExPolygons neg_expolys = union_ex(slice_mesh(m_negative_mesh->its, height_mesh, slicing_params)); + const ExPolygons neg_expolys = union_ex(slice_mesh(*m_negative_mesh, height_mesh, slicing_params)); expolys = diff_ex(expolys, neg_expolys); } diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index 916380c..842bc3b 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -6,7 +6,7 @@ #include "libslic3r/Geometry.hpp" #include "libslic3r/SLA/IndexedMesh.hpp" #include "admesh/stl.h" - +#include "libslic3r/AnyPtr.hpp" #include "slic3r/GUI/GLModel.hpp" #include @@ -93,9 +93,11 @@ public: // Which mesh to cut. MeshClipper remembers const * to it, caller // must make sure that it stays valid. - void set_mesh(const TriangleMesh& mesh); + void set_mesh(const indexed_triangle_set &mesh); + void set_mesh(AnyPtr &&ptr); - void set_negative_mesh(const TriangleMesh &mesh); + void set_negative_mesh(const indexed_triangle_set &mesh); + void set_negative_mesh(AnyPtr &&ptr); // Inform the MeshClipper about the transformation that transforms the mesh // into world coordinates. @@ -115,8 +117,8 @@ private: void recalculate_triangles(); void reset(); Geometry::Transformation m_trafo; - const TriangleMesh * m_mesh = nullptr; - const TriangleMesh * m_negative_mesh = nullptr; + AnyPtr m_mesh; + AnyPtr m_negative_mesh; ClippingPlane m_plane; ClippingPlane m_limiting_plane = ClippingPlane::ClipsNothing(); diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index 9e956ce..69ab573 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -459,23 +459,6 @@ bool MonitorPanel::Show(bool show) return wxPanel::Show(show); } -void MonitorPanel::update_side_panel() -{ - Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (!dev) return; - - auto is_next_machine = false; - if (!dev->get_first_online_user_machine().empty()) { - wxCommandEvent* event = new wxCommandEvent(wxEVT_COMMAND_CHOICE_SELECTED); - event->SetString(dev->get_first_online_user_machine()); - wxQueueEvent(this, event); - is_next_machine = true; - return; - } - - if (!is_next_machine) { m_side_tools->set_none_printer_mode(); } -} - void MonitorPanel::show_status(int status) { if (!m_initialized) return; diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index 9b3b391..7d2846f 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -144,7 +144,6 @@ public: void update_hms_tag(); bool Show(bool show); - void update_side_panel(); void show_status(int status); std::string get_string_from_tab(PrinterTab tab); diff --git a/src/slic3r/GUI/MultiTaskManagerPage.cpp b/src/slic3r/GUI/MultiTaskManagerPage.cpp index a5b40e2..bb806ca 100644 --- a/src/slic3r/GUI/MultiTaskManagerPage.cpp +++ b/src/slic3r/GUI/MultiTaskManagerPage.cpp @@ -6,6 +6,7 @@ #include "Widgets/RadioBox.hpp" #include #include +#include "QDTUtil.hpp" namespace Slic3r { namespace GUI { @@ -176,7 +177,7 @@ void MultiTaskItem::update_info() void MultiTaskItem::onPause() { if (get_obj() && !get_obj()->can_resume()) { - BOOST_LOG_TRIVIAL(info) << "MultiTask: pause current print task dev_id =" << get_obj()->dev_id; + BOOST_LOG_TRIVIAL(info) << "MultiTask: pause current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); get_obj()->command_task_pause(); m_button_pause->Hide(); m_button_resume->Show(); @@ -187,7 +188,7 @@ void MultiTaskItem::onPause() void MultiTaskItem::onResume() { if (get_obj() && get_obj()->can_resume()) { - BOOST_LOG_TRIVIAL(info) << "MultiTask: resume current print task dev_id =" << get_obj()->dev_id; + BOOST_LOG_TRIVIAL(info) << "MultiTask: resume current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); get_obj()->command_task_resume(); m_button_pause->Show(); m_button_resume->Hide(); @@ -198,7 +199,7 @@ void MultiTaskItem::onResume() void MultiTaskItem::onStop() { if (get_obj()) { - BOOST_LOG_TRIVIAL(info) << "MultiTask: abort current print task dev_id =" << get_obj()->dev_id; + BOOST_LOG_TRIVIAL(info) << "MultiTask: abort current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); get_obj()->command_task_abort(); m_button_pause->Hide(); m_button_resume->Hide(); @@ -536,7 +537,7 @@ LocalTaskManagerPage::LocalTaskManagerPage(wxWindow* parent) #ifdef __WINDOWS__ SetDoubleBuffered(true); #endif //__WINDOWS__ - SetBackgroundColour(wxColour(0xEEEEEE)); + SetBackgroundColour(wxColour("#EEEEEE")); m_main_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); m_main_panel->SetBackgroundColour(*wxWHITE); m_main_sizer = new wxBoxSizer(wxVERTICAL); @@ -898,10 +899,10 @@ CloudTaskManagerPage::CloudTaskManagerPage(wxWindow* parent) #ifdef __WINDOWS__ SetDoubleBuffered(true); #endif //__WINDOWS__ - SetBackgroundColour(wxColour(0xEEEEEE)); + SetBackgroundColour(wxColour("#EEEEEE")); m_sort.set_role(SortItem::SR_SEND_TIME, true); - SetBackgroundColour(wxColour(0xEEEEEE)); + SetBackgroundColour(wxColour("#EEEEEE")); m_main_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); m_main_panel->SetBackgroundColour(*wxWHITE); m_main_sizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/NetworkTestDialog.cpp b/src/slic3r/GUI/NetworkTestDialog.cpp index c7c9829..c6dbaa6 100644 --- a/src/slic3r/GUI/NetworkTestDialog.cpp +++ b/src/slic3r/GUI/NetworkTestDialog.cpp @@ -269,7 +269,7 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent) }); btn_network_plugin->Bind(wxEVT_BUTTON, [this](wxCommandEvent &evt) { - start_test_plugin_download_thread(); + start_test_plugin_download_thread(); }); return sizer; @@ -687,7 +687,7 @@ void NetworkTestDialog::start_test_oss_download() } bool cancel = false; - BOOST_LOG_TRIVIAL(info) << "[test_storage_download] get_url = " << download_url; + //BOOST_LOG_TRIVIAL(info) << "[test_storage_download] get_url = " << download_url; // download Slic3r::Http http = Slic3r::Http::get(download_url); @@ -831,7 +831,7 @@ void NetworkTestDialog:: start_test_plugin_download(){ } bool cancel = false; - BOOST_LOG_TRIVIAL(info) << "[test_plugin_download] get_url = " << download_url; + //BOOST_LOG_TRIVIAL(info) << "[test_plugin_download] get_url = " << download_url; // download Slic3r::Http http = Slic3r::Http::get(download_url); @@ -937,8 +937,8 @@ void NetworkTestDialog::start_test_oss_upload_thread() void NetworkTestDialog:: start_test_plugin_download_thread(){ - test_job[TEST_PLUGIN_JOB] = new boost::thread([this] { - start_test_plugin_download(); + test_job[TEST_PLUGIN_JOB] = new boost::thread([this] { + start_test_plugin_download(); }); } diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index a0db00a..c41d250 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1301,6 +1301,7 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty // QDS //case InfoItemType::CustomSeam: text += format(("%1$d Object has custom seam.", "%1$d Objects have custom seam.", (*it).second), (*it).second) + "\n"; break; case InfoItemType::MmuSegmentation: text += format(_L_PLURAL("%1$d Object has color painting.", "%1$d Objects have color painting.",(*it).second), (*it).second) + "\n"; break; + case InfoItemType::FuzzySkin: text += format(_L_PLURAL("%1$d Object has fuzzy skin.", "%1$d Objects have fuzzy skin.", (*it).second), (*it).second) + "\n"; break; // QDS //case InfoItemType::Sinking: text += format(("%1$d Object has partial sinking.", "%1$d Objects have partial sinking.", (*it).second), (*it).second) + "\n"; break; case InfoItemType::CutConnectors: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object", (*it).second), (*it).second) + "\n"; break; diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 04ede51..c89277d 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -154,6 +154,7 @@ enum class NotificationType QDTSliceMultiExtruderHeightOutside, QDTBedFilamentIncompatible, QDTMixUsePLAAndPETG, + QDTNozzleFilamentIncompatible, AssemblyWarning, AssemblyInfo, NotificationTypeCount diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index 2990dee..a0fc7b5 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -783,7 +783,9 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos) } is_url_string = !suppress_hyperlinks && !og_line.label_path.empty(); // QDS - h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label /* + ":" */, text_clr, icon_pos + ctrl->opt_group->label_width * ctrl->m_em_unit - h_pos, is_url_string, true); + wxCoord indent = og_line.subline ? lround(1.5 * ctrl->m_em_unit) : 0; + h_pos = draw_text(dc, wxPoint(h_pos + indent, v_pos), label /* + ":" */, text_clr, icon_pos + ctrl->opt_group->label_width * ctrl->m_em_unit - h_pos, is_url_string, true); + h_pos -= indent; } // If there's a widget, build it and set result to the correct position. diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 64a7596..e1b8ed3 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -63,6 +63,7 @@ struct InfoItemAtributes { const std::map INFO_ITEMS{ // info_item Type info_item Name info_item BitmapName { InfoItemType::CustomSupports, {L("Support painting"), "toolbar_support" }, }, + {InfoItemType::FuzzySkin,{L("Fuzzy skin"), "toolbar_fuzzyskin"},}, //{ InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, }, { InfoItemType::MmuSegmentation, {L("Color painting"), "mmu_segmentation"}, }, //{ InfoItemType::Sinking, {L("Sinking"), "objlist_sinking"}, }, @@ -247,6 +248,16 @@ void ObjectDataViewModelNode::set_support_icon(bool enable, bool force) m_support_icon = create_scaled_bitmap("dot"); } +void ObjectDataViewModelNode::set_fuzzyskin_icon(bool enable, bool force) +{ + if (!force && m_fuzzyskin_enable == enable) return; + m_fuzzyskin_enable = enable; + if ((m_type & itObject) && enable) + m_fuzzyskin_icon = create_scaled_bitmap("toolbar_fuzzyskin"); + else + m_fuzzyskin_icon = create_scaled_bitmap("dot"); +} + void ObjectDataViewModelNode::set_sinking_icon(bool enable, bool force) { if (!force && m_sink_enable == enable) @@ -343,6 +354,9 @@ bool ObjectDataViewModelNode::SetValue(const wxVariant& variant, unsigned col) case colSupportPaint: m_support_icon << variant; break; + case colFuzzySkin: + m_fuzzyskin_icon << variant; + break; case colSinking: m_sinking_icon << variant; break; @@ -1778,6 +1792,9 @@ void ObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem &ite case colSupportPaint: variant << node->m_support_icon; break; + case colFuzzySkin: + variant << node->m_fuzzyskin_icon; + break; case colSinking: variant << node->m_sinking_icon; break; @@ -2326,6 +2343,15 @@ bool ObjectDataViewModel::IsSupportPainted(wxDataViewItem& item) const return node->m_support_enable; } +bool ObjectDataViewModel::IsFuzzySkinPainted(wxDataViewItem &item) const +{ + ObjectDataViewModelNode *node = static_cast(item.GetID()); + if (!node) + return false; + + return node->m_fuzzyskin_enable; +} + bool ObjectDataViewModel::IsSinked(wxDataViewItem &item) const { ObjectDataViewModelNode *node = static_cast(item.GetID()); @@ -2354,6 +2380,15 @@ void ObjectDataViewModel::SetSupportPaintState(const bool painted, wxDataViewIte ItemChanged(obj_item); } +void ObjectDataViewModel::SetFuzzySkinPaintState(const bool painted, wxDataViewItem obj_item, bool force) +{ + ObjectDataViewModelNode *node = static_cast(obj_item.GetID()); + if (!node) return; + + node->set_fuzzyskin_icon(painted, force); + ItemChanged(obj_item); +} + void ObjectDataViewModel::SetSinkState(const bool painted, wxDataViewItem obj_item, bool force) { ObjectDataViewModelNode *node = static_cast(obj_item.GetID()); diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index 2136abf..9115f40 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -44,6 +44,7 @@ enum ColumnNumber colFilament , // extruder selection // QDS colSupportPaint , + colFuzzySkin , colColorPaint , colSinking , colEditing , // item editing @@ -68,6 +69,7 @@ enum class InfoItemType Undef, CustomSupports, //CustomSeam, + FuzzySkin, MmuSegmentation, //Sinking CutConnectors, @@ -97,6 +99,7 @@ class ObjectDataViewModelNode wxBitmap m_action_icon; // QDS wxBitmap m_support_icon; + wxBitmap m_fuzzyskin_icon; wxBitmap m_color_icon; wxBitmap m_sinking_icon; PrintIndicator m_printable {piUndef}; @@ -115,6 +118,7 @@ class ObjectDataViewModelNode bool m_action_enable = false; // can undo all settings // QDS bool m_support_enable = false; + bool m_fuzzyskin_enable = false; bool m_color_enable = false; bool m_sink_enable = false; @@ -260,6 +264,7 @@ public: // QDS bool HasColorPainting() const { return m_color_enable; } bool HasSupportPainting() const { return m_support_enable; } + bool HasFuzzySkinPainting() const { return m_fuzzyskin_enable; } bool HasSinking() const { return m_sink_enable; } bool IsActionEnabled() const { return m_action_enable; } void UpdateExtruderAndColorIcon(wxString extruder = ""); @@ -303,6 +308,7 @@ public: // QDS void set_color_icon(bool enable, bool force = false); void set_support_icon(bool enable,bool force = false); + void set_fuzzyskin_icon(bool enable, bool force = false); void set_sinking_icon(bool enable, bool force = false); // Set warning icon for node @@ -508,9 +514,11 @@ public: // QDS bool IsColorPainted(wxDataViewItem& item) const; bool IsSupportPainted(wxDataViewItem &item) const; + bool IsFuzzySkinPainted(wxDataViewItem &item) const; bool IsSinked(wxDataViewItem &item) const; void SetColorPaintState(const bool painted, wxDataViewItem obj_item,bool force = false); void SetSupportPaintState(const bool painted, wxDataViewItem obj_item,bool force = false); + void SetFuzzySkinPaintState(const bool painted, wxDataViewItem obj_item, bool force = false); void SetSinkState(const bool painted, wxDataViewItem obj_item,bool force = false); void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; } diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index bcca692..5f4f0c5 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -793,6 +793,16 @@ bool OpenGLManager::is_gizmo_keep_screen_size_enabled() const return m_b_gizmo_keep_screen_size_enabled; } +void OpenGLManager::set_toolbar_rendering_style(uint8_t style) +{ + m_toolbar_rendering_style = style; +} + +uint8_t OpenGLManager::get_toolbar_rendering_style() const +{ + return m_toolbar_rendering_style; +} + std::string OpenGLManager::framebuffer_type_to_string(EFramebufferType type) { switch (type) diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index dc941ac..954081d 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -231,6 +231,7 @@ private: uint32_t m_vao{ 0 }; bool m_b_legacy_framebuffer_enabled{ true }; bool m_b_gizmo_keep_screen_size_enabled{ true }; + uint8_t m_toolbar_rendering_style{ 0 }; static GLInfo s_gl_info; #ifdef __APPLE__ // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets @@ -280,6 +281,9 @@ public: bool is_fxaa_enabled() const; void blit_framebuffer(const std::string& source, const std::string& target); + void set_toolbar_rendering_style(uint8_t style); + uint8_t get_toolbar_rendering_style() const; + static bool init(); static bool are_compressed_textures_supported() { return s_compressed_textures_supported; } static bool can_multisample() { return s_multisample == EMultisampleState::Enabled; } diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index be13c20..ea00fe8 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -580,12 +580,13 @@ void OptionsGroup::clear(bool destroy_custom_ctrl) m_fields.clear(); } -Line OptionsGroup::create_single_option_line(const Option& option, const std::string& path/* = std::string()*/) const +Line OptionsGroup::create_single_option_line(const Option& option, const std::string& path/* = std::string()*/, bool subline) const { wxString tooltip = _(option.opt.tooltip); edit_tooltip(tooltip); Line retval{ _(option.opt.label), tooltip }; retval.label_path = path; + retval.subline = subline; retval.append_option(option); return retval; } diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 6c4bc35..faab470 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -60,6 +60,7 @@ public: size_t full_width {0}; wxColour* full_Label_color {nullptr}; bool blink {false}; + bool subline {false}; widget_t widget {nullptr}; std::function near_label_widget{ nullptr }; wxWindow* near_label_widget_win {nullptr}; @@ -147,8 +148,8 @@ public: // delete all controls from the option group void clear(bool destroy_custom_ctrl = false); - Line create_single_option_line(const Option& option, const std::string& path = std::string()) const; - void append_single_option_line(const Option& option, const std::string& path = std::string()) { append_line(create_single_option_line(option, path)); } + Line create_single_option_line(const Option& option, const std::string& path = std::string(), bool subline = false) const; + void append_single_option_line(const Option& option, const std::string& path = std::string(), bool subline = false) { append_line(create_single_option_line(option, path, subline)); } void append_separator(); // return a non-owning pointer reference @@ -272,13 +273,13 @@ public: Line create_single_option_line(const Option& option, const std::string& path = std::string()) const { return OptionsGroup::create_single_option_line(option, path); } - void append_single_option_line(const Option& option, const std::string& path = std::string()) { - OptionsGroup::append_single_option_line(option, path); + void append_single_option_line(const Option& option, const std::string& path = std::string(), bool subline = false) { + OptionsGroup::append_single_option_line(option, path, subline); } - void append_single_option_line(const std::string title, const std::string& path = std::string(), int idx = -1) + void append_single_option_line(const std::string title, const std::string& path = std::string(), int idx = -1, bool subline = false) { Option option = get_option(title, idx); - append_single_option_line(option, path); + append_single_option_line(option, path, subline); } void on_change_OG(const t_config_option_key& opt_id, const boost::any& value) override; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index a9fee2e..545c2b3 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -53,6 +53,7 @@ static const int PARTPLATE_ICON_SIZE = 16; static const int PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE = 12; static const int PARTPLATE_PLATE_NAME_FIX_HEIGHT_SIZE = 20; static const int PARTPLATE_ICON_GAP_TOP = 3; +static const int PARTPLATE_NAME_EDIT_ICON_GAP_LEFT = 3; //B static const int PARTPLATE_ICON_GAP_LEFT = 10; static const int PARTPLATE_ICON_GAP_Y = 5; @@ -417,6 +418,15 @@ void PartPlate::calc_height_limit() { BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create height limit top lines\n"; } +int PartPlate::get_right_icon_offset_bed() { + if (&wxGetApp() && wxGetApp().plater()) { + auto offset = wxGetApp().plater()->get_right_icon_offset_bed(); + return offset == 0 ? PARTPLATE_ICON_GAP_LEFT : offset; + } else { + return PARTPLATE_ICON_GAP_LEFT; + } +} + void PartPlate::calc_vertex_for_plate_name(GLTexture &texture, GLModel &gl_model) { if (texture.get_width() > 0 && texture.get_height()) { @@ -428,10 +438,10 @@ void PartPlate::calc_vertex_for_plate_name(GLTexture &texture, GLModel &gl_model w = int(factor * (texture.get_width() * 16) / texture.get_height()); h = PARTPLATE_PLATE_NAME_FIX_HEIGHT_SIZE; Vec2d p = bed_ext[3] + Vec2d(0, PARTPLATE_PLATENAME_OFFSET_Y + h * texture.m_original_height / texture.get_height()); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) - h )}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - h )}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w - offset_x), scale_(p(1) )}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) )}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w - offset_x), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w - offset_x), scale_(p(1))}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x), scale_(p(1))}); auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); gl_model.reset(); @@ -455,18 +465,18 @@ void PartPlate::calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int ind if (texture && texture->get_width() > 0 && texture->get_height()) { w = int(factor * (texture->get_original_width() * 16) / texture->get_height()) + 1; - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w), scale_(p(1) - h )}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + w), scale_(p(1) )}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + w), scale_(p(1))}); triangles = triangulate_expolygon_2f(poly, NORMALS_UP); } else { - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x ), scale_(p(1) - h )}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) )}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1) - h)}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x + PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE), scale_(p(1))}); + poly.contour.append({scale_(p(0) + PARTPLATE_NAME_EDIT_ICON_GAP_LEFT + offset_x), scale_(p(1))}); triangles = triangulate_expolygon_2f(poly, NORMALS_UP); } @@ -475,21 +485,6 @@ void PartPlate::calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int ind BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; } -void PartPlate::calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer) -{ - ExPolygon poly; - Vec2d & p = m_partplate_list->m_shape[2]; - - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - icon_count * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y)- PARTPLATE_ICON_GAP_TOP) }); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - PARTPLATE_ICON_GAP_TOP)}); - poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - PARTPLATE_ICON_GAP_TOP) }); - - auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); - if (!buffer.set_from_triangles(triangles, GROUND_Z)) - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n"; -} - bool PartPlate::calc_bed_3d_boundingbox(BoundingBoxf3 &box_in_plate_origin) { if (m_partplate_list && m_partplate_list->m_bed3d && !m_partplate_list->m_bed3d->get_model_filename().empty()) { auto cur_bed = m_partplate_list->m_bed3d; @@ -1394,6 +1389,85 @@ bool PartPlate::check_mixture_of_pla_and_petg(const DynamicPrintConfig &config) return true; } +bool PartPlate::check_compatible_of_nozzle_and_filament(const DynamicPrintConfig &config, const std::vector &filament_presets, std::string &error_msg) +{ + float nozzle_diameter = config.option("nozzle_diameter")->values[0]; + auto volume_type_opt = config.option("nozzle_volume_type"); + + auto get_filament_alias = [](std::string preset_name) -> std::string { + size_t at_pos = preset_name.find('@'); + std::string alias = preset_name.substr(0, at_pos); + size_t first = alias.find_first_not_of(' '); + if (first == std::string::npos) return ""; + size_t last = alias.find_last_not_of(' '); + return alias.substr(first, last - first + 1); + }; + + bool with_same_volume_type = std::all_of(volume_type_opt->values.begin(), volume_type_opt->values.end(), + [first_value = volume_type_opt->values[0]](int value) { return value == first_value; }); + + std::set selected_filament_alias; + for (auto &filament_preset : filament_presets) { selected_filament_alias.insert(get_filament_alias(filament_preset)); } + + auto get_incompatible_selected = [&](const NozzleVolumeType volume_type) -> std::set { + std::vector incompatible_filaments = Print::get_incompatible_filaments_by_nozzle(nozzle_diameter, volume_type); + std::set ret; + for (auto &filament : selected_filament_alias) { + if (std::find(incompatible_filaments.begin(), incompatible_filaments.end(), filament) != incompatible_filaments.end()) ret.insert(filament); + } + return ret; + }; + + auto get_nozzle_msg = [](const float nozzle_diameter, const NozzleVolumeType volume_type) -> std::string { + std::ostringstream oss; + oss << std::fixed << std::setprecision(1) << nozzle_diameter; + std::string nozzle_msg = oss.str(); + ((nozzle_msg += "mm ") += _u8L(get_nozzle_volume_type_string(volume_type))) += _u8L(" nozzle"); + return nozzle_msg; + }; + + auto get_incompatible_filament_msg = [](const std::set &incompatible_selected_filaments) -> std::string { + std::string filament_str; + size_t idx = 0; + for (const auto &filament : incompatible_selected_filaments) { + if (idx > 0) filament_str += ','; + filament_str += filament; + ++idx; + } + return filament_str; + }; + + error_msg.clear(); + + std::set nozzle_volumes(volume_type_opt->values.begin(), volume_type_opt->values.end()); + std::map> incompatible_selected_map; + + for (auto volume_type_value : nozzle_volumes) { + NozzleVolumeType volume_type = static_cast(volume_type_value); + auto incompatible_selected = get_incompatible_selected(volume_type); + if (!incompatible_selected.empty()) incompatible_selected_map[volume_type] = incompatible_selected; + } + + if (incompatible_selected_map.empty()) return true; + + if (incompatible_selected_map.size() == 1) { + auto elem = incompatible_selected_map.begin(); + NozzleVolumeType volume_type = elem->first; + auto incompatible_selected = elem->second; + error_msg = GUI::format(_L("It is not recommended to print the following filament(s) with %1%: %2%\n"), get_nozzle_msg(nozzle_diameter, volume_type), + get_incompatible_filament_msg(incompatible_selected)); + } else { + std::string warning_msg = _u8L("It is not recommended to use the following nozzle and filament combinations:\n"); + for (auto &elem : incompatible_selected_map) { + NozzleVolumeType volume_type = elem.first; + auto incompatible_selected = elem.second; + warning_msg += GUI::format(_L("%1% with %2%\n"),get_nozzle_msg(nozzle_diameter, volume_type), get_incompatible_filament_msg(incompatible_selected)); + } + error_msg = warning_msg; + } + return false; +} + /*Vec3d PartPlate::calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size, bool use_global_objects) const { Vec3d wipe_tower_size; @@ -2353,76 +2427,6 @@ void PartPlate::set_logo_box_by_bed(const BoundingBoxf3& box) } } -void PartPlate::generate_print_polygon(ExPolygon &print_polygon) -{ - auto compute_points = [&print_polygon](Vec2d& center, double radius, double start_angle, double stop_angle, int count) - { - double angle, angle_steps; - angle_steps = (stop_angle - start_angle) / (count - 1); - for(int j = 0; j < count; j++ ) - { - double angle = start_angle + j * angle_steps; - double x = center(0) + ::cos(angle) * radius; - double y = center(1) + ::sin(angle) * radius; - print_polygon.contour.append({ scale_(x), scale_(y) }); - } - }; - - int points_count = 8; - if (m_shape.size() == 4) - { - //rectangle case - for (int i = 0; i < 4; i++) - { - const Vec2d& p = m_shape[i]; - Vec2d center; - double start_angle, stop_angle, angle_steps, radius_x, radius_y, radius; - switch (i) { - case 0: - radius = 5.f; - center(0) = p(0) + radius; - center(1) = p(1) + radius; - start_angle = PI; - stop_angle = 1.5 * PI; - compute_points(center, radius, start_angle, stop_angle, points_count); - break; - case 1: - print_polygon.contour.append({ scale_(p(0)), scale_(p(1)) }); - break; - case 2: - radius_x = (int)(p(0)) % 10; - radius_y = (int)(p(1)) % 10; - radius = (radius_x > radius_y)?radius_y: radius_x; - if (radius < 5.0) - radius = 5.f; - center(0) = p(0) - radius; - center(1) = p(1) - radius; - start_angle = 0; - stop_angle = 0.5 * PI; - compute_points(center, radius, start_angle, stop_angle, points_count); - break; - case 3: - radius_x = (int)(p(0)) % 10; - radius_y = (int)(p(1)) % 10; - radius = (radius_x > radius_y)?radius_y: radius_x; - if (radius < 5.0) - radius = 5.f; - center(0) = p(0) + radius; - center(1) = p(1) - radius; - start_angle = 0.5 * PI; - stop_angle = PI; - compute_points(center, radius, start_angle, stop_angle, points_count); - break; - } - } - } - else { - for (const Vec2d& p : m_shape) { - print_polygon.contour.append({ scale_(p(0)), scale_(p(1)) }); - } - } -} - void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon) { auto compute_exclude_points = [&exclude_polygon](Vec2d& center, double radius, double start_angle, double stop_angle, int count) @@ -2449,7 +2453,7 @@ void PartPlate::generate_exclude_polygon(ExPolygon &exclude_polygon) double start_angle, stop_angle, angle_steps, radius_x, radius_y, radius; switch (i) { case 0: - radius = 5.f; + radius = 8.f; center(0) = p(0) + radius; center(1) = p(1) + radius; start_angle = PI; @@ -3011,7 +3015,7 @@ void PartPlate::print() const BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(": plate index %1%, pointer %2%, print_index %3% print pointer %4%") % m_plate_index % this % m_print_index % m_print; BOOST_LOG_TRIVIAL(trace) << boost::format("\t origin {%1%,%2%,%3%}, width %4%, depth %5%, height %6%") % m_origin.x() % m_origin.y() % m_origin.z() % m_width % m_depth % m_height; BOOST_LOG_TRIVIAL(trace) << boost::format("\t m_printable %1%, m_locked %2%, m_ready_for_slice %3%, m_slice_result_valid %4%, m_tmp_gcode_path %5%, set size %6%")\ - % m_printable % m_locked % m_ready_for_slice % m_slice_result_valid % m_tmp_gcode_path % obj_to_instance_set.size(); + % m_printable % m_locked % m_ready_for_slice % m_slice_result_valid % PathSanitizer::sanitize(m_tmp_gcode_path) % obj_to_instance_set.size(); /*for (std::set>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) { int obj_id = it->first; int instance_id = it->second; @@ -3248,9 +3252,13 @@ void PartPlateList::generate_print_polygon(ExPolygon &print_polygon) print_polygon.contour.append({scale_(x), scale_(y)}); } }; - + bool use_rect_grid = false; + if (&wxGetApp() && wxGetApp().plater()) { + auto pm = wxGetApp().plater()->get_curr_printer_model(); + use_rect_grid = (pm && pm->use_rect_grid == "true") ? true : false; + } int points_count = 8; - if (m_shape.size() == 4) { + if (m_shape.size() == 4 && !use_rect_grid) { // rectangle case for (int i = 0; i < 4; i++) { const Vec2d &p = m_shape[i]; @@ -3258,7 +3266,7 @@ void PartPlateList::generate_print_polygon(ExPolygon &print_polygon) double start_angle, stop_angle, radius_x, radius_y, radius; switch (i) { case 0: - radius = 5.f; + radius = 8.f; center(0) = p(0) + radius; center(1) = p(1) + radius; start_angle = PI; @@ -3319,7 +3327,7 @@ void PartPlateList::generate_exclude_polygon(ExPolygon &exclude_polygon) double start_angle, stop_angle, radius; switch (i) { case 0: - radius = 5.f; + radius = 8.f; center(0) = p(0) + radius; center(1) = p(1) + radius; start_angle = PI; @@ -3424,11 +3432,11 @@ void PartPlateList::calc_vertex_for_number(int index, bool one_number, GLModel & #else // in the bottom Vec2d &p = m_shape[1]; float offset_x = one_number ? PARTPLATE_TEXT_OFFSET_X1 : PARTPLATE_TEXT_OFFSET_X2; - - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); + auto right_icon_offset_bed = m_plate_list.size() > 0 ? m_plate_list[0]->get_right_icon_offset_bed() : PARTPLATE_ICON_GAP_LEFT; + poly.contour.append({scale_(p(0) + right_icon_offset_bed + offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed + offset_x), scale_(p(1) + PARTPLATE_ICON_SIZE - PARTPLATE_TEXT_OFFSET_Y)}); #endif auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); gl_model.reset(); @@ -3439,14 +3447,11 @@ void PartPlateList::calc_vertex_for_icons(int index, GLModel &gl_model) { ExPolygon poly; Vec2d & p = m_shape[2]; - - poly.contour.append( - {scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), - scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); - poly.contour.append( - {scale_(p(0) + PARTPLATE_ICON_GAP_LEFT + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); - poly.contour.append({scale_(p(0) + PARTPLATE_ICON_GAP_LEFT), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); + auto right_icon_offset_bed = m_plate_list.size() > 0 ? m_plate_list[0]->get_right_icon_offset_bed() : PARTPLATE_ICON_GAP_LEFT; + poly.contour.append({scale_(p(0) + right_icon_offset_bed), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP - PARTPLATE_ICON_SIZE)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed + PARTPLATE_ICON_SIZE), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); + poly.contour.append({scale_(p(0) + right_icon_offset_bed), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP_Y) - PARTPLATE_ICON_GAP_TOP)}); auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); gl_model.reset(); @@ -5871,8 +5876,9 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w plate_data_item->objects_and_instances.emplace_back(it->first, it->second); } - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <m_gcode_result->filename % with_slice_info %m_plate_list[i]->is_slice_result_valid()%plate_data_item->objects_and_instances.size(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <m_gcode_result->filename) % with_slice_info % m_plate_list[i]->is_slice_result_valid() % + plate_data_item->objects_and_instances.size(); if (with_slice_info) { if (m_plate_list[i]->get_slice_result() && m_plate_list[i]->is_slice_result_valid()) { @@ -5942,8 +5948,9 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list, int f { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":plate index %1% seems invalid, skip it")% plate_data_list[i]->plate_index; } - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%, is_support_used %5% is_label_object_enabled %6%") - %i %plate_data_list[i]->gcode_file %plate_data_list[i]->is_sliced_valid %plate_data_list[i]->toolpath_outside %plate_data_list[i]->is_support_used %plate_data_list[i]->is_label_object_enabled; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%, is_support_used %5% is_label_object_enabled %6%") % i % + PathSanitizer::sanitize(plate_data_list[i]->gcode_file) % plate_data_list[i]->is_sliced_valid % plate_data_list[i]->toolpath_outside % + plate_data_list[i]->is_support_used % plate_data_list[i]->is_label_object_enabled; //load object and instance from 3mf //just test for file correct or not, we will rebuild later /*for (std::vector>::iterator it = plate_data_list[i]->objects_and_instances.begin(); it != plate_data_list[i]->objects_and_instances.end(); ++it) @@ -5971,7 +5978,7 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list, int f gcode_result->warnings = plate_data_list[i]->warnings; gcode_result->filament_maps = plate_data_list[i]->filament_maps; if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load thumbnail from %2%.")%(i+1) %plate_data_list[i]->thumbnail_file; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load thumbnail from %2%.") % (i + 1) % PathSanitizer::sanitize(plate_data_list[i]->thumbnail_file); if (boost::filesystem::exists(plate_data_list[i]->thumbnail_file)) { m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file, m_plate_list[index]->thumbnail_data); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <no_light_thumbnail_file.empty()) { if (boost::filesystem::exists(plate_data_list[i]->no_light_thumbnail_file)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load no_light_thumbnail_file from %2%.")%(i+1) %plate_data_list[i]->no_light_thumbnail_file; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load no_light_thumbnail_file from %2%.") % (i + 1) % PathSanitizer::sanitize(plate_data_list[i]->no_light_thumbnail_file); m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->no_light_thumbnail_file, m_plate_list[index]->no_light_thumbnail_data); } } @@ -5994,13 +6001,13 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list, int f }*/ if (m_plater && !plate_data_list[i]->top_file.empty()) { if (boost::filesystem::exists(plate_data_list[i]->top_file)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load top_thumbnail from %2%.")%(i+1) %plate_data_list[i]->top_file; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load top_thumbnail from %2%.") % (i + 1) % PathSanitizer::sanitize(plate_data_list[i]->top_file); m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->top_file, m_plate_list[index]->top_thumbnail_data); } } if (m_plater && !plate_data_list[i]->pick_file.empty()) { if (boost::filesystem::exists(plate_data_list[i]->pick_file)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load pick_thumbnail from %2%.")%(i+1) %plate_data_list[i]->pick_file; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load pick_thumbnail from %2%.") % (i + 1) % PathSanitizer::sanitize(plate_data_list[i]->pick_file); m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->pick_file, m_plate_list[index]->pick_thumbnail_data); } } @@ -6132,15 +6139,54 @@ void PartPlateList::init_bed_type_info() BedTextureInfo::TexturePart pei_part2(74, -10, 148, 12, "qdt_bed_pei_bottom.svg"); BedTextureInfo::TexturePart pte_part1(10, 52, 8.393f, 192, "qdt_bed_pte_left.svg"); BedTextureInfo::TexturePart pte_part2(74, -10, 148, 12, "qdt_bed_pte_bottom.svg"); - + auto bed_texture_maps = wxGetApp().plater()->get_bed_texture_maps(); + std::string bottom_texture_end_name = bed_texture_maps.find("bottom_texture_end_name") != bed_texture_maps.end() ? bed_texture_maps["bottom_texture_end_name"] : ""; + std::string bottom_texture_rect_str = bed_texture_maps.find("bottom_texture_rect") != bed_texture_maps.end() ? bed_texture_maps["bottom_texture_rect"] : ""; + std::string middle_texture_rect_str = bed_texture_maps.find("middle_texture_rect") != bed_texture_maps.end() ? bed_texture_maps["middle_texture_rect"] : ""; + std::array bottom_texture_rect = {0, 0, 0, 0}, middle_texture_rect = {0, 0, 0, 0}; + if (bottom_texture_rect_str.size() > 0) { + std::vector items; + boost::algorithm::erase_all(bottom_texture_rect_str, " "); + boost::split(items, bottom_texture_rect_str, boost::is_any_of(",")); + if (items.size() == 4) { + for (int i = 0; i < items.size(); i++) { + bottom_texture_rect[i] = std::atof(items[i].c_str()); + } + } + } + if (middle_texture_rect_str.size() > 0) { + std::vector items; + boost::algorithm::erase_all(middle_texture_rect_str, " "); + boost::split(items, middle_texture_rect_str, boost::is_any_of(",")); + if (items.size() == 4) { + for (int i = 0; i < items.size(); i++) { + middle_texture_rect[i] = std::atof(items[i].c_str()); + } + } + } auto is_single_extruder = wxGetApp().preset_bundle->get_printer_extruder_count() == 1; if (!is_single_extruder) { m_allow_bed_type_in_double_nozzle.clear(); pte_part1 = BedTextureInfo::TexturePart(57, 300, 236.12f, 10.f, "qdt_bed_pte_middle.svg"); + auto &middle_rect = middle_texture_rect; + if (middle_rect[2] > 0.f) { + pte_part1 = BedTextureInfo::TexturePart(middle_rect[0], middle_rect[1], middle_rect[2], middle_rect[3], "qdt_bed_pte_middle.svg"); + } pte_part2 = BedTextureInfo::TexturePart(45, -14.5, 70, 8, "qdt_bed_pte_left_bottom.svg"); - + auto &bottom_rect = bottom_texture_rect; + if (bottom_texture_end_name.size() > 0 && bottom_rect[2] > 0.f) { + std::string pte_part2_name = "qdt_bed_pte_bottom_" + bottom_texture_end_name + ".svg"; + pte_part2 = BedTextureInfo::TexturePart(bottom_rect[0], bottom_rect[1], bottom_rect[2], bottom_rect[3], pte_part2_name); + } pei_part1 = BedTextureInfo::TexturePart(57, 300, 236.12f, 10.f, "qdt_bed_pei_middle.svg"); + if (middle_rect[2] > 0.f) { + pei_part1 = BedTextureInfo::TexturePart(middle_rect[0], middle_rect[1], middle_rect[2], middle_rect[3], "qdt_bed_pte_middle.svg"); + } pei_part2 = BedTextureInfo::TexturePart(45, -14.5, 70, 8, "qdt_bed_pei_left_bottom.svg"); + if (bottom_texture_end_name.size() > 0 && bottom_rect[2] > 0.f) { + std::string pei_part2_name = "qdt_bed_pei_bottom_" + bottom_texture_end_name + ".svg"; + pei_part2 = BedTextureInfo::TexturePart(bottom_rect[0], bottom_rect[1], bottom_rect[2], bottom_rect[3], pei_part2_name); + } m_allow_bed_type_in_double_nozzle[(int) btPEI] = true; m_allow_bed_type_in_double_nozzle[(int) btPTE] = true; } @@ -6166,8 +6212,8 @@ void PartPlateList::init_bed_type_info() float base_width = 256;//standard 256*256 for single_extruder float base_height = 256; if (!is_single_extruder) {//standard 350*325 for double_extruder - base_width = 350; - base_height = 320; + base_width = bed_width; + base_height = bed_height; } float x_rate = bed_width / base_width; float y_rate = bed_height / base_height; diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 8a79f81..6577133 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -152,16 +152,15 @@ private: void init(); bool valid_instance(int obj_id, int instance_id); - void generate_print_polygon(ExPolygon &print_polygon); void generate_exclude_polygon(ExPolygon &exclude_polygon); void generate_logo_polygon(ExPolygon &logo_polygon); void generate_logo_polygon(ExPolygon &logo_polygon,const BoundingBoxf3& box); void calc_bounding_boxes() const; void calc_height_limit(); + int get_right_icon_offset_bed(); void calc_vertex_for_plate_name(GLTexture &texture, GLModel &buffer); void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, GLModel &buffer); - void calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer); bool calc_bed_3d_boundingbox(BoundingBoxf3 & box_in_plate_origin); void render_logo(bool bottom, bool render_cali = true); void render_logo_texture(GLTexture &logo_texture, GLModel &logo_buffer, bool bottom); @@ -318,6 +317,7 @@ public: bool check_filament_printable(const DynamicPrintConfig & config, wxString& error_message); bool check_tpu_printable_status(const DynamicPrintConfig & config, const std::vector &tpu_filaments); bool check_mixture_of_pla_and_petg(const DynamicPrintConfig & config); + bool check_compatible_of_nozzle_and_filament(const DynamicPrintConfig & config, const std::vector& filament_presets, std::string& error_msg); /* instance related operations*/ //judge whether instance is bound in plate or not diff --git a/src/slic3r/GUI/PartSkipCommon.hpp b/src/slic3r/GUI/PartSkipCommon.hpp new file mode 100644 index 0000000..bd158ed --- /dev/null +++ b/src/slic3r/GUI/PartSkipCommon.hpp @@ -0,0 +1,18 @@ +#ifndef PARTSKIPCOMMON_H +#define PARTSKIPCOMMON_H + + +namespace Slic3r { namespace GUI { + +enum PartState { + psUnCheck, + psChecked, + psSkipped +}; + + +typedef std::vector> PartsInfo; + +}} + +#endif // PARTSKIPCOMMON_H \ No newline at end of file diff --git a/src/slic3r/GUI/PartSkipDialog.cpp b/src/slic3r/GUI/PartSkipDialog.cpp new file mode 100644 index 0000000..698a7d8 --- /dev/null +++ b/src/slic3r/GUI/PartSkipDialog.cpp @@ -0,0 +1,1048 @@ +#include "GUI_Utils.hpp" +#include "GUI_App.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Widgets/CheckBox.hpp" +#include "Widgets/Label.hpp" + +#include "MsgDialog.hpp" +#include "Printer/PrinterFileSystem.h" +#include "PartSkipDialog.hpp" +#include "SkipPartCanvas.hpp" +#include "MediaPlayCtrl.h" + +namespace Slic3r { namespace GUI { + +extern wxString hide_passwd(wxString url, std::vector const &passwords); +extern void refresh_agora_url(char const *device, char const *dev_ver, char const *channel, void *context, void (*callback)(void *context, char const *url)); + +StateColor percent_bg(std::pair(wxColour(255, 255, 255), StateColor::Disabled), + std::pair(wxColour(255, 255, 255), StateColor::Pressed), + std::pair(wxColour(255, 255, 255), StateColor::Hovered), + std::pair(wxColour(255, 255, 255), StateColor::Enabled), + std::pair(wxColour(255, 255, 255), StateColor::Normal)); + +static StateColor zoom_bg(std::pair(wxColour(255, 255, 255), StateColor::Disabled), + std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(wxColour(255, 255, 255), StateColor::Enabled), + std::pair(wxColour(255, 255, 255), StateColor::Normal)); + +static StateColor zoom_bd(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); +static StateColor zoom_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); + +static StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + +static StateColor btn_bg_gray(std::pair(wxColour(194, 194, 194), StateColor::Pressed), + std::pair(wxColour(194, 194, 194), StateColor::Hovered), + std::pair(wxColour(194, 194, 194), StateColor::Normal)); + +//y +static StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), + std::pair(wxColour(68, 121, 251), StateColor::Normal)); + +PartSkipDialog::PartSkipDialog(wxWindow *parent) : DPIDialog(parent, wxID_ANY, _L("Skip Objects"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + std::time_t t = std::time(0); + std::stringstream buf; + buf << put_time(std::localtime(&t), "%a_%b_%d_%H_%M_%S/"); + m_timestamp = buf.str(); + + std::string icon_path = (boost::format("%1%/images/QIDIStudioTitle.ico") % Slic3r::resources_dir()).str(); + SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + SetBackgroundColour(*wxWHITE); + + m_sizer = new wxBoxSizer(wxVERTICAL); + + m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line_top->SetMinSize(wxSize(-1, 1)); + m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA)); + m_sizer->Add(m_line_top, 0, wxEXPAND | wxTOP, FromDIP(0)); + + m_simplebook = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0); + m_simplebook->SetMinSize(wxSize(FromDIP(720), FromDIP(535))); + m_simplebook->SetMaxSize(wxSize(FromDIP(720), FromDIP(535))); + m_book_first_panel = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_book_third_panel = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_book_third_panel->SetBackgroundColour(*wxWHITE); + m_dlg_sizer = new wxBoxSizer(wxVERTICAL); + m_dlg_content_sizer = new wxBoxSizer(wxHORIZONTAL); + m_canvas_sizer = new wxBoxSizer(wxVERTICAL); + + // page 3 + wxGLAttributes canvasAttrs; + canvasAttrs.PlatformDefaults().Defaults().Stencil(8).EndList(); + m_canvas = new SkipPartCanvas(m_book_third_panel, canvasAttrs); + m_canvas->SetMinSize(wxSize(FromDIP(400), FromDIP(400))); + m_canvas->SetMaxSize(wxSize(FromDIP(400), FromDIP(400))); + + m_canvas_btn_sizer = new wxBoxSizer(wxHORIZONTAL); + m_canvas_btn_sizer->SetMinSize(wxSize(-1, FromDIP(28))); + + zoom_bg.setTakeFocusedAsHovered(false); + + m_zoom_out_btn = new Button(m_book_third_panel, wxEmptyString); + m_zoom_out_btn->SetIcon("canvas_zoom_out"); + m_zoom_out_btn->SetToolTip(_L("Zoom Out")); + m_zoom_out_btn->SetBackgroundColor(zoom_bg); + m_zoom_out_btn->SetBorderColor(wxColour(238, 238, 238)); + m_zoom_out_btn->SetCornerRadius(0); + m_zoom_out_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + + m_percent_label = new Button(m_book_third_panel, _L("100 %")); + m_percent_label->SetBackgroundColor(percent_bg); + m_percent_label->SetBorderColor(wxColour(238, 238, 238)); + m_percent_label->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_percent_label->SetCornerRadius(0); + + m_zoom_in_btn = new Button(m_book_third_panel, wxEmptyString); + m_zoom_in_btn->SetIcon("canvas_zoom_in"); + m_zoom_in_btn->SetToolTip(_L("Zoom In")); + m_zoom_in_btn->SetBackgroundColor(zoom_bg); + m_zoom_in_btn->SetBorderColor(wxColour(238, 238, 238)); + m_zoom_in_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_zoom_in_btn->SetCornerRadius(0); + + m_switch_drag_btn = new Button(m_book_third_panel, wxEmptyString); + m_switch_drag_btn->SetIcon("canvas_drag"); + m_switch_drag_btn->SetToolTip(_L("Drag")); + m_switch_drag_btn->SetBackgroundColor(*wxWHITE); + m_switch_drag_btn->SetBorderColor(wxColour(238, 238, 238)); + m_switch_drag_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_switch_drag_btn->SetCornerRadius(0); + + m_canvas_btn_sizer->Add(m_zoom_out_btn, 0, wxEXPAND | wxLEFT, FromDIP(105)); + m_canvas_btn_sizer->Add(m_percent_label, 0, wxEXPAND, 0); + m_canvas_btn_sizer->Add(m_zoom_in_btn, 0, wxEXPAND, 0); + m_canvas_btn_sizer->Add(m_switch_drag_btn, 0, wxEXPAND | wxRIGHT, FromDIP(88)); + + m_list_sizer = new wxBoxSizer(wxVERTICAL); + m_list_sizer->SetMinSize(wxSize(FromDIP(267), FromDIP(422))); + + auto all_checkbox_sizer = new wxBoxSizer(wxHORIZONTAL); + m_all_checkbox = new CheckBox(m_book_third_panel, wxID_ANY); + m_all_checkbox->SetValue(false); + m_all_checkbox->SetMinSize(wxSize(FromDIP(18), FromDIP(18))); + m_all_checkbox->SetBackgroundColour(*wxWHITE); + m_all_label = new Label(m_book_third_panel, _L("Select All")); + m_all_label->Wrap(-1); + m_all_label->SetMinSize(wxSize(-1, FromDIP(18))); + m_all_label->SetBackgroundColour(*wxWHITE); + + m_all_label->SetMinSize(wxSize(267, -1)); + m_all_label->SetMaxSize(wxSize(267, -1)); + all_checkbox_sizer->Add(m_all_checkbox, 0, wxALIGN_CENTER_VERTICAL, 0); + all_checkbox_sizer->Add(m_all_label, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(8)); + + m_line = new wxPanel(m_book_third_panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(267), FromDIP(1)), wxTAB_TRAVERSAL); + m_line->SetMinSize(wxSize(FromDIP(267), 1)); + m_line->SetMaxSize(wxSize(FromDIP(267), 1)); + m_line->SetBackgroundColour(wxColor(238, 238, 238)); + + m_list_view = new wxScrolledWindow(m_book_third_panel, wxID_ANY, wxDefaultPosition, wxSize(267, -1), wxHSCROLL | wxVSCROLL); + m_list_view->SetScrollRate(5, 5); + m_list_view->SetMinSize(wxSize(FromDIP(267), FromDIP(378))); + m_list_view->SetMaxSize(wxSize(FromDIP(267), FromDIP(378))); + m_list_view->SetBackgroundColour(*wxWHITE); + + m_scroll_sizer = new wxBoxSizer(wxVERTICAL); + m_list_view->SetSizer(m_scroll_sizer); + m_list_view->Layout(); + + m_dlg_btn_sizer = new wxBoxSizer(wxHORIZONTAL); + m_dlg_btn_sizer->SetMinSize(wxSize(-1, FromDIP(54))); + + m_cnt_label = new Label(m_book_third_panel, wxEmptyString); + m_cnt_label->Wrap(-1); + m_cnt_label->SetBackgroundColour(*wxWHITE); + m_cnt_label->SetForegroundColour(wxColour(0, 174, 66)); + m_cnt_label->SetFont(Label::Head_16); + m_cnt_label->SetSize(wxSize(-1, FromDIP(20))); + m_cnt_label->SetMaxSize(wxSize(-1, FromDIP(20))); + + m_tot_label = new Label(m_book_third_panel, wxEmptyString); + m_tot_label->Wrap(-1); + m_tot_label->SetBackgroundColour(*wxWHITE); + m_tot_label->SetMinSize(wxSize(FromDIP(200), FromDIP(20))); + + m_apply_btn = new Button(m_book_third_panel, _L("Skip")); + m_apply_btn->SetBackgroundColor(btn_bg_gray); + m_apply_btn->SetTextColor(*wxWHITE); + // m_apply_btn->SetBorderColor(wxColour(38, 46, 48)); + m_apply_btn->SetFont(Label::Body_14); + m_apply_btn->SetSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_btn->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_btn->SetCornerRadius(FromDIP(16)); + m_apply_btn->SetToolTip(wxEmptyString); + + m_canvas_sizer->Add(m_canvas, 0, wxLEFT | wxTOP | wxEXPAND, FromDIP(17)); + m_canvas_sizer->Add(m_canvas_btn_sizer, 0, wxTOP, FromDIP(8)); + m_list_sizer->Add(0, 0, 1, wxEXPAND, 0); + + m_list_sizer->Add(0, 0, 0, wxTOP, FromDIP(27)); + m_list_sizer->Add(all_checkbox_sizer, 0, wxLEFT, FromDIP(0)); + m_list_sizer->Add(m_line, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(12)); + m_list_sizer->Add(m_list_view, 0, wxEXPAND, 0); + m_list_sizer->Add(0, 0, 1, wxEXPAND, 0); + + m_dlg_content_sizer->Add(m_canvas_sizer, 0, wxEXPAND, FromDIP(0)); + m_dlg_content_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(22)); + m_dlg_content_sizer->Add(m_list_sizer, 0, wxRIGHT | wxEXPAND, FromDIP(14)); + + m_dlg_btn_sizer->Add(0, 0, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(21)); + m_dlg_btn_sizer->Add(m_cnt_label, 0, wxALIGN_CENTER_VERTICAL, FromDIP(0)); +#ifdef __WXMSW__ + m_dlg_btn_sizer->Add(m_tot_label, 0, wxLEFT | wxTOP | wxALIGN_CENTER_VERTICAL, FromDIP(2)); +#else + m_dlg_btn_sizer->Add(m_tot_label, 0, wxALIGN_CENTER_VERTICAL, 0); +#endif + m_dlg_btn_sizer->Add(0, 0, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL, FromDIP(0)); + m_dlg_btn_sizer->Add(m_apply_btn, 0, wxALIGN_CENTER_VERTICAL, FromDIP(0)); + m_dlg_btn_sizer->Add(0, 0, 0, wxLEFT | wxEXPAND | wxALIGN_CENTER_VERTICAL, FromDIP(24)); + + m_dlg_placeholder = new wxPanel(m_book_third_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_dlg_placeholder->SetMinSize(wxSize(-1, FromDIP(15))); + m_dlg_placeholder->SetMaxSize(wxSize(-1, FromDIP(15))); + m_dlg_placeholder->SetBackgroundColour(*wxWHITE); + + m_dlg_sizer->Add(m_dlg_content_sizer, 1, wxEXPAND, FromDIP(0)); + // m_dlg_sizer->Add( 0, 0, 1, wxEXPAND, FromDIP(0)); + m_dlg_sizer->Add(m_dlg_btn_sizer, 0, wxEXPAND, FromDIP(0)); + m_dlg_sizer->Add(m_dlg_placeholder, 0, 0, wxEXPAND, 0); + + m_book_third_panel->SetSizer(m_dlg_sizer); + m_book_third_panel->Layout(); + m_dlg_sizer->Fit(m_book_third_panel); + + // page 2 + m_book_second_panel = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_book_second_panel->SetBackgroundColour(*wxWHITE); + m_book_second_sizer = new wxBoxSizer(wxVERTICAL); + m_book_second_btn_sizer = new wxBoxSizer(wxHORIZONTAL); + + m_retry_bitmap = new wxStaticBitmap(m_book_second_panel, -1, create_scaled_bitmap("partskip_retry", m_book_second_panel, 200), wxDefaultPosition, wxDefaultSize); + m_retry_label = new Label(m_book_second_panel, _L("Load skipping objects information failed. Please try again.")); + m_retry_label->Wrap(-1); + m_retry_label->SetBackgroundColour(*wxWHITE); + m_book_second_sizer->Add(0, 0, 1, wxEXPAND, 0); + m_book_second_sizer->Add(m_retry_bitmap, 0, wxALIGN_CENTER_HORIZONTAL, 0); + m_book_second_sizer->Add(m_retry_label, 0, wxALIGN_CENTER_HORIZONTAL, 0); + m_book_second_sizer->Add(0, 0, 1, wxEXPAND, 0); + + m_second_retry_btn = new Button(m_book_second_panel, _L("Retry")); + m_second_retry_btn->SetBackgroundColor(btn_bg_blue); + // m_second_retry_btn->SetBorderColor(wxColour(38, 46, 48)); + m_second_retry_btn->SetTextColor(*wxWHITE); + m_second_retry_btn->SetFont(Label::Body_14); + m_second_retry_btn->SetSize(wxSize(FromDIP(80), FromDIP(32))); + m_second_retry_btn->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_second_retry_btn->SetCornerRadius(FromDIP(16)); + m_second_retry_btn->Bind(wxEVT_BUTTON, &PartSkipDialog::OnRetryButton, this); + m_book_second_btn_sizer->Add(m_second_retry_btn, 0, wxALL, FromDIP(24)); + + m_book_second_sizer->Add(m_book_second_btn_sizer, 0, wxALIGN_RIGHT, 0); + m_book_second_panel->SetSizer(m_book_second_sizer); + m_book_second_panel->Layout(); + m_book_second_sizer->Fit(m_book_second_panel); + + // page 1 + m_book_first_panel = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_book_first_sizer = new wxBoxSizer(wxVERTICAL); + // m_book_first_sizer->SetMinSize(wxSize(FromDIP(720), FromDIP(500))); + + auto m_loading_sizer = new wxBoxSizer(wxHORIZONTAL); + std::vector list{"ams_rfid_1", "ams_rfid_2", "ams_rfid_3", "ams_rfid_4"}; + m_loading_icon = new AnimaIcon(m_book_first_panel, wxID_ANY, list, "refresh_printer", 100); + m_loading_icon->SetMinSize(wxSize(FromDIP(25), FromDIP(25))); + + m_loading_label = new Label(m_book_first_panel, _L("Loading ...")); + m_loading_label->Wrap(-1); + m_loading_label->SetBackgroundColour(*wxWHITE); + + m_loading_sizer->Add(m_loading_icon, 0, wxALIGN_CENTER_VERTICAL, FromDIP(0)); + m_loading_sizer->Add(m_loading_label, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + + m_book_first_sizer->Add(0, 0, 1, wxEXPAND, 0); + m_book_first_sizer->Add(m_loading_sizer, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL, 0); + m_book_first_sizer->Add(0, 0, 1, wxEXPAND, 0); + + m_book_first_panel->SetSizer(m_book_first_sizer); + m_book_first_panel->Layout(); + m_book_first_sizer->Fit(m_book_first_panel); + + m_simplebook->AddPage(m_book_first_panel, _("loading page"), false); + m_simplebook->AddPage(m_book_second_panel, _("retry page"), false); + m_simplebook->AddPage(m_book_third_panel, _("dialog page"), false); + m_sizer->Add(m_simplebook, 1, wxEXPAND | wxALL, 5); + + SetSizer(m_sizer); + m_zoom_in_btn->Bind(wxEVT_BUTTON, &PartSkipDialog::OnZoomIn, this); + m_zoom_out_btn->Bind(wxEVT_BUTTON, &PartSkipDialog::OnZoomOut, this); + m_switch_drag_btn->Bind(wxEVT_BUTTON, &PartSkipDialog::OnSwitchDrag, this); + m_canvas->Bind(EVT_ZOOM_PERCENT, &PartSkipDialog::OnZoomPercent, this); + m_canvas->Bind(EVT_CANVAS_PART, &PartSkipDialog::UpdatePartsStateFromCanvas, this); + + m_apply_btn->Bind(wxEVT_BUTTON, &PartSkipDialog::OnApplyDialog, this); + m_all_checkbox->Bind(wxEVT_TOGGLEBUTTON, &PartSkipDialog::OnAllCheckbox, this); + + Layout(); + Fit(); + CentreOnParent(); +} + +PartSkipDialog::~PartSkipDialog() {} + +void PartSkipDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_canvas->LoadPickImage(m_local_paths[0]); + + m_loading_icon->SetMinSize(wxSize(FromDIP(25), FromDIP(25))); + m_retry_bitmap->SetBitmap(create_scaled_bitmap("partskip_retry", m_book_second_panel, 200)); + + m_percent_label->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_percent_label->SetMaxSize(wxSize(FromDIP(56), FromDIP(28))); + m_zoom_out_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_zoom_out_btn->SetMaxSize(wxSize(FromDIP(56), FromDIP(28))); + m_zoom_in_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_zoom_in_btn->SetMaxSize(wxSize(FromDIP(56), FromDIP(28))); + m_switch_drag_btn->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); + m_switch_drag_btn->SetMaxSize(wxSize(FromDIP(56), FromDIP(28))); + m_percent_label->Rescale(); + m_zoom_out_btn->Rescale(); + m_zoom_in_btn->Rescale(); + m_switch_drag_btn->Rescale(); + + m_cnt_label->SetMaxSize(wxSize(-1, FromDIP(20))); + + m_tot_label->SetMinSize(wxSize(FromDIP(200), FromDIP(20))); + m_tot_label->SetLabel(m_tot_label->GetLabel()); + m_tot_label->Refresh(); + + m_line_top->SetMinSize(wxSize(-1, 1)); + m_line->SetMinSize(wxSize(FromDIP(267), 1)); + m_line->SetMaxSize(wxSize(FromDIP(267), 1)); + + m_apply_btn->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_btn->SetCornerRadius(FromDIP(16)); + m_apply_btn->Rescale(); + + m_dlg_placeholder->SetMinSize(wxSize(-1, FromDIP(15))); + m_dlg_placeholder->SetMaxSize(wxSize(-1, FromDIP(15))); + + // m_second_retry_btn->SetSize(wxSize(-1, FromDIP(32))); + m_second_retry_btn->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_second_retry_btn->SetCornerRadius(FromDIP(16)); + m_second_retry_btn->Rescale(); + + m_all_checkbox->SetMinSize(wxSize(FromDIP(18), FromDIP(18))); + m_all_checkbox->Rescale(); + + for (auto it = m_scroll_sizer->GetChildren().begin(); it != m_scroll_sizer->GetChildren().end(); ++it) { + wxSizerItem *item = *it; + if (item && item->IsSizer()) { + wxSizer *sizer = item->GetSizer(); + auto check_item = sizer->GetItem((size_t) 0); + if (check_item && check_item->IsWindow()) { + wxWindow *window = check_item->GetWindow(); + CheckBox *checkbox = dynamic_cast(window); + checkbox->SetMinSize(wxSize(FromDIP(18), FromDIP(18))); + checkbox->Rescale(); + } + } + } + m_canvas_btn_sizer->SetMinSize(wxSize(-1, FromDIP(28))); + m_canvas_btn_sizer->Layout(); + m_canvas_sizer->Layout(); + m_dlg_content_sizer->Layout(); + m_dlg_sizer->Layout(); + + Fit(); + Layout(); +} + +std::string PartSkipDialog::create_tmp_path() +{ + boost::filesystem::path parent_path(temporary_dir()); + + std::stringstream buf; + buf << "/bamboo_task/"; + buf << m_timestamp; + if (m_obj) { + buf << m_obj->dev_id << "_"; + buf << m_obj->job_id_ << "/"; + } else { + buf << 1 << "_" << 1 << "/"; + } + std::string tmp_path = (parent_path / buf.str()).string(); + + if (!std::filesystem::exists(tmp_path + "Metadata/") && !fs::create_directories(tmp_path + "Metadata/")) { wxMessageBox("create file failed."); } + return tmp_path; +} + +bool PartSkipDialog::is_local_file_existed(const std::vector &local_paths) +{ + for (auto path : local_paths) { + if (!std::filesystem::exists(path)) { return false; } + } + return true; +} + +void PartSkipDialog::DownloadPartsFile() +{ + BOOST_LOG_TRIVIAL(info) << "part skip: create temp path begin."; + m_tmp_path = create_tmp_path(); // wxGetApp().app_config->get("download_path"); + BOOST_LOG_TRIVIAL(info) << "part skip: create temp path end."; + + m_local_paths.clear(); + m_target_paths.clear(); + + m_plate_idx = m_obj ? m_obj->m_plate_index : -1; + if (m_plate_idx < 0) { + m_plate_idx = 1; + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << "part skip: printer plate index is invalid."; + } + + m_local_paths.push_back(m_tmp_path + "Metadata/pick_" + std::to_string(m_plate_idx) + ".png"); + m_local_paths.push_back(m_tmp_path + "Metadata/model_settings.config"); + m_local_paths.push_back(m_tmp_path + "Metadata/slice_info.config"); + + m_target_paths.push_back("Metadata/pick_" + std::to_string(m_plate_idx) + ".png"); + m_target_paths.push_back("Metadata/model_settings.config"); + m_target_paths.push_back("Metadata/slice_info.config"); + + if (!is_local_file_existed(m_local_paths)) { + if (!m_file_sys) { + m_file_sys = boost::make_shared(); + m_file_sys->Attached(); + m_file_sys->Bind(EVT_STATUS_CHANGED, &PartSkipDialog::OnFileSystemEvent, this); + m_file_sys->Bind(EVT_RAMDOWNLOAD, &PartSkipDialog::OnFileSystemResult, this); + m_file_sys->Start(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "part skip: print file system start."; + } else { + m_file_sys->Retry(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "part skip: print file system retry."; + } + } else { + m_file_sys->SendExistedFile(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "part skip: local parts info file is existed."; + } +} +// actor +void PartSkipDialog::fetchUrl(boost::weak_ptr wfs) +{ + boost::shared_ptr fs(wfs.lock()); + if (!fs) return; + + DeviceManager *dm = GUI::wxGetApp().getDeviceManager(); + MachineObject *obj = dm->get_selected_machine(); + + if (obj == nullptr) { + fs->SetUrl("0"); + return; + } + std::string dev_ver = obj->get_ota_version(); + std::string dev_id = obj->dev_id; + // int remote_proto = obj->get_file_remote(); + + NetworkAgent *agent = wxGetApp().getAgent(); + std::string agent_version = agent ? agent->get_version() : ""; + + auto url_state = m_url_state; + if (obj->is_lan_mode_printer()) { url_state = URL_TCP; } + + if (agent) { + switch (url_state) { + case URL_TCP: { + std::string devIP = obj->dev_ip; + std::string accessCode = obj->get_access_code(); + std::string tcp_url = "qidi:///local/" + devIP + "?port=6000&user=" + "qdtp" + "&passwd=" + accessCode; + CallAfter([=] { + boost::shared_ptr fs(wfs.lock()); + if (!fs) return; + if (boost::algorithm::starts_with(tcp_url, "qidi:///")) { + fs->SetUrl(tcp_url); + } else { + fs->SetUrl("3"); + } + }); + break; + } + case URL_TUTK: { + std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""}; + agent->get_camera_url(obj->dev_id + "|" + dev_ver + "|" + protocols[3], [this, wfs, m = dev_id, v = agent->get_version(), dv = dev_ver](std::string url) { + if (boost::algorithm::starts_with(url, "qidi:///")) { + url += "&device=" + m; + url += "&net_ver=" + v; + url += "&dev_ver=" + dv; + url += "&refresh_url=" + boost::lexical_cast(&refresh_agora_url); + url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid"); + url += "&cli_ver=" + std::string(SLIC3R_VERSION); + } + CallAfter([=] { + boost::shared_ptr fs(wfs.lock()); + if (!fs) return; + if (boost::algorithm::starts_with(url, "qidi:///")) { + fs->SetUrl(url); + } else { + fs->SetUrl("3"); + } + }); + }); + break; + } + default: break; + } + } +} +// controller +void PartSkipDialog::OnFileSystemEvent(wxCommandEvent &e) +{ + e.Skip(); + auto wfs = boost::weak_ptr(m_file_sys); + boost::shared_ptr fs(wfs.lock()); + if (!fs) return; + + wxString msg; + int status = e.GetInt(); + // int extra = e.GetExtraLong(); + + switch (status) { + case PrinterFileSystem::Initializing: + case PrinterFileSystem::Connecting: break; + case PrinterFileSystem::ListSyncing: { + m_file_sys->GetPickImages(m_local_paths, m_target_paths); + break; + } + case PrinterFileSystem::Failed: { + m_file_sys->Stop(); + if (m_url_state == URL_TCP) { + m_url_state = URL_TUTK; + m_file_sys->SetUrl("3"); + m_file_sys->Retry(); + BOOST_LOG_TRIVIAL(info) << "part skip: print file system connnect failed first."; + } else { + m_file_sys->SendConnectFail(); + BOOST_LOG_TRIVIAL(info) << "part skip: print file system connnect failed second."; + } + break; + } + case PrinterFileSystem::Reconnecting: break; + } + if (e.GetInt() == PrinterFileSystem::Initializing) { + CallAfter([=] { + boost::shared_ptr fs(wfs.lock()); + if (!fs) return; + fetchUrl(boost::weak_ptr(fs)); + BOOST_LOG_TRIVIAL(info) << "part skip: fetch url, get parts info files from printer."; + }); + } +} + +// reseter: [TCP -> TUTK(TCP)] -> [TCP -> TUTK(TCP)] +void PartSkipDialog::OnFileSystemResult(wxCommandEvent &event) +{ + int result = event.GetInt(); + m_loading_icon->Stop(); + if (result == 0) { + InitDialogUI(); + SetSimplebookPage(2); + m_file_sys->Stop(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "part skip: on file system result success."; + } else { + m_url_state = URL_TCP; + SetSimplebookPage(1); + m_file_sys->Stop(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "part skip: on file system result failed."; + } +} + +void PartSkipDialog::InitSchedule(MachineObject *obj) +{ + m_obj = obj; + SetSimplebookPage(0); + m_loading_icon->Play(); + DownloadPartsFile(); +} + +void PartSkipDialog::OnRetryButton(wxCommandEvent &event) +{ + event.Skip(); + InitSchedule(m_obj); + Refresh(); +} + +bool PartSkipDialog::is_drag_mode() { return m_is_drag == true; } + +PartsInfo PartSkipDialog::GetPartsInfo() +{ + PartsInfo parts_info; + for (auto [part_id, part_state] : this->m_parts_state) { parts_info.push_back(std::pair(part_id, part_state)); } + return parts_info; +} + +void PartSkipDialog::OnZoomIn(wxCommandEvent &event) +{ + m_canvas->ZoomIn(20); + UpdateZoomPercent(); +} + +void PartSkipDialog::OnZoomOut(wxCommandEvent &event) +{ + m_canvas->ZoomOut(20); + UpdateZoomPercent(); +} + +void PartSkipDialog::OnSwitchDrag(wxCommandEvent &event) +{ + if (this->is_drag_mode()) { + m_is_drag = false; + m_switch_drag_btn->SetBackgroundColor(*wxWHITE); + m_switch_drag_btn->SetIcon("canvas_drag"); + } else { + m_is_drag = true; + m_switch_drag_btn->SetBackgroundColor(wxColour(0, 174, 66)); + m_switch_drag_btn->SetIcon("canvas_drag_active"); + } + m_canvas->SwitchDrag(m_is_drag); +} + +void PartSkipDialog::OnZoomPercent(wxCommandEvent &event) +{ + m_zoom_percent = event.GetInt(); + if (m_zoom_percent >= 1000) { + m_zoom_percent = 1000; + m_zoom_in_btn->Enable(false); + m_zoom_in_btn->SetIcon("canvas_zoom_in_disable"); + } else if (m_zoom_percent <= 100) { + m_zoom_percent = 100; + m_zoom_out_btn->Enable(false); + m_zoom_out_btn->SetIcon("canvas_zoom_out_disable"); + } else { + m_zoom_in_btn->Enable(true); + m_zoom_out_btn->Enable(true); + m_zoom_in_btn->SetIcon("canvas_zoom_in"); + m_zoom_out_btn->SetIcon("canvas_zoom_out"); + } + + UpdateZoomPercent(); +} + +void PartSkipDialog::UpdatePartsStateFromCanvas(wxCommandEvent &event) +{ + int part_id = event.GetExtraLong(); + PartState part_state = PartState(event.GetInt()); + + m_parts_state[part_id] = part_state; + if (part_state == psUnCheck) { m_all_checkbox->SetValue(false); } + if (IsAllChecked()) { m_all_checkbox->SetValue(true); } + + UpdateApplyButtonStatus(); + UpdateDialogUI(); +} + +void PartSkipDialog::UpdateZoomPercent() { m_percent_label->SetLabel(wxString::Format(_L("%d%%"), m_zoom_percent)); } + +void PartSkipDialog::UpdateCountLabel() +{ + int check_cnt = 0; + int tot_cnt = 0; + for (auto [part_id, part_state] : m_parts_state) { + if (part_state == PartState::psChecked) check_cnt++; + if (part_state != PartState::psSkipped) tot_cnt++; + } + m_cnt_label->SetLabel(wxString::Format(_L("%d"), check_cnt)); + m_cnt_label->Fit(); + m_tot_label->SetLabel(wxString::Format(_L("/%d Selected"), tot_cnt)); + m_tot_label->Fit(); + m_dlg_btn_sizer->Layout(); +} + +bool PartSkipDialog::Show(bool show) +{ + if (show) { + wxGetApp().UpdateDlgDarkUI(this); + CentreOnParent(); + + Layout(); + Fit(); + } + return DPIDialog::Show(show); +} + +void PartSkipDialog::InitDialogUI() +{ + m_print_lock = true; + is_model_support_partskip = false; + BOOST_LOG_TRIVIAL(info) << "part skip: lock parts info from printer."; + m_scroll_sizer->Clear(true); + m_all_checkbox->SetValue(false); + m_parts_state.clear(); + m_parts_name.clear(); + + string pick_img = m_local_paths[0]; + string slice_info = m_local_paths[2]; + + m_switch_drag_btn->SetIcon("canvas_drag"); + m_switch_drag_btn->SetBackgroundColor(*wxWHITE); + m_is_drag = false; + m_canvas->SwitchDrag(false); + m_canvas->SetZoomPercent(100); + m_canvas->SetOffset(wxPoint(0, 0)); + + BOOST_LOG_TRIVIAL(info) << "part skip: load canvas pick image begin."; + m_canvas->LoadPickImage(pick_img); + BOOST_LOG_TRIVIAL(info) << "part skip: load canvas pick image end."; + ModelSettingHelper helper(slice_info); + + if (helper.Parse()) { + is_model_support_partskip = helper.GetLabelObjectEnabled(m_plate_idx); + auto parse_result = helper.GetPlateObjects(m_plate_idx); + for (const auto &part : parse_result) { + m_parts_state[part.identify_id] = part.state; + m_parts_name[part.identify_id] = part.name; + } + if (m_obj) { + std::vector partskip_ids = m_obj->m_partskip_ids; + for (auto part_id : partskip_ids) { m_parts_state[part_id] = PartState::psSkipped; } + } + + for (const auto &[part_id, part_state] : m_parts_state) { + auto line_sizer = new wxBoxSizer(wxHORIZONTAL); + auto checkbox = new CheckBox(m_list_view); + auto label = new Label(m_list_view, wxEmptyString); + + checkbox->Bind( + wxEVT_TOGGLEBUTTON, + [this, part_id = part_id](wxCommandEvent &event) { + m_parts_state[part_id] = event.IsChecked() ? PartState::psChecked : PartState::psUnCheck; + if (!event.IsChecked()) { + m_all_checkbox->SetValue(false); + } else if (IsAllChecked()) { + m_all_checkbox->SetValue(true); + } + m_canvas->UpdatePartsInfo(GetPartsInfo()); + UpdateCountLabel(); + UpdateApplyButtonStatus(); + event.Skip(); + }, + checkbox->GetId()); + + if (part_state == PartState::psChecked) { + checkbox->SetValue(true); + checkbox->Enable(true); + } else if (part_state == PartState::psUnCheck) { + checkbox->SetValue(false); + checkbox->Enable(true); + } else if (part_state == PartState::psSkipped) { + checkbox->SetValue(true); + checkbox->Enable(false); + } + label->SetLabel(wxString::FromUTF8(m_parts_name[part_id])); + label->SetBackgroundColour(*wxWHITE); + label->SetForegroundColour(wxColor(107, 107, 107)); + label->Wrap(-1); + label->SetMinSize(wxSize(-1, FromDIP(18))); + checkbox->SetBackgroundColour(*wxWHITE); + checkbox->SetMinSize(wxSize(FromDIP(18), FromDIP(18))); + checkbox->SetMaxSize(wxSize(FromDIP(18), FromDIP(18))); + + line_sizer->Add(checkbox, 0, wxALIGN_CENTER_VERTICAL, 0); + line_sizer->Add(label, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(8)); + m_scroll_sizer->Add(line_sizer, 0, wxBOTTOM | wxEXPAND, FromDIP(12)); + } + m_canvas->UpdatePartsInfo(GetPartsInfo()); + BOOST_LOG_TRIVIAL(info) << "part skip: update canvas parts info."; + } + + m_scroll_sizer->Layout(); + m_list_view->FitInside(); + UpdateApplyButtonStatus(); + UpdateCountLabel(); + Refresh(); + m_print_lock = false; + BOOST_LOG_TRIVIAL(info) << "part skip: unlock parts info from printer."; +} + +void PartSkipDialog::UpdatePartsStateFromPrinter(MachineObject *obj) +{ + if (m_print_lock) { + BOOST_LOG_TRIVIAL(info) << "part skip: parts info from printer is locked."; + return; + } + m_obj = obj; + if (m_obj) { + bool update_flag = false; + std::vector partskip_ids = m_obj->m_partskip_ids; + for (auto part_id : partskip_ids) { + if (m_parts_state[part_id] != PartState::psSkipped) { + m_parts_state[part_id] = PartState::psSkipped; + update_flag = true; + } + } + if (update_flag) { + m_canvas->UpdatePartsInfo(GetPartsInfo()); + UpdateDialogUI(); + } + } +} + +void PartSkipDialog::UpdateDialogUI() +{ + if (m_parts_state.size() != m_scroll_sizer->GetItemCount()) { + BOOST_LOG_TRIVIAL(warning) << "part skip: m_parts_state and m_scroll_sizer mismatch."; + return; + } + + for (auto it = m_parts_state.begin(); it != m_parts_state.end(); ++it) { + int idx = std::distance(m_parts_state.begin(), it); + auto part_state = it->second; + + wxSizerItem *item = m_scroll_sizer->GetItem(idx); + if (item && item->IsSizer()) { + wxSizer *sizer = item->GetSizer(); + auto check_item = sizer->GetItem((size_t) 0); + + if (check_item && check_item->IsWindow()) { + wxWindow *window = check_item->GetWindow(); + CheckBox *checkbox = dynamic_cast(window); + if (part_state == PartState::psChecked) { + checkbox->SetValue(true); + } else if (part_state == PartState::psUnCheck) { + checkbox->SetValue(false); + } else { + checkbox->SetValue(true); + checkbox->Enable(false); + } + } + } + } + + UpdateCountLabel(); + Refresh(); +} + +void PartSkipDialog::SetSimplebookPage(int page) { m_simplebook->SetSelection(page); } + +bool PartSkipDialog::IsAllChecked() +{ + for (auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psUnCheck) return false; + } + return true; +} + +bool PartSkipDialog::IsAllCancled() +{ + for (auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psChecked) return false; + } + return true; +} + +void PartSkipDialog::OnAllCheckbox(wxCommandEvent &event) +{ + if (m_all_checkbox->GetValue()) { + for (auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psUnCheck) part_state = PartState::psChecked; + } + } else { + for (auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psChecked) part_state = PartState::psUnCheck; + } + } + UpdateApplyButtonStatus(); + m_canvas->UpdatePartsInfo(GetPartsInfo()); + UpdateDialogUI(); + event.Skip(); +} + +void PartSkipDialog::UpdateApplyButtonStatus() +{ + if (IsAllCancled()) { + m_apply_btn->SetBackgroundColor(btn_bg_gray); + m_apply_btn->SetToolTip(_L("Nothing selected")); + m_enable_apply_btn = false; + } else if (m_parts_state.size() > 64) { + m_apply_btn->SetBackgroundColor(btn_bg_gray); + m_apply_btn->SetToolTip(_L("Over 64 objects in single plate")); + m_enable_apply_btn = false; + } else if (!is_model_support_partskip) { + m_apply_btn->SetBackgroundColor(btn_bg_gray); + m_apply_btn->SetToolTip(_L("The current print job cannot be skipped")); + m_enable_apply_btn = false; + } else { + m_apply_btn->SetBackgroundColor(btn_bg_blue); + m_apply_btn->SetToolTip(wxEmptyString); + m_enable_apply_btn = true; + } +} + +void PartSkipDialog::OnApplyDialog(wxCommandEvent &event) +{ + event.Skip(); + + if (!m_enable_apply_btn) return; + + m_partskip_ids.clear(); + for (const auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psChecked) { m_partskip_ids.push_back(part_id); } + } + + bool all_skipped = true; + for (auto [part_id, part_state] : m_parts_state) { + if (part_state == PartState::psUnCheck) all_skipped = false; + } + + PartSkipConfirmDialog confirm_dialog(this); + if (all_skipped) { + confirm_dialog.SetMsgLabel(_L("Skipping all objects.")); + confirm_dialog.SetTipLabel(_L("The printing job will be stopped. Continue?")); + } else { + confirm_dialog.SetMsgLabel(wxString::Format(_L("Skipping %d objects."), m_partskip_ids.size())); + confirm_dialog.SetTipLabel(_L("This action cannot be undone. Continue?")); + } + + if (confirm_dialog.ShowModal() == wxID_OK) { + if (m_obj) { + BOOST_LOG_TRIVIAL(info) << "part skip: skipping " << m_partskip_ids.size() << " objects."; + + if (all_skipped) { + m_obj->command_task_abort(); + BOOST_LOG_TRIVIAL(info) << "part skip: command skip all parts, abort task."; + } else if (m_partskip_ids.size() > 0) { + m_obj->command_task_partskip(m_partskip_ids); + BOOST_LOG_TRIVIAL(info) << "part skip: command skip " << m_partskip_ids.size() << " parts."; + } + EndModal(wxID_OK); + } else { + BOOST_LOG_TRIVIAL(warning) << "part skip: machine object is null."; + } + } +} + +int PartSkipDialog::GetAllSkippedPartsNum() +{ + int skipped_cnt = 0; + for (auto &[part_id, part_state] : m_parts_state) { + if (part_state == PartState::psSkipped || part_state == PartState::psChecked) skipped_cnt++; + } + return skipped_cnt; +} + +PartSkipConfirmDialog::PartSkipConfirmDialog(wxWindow *parent) : DPIDialog(parent, wxID_ANY, _L("Skip Objects"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + std::string icon_path = (boost::format("%1%/images/QIDIStudioTitle.ico") % Slic3r::resources_dir()).str(); + SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + SetBackgroundColour(*wxWHITE); + SetMinSize(wxSize(FromDIP(480), FromDIP(215))); + SetSizeHints(wxDefaultSize, wxDefaultSize); + + wxBoxSizer *m_sizer; + m_sizer = new wxBoxSizer(wxVERTICAL); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line_top->SetMinSize(wxSize(FromDIP(480), 1)); + m_line_top->SetMaxSize(wxSize(FromDIP(480), 1)); + m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA)); + m_sizer->Add(m_line_top, 0, wxEXPAND, 0); + m_sizer->Add(0, 0, 0, wxALL, FromDIP(15)); + + m_msg_label = new Label(this, _L("Skipping objects.")); + m_msg_label->Wrap(-1); + m_msg_label->SetBackgroundColour(*wxWHITE); + + m_tip_label = new Label(this, _L("This action cannot be undone. Continue?")); + m_tip_label->Wrap(-1); + m_tip_label->SetBackgroundColour(*wxWHITE); + m_tip_label->SetForegroundColour(wxColor(92, 92, 92)); + + m_sizer->Add(m_msg_label, 0, wxLEFT, FromDIP(29)); + m_sizer->Add(0, 0, 0, wxTOP, FromDIP(9)); + m_sizer->Add(m_tip_label, 0, wxLEFT, FromDIP(29)); + + wxBoxSizer *m_button_sizer; + m_button_sizer = new wxBoxSizer(wxHORIZONTAL); + m_button_sizer->SetMinSize(wxSize(FromDIP(480), FromDIP(54))); + m_button_sizer->Add(0, 0, 1, wxEXPAND, 0); + + StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + + //y + StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), + std::pair(wxColour(68, 121, 251), StateColor::Normal)); + + m_apply_button = new Button(this, _L("Continue")); + m_apply_button->SetBackgroundColor(btn_bg_blue); + m_apply_button->SetTextColor(*wxWHITE); + // m_apply_button->SetBorderColor(wxColour(38, 46, 48)); + m_apply_button->SetFont(Label::Body_14); + m_apply_button->SetSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_button->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_button->SetCornerRadius(FromDIP(16)); + m_apply_button->Bind(wxEVT_BUTTON, [this](auto &e) { + EndModal(wxID_OK); + e.Skip(); + }); + + m_button_sizer->Add(m_apply_button, 0, wxRIGHT | wxBOTTOM, FromDIP(24)); + m_sizer->Add(m_button_sizer, 1, wxEXPAND, FromDIP(5)); + m_sizer->Fit(this); + + SetSizer(m_sizer); + Layout(); + Fit(); +} + +PartSkipConfirmDialog::~PartSkipConfirmDialog() {} + +bool PartSkipConfirmDialog::Show(bool show) +{ + if (show) { + wxGetApp().UpdateDlgDarkUI(this); + CentreOnParent(); + + Layout(); + Fit(); + } + return DPIDialog::Show(show); +} + +void PartSkipConfirmDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + m_apply_button->SetMinSize(wxSize(FromDIP(80), FromDIP(32))); + m_apply_button->SetCornerRadius(FromDIP(16)); + m_apply_button->Rescale(); + Layout(); + Fit(); +} + +Button *PartSkipConfirmDialog::GetConfirmButton() { return m_apply_button; } + +void PartSkipConfirmDialog::SetMsgLabel(wxString msg) { m_msg_label->SetLabel(msg); } + +void PartSkipConfirmDialog::SetTipLabel(wxString msg) { m_tip_label->SetLabel(msg); } + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PartSkipDialog.hpp b/src/slic3r/GUI/PartSkipDialog.hpp new file mode 100644 index 0000000..4f0b5bf --- /dev/null +++ b/src/slic3r/GUI/PartSkipDialog.hpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Widgets/Label.hpp" +#include "Widgets/CheckBox.hpp" +#include "Widgets/Button.hpp" +#include "Widgets/AnimaController.hpp" +#include "DeviceManager.hpp" +#include "PartSkipCommon.hpp" +#include "Printer/PrinterFileSystem.h" +#include "I18N.hpp" +#include "GUI_Utils.hpp" + + +namespace Slic3r { namespace GUI { + +class SkipPartCanvas; + +enum URL_STATE { + URL_TCP, + URL_TUTK, +}; + +class PartSkipConfirmDialog : public DPIDialog +{ +private: +protected: + Label *m_msg_label; + Label *m_tip_label; + Button *m_apply_button; + +public: + PartSkipConfirmDialog(wxWindow *parent); + ~PartSkipConfirmDialog(); + + void on_dpi_changed(const wxRect &suggested_rect); + Button *GetConfirmButton(); + void SetMsgLabel(wxString msg); + void SetTipLabel(wxString msg); + bool Show(bool show); +}; + +class PartSkipDialog : public DPIDialog +{ +public: + PartSkipDialog(wxWindow *parent); + ~PartSkipDialog(); + void on_dpi_changed(const wxRect &suggested_rect); + bool Show(bool show); + + void UpdatePartsStateFromPrinter(MachineObject *obj_); + void SetSimplebookPage(int page); + void InitSchedule(MachineObject *obj_); + void InitDialogUI(); + int GetAllSkippedPartsNum(); + + MachineObject *m_obj{nullptr}; + + wxSimplebook *m_simplebook; + wxPanel *m_book_third_panel; + wxPanel *m_book_second_panel; + wxPanel *m_book_first_panel; + + SkipPartCanvas *m_canvas; + Button *m_zoom_in_btn; + Button *m_zoom_out_btn; + Button *m_switch_drag_btn; + CheckBox *m_all_checkbox; + Button *m_percent_label; + Label *m_all_label; + wxPanel *m_line; + wxPanel *m_line_top; + wxScrolledWindow *m_list_view; + + wxPanel *m_dlg_placeholder; + Label *m_cnt_label; + Label *m_tot_label; + + Button *m_apply_btn; + + Label *m_loading_label; + Label *m_retry_label; + ScalableBitmap *m_retry_icon; + wxStaticBitmap *m_retry_bitmap; + + wxBoxSizer *m_sizer; + wxBoxSizer *m_dlg_sizer; + wxBoxSizer *m_dlg_content_sizer; + wxBoxSizer *m_dlg_btn_sizer; + wxBoxSizer *m_canvas_sizer; + wxBoxSizer *m_canvas_btn_sizer; + wxBoxSizer *m_list_sizer; + wxBoxSizer *m_scroll_sizer; + wxBoxSizer *m_book_first_sizer; + wxBoxSizer *m_book_second_sizer; + wxBoxSizer *m_book_second_btn_sizer; + Button *m_second_retry_btn; + AnimaIcon *m_loading_icon; + +private: + int m_plate_idx{-1}; + int m_zoom_percent{100}; + bool m_is_drag{false}; + bool m_print_lock{true}; + bool m_enable_apply_btn{false}; + bool is_model_support_partskip{false}; + + std::map m_parts_state; + std::map m_parts_name; + std::vector m_partskip_ids; + + enum URL_STATE m_url_state = URL_STATE::URL_TCP; + + PartsInfo GetPartsInfo(); + bool is_drag_mode(); + + boost::shared_ptr m_file_sys; + bool m_file_sys_result{false}; + std::string m_timestamp; + std::string m_tmp_path; + std::vector m_local_paths; + std::vector m_target_paths; + std::string create_tmp_path(); + + bool is_local_file_existed(const std::vector &local_paths); + + void DownloadPartsFile(); + void OnFileSystemEvent(wxCommandEvent &event); + void OnFileSystemResult(wxCommandEvent &event); + void fetchUrl(boost::weak_ptr wfs); + + void OnZoomIn(wxCommandEvent &event); + void OnZoomOut(wxCommandEvent &event); + void OnSwitchDrag(wxCommandEvent &event); + void OnZoomPercent(wxCommandEvent &event); + void UpdatePartsStateFromCanvas(wxCommandEvent &event); + + void UpdateZoomPercent(); + void UpdateCountLabel(); + void UpdateDialogUI(); + void UpdateApplyButtonStatus(); + bool IsAllChecked(); + bool IsAllCancled(); + + void OnRetryButton(wxCommandEvent &event); + void OnAllCheckbox(wxCommandEvent &event); + void OnApplyDialog(wxCommandEvent &event); +}; + +}} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 89a07ba..ec09321 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -203,10 +203,8 @@ wxDEFINE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent); wxDEFINE_EVENT(EVT_NOTICE_CHILDE_SIZE_CHANGED, SimpleEvent); wxDEFINE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent); #define PRINTER_THUMBNAIL_SIZE (wxSize(FromDIP(48), FromDIP(48))) -#define PRINTER_THUMBNAIL_SIZE_SMALL (wxSize(FromDIP(32), FromDIP(32))) -#define PRINTER_PANEL_SIZE_SMALL (wxSize(FromDIP(98), FromDIP(68))) -#define PRINTER_PANEL_SIZE_WIDEN (wxSize(FromDIP(136), FromDIP(68))) -#define PRINTER_PANEL_SIZE (wxSize(FromDIP(98), FromDIP(98))) +#define PRINTER_PANEL_SIZE (wxSize(FromDIP(96), FromDIP(96))) +#define BTN_SYNC_SIZE (wxSize(FromDIP(96), FromDIP(98))) static string get_diameter_string(float diameter) { @@ -241,6 +239,21 @@ void Plater::show_illegal_characters_warning(wxWindow* parent) show_error(parent, _L("Invalid name, the following characters are not allowed:") + " <>:/\\|?*\"" +_L("(Including its escape characters)")); } +void Plater::mark_plate_toolbar_image_dirty() +{ + m_b_plate_toolbar_image_dirty = true; +} + +bool Plater::is_plate_toolbar_image_dirty() const +{ + return m_b_plate_toolbar_image_dirty; +} + +void Plater::clear_plate_toolbar_image_dirty() +{ + m_b_plate_toolbar_image_dirty = false; +} + static std::map bed_type_thumbnails = { {BedType::btPC, "bed_cool"}, {BedType::btEP, "bed_engineering"}, @@ -542,13 +555,12 @@ void Sidebar::priv::layout_printer(bool is_support_box, bool isDual) // double auto hsizer_extruder = new wxBoxSizer(wxHORIZONTAL); + hsizer_extruder->Add(left_extruder->sizer, 1, wxEXPAND, 0); hsizer_extruder->AddSpacer(FromDIP(4)); - hsizer_extruder->Add(left_extruder->sizer, 1, wxEXPAND); - hsizer_extruder->Add(right_extruder->sizer, 1, wxLEFT | wxEXPAND, FromDIP(4)); - hsizer_extruder->AddSpacer(FromDIP(4)); + hsizer_extruder->Add(right_extruder->sizer, 1, wxEXPAND, 0); // single - vsizer_printer->Add(hsizer_extruder, 0, wxEXPAND | wxLEFT, 0); + vsizer_printer->Add(hsizer_extruder, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(4)); vsizer_printer->Add(single_extruder->sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(4)); vsizer_printer->AddSpacer(FromDIP(4)); @@ -743,14 +755,20 @@ static struct DynamicFilamentList : DynamicList void apply_on(Choice *c) override { + if (!c) { + return; + } if (items.empty()) update(true); auto cb = dynamic_cast(c->window); + if (!cb) { + return; + } int n = cb->GetSelection(); cb->Clear(); cb->Append(_L("Default")); for (auto i : items) { - cb->Append(i.first, *i.second); + cb->Append(i.first, i.second ? wxNullBitmap : * i.second); } if ((unsigned int)n < cb->GetCount()) cb->SetSelection(n); @@ -974,20 +992,22 @@ ExtruderGroup::ExtruderGroup(wxWindow * parent, int index, wxString const &title hsizer_ams->Add(btn_edit, 0, wxLEFT | wxALIGN_CENTER, FromDIP(2)); hsizer_ams->Add(ams_not_installed_msg, 0, wxALIGN_CENTER); - btn_up = new ScalableButton(this, wxID_ANY, "page_up", "", {-1, FromDIP(14)}); + btn_up = new ScalableButton(this, wxID_ANY, "page_up", "", {FromDIP(14), FromDIP(14)}, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 14); btn_up->SetBackgroundColour(*wxWHITE); btn_up->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this, index](auto &evt) { if (page_cur > 0) --page_cur; update_ams(); }); - btn_down = new ScalableButton(this, wxID_ANY, "page_down", "", {-1, FromDIP(14)}); + btn_up->Hide(); + btn_down = new ScalableButton(this, wxID_ANY, "page_down", "", {FromDIP(14), FromDIP(14)}, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 14); btn_down->SetBackgroundColour(*wxWHITE); btn_down->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this, index](auto &evt) { if (page_cur + 1 < page_num) ++page_cur; update_ams(); }); + btn_down->Hide(); wxBoxSizer *hsizer_diameter = new wxBoxSizer(wxHORIZONTAL); @@ -1162,7 +1182,7 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) return false; } - std::string machine_print_name = obj->printer_type; + std::string machine_print_name = obj->get_show_printer_type(); PresetBundle *preset_bundle = wxGetApp().preset_bundle; std::string target_model_id = preset_bundle->printers.get_selected_preset().get_printer_type(preset_bundle); Preset* machine_preset = get_printer_preset(obj); @@ -1298,7 +1318,7 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) // 1. update printer status //y59 //const Preset &cur_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); - //if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->printer_type) { + //if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->get_show_printer_type()) { std::string cur_preset_name = wxGetApp().get_tab(Preset::TYPE_PRINTER)->get_presets()->get_edited_preset().name; if (preset_bundle && cur_preset_name == wxGetApp().plater()->sidebar().box_list_preset_name) { panel_printer_preset->ShowBadge(true); @@ -1537,7 +1557,7 @@ Sidebar::Sidebar(Plater *parent) // add printer title scrolled_sizer->Add(p->m_panel_printer_title, 0, wxEXPAND | wxALL, 0); - p->m_panel_printer_title->Bind(wxEVT_LEFT_UP, [this] (auto & e) { + p->m_panel_printer_title->Bind(wxEVT_LEFT_DOWN, [this] (auto & e) { if (p->m_panel_printer_content->GetMaxHeight() == 0) p->m_panel_printer_content->SetMaxSize({-1, -1}); else @@ -1576,16 +1596,16 @@ Sidebar::Sidebar(Plater *parent) if (p->combo_printer->switch_to_tab()) p->editing_filament = 0; }); - p->btn_edit_printer = edit_btn; - ScalableBitmap bitmap_printer(p->panel_printer_preset, "printer_placeholder", 48); - p->image_printer = new wxStaticBitmap(p->panel_printer_preset, wxID_ANY, bitmap_printer.bmp(), wxDefaultPosition, PRINTER_THUMBNAIL_SIZE, 0); - p->image_printer->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) { - p->combo_printer->wxEvtHandler::ProcessEvent(evt); - }); - - PlaterPresetComboBox *combo_printer = new PlaterPresetComboBox(p->panel_printer_preset, Preset::TYPE_PRINTER); - combo_printer->SetWindowStyle(combo_printer->GetWindowStyle() & ~wxALIGN_MASK | wxALIGN_CENTER_HORIZONTAL); - combo_printer->SetBorderWidth(0); + p->btn_edit_printer = edit_btn; + ScalableBitmap bitmap_printer(p->panel_printer_preset, "printer_placeholder", 48); + p->image_printer = new wxStaticBitmap(p->panel_printer_preset, wxID_ANY, bitmap_printer.bmp(), wxDefaultPosition, PRINTER_THUMBNAIL_SIZE, 0); + p->image_printer->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) { + p->combo_printer->wxEvtHandler::ProcessEvent(evt); + }); + + PlaterPresetComboBox *combo_printer = new PlaterPresetComboBox(p->panel_printer_preset, Preset::TYPE_PRINTER); + combo_printer->SetWindowStyle(combo_printer->GetWindowStyle() & ~wxALIGN_MASK | wxALIGN_CENTER_HORIZONTAL); + combo_printer->SetBorderWidth(0); p->combo_printer = combo_printer; // y5 @@ -1599,12 +1619,12 @@ Sidebar::Sidebar(Plater *parent) // }); { - auto hovered = std::make_shared(); - for (wxWindow *w : std::initializer_list{p->panel_printer_preset, edit_btn, p->image_printer, combo_printer}) { - w->Bind(wxEVT_ENTER_WINDOW, [w, hovered, edit_btn](wxMouseEvent &evt) { *hovered = w; edit_btn->SetBitmap_("edit"); }); - w->Bind(wxEVT_LEAVE_WINDOW, [w, hovered, edit_btn](wxMouseEvent &evt) { if (*hovered == w) { edit_btn->SetBitmap_("dot"); *hovered = nullptr; } }); - } - } + auto hovered = std::make_shared(); + for (wxWindow *w : std::initializer_list{p->panel_printer_preset, edit_btn, p->image_printer, combo_printer}) { + w->Bind(wxEVT_ENTER_WINDOW, [w, hovered, edit_btn](wxMouseEvent &evt) { *hovered = w; edit_btn->SetBitmap_("edit"); }); + w->Bind(wxEVT_LEAVE_WINDOW, [w, hovered, edit_btn](wxMouseEvent &evt) { if (*hovered == w) { edit_btn->SetBitmap_("dot"); *hovered = nullptr; } }); + } + } // Bed type selection p->panel_printer_bed = new StaticBox(p->m_panel_printer_content); @@ -1668,6 +1688,7 @@ Sidebar::Sidebar(Plater *parent) bed_type_vsizer->AddStretchSpacer(1); p->panel_printer_bed->SetSizer(bed_type_vsizer); + AppConfig *app_config = wxGetApp().app_config; std::string str_bed_type = app_config->get("curr_bed_type"); int bed_type_value = atoi(str_bed_type.c_str()); @@ -1691,7 +1712,7 @@ Sidebar::Sidebar(Plater *parent) project_config.set_key_value("curr_bed_type", new ConfigOptionEnum(bed_type)); // Sync printer information - btn_sync = new Button(p->m_panel_printer_content, _L("Sync printer information"), "printer_sync", 0, 32); + btn_sync = new Button(p->m_panel_printer_content, _L("Sync info"), "printer_sync", 0, 32); //btn_sync->SetFont(Label::Body_8); btn_sync->SetToolTip(_L("Synchronize nozzle information and the number of BOX")); btn_sync->SetCornerRadius(8); @@ -1707,8 +1728,8 @@ Sidebar::Sidebar(Plater *parent) btn_sync->SetBorderColor(btn_sync_bd_col); btn_sync->SetCanFocus(false); btn_sync->SetPaddingSize({FromDIP(6), FromDIP(12)}); - btn_sync->SetMinSize(PRINTER_PANEL_SIZE); - btn_sync->SetMaxSize(PRINTER_PANEL_SIZE); + btn_sync->SetMinSize(BTN_SYNC_SIZE); + btn_sync->SetMaxSize(BTN_SYNC_SIZE); btn_sync->SetVertical(); btn_sync->Bind(wxEVT_UPDATE_UI, &Sidebar::update_sync_ams_btn_enable, this); btn_sync->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { @@ -1747,7 +1768,7 @@ Sidebar::Sidebar(Plater *parent) p->m_panel_filament_title = new StaticBox(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_NONE); p->m_panel_filament_title->SetBackgroundColor(title_bg); p->m_panel_filament_title->SetBackgroundColor2(0xF1F1F1); - p->m_panel_filament_title->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent &e) { + p->m_panel_filament_title->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { if (e.GetPosition().x > (p->m_flushing_volume_btn->IsShown() ? p->m_flushing_volume_btn->GetPosition().x : p->m_bpButton_add_filament->GetPosition().x)) return; @@ -2025,7 +2046,6 @@ Sidebar::Sidebar(Plater *parent) p->m_search_bar->ShowSearchButton(true); p->m_search_bar->ShowCancelButton(true); p->m_search_bar->SetDescriptiveText(_L("Search plate, object and part.")); - p->m_search_bar->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#000000"))); p->m_search_bar->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent&) { this->p->on_search_update(); @@ -2100,7 +2120,6 @@ void Sidebar::on_leave_image_printer_bed(wxMouseEvent &evt) { //} p->big_bed_image_popup->on_hide(); } - void Sidebar::on_change_color_mode(bool is_dark) { const ModelObjectPtrs &mos = wxGetApp().model().objects; for (int i = 0; i < mos.size(); i++) { @@ -2432,8 +2451,9 @@ void Sidebar::update_presets(Preset::Type preset_type) } Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); - - bool isQDT = printer_preset.is_qdt_vendor_preset(wxGetApp().preset_bundle); + + //wxGetApp().mainframe->update_calibration_button_status(); + //B y58 wxGetApp().mainframe->show_calibration_button(false); @@ -2442,9 +2462,10 @@ void Sidebar::update_presets(Preset::Type preset_type) } else wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = false; + // Update dual extrudes auto extruder_variants = printer_preset.config.option("extruder_variant_list"); - + bool isQDT = printer_preset.is_qdt_vendor_preset(wxGetApp().preset_bundle); bool is_dual_extruder = extruder_variants->size() == 2; //y65 @@ -2644,7 +2665,6 @@ bool Sidebar::reset_bed_type_combox_choices(bool is_sidebar_init) if (m_cur_image_bed_type != pm->id) { m_cur_image_bed_type = pm->id; } - for (auto item : bed_type_def->enum_labels) { index++; bool find = std::find(pm->not_support_bed_types.begin(), pm->not_support_bed_types.end(), item) != pm->not_support_bed_types.end(); @@ -2728,8 +2748,7 @@ void Sidebar::msw_rescale() p->single_extruder->Rescale(); p->btn_sync_printer->SetPaddingSize({FromDIP(6), FromDIP(12)}); - p->btn_sync_printer->SetMinSize(PRINTER_PANEL_SIZE); - p->btn_sync_printer->SetMaxSize(PRINTER_PANEL_SIZE); + p->btn_sync_printer->SetMinSize(BTN_SYNC_SIZE); p->panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE); p->btn_sync_printer->Rescale(); #if 0 @@ -3074,15 +3093,16 @@ std::map Sidebar::build_filament_ams_list(MachineObject tray_config.set_key_value("filament_type", new ConfigOptionStrings{tray.type}); tray_config.set_key_value("tray_name", new ConfigOptionStrings{ name }); tray_config.set_key_value("filament_colour", new ConfigOptionStrings{into_u8(wxColour("#" + tray.color).GetAsString(wxC2S_HTML_SYNTAX))}); + tray_config.set_key_value("filament_multi_colour", new ConfigOptionStrings{}); + tray_config.set_key_value("filament_colour_type", new ConfigOptionStrings{std::to_string(tray.ctype)}); tray_config.set_key_value("filament_exist", new ConfigOptionBools{tray.is_exists}); - tray_config.set_key_value("filament_multi_colors", new ConfigOptionStrings{}); std::optional info; if (wxGetApp().preset_bundle) { info = wxGetApp().preset_bundle->get_filament_by_filament_id(tray.setting_id); } tray_config.set_key_value("filament_is_support", new ConfigOptionBools{ info.has_value() ? info->is_support : false}); for (int i = 0; i < tray.cols.size(); ++i) { - tray_config.opt("filament_multi_colors")->values.push_back(into_u8(wxColour("#" + tray.cols[i]).GetAsString(wxC2S_HTML_SYNTAX))); + tray_config.opt("filament_multi_colour")->values.push_back(into_u8(wxColour("#" + tray.cols[i]).GetAsString(wxC2S_HTML_SYNTAX))); } return tray_config; }; @@ -3131,7 +3151,7 @@ bool Sidebar::need_auto_sync_extruder_list_after_connect_priner(const MachineObj if(!obj) return false; - std::string machine_print_name = obj->printer_type; + std::string machine_print_name = obj->get_show_printer_type(); PresetBundle *preset_bundle = wxGetApp().preset_bundle; std::string target_model_id = preset_bundle->printers.get_selected_preset().get_printer_type(preset_bundle); if (machine_print_name != target_model_id) { @@ -3349,7 +3369,7 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) }; { // badge ams filament clear_combos_filament_badge(); - { + if (sync_result.direct_sync) { for (auto &c : p->combos_filament) { badge_combox_filament(c); } @@ -3432,6 +3452,7 @@ std::map Sidebar::build_filament_box_list(std::vector Sidebar::build_filament_box_list(std::vector("filament_multi_colors")->values.push_back(into_u8(wxColour(color[i]).GetAsString(wxC2S_HTML_SYNTAX))); + //y68 + tray_config.set_key_value("filament_colour_type", new ConfigOptionStrings{"1"}); + + tray_config.set_key_value("filament_exist", new ConfigOptionBools{ true }); //default + tray_config.set_key_value("filament_multi_colour", new ConfigOptionStrings{}); + tray_config.opt("filament_multi_colour")->values.push_back(into_u8(wxColour(color[i]).GetAsString(wxC2S_HTML_SYNTAX))); filament_ams_list.emplace('A' + i, std::move(tray_config)); } @@ -3467,9 +3491,11 @@ std::map Sidebar::build_filament_box_list(std::vector("filament_multi_colors")->values.push_back(into_u8(wxColour(color.back()).GetAsString(wxC2S_HTML_SYNTAX))); + tray_config.set_key_value("filament_multi_colour", new ConfigOptionStrings{}); + tray_config.opt("filament_multi_colour")->values.push_back(into_u8(wxColour(color.back()).GetAsString(wxC2S_HTML_SYNTAX))); filament_ams_list.emplace('A' + count + 1, std::move(tray_config)); } @@ -4011,9 +4037,7 @@ void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int const auto& full_config = wxGetApp().preset_bundle->full_config(); auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment; size_t extruder_nums = preset_bundle->get_printer_extruder_count(); - bool is_multi_extruder = extruder_nums > 1; - NozzleVolumeType volume_type=NozzleVolumeType(full_config.option("nozzle_volume_type")->values[extruder_id]); - + int nozzle_flush_dataset = full_config.option("nozzle_flush_dataset")->values[extruder_id]; std::vector init_matrix = get_flush_volumes_matrix((project_config.option("flush_volumes_matrix"))->values, extruder_id, extruder_nums); const std::vector& min_flush_volumes = get_min_flush_volumes(full_config, extruder_id); @@ -4050,7 +4074,7 @@ void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int // from to modify int from_idx = i; if (from_idx != modify_id) { - Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], m_max_flush_volume, is_multi_extruder,volume_type); + Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], m_max_flush_volume, nozzle_flush_dataset); int flushing_volume = 0; bool is_from_support = is_support_filament(from_idx); bool is_to_support = is_support_filament(modify_id); @@ -4075,7 +4099,7 @@ void Sidebar::auto_calc_flushing_volumes_internal(const int modify_id, const int // modify to to int to_idx = i; if (to_idx != modify_id) { - Slic3r::FlushVolCalculator calculator(min_flush_volumes[modify_id], m_max_flush_volume, is_multi_extruder, volume_type); + Slic3r::FlushVolCalculator calculator(min_flush_volumes[modify_id], m_max_flush_volume, nozzle_flush_dataset); bool is_from_support = is_support_filament(modify_id); bool is_to_support = is_support_filament(to_idx); int flushing_volume = 0; @@ -4331,6 +4355,7 @@ public: bool show_render_statistic_dialog{ false }; bool show_wireframe{ false }; bool wireframe_enabled{ true }; + bool show_text_cs{false}; bool show_non_manifold_edges{false}; static const std::regex pattern_bundle; static const std::regex pattern_3mf; @@ -4813,7 +4838,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , m_ui_jobs(this) , m_job_prepare_state(Job::JobPrepareState::PREPARE_STATE_DEFAULT) , delayed_scene_refresh(false) - , collapse_toolbar(GLToolbar::Normal, "Collapse") + , collapse_toolbar(GLToolbar::EType::Normal, "Collapse") //QDS :partplatelist construction , partplate_list(this->q, &model) { @@ -4822,7 +4847,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) m_aui_mgr.SetDockSizeConstraint(1, 1); // m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0); // m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2); - m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 0); + m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, wxGetApp().app_config->get_bool("enable_sidebar_floatable") ? 8 : 0); m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_GRADIENT_TYPE, wxAUI_GRADIENT_NONE); this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -4898,19 +4923,17 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) }); update(); - // Orca: Make sidebar dockable - auto look = wxGetApp().app_config->get_bool("enable_sidebar_resizable"); m_aui_mgr.AddPane(sidebar, wxAuiPaneInfo() .Name("sidebar") .Left() .CloseButton(false) .TopDockable(false) .BottomDockable(false) - //.Floatable(true) + .Floatable(wxGetApp().app_config->get_bool("enable_sidebar_floatable")) .Resizable(wxGetApp().app_config->get_bool("enable_sidebar_resizable")) - .MinSize(wxSize(41 * wxGetApp().em_unit(), -1)) - .BestSize(wxSize(42 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); + .MinSize(wxSize(15 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit())) + .BestSize(wxSize(42 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); auto *panel_sizer = new wxBoxSizer(wxHORIZONTAL); panel_sizer->Add(view3D, 1, wxEXPAND | wxALL, 0); @@ -5331,10 +5354,8 @@ void Plater::priv::update(unsigned int flags) // QDS assemble view this->assemble_view->reload_scene(false, flags); - if (current_panel && q->is_preview_shown()) { - q->force_update_all_plate_thumbnails(); - //update_fff_scene_only_shells(true); - } + // todo: better to mark thumbnail dirty here + q->mark_plate_toolbar_image_dirty(); if (force_background_processing_restart) this->restart_background_process(update_status); @@ -5386,6 +5407,34 @@ const VendorProfile::PrinterModel *Plater::get_curr_printer_model() return nullptr; } +std::map Plater::get_bed_texture_maps() +{ + auto pm = get_curr_printer_model(); + if (pm) { + std::map maps; + if (pm->bottom_texture_end_name.size() > 0) { + maps["bottom_texture_end_name"] = pm->bottom_texture_end_name; + } + if (pm->bottom_texture_rect.size() > 0) { + maps["bottom_texture_rect"] = pm->bottom_texture_rect; + } + if (pm->middle_texture_rect.size() > 0) { + maps["middle_texture_rect"] = pm->middle_texture_rect; + } + return maps; + } + return {}; +} + +int Plater::get_right_icon_offset_bed() +{ + auto pm = get_curr_printer_model(); + if (pm && pm->right_icon_offset_bed.size() > 0) { + return std::stoi(pm->right_icon_offset_bed); + } + return 0; +} + wxColour Plater::get_next_color_for_filament() { static int curr_color_filamenet = 0; @@ -5508,7 +5557,14 @@ void Plater::priv::collapse_sidebar(bool collapse) // Now update the tooltip in the toolbar. std::string new_tooltip = collapse ? _u8L("Expand sidebar") : _u8L("Collapse sidebar"); + new_tooltip += " [Shift+Tab]"; + #ifdef __APPLE__ + new_tooltip += "\n" + _u8L("Reset Window Layout") + "[command+W]"; +#else + new_tooltip += "\n" + _u8L("Reset Window Layout") + "[Ctrl+W]"; +#endif + int id = collapse_toolbar.get_item_id("collapse_sidebar"); collapse_toolbar.set_tooltip(id, new_tooltip); @@ -5889,33 +5945,33 @@ std::vector Plater::priv::load_files(const std::vector& input_ show_info(q, _L("The 3mf is not from QIDI Tech, load geometry data only."), _L("Load 3mf")); } //w18 - ////else if (load_config && (file_version.maj() != app_version.maj())) { - //// // version mismatch, only load geometries - //// load_config = false; - //// if (!load_model) { - //// // only load config case, return directly - //// show_info(q, _L("The Config can not be loaded."), _L("Load 3mf")); - //// q->skip_thumbnail_invalid = false; - //// return empty_result; - //// } - //// load_old_project = true; - //// // select view to 3D - //// q->select_view_3D("3D"); - //// // select plate 0 as default - //// q->select_plate(0); - //// if (load_type != LoadType::LoadGeometry) { - //// if (en_3mf_file_type == En3mfType::From_QDS) - //// show_info(q, _L("Due to the lower version of QIDI Studio, this 3mf file cannot be fully loaded. Please update QIDI Studio to the latest version"), _L("Load 3mf")); - //// else - //// show_info(q, _L("The 3mf is not from QIDI Tech, load geometry data only."), _L("Load 3mf")); - //// } - //// for (ModelObject *model_object : model.objects) { - //// model_object->config.reset(); - //// // Is there any modifier or advanced config data? - //// for (ModelVolume *model_volume : model_object->volumes) model_volume->config.reset(); - //// } + else if (load_config && (file_version.maj() != app_version.maj())) { + // version mismatch, only load geometries + load_config = false; + if (!load_model) { + // only load config case, return directly + show_info(q, _L("The Config can not be loaded."), _L("Load 3mf")); + q->skip_thumbnail_invalid = false; + return empty_result; + } + load_old_project = true; + // select view to 3D + q->select_view_3D("3D"); + // select plate 0 as default + q->select_plate(0); + if (load_type != LoadType::LoadGeometry) { + if (en_3mf_file_type == En3mfType::From_QDS) + show_info(q, _L("Due to the lower version of QIDI Studio, this 3mf file cannot be fully loaded. Please update QIDI Studio to the latest version"), _L("Load 3mf")); + else + show_info(q, _L("The 3mf is not from QIDI Tech, load geometry data only."), _L("Load 3mf")); + } + for (ModelObject *model_object : model.objects) { + model_object->config.reset(); + // Is there any modifier or advanced config data? + for (ModelVolume *model_volume : model_object->volumes) model_volume->config.reset(); + } + } //y54 - // // } // // else if (load_config && (file_version > app_version)) { // Semver cloud_ver; // if (wxGetApp().app_config->has("app", "cloud_version")) { @@ -5957,10 +6013,13 @@ std::vector Plater::priv::load_files(const std::vector& input_ //} else if (load_config && config_loaded.empty()) { load_config = false; - if (file_version.maj() == 0 && file_version.min() == 0 && file_version.patch() == 0) { - show_info(q, _L("The 3mf is not from QIDI Tech, load geometry data only."), _L("Load 3mf")); - } else { - show_info(q, _L("The 3mf is generated by old QIDI Studio, load geometry data only."), _L("Load 3mf")); + if (wxGetApp().app_config->get_bool("skip_non_qidi_3mf_warning") != true) { + TipsDialog dlg(q, _L("Load 3mf"), + file_version.maj() == 0 && file_version.min() == 0 && file_version.patch() == 0 + ? _L("The 3mf is not from QIDI Tech, load geometry data only.") + : _L("The 3mf is generated by old QIDI Studio, load geometry data only."), + "skip_non_qidi_3mf_warning", wxOK); + dlg.ShowModal(); } } else if (!load_config) { @@ -6081,6 +6140,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ if (!config.empty()) { Preset::normalize(config); PresetBundle *preset_bundle = wxGetApp().preset_bundle; + { // QDS: modify the prime tower params for old version file Semver old_version3(2, 0, 0); @@ -6283,11 +6343,42 @@ std::vector Plater::priv::load_files(const std::vector& input_ *wipe_tower_y = *file_wipe_tower_y; ConfigOptionStrings* filament_color = proj_cfg.opt("filament_colour"); - ConfigOptionInts* filament_map = proj_cfg.opt("filament_map", true); - if (filament_color && filament_color->size() != filament_map->size()) { - filament_map->values.resize(filament_color->size(), 1); + if (filament_color) { + size_t filament_count = filament_color->size(); + + // Sync filament map + ConfigOptionInts* filament_map = proj_cfg.opt("filament_map", true); + if (filament_map->size() != filament_count) { + filament_map->values.resize(filament_count, 1); + } + + // Sync filament multi colour + ConfigOptionStrings* filament_multi_color = proj_cfg.opt("filament_multi_colour", true); + if (filament_multi_color->size() != filament_count) { + filament_multi_color->values.resize(filament_count); + } + // If there is no multi-color data or color is not match, use single color as default value + for (size_t i = 0; i < filament_count; i++) { + std::vector colors = Slic3r::split_string(filament_multi_color->values[i], ' '); + if (i >= filament_multi_color->values.size() || colors.empty() || colors[0] != filament_color->values[i] ) { + filament_multi_color->values[i] = filament_color->values[i]; + } + } + // Sync filament colour type + ConfigOptionStrings* filament_color_type = proj_cfg.opt("filament_colour_type", true); + if (filament_color_type && filament_color_type->size() != filament_count) { + filament_color_type->values.resize(filament_count); + + for (size_t i = 0; i < filament_count; i++) { + if (i >= filament_color_type->values.size() || filament_color_type->values[i].empty()) { + filament_color_type->values[i] = "1"; + } + } + } } } + // Update filament combobox after loading config + wxGetApp().plater()->sidebar().update_presets(Preset::TYPE_FILAMENT); } } if (!silence) wxGetApp().app_config->update_config_dir(path.parent_path().string()); @@ -6307,7 +6398,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ makerlab_name = in_out.ml_name; makerlab_id = in_out.ml_id; - if (!boost::iends_with(path.string(), ".obj")) { return; } + if (!boost::iends_with(path.string(), ".obj")) { return; } const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); ObjColorDialog color_dlg(nullptr, in_out, extruder_colours); if (color_dlg.ShowModal() != wxID_OK) { @@ -7200,13 +7291,6 @@ void Plater::priv::delete_all_objects_from_model() view3D->get_canvas3d()->reset_sequential_print_clearance(); - if (assemble_view) { - const auto& p_camera = assemble_view->get_override_camera(); - if (p_camera) { - p_camera->requires_zoom_to_volumes = true; - } - } - m_ui_jobs.cancel_all(); // Stop and reset the Print content. @@ -7246,6 +7330,13 @@ void Plater::priv::reset(bool apply_presets_change) view3D->get_canvas3d()->reset_sequential_print_clearance(); + if (assemble_view) { + const auto& p_camera = assemble_view->get_override_camera(); + if (p_camera) { + p_camera->requires_zoom_to_volumes = true; + } + } + m_ui_jobs.cancel_all(); //QDS: clear the partplate list's object before object cleared @@ -7679,7 +7770,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool if (background_process.finished() && cur_plate && cur_plate->is_slice_result_valid()) { //ready_to_slice = false; - this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, false, true); + this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, false); } else if (!background_process.empty() && !background_process.running()) /* Do not update buttons if background process is running @@ -7689,7 +7780,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool { if (cur_plate->can_slice()) { //ready_to_slice = true; - this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, true, true); + this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, true); process_completed_with_error = -1; } else { @@ -7970,6 +8061,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const else if (old_volume->source.is_converted_from_meters) new_volume->convert_from_meters(); new_volume->supported_facets.assign(old_volume->supported_facets); + new_volume->fuzzy_skin_facets.assign(old_volume->fuzzy_skin_facets); new_volume->seam_facets.assign(old_volume->seam_facets); new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets); std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back()); @@ -8602,7 +8694,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) preview->set_as_dirty(); }; - // Add sidebar and toolbar collapse logic if (panel == view3D || panel == preview) { this->enable_sidebar(!q->only_gcode_mode()); @@ -8616,9 +8707,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) preview->get_canvas3d()->enable_select_plate_toolbar(true); } } - else { - preview->get_canvas3d()->clear_select_plate_toolbar_render_flag(); - } if (current_panel == panel) { @@ -8883,7 +8971,6 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) } auto idx = combo->get_filament_idx(); - bool flag = is_support_filament(idx); //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, //! but the OSX version derived from wxOwnerDrawnCombo. @@ -8930,23 +9017,23 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) else physical_printers.unselect_printer(); - if (marker == PresetComboBox::LABEL_ITEM_PRINTER_MODELS) { - auto preset = wxGetApp().preset_bundle->get_similar_printer_preset(preset_name, {}); - if (preset == nullptr) { - MessageDialog dlg(this->sidebar, _L(""), _L("")); - dlg.ShowModal(); - } - preset->is_visible = true; // force visible - preset_name = preset->name; + if (marker == PresetComboBox::LABEL_ITEM_PRINTER_MODELS) { + auto preset = wxGetApp().preset_bundle->get_similar_printer_preset(preset_name, {}); + if (preset == nullptr) { + MessageDialog dlg(this->sidebar, _L(""), _L("")); + dlg.ShowModal(); } - std::string old_preset_name = wxGetApp().preset_bundle->printers.get_edited_preset().name; - - update_objects_position_when_select_preset([this, &preset_type, &preset_name]() { - wxWindowUpdateLocker noUpdates2(sidebar->filament_panel()); - wxGetApp().get_tab(preset_type)->select_preset(preset_name); - // update plater with new config - q->on_config_change(wxGetApp().preset_bundle->full_config()); - }); + preset->is_visible = true; // force visible + preset_name = preset->name; + } + std::string old_preset_name = wxGetApp().preset_bundle->printers.get_edited_preset().name; + + update_objects_position_when_select_preset([this, &preset_type, &preset_name]() { + wxWindowUpdateLocker noUpdates2(sidebar->filament_panel()); + wxGetApp().get_tab(preset_type)->select_preset(preset_name); + // update plater with new config + q->on_config_change(wxGetApp().preset_bundle->full_config()); + }); if (old_preset_name != preset_name && wxGetApp().app_config->get("auto_calculate_flush") == "all") { @@ -8959,7 +9046,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) if (obj && obj->is_multi_extruders()) { PresetBundle *preset_bundle = wxGetApp().preset_bundle; Preset& cur_preset = preset_bundle->printers.get_edited_preset(); - if (cur_preset.get_printer_type(preset_bundle) == obj->printer_type) { + if (cur_preset.get_printer_type(preset_bundle) == obj->get_show_printer_type()) { double preset_nozzle_diameter = cur_preset.config.option("nozzle_diameter")->values[0]; bool same_nozzle_diameter = true; for (const Extder &extruder : obj->m_extder_data.extders) { @@ -9541,46 +9628,46 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) int extruders_size = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_filaments().size(); std::string box_ip = wxGetApp().plater()->sidebar().box_list_printer_ip; - //y61 - bool has_diff = false; - if (!box_ip.empty()) { -#if QDT_RELEASE_TO_PUBLIC - QIDINetwork qidi; - wxString msg = ""; - GUI::Box_info filament_info; - filament_info = qidi.get_box_info(msg, box_ip); - GUI::Box_info cur_box_info; - cur_box_info = q->get_cur_box_info(); +// //y61 +// bool has_diff = false; +// if (!box_ip.empty()) { +// #if QDT_RELEASE_TO_PUBLIC +// QIDINetwork qidi; +// wxString msg = ""; +// GUI::Box_info filament_info; +// filament_info = qidi.get_box_info(msg, box_ip); +// GUI::Box_info cur_box_info; +// cur_box_info = q->get_cur_box_info(); - if (filament_info.filament_index != cur_box_info.filament_index - || filament_info.filament_vendor != cur_box_info.filament_vendor - || filament_info.filament_color_index != cur_box_info.filament_color_index - || filament_info.box_count != cur_box_info.box_count - || filament_info.auto_reload_detect != cur_box_info.auto_reload_detect) { - has_diff = true; - } -#endif - } +// if (filament_info.filament_index != cur_box_info.filament_index +// || filament_info.filament_vendor != cur_box_info.filament_vendor +// || filament_info.filament_color_index != cur_box_info.filament_color_index +// || filament_info.box_count != cur_box_info.box_count +// || filament_info.auto_reload_detect != cur_box_info.auto_reload_detect) { +// has_diff = true; +// } +// #endif +// } -//y65 +//y65 y68 bool is_can_change_color = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->get_is_can_change_color(); if(extruders_size > 1 && box_ip.empty() && !is_can_change_color){ wxGetApp().plater()->sidebar().sync_box_list(); } - //y61 - else if(has_diff){ - MessageDialog dlg(nullptr, _L("The filament information in the BOX has changed. Please resynchronize it."), _L("BOX message has change"), wxYES); - if (dlg.ShowModal() == wxID_YES) { - wxGetApp().plater()->sidebar().sync_box_list(); - } - }else{ - //y40 - SelectMachineDialog* dlg = new SelectMachineDialog(q); - //y52 - dlg->prepare(partplate_list.get_curr_plate_index()); - dlg->ShowModal(); - } + // //y61 + // else if(has_diff){ + // MessageDialog dlg(nullptr, _L("The filament information in the BOX has changed. Please resynchronize it."), _L("BOX message has change"), wxYES); + // if (dlg.ShowModal() == wxID_YES) { + // wxGetApp().plater()->sidebar().sync_box_list(); + // } + // } + + //y40 + SelectMachineDialog* dlg = new SelectMachineDialog(q); + //y52 + dlg->prepare(partplate_list.get_curr_plate_index()); + dlg->ShowModal(); //if (!m_select_machine_dlg) m_select_machine_dlg = new SelectMachineDialog(q); //m_select_machine_dlg->set_print_type(PrintFromType::FROM_NORMAL); @@ -9589,11 +9676,12 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) //record_start_print_preset("print_plate"); } +//y void Plater::priv::resetUploadCount() { UploadCount = 0; m_sending_interval = 0; -}; +} void Plater::priv::on_action_send_to_multi_machine(SimpleEvent&) { @@ -10078,6 +10166,8 @@ void Plater::priv::on_right_click(RBtnEvent& evt) if (model_volume != nullptr) { if (model_volume->is_svg()) { menu = menus.svg_part_menu(); + } else if (model_volume->is_text()) { + menu = menus.text_part_menu(); } else if (model_volume->is_cut_connector()) { menu = menus.cut_connector_menu(); } else { @@ -10312,7 +10402,7 @@ void Plater::priv::set_project_filename(const wxString& filename) full_path.replace_extension(""); m_project_folder = full_path.parent_path(); - BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << __LINE__ << " project folder is:" << m_project_folder.string(); + BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << __LINE__ << " project folder is:" << PathSanitizer::sanitize(m_project_folder); //QDS wxString project_name = from_u8(full_path.filename().string()); @@ -10531,6 +10621,7 @@ void Plater::set_print_job_plate_idx(int plate_idx) } } + int Plater::get_send_calibration_finished_event() { return EVT_SEND_CALIBRATION_FINISHED; @@ -10609,7 +10700,7 @@ bool Plater::priv::check_ams_status_impl(bool is_slice_all) return true; } PresetBundle *preset_bundle = wxGetApp().preset_bundle; - if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->printer_type) { + if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->get_show_printer_type()) { bool is_same_as_printer = true; auto nozzle_volumes_values = preset_bundle->project_config.option("nozzle_volume_type")->values; assert(obj->m_extder_data.extders.size() == 2 && nozzle_volumes_values.size() == 2); @@ -10699,7 +10790,7 @@ bool Plater::priv::get_machine_sync_status() return false; PresetBundle *preset_bundle = wxGetApp().preset_bundle; - return preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->printer_type; + return preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->get_show_printer_type(); } Camera& Plater::priv::get_current_camera() @@ -10735,19 +10826,21 @@ bool Plater::priv::init_collapse_toolbar() if (!collapse_toolbar.init(background_data)) return false; - collapse_toolbar.set_layout_type(GLToolbar::Layout::Vertical); - collapse_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right); - collapse_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); + collapse_toolbar.set_layout_type(ToolbarLayout::EType::Vertical); + collapse_toolbar.set_horizontal_orientation(ToolbarLayout::HO_Right); + collapse_toolbar.set_vertical_orientation(ToolbarLayout::VO_Top); collapse_toolbar.set_border(0.0f); collapse_toolbar.set_separator_size(5); collapse_toolbar.set_gap_size(2); collapse_toolbar.del_all_item(); + collapse_toolbar.set_position_mode(ToolbarLayout::EPositionMode::TopLeft); GLToolbarItem::Data item; item.name = "collapse_sidebar"; - // set collapse svg name - item.icon_filename = "collapse.svg"; + item.icon_filename_callback = [](bool is_dark_mode)->std::string { + return "collapse.svg"; + }; item.sprite_id = 0; item.left.action_callback = []() { wxGetApp().plater()->collapse_sidebar(!wxGetApp().plater()->is_sidebar_collapsed()); @@ -10986,20 +11079,18 @@ bool Plater::priv::can_delete_all() const bool Plater::priv::can_edit_text() const { - const Selection &selection = view3D->get_canvas3d()->get_selection(); - if (selection.is_single_full_instance()) - return true; - - if (selection.is_single_volume()) { - const GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); - int out_object_idx = gl_volume->object_idx(); - ModelObject * model_object = selection.get_model()->objects[out_object_idx]; - int out_volume_idx = gl_volume->volume_idx(); - ModelVolume * model_volume = model_object->volumes[out_volume_idx]; - if (model_volume) - return !model_volume->get_text_info().m_text.empty(); - } - return false; + if (wxGetApp().plater() == nullptr) + return false; + const Selection &selection = wxGetApp().plater()->get_selection(); + if (selection.volumes_count() != 1) + return false; + const GLVolume *gl_volume = selection.get_first_volume(); + if (gl_volume == nullptr) + return false; + const ModelVolume *mv = get_model_volume(*gl_volume, selection.get_model()->objects); + if (mv == nullptr) + return false; + return mv->is_text(); } bool Plater::priv::can_add_plate() const @@ -11276,7 +11367,8 @@ void Plater::priv::undo() auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); // QDS: undo-redo until modify record while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current)); - if (it_current == snapshots.begin()) return; + if (it_current == snapshots.begin()) + return; if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { if (it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::GizmoAction && it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::EnteringGizmo && @@ -11833,10 +11925,7 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) } float machine_nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; - std::string printer_type = obj->printer_type; - // handle p1p with upgraded kit - if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) - printer_type = "C12"; + std::string printer_type = obj->get_show_printer_type(); // can not find the preset for connected printer, return false Preset* machine_preset = get_printer_preset(obj); @@ -11894,7 +11983,7 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) int Plater::load_project(wxString const &filename2, wxString const& originfile) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "filename is: " << filename2 << "and originfile is: " << originfile; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "filename is: " << PathSanitizer::sanitize(filename2.mb_str()) << "and originfile is: " << PathSanitizer::sanitize(originfile.mb_str()); auto filename = filename2; auto check = [&filename, this] (bool yes_or_no) { if (!yes_or_no && !wxGetApp().check_and_save_current_preset_changes(_L("Load project"), @@ -12037,7 +12126,12 @@ int Plater::save_project(bool saveAs) return wxID_CANCEL; //QDS export 3mf without gcode - if (export_3mf(into_path(filename), SaveStrategy::SplitModel | SaveStrategy::ShareMesh | SaveStrategy::FullPathSources) < 0) { + auto save_strategy = SaveStrategy::SplitModel | SaveStrategy::ShareMesh; + bool full_pathnames = wxGetApp().app_config->get_bool("export_sources_full_pathnames"); + if (full_pathnames) { + save_strategy = save_strategy | SaveStrategy::FullPathSources; + } + if (export_3mf(into_path(filename), save_strategy) < 0) { MessageDialog(this, _L("Failed to save the project.\nPlease check whether the folder exists online or if other programs open the project file or if there is enough disk space."), _L("Save project"), wxOK | wxICON_WARNING).ShowModal(); return wxID_CANCEL; @@ -12424,6 +12518,8 @@ std::string Plater::double_to_str(const double value) void Plater::calib_pa(const Calib_Params ¶ms) { + model().calib_pa_pattern.reset(nullptr); + const auto calib_pa_name = wxString::Format(L"Pressure Advance Test"); if (new_project(false, true, calib_pa_name) == wxID_CANCEL) return; @@ -12674,6 +12770,14 @@ void Plater::_calib_pa_pattern(const Calib_Params ¶ms) // start with pattern centered on plate center_selection(); const Vec3d plate_center = get_partplate_list().get_curr_plate()->get_center_origin(); + + if ((plate_center.x() - (pa_pattern.print_size_x() / 2) < plate_origin.x()) || + (plate_center.y() - (pa_pattern.print_size_y() / 2) - pa_pattern.handle_spacing() < plate_origin.y())) { + MessageDialog dlg(this, _L("The current settings produce a model that is too large. Please narrow the range or increase the step size. (Model size is proportional to (End - Start) / Step size.)"), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); + return; + } + giz_obj_manip.on_change("position", 0, plate_center.x() - (pa_pattern.print_size_x() / 2)); giz_obj_manip.on_change("position", 1, plate_center.y() - (pa_pattern.print_size_y() / 2) - pa_pattern.handle_spacing()); @@ -12908,6 +13012,9 @@ void Plater::_calib_pa_tower(const Calib_Params ¶ms) if (new_height < obj_bb.size().z()) { std::array plane_pts = get_cut_plane(obj_bb, new_height); cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); + } else { + MessageDialog dlg(this, _L("The current settings produce a model that is too large. Please narrow the range or increase the step size. (Model size is proportional to (End - Start) / Step size.)"), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); } _calib_pa_select_added_objects();*/ @@ -13098,6 +13205,8 @@ void Plater::calib_flowrate(int pass,double input_value) void Plater::calib_temp(const Calib_Params ¶ms) { + model().calib_pa_pattern.reset(nullptr); + try { json js; js["cali_type"] = "third_cali_temp"; @@ -13159,7 +13268,10 @@ void Plater::calib_temp(const Calib_Params ¶ms) void Plater::calib_max_vol_speed(const Calib_Params ¶ms) { //w29 - /*try { + /* + model().calib_pa_pattern.reset(nullptr); + + try { json js; js["cali_type"] = "third_cali_max_flowrate"; std::string filament_id = wxGetApp().preset_bundle->filaments.get_edited_preset().filament_id; @@ -13200,6 +13312,7 @@ void Plater::calib_max_vol_speed(const Calib_Params ¶ms) filament_config->set_key_value("slow_down_layer_time", new ConfigOptionInts{0}); print_config->set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable{false}); + print_config->set_key_value("enable_height_slowdown", new ConfigOptionBoolsNullable{ false }); print_config->set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); print_config->set_key_value("wall_loops", new ConfigOptionInt(1)); print_config->set_key_value("top_shell_layers", new ConfigOptionInt(0)); @@ -13227,6 +13340,9 @@ void Plater::calib_max_vol_speed(const Calib_Params ¶ms) if (height < obj_bb.size().z()) { std::array plane_pts = get_cut_plane(obj_bb, height); cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); + } else { + MessageDialog dlg(this, _L("The current settings produce a model that is too large. Please narrow the range or increase the step size. (Model size is proportional to (End - Start) / Step size.)"), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); } auto new_params = params; @@ -13325,6 +13441,8 @@ void Plater::calib_max_vol_speed(const Calib_Params ¶ms) void Plater::calib_retraction(const Calib_Params ¶ms) { + model().calib_pa_pattern.reset(nullptr); + try { json js; js["cali_type"] = "third_cali_retraction"; @@ -13368,6 +13486,9 @@ void Plater::calib_retraction(const Calib_Params ¶ms) if (height < obj_bb.size().z()) { std::array plane_pts = get_cut_plane(obj_bb, height); cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); + } else { + MessageDialog dlg(this, _L("The current settings produce a model that is too large. Please narrow the range or increase the step size. (Model size is proportional to (End - Start) / Step size.)"), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); } p->background_process.fff_print()->set_calib_params(params); @@ -13375,6 +13496,8 @@ void Plater::calib_retraction(const Calib_Params ¶ms) void Plater::calib_VFA(const Calib_Params ¶ms) { + model().calib_pa_pattern.reset(nullptr); + try { json js; js["cali_type"] = "third_cali_VFA"; @@ -13397,6 +13520,7 @@ void Plater::calib_VFA(const Calib_Params ¶ms) filament_config->set_key_value("slow_down_layer_time", new ConfigOptionInts{0}); filament_config->set_key_value("filament_max_volumetric_speed", new ConfigOptionFloatsNullable{200}); print_config->set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable{false}); + print_config->set_key_value("enable_height_slowdown", new ConfigOptionBoolsNullable{ false }); print_config->set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); print_config->set_key_value("wall_loops", new ConfigOptionInt(1)); print_config->set_key_value("top_shell_layers", new ConfigOptionInt(0)); @@ -13419,6 +13543,9 @@ void Plater::calib_VFA(const Calib_Params ¶ms) if (height < obj_bb.size().z()) { std::array plane_pts = get_cut_plane(obj_bb, height); cut(0, 0, plane_pts, ModelObjectCutAttribute::KeepLower); + } else { + MessageDialog dlg(this, _L("The current settings produce a model that is too large. Please narrow the range or increase the step size. (Model size is proportional to (End - Start) / Step size.)"), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); } p->background_process.fff_print()->set_calib_params(params); @@ -13506,6 +13633,8 @@ void Plater::load_gcode(const wxString& filename) current_print.apply(this->model(), wxGetApp().preset_bundle->full_config()); + current_print.apply_config_for_render(processor.export_config_for_render()); + //QDS: add cost info when drag in gcode auto& ps = current_result->print_statistics; double total_cost = 0.0; @@ -13613,8 +13742,6 @@ void Plater::force_update_all_plate_thumbnails() invalid_all_plate_thumbnails(); update_all_plate_thumbnails(true); } - get_preview_canvas3D()->clear_select_plate_toolbar_render_flag(); - get_preview_canvas3D()->update_plate_thumbnails(); } // QDS: backup @@ -14007,11 +14134,11 @@ bool Plater::load_svg(const wxArrayString &filenames, bool from_toolbar_or_file_ if (filenames.size() == 1) { const wxString &filename = filenames[0]; if (boost::iends_with(filenames[0].ToStdString(), ".svg")) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << filename; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << PathSanitizer::sanitize(filename.mb_str()); emboss_svg(filename, from_toolbar_or_file_menu); return true; } else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << ",fail:" << filename; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << ",fail:" << PathSanitizer::sanitize(filename.mb_str()); } } else { @@ -15229,8 +15356,7 @@ Preset *get_printer_preset(MachineObject *obj) if (printer_nozzle_opt) printer_nozzle_vals = dynamic_cast(printer_nozzle_opt); std::string model_id = printer_it->get_current_printer_type(preset_bundle); - std::string printer_type = obj->printer_type; - if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) printer_type = "C12"; + std::string printer_type = obj->get_show_printer_type(); if (model_id.compare(printer_type) == 0 && printer_nozzle_vals && abs(printer_nozzle_vals->get_at(0) - machine_nozzle_diameter) < 1e-3) { printer_preset = &(*printer_it); } @@ -15260,7 +15386,7 @@ bool Plater::check_printer_initialized(MachineObject *obj, bool only_warning, bo if (!has_been_initialized) { if (popup_warning) { if (!only_warning) { - if (DeviceManager::get_printer_can_set_nozzle(obj->printer_type)) { + if (DeviceManager::get_printer_can_set_nozzle(obj->get_show_printer_type())) { MessageDialog dlg(wxGetApp().plater(), _L("The nozzle type is not set. Please set the nozzle and try again."), _L("Warning"), wxOK | wxICON_WARNING); dlg.ShowModal(); } else { @@ -15315,16 +15441,16 @@ TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, st csgmesh.reserve(2 * mo.volumes.size()); bool has_splitable_volume = csg::model_to_csgmesh(mo.const_volumes(), Transform3d::Identity(), std::back_inserter(csgmesh), csg::mpartsPositive | csg::mpartsNegative); - csg::BooleanFailReason fail_reason; - std::string fail_msg = check_boolean_possible(mo.const_volumes(), fail_reason); - if (fail_msg.empty() || fail_reason == csg::BooleanFailReason::NotBoundAVolume) { - try { - MeshBoolean::mcut::McutMeshPtr meshPtr = csg::perform_csgmesh_booleans_mcut(Range{std::begin(csgmesh), std::end(csgmesh)}); - mesh = MeshBoolean::mcut::mcut_to_triangle_mesh(*meshPtr); - if (mesh.its.indices.size() > 0) { - fail_msg = ""; - } - } catch (...) {} + csg::BooleanFailReason fail_reason; + std::string fail_msg = check_boolean_possible(mo.const_volumes(), fail_reason); + if (fail_msg.empty() || fail_reason == csg::BooleanFailReason::NotBoundAVolume) { + try { + MeshBoolean::mcut::McutMeshPtr meshPtr = csg::perform_csgmesh_booleans_mcut(Range{std::begin(csgmesh), std::end(csgmesh)}); + mesh = MeshBoolean::mcut::mcut_to_triangle_mesh(*meshPtr); + if (mesh.its.indices.size() > 0) { + fail_msg = ""; + } + } catch (...) {} #if 0 // if mcut fails, try again with CGAL if (mesh.empty()) { @@ -15711,8 +15837,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy const std::string path_u8 = into_u8(path); wxBusyCursor wait; - BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(": path=%1%, backup=%2%, export_plate_idx=%3%, SaveStrategy=%4%") - %output_path.string()%(strategy & SaveStrategy::Backup)%export_plate_idx %(unsigned int)strategy; + BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(": path=%1%, backup=%2%, export_plate_idx=%3%, SaveStrategy=%4%") % PathSanitizer::sanitize(output_path) % + (strategy & SaveStrategy::Backup) % export_plate_idx % (unsigned int) strategy; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": path=%1%, backup=%2%, export_plate_idx=%3%, SaveStrategy=%4%") % std::string("") % (strategy & SaveStrategy::Backup) % export_plate_idx % (unsigned int)strategy; @@ -16405,7 +16531,7 @@ void Plater::print_job_finished(wxCommandEvent &evt) { //start print failed if (p) { - #ifdef __APPLE__ +#ifdef __APPLE__ p->hide_select_machine_dlg(); #else if (Slic3r::GUI::wxGetApp().get_inf_dialog_contect().empty()) { @@ -16420,7 +16546,6 @@ void Plater::print_job_finished(wxCommandEvent &evt) Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; - dev->set_selected_machine(evt.GetString().ToStdString()); p->main_frame->request_select_tab(MainFrame::TabPosition::tpMonitor); //jump to monitor and select device status panel MonitorPanel* curr_monitor = p->main_frame->m_monitor; @@ -16508,29 +16633,6 @@ bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** o return false; } -bool Plater::on_filament_change(size_t filament_idx) -{ - auto& filament_presets = wxGetApp().preset_bundle->filament_presets; - if (filament_idx >= filament_presets.size()) - return false; - Slic3r::Preset* filament = wxGetApp().preset_bundle->filaments.find_preset(filament_presets[filament_idx]); - if (filament == nullptr) - return false; - std::string filament_type = filament->config.option("filament_type")->values[0]; - if (filament_type == "PVA") { - auto nozzle_diameters = p->config->option("nozzle_diameter")->values; - if (std::find(nozzle_diameters.begin(), nozzle_diameters.end(), 0.2) != nozzle_diameters.end()) { - wxString msg_text = _(L("It is not recommended to use PVA filaments with 0.2mm nozzles.")); - msg_text += "\n" + _(L("Are you sure to use them? \n")); - MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO); - if (dialog.ShowModal() == wxID_NO) { - return false; - } - } - } - return true; -} - int Plater::update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path) { return p->update_print_required_data(config, model, plate_data_list, file_name, file_path); @@ -16562,7 +16664,30 @@ bool Plater::search_string_getter(int idx, const char** label, const char** tool return false; } -// QDS. +bool Plater::on_filament_change(size_t filament_idx) +{ + auto& filament_presets = wxGetApp().preset_bundle->filament_presets; + if (filament_idx >= filament_presets.size()) + return false; + Slic3r::Preset* filament = wxGetApp().preset_bundle->filaments.find_preset(filament_presets[filament_idx]); + if (filament == nullptr) + return false; + std::string filament_type = filament->config.option("filament_type")->values[0]; + if (filament_type == "PVA") { + auto nozzle_diameters = p->config->option("nozzle_diameter")->values; + if (std::find(nozzle_diameters.begin(), nozzle_diameters.end(), 0.2) != nozzle_diameters.end()) { + wxString msg_text = _(L("It is not recommended to use PVA filaments with 0.2mm nozzles.")); + msg_text += "\n" + _(L("Are you sure to use them? \n")); + MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO); + if (dialog.ShowModal() == wxID_NO) { + return false; + } + } + } + return true; +} + +// BBS. void Plater::on_filament_count_change(size_t num_filaments) { // only update elements in plater @@ -16945,6 +17070,26 @@ std::vector Plater::get_extruder_colors_from_plater_config(const GC } } +std::vector Plater::get_filament_colors_render_info() const +{ + const Slic3r::DynamicPrintConfig* config = &wxGetApp().preset_bundle->project_config; + std::vector color_packs; + if (!config->has("filament_multi_colour")) return color_packs; + + color_packs = (config->option("filament_multi_colour"))->values; + return color_packs; +} + +std::vector Plater::get_filament_color_render_type() const +{ + const Slic3r::DynamicPrintConfig *config = &wxGetApp().preset_bundle->project_config; + std::vector ctype; + if (!config->has("filament_colour_type")) return ctype; + + ctype = (config->option("filament_colour_type"))->values; + return ctype; +} + /* Get vector of colors used for rendering of a Preview scene in "Color print" mode * It consists of extruder colors and colors, saved in model.custom_gcode_per_print_z */ @@ -17172,8 +17317,9 @@ void Plater::clear_before_change_mesh(int obj_idx) // may be different and they would make no sense. bool paint_removed = false; for (ModelVolume* mv : mo->volumes) { - paint_removed |= ! mv->supported_facets.empty() || ! mv->seam_facets.empty() || ! mv->mmu_segmentation_facets.empty(); + paint_removed |= !mv->supported_facets.empty() || !mv->fuzzy_skin_facets.empty() || !mv->seam_facets.empty() || !mv->mmu_segmentation_facets.empty(); mv->supported_facets.reset(); + mv->fuzzy_skin_facets.reset(); mv->seam_facets.reset(); mv->mmu_segmentation_facets.reset(); } @@ -17186,6 +17332,32 @@ void Plater::clear_before_change_mesh(int obj_idx) } } +void Plater::clear_before_change_mesh(int obj_idx, int vol_idx) +{ + ModelObject *mo = model().objects[obj_idx]; + + // If there are custom supports/seams/mmu segmentation, remove them. Fixed mesh + // may be different and they would make no sense. + bool paint_removed = false; + std::string model_name = ""; + for (size_t i = 0; i < mo->volumes.size(); i++) { + if (vol_idx != i) { continue; } + auto mv = mo->volumes[i]; + model_name = mv->name; + paint_removed |= !mv->supported_facets.empty() || !mv->fuzzy_skin_facets.empty() || !mv->seam_facets.empty() || !mv->mmu_segmentation_facets.empty(); + mv->supported_facets.reset(); + mv->fuzzy_skin_facets.reset(); + mv->seam_facets.reset(); + mv->mmu_segmentation_facets.reset(); + } + if (paint_removed) { + // snapshot_time is captured by copy so the lambda knows where to undo/redo to. + get_notification_manager()->push_notification(NotificationType::CustomSupportsAndSeamRemovedAfterRepair, + NotificationManager::NotificationLevel::PrintInfoNotificationLevel, + _u8L("Custom supports,seam_facets and color painting were removed before repairing,model name:") + model_name); + } +} + void Plater::changed_mesh(int obj_idx) { ModelObject* mo = model().objects[obj_idx]; @@ -17309,7 +17481,7 @@ void Plater::pop_warning_and_go_to_device_page(wxString printer_name, PrinterWar } else if (type == PrinterWarningType::EMPTY_FILAMENT) { content = _L("The filaments on the printer are all unknown types. Please go to the printer screen or software device page to set the filament type."); } - MessageDialog dlg(this, content, title, wxOK | wxICON_WARNING); + MessageDialog dlg(this, content, title, wxOK | wxFORWARD | wxICON_WARNING, _L("Device Page")); auto result = dlg.ShowModal(); if (result == wxFORWARD) { wxGetApp().mainframe->select_tab(size_t(MainFrame::tpMonitor)); @@ -17571,7 +17743,6 @@ int Plater::select_plate(int plate_index, bool need_slice) } const auto& preset_bundle = wxGetApp().preset_bundle; - if ((!ret) && (p->background_process.can_switch_print())) { //select successfully @@ -18290,7 +18461,9 @@ void Plater::show_object_info() t = model_object->instances[inst_idx]->get_matrix() * vol->get_matrix(); info_text += (boost::format(_utf8(L("Part name: %1%\n"))) % vol->name).str(); face_count = static_cast(vol->mesh().facets_count()); - size = vol->get_convex_hull().transformed_bounding_box(t).size(); + if (&vol->get_convex_hull()) { + size = vol->get_convex_hull().transformed_bounding_box(t).size(); + } } else { //int obj_idx, vol_idx; @@ -18579,6 +18752,7 @@ void Plater::show_status_message(std::string s) void Plater::edit_text() { auto &manager = get_view3D_canvas3D()->get_gizmos_manager(); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Edit existed text"); manager.open_gizmo(GLGizmosManager::Text); update(); } @@ -18680,6 +18854,14 @@ bool Plater::is_show_non_manifold_edges() { return p->show_non_manifold_edges; } +void Plater::toggle_text_cs() { + p->show_text_cs = !p->show_text_cs; +} + +bool Plater::is_show_text_cs() { + return p->show_text_cs; +} + void Plater::toggle_show_wireframe() { p->show_wireframe = !p->show_wireframe; } @@ -18764,8 +18946,9 @@ bool Plater::PopupObjectTableBySelection() wxMenu* Plater::plate_menu() { return p->menus.plate_menu(); } wxMenu* Plater::object_menu() { return p->menus.object_menu(); } wxMenu *Plater::part_menu() { return p->menus.part_menu(); } +wxMenu *Plater::text_part_menu() { return p->menus.text_part_menu(); } wxMenu *Plater::svg_part_menu() { return p->menus.svg_part_menu(); } -wxMenu* Plater::cut_connector_menu() { return p->menus.cut_connector_menu(); } +wxMenu* Plater::cut_connector_menu() { return p->menus.cut_connector_menu(); } wxMenu* Plater::sla_object_menu() { return p->menus.sla_object_menu(); } wxMenu* Plater::default_menu() { return p->menus.default_menu(); } wxMenu* Plater::instance_menu() { return p->menus.instance_menu(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index ae792af..57657ec 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -141,7 +141,7 @@ struct Box_msg { }; class Sidebar : public wxPanel -{ +{ ConfigOptionMode m_mode; Button * btn_sync{nullptr}; ScalableButton * ams_btn{nullptr}; @@ -404,7 +404,9 @@ public: void invalid_all_plate_thumbnails(); void force_update_all_plate_thumbnails(); - const VendorProfile::PrinterModel *get_curr_printer_model(); + const VendorProfile::PrinterModel * get_curr_printer_model(); + std::map get_bed_texture_maps(); + int get_right_icon_offset_bed(); static wxColour get_next_color_for_filament(); static wxString get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning); @@ -528,6 +530,7 @@ public: void reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false); void clear_before_change_mesh(int obj_idx); + void clear_before_change_mesh(int obj_idx, int vol_idx); void changed_mesh(int obj_idx); void changed_object(ModelObject &object); @@ -578,6 +581,7 @@ public: std::vector> get_extruders_colors(); // QDS void on_bed_type_change(BedType bed_type,bool is_gcode_file = false); + bool update_filament_colors_in_full_config(); void config_change_notification(const DynamicPrintConfig &config, const std::string& key); void on_config_change(const DynamicPrintConfig &config); @@ -586,6 +590,8 @@ public: // On activating the parent window. void on_activate(); std::vector get_extruder_colors_from_plater_config(const GCodeProcessorResult* const result = nullptr) const; + std::vector get_filament_colors_render_info() const; + std::vector get_filament_color_render_type() const; std::vector get_colors_for_color_print(const GCodeProcessorResult* const result = nullptr) const; void set_global_filament_map_mode(FilamentMapMode mode); @@ -594,7 +600,6 @@ public: FilamentMapMode get_global_filament_map_mode() const; void update_menus(); - wxString get_selected_printer_name_in_combox(); enum class PrinterWarningType { NOT_CONNECTED, @@ -887,6 +892,8 @@ public: void toggle_non_manifold_edges(); bool is_show_non_manifold_edges(); + void toggle_text_cs(); + bool is_show_text_cs(); void toggle_show_wireframe(); bool is_show_wireframe() const; void enable_wireframe(bool status); @@ -905,6 +912,7 @@ public: wxMenu* plate_menu(); wxMenu* object_menu(); wxMenu* part_menu(); + wxMenu* text_part_menu(); wxMenu* svg_part_menu(); wxMenu* cut_connector_menu(); wxMenu* sla_object_menu(); @@ -920,6 +928,7 @@ public: static bool has_illegal_filename_characters(const std::string& name); static void show_illegal_characters_warning(wxWindow* parent); + std::string get_preview_only_filename() { return m_preview_only_filename; }; bool last_arrange_job_is_finished() @@ -930,6 +939,10 @@ public: std::atomic m_arrange_running{false}; void reset_check_status() { m_check_status = 0; } + void mark_plate_toolbar_image_dirty(); + bool is_plate_toolbar_image_dirty() const; + void clear_plate_toolbar_image_dirty(); + //y void resetUploadCount(); //y58 @@ -968,6 +981,7 @@ private: std::string m_preview_only_filename; int m_valid_plates_count { 0 }; int m_check_status = 0; // 0 not check, 1 check success, 2 check failed + bool m_b_plate_toolbar_image_dirty{ true }; void suppress_snapshots(); void allow_snapshots(); diff --git a/src/slic3r/GUI/PrePrintChecker.cpp b/src/slic3r/GUI/PrePrintChecker.cpp index 315db1f..0e68239 100644 --- a/src/slic3r/GUI/PrePrintChecker.cpp +++ b/src/slic3r/GUI/PrePrintChecker.cpp @@ -1,7 +1,7 @@ #include "PrePrintChecker.hpp" #include "GUI_Utils.hpp" #include "I18N.hpp" - +#include namespace Slic3r { namespace GUI { @@ -94,7 +94,7 @@ void PrePrintChecker::clear() filamentList.clear(); } -void PrePrintChecker::add(PrintDialogStatus state, wxString msg, wxString tip) +void PrePrintChecker::add(PrintDialogStatus state, wxString msg, wxString tip, const wxString& wiki_url) { prePrintInfo info; @@ -124,12 +124,18 @@ void PrePrintChecker::add(PrintDialogStatus state, wxString msg, wxString tip) info.tips = wxEmptyString; } + info.wiki_url = wiki_url; + switch (info.type) { case prePrintInfoType::Filament: - filamentList.push_back(info); + if (std::find(filamentList.begin(), filamentList.end(), info) == filamentList.end()) { + filamentList.push_back(info); + } break; case prePrintInfoType::Printer: - printerList.push_back(info); + if (std::find(printerList.begin(), printerList.end(), info) == printerList.end()) { + printerList.push_back(info); + } break; default: break; } @@ -171,68 +177,64 @@ PrinterMsgPanel::PrinterMsgPanel(wxWindow *parent) this->SetSizer(m_sizer); } -void PrinterMsgPanel::SetLabelList(const std::vector &texts, const wxColour &colour) +static wxColour _GetLabelColour(const prePrintInfo& info) { - if (texts == m_last_texts) - return; - - m_last_texts = texts; - m_labels.clear(); - m_sizer->Clear(true); - std::set unique_texts; - - for (const wxString &text : texts) { - if (text.empty()) { - continue; - } - if (!unique_texts.insert(text).second) { - continue; - } - Label *label = new Label(this); - label->SetFont(::Label::Body_13); - label->SetForegroundColour(colour); - label->SetLabel(text); - label->Wrap(this->GetMinSize().GetWidth()); - label->Show(); - m_sizer->Add(label, 0, wxBOTTOM, FromDIP(4)); - m_labels.push_back(label); + if (info.level == Error) + { + return wxColour("#D01B1B"); } + else if (info.level == Warning) + { + return wxColour("#FF6F00"); + } + + return *wxBLACK; // Default colour for normal messages +} + +bool PrinterMsgPanel::UpdateInfos(const std::vector& infos) +{ + if (m_infos == infos) + { + return false; + } + m_infos = infos; + + m_sizer->Clear(true); + for (const prePrintInfo& info : infos) + { + if (!info.msg.empty()) + { + Label* label = new Label(this); + label->SetFont(::Label::Body_13); + label->SetForegroundColour(_GetLabelColour(info)); + + + if (info.wiki_url.empty()) + { + label->SetLabel(info.msg); + } + else + { + label->SetLabel(info.msg + " " + _L("Please refer to Wiki before use->")); + label->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); + label->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); + label->Bind(wxEVT_LEFT_DOWN, [info](wxMouseEvent& event) { wxLaunchDefaultBrowser(info.wiki_url); }); + } + + label->Wrap(this->GetMinSize().GetWidth()); + label->Show(); + m_sizer->Add(label, 0, wxBOTTOM, FromDIP(4)); + } + } + this->Show(); this->Layout(); + Fit(); + + return true; } -//void PrinterMsgPanel::SetLabelSingle(const wxString &texts, const wxColour &colour) -//{ -// Label *label = new Label(this); -// label->SetMinSize(wxSize(FromDIP(420), -1)); -// label->SetMaxSize(wxSize(FromDIP(420), -1)); -// label->SetFont(::Label::Body_13); -// label->SetForegroundColour(colour); -// label->SetLabel(texts); -// label->Wrap(FromDIP(-1)); -// label->Show(); -// m_sizer->Add(label, 0, wxBOTTOM, FromDIP(4)); -// m_labels.push_back(label); -// this->Layout(); -// Fit(); -//} - -wxString PrinterMsgPanel::GetLabel() { - if (!m_labels.empty() && m_labels[0] != nullptr) - return m_labels[0]->GetLabel(); - return wxEmptyString; -} - - -std::vector PrinterMsgPanel::GetLabelList() { - if (m_last_texts.empty()) - wxLogDebug(_L("No labels are currently stored.")); - return m_last_texts; -} - - - } }; diff --git a/src/slic3r/GUI/PrePrintChecker.hpp b/src/slic3r/GUI/PrePrintChecker.hpp index 96398cc..7487b52 100644 --- a/src/slic3r/GUI/PrePrintChecker.hpp +++ b/src/slic3r/GUI/PrePrintChecker.hpp @@ -22,7 +22,15 @@ struct prePrintInfo prePrintInfoType type; wxString msg; wxString tips; + wxString wiki_url; int index; + +public: + bool operator==(const prePrintInfo& other) const { + return level == other.level && type == other.type && + msg == other.msg && tips == other.tips && + wiki_url == other.wiki_url && index == other.index; + } }; enum PrintDialogStatus : unsigned int { @@ -58,6 +66,7 @@ enum PrintDialogStatus : unsigned int { PrintStatusBlankPlate, PrintStatusUnsupportedPrinter, PrintStatusInvalidMapping, + PrintStatusPrinterErrorEnd, // Errors for filament, Block Print @@ -68,6 +77,7 @@ enum PrintDialogStatus : unsigned int { PrintStatusAmsMappingMixInvalid, PrintStatusTPUUnsupportAutoCali, PrintStatusHasFilamentInBlackListError, + PrintStatusFilamentErrorEnd, PrintStatusErrorEnd,//->end error<- @@ -109,13 +119,20 @@ enum PrintDialogStatus : unsigned int { PrintStatusPublicInitFailed, PrintStatusPublicUploadFiled, - //y65 - PrintStatusPrinterOffline, + //y68 + QDTPrinterErrorBegin, PrintStatusPrinterNotStandby, PrintStatusPinrterPrinting, - PrinterNotConnectBox, - PrintStatusNeedUpgradingBox, + PrintStatusPrinterOffline, + QDTPrinterErrorEnd, + + //y68 + QDTBoxErrorBegin, BoxhasSomeProblem, + PrintStatusNeedUpgradingBox, + PrinterNotConnectBox, + QDTBoxErrorEnd, + }; class PrePrintChecker @@ -127,13 +144,16 @@ public: public: void clear(); /*auto merge*/ - void add(PrintDialogStatus state, wxString msg, wxString tip); + void add(PrintDialogStatus state, wxString msg, wxString tip, const wxString& wiki_url); static ::std::string get_print_status_info(PrintDialogStatus status); wxString get_pre_state_msg(PrintDialogStatus status); - static bool is_error(PrintDialogStatus status) { return (PrintStatusErrorBegin < status) && (PrintStatusErrorEnd > status); }; - static bool is_error_printer(PrintDialogStatus status) { return (PrintStatusPrinterErrorBegin < status) && (PrintStatusPrinterErrorEnd > status); }; - static bool is_error_filament(PrintDialogStatus status) { return (PrintStatusFilamentErrorBegin < status) && (PrintStatusFilamentErrorEnd > status); }; + + //y68 + static bool is_error(PrintDialogStatus status) { return ((PrintStatusErrorBegin < status) && (PrintStatusErrorEnd > status)) || ((QDTPrinterErrorBegin < status) && (QDTBoxErrorEnd > status)); }; + static bool is_error_printer(PrintDialogStatus status) { return ((PrintStatusPrinterErrorBegin < status) && (PrintStatusPrinterErrorEnd > status)) || ((QDTPrinterErrorBegin < status) && (QDTPrinterErrorEnd > status)); }; + static bool is_error_filament(PrintDialogStatus status) { return ((PrintStatusFilamentErrorBegin < status) && (PrintStatusFilamentErrorEnd > status)) || ((QDTBoxErrorBegin < status) || (QDTBoxErrorEnd > status)); }; + static bool is_warning(PrintDialogStatus status) { return (PrintStatusWarningBegin < status) && (PrintStatusWarningEnd > status); }; static bool is_warning_printer(PrintDialogStatus status) { return (PrintStatusPrinterWarningBegin < status) && (PrintStatusPrinterWarningEnd > status); }; static bool is_warning_filament(PrintDialogStatus status) { return (PrintStatusFilamentWarningBegin < status) && (PrintStatusFilamentWarningEnd > status); }; @@ -172,17 +192,13 @@ class PrinterMsgPanel : public wxPanel public: PrinterMsgPanel(wxWindow *parent); - void SetLabelList(const std::vector &texts, const wxColour &colour); - - // void SetLabelSingle(const wxString &texts,const wxColour& colour); - - wxString GetLabel(); - std::vector GetLabelList(); +public: + bool UpdateInfos(const std::vector& infos); private: - wxBoxSizer * m_sizer = nullptr; - std::vector