From 5cdfef9f9edf37c1aab6ca51641b5d7796e20598 Mon Sep 17 00:00:00 2001 From: QIDI TECH <893239786@qq.com> Date: Wed, 17 Sep 2025 12:32:36 +0800 Subject: [PATCH] update slic3r --- .gitignore | 5 +- DockerBuild.sh | 80 +- docker/BuildAppimageDockerfile | 19 + docker/BuildDepsDockerfile | 39 + docker/BuildDepsDockerfile24 | 39 + src/CMakeLists.txt | 2 +- src/QIDIStudio.cpp | 626 ++- src/QIDIStudio.hpp | 10 +- src/slic3r/CMakeLists.txt | 9 + src/slic3r/GUI/3DScene.cpp | 2 +- src/slic3r/GUI/AMSMaterialsSetting.cpp | 66 +- src/slic3r/GUI/AmsMappingPopup.cpp | 185 +- src/slic3r/GUI/AmsMappingPopup.hpp | 45 +- src/slic3r/GUI/AmsWidgets.cpp | 16 +- src/slic3r/GUI/Auxiliary.cpp | 2 +- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 14 + src/slic3r/GUI/BindDialog.cpp | 18 +- src/slic3r/GUI/CaliHistoryDialog.cpp | 16 +- src/slic3r/GUI/Calibration.cpp | 16 +- src/slic3r/GUI/CalibrationPanel.cpp | 2 +- src/slic3r/GUI/CalibrationWizard.hpp | 2 - src/slic3r/GUI/CameraPopup.cpp | 5 +- src/slic3r/GUI/ConfigManipulation.cpp | 48 +- src/slic3r/GUI/ConfigManipulation.hpp | 1 + src/slic3r/GUI/ConnectPrinter.cpp | 9 +- src/slic3r/GUI/ConnectPrinter.hpp | 4 +- src/slic3r/GUI/CreatePresetsDialog.cpp | 8 +- src/slic3r/GUI/DailyTips.cpp | 40 +- src/slic3r/GUI/DailyTips.hpp | 2 + src/slic3r/GUI/DeviceCore/CMakeLists.txt | 52 + src/slic3r/GUI/DeviceCore/DevBed.cpp | 25 + src/slic3r/GUI/DeviceCore/DevBed.h | 30 + src/slic3r/GUI/DeviceCore/DevConfig.cpp | 54 + src/slic3r/GUI/DeviceCore/DevConfig.h | 78 + src/slic3r/GUI/DeviceCore/DevConfigUtil.cpp | 239 + src/slic3r/GUI/DeviceCore/DevConfigUtil.h | 175 + src/slic3r/GUI/DeviceCore/DevCtrl.cpp | 26 + src/slic3r/GUI/DeviceCore/DevCtrl.h | 26 + src/slic3r/GUI/DeviceCore/DevDefs.h | 99 + .../GUI/DeviceCore/DevExtruderSystem.cpp | 292 ++ src/slic3r/GUI/DeviceCore/DevExtruderSystem.h | 190 + .../GUI/DeviceCore/DevExtruderSystemCtrl.cpp | 22 + src/slic3r/GUI/DeviceCore/DevFan.cpp | 227 + src/slic3r/GUI/DeviceCore/DevFan.h | 151 + .../GUI/DeviceCore/DevFilaAmsSetting.cpp | 13 + src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.h | 35 + .../GUI/DeviceCore/DevFilaBlackList.cpp | 254 ++ src/slic3r/GUI/DeviceCore/DevFilaBlackList.h | 18 + src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp | 691 +++ src/slic3r/GUI/DeviceCore/DevFilaSystem.h | 196 + src/slic3r/GUI/DeviceCore/DevFirmware.cpp | 2 + src/slic3r/GUI/DeviceCore/DevFirmware.h | 59 + src/slic3r/GUI/DeviceCore/DevHMS.cpp | 67 + src/slic3r/GUI/DeviceCore/DevHMS.h | 84 + src/slic3r/GUI/DeviceCore/DevInfo.cpp | 7 + src/slic3r/GUI/DeviceCore/DevInfo.h | 37 + src/slic3r/GUI/DeviceCore/DevLamp.cpp | 18 + src/slic3r/GUI/DeviceCore/DevLamp.h | 44 + src/slic3r/GUI/DeviceCore/DevLampCtrl.cpp | 64 + src/slic3r/GUI/DeviceCore/DevManager.cpp | 845 ++++ src/slic3r/GUI/DeviceCore/DevManager.h | 126 + src/slic3r/GUI/DeviceCore/DevMapping.cpp | 428 ++ src/slic3r/GUI/DeviceCore/DevMapping.h | 33 + src/slic3r/GUI/DeviceCore/DevNozzleSystem.cpp | 141 + src/slic3r/GUI/DeviceCore/DevNozzleSystem.h | 50 + src/slic3r/GUI/DeviceCore/DevPrintOptions.cpp | 280 ++ src/slic3r/GUI/DeviceCore/DevPrintOptions.h | 91 + .../GUI/DeviceCore/DevPrintTaskInfo.cpp | 1 + src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.h | 27 + src/slic3r/GUI/DeviceCore/DevStorage.cpp | 34 + src/slic3r/GUI/DeviceCore/DevStorage.h | 36 + src/slic3r/GUI/DeviceCore/DevUtil.cpp | 114 + src/slic3r/GUI/DeviceCore/DevUtil.h | 72 + src/slic3r/GUI/DeviceErrorDialog.cpp | 496 +++ src/slic3r/GUI/DeviceErrorDialog.hpp | 99 + src/slic3r/GUI/DeviceManager.cpp | 3828 ++--------------- src/slic3r/GUI/DeviceManager.hpp | 1095 +---- .../GUI/DeviceTab/uiAmsHumidityPopup.cpp | 4 +- src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h | 8 +- .../GUI/DeviceTab/uiDeviceUpdateVersion.cpp | 43 +- .../GUI/DeviceTab/uiDeviceUpdateVersion.h | 2 +- src/slic3r/GUI/EncodedFilament.hpp | 2 + src/slic3r/GUI/FilamentBitmapUtils.cpp | 73 +- src/slic3r/GUI/FilamentGroupPopup.cpp | 2 +- src/slic3r/GUI/FilamentPickerDialog.cpp | 169 +- src/slic3r/GUI/FilamentPickerDialog.hpp | 20 + src/slic3r/GUI/GCodeViewer.cpp | 770 +++- src/slic3r/GUI/GCodeViewer.hpp | 117 +- src/slic3r/GUI/GLCanvas3D.cpp | 50 +- src/slic3r/GUI/GLCanvas3D.hpp | 2 + src/slic3r/GUI/GUI.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 186 +- src/slic3r/GUI/GUI_App.hpp | 11 +- src/slic3r/GUI/GUI_Factories.cpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 134 +- src/slic3r/GUI/GUI_ObjectList.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp | 14 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 3 + src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoText.cpp | 99 +- src/slic3r/GUI/Gizmos/GLGizmoText.hpp | 7 +- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 5 + src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 1 + src/slic3r/GUI/HMS.cpp | 29 +- src/slic3r/GUI/HMSPanel.cpp | 14 +- src/slic3r/GUI/HMSPanel.hpp | 10 +- src/slic3r/GUI/HintNotification.cpp | 692 +-- src/slic3r/GUI/HintNotification.hpp | 80 +- src/slic3r/GUI/ImGuiWrapper.cpp | 1 + src/slic3r/GUI/ImageGrid.cpp | 2 +- src/slic3r/GUI/ImageMessageDialog.cpp | 102 + src/slic3r/GUI/ImageMessageDialog.hpp | 46 + src/slic3r/GUI/Jobs/ArrangeJob.cpp | 18 +- src/slic3r/GUI/Jobs/BindJob.cpp | 2 + .../GUI/Jobs/CreateFontNameImageJob.cpp | 9 +- .../GUI/Jobs/CreateFontStyleImagesJob.cpp | 4 +- src/slic3r/GUI/Jobs/EmbossJob.cpp | 32 +- src/slic3r/GUI/Jobs/EmbossJob.hpp | 6 +- src/slic3r/GUI/Jobs/FillBedJob.cpp | 5 +- src/slic3r/GUI/Jobs/PrintJob.cpp | 32 +- src/slic3r/GUI/Jobs/PrintJob.hpp | 4 + src/slic3r/GUI/MainFrame.cpp | 55 +- src/slic3r/GUI/MainFrame.hpp | 2 +- src/slic3r/GUI/MediaFilePanel.cpp | 30 +- src/slic3r/GUI/MediaFilePanel.h | 4 +- src/slic3r/GUI/MediaPlayCtrl.cpp | 41 +- src/slic3r/GUI/MediaPlayCtrl.h | 3 + src/slic3r/GUI/Monitor.cpp | 96 +- src/slic3r/GUI/Monitor.hpp | 4 +- src/slic3r/GUI/MultiMachine.cpp | 12 +- src/slic3r/GUI/MultiMachineManagerPage.cpp | 12 +- src/slic3r/GUI/MultiMachinePage.cpp | 12 +- src/slic3r/GUI/MultiSendMachineModel.cpp | 2 +- src/slic3r/GUI/MultiTaskManagerPage.cpp | 8 +- src/slic3r/GUI/NotificationManager.cpp | 46 +- src/slic3r/GUI/NotificationManager.hpp | 11 +- src/slic3r/GUI/ObjColorDialog.cpp | 32 +- src/slic3r/GUI/OptionsGroup.cpp | 24 +- src/slic3r/GUI/PartPlate.cpp | 170 +- src/slic3r/GUI/PartPlate.hpp | 39 +- src/slic3r/GUI/PartSkipDialog.cpp | 14 +- src/slic3r/GUI/PhysicalPrinterDialog.cpp | 72 +- src/slic3r/GUI/PhysicalPrinterDialog.hpp | 2 +- src/slic3r/GUI/PhysicalPrinterDialog_1.cpp | 11 + src/slic3r/GUI/PhysicalPrinterDialog_1.hpp | 1 + src/slic3r/GUI/Plater.cpp | 707 ++- src/slic3r/GUI/Plater.hpp | 38 +- src/slic3r/GUI/Preferences.cpp | 321 +- src/slic3r/GUI/Preferences.hpp | 18 +- src/slic3r/GUI/PresetComboBoxes.cpp | 48 +- src/slic3r/GUI/PrintOptionsDialog.cpp | 162 +- src/slic3r/GUI/PrintOptionsDialog.hpp | 3 +- src/slic3r/GUI/Printer/PrinterFileSystem.cpp | 13 +- src/slic3r/GUI/PrinterWebView.cpp | 21 +- src/slic3r/GUI/ReleaseNote.cpp | 426 +- src/slic3r/GUI/ReleaseNote.hpp | 51 +- src/slic3r/GUI/SelectMachine.cpp | 416 +- src/slic3r/GUI/SelectMachine.hpp | 18 +- src/slic3r/GUI/SelectMachinePop.cpp | 30 +- src/slic3r/GUI/Selection.cpp | 13 + src/slic3r/GUI/SendMultiMachinePage.cpp | 21 +- src/slic3r/GUI/SendToPrinter.cpp | 41 +- src/slic3r/GUI/SkipPartCanvas.cpp | 2 + src/slic3r/GUI/StatusPanel.cpp | 1015 ++--- src/slic3r/GUI/StatusPanel.hpp | 17 +- src/slic3r/GUI/SyncAmsInfoDialog.cpp | 134 +- src/slic3r/GUI/SyncAmsInfoDialog.hpp | 6 +- src/slic3r/GUI/SyncBoxInfoDialog.cpp | 194 +- src/slic3r/GUI/SyncBoxInfoDialog.hpp | 8 +- src/slic3r/GUI/Tab.cpp | 138 +- src/slic3r/GUI/Tab.hpp | 1 + src/slic3r/GUI/TaskManager.hpp | 2 + src/slic3r/GUI/UnsavedChangesDialog.cpp | 9 +- src/slic3r/GUI/UpgradePanel.cpp | 243 +- src/slic3r/GUI/UpgradePanel.hpp | 34 +- src/slic3r/GUI/UserManager.cpp | 2 + src/slic3r/GUI/WebGuideDialog.cpp | 4 +- src/slic3r/GUI/WebViewDialog.cpp | 39 +- src/slic3r/GUI/WebViewDialog.hpp | 1 + src/slic3r/GUI/Widgets/AMSControl.cpp | 233 +- src/slic3r/GUI/Widgets/AMSControl.hpp | 5 +- src/slic3r/GUI/Widgets/AMSItem.cpp | 170 +- src/slic3r/GUI/Widgets/AMSItem.hpp | 14 +- src/slic3r/GUI/Widgets/DropDown.cpp | 2 + src/slic3r/GUI/Widgets/FanControl.cpp | 77 +- src/slic3r/GUI/Widgets/FanControl.hpp | 4 +- src/slic3r/GUI/Widgets/LinkLabel.cpp | 53 + src/slic3r/GUI/Widgets/LinkLabel.hpp | 24 + src/slic3r/GUI/Widgets/SideTools.cpp | 4 +- src/slic3r/GUI/wxExtensions.cpp | 46 +- src/slic3r/Utils/CalibUtils.cpp | 490 ++- src/slic3r/Utils/CalibUtils.hpp | 12 +- src/slic3r/Utils/HelioDragon.cpp | 821 ++++ src/slic3r/Utils/HelioDragon.hpp | 298 ++ src/slic3r/Utils/Http.cpp | 15 +- src/slic3r/Utils/PresetUpdater.cpp | 5 +- src/slic3r/Utils/qidi_networking.hpp | 3 +- 199 files changed, 14601 insertions(+), 7804 deletions(-) create mode 100644 docker/BuildAppimageDockerfile create mode 100644 docker/BuildDepsDockerfile create mode 100644 docker/BuildDepsDockerfile24 create mode 100644 src/slic3r/GUI/DeviceCore/CMakeLists.txt create mode 100644 src/slic3r/GUI/DeviceCore/DevBed.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevBed.h create mode 100644 src/slic3r/GUI/DeviceCore/DevConfig.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevConfig.h create mode 100644 src/slic3r/GUI/DeviceCore/DevConfigUtil.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevConfigUtil.h create mode 100644 src/slic3r/GUI/DeviceCore/DevCtrl.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevCtrl.h create mode 100644 src/slic3r/GUI/DeviceCore/DevDefs.h create mode 100644 src/slic3r/GUI/DeviceCore/DevExtruderSystem.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevExtruderSystem.h create mode 100644 src/slic3r/GUI/DeviceCore/DevExtruderSystemCtrl.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFan.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFan.h create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.h create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaBlackList.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaBlackList.h create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFilaSystem.h create mode 100644 src/slic3r/GUI/DeviceCore/DevFirmware.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevFirmware.h create mode 100644 src/slic3r/GUI/DeviceCore/DevHMS.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevHMS.h create mode 100644 src/slic3r/GUI/DeviceCore/DevInfo.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevInfo.h create mode 100644 src/slic3r/GUI/DeviceCore/DevLamp.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevLamp.h create mode 100644 src/slic3r/GUI/DeviceCore/DevLampCtrl.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevManager.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevManager.h create mode 100644 src/slic3r/GUI/DeviceCore/DevMapping.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevMapping.h create mode 100644 src/slic3r/GUI/DeviceCore/DevNozzleSystem.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevNozzleSystem.h create mode 100644 src/slic3r/GUI/DeviceCore/DevPrintOptions.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevPrintOptions.h create mode 100644 src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.h create mode 100644 src/slic3r/GUI/DeviceCore/DevStorage.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevStorage.h create mode 100644 src/slic3r/GUI/DeviceCore/DevUtil.cpp create mode 100644 src/slic3r/GUI/DeviceCore/DevUtil.h create mode 100644 src/slic3r/GUI/DeviceErrorDialog.cpp create mode 100644 src/slic3r/GUI/DeviceErrorDialog.hpp create mode 100644 src/slic3r/GUI/ImageMessageDialog.cpp create mode 100644 src/slic3r/GUI/ImageMessageDialog.hpp create mode 100644 src/slic3r/GUI/Widgets/LinkLabel.cpp create mode 100644 src/slic3r/GUI/Widgets/LinkLabel.hpp create mode 100644 src/slic3r/Utils/HelioDragon.cpp create mode 100644 src/slic3r/Utils/HelioDragon.hpp diff --git a/.gitignore b/.gitignore index 5ea57b4..6b47bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,6 @@ 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 +.clangd \ No newline at end of file diff --git a/DockerBuild.sh b/DockerBuild.sh index 3c98eda..5f5aa97 100644 --- a/DockerBuild.sh +++ b/DockerBuild.sh @@ -1,15 +1,73 @@ #!/bin/bash PROJECT_ROOT=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)") -set -x +set -e -# Wishlist hint: For developers, creating a Docker Compose -# setup with persistent volumes for the build & deps directories -# would speed up recompile times significantly. For end users, -# the simplicity of a single Docker image and a one-time compilation -# seems better. -docker build -t qidistudio \ - --build-arg USER=${USER:-root} \ - --build-arg UID=$(id -u) \ - --build-arg GID=$(id -g) \ - $PROJECT_ROOT +function usage() { + echo "Usage: ./DockerBuild.sh [-c][-d][-i][-v]" + echo " -c: Build a self-contained Docker image that can be run directly" + echo " -d: disable safe parallel number limit(By default, the maximum number of parallels is set to free memory/2.5)" + echo " -i: Build and export an AppImage" + echo " -v: Build System Version:ubu22 or ubu24" + echo " -h: this help output" + echo "If you only need to run the program on a built Docker container, just use './DockerBuild.sh -c'" + echo "If you need to build an AppImage using Docker, first run './DockerBuild.sh -d', then run './DockerBuild.sh -s'." +} + +unset name +while getopts "hcdiv:" opt; do + case ${opt} in + c ) + BUILD_RUNNER=1 + ;; + d ) + BUILD_DEPS=1 + ;; + i ) + BUILD_APPIMAGE=1 + ;; + v ) + SYSTEM_VERSION="$OPTARG" + ;; + h ) usage + exit 0 + ;; + esac +done + +if [ -z "$SYSTEM_VERSION" ]; then + SYSTEM_VERSION="ubu22" +fi + +if [[ -n "${BUILD_DEPS}" ]]; then + if [ "$SYSTEM_VERSION" == "ubu22" ]; then + echo "Building dependencies for Ubuntu 22.04..." + docker build -f docker/BuildDepsDockerfile -t studio_dep_22:1.0 . + else + docker build -f docker/BuildDepsDockerfile24 -t studio_dep_24:1.0 . + fi +fi + +if [[ -n "${BUILD_APPIMAGE}" ]]; then + if [ "$SYSTEM_VERSION" == "ubu22" ]; then + docker build -f docker/BuildAppimageDockerfile --build-arg VERSION=studio_dep_22 -o type=local,dest=./build . + mv build/QIDIStudio_ubu64.AppImage build/QIDIStudio_ubu22.AppImage + else + docker build -f docker/BuildAppimageDockerfile --build-arg VERSION=studio_dep_24 -o type=local,dest=./build . + mv build/QIDIStudio_ubu64.AppImage build/QIDIStudio_ubu24.AppImage + fi +fi + +if [[ -n "${BUILD_RUNNER}" ]] +then + # Wishlist hint: For developers, creating a Docker Compose + # setup with persistent volumes for the build & deps directories + # would speed up recompile times significantly. For end users, + # the simplicity of a single Docker image and a one-time compilation + # seems better. + docker build -t qidistudio \ + --build-arg USER=${USER:-root} \ + --build-arg UID=$(id -u) \ + --build-arg GID=$(id -g) \ + $PROJECT_ROOT +fi \ No newline at end of file diff --git a/docker/BuildAppimageDockerfile b/docker/BuildAppimageDockerfile new file mode 100644 index 0000000..0c39067 --- /dev/null +++ b/docker/BuildAppimageDockerfile @@ -0,0 +1,19 @@ +ARG VERSION="studio_dep_22" +FROM ${VERSION}:1.0 AS builder + +COPY ./ /QIDIStudio + +WORKDIR /QIDIStudio + +RUN mkdir -p /QIDIStudio/deps/build + +RUN mv /destdir /QIDIStudio/deps/build/ + +RUN ./BuildLinux.sh -s + +ENV container=podman +RUN ./BuildLinux.sh -i + +FROM scratch AS export-stage + +COPY --from=builder /QIDIStudio/build/QIDIStudio_ubu64.AppImage / \ No newline at end of file diff --git a/docker/BuildDepsDockerfile b/docker/BuildDepsDockerfile new file mode 100644 index 0000000..be8875e --- /dev/null +++ b/docker/BuildDepsDockerfile @@ -0,0 +1,39 @@ +FROM docker.io/ubuntu:22.04 + +# Disable interactive package configuration +RUN apt-get update && \ + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections + +RUN apt-get update && apt-get install -y \ + autoconf \ + build-essential \ + cmake \ + curl \ + xvfb \ + extra-cmake-modules \ + file \ + git \ + locales \ + locales-all \ + m4 \ + pkgconf \ + sudo \ + wayland-protocols \ + libwebkit2gtk-4.0-dev \ + wget + +COPY ./ /QIDIStudio + +WORKDIR /QIDIStudio + +# Allow password-less sudo for ALL users +RUN echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/999-passwordless +RUN chmod 440 /etc/sudoers.d/999-passwordless + +RUN ./BuildLinux.sh -u + +RUN ./BuildLinux.sh -dfr + +RUN cp -r deps/build/destdir / + +RUN rm -rf /QIDIStudio diff --git a/docker/BuildDepsDockerfile24 b/docker/BuildDepsDockerfile24 new file mode 100644 index 0000000..34c4f20 --- /dev/null +++ b/docker/BuildDepsDockerfile24 @@ -0,0 +1,39 @@ +FROM docker.io/ubuntu:24.04 + +# Disable interactive package configuration +RUN apt-get update && \ + echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections + +RUN apt-get update && apt-get install -y \ + autoconf \ + build-essential \ + cmake \ + curl \ + xvfb \ + extra-cmake-modules \ + file \ + git \ + locales \ + locales-all \ + m4 \ + pkgconf \ + sudo \ + wayland-protocols \ + libwebkit2gtk-4.1-dev \ + wget + +COPY ./ /QIDIStudio + +WORKDIR /QIDIStudio + +# Allow password-less sudo for ALL users +RUN echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/999-passwordless +RUN chmod 440 /etc/sudoers.d/999-passwordless + +RUN ./BuildLinux.sh -u + +RUN ./BuildLinux.sh -dfr + +RUN cp -r deps/build/destdir / + +RUN rm -rf /QIDIStudio diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d9acc4c..b44f805 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,7 +108,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/QIDIStudio.rc.in ${CMAKE configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/QIDIStudio.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/QIDIStudio.manifest @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) if (WIN32) - add_library(QIDIStudio SHARED QIDIStudio.cpp QIDIStudio.hpp BaseException.cpp BaseException.h StackWalker.cpp StackWalker.h) + add_library(QIDIStudio SHARED QIDIStudio.cpp QIDIStudio.hpp) else () add_executable(QIDIStudio QIDIStudio.cpp QIDIStudio.hpp) endif () diff --git a/src/QIDIStudio.cpp b/src/QIDIStudio.cpp index b746e0a..d1be526 100644 --- a/src/QIDIStudio.cpp +++ b/src/QIDIStudio.cpp @@ -74,7 +74,7 @@ using namespace nlohmann; //QDS: add exception handler for win32 #include #ifdef WIN32 -#include "BaseException.h" +//#include "BaseException.h" #endif #include "slic3r/GUI/PartPlate.hpp" #include "slic3r/GUI/BitmapCache.hpp" @@ -148,9 +148,11 @@ std::map cli_errors = { {CLI_ONLY_ONE_TPU_SUPPORTED, "Not support printing 2 or more TPU filaments."}, {CLI_FILAMENTS_NOT_SUPPORTED_BY_EXTRUDER, "Some filaments cannot be printed on the extruder mapped to."}, {CLI_SLICING_ERROR, "Failed slicing the model. Please verify the slicing of all plates on QIDI Studio before uploading."}, - {CLI_GCODE_PATH_CONFLICTS, " G-code conflicts detected after slicing. Please make sure the 3mf file can be successfully sliced in the latest QIDI Studio."}, + {CLI_GCODE_PATH_CONFLICTS, " G-code conflicts detected after slicing. Please make sure the 3mf file can be successfully sliced in the latest QIDI Studio. If the file slices normally in QIDI Studio, try moving the wipe tower further from other models, as we use more conservative parameters for it during upload."}, {CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, "Found G-code in unprintable area of multi-extruder printers after slicing. Please make sure the 3mf file can be successfully sliced in the latest QIDI Studio."}, - {CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER, "Found some filament unprintable at first layer on current Plate. Please make sure the 3mf file can be successfully sliced with the same Plate type in the latest QIDI Studio."} + {CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER, "Found some filament unprintable at first layer on current Plate. Please make sure the 3mf file can be successfully sliced with the same Plate type in the latest QIDI Studio."}, + {CLI_GCODE_PATH_OUTSIDE, "Found G-code outside of the printable area. The issue may be caused by support, wipe tower, brim, or skirt. If the file slices normally in QIDI Studio, try moving the wipe tower further inside the build plate, as we use more conservative parameters for it during upload."}, + {CLI_GCODE_IN_WRAPPING_DETECT_AREA, "Found G-code in the wrapping detect area. Please make sure the 3mf file can be successfully sliced in the latest QIDI Studio."} }; typedef struct _object_info{ @@ -634,7 +636,7 @@ static int load_key_values_from_json(const std::string &file, std::map gcodes_key_set = {"filament_end_gcode", "filament_start_gcode", "change_filament_gcode", "layer_change_gcode", "machine_end_gcode", "machine_pause_gcode", "machine_start_gcode", - "template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode"}; + "template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode"}; static void load_default_gcodes_to_config(DynamicPrintConfig& config, Preset::Type type) { @@ -671,6 +673,9 @@ static void load_default_gcodes_to_config(DynamicPrintConfig& config, Preset::Ty ConfigOptionString* timeplase_gcode_opt = config.option("time_lapse_gcode", true); BOOST_LOG_TRIVIAL(trace) << __FUNCTION__<< ", time_lapse_gcode: "<value; + + ConfigOptionString *wrapping_detection_gcode_opt = config.option("wrapping_detection_gcode", true); + BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ", wrapping_detection_gcode: " << wrapping_detection_gcode_opt->value; } else if (type == Preset::TYPE_FILAMENT) { @@ -1371,31 +1376,21 @@ int CLI::run(int argc, char **argv) return CLI_ENVIRONMENT_ERROR; } - /*BOOST_LOG_TRIVIAL(info) << "begin to setup params, argc=" << argc << std::endl; - for (int index = 0; index < argc; index++) - BOOST_LOG_TRIVIAL(info) << "index=" << index << ", arg is " << argv[index] << std::endl; - int debug_argc = 18; - char* debug_argv[] = { - "F:\work\projects\qidi_debug\qidi_slicer\build_debug\src\Debug\qidi-studio.exe", - "--debug=2", - "--uptodate", - "--load-settings", - "machine_H2D.json", - "--load-defaultfila", - "--load-filaments", - ";filament_pla_basic_H2D.json;filament_pla_basic_H2D.json;filament_pla_basic_H2D.json;;", - "--export-3mf=output.3mf", - "--filament-colour", - "#FF00FFFF;#F4EE2AFF;#FFFFFFFF;#F99963FF;#F99963FF;#FF0000FF", - "--nozzle-volume-type", - "Standard,Standard", - "--filament-map-mode", - "Auto For Flush", - "--slice=1", - "--min-save", - "h2d_filament_map_test.3mf" - }; - if (!this->setup(debug_argc, debug_argv))*/ + /* BOOST_LOG_TRIVIAL(info) << "begin to setup params, argc=" << argc << std::endl; + for (int index = 0; index < argc; index++) + BOOST_LOG_TRIVIAL(info) << "index=" << index << ", arg is " << argv[index] << std::endl; + int debug_argc = 8; + char* debug_argv[] = { + "F:\work\projects\qidi_debug\qidi_slicer\build_debug\src\Debug\qidi-studio.exe", + "--debug=3", + "--export-3mf=output.3mf", + "--uptodate", + "--downward-check", + "--slice=1", + "--min-save", + "cube_a1_switch.3mf" + }; + if (!this->setup(debug_argc, debug_argv))*/ if (!this->setup(argc, argv)) { boost::nowide::cerr << "setup params error" << std::endl; @@ -1420,11 +1415,11 @@ int CLI::run(int argc, char **argv) #endif // _WIN32*/ - bool translate_old = false, regenerate_thumbnails = false, keep_old_params = false, filament_color_changed = false, downward_check = false; + bool translate_old = false, regenerate_thumbnails = false, keep_old_params = false, remove_wrapping_detect = false, filament_color_changed = false, downward_check = false; int current_printable_width, current_printable_depth, current_printable_height, shrink_to_new_bed = 0; int old_printable_height = 0, old_printable_width = 0, old_printable_depth = 0; Pointfs old_printable_area, old_exclude_area; - float old_max_radius = 0.f, old_height_to_rod = 0.f, old_height_to_lid = 0.f, old_filament_prime_volume = 0.f; + float old_max_radius = 0.f, old_height_to_rod = 0.f, old_height_to_lid = 0.f, old_filament_prime_volume = 0.f, old_distance_to_rod = 0.f; std::vector old_max_layer_height, old_min_layer_height; std::string outfile_dir = m_config.opt_string("outputdir", true); std::vector &load_configs = m_config.option("load_settings", true)->values; @@ -1682,16 +1677,17 @@ int CLI::run(int argc, char **argv) PlateDataPtrs plate_data_src; std::vector plate_obj_size_infos; //int arrange_option; - int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0, current_extruder_count = 1, new_extruder_count = 1; - bool first_file = true, is_qdt_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false; - bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false, allow_mix_temp = false; + int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0, current_extruder_count = 1, new_extruder_count = 1, current_printer_variant_count = 1, current_print_variant_count = 1, new_printer_variant_count = 1; + bool first_file = true, is_qdt_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false, has_support = false; + bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false, allow_mix_temp = false, enable_wrapping_detect = false; Semver file_version; Slic3r::GUI::Camera::ViewAngleType camera_view = Slic3r::GUI::Camera::ViewAngleType::Iso; std::map orients_requirement; std::vector project_presets; + std::vector current_nozzle_volume_type, new_nozzle_volume_type; std::string new_printer_name, current_printer_name, new_process_name, current_process_name, current_printer_system_name, current_process_system_name, new_process_system_name, new_printer_system_name, printer_model_id, current_printer_model, printer_model, new_default_process_name; std::vector upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings; - std::vector current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants; + std::vector current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants, new_extruder_variants, current_print_extruder_variants, new_printer_extruder_variants; DynamicPrintConfig load_process_config, load_machine_config; bool new_process_config_is_system = true, new_printer_config_is_system = true; std::string pipe_name, makerlab_name, makerlab_version, different_process_setting; @@ -1912,7 +1908,7 @@ int CLI::run(int argc, char **argv) record_exit_reson(outfile_dir, CLI_FILE_VERSION_NOT_SUPPORTED, 0, cli_errors[CLI_FILE_VERSION_NOT_SUPPORTED], sliced_info); flush_and_exit(CLI_FILE_VERSION_NOT_SUPPORTED); } - Semver old_version(1, 5, 9), old_version2(1, 5, 9), old_version3(2, 0, 0); + Semver old_version(1, 5, 9), old_version2(1, 5, 9), old_version3(2, 0, 0), old_version4(2, 2, 0); if ((file_version < old_version) && !config.empty()) { translate_old = true; BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, need to translate")%file_version.to_string(); @@ -1937,6 +1933,11 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, need to keep old params")%file_version.to_string(); } + if (file_version < old_version4) { + remove_wrapping_detect = true; + BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, need to set enable_wrapping_detection to false")%file_version.to_string(); + } + if (normative_check) { ConfigOptionStrings* postprocess_scripts = config.option("post_process"); if (postprocess_scripts) { @@ -1960,18 +1961,29 @@ int CLI::run(int argc, char **argv) current_printer_model = config.option("printer_model", true)->value; current_filaments_name = config.option("filament_settings_id")->values; current_extruder_count = config.option("nozzle_diameter")->values.size(); + current_printer_variant_count = config.option("printer_extruder_variant", true)->values.size(); + current_print_variant_count = config.option("print_extruder_variant", true)->values.size(); current_is_multi_extruder = current_extruder_count > 1; - if (current_is_multi_extruder) { + //if (current_is_multi_extruder || (current_printer_variant_count > 1)) { auto opt_extruder_type = dynamic_cast(config.option("extruder_type")); auto opt_nozzle_volume_type = dynamic_cast(config.option("nozzle_volume_type")); + if (opt_nozzle_volume_type) { + int nozzle_volume_type_size = opt_nozzle_volume_type->values.size(); + current_nozzle_volume_type.resize(nozzle_volume_type_size, nvtStandard); + for (int i = 0; i < nozzle_volume_type_size; i++) + { + current_nozzle_volume_type[i] = (NozzleVolumeType)(opt_nozzle_volume_type->values[i]); + } + } + current_extruder_variants.resize(current_extruder_count, ""); for (int e_index = 0; e_index < current_extruder_count; e_index++) { - ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(e_index)); - NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index)); + ExtruderType extruder_type = opt_extruder_type ? (ExtruderType)(opt_extruder_type->get_at(e_index)):etDirectDrive; + NozzleVolumeType nozzle_volume_type = opt_nozzle_volume_type?(NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index)) : nvtStandard; current_extruder_variants[e_index] = get_extruder_variant_string(extruder_type, nozzle_volume_type); } - } + //} BOOST_LOG_TRIVIAL(info) << boost::format("current_printer_name %1%, current_process_name %2%")%current_printer_name %current_process_name; ConfigOptionStrings* option_strings = config.option("inherits_group"); @@ -2032,12 +2044,14 @@ int CLI::run(int argc, char **argv) old_height_to_lid = config.opt_float("extruder_clearance_height_to_lid"); if (config.option("extruder_clearance_max_radius")) old_max_radius = config.opt_float("extruder_clearance_max_radius"); + if (config.option("extruder_clearance_dist_to_rod")) + old_distance_to_rod = config.opt_float("extruder_clearance_dist_to_rod"); if (config.option("max_layer_height")) old_max_layer_height = config.option("max_layer_height")->values; if (config.option("min_layer_height")) old_min_layer_height = config.option("min_layer_height")->values; BOOST_LOG_TRIVIAL(info) << boost::format("old printable size from 3mf: {%1%, %2%, %3%}")%old_printable_width %old_printable_depth %old_printable_height; - BOOST_LOG_TRIVIAL(info) << boost::format("old extruder_clearance_height_to_rod %1%, extruder_clearance_height_to_lid %2%, extruder_clearance_max_radius %3%}")%old_height_to_rod %old_height_to_lid %old_max_radius; + BOOST_LOG_TRIVIAL(info) << boost::format("old extruder_clearance_height_to_rod %1%, extruder_clearance_height_to_lid %2%, extruder_clearance_max_radius %3% extruder_clearance_dist_to_rod %4%}")%old_height_to_rod %old_height_to_lid %old_max_radius %old_distance_to_rod; } else { @@ -2161,6 +2175,21 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(warning) << boost::format("%1%: not support to slice plate %2%, reset to 0")%__LINE__ %plate_to_slice; plate_to_slice = 0; } + if (is_qdt_3mf) { + //support params process + ConfigOptionBool *enable_support_option = m_print_config.option("enable_support", true); + //traverse each object one by one + size_t num_objects = m_models[0].objects.size(); + for (int i = 0; i < num_objects; ++i) { + ModelObject* object = m_models[0].objects[i]; + DynamicPrintConfig object_config = object->config.get(); + ConfigOptionBool *obj_enable_support_option = object_config.option("enable_support"); + if (enable_support_option->value || (obj_enable_support_option && obj_enable_support_option->value)) { + has_support = true; + break; + } + } + } //load custom gcode file std::map custom_gcodes_map; @@ -2950,9 +2979,51 @@ int CLI::run(int argc, char **argv) m_print_config.set("print_settings_id", new_preset->name, true); project_presets.push_back(new_preset); } + //compute extruder variant index + auto compute_variant_index = [](DynamicPrintConfig& full_config, const DynamicPrintConfig& new_config, std::string id_name, std::string variant_name, std::vector& new_index, bool& count_changed) { + auto curr_variant_opt = dynamic_cast(full_config.option(variant_name)); + auto new_variant_opt = dynamic_cast(new_config.option(variant_name)); + auto curr_id_opt = dynamic_cast(full_config.option(id_name)); + auto new_id_opt = dynamic_cast(new_config.option(id_name)); + if (!new_variant_opt || !new_id_opt) { + BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% or %4% from new config")%__FUNCTION__ %__LINE__ % variant_name %id_name; + count_changed = false; + return; + } + int new_variant_count = new_variant_opt->size(), curr_variant_count = 0; + new_index.clear(); + new_index.resize(new_variant_count, -1); + if (curr_variant_opt && curr_id_opt) { + if (curr_variant_opt->size() != curr_id_opt->size()) { + BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, %3%'s size %4% not equal to %5%'s size %6%")%__FUNCTION__ %__LINE__ % variant_name %curr_variant_opt->size() %id_name %curr_id_opt->size(); + count_changed = false; + return; + } + curr_variant_count = curr_variant_opt->size(); + count_changed = (curr_variant_count != new_variant_count); + } + else + count_changed = (new_variant_count != 1); + + + for (int i = 0; i < new_variant_count; i++) + { + if (curr_variant_count > 0) { + for (int j = 0; j < curr_variant_count; j++) + { + if ((curr_variant_opt->values[j] == new_variant_opt->values[i]) && (curr_id_opt->values[j] == new_id_opt->values[i])) { + new_index[i] = j; + break; + } + } + } + else if ((new_variant_opt->values[i] == "Direct Drive Standard") && (new_id_opt->values[i] == 1)) + new_index[i] = 0; + } + }; //update seperate configs into full config - auto update_full_config = [](DynamicPrintConfig& full_config, const DynamicPrintConfig& config, std::set& diff_key_sets, bool update_all = false, bool skip_gcodes = false) { + auto update_full_config = [](DynamicPrintConfig& full_config, const DynamicPrintConfig& config, std::set& diff_key_sets, bool variant_count_changed, std::set& key_set_1, std::set& key_set_2, std::vector variant_index, bool update_all = false, bool skip_gcodes = false) { const t_config_option_keys& config_keys = config.keys(); BOOST_LOG_TRIVIAL(info) << boost::format("update_full_config: config keys count %1%")%config_keys.size(); for (const t_config_option_key &opt_key : config_keys) { @@ -2967,7 +3038,31 @@ int CLI::run(int argc, char **argv) else { //uptodate, diff keys, continue BOOST_LOG_TRIVIAL(info) << boost::format("%1%, keep key %2%")%__LINE__ %opt_key; - continue; + if (variant_count_changed) { + // + int stride = 0; + if (key_set_1.count(opt_key) > 0) + { + stride = 1; + } + else if (key_set_2.count(opt_key) > 0) + { + stride = 2; + } + + if (stride > 0) { + const ConfigOption *source_opt = config.option(opt_key); + ConfigOption *dest_opt = full_config.option(opt_key, true); + const ConfigOptionVectorBase* opt_vec_src = static_cast(source_opt); + ConfigOptionVectorBase* opt_vec_dest = static_cast(dest_opt); + + opt_vec_dest->set_with_restore(opt_vec_src, variant_index, stride); + } + else + continue; + } + else + continue; } } } @@ -3000,6 +3095,9 @@ int CLI::run(int argc, char **argv) if (!is_qdt_3mf && !different_process_setting.empty()) { different_settings[0] = different_process_setting; } + + std::vector new_variant_index; + bool variant_count_changed = false; //set the machine settings into print config if (!new_printer_name.empty() || up_config_to_date) { std::vector different_keys; @@ -3028,7 +3126,8 @@ int CLI::run(int argc, char **argv) load_default_gcodes_to_config(load_machine_config, Preset::TYPE_PRINTER); if (new_printer_name.empty()) { int diff_keys_size = different_keys_set.size(); - ret = update_full_config(m_print_config, load_machine_config, different_keys_set, false, skip_modified_gcodes); + compute_variant_index(m_print_config, load_machine_config, "printer_extruder_id", "printer_extruder_variant", new_variant_index, variant_count_changed); + ret = update_full_config(m_print_config, load_machine_config, different_keys_set, variant_count_changed, printer_options_with_variant_1, printer_options_with_variant_2, new_variant_index, false, skip_modified_gcodes); if (diff_keys_size != different_keys_set.size()) { //changed BOOST_LOG_TRIVIAL(info) << boost::format("new different key size %1%")%different_keys_set.size(); @@ -3041,7 +3140,7 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("no new printer, only update the different key, new different_settings: %1%")%different_settings[filament_count+1]; } else { - ret = update_full_config(m_print_config, load_machine_config, different_keys_set, true); + ret = update_full_config(m_print_config, load_machine_config, different_keys_set, variant_count_changed, printer_options_with_variant_1, printer_options_with_variant_2, new_variant_index, true); BOOST_LOG_TRIVIAL(info) << boost::format("load a new printer, update all the keys, different_settings: %1%")%different_settings[filament_count+1]; if (new_printer_name != current_printer_name) { @@ -3124,6 +3223,8 @@ int CLI::run(int argc, char **argv) if (m_print_config.option("nozzle_diameter")) { new_extruder_count = m_print_config.option("nozzle_diameter")->values.size(); new_is_multi_extruder = new_extruder_count > 1; + new_printer_extruder_variants = m_print_config.option("printer_extruder_variant", true)->values; + new_printer_variant_count = new_printer_extruder_variants.size(); } //set the process settings into print config @@ -3169,7 +3270,8 @@ int CLI::run(int argc, char **argv) load_default_gcodes_to_config(load_process_config, Preset::TYPE_PRINT); if (new_process_name.empty()) { int diff_keys_size = different_keys_set.size(); - ret = update_full_config(m_print_config, load_process_config, different_keys_set, false, skip_modified_gcodes); + compute_variant_index(m_print_config, load_process_config, "print_extruder_id", "print_extruder_variant", new_variant_index, variant_count_changed); + ret = update_full_config(m_print_config, load_process_config, different_keys_set, variant_count_changed, print_options_with_variant, empty_options, new_variant_index, false, skip_modified_gcodes); if (diff_keys_size != different_keys_set.size()) { //changed BOOST_LOG_TRIVIAL(info) << boost::format("new different key size %1%")%different_keys_set.size(); @@ -3182,9 +3284,10 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("no new process, only update the different key, new different_settings: %1%")%different_settings[0]; } else { - ret = update_full_config(m_print_config, load_process_config, different_keys_set, true); + ret = update_full_config(m_print_config, load_process_config, different_keys_set, variant_count_changed, print_options_with_variant, empty_options, new_variant_index, true); BOOST_LOG_TRIVIAL(info) << boost::format("load a new process, update all the keys, different_settings: %1%")%different_settings[0]; } + current_print_variant_count = m_print_config.option("print_extruder_variant", true)->values.size(); if (ret) { record_exit_reson(outfile_dir, ret, 0, cli_errors[ret], sliced_info); @@ -3192,6 +3295,34 @@ int CLI::run(int argc, char **argv) } } + //get nozzle_volume_type + if(m_extra_config.has("nozzle_volume_type")) { + auto opt_nozzle_volume_type = dynamic_cast(m_extra_config.option("nozzle_volume_type")); + if (opt_nozzle_volume_type) { + int nozzle_volume_type_size = opt_nozzle_volume_type->values.size(); + new_nozzle_volume_type.resize(nozzle_volume_type_size, nvtStandard); + for (int i = 0; i < nozzle_volume_type_size; i++) + { + new_nozzle_volume_type[i] = (NozzleVolumeType) (opt_nozzle_volume_type->values[i]); + } + } + } + else { + new_nozzle_volume_type.resize(new_extruder_count, nvtStandard); + } + new_extruder_variants.resize(new_extruder_count, ""); + const ConfigOptionEnumsGeneric *opt_extruder_type = dynamic_cast(m_print_config.option("extruder_type")); + for (int e_index = 0; e_index < new_extruder_count; e_index++) { + ExtruderType extruder_type = opt_extruder_type ? (ExtruderType) (opt_extruder_type->get_at(e_index)) : etDirectDrive; + new_extruder_variants[e_index] = get_extruder_variant_string(extruder_type, new_nozzle_volume_type[e_index]); + } + + if (current_nozzle_volume_type.empty()) + { + current_nozzle_volume_type.resize(current_extruder_count, nvtStandard); + } + current_print_extruder_variants = m_print_config.option("print_extruder_variant", true)->values; + if (machine_switch) { print_compatible_printers.push_back(new_printer_system_name); @@ -3213,7 +3344,7 @@ int CLI::run(int argc, char **argv) } //add multi-extruder related logic - if (new_process_name.empty() && (current_is_multi_extruder != new_is_multi_extruder)) { + if (new_process_name.empty() && ((current_extruder_count != new_extruder_count) || (current_print_variant_count != new_printer_variant_count))) { if (new_default_process_name.empty()) { BOOST_LOG_TRIVIAL(error) << boost::format("machine_switch: default process configis null, should not happen, new_printer_name %1%")%new_printer_name; record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); @@ -3234,15 +3365,17 @@ int CLI::run(int argc, char **argv) record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); flush_and_exit(CLI_CONFIG_FILE_ERROR); } - BOOST_LOG_TRIVIAL(info) << boost::format("machine_switch: loaded default process config %1%, from %2%")%config_name %file_path ; + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, machine_switch: loaded default process config %2%, from %3%")%__LINE__ %config_name %file_path ; + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, current_is_multi_extruder: %2%, new_is_multi_extruder: %3%, current_print_variant_count: %4%, new_printer_variant_count: %5%") + %__LINE__ %current_is_multi_extruder %new_is_multi_extruder %current_print_variant_count %new_printer_variant_count; - if (!current_is_multi_extruder && new_is_multi_extruder) { + if (!current_is_multi_extruder && new_is_multi_extruder && (current_print_variant_count == 1)) { //single -> multiple ret = m_print_config.update_values_from_single_to_multi(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant"); } - else if (current_is_multi_extruder && !new_is_multi_extruder) { + else { //multiple -> single - ret = m_print_config.update_values_from_multi_to_single(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant", current_extruder_variants); + ret = m_print_config.update_values_from_multi_to_multi(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant", new_extruder_variants); } if (ret) { @@ -3257,26 +3390,34 @@ int CLI::run(int argc, char **argv) //set the filament settings into print config if ((load_filament_count > 0) || (up_config_to_date)) { - std::vector filament_variant_count(filament_count, 1); - std::vector old_start_index(filament_count, 0); - std::vector old_variant_count(filament_count, 1); - if (current_is_multi_extruder) { - std::vector& old_self_indice = m_print_config.option("filament_self_index", true)->values; - int old_self_indice_size = old_self_indice.size(); - int k = -1, current_filament = 0; - for (size_t i = 0; i < old_self_indice_size; i++) { - if (old_self_indice[i] > current_filament) { - current_filament = old_self_indice[i]; - old_start_index[++k] = i; - old_variant_count[k] = 1; - } - else { - old_variant_count[k] = old_variant_count[k] + 1; - } - } - if (load_filament_count == 0) - filament_variant_count = old_variant_count; + //std::vector filament_variant_count(filament_count, 1); + std::vector old_start_indice(filament_count, 0); + std::vector old_variant_counts(filament_count, 1), new_variant_counts; + + ConfigOptionInts* filament_self_index_opt = m_print_config.option("filament_self_index"); + if (!filament_self_index_opt) { + filament_self_index_opt = m_print_config.option("filament_self_index", true); + std::vector& filament_self_indice = filament_self_index_opt->values; + filament_self_indice.resize(filament_count); + for (int index = 0; index < filament_count; index++) + filament_self_indice[index] = index + 1; } + + std::vector old_self_indice= filament_self_index_opt->values; + int old_self_indice_size = old_self_indice.size(); + int k = -1, current_filament = 0; + for (size_t i = 0; i < old_self_indice_size; i++) { + if (old_self_indice[i] > current_filament) { + current_filament = old_self_indice[i]; + old_start_indice[++k] = i; + old_variant_counts[k] = 1; + } + else { + old_variant_counts[k] = old_variant_counts[k] + 1; + } + } + new_variant_counts = old_variant_counts; + //filament_variant_count = old_variant_counts; for (int index = 0; index < load_filaments_config.size(); index++) { DynamicPrintConfig& config = load_filaments_config[index]; int filament_index = load_filaments_index[index]; @@ -3324,6 +3465,30 @@ int CLI::run(int argc, char **argv) opt_filament_ids->resize(filament_count, filament_id_setting); opt_filament_ids->set_at(filament_id_setting, filament_index-1, 0); + //compute the variant index logic + ConfigOptionStrings *curr_variant_opt = m_print_config.option("filament_extruder_variant"); + if (!curr_variant_opt) { + curr_variant_opt = m_print_config.option("filament_extruder_variant", true); + std::vector& filament_variants = curr_variant_opt->values; + filament_variants.resize(filament_count, get_extruder_variant_string(etDirectDrive, nvtStandard)); + } + const ConfigOptionStrings *new_variant_opt = dynamic_cast(config.option("filament_extruder_variant", true)); + + std::vector new_variant_indice; + int new_variant_count = new_variant_opt->size(), old_variant_count = old_variant_counts[filament_index - 1]; + new_variant_indice.resize(new_variant_count, -1); + + for (int i = 0; i < new_variant_count; i++) + { + for (int j = old_start_indice[filament_index - 1]; j < old_start_indice[filament_index - 1] + old_variant_count; j++) + { + if (curr_variant_opt->values[j] == new_variant_opt->values[i]) { + new_variant_indice[i] = j; + break; + } + } + } + //parse the filament value to index th //loop through options and apply them std::set different_keys_set(different_keys.begin(), different_keys.end()); @@ -3331,6 +3496,17 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("update filament %1%'s config to newest, different size %2%, name %3%, different_settings %4%") %filament_index%different_keys_set.size()%load_filaments_name[index] % different_settings[filament_index]; for (const t_config_option_key &opt_key : config.keys()) { + // Create a new option with default value for the key. + // If the key is not in the parameter definition, or this ConfigBase is a static type and it does not support the parameter, + // an exception is thrown if not ignore_nonexistent. + const ConfigOption *source_opt = config.option(opt_key); + if (source_opt == nullptr) { + // The key was not found in the source config, therefore it will not be initialized! + BOOST_LOG_TRIVIAL(error) << boost::format("can not find %1% from filament %2%: %3%")%opt_key%filament_index%load_filaments_name[index]; + record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + if ((load_filament_count == 0) && !different_keys_set.empty()) { std::set::iterator iter = different_keys_set.find(opt_key); @@ -3343,21 +3519,27 @@ int CLI::run(int argc, char **argv) else { //uptodate, diff keys, continue BOOST_LOG_TRIVIAL(info) << boost::format("%1%, keep key %2%")%__LINE__ %opt_key; + if (filament_options_with_variant.find(opt_key) != filament_options_with_variant.end()) + { + ConfigOption *opt = m_print_config.option(opt_key); + if (opt == nullptr) { + // opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def(). + // This is only possible if other is of DynamicConfig type. + BOOST_LOG_TRIVIAL(error) << boost::format("can not find option %1% from config, but can find it in different settings")%opt_key; + record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + ConfigOptionVectorBase* opt_vec_dst = static_cast(opt); + const ConfigOptionVectorBase* opt_vec_src = static_cast(source_opt); + //set with index + opt_vec_dst->set_with_restore_2(opt_vec_src, new_variant_indice, old_start_indice[filament_index - 1], old_variant_count); + } + continue; } } } - // Create a new option with default value for the key. - // If the key is not in the parameter definition, or this ConfigBase is a static type and it does not support the parameter, - // an exception is thrown if not ignore_nonexistent. - const ConfigOption *source_opt = config.option(opt_key); - if (source_opt == nullptr) { - // The key was not found in the source config, therefore it will not be initialized! - BOOST_LOG_TRIVIAL(error) << boost::format("can not find %1% from filament %2%: %3%")%opt_key%filament_index%load_filaments_name[index]; - record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); - flush_and_exit(CLI_CONFIG_FILE_ERROR); - } if (source_opt->is_scalar()) { if (opt_key == "compatible_printers_condition") { ConfigOption *opt = m_print_config.option("compatible_machine_expression_group", true); @@ -3393,33 +3575,29 @@ int CLI::run(int argc, char **argv) } ConfigOptionVectorBase* opt_vec_dst = static_cast(opt); const ConfigOptionVectorBase* opt_vec_src = static_cast(source_opt); - if (new_is_multi_extruder && (filament_options_with_variant.find(opt_key) != filament_options_with_variant.end())) { - if (load_filament_count > 0) { - if (filament_index == 1) - opt_vec_dst->set(opt_vec_src); - else - opt_vec_dst->append(opt_vec_src); + if (filament_options_with_variant.find(opt_key) != filament_options_with_variant.end()) { + std::vector temp_variant_indice; + temp_variant_indice.resize(new_variant_count, -1); + opt_vec_dst->set_with_restore_2(opt_vec_src, temp_variant_indice, old_start_indice[filament_index - 1], old_variant_count); - if (opt_key == "filament_extruder_variant") - filament_variant_count[filament_index - 1] = opt_vec_src->size(); - } - else { - //only update - for (size_t i = 0; i < old_variant_count[filament_index-1]; i++) { - opt_vec_dst->set_at(opt_vec_src, old_start_index[filament_index - 1] + i, i); - } - } + if (opt_key == "filament_extruder_variant") + new_variant_counts[filament_index - 1] = opt_vec_src->size(); } else { - if (current_is_multi_extruder && !new_is_multi_extruder && filament_options_with_variant.find(opt_key) != filament_options_with_variant.end()) { - if (opt_vec_dst->size() > filament_count) - opt_vec_dst->resize(filament_count); - } opt_vec_dst->set_at(opt_vec_src, filament_index - 1, 0); } } } + //update the old index + if (old_variant_count != new_variant_count) + { + for (int i = index + 1; i < filament_count; i++ ) + { + old_start_indice[i] += new_variant_count - old_variant_count; + } + } + if (diff_keys_size != different_keys_set.size()) { //changed different_keys.clear(); @@ -3437,7 +3615,7 @@ int CLI::run(int argc, char **argv) filament_self_indice.resize(index_size, 1); int k = 0; for (size_t i = 0; i < filament_count; i++) { - for (size_t j = 0; j < filament_variant_count[i]; j++) { + for (size_t j = 0; j < new_variant_counts[i]; j++) { filament_self_indice[k++] = i + 1; } } @@ -3454,7 +3632,9 @@ int CLI::run(int argc, char **argv) std::vector& project_filament_colors = project_filament_colors_option->values; project_filament_colors.resize(filament_count, "#FFFFFF"); } - if (project_filament_colors_option && (selected_filament_colors_option || !m_print_config.option("flush_volumes_matrix") || (new_extruder_count != current_extruder_count))) + + if (project_filament_colors_option && + (selected_filament_colors_option || !m_print_config.option("flush_volumes_matrix") || (current_extruder_count != new_extruder_count) || (new_nozzle_volume_type != current_nozzle_volume_type))) { std::vector selected_filament_colors; if (selected_filament_colors_option) { @@ -3543,7 +3723,7 @@ int CLI::run(int argc, char **argv) { 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); + nozzle_flush_dataset_full.resize(new_printer_variant_count, 0); else nozzle_flush_dataset_full.resize(1, 0); @@ -3639,7 +3819,7 @@ int CLI::run(int argc, char **argv) //update the object config due to extruder count change - if ((machine_switch) && (new_extruder_count != current_extruder_count)) + if ((machine_switch) && ((current_extruder_count != new_extruder_count) || (current_print_variant_count != new_printer_variant_count))) { //process the object params here size_t num_objects = m_models[0].objects.size(); @@ -3647,20 +3827,22 @@ int CLI::run(int argc, char **argv) ModelObject* object = m_models[0].objects[i]; DynamicPrintConfig object_config = object->config.get(); if (!object_config.empty()) { - if (current_extruder_count < new_extruder_count) + /* if (current_extruder_count < new_extruder_count) object_config.update_values_from_single_to_multi_2(m_print_config, print_options_with_variant); else - object_config.update_values_from_multi_to_single_2(print_options_with_variant); + object_config.update_values_from_multi_to_single_2(print_options_with_variant);*/ + object_config.update_values_from_multi_to_multi_2(current_print_extruder_variants, new_printer_extruder_variants, m_print_config, print_options_with_variant); object->config.assign_config(std::move(object_config)); } for (ModelVolume* v : object->volumes) { if (v->is_model_part() || v->is_modifier()) { DynamicPrintConfig volume_config = v->config.get(); if (!volume_config.empty()) { - if (current_extruder_count < new_extruder_count) + /* if (current_extruder_count < new_extruder_count) volume_config.update_values_from_single_to_multi_2(m_print_config, print_options_with_variant); else - volume_config.update_values_from_multi_to_single_2(print_options_with_variant); + volume_config.update_values_from_multi_to_single_2(print_options_with_variant);*/ + volume_config.update_values_from_multi_to_multi_2(current_print_extruder_variants, new_printer_extruder_variants, m_print_config, print_options_with_variant); v->config.assign_config(std::move(volume_config)); } } @@ -3670,10 +3852,11 @@ int CLI::run(int argc, char **argv) ModelConfig& layer_model_config = layer_config_it.second; DynamicPrintConfig layer_config = layer_model_config.get(); if (!layer_config.empty()) { - if (current_extruder_count < new_extruder_count) + /*if (current_extruder_count < new_extruder_count) layer_config.update_values_from_single_to_multi_2(m_print_config, print_options_with_variant); else - layer_config.update_values_from_multi_to_single_2(print_options_with_variant); + layer_config.update_values_from_multi_to_single_2(print_options_with_variant);*/ + layer_config.update_values_from_multi_to_multi_2(current_print_extruder_variants, new_printer_extruder_variants, m_print_config, print_options_with_variant); layer_model_config.assign_config(std::move(layer_config)); } } @@ -3755,6 +3938,19 @@ int CLI::run(int argc, char **argv) flush_and_exit(CLI_INVALID_VALUES_IN_3MF); } + ConfigOptionBool* enable_wrapping_detection_option = m_print_config.option("enable_wrapping_detection", true); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, remove_wrapping_detect %2%, old value %3%")%__LINE__ %remove_wrapping_detect %enable_wrapping_detection_option->value; + if (is_qdt_3mf && remove_wrapping_detect) { + enable_wrapping_detection_option->value = false; + } + enable_wrapping_detect = enable_wrapping_detection_option->value; + Pointfs current_wrapping_exclude_area = m_print_config.opt("wrapping_exclude_area", true)->values; + if (disable_wipe_tower_after_mapping && enable_wrapping_detect && !current_wrapping_exclude_area.empty()) + { + disable_wipe_tower_after_mapping = false; + BOOST_LOG_TRIVIAL(info) << boost::format("%1%, set disable_wipe_tower_after_mapping back to false due to wrapping detect")%__LINE__; + } + auto timelapse_type_opt = m_print_config.option("timelapse_type"); bool is_smooth_timelapse = false; if (enable_timelapse && timelapse_type_opt && (timelapse_type_opt->getInt() == TimelapseType::tlSmooth)) @@ -3802,6 +3998,8 @@ int CLI::run(int argc, char **argv) double height_to_lid = m_print_config.opt_float("extruder_clearance_height_to_lid"); double height_to_rod = m_print_config.opt_float("extruder_clearance_height_to_rod"); double cleareance_radius = m_print_config.opt_float("extruder_clearance_max_radius"); + double distance_to_rod = m_print_config.opt_float("extruder_clearance_dist_to_rod"); + int shared_printable_width = 0, shared_printable_depth = 0, shared_printable_height = 0, shared_center_x = 0, shared_center_y = 0; //double plate_stride; std::string bed_texture; @@ -3820,6 +4018,37 @@ int CLI::run(int argc, char **argv) old_printable_depth = current_printable_depth; if (old_printable_height == 0) old_printable_height = current_printable_height; + if ((current_extruder_areas.size() > 0) && (current_extruder_areas.size() == current_extruder_print_heights.size())) { + BoundingBox current_bbox({0, 0}, {current_printable_width, current_printable_depth}); + int temp_height = current_printable_height; + + for (unsigned int temp_index = 0; temp_index < current_extruder_areas.size(); temp_index++) + { + BoundingBox temp_bbox; + Pointfs& temp_extruder_shape = current_extruder_areas[temp_index]; + for (unsigned int temp_index2 = 0; temp_index2 < temp_extruder_shape.size(); temp_index2++) + temp_bbox.merge({temp_extruder_shape[temp_index2].x(), temp_extruder_shape[temp_index2].y()}); + + if (current_bbox.min.x() < temp_bbox.min.x()) + current_bbox.min.x() = temp_bbox.min.x(); + if (current_bbox.min.y() < temp_bbox.min.y()) + current_bbox.min.y() = temp_bbox.min.y(); + if (current_bbox.max.x() > temp_bbox.max.x()) + current_bbox.max.x() = temp_bbox.max.x(); + if (current_bbox.max.y() > temp_bbox.max.y()) + current_bbox.max.y() = temp_bbox.max.y(); + if ((int)(current_extruder_print_heights[temp_index]) < temp_height) + temp_height = current_extruder_print_heights[temp_index]; + } + shared_printable_width = current_bbox.size().x(); + shared_printable_depth = current_bbox.size().y(); + shared_printable_height = temp_height; + shared_center_x = current_bbox.center().x(); + shared_center_y = current_bbox.center().y(); + + BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: shared_printable_size {%2%, %3%, %4%}, shared_center {%5%, %6%}") + %__LINE__ %shared_printable_width %shared_printable_depth %shared_printable_height %shared_center_x %shared_center_y; + } if (is_qdt_3mf && (old_printable_width > 0) && (old_printable_depth > 0) && (old_printable_height > 0)) { //check the printable size logic @@ -3861,7 +4090,8 @@ int CLI::run(int argc, char **argv) else { partplate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, false); } - partplate_list.set_shapes(current_printable_area, current_exclude_area, current_extruder_areas, current_extruder_print_heights, bed_texture, height_to_lid, height_to_rod); + partplate_list.set_shapes(current_printable_area, current_exclude_area, current_wrapping_exclude_area, current_extruder_areas, current_extruder_print_heights, bed_texture, + height_to_lid, height_to_rod); //plate_stride = partplate_list.plate_stride_x(); } @@ -4017,7 +4247,10 @@ int CLI::run(int argc, char **argv) ConfigOptionFloats* volume_option = print_config.option("filament_prime_volume", true); std::vector wipe_volume = volume_option->values; - Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, get_max_element(wipe_volume), new_extruder_count, filaments_cnt); + const ConfigOptionBool * wrapping_detection = print_config.option("enable_wrapping_detection"); + bool enable_wrapping = (wrapping_detection != nullptr) && wrapping_detection->value; + + Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, get_max_element(wipe_volume), new_extruder_count, filaments_cnt, false, enable_wrapping); plate_obj_size_info.wipe_width = wipe_tower_size(0); plate_obj_size_info.wipe_depth = wipe_tower_size(1); @@ -4031,7 +4264,7 @@ int CLI::run(int argc, char **argv) %(plate_index+1) %start.x() % start.y() % start.z() %end.x() % end.y() % end.z(); }; - auto translate_models = [translate_old, shrink_to_new_bed, old_printable_width, old_printable_depth, old_printable_height, current_printable_width, current_printable_depth, current_printable_height, current_exclude_area, &plate_obj_size_infos] (Slic3r::GUI::PartPlateList& plate_list, DynamicPrintConfig& print_config) { + auto translate_models = [translate_old, shrink_to_new_bed, old_printable_width, old_printable_depth, old_printable_height, current_printable_width, current_printable_depth, current_printable_height, shared_center_x, shared_center_y, current_exclude_area, &plate_obj_size_infos] (Slic3r::GUI::PartPlateList& plate_list, DynamicPrintConfig& print_config) { //QDS: translate old 3mf to correct positions if (translate_old) { //translate the objects @@ -4088,10 +4321,24 @@ int CLI::run(int argc, char **argv) Vec3d new_center_offset { ((double)current_printable_width + exclude_width)/2, ((double)current_printable_depth + exclude_depth)/2, 0}; BoundingBoxf3& bbox = plate_obj_size_infos[index].obj_bbox; Vec3d size = bbox.size(); - if (size.x() > (current_printable_width - exclude_width)) - new_center_offset(0) = ((double)current_printable_width)/2; - if (size.y() > (current_printable_depth - exclude_depth)) - new_center_offset(1) = ((double)current_printable_depth)/2; + if (shared_center_x != 0) + new_center_offset(0) = (double)shared_center_x; + else if (exclude_width > 0) { + if (size.x() > (current_printable_width - exclude_width)) + new_center_offset(0) = ((double)current_printable_width)/2; + else if (size.x() <= (current_printable_width - exclude_width - DOWNWARD_CHECK_MARGIN)) + new_center_offset(0) = new_center_offset(0) - DOWNWARD_CHECK_MARGIN/2; + } + + if (shared_center_y != 0) + new_center_offset(1) = (double)shared_center_y; + else if (exclude_depth > 0) { + if (size.y() > (current_printable_depth - exclude_depth)) + new_center_offset(1) = ((double)current_printable_depth)/2; + else if (size.y() <= (current_printable_depth - exclude_depth - DOWNWARD_CHECK_MARGIN)) + new_center_offset(1) = new_center_offset(1) - DOWNWARD_CHECK_MARGIN/2; + } + Vec3d new_center = new_origin + new_center_offset; offset = new_center - bbox.center(); @@ -4175,12 +4422,18 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: loaded machine config %1%, from %2%")%config_name %file_path ; printer_plate_info_t printer_plate; - Pointfs temp_printable_area, temp_exclude_area; + Pointfs temp_printable_area, temp_exclude_area, temp_wrapping_area; + std::vector temp_extruder_areas; + std::vector temp_extruder_print_heights; printer_plate.printer_name = config_name; temp_printable_area = config.option("printable_area", true)->values; temp_exclude_area = config.option("bed_exclude_area", true)->values; + temp_wrapping_area = config.option("wrapping_exclude_area", true)->values; + temp_extruder_areas = config.option("extruder_printable_area", true)->values; + temp_extruder_print_heights = config.option("extruder_printable_height", true)->values; + if (temp_printable_area.size() >= 4) { printer_plate.printable_width = (int)(temp_printable_area[2].x() - temp_printable_area[0].x()); printer_plate.printable_depth = (int)(temp_printable_area[2].y() - temp_printable_area[0].y()); @@ -4192,9 +4445,45 @@ int CLI::run(int argc, char **argv) printer_plate.exclude_x = (int)temp_exclude_area[0].x(); printer_plate.exclude_y = (int)temp_exclude_area[0].y(); } - BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: printable size{%1%,%2%, %3%}, exclude area{%4%, %5%: %6% x %7%}") + if (temp_wrapping_area.size() >= 4) { + printer_plate.wrapping_width = (int)(temp_wrapping_area[2].x() - temp_wrapping_area[0].x()); + printer_plate.wrapping_depth = (int)(temp_wrapping_area[2].y() - temp_wrapping_area[0].y()); + printer_plate.wrapping_x = (int)temp_wrapping_area[0].x(); + printer_plate.wrapping_y = (int)temp_wrapping_area[0].y(); + } + if ((temp_extruder_areas.size() > 0) && (temp_extruder_print_heights.size() == temp_extruder_areas.size())) { + double temp_extruder_height = printer_plate.printable_height; + BoundingBox current_bbox({0, 0}, {printer_plate.printable_width, printer_plate.printable_depth}); + + for (unsigned int temp_index = 0; temp_index < temp_extruder_areas.size(); temp_index++) + { + BoundingBox temp_bbox; + Pointfs& temp_extruder_shape = temp_extruder_areas[temp_index]; + for (unsigned int temp_index2 = 0; temp_index2 < temp_extruder_shape.size(); temp_index2++) + temp_bbox.merge({temp_extruder_shape[temp_index2].x(), temp_extruder_shape[temp_index2].y()}); + + if (current_bbox.min.x() < temp_bbox.min.x()) + current_bbox.min.x() = temp_bbox.min.x(); + if (current_bbox.min.y() < temp_bbox.min.y()) + current_bbox.min.y() = temp_bbox.min.y(); + if (current_bbox.max.x() > temp_bbox.max.x()) + current_bbox.max.x() = temp_bbox.max.x(); + if (current_bbox.max.y() > temp_bbox.max.y()) + current_bbox.max.y() = temp_bbox.max.y(); + if (temp_extruder_height > temp_extruder_print_heights[temp_index]) + temp_extruder_height = temp_extruder_print_heights[temp_index]; + } + printer_plate.printable_width = current_bbox.size().x(); + printer_plate.printable_depth = current_bbox.size().y(); + printer_plate.printable_height = temp_extruder_height; + + BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: for multi-extruder printer, change printable size to bbox {%1%, %2%, 0} - {%3%, %4%, %5%}") + %current_bbox.min.x() %current_bbox.min.y() %current_bbox.max.x() %current_bbox.max.y() %temp_extruder_height; + } + BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: printable size{%1%,%2%, %3%}, exclude area{%4%, %5%: %6% x %7%}, wrapping area{%8%, %9%: %10% x %11%}, enable_wrapping_detect %12%") %printer_plate.printable_width %printer_plate.printable_depth %printer_plate.printable_height - %printer_plate.exclude_x %printer_plate.exclude_y %printer_plate.exclude_width %printer_plate.exclude_depth; + %printer_plate.exclude_x %printer_plate.exclude_y %printer_plate.exclude_width %printer_plate.exclude_depth + %printer_plate.wrapping_x %printer_plate.wrapping_y %printer_plate.wrapping_width %printer_plate.wrapping_depth %enable_wrapping_detect; if (config.option("extruder_clearance_height_to_lid")) printer_plate.height_to_lid = config.opt_float("extruder_clearance_height_to_lid"); @@ -4204,6 +4493,9 @@ int CLI::run(int argc, char **argv) if (config.option("extruder_clearance_max_radius")) printer_plate.cleareance_radius = config.opt_float("extruder_clearance_max_radius"); + + if (config.option("extruder_clearance_dist_to_rod")) + printer_plate.distance_to_rod = config.opt_float("extruder_clearance_dist_to_rod"); downward_check_printers.push_back(std::move(printer_plate)); } } @@ -4239,13 +4531,14 @@ int CLI::run(int argc, char **argv) printer_plate_info_t& plate_info = downward_check_printers[index2]; if (is_sequence) { - if ((plate_info.cleareance_radius > 0.f) && (plate_info.height_to_rod > 0.f) && (plate_info.height_to_lid > 0.f)) { + if ((plate_info.cleareance_radius > 0.f) && (plate_info.height_to_rod > 0.f) && (plate_info.height_to_lid > 0.f) && (plate_info.distance_to_rod > 0.f)) { if ((cleareance_radius < plate_info.cleareance_radius) || (height_to_rod > plate_info.height_to_rod) - || (height_to_lid > plate_info.height_to_lid)) + || (height_to_lid > plate_info.height_to_lid) + || (distance_to_rod < plate_info.distance_to_rod)) { - BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, sequence print, original clearance{%4%, %5%, %6%} exceeds new {%7%, %8%, %9%}") - %(index+1) %(index2+1) %plate_info.printer_name %cleareance_radius %height_to_rod %height_to_lid %plate_info.cleareance_radius %plate_info.height_to_rod %plate_info.height_to_lid; + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, sequence print, original clearance{%4%, %5%, %6% %7%} exceeds new {%8%, %9%, %10%, %11%}") + %(index+1) %(index2+1) %plate_info.printer_name %cleareance_radius %height_to_rod %height_to_lid %distance_to_rod %plate_info.cleareance_radius %plate_info.height_to_rod %plate_info.height_to_lid %plate_info.distance_to_rod; downward_check_status[index2] = true; failed_count ++; continue; @@ -4270,7 +4563,11 @@ int CLI::run(int argc, char **argv) if (plate_info.exclude_width > 0) { int real_width = plate_info.printable_width - plate_info.exclude_width; int real_depth = plate_info.printable_depth - plate_info.exclude_depth; - if ((size.x() > real_width) && (size.y() > real_depth)) { + if (has_support && (old_printable_width > real_width) && (old_printable_depth > real_depth) && (old_exclude_area.empty())) { + real_width -= DOWNWARD_CHECK_MARGIN; + real_depth -= DOWNWARD_CHECK_MARGIN; + } + if ((size.x() > real_width) || (size.y() > real_depth)) { BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%} exceeds real size without exclude_area {%6%, %7%}") %(index+1) %(index2+1) %plate_info.printer_name %size.x() % size.y() %real_width %real_depth; @@ -4279,6 +4576,18 @@ int CLI::run(int argc, char **argv) continue; } } + if (enable_wrapping_detect && plate_info.wrapping_width > 0) { + //int real_width = plate_info.printable_width - plate_info.wrapping_width; + int real_depth = plate_info.printable_depth - plate_info.wrapping_depth; + if ( size.y() > real_depth) { + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%} exceeds real size without wrapping_area {%6%, %7%}") + %(index+1) %(index2+1) %plate_info.printer_name + %size.x() % size.y() %plate_info.printable_width %real_depth; + downward_check_status[index2] = true; + failed_count ++; + continue; + } + } } } @@ -4294,7 +4603,7 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: found compatible printer %1%")%plate_info.printer_name; } } - BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: downward_check_size %1%, failed_count %2%")%downward_check_size %failed_count; + BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%, downward_check: downward_check_size %2%, failed_count %3%")%__LINE__ %downward_check_size %failed_count; sliced_info.downward_machines = downward_compatible_machines; for(std::vector::iterator it = sliced_info.upward_machines.begin(); it != sliced_info.upward_machines.end();){ @@ -4683,12 +4992,13 @@ int CLI::run(int argc, char **argv) { if (((old_height_to_rod != 0.f) && (old_height_to_rod != height_to_rod)) || ((old_height_to_lid != 0.f) && (old_height_to_lid != height_to_lid)) - || ((old_max_radius != 0.f) && (old_max_radius != cleareance_radius))) + || ((old_max_radius != 0.f) && (old_max_radius != cleareance_radius)) + || ((old_distance_to_rod != 0.f) && (old_distance_to_rod != distance_to_rod))) { if (is_seq_print_for_curr_plate) { need_arrange = true; - BOOST_LOG_TRIVIAL(info) << boost::format("old_height_to_rod %1%, old_height_to_lid %2%, old_max_radius %3%, current height_to_rod %4%, height_to_lid %5%, cleareance_radius %6%, need arrange!") - %old_height_to_rod %old_height_to_lid %old_max_radius %height_to_rod %height_to_lid %cleareance_radius; + BOOST_LOG_TRIVIAL(info) << boost::format("old_height_to_rod %1%, old_height_to_lid %2%, old_max_radius %3%, old_distance_to_rod %4%, current height_to_rod %5%, height_to_lid %6%, cleareance_radius %7%, distance_to_rod %8%, need arrange!") + %old_height_to_rod %old_height_to_lid %old_max_radius %old_distance_to_rod %height_to_rod %height_to_lid %cleareance_radius %distance_to_rod; } } } @@ -4780,7 +5090,7 @@ int CLI::run(int argc, char **argv) } } - if (!arrange_cfg.is_seq_print && assemble_plate.filaments_count > 1) + if (!arrange_cfg.is_seq_print && (assemble_plate.filaments_count > 1)||(enable_wrapping_detect && !current_wrapping_exclude_area.empty())) { //prepare the wipe tower int plate_count = partplate_list.get_plate_count(); @@ -4833,7 +5143,7 @@ int CLI::run(int argc, char **argv) } // add the virtual object into unselect list if has - partplate_list.preprocess_exclude_areas(unselected, i + 1); + partplate_list.preprocess_exclude_areas(unselected, enable_wrapping_detect, i + 1); if (avoid_extrusion_cali_region) partplate_list.preprocess_nonprefered_areas(unselected, i + 1); @@ -4860,7 +5170,7 @@ int CLI::run(int argc, char **argv) beds = get_shrink_bedpts(m_print_config, arrange_cfg); - partplate_list.preprocess_exclude_areas(arrange_cfg.excluded_regions, 1, scale_(1)); + partplate_list.preprocess_exclude_areas(arrange_cfg.excluded_regions, enable_wrapping_detect, 1, scale_(1)); { BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << beds[0].transpose() << ", " << beds[1].transpose() << ", " << beds[2].transpose() << ", " << beds[3].transpose(); @@ -5069,7 +5379,7 @@ int CLI::run(int argc, char **argv) } //add the virtual object into unselect list if has - partplate_list.preprocess_exclude_areas(unselected); + partplate_list.preprocess_exclude_areas(unselected, enable_wrapping_detect); if (used_filament_set.size() > 0) { @@ -5202,7 +5512,7 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange: slice filaments info invalid or need_skip, get from partplate: filament_count %1%")%filaments_cnt; } - if ((filaments_cnt <= 1) && !is_smooth_timelapse) + if ((filaments_cnt <= 1) && !is_smooth_timelapse && (!enable_wrapping_detect || current_wrapping_exclude_area.empty())) { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("arrange: not a multi-color object anymore, drop the wipe tower before arrange."); } @@ -5215,7 +5525,10 @@ int CLI::run(int argc, char **argv) //float depth = v * (filaments_cnt - 1) / (layer_height * w); - Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, get_max_element(v), new_extruder_count, filaments_cnt); + const ConfigOptionBool *wrapping_detection = m_print_config.option("enable_wrapping_detection"); + bool enable_wrapping = (wrapping_detection != nullptr) && wrapping_detection->value; + + Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, get_max_element(v), new_extruder_count, filaments_cnt, false, enable_wrapping); Vec3d plate_origin = cur_plate->get_origin(); int plate_width, plate_depth, plate_height; partplate_list.get_plate_size(plate_width, plate_depth, plate_height); @@ -5278,7 +5591,7 @@ int CLI::run(int argc, char **argv) } // add the virtual object into unselect list if has - partplate_list.preprocess_exclude_areas(unselected, plate_to_slice); + partplate_list.preprocess_exclude_areas(unselected, enable_wrapping_detect, plate_to_slice); } @@ -5305,7 +5618,7 @@ int CLI::run(int argc, char **argv) beds=get_shrink_bedpts(m_print_config, arrange_cfg); - partplate_list.preprocess_exclude_areas(arrange_cfg.excluded_regions, 1, scale_(1)); + partplate_list.preprocess_exclude_areas(arrange_cfg.excluded_regions, enable_wrapping_detect, 1, scale_(1)); { BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << beds[0].transpose() << ", " << beds[1].transpose() << ", " << beds[2].transpose() << ", " << beds[3].transpose(); @@ -6149,6 +6462,16 @@ int CLI::run(int argc, char **argv) //BOOST_LOG_TRIVIAL(info) << boost::format("print_volume {%1%,%2%,%3%}->{%4%, %5%, %6%}, has %7% printables") % print_volume.min(0) % print_volume.min(1) // % print_volume.min(2) % print_volume.max(0) % print_volume.max(1) % print_volume.max(2) % count << std::endl; #endif + if (is_qdt_3mf && !no_check && load_filament_count == 0) + { + //set filament_prime_volume to 45 when uploading + ConfigOptionFloats *filament_prime_volume_option = m_print_config.option("filament_prime_volume"); + int temp_count = filament_prime_volume_option->values.size(); + for (int temp_index = 0; temp_index < temp_count; temp_index++) + { + filament_prime_volume_option->values[temp_index] = 45.f; + } + } DynamicPrintConfig new_print_config = m_print_config; new_print_config.apply(*part_plate->config()); new_print_config.apply(m_extra_config, true); @@ -6200,6 +6523,12 @@ int CLI::run(int argc, char **argv) for (int index = 0; index < filament_count; index++) final_filament_maps[index] = 1; } + if(!new_print_config.has("nozzle_volume_type")) { + //set default nozzle_volume_type + ConfigOptionEnumsGeneric* final_nozzle_volume_type_opt = new_print_config.option("nozzle_volume_type", true); + final_nozzle_volume_type_opt->values.resize(new_extruder_count, nvtStandard); + } + print->apply(model, new_print_config); BOOST_LOG_TRIVIAL(info) << boost::format("set no_check to %1%:")%no_check; print->set_no_check_flag(no_check);//QDS @@ -6398,16 +6727,27 @@ int CLI::run(int argc, char **argv) else { if (!opengl_valid) opengl_valid = init_opengl_and_colors(model, colors); - outfile = print_fff->export_gcode(outfile, gcode_result, cli_generate_thumbnails); + outfile = opengl_valid ? print_fff->export_gcode(outfile, gcode_result, cli_generate_thumbnails) : print_fff->export_gcode(outfile, gcode_result, nullptr); } slice_time[TIME_USING_CACHE] = slice_time[TIME_USING_CACHE] + ((long long)Slic3r::Utils::get_current_milliseconds_time_utc() - temp_time); BOOST_LOG_TRIVIAL(info) << "export_gcode finished: time_using_cache update to " << slice_time[TIME_USING_CACHE] << " secs."; if (gcode_result && gcode_result->gcode_check_result.error_code) { + BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode unprintable! gcode_result->gcode_check_result.error_code = " + << gcode_result->gcode_check_result.error_code << std::endl; //found gcode error - BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of multi extruder printers!" << std::endl; - record_exit_reson(outfile_dir, CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, index + 1, cli_errors[CLI_GCODE_PATH_IN_UNPRINTABLE_AREA], sliced_info); - flush_and_exit(CLI_GCODE_PATH_IN_UNPRINTABLE_AREA); + if (gcode_result->gcode_check_result.error_code & 0b1100) { + record_exit_reson(outfile_dir, CLI_GCODE_PATH_OUTSIDE, index + 1, cli_errors[CLI_GCODE_PATH_OUTSIDE], sliced_info); + flush_and_exit(CLI_GCODE_PATH_OUTSIDE); + } + else if (gcode_result->gcode_check_result.error_code & 0b10000) { + record_exit_reson(outfile_dir, CLI_GCODE_IN_WRAPPING_DETECT_AREA, index + 1, cli_errors[CLI_GCODE_IN_WRAPPING_DETECT_AREA], sliced_info); + flush_and_exit(CLI_GCODE_IN_WRAPPING_DETECT_AREA); + } + else if (gcode_result->gcode_check_result.error_code & 0b00011) { + record_exit_reson(outfile_dir, CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, index + 1, cli_errors[CLI_GCODE_PATH_IN_UNPRINTABLE_AREA], sliced_info); + flush_and_exit(CLI_GCODE_PATH_IN_UNPRINTABLE_AREA); + } } if (gcode_result && gcode_result->filament_printable_reuslt.has_value()) { @@ -7744,10 +8084,10 @@ extern "C" { //QDS: register default exception handler #if QDT_RELEASE_TO_PUBLIC - SET_DEFULTER_HANDLER(); + //SET_DEFULTER_HANDLER(); #else //AddVectoredExceptionHandler(1, CBaseException::UnhandledExceptionFilter); - SET_DEFULTER_HANDLER(); + //SET_DEFULTER_HANDLER(); #endif std::set_new_handler([]() { int *a = nullptr; diff --git a/src/QIDIStudio.hpp b/src/QIDIStudio.hpp index 6156b16..b618f1c 100644 --- a/src/QIDIStudio.hpp +++ b/src/QIDIStudio.hpp @@ -17,6 +17,8 @@ namespace IO { }; } +#define DOWNWARD_CHECK_MARGIN 10 + #define JSON_ASSEMPLE_PLATES "plates" #define JSON_ASSEMPLE_PLATE_PARAMS "plate_params" #define JSON_ASSEMPLE_PLATE_NAME "plate_name" @@ -87,10 +89,16 @@ typedef struct _printer_plate_info { int exclude_depth{0}; int exclude_x{0}; int exclude_y{0}; - //1.9.7.52 + + int wrapping_width{0}; + int wrapping_depth{0}; + int wrapping_x{0}; + int wrapping_y{0}; + float height_to_lid{0.f}; float height_to_rod{0.f}; float cleareance_radius{0.f}; + float distance_to_rod{0.f}; }printer_plate_info_t; typedef struct _plate_obj_size_info { diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 6699c60..639abb7 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -34,6 +34,8 @@ set(SLIC3R_GUI_SOURCES GUI/Widgets/PopupWindow.hpp GUI/Widgets/Label.cpp GUI/Widgets/Label.hpp + GUI/Widgets/LinkLabel.cpp + GUI/Widgets/LinkLabel.hpp GUI/Widgets/Scrollbar.cpp GUI/Widgets/Scrollbar.hpp GUI/Widgets/ScrolledWindow.cpp @@ -346,8 +348,12 @@ set(SLIC3R_GUI_SOURCES GUI/PlateSettingsDialog.hpp GUI/ImGuiWrapper.hpp GUI/ImGuiWrapper.cpp + GUI/ImageMessageDialog.hpp + GUI/ImageMessageDialog.cpp GUI/DeviceManager.hpp GUI/DeviceManager.cpp + GUI/DeviceErrorDialog.hpp + GUI/DeviceErrorDialog.cpp GUI/UserManager.hpp GUI/UserManager.cpp GUI/HttpServer.hpp @@ -587,10 +593,13 @@ set(SLIC3R_GUI_SOURCES Utils/FontUtils.hpp Utils/WxFontUtils.hpp Utils/WxFontUtils.cpp + Utils/HelioDragon.cpp + Utils/HelioDragon.hpp GUI/Filament_web.hpp GUI/Filament_web.cpp ) +add_subdirectory(GUI/DeviceCore) add_subdirectory(GUI/DeviceTab) if(QDT_RELEASE_TO_PUBLIC) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index d05bae4..cca8956 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1747,7 +1747,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip //shader->set_uniform("print_volume.z_data", m_render_volume.zs); if (printable_heights) { std::array extruder_printable_heights; - if ((*printable_heights).size() > 0) { + if ((*printable_heights).size() > 1) { extruder_printable_heights[0] = 2.0f; extruder_printable_heights[1] = (*printable_heights)[0]; extruder_printable_heights[2] = (*printable_heights)[1]; diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index ce57f69..9be77da 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -11,6 +11,14 @@ #include "../Utils/ColorSpaceConvert.hpp" #include "EncodedFilament.hpp" +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevExtruderSystem.h" +#include "DeviceCore/DevFilaBlackList.h" +#include "DeviceCore/DevFilaSystem.h" + +#define FILAMENT_MAX_TEMP 300 +#define FILAMENT_MIN_TEMP 120 + namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent); @@ -534,7 +542,7 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) { select_index_info.tray_id = tray_id; select_index_info.ams_id = ams_id; select_index_info.slot_id = slot_id; - select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + select_index_info.nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); select_index_info.cali_idx = -1; select_index_info.filament_id = selected_ams_id; CalibUtils::select_PA_calib_result(select_index_info); @@ -571,7 +579,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) if (vendor && (vendor->values.size() > 0)) { std::string vendor_name = vendor->values[0]; - DeviceManager::check_filaments_in_blacklist(obj->printer_type, vendor_name, filamnt_type, it->filament_id, ams_id, slot_id, it->name, in_blacklist, action, info); + DevFilaBlacklist::check_filaments_in_blacklist(obj->printer_type, vendor_name, filamnt_type, it->filament_id, ams_id, slot_id, it->name, in_blacklist, action, info); } if (in_blacklist) { @@ -659,7 +667,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) select_index_info.tray_id = vt_tray; select_index_info.ams_id = ams_id; select_index_info.slot_id = 0; - select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + select_index_info.nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); auto cali_select_id = m_comboBox_cali_result->GetSelection(); if (m_pa_profile_items.size() > 0 && cali_select_id >= 0) { @@ -700,7 +708,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) select_index_info.tray_id = cali_tray_id; select_index_info.ams_id = ams_id; select_index_info.slot_id = slot_id; - select_index_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + select_index_info.nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); auto cali_select_id = m_comboBox_cali_result->GetSelection(); if (m_pa_profile_items.size() > 0 && cali_select_id > 0) { @@ -784,14 +792,7 @@ void AMSMaterialsSetting::on_clr_picker(wxMouseEvent &event) } std::vector ams_colors; - for (auto ams_it = obj->amsList.begin(); ams_it != obj->amsList.end(); ++ams_it) { - for (auto tray_id = ams_it->second->trayList.begin(); tray_id != ams_it->second->trayList.end(); ++tray_id) { - std::vector::iterator iter = find(ams_colors.begin(), ams_colors.end(), AmsTray::decode_color(tray_id->second->color)); - if (iter == ams_colors.end()) { - ams_colors.push_back(AmsTray::decode_color(tray_id->second->color)); - } - } - } + obj->GetFilaSystem()->CollectAmsColors(ams_colors); wxPoint img_pos = m_clr_picker->ClientToScreen(wxPoint(0, 0)); wxPoint popup_pos(img_pos.x - m_color_picker_popup.GetSize().x - FromDIP(95), img_pos.y - FromDIP(65)); @@ -882,9 +883,9 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi std::set filament_id_set; PresetBundle * preset_bundle = wxGetApp().preset_bundle; std::ostringstream stream; - stream << std::fixed << std::setprecision(1) << obj->m_extder_data.extders[0].current_nozzle_diameter; + stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(0); std::string nozzle_diameter_str = stream.str(); - std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), nozzle_diameter_str); + std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str); if (preset_bundle) { BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size(); @@ -1121,9 +1122,9 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) if (preset_bundle) { std::ostringstream stream; if (obj) - stream << std::fixed << std::setprecision(1) << obj->m_extder_data.extders[0].current_nozzle_diameter; + stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(0); std::string nozzle_diameter_str = stream.str(); - std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), + std::set printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str); for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) { if (!m_comboBox_filament->GetValue().IsEmpty()) { @@ -1241,13 +1242,13 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) }; int extruder_id = obj->get_extruder_id_by_ams_id(std::to_string(ams_id)); - if (obj->is_nozzle_flow_type_supported() && (obj->get_nozzle_flow_type(extruder_id) == NozzleFlowType::NONE_FLOWTYPE)) + if (obj->is_nozzle_flow_type_supported() && (obj->GetExtderSystem()->GetNozzleFlowType(extruder_id) == NozzleFlowType::NONE_FLOWTYPE)) { MessageDialog dlg(nullptr, _L("The nozzle flow is not set. Please set the nozzle flow rate before editing the filament.\n'Device -> Print parts'"), _L("Warning"), wxICON_WARNING | wxOK); dlg.ShowModal(); } - NozzleFlowType nozzle_flow_type = obj->get_nozzle_flow_type(extruder_id); + NozzleFlowType nozzle_flow_type = obj->GetExtderSystem()->GetNozzleFlowType(extruder_id); NozzleVolumeType nozzle_volume_type = NozzleVolumeType::nvtStandard; if (nozzle_flow_type != NozzleFlowType::NONE_FLOWTYPE) { @@ -1259,7 +1260,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) PACalibResult default_item; default_item.cali_idx = -1; default_item.filament_id = ams_filament_id; - if (obj->is_support_auto_flow_calibration) { + if (obj->GetConfig()->SupportCalibrationPA_FlowAuto()) { default_item.k_value = -1; default_item.n_coef = -1; } @@ -1301,21 +1302,20 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt) } else { if (from_printer && (*from_printer == 1)) { - if (this->obj->amsList.find(std::to_string(ams_id)) != this->obj->amsList.end()) { - Ams* selected_ams = this->obj->amsList[std::to_string(ams_id)]; - if (!selected_ams) - return; - AmsTray* selected_tray = selected_ams->trayList[std::to_string(slot_id)]; - if (!selected_tray) - return; - cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, selected_tray->cali_idx); - if (cali_select_idx < 0) { - BOOST_LOG_TRIVIAL(info) << "extrusion_cali_status_error: cannot find pa profile, ams_id = " << ams_id - << ", slot_id = " << slot_id << ", cali_idx = " << selected_tray->cali_idx; - cali_select_idx = 0; - } - m_comboBox_cali_result->SetSelection(cali_select_idx); + DevAmsTray* selected_tray = this->obj->GetFilaSystem()->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id)); + if (!selected_tray) + { + return; } + + cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, selected_tray->cali_idx); + if (cali_select_idx < 0) + { + BOOST_LOG_TRIVIAL(info) << "extrusion_cali_status_error: cannot find pa profile, ams_id = " << ams_id + << ", slot_id = " << slot_id << ", cali_idx = " << selected_tray->cali_idx; + cali_select_idx = 0; + } + m_comboBox_cali_result->SetSelection(cali_select_idx); } else { int index = get_cali_index(m_comboBox_filament->GetLabel().ToStdString()); diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index 9174062..7128586 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -23,6 +23,8 @@ #include "BitmapCache.hpp" #include "BindDialog.hpp" +#include "DeviceCore/DevFilaSystem.h" + namespace Slic3r { namespace GUI { #define MATERIAL_ITEM_SIZE wxSize(FromDIP(65), FromDIP(50)) #define MATERIAL_REC_WHEEL_SIZE wxSize(FromDIP(17), FromDIP(16)) @@ -227,15 +229,23 @@ void MaterialItem::render(wxDC &dc) auto material_txt_size = dc.GetTextExtent(m_material_name); dc.DrawText(m_material_name, wxPoint((GetSize().x - material_txt_size.x) / 2, ((float)GetSize().y * 2 / 5 - material_txt_size.y) / 2)); - - auto mapping_txt_size = dc.GetTextExtent(mapping_txt); - dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(0x26, 0x2E, 0x30))); dc.SetFont(::Label::Head_12); - m_text_pos_y =((float)GetSize().y * 3 / 5 - mapping_txt_size.y) / 2 + (float)GetSize().y * 2 / 5; + + auto mapping_txt_size = wxSize(0, 0); + if (mapping_txt.size() >= 4) { + mapping_txt.insert(mapping_txt.size() / 2, "\n"); + mapping_txt_size = dc.GetTextExtent(mapping_txt); + m_text_pos_y = ((float) GetSize().y * 3 / 5 - mapping_txt_size.y) / 2 + (float) GetSize().y * 2 / 5 - mapping_txt_size.y / 2; + m_text_pos_x = mapping_txt_size.x / 4; + } else { + mapping_txt_size = dc.GetTextExtent(mapping_txt); + m_text_pos_y = ((float) GetSize().y * 3 / 5 - mapping_txt_size.y) / 2 + (float) GetSize().y * 2 / 5; + m_text_pos_x = 0; + } if (m_match) { - dc.DrawText(mapping_txt, wxPoint(GetSize().x / 2 + (GetSize().x / 2 - mapping_txt_size.x) / 2 - FromDIP(8) - FromDIP(LEFT_OFFSET), m_text_pos_y)); + dc.DrawText(mapping_txt, wxPoint(GetSize().x / 2 + (GetSize().x / 2 - mapping_txt_size.x) / 2 - FromDIP(8) - FromDIP(LEFT_OFFSET) + m_text_pos_x, m_text_pos_y)); } } @@ -1028,12 +1038,12 @@ void AmsMapingPopup::update_items_check_state(const std::vector& a void AmsMapingPopup::update(MachineObject* obj, const std::vector& ams_mapping_result) { - //BOOST_LOG_TRIVIAL(info) << "ams_mapping nozzle count " << obj->m_extder_data.nozzle.size(); - BOOST_LOG_TRIVIAL(info) << "ams_mapping total count " << obj->amsList.size(); + //BOOST_LOG_TRIVIAL(info) << "ams_mapping nozzle count " << obj->get_extder_system()->nozzle.size(); + BOOST_LOG_TRIVIAL(info) << "ams_mapping total count " << ams_mapping_result.size(); - if (!obj) {return;} - m_ams_remain_detect_flag = obj->ams_calibrate_remain_flag; + // if (!obj) {return;} + // m_ams_remain_detect_flag = obj->GetFilaSystem()->IsDetectRemainEnabled(); for (auto& ams_container : m_amsmapping_container_list) { ams_container->Destroy(); @@ -1059,7 +1069,7 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& //size_t nozzle_nums = full_config.option("nozzle_diameter")->values.size(); //y59 - //size_t nozzle_nums = obj->m_extder_data.total_extder_count; + //size_t nozzle_nums = obj->GetExtderSystem()->GetTotalExtderCount(); size_t nozzle_nums = 1; if (nozzle_nums == 1) { @@ -1140,13 +1150,12 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& // //else { // td.type = NORMAL; // // td.remain = tray_data->remain; - // td.colour = AmsTray::decode_color((filament_colors[i].erase(0, 1)) + "FF"); + // td.colour = DevAmsTray::decode_color(tray_data->color); // td.name = filament_type[i]; // td.filament_type = filament_type[i]; // td.ctype = TrayType::NORMAL; // for (int j = 0; j < 4 * box_count; j++) { - // td.material_cols.push_back(AmsTray::decode_color((filament_colors[i].erase(0, 1)) + "FF")); - // } + // td.material_cols.push_back(DevAmsTray::decode_color(col)); // //} // //if (obj->vt_slot[i].id == std::to_string(VIRTUAL_TRAY_MAIN_ID)) { @@ -1200,19 +1209,16 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& td.type = NORMAL; td.remain = 0; std::string color = filament_colors[i]; - td.colour = AmsTray::decode_color((color.erase(0, 1)) + "FF"); + td.colour = DevAmsTray::decode_color((color.erase(0, 1)) + "FF"); td.name = filament_type[i]; td.filament_type = filament_type[i]; td.ctype = TrayType::NORMAL; - //for (int j = 0; j < 4 * box_count; j++) { - // td.material_cols.push_back(AmsTray::decode_color((filament_colors[i].erase(0, 1)) + "FF")); - //} tray_datas.push_back(td); } ams_mapping_item_container->Show(); - add_ams_mapping(tray_datas, obj->ams_calibrate_remain_flag, ams_mapping_item_container, sizer_mapping_list); + add_ams_mapping(tray_datas, false, ams_mapping_item_container, sizer_mapping_list); m_amsmapping_container_sizer_list.push_back(sizer_mapping_list); m_amsmapping_container_list.push_back(ams_mapping_item_container); @@ -1253,7 +1259,7 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& td.type = NORMAL; td.remain = 0; std::string color = filament_colors.back(); - td.colour = AmsTray::decode_color((color.erase(0, 1)) + "FF"); + td.colour = DevAmsTray::decode_color((color.erase(0, 1)) + "FF"); td.name = filament_type.back(); td.filament_type = filament_type.back(); td.ctype = TrayType::NORMAL; @@ -1274,22 +1280,22 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& Refresh(); } -std::vector AmsMapingPopup::parse_ams_mapping(std::map amsList) +std::vector AmsMapingPopup::parse_ams_mapping(std::map amsList) { std::vector m_tray_data; - std::map::iterator ams_iter; + std::map::iterator ams_iter; for (ams_iter = amsList.begin(); ams_iter != amsList.end(); ams_iter++) { BOOST_LOG_TRIVIAL(trace) << "ams_mapping ams id " << ams_iter->first.c_str(); auto ams_indx = atoi(ams_iter->first.c_str()); - Ams* ams_group = ams_iter->second; + DevAms* ams_group = ams_iter->second; std::vector tray_datas; - std::map::iterator tray_iter; + std::map::const_iterator tray_iter; - for (tray_iter = ams_group->trayList.begin(); tray_iter != ams_group->trayList.end(); tray_iter++) { - AmsTray* tray_data = tray_iter->second; + for (tray_iter = ams_group->GetTrays().cbegin(); tray_iter != ams_group->GetTrays().cend(); tray_iter++) { + DevAmsTray* tray_data = tray_iter->second; TrayData td; td.id = ams_indx * AMS_TOTAL_COUNT + atoi(tray_data->id.c_str()); @@ -1304,7 +1310,7 @@ std::vector AmsMapingPopup::parse_ams_mapping(std::mapremain; - td.colour = AmsTray::decode_color(tray_data->color); + td.colour = DevAmsTray::decode_color(tray_data->color); td.name = tray_data->get_display_filament_type(); td.filament_type = tray_data->get_filament_type(); } @@ -1392,7 +1398,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, tray_data.colour, tray_data.name, false, tray_data, true); + item->set_data(m_tag_material, m_ext_mapping_filatype_check ? wxColour(0xEE, 0xEE, 0xEE) : tray_data.colour, tray_data.name, false, tray_data, true); m_has_unmatch_filament = true; } @@ -1578,6 +1584,9 @@ void MappingItem::render(wxDC &dc) top += txt_size.y + FromDIP(2); m_name.size() > 4 ? dc.SetFont(::Label::Body_9) : dc.SetFont(::Label::Body_12); + if(m_name.size() > 5){ + m_name = m_name.substr(0,5) + "..."; + } txt_size = dc.GetTextExtent(m_name); dc.DrawText(m_name, wxPoint((GetSize().x - txt_size.x) / 2, top)); } @@ -1843,30 +1852,43 @@ AmsHumidityTipPopup::AmsHumidityTipPopup(wxWindow* parent) wxGetApp().UpdateDarkUIWin(this); } +void AmsHumidityTipPopup::set_humidity_level(int level) +{ + if (0 < level && level < 6) + { + current_humidity_level = level; + std::string mode_string = wxGetApp().dark_mode() ? "_dark" : "_light"; + curr_humidity_img->SetBitmap(create_scaled_bitmap("hum_level" + std::to_string(current_humidity_level) + mode_string, this, 132)); + curr_humidity_img->Refresh(); + curr_humidity_img->Update(); + } +} + +void AmsHumidityTipPopup::msw_rescale() +{ + // close image + close_img.msw_rescale(); + + // current humidity level image + if (0 < current_humidity_level && current_humidity_level < 6) + { + std::string mode_string = wxGetApp().dark_mode() ? "_dark" : "_light"; + curr_humidity_img->SetBitmap(create_scaled_bitmap("hum_level" + std::to_string(current_humidity_level) + mode_string, this, 132)); + } + + // the list + humidity_level_list->msw_rescale(); + + // refresh + Refresh(); +} + void AmsHumidityTipPopup::paintEvent(wxPaintEvent& evt) { wxPaintDC dc(this); render(dc); } -void AmsHumidityTipPopup::OnDismiss() {} - -bool AmsHumidityTipPopup::ProcessLeftDown(wxMouseEvent& event) { - return PopupWindow::ProcessLeftDown(event); -} - -void AmsHumidityTipPopup::set_humidity_level(int level) -{ - current_humidity_level = level; - if (current_humidity_level<= 0) {return;} - - std::string mode_string = wxGetApp().dark_mode()?"_dark":"_light"; - - curr_humidity_img->SetBitmap(create_scaled_bitmap("hum_level" + std::to_string(current_humidity_level) + mode_string, this, 132)); - curr_humidity_img->Refresh(); - curr_humidity_img->Update(); -} - void AmsHumidityTipPopup::render(wxDC& dc) { #ifdef __WXMSW__ @@ -1899,6 +1921,8 @@ void AmsHumidityTipPopup::doRender(wxDC& dc) dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); } + + AmsTutorialPopup::AmsTutorialPopup(wxWindow* parent) :PopupWindow(parent, wxBORDER_NONE) { @@ -2262,7 +2286,7 @@ void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj) if (obj) { m_obj = obj; - if (obj->m_extder_data.total_extder_count > 1) + if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) { m_nozzle_btn_panel->updateState("right"); m_nozzle_btn_panel->Show(); @@ -2272,7 +2296,7 @@ void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj) m_nozzle_btn_panel->Hide(); } - update_to_nozzle(MAIN_NOZZLE_ID); + update_to_nozzle(MAIN_EXTRUDER_ID); } } @@ -2325,7 +2349,7 @@ void AmsReplaceMaterialDialog::update_to_nozzle(int nozzle_id) return; } - if (m_obj->m_extder_data.extders.size() < nozzle_id) + if (m_obj->GetExtderSystem()->GetTotalExtderCount() < nozzle_id) { return; } @@ -2333,38 +2357,40 @@ void AmsReplaceMaterialDialog::update_to_nozzle(int nozzle_id) //update group int group_index = 0; m_groups_sizer->Clear(true); - if (m_obj->is_support_filament_backup && m_obj->ams_auto_switch_filament_flag) + if (m_obj->is_support_filament_backup && m_obj->GetFilaSystem()->IsAutoRefillEnabled()) { // traverse the amd list - std::unordered_map id2tray;// tray id to tray + std::unordered_map id2tray;// tray id to tray try { - for (const auto& ams_info : m_obj->amsList) + for (const auto& ams_info : m_obj->GetFilaSystem()->GetAmsList()) { int ams_device_id = atoi(ams_info.first.c_str()); if (ams_device_id < 128) { int ams_base_id = ams_device_id * 4; - for (auto tray_info : ams_info.second->trayList) + for (auto tray_info : ams_info.second->GetTrays()) { int tray_offset = atoi(tray_info.first.c_str()); id2tray[ams_base_id + tray_offset] = tray_info.second; } } - else if (ams_info.second->trayList.size() == 1)/*n3f*/ + else if (ams_info.second->GetTrays().size() == 1)/*n3f*/ { - id2tray[ams_device_id] = ams_info.second->trayList.begin()->second; + id2tray[ams_device_id] = ams_info.second->GetTrays().begin()->second; } } } catch (...) {} - const Extder& extder = m_obj->m_extder_data.extders[nozzle_id]; - for (int filam : extder.filam_bak) + const auto& extder = m_obj->GetExtderSystem()->GetExtderById(nozzle_id); + if (extder) { - std::map group_info; - std::string group_material; - bool is_in_tray = false; + for (int filam : extder->GetFilamBackup()) + { + std::map group_info; + std::string group_material; + bool is_in_tray = false; //get color & material const auto& trayid_group = _GetBackupStatus(filam); @@ -2372,31 +2398,32 @@ void AmsReplaceMaterialDialog::update_to_nozzle(int nozzle_id) { if (elem.second) { - AmsTray* cur_tray = id2tray[elem.first]; + DevAmsTray* cur_tray = id2tray[elem.first]; if (cur_tray) { - auto tray_name = wxGetApp().transition_tridid(elem.first, elem.first > 127).ToStdString(); + auto tray_name = wxGetApp().transition_tridid(elem.first).ToStdString(); auto it = std::find(m_tray_used.begin(), m_tray_used.end(), tray_name); if (it != m_tray_used.end()) { is_in_tray = true; } - group_info[tray_name] = AmsTray::decode_color(cur_tray->color); - group_material = cur_tray->get_display_filament_type(); + group_info[tray_name] = DevAmsTray::decode_color(cur_tray->color); + group_material = cur_tray->get_display_filament_type(); + } } } - } - if (group_info.size() < 2) /* do not show refill if there is one tray*/ - { - continue; - } + if (group_info.size() < 2) /* do not show refill if there is one tray*/ + { + continue; + } - if (is_in_tray || m_tray_used.size() <= 0) - { - m_groups_sizer->Add(create_backup_group(wxString::Format("%s%d", _L("Group"), group_index + 1), group_info, group_material), 0, wxALL, FromDIP(10)); - group_index++; + if (is_in_tray || m_tray_used.size() <= 0) + { + m_groups_sizer->Add(create_backup_group(wxString::Format("%s%d", _L("Group"), group_index + 1), group_info, group_material), 0, wxALL, FromDIP(10)); + group_index++; + } } } } @@ -2434,7 +2461,7 @@ void AmsReplaceMaterialDialog::update_to_nozzle(int nozzle_id) { label_txt->SetLabel(_L("The printer does not currently support auto refill.")); } - else if (!m_obj->ams_auto_switch_filament_flag) + else if (!m_obj->GetFilaSystem()->IsAutoRefillEnabled()) { label_txt->SetLabelText(_L("BOX filament backup is not enabled, please enable it in the BOX settings.")); } @@ -2702,7 +2729,19 @@ AmsHumidityLevelList::AmsHumidityLevelList(wxWindow* parent) void AmsHumidityLevelList::msw_rescale() { + background_img.msw_rescale(); + for (int i = 0; i < hum_level_img_light.size(); i++) + { + hum_level_img_light[i].msw_rescale(); + } + + for (int i = 0; i < hum_level_img_dark.size(); i++) + { + hum_level_img_dark[i].msw_rescale(); + } + + Refresh(); } void AmsHumidityLevelList::paintEvent(wxPaintEvent& evt) diff --git a/src/slic3r/GUI/AmsMappingPopup.hpp b/src/slic3r/GUI/AmsMappingPopup.hpp index 3f22f9b..53ce92c 100644 --- a/src/slic3r/GUI/AmsMappingPopup.hpp +++ b/src/slic3r/GUI/AmsMappingPopup.hpp @@ -75,6 +75,7 @@ struct TrayData class MaterialItem: public wxPanel { protected: + int m_text_pos_x = 0; int m_text_pos_y = -1; bool m_dropdown_allow_painted = true; @@ -276,7 +277,7 @@ public: void paintEvent(wxPaintEvent &evt); void set_parent_item(MaterialItem* item) {m_parent_item = item;}; void set_show_type(ShowType type) { m_show_type = type; }; - std::vector parse_ams_mapping(std::map amsList); + std::vector parse_ams_mapping(std::map amsList); using ResetCallback = std::function; void reset_ams_info(); @@ -323,25 +324,18 @@ public: AmsHumidityLevelList(wxWindow* parent); ~AmsHumidityLevelList() {}; - ScalableBitmap background_img; - ScalableBitmap hum_level1_img; - ScalableBitmap hum_level2_img; - ScalableBitmap hum_level3_img; - ScalableBitmap hum_level4_img; - - std::vector hum_level_img_light; - std::vector hum_level_img_dark; - - wxStaticBitmap* hum_level1_bitmap; - wxStaticBitmap* hum_level2_bitmap; - wxStaticBitmap* hum_level3_bitmap; - wxStaticBitmap* hum_level4_bitmap; - wxStaticBitmap* hum_level5_bitmap; - +public: void msw_rescale(); + +private: void paintEvent(wxPaintEvent& evt); void render(wxDC& dc); void doRender(wxDC& dc); + +private: + ScalableBitmap background_img; + std::vector hum_level_img_light; + std::vector hum_level_img_dark; }; class AmsHumidityTipPopup : public PopupWindow @@ -349,24 +343,31 @@ class AmsHumidityTipPopup : public PopupWindow public: AmsHumidityTipPopup(wxWindow* parent); ~AmsHumidityTipPopup() {}; - void paintEvent(wxPaintEvent& evt); - - virtual void OnDismiss() wxOVERRIDE; - virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE; +public: void set_humidity_level(int level); + void msw_rescale(); + +private: + virtual void OnDismiss() wxOVERRIDE {}; + virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE { return PopupWindow::ProcessLeftDown(event); }; + + void paintEvent(wxPaintEvent& evt); void render(wxDC& dc); void doRender(wxDC& dc); -public: +private: int current_humidity_level = 0; ScalableBitmap close_img; + wxStaticBitmap* curr_humidity_img; - AmsHumidityLevelList* humidity_level_list{nullptr}; wxStaticBitmap* m_img; + Label* m_staticText;; Label* m_staticText_note; + + AmsHumidityLevelList* humidity_level_list{nullptr}; }; class AmsTutorialPopup : public PopupWindow diff --git a/src/slic3r/GUI/AmsWidgets.cpp b/src/slic3r/GUI/AmsWidgets.cpp index 14a5210..4e6b686 100644 --- a/src/slic3r/GUI/AmsWidgets.cpp +++ b/src/slic3r/GUI/AmsWidgets.cpp @@ -10,6 +10,7 @@ #include "Widgets/Label.hpp" #include "format.hpp" +#include "DeviceCore/DevFilaSystem.h" namespace Slic3r { namespace GUI { @@ -139,16 +140,19 @@ void TrayListModel::update(MachineObject* obj) m_saturabilityColValues.clear(); m_transmittanceColValues.clear(); - std::map::iterator ams_it; - std::map::iterator tray_it; + std::map::iterator ams_it; + std::map::const_iterator tray_it; int tray_index = 0; - for (ams_it = obj->amsList.begin(); ams_it != obj->amsList.end(); ams_it++) { + + const auto& ams_list = obj->GetFilaSystem()->GetAmsList(); + for (auto ams_it = ams_list.begin(); ams_it != ams_list.end(); ams_it++) + { if (ams_it->second) { - for (tray_it = ams_it->second->trayList.begin(); tray_it != ams_it->second->trayList.end(); tray_it++) { - AmsTray* tray = tray_it->second; + for (tray_it = ams_it->second->GetTrays().cbegin(); tray_it != ams_it->second->GetTrays().cend(); tray_it++) { + DevAmsTray* tray = tray_it->second; if (tray) { tray_index++; - wxString title_text = wxString::Format("tray %s(ams %s)", tray->id, ams_it->second->id); + wxString title_text = wxString::Format("tray %s(ams %s)", tray->id, ams_it->second->GetAmsId()); m_titleColValues.push_back(title_text); wxString color_text = wxString::Format("%s", tray->wx_color.GetAsString()); m_colorColValues.push_back(color_text); diff --git a/src/slic3r/GUI/Auxiliary.cpp b/src/slic3r/GUI/Auxiliary.cpp index 8220eb7..c9103a4 100644 --- a/src/slic3r/GUI/Auxiliary.cpp +++ b/src/slic3r/GUI/Auxiliary.cpp @@ -996,7 +996,7 @@ void AuxiliaryPanel::Reload(wxString aux_path) try { fs::remove_all(fs::path(m_root_dir.ToStdWstring())); } catch (...) { - BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str(); + BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << PathSanitizer::sanitize(m_root_dir.ToUTF8().data()); } m_root_dir = aux_path; diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 604bfe5..22664dc 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -24,6 +24,20 @@ class DynamicPrintConfig; class Model; class SLAPrint; +class HelioCompletionEvent : public wxEvent +{ +public: + HelioCompletionEvent(wxEventType eventType, int winid, std::string in_simulated_path, std::string in_tmp_path, bool in_is_successful, std::string in_error_message = "") + : wxEvent(winid, eventType), tmp_path(in_tmp_path), simulated_path(in_simulated_path), is_successful(in_is_successful), error_message(in_error_message) + {} + virtual wxEvent *Clone() const { return new HelioCompletionEvent(*this); } + + std::string tmp_path; + std::string simulated_path; + bool is_successful; + std::string error_message; +}; + class SlicingStatusEvent : public wxEvent { public: diff --git a/src/slic3r/GUI/BindDialog.cpp b/src/slic3r/GUI/BindDialog.cpp index 407d59d..9f8e357 100644 --- a/src/slic3r/GUI/BindDialog.cpp +++ b/src/slic3r/GUI/BindDialog.cpp @@ -16,6 +16,8 @@ #include "Plater.hpp" #include "Widgets/WebView.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -844,7 +846,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { EndModal(wxID_OK); MessageDialog msg_wingow(nullptr, _L("Log in successful."), "", wxAPPLY | wxOK); msg_wingow.ShowModal(); - if(m_machine_info) wxGetApp().on_start_subscribe_again(m_machine_info->dev_id); + if(m_machine_info) wxGetApp().on_start_subscribe_again(m_machine_info->get_dev_id()); } void BindMachineDialog::on_bind_printer(wxCommandEvent &event) @@ -860,7 +862,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { if (m_machine_info == nullptr || m_machine_info == NULL) return; //check dev_id - if (m_machine_info->dev_id.empty()) return; + if (m_machine_info->get_dev_id().empty()) return; // update ota version NetworkAgent* agent = wxGetApp().getAgent(); @@ -869,7 +871,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_simplebook->SetSelection(0); m_bind_job = std::make_shared(m_status_bar, wxGetApp().plater(), - m_machine_info->dev_id, m_machine_info->dev_ip, m_machine_info->bind_sec_link, m_machine_info->bind_ssdp_version); + m_machine_info->get_dev_id(), m_machine_info->get_dev_ip(), m_machine_info->bind_sec_link, m_machine_info->bind_ssdp_version); if (m_machine_info && (m_machine_info->get_printer_series() == PrinterSeries::SERIES_X1)) { m_bind_job->set_improved(false); @@ -919,7 +921,7 @@ void BindMachineDialog::on_show(wxShowEvent &event) m_printer_img->Refresh(); m_printer_img->Show(); - m_printer_name->SetLabelText(from_u8(m_machine_info->dev_name)); + m_printer_name->SetLabelText(from_u8(m_machine_info->get_dev_name())); if (wxGetApp().is_user_login()) { wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickanme()); @@ -1100,16 +1102,16 @@ void UnBindMachineDialog::on_unbind_printer(wxCommandEvent &event) } m_machine_info->set_access_code(""); - int result = wxGetApp().request_user_unbind(m_machine_info->dev_id); + int result = wxGetApp().request_user_unbind(m_machine_info->get_dev_id()); if (result == 0) { DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; // clean local machine access code info - MachineObject* obj = dev->get_local_machine(m_machine_info->dev_id); + MachineObject* obj = dev->get_local_machine(m_machine_info->get_dev_id()); if (obj) { obj->set_access_code(""); } - dev->erase_user_machine(m_machine_info->dev_id); + dev->erase_user_machine(m_machine_info->get_dev_id()); m_status_text->SetLabelText(_L("Log out successful.")); m_button_cancel->SetLabel(_L("Close")); @@ -1139,7 +1141,7 @@ void UnBindMachineDialog::on_show(wxShowEvent &event) m_printer_img->Refresh(); m_printer_img->Show(); - m_printer_name->SetLabelText(from_u8(m_machine_info->dev_name)); + m_printer_name->SetLabelText(from_u8(m_machine_info->get_dev_name())); if (wxGetApp().is_user_login()) { diff --git a/src/slic3r/GUI/CaliHistoryDialog.cpp b/src/slic3r/GUI/CaliHistoryDialog.cpp index 4340ace..51b1ebf 100644 --- a/src/slic3r/GUI/CaliHistoryDialog.cpp +++ b/src/slic3r/GUI/CaliHistoryDialog.cpp @@ -8,6 +8,9 @@ #include "MsgDialog.hpp" #include "slic3r/Utils/CalibUtils.hpp" +#include "DeviceCore/DevExtruderSystem.h" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -15,7 +18,7 @@ namespace GUI { #define HISTORY_WINDOW_SIZE wxSize(FromDIP(700), FromDIP(600)) #define EDIT_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(160), FromDIP(24)) #define NEW_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(250), FromDIP(24)) -#define HISTORY_WINDOW_ITEMS_COUNT 5 +#define HISTORY_WINDOW_ITEMS_COUNT 6 enum CaliColumnType : int { Cali_Name = 0, @@ -225,7 +228,7 @@ void HistoryWindow::on_device_connected(MachineObject* obj) int selection = 1; for (int i = 0; i < nozzle_diameter_list.size(); i++) { m_comboBox_nozzle_dia->AppendString(wxString::Format("%1.1f mm", nozzle_diameter_list[i])); - if (abs(curr_obj->m_extder_data.extders[0].current_nozzle_diameter - nozzle_diameter_list[i]) < 1e-3) { + if (abs(curr_obj->GetExtderSystem()->GetNozzleDiameter(0) - nozzle_diameter_list[i]) < 1e-3) { selection = i; } } @@ -378,7 +381,8 @@ void HistoryWindow::sync_history_data() { delete_button->Bind(wxEVT_BUTTON, [this, gbSizer, i, &result](auto& e) { for (int j = 0; j < HISTORY_WINDOW_ITEMS_COUNT; j++) { auto item = gbSizer->FindItemAtPosition({ i, j }); - item->GetWindow()->Hide(); + if (item) + item->GetWindow()->Hide(); } gbSizer->SetEmptyCellSize({ 0,0 }); m_history_data_panel->Layout(); @@ -658,7 +662,7 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject std::set filament_id_set; std::set printer_names; std::ostringstream stream; - stream << std::fixed << std::setprecision(1) << obj->m_extder_data.extders[0].current_nozzle_diameter; + stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(0); std::string nozzle_diameter_str = stream.str(); for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) { @@ -672,7 +676,7 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject continue; // use printer_model as printer type - if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type)) + if (printer_model_str->value != DevPrinterConfigUtil::get_printer_display_name(obj->printer_type)) continue; if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) @@ -802,7 +806,7 @@ NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const static std::array nozzle_diameter_list = {0.2f, 0.4f, 0.6f, 0.8f}; for (int i = 0; i < nozzle_diameter_list.size(); i++) { m_comboBox_nozzle_diameter->AppendString(wxString::Format("%1.1f mm", nozzle_diameter_list[i])); - if (abs(obj->m_extder_data.extders[0].current_nozzle_diameter - nozzle_diameter_list[i]) < 1e-3) { + if (abs(obj->GetExtderSystem()->GetNozzleDiameter(0) - nozzle_diameter_list[i]) < 1e-3) { m_comboBox_nozzle_diameter->SetSelection(i); } } diff --git a/src/slic3r/GUI/Calibration.cpp b/src/slic3r/GUI/Calibration.cpp index c911316..cea2e5f 100644 --- a/src/slic3r/GUI/Calibration.cpp +++ b/src/slic3r/GUI/Calibration.cpp @@ -11,6 +11,8 @@ #include "Widgets/RoundedRectangle.hpp" #include "Widgets/StaticBox.hpp" +#include "DeviceCore/DevConfig.h" + static wxColour FG_COLOR = wxColour(0x32, 0x3A, 0x3D); static wxColour BG_COLOR = wxColour(0xF8, 0xF8, 0xF8); @@ -216,7 +218,8 @@ wxWindow* CalibrationDialog::create_check_option(wxString title, wxWindow* paren void CalibrationDialog::update_cali(MachineObject *obj) { if (!obj) return; - if (obj->is_support_ai_monitoring && obj->is_support_lidar_calibration) { + if (obj->GetConfig()->SupportAIMonitor() && obj->GetConfig()->SupportCalibrationLidar()) + { select_xcam_cali->Show(); } else { select_xcam_cali->Hide(); @@ -237,19 +240,16 @@ void CalibrationDialog::update_cali(MachineObject *obj) m_checkbox_list["motor_noise"]->SetValue(false); } - if (obj->is_support_nozzle_offset_cali) { + if (obj->GetConfig()->SupportCalibrationNozzleOffset()) { select_nozzle_cali->Show(); } else { select_nozzle_cali->Hide(); m_checkbox_list["nozzle_cali"]->SetValue(false); } - if (obj->is_support_high_tempbed_cali) - { + if (obj->GetConfig()->SupportCalibrationHighTempBed()) { select_heatbed_cali->Show(); - } - else - { + } else { select_heatbed_cali->Hide(); m_checkbox_list["bed_cali"]->SetValue(false); } @@ -279,7 +279,7 @@ void CalibrationDialog::update_cali(MachineObject *obj) // change items if stage_list_info changed m_calibration_flow->DeleteAllItems(); for (int i = 0; i < obj->stage_list_info.size(); i++) { - m_calibration_flow->AppendItem(get_stage_string(obj->stage_list_info[i])); + m_calibration_flow->AppendItem(Slic3r::get_stage_string(obj->stage_list_info[i])); } } int index = obj->get_curr_stage_idx(); diff --git a/src/slic3r/GUI/CalibrationPanel.cpp b/src/slic3r/GUI/CalibrationPanel.cpp index 2a53061..1ce1a99 100644 --- a/src/slic3r/GUI/CalibrationPanel.cpp +++ b/src/slic3r/GUI/CalibrationPanel.cpp @@ -267,7 +267,7 @@ bool CalibrationPanel::Show(bool show) { dev->load_last_machine(); obj = dev->get_selected_machine(); if (obj) - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } else { obj->reset_update_time(); diff --git a/src/slic3r/GUI/CalibrationWizard.hpp b/src/slic3r/GUI/CalibrationWizard.hpp index f9a3571..99e32ca 100644 --- a/src/slic3r/GUI/CalibrationWizard.hpp +++ b/src/slic3r/GUI/CalibrationWizard.hpp @@ -79,8 +79,6 @@ protected: /* save steps of calibration pages */ std::vector m_page_steps; - - SecondaryCheckDialog *go_home_dialog = nullptr; }; class PressureAdvanceWizard : public CalibrationWizard { diff --git a/src/slic3r/GUI/CameraPopup.cpp b/src/slic3r/GUI/CameraPopup.cpp index ce3ee48..4c6f4d2 100644 --- a/src/slic3r/GUI/CameraPopup.cpp +++ b/src/slic3r/GUI/CameraPopup.cpp @@ -10,6 +10,9 @@ #include "GUI_App.hpp" #include +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevStorage.h" + namespace Slic3r { namespace GUI { @@ -154,7 +157,7 @@ void CameraPopup::sdcard_absent_hint() void CameraPopup::on_switch_recording(wxCommandEvent& event) { if (!m_obj) return; - if (m_obj->sdcard_state != MachineObject::SdcardState::HAS_SDCARD_NORMAL) { + if (m_obj->GetStorage()->get_sdcard_state() != DevStorage::SdcardState::HAS_SDCARD_NORMAL) { sdcard_absent_hint(); return; } diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index bbef7df..4dc7d00 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -129,7 +129,7 @@ void ConfigManipulation::check_filament_max_volumetric_speed(DynamicPrintConfig float max_volumetric_speed = config->has("filament_max_volumetric_speed") ? config->opt_float_nullable("filament_max_volumetric_speed", (float) 0.5) : 0.5; // QDS: limite the min max_volumetric_speed - if (max_volumetric_speed < 0.5) { + if (max_volumetric_speed < 0.5 && wxGetApp().initialized()) { const wxString msg_text = _(L("Too small max volumetric speed.\nReset to 0.5")); MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK); DynamicPrintConfig new_conf = *config; @@ -142,6 +142,35 @@ void ConfigManipulation::check_filament_max_volumetric_speed(DynamicPrintConfig } +void ConfigManipulation::check_filament_scarf_setting(DynamicPrintConfig *config) +{ + bool post_warning = false; + float layer_height = wxGetApp().preset_bundle->prints.get_selected_preset().config.opt_float("layer_height"); + DynamicPrintConfig new_conf = *config; + //std::vector new_data = config->option("filament_scarf_height")->values; + for (size_t i = 0; i < config->option("filament_scarf_height")->size(); i++) { + double value = config->option("filament_scarf_height")->values[i].get_abs_value(1); + bool reset = false; + if (config->option("filament_scarf_height")->values[i].percent) { + if (value >= 1) + reset = true; + } else if (value > layer_height) + reset = true; + if (reset && wxGetApp().initialized()) { + post_warning = true; + new_conf.set_key_value("filament_scarf_height", new ConfigOptionFloatsOrPercents{FloatOrPercent(10, true)}); + } + + } + if (post_warning) { + const wxString msg_text = _(L("Should not large than 100%.\nReset to defualt")); + MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK); + is_msg_dlg_already_exist = true; + dialog.ShowModal(); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } +} void ConfigManipulation::check_chamber_temperature(DynamicPrintConfig* config) { const static std::maprecommend_temp_map = { @@ -364,7 +393,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con config->opt_enum("ensure_vertical_shell_thickness") == EnsureVerticalThicknessLevel::evtEnabled && !config->opt_bool("detect_thin_wall") && config->opt_enum("timelapse_type") == TimelapseType::tlTraditional && - !config->opt_bool("z_direction_outwall_speed_continuous"))) + !config->opt_bool("z_direction_outwall_speed_continuous") && + !config->opt_bool("enable_wrapping_detection"))) { DynamicPrintConfig new_conf = *config; auto answer = show_spiral_mode_settings_dialog(is_object_config); @@ -379,6 +409,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); new_conf.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); new_conf.set_key_value("z_direction_outwall_speed_continuous", new ConfigOptionBool(false)); + new_conf.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); sparse_infill_density = 0; timelapse_type = TimelapseType::tlTraditional; support = false; @@ -565,7 +596,12 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con if (opt != nullptr) { if (opt->getInt() > filament_cnt) { DynamicPrintConfig new_conf = *config; - new_conf.set_key_value(key, new ConfigOptionInt(0)); + const DynamicPrintConfig *conf_temp = wxGetApp().plater()->config(); + int new_value = 0; + if (conf_temp != nullptr && conf_temp->has(key)) { + new_value = conf_temp->opt_int(key); + } + new_conf.set_key_value(key, new ConfigOptionInt(new_value)); apply(config, &new_conf); } } @@ -846,6 +882,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in 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); + ConfigOptionPoints *wrapping_exclude_area_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option("wrapping_exclude_area"); + bool support_wrapping_detect = wrapping_exclude_area_opt &&wrapping_exclude_area_opt->values.size() > 3; + toggle_line("enable_wrapping_detection", support_wrapping_detect); + //w16 bool is_resonance_avoidance = config->opt_bool("resonance_avoidance", 0); toggle_line("min_resonance_avoidance_speed", is_resonance_avoidance); @@ -930,7 +970,7 @@ void ConfigManipulation::toggle_print_sla_options(DynamicPrintConfig* config) int ConfigManipulation::show_spiral_mode_settings_dialog(bool is_object_config) { - wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0, timelapse type is traditional and smoothing wall speed in z direction is false.")); + wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, clumping detection by probing is disabled, top shell layers is 0, sparse infill density is 0, timelapse type is traditional and smoothing wall speed in z direction is false.")); auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option>("printer_structure"); if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) { msg_text += _(L(" But machines with I3 structure will not generate timelapse videos.")); diff --git a/src/slic3r/GUI/ConfigManipulation.hpp b/src/slic3r/GUI/ConfigManipulation.hpp index b18e1df..45ecf34 100644 --- a/src/slic3r/GUI/ConfigManipulation.hpp +++ b/src/slic3r/GUI/ConfigManipulation.hpp @@ -78,6 +78,7 @@ public: void check_nozzle_temperature_range(DynamicPrintConfig* config); void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config); void check_filament_max_volumetric_speed(DynamicPrintConfig *config); + void check_filament_scarf_setting(DynamicPrintConfig *config); void check_chamber_temperature(DynamicPrintConfig* config); //58 void check_box_temperature(DynamicPrintConfig* config); diff --git a/src/slic3r/GUI/ConnectPrinter.cpp b/src/slic3r/GUI/ConnectPrinter.cpp index 5a2e72e..b8e444f 100644 --- a/src/slic3r/GUI/ConnectPrinter.cpp +++ b/src/slic3r/GUI/ConnectPrinter.cpp @@ -4,6 +4,8 @@ #include #include "libslic3r/AppConfig.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) : DPIDialog(parent, id, _L("ConnectPrinter(LAN)"), pos, size, style) @@ -119,7 +121,7 @@ void ConnectPrinterDialog::init_bitmap() std::string language = config->get("language"); if (m_obj) { - std::string img_str = DeviceManager::get_printer_diagram_img(m_obj->printer_type); + std::string img_str = DevPrinterConfigUtil::get_printer_connect_help_img(m_obj->printer_type); if(img_str.empty()){img_str = "input_access_code_x1"; } if (language == "zh_CN") { @@ -170,7 +172,7 @@ void ConnectPrinterDialog::on_input_enter(wxCommandEvent& evt) } -void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event) +void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event) { wxString code = m_textCtrl_code->GetTextCtrl()->GetValue(); for (char c : code) { @@ -181,9 +183,6 @@ void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event) } if (m_obj) { m_obj->set_user_access_code(code.ToStdString()); - if (m_need_connect) { - wxGetApp().getDeviceManager()->set_selected_machine(m_obj->dev_id); - } } EndModal(wxID_OK); } diff --git a/src/slic3r/GUI/ConnectPrinter.hpp b/src/slic3r/GUI/ConnectPrinter.hpp index d73a3ba..971c102 100644 --- a/src/slic3r/GUI/ConnectPrinter.hpp +++ b/src/slic3r/GUI/ConnectPrinter.hpp @@ -25,7 +25,6 @@ class ConnectPrinterDialog : public DPIDialog { private: protected: - bool m_need_connect{true}; wxStaticText * m_staticText_connection_code; TextInput * m_textCtrl_code; Button * m_button_confirm; @@ -46,12 +45,11 @@ public: ~ConnectPrinterDialog(); - void go_connect_printer(bool need) {m_need_connect = need;}; void end_modal(wxStandardID id); void init_bitmap(); void set_machine_object(MachineObject* obj); void on_input_enter(wxCommandEvent& evt); - void on_button_confirm(wxCommandEvent &event); + void on_button_confirm(wxCommandEvent &event); void on_dpi_changed(const wxRect &suggested_rect) override; }; }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/CreatePresetsDialog.cpp b/src/slic3r/GUI/CreatePresetsDialog.cpp index 635cc57..d7683c2 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.cpp +++ b/src/slic3r/GUI/CreatePresetsDialog.cpp @@ -556,7 +556,7 @@ static void adjust_dialog_in_screen(DPIDialog* dialog) { } CreateFilamentPresetDialog::CreateFilamentPresetDialog(wxWindow *parent) - : DPIDialog(parent ? parent : nullptr, wxID_ANY, _L("Create Filament"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxCENTRE) + : DPIDialog(parent ? parent : nullptr, wxID_ANY, _L("Create Filament"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxCENTRE | wxRESIZE_BORDER) { m_create_type.base_filament = _L("Create Based on Current Filament"); m_create_type.base_filament_preset = _L("Copy Current Filament Preset "); @@ -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(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)))); + m_scrolled_preset_panel->SetMinSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(100, height + FromDIP(18)))); + m_scrolled_preset_panel->SetMaxSize(wxSize(std::min(1400, width + FromDIP(26)), std::min(100, height + FromDIP(18)))); + m_scrolled_preset_panel->SetSize(wxSize(std::min(1500, width + FromDIP(26)), std::min(100, height + FromDIP(18)))); Layout(); Fit(); Refresh(); diff --git a/src/slic3r/GUI/DailyTips.cpp b/src/slic3r/GUI/DailyTips.cpp index 8fb44b2..207ac63 100644 --- a/src/slic3r/GUI/DailyTips.cpp +++ b/src/slic3r/GUI/DailyTips.cpp @@ -143,6 +143,21 @@ void DailyTipsDataRenderer::render_img(const ImVec2& start_pos, const ImVec2& si } } +bool has_cjk(const std::string &text) +{ + for (size_t i = 0; i < text.size() - 2; ++i) { + unsigned char c1 = text[i]; + unsigned char c2 = text[i + 1]; + unsigned char c3 = text[i + 2]; + + if ((c1 & 0xF0) == 0xE0 && (c2 & 0xC0) == 0x80 && (c3 & 0xC0) == 0x80) { + int codepoint = ((c1 & 0x0F) << 12 | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); + if (codepoint >= 0x3000 && codepoint <= 0x9FFF) { return true; } + } + } + return false; +} + void DailyTipsDataRenderer::render_text(const ImVec2& start_pos, const ImVec2& size) const { ImGuiWrapper& imgui = *wxGetApp().imgui(); @@ -157,16 +172,14 @@ void DailyTipsDataRenderer::render_text(const ImVec2& start_pos, const ImVec2& s title_line = m_data.main_text.substr(0, end_pos); title_line = ImGui::ColorMarkerStart + title_line + ImGui::ColorMarkerEnd; content_lines = m_data.main_text.substr(end_pos + 1); + } else { + content_lines = m_data.main_text; } ImGui::SetCursorPos(start_pos); imgui.text(title_line); - bool is_zh = false; - for (int i = 0; i < content_lines.size() - 1; i += 2) { - if ((content_lines[i] & 0x80) && (content_lines[i + 1] & 0x80)) - is_zh = true; - } + bool is_zh = has_cjk(content_lines); if (!is_zh) { // problem in Chinese with spaces ImGui::SetCursorPosX(start_pos.x); @@ -176,7 +189,11 @@ void DailyTipsDataRenderer::render_text(const ImVec2& start_pos, const ImVec2& s Label* wrapped_text = new Label(wxGetApp().GetTopWindow()); wrapped_text->Hide(); wrapped_text->SetLabelText(wxString::FromUTF8(content_lines)); - wrapped_text->Wrap(size.x + ImGui::CalcTextSize("A").x * 5.0f); + float wrap_width = size.x + ImGui::CalcTextSize("A").x * 5.0f; +#ifdef __APPLE__ + wrap_width /= 2.0f; +#endif + wrapped_text->Wrap(wrap_width); std::string wrapped_content_lines = wrapped_text->GetLabel().ToUTF8().data(); wrapped_text->Destroy(); ImGui::SetCursorPosX(start_pos.x); @@ -316,7 +333,7 @@ void DailyTipsPanel::render() void DailyTipsPanel::retrieve_data_from_hint_database(HintDataNavigation nav) { - HintData* hint_data = HintDatabase::get_instance().get_hint(nav); + HintData* hint_data = HintDatabase::get_instance().get_hint(nav, m_is_helio); if (hint_data != nullptr) { DailyTipsData data{ hint_data->text, @@ -351,6 +368,11 @@ bool DailyTipsPanel::is_expanded() return m_is_expanded; } +void DailyTipsPanel::set_is_helio(bool is_helio) +{ + m_is_helio = is_helio; +} + void DailyTipsPanel::on_change_color_mode(bool is_dark) { m_is_dark = is_dark; @@ -460,8 +482,8 @@ void DailyTipsPanel::render_controller_buttons(const ImVec2& pos, const ImVec2& } // page index - m_page_index = HintDatabase::get_instance().get_index() + 1; - m_pages_count = HintDatabase::get_instance().get_count(); + m_page_index = HintDatabase::get_instance().get_index(m_is_helio) + 1; + m_pages_count = HintDatabase::get_instance().get_count(m_is_helio); std::string text_str = std::to_string(m_page_index) + "/" + std::to_string(m_pages_count); float text_item_width = ImGui::CalcTextSize(text_str.c_str()).x; ImGui::PushItemWidth(text_item_width); diff --git a/src/slic3r/GUI/DailyTips.hpp b/src/slic3r/GUI/DailyTips.hpp index 508a8ad..eb8d349 100644 --- a/src/slic3r/GUI/DailyTips.hpp +++ b/src/slic3r/GUI/DailyTips.hpp @@ -29,6 +29,7 @@ public: void expand(bool expand = true); void collapse(); bool is_expanded(); + void set_is_helio(bool is_helio); void on_change_color_mode(bool is_dark); void set_fade_opacity(float opacity); @@ -49,6 +50,7 @@ private: float m_content_height; float m_footer_height; int m_uid; + bool m_is_helio{ false }; bool m_first_enter{ false }; bool m_is_dark{ false }; DailyTipsLayout m_layout{ DailyTipsLayout::Vertical }; diff --git a/src/slic3r/GUI/DeviceCore/CMakeLists.txt b/src/slic3r/GUI/DeviceCore/CMakeLists.txt new file mode 100644 index 0000000..caa2936 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/CMakeLists.txt @@ -0,0 +1,52 @@ +# GUI/DeviceCore +# usage -- none GUI structure about device +# date -- 2025.07.14 +# status -- Building + +list(APPEND SLIC3R_GUI_SOURCES + GUI/DeviceCore/DevBed.cpp + GUI/DeviceCore/DevBed.h + GUI/DeviceCore/DevConfig.h + GUI/DeviceCore/DevConfig.cpp + GUI/DeviceCore/DevConfigUtil.h + GUI/DeviceCore/DevConfigUtil.cpp + GUI/DeviceCore/DevCtrl.h + GUI/DeviceCore/DevCtrl.cpp + GUI/DeviceCore/DevDefs.h + GUI/DeviceCore/DevExtruderSystem.h + GUI/DeviceCore/DevExtruderSystem.cpp + GUI/DeviceCore/DevExtruderSystemCtrl.cpp + GUI/DeviceCore/DevFan.cpp + GUI/DeviceCore/DevFan.h + GUI/DeviceCore/DevFilaAmsSetting.h + GUI/DeviceCore/DevFilaAmsSetting.cpp + GUI/DeviceCore/DevFilaBlackList.h + GUI/DeviceCore/DevFilaBlackList.cpp + GUI/DeviceCore/DevFilaSystem.h + GUI/DeviceCore/DevFilaSystem.cpp + GUI/DeviceCore/DevFirmware.h + GUI/DeviceCore/DevFirmware.cpp + GUI/DeviceCore/DevPrintOptions.h + GUI/DeviceCore/DevPrintOptions.cpp + GUI/DeviceCore/DevPrintTaskInfo.h + GUI/DeviceCore/DevPrintTaskInfo.cpp + GUI/DeviceCore/DevHMS.h + GUI/DeviceCore/DevHMS.cpp + GUI/DeviceCore/DevStorage.h + GUI/DeviceCore/DevStorage.cpp + GUI/DeviceCore/DevInfo.h + GUI/DeviceCore/DevInfo.cpp + GUI/DeviceCore/DevLamp.h + GUI/DeviceCore/DevLamp.cpp + GUI/DeviceCore/DevLampCtrl.cpp + GUI/DeviceCore/DevManager.h + GUI/DeviceCore/DevManager.cpp + GUI/DeviceCore/DevMapping.h + GUI/DeviceCore/DevMapping.cpp + GUI/DeviceCore/DevNozzleSystem.h + GUI/DeviceCore/DevNozzleSystem.cpp + GUI/DeviceCore/DevUtil.h + GUI/DeviceCore/DevUtil.cpp + +) +set(SLIC3R_GUI_SOURCES ${SLIC3R_GUI_SOURCES} PARENT_SCOPE) \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevBed.cpp b/src/slic3r/GUI/DeviceCore/DevBed.cpp new file mode 100644 index 0000000..09fd553 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevBed.cpp @@ -0,0 +1,25 @@ +#include "DevBed.h" +#include "slic3r/GUI/DeviceManager.hpp" + +namespace Slic3r { + +void DevBed::ParseV1_0(const json &print_json, DevBed *system) +{ + if (print_json.contains("bed_temper")) { + if (print_json["bed_temper"].is_number()) { system->bed_temp = print_json["bed_temper"].get(); } + } + if (print_json.contains("bed_target_temper")) { + if (print_json["bed_target_temper"].is_number()) { system->bed_temp_target = print_json["bed_target_temper"].get(); } + } +} + +void DevBed::ParseV2_0(const json &print_json, DevBed *system) +{ + if (print_json.contains("bed_temp") && print_json["bed_temp"].is_number()) { + int bed_temp_bits = print_json["bed_temp"].get(); + system->bed_temp = system->m_owner->get_flag_bits(bed_temp_bits, 0, 16); + system->bed_temp_target = system->m_owner->get_flag_bits(bed_temp_bits, 16, 16); + } +} + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevBed.h b/src/slic3r/GUI/DeviceCore/DevBed.h new file mode 100644 index 0000000..dcdb698 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevBed.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" + +namespace Slic3r { + +class MachineObject; + +class DevBed +{ +public: + DevBed(MachineObject *obj) : m_owner(obj), bed_temp(0.0f), bed_temp_target(0.0f) {} + + float GetBedTemp() { return bed_temp; }; + float GetBedTempTarget() { return bed_temp_target; }; + +public: + + static void ParseV1_0(const json &print_json, DevBed *system); + static void ParseV2_0(const json &print_json, DevBed *system); + +private: + + float bed_temp; + float bed_temp_target; + + MachineObject* m_owner = nullptr; +}; + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevConfig.cpp b/src/slic3r/GUI/DeviceCore/DevConfig.cpp new file mode 100644 index 0000000..52d2871 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevConfig.cpp @@ -0,0 +1,54 @@ +#include + +#include "DevConfig.h" +#include "DevUtil.h" + +using namespace nlohmann; + +namespace Slic3r +{ + +void DevConfig::ParseConfig(const json& print_json) +{ + ParseChamberConfig(print_json); + ParsePrintOptionsConfig(print_json); + ParseCalibrationConfig(print_json); + +} + +void DevConfig::ParseChamberConfig(const json& print_json) +{ + DevJsonValParser::ParseVal(print_json, "support_chamber_temp_edit", m_support_chamber_edit); + if (m_support_chamber_edit) + { + if (print_json.contains("support_chamber_temp_edit_range")) + { + const auto &support_champer_range = print_json["support_chamber_temp_edit_range"]; + if (support_champer_range.is_array() && support_champer_range.size() > 1) { + m_chamber_temp_edit_min = support_champer_range[0]; + m_chamber_temp_edit_max = support_champer_range[1]; + } + } + + DevJsonValParser::ParseVal(print_json, "support_chamber_temp_switch_heating", m_chamber_temp_switch_heat); + } +} + +void DevConfig::ParsePrintOptionsConfig(const json& print_json) +{ + DevJsonValParser::ParseVal(print_json, "support_first_layer_inspect", m_support_first_layer_inspect); + DevJsonValParser::ParseVal(print_json, "support_save_remote_print_file_to_storage", m_support_save_remote_print_file_to_storage); + DevJsonValParser::ParseVal(print_json, "support_ai_monitoring", m_support_ai_monitor); + DevJsonValParser::ParseVal(print_json, "support_print_without_sd", m_support_print_without_sd); + DevJsonValParser::ParseVal(print_json, "support_print_all", m_support_print_all); +} + +void DevConfig::ParseCalibrationConfig(const json& print_json) +{ + DevJsonValParser::ParseVal(print_json, "support_lidar_calibration", m_support_calibration_lidar); + DevJsonValParser::ParseVal(print_json, "support_nozzle_offset_calibration", m_support_calibration_nozzle_offset); + DevJsonValParser::ParseVal(print_json, "support_high_tempbed_calibration", m_support_calibration_high_temp_bed); + DevJsonValParser::ParseVal(print_json, "support_auto_flow_calibration", m_support_calibration_pa_flow_auto); +} + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevConfig.h b/src/slic3r/GUI/DeviceCore/DevConfig.h new file mode 100644 index 0000000..29fd120 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevConfig.h @@ -0,0 +1,78 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include +#include + + +namespace Slic3r +{ + +//Previous definitions +class MachineObject; + + +class DevConfig +{ +public: + DevConfig(MachineObject* obj) : m_obj(obj) {}; + ~DevConfig() = default; + +public: + // chamber + bool SupportChamberEdit() const { return m_support_chamber_edit; } + int GetChamberTempEditMin() const { return m_chamber_temp_edit_min; } + int GetChamberTempEditMax() const { return m_chamber_temp_edit_max; } + int GetChamberTempSwitchHeat() const { return m_chamber_temp_switch_heat; } + + // print options + bool SupportFirstLayerInspect() const { return m_support_first_layer_inspect; } + bool SupportSaveRemotePrintFileToStorage() const { return m_support_save_remote_print_file_to_storage; } + bool SupportAIMonitor() const { return m_support_ai_monitor; } + + bool SupportPrintWithoutSD() const { return m_support_print_without_sd; } + bool SupportPrintAllPlates() const { return m_support_print_all; } + + // calibration options + bool SupportCalibrationLidar() const { return m_support_calibration_lidar; } + bool SupportCalibrationNozzleOffset() const { return m_support_calibration_nozzle_offset; } + bool SupportCalibrationHighTempBed() const { return m_support_calibration_high_temp_bed; } + + bool SupportCalibrationPA_FlowAuto() const { return m_support_calibration_pa_flow_auto; } + +public: + /*Setters*/ + void ParseConfig(const json& print_json); + + void ParseChamberConfig(const json& print_json); // chamber + void ParsePrintOptionsConfig(const json& print_json); // print options + void ParseCalibrationConfig(const json& print_json); //cali + +private: + MachineObject* m_obj; + + /*configure vals*/ + // chamber + bool m_support_chamber_edit = false; + int m_chamber_temp_edit_min = 0; + int m_chamber_temp_edit_max = 60; + int m_chamber_temp_switch_heat = std::numeric_limits::max(); /* the min temp to start heating, default to max */ + + // print options + bool m_support_first_layer_inspect = false; + bool m_support_save_remote_print_file_to_storage = false; + bool m_support_ai_monitor = false; + + bool m_support_print_without_sd = false; + bool m_support_print_all = false; + + // calibration options + bool m_support_calibration_lidar = false; + bool m_support_calibration_nozzle_offset = false; + bool m_support_calibration_high_temp_bed = false; // High-temperature Heatbed Calibration + + bool m_support_calibration_pa_flow_auto = false;// PA flow calibration. used in SendPrint +}; + +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevConfigUtil.cpp b/src/slic3r/GUI/DeviceCore/DevConfigUtil.cpp new file mode 100644 index 0000000..ae5e9df --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevConfigUtil.cpp @@ -0,0 +1,239 @@ +#include "DevConfigUtil.h" + +#include + +using namespace nlohmann; + +namespace Slic3r +{ + +std::string DevPrinterConfigUtil::m_resource_file_path = ""; + + +std::map DevPrinterConfigUtil::get_all_model_id_with_name() +{ + { + std::map models; + + wxDir dir(m_resource_file_path + "/printers/"); + if (!dir.IsOpened()) + { + return models; + } + + wxString filename; + std::vector m_files; + bool hasFile = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES); + while (hasFile) + { + m_files.push_back(filename); + hasFile = dir.GetNext(&filename); + } + + for (wxString file : m_files) + { + std::string config_file = m_resource_file_path + "/printers/" + file.ToStdString(); + 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"]; + + std::string model_id; + std::string display_name; + if (printer.contains("model_id")) { model_id = printer["model_id"].get(); } + if (printer.contains("display_name")) { display_name = printer["display_name"].get(); } + models[display_name] = model_id; + } + } + } + catch (...) {} + } + + return models; + } +} + +PrinterArch DevPrinterConfigUtil::get_printer_arch(std::string type_str) +{ + const std::string& arch_str = get_value_from_config(type_str, "printer_arch"); + if (arch_str == "i3") + { + return PrinterArch::ARCH_I3; + } + else if (arch_str == "core_xy") + { + return PrinterArch::ARCH_CORE_XY; + } + + return PrinterArch::ARCH_CORE_XY; +} + +std::string DevPrinterConfigUtil::get_printer_ext_img(const std::string& type_str, int pos) +{ + const auto& vec = get_value_from_config>(type_str, "printer_ext_image"); + return (vec.size() > pos) ? vec[pos] : std::string(); +}; + +std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, const std::string& key) +{ + std::vector filaments; + std::string config_file = m_resource_file_path + "/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 std::string(); +} + +std::string DevPrinterConfigUtil::get_fan_text(const std::string& type_str, int airduct_mode, int airduct_func, int submode) +{ + std::vector filaments; + std::string config_file = m_resource_file_path + "/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")) + { + return std::string(); + } + + json const& fan_item = printer["fan"]; + const auto& airduct_mode_str = std::to_string(airduct_mode); + if (!fan_item.contains(airduct_mode_str)) + { + return std::string(); + } + + json const& airduct_item = fan_item[airduct_mode_str]; + const auto& airduct_func_str = std::to_string(airduct_func); + if (airduct_item.contains(airduct_func_str)) + { + const auto& airduct_func_item = airduct_item[airduct_func_str]; + if (airduct_func_item.is_object()) + { + return airduct_func_item[std::to_string(submode)].get(); + } + else if (airduct_func_item.is_string()) + { + return airduct_func_item.get(); + } + } + } + } + } + catch (...) {} + return std::string(); +} + +std::map> DevPrinterConfigUtil::get_all_subseries(std::string type_str) +{ + std::vector m_files; + std::map> subseries; + +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": path= " << m_resource_file_path + "/printers/"; +#endif + + wxDir dir(m_resource_file_path + "/printers/"); + if (!dir.IsOpened()) { return subseries; } + + wxString filename; + bool hasFile = dir.GetFirst(&filename, "*.json", wxDIR_FILES); + while (hasFile) + { + m_files.push_back(filename); + hasFile = dir.GetNext(&filename); + } + + for (wxString file : m_files) + { + std::string config_file = m_resource_file_path + "/printers/" + file.ToStdString(); + 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("subseries")) + { + std::vector subs; + + std::string model_id = printer["model_id"].get(); + if (model_id == type_str || type_str.empty()) + { + for (auto res : printer["subseries"]) + { + subs.emplace_back(res.get()); + } + } + subseries.insert(make_pair(model_id, subs)); + } + } + } + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to load " << file; + } + } + +#if !QDT_RELEASE_TO_PUBLIC + wxString result_str; + for (auto item : subseries) + { + wxString item_str = item.first; + item_str += ": "; + for (auto to_item : item.second) + { + item_str += to_item; + item_str += " "; + } + + result_str += item_str + ", "; + } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": result= " << result_str; +#endif + + if (subseries.empty()) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": result= " << "empty"; + } + + return subseries; +} + +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevConfigUtil.h b/src/slic3r/GUI/DeviceCore/DevConfigUtil.h new file mode 100644 index 0000000..6add560 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevConfigUtil.h @@ -0,0 +1,175 @@ +/** +* @file DevConfigUtil.h +* @brief Parses configuration files and provides access to printer options. +* +* This class loads a configuration file and allows querying options by key. +* The configuration file format is expected to be key-value pairs (e.g., INI or simple text). +*/ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +#include + +#include "slic3r/GUI/DeviceCore/DevDefs.h" + +namespace Slic3r +{ + +class dePrinterConfigFactory +{ +public: + dePrinterConfigFactory() = default; + ~dePrinterConfigFactory() = default; +}; + + +class DevPrinterConfigUtil +{ +public: + DevPrinterConfigUtil() = default; + ~DevPrinterConfigUtil() = default; + +public: + static void InitFilePath(const std::string& res_file_path) { m_resource_file_path = res_file_path; }; + + /*printer*/ + // info + static std::map get_all_model_id_with_name(); + static std::string get_printer_type(const std::string& type_str) { return get_value_from_config(type_str, "printer_type"); } + static std::string get_printer_display_name(const std::string& type_str) { return get_value_from_config(type_str, "display_name"); } + static std::string get_printer_series_str(std::string type_str) { return get_value_from_config(type_str, "printer_series"); } + static PrinterArch get_printer_arch(std::string type_str); + + // images + static std::string get_printer_thumbnail_img(const std::string& type_str) { return get_value_from_config(type_str, "printer_thumbnail_image"); } + static std::string get_printer_connect_help_img(const std::string& type_str) { return get_value_from_config(type_str, "printer_connect_help_image"); } + static std::string get_printer_auto_pa_cali_image(const std::string& type_str) { return get_value_from_config(type_str, "auto_pa_cali_thumbnail_image"); } + + /*media*/ + static std::string get_ftp_folder(std::string type_str) { return get_value_from_config(type_str, "ftp_folder"); } + static std::vector get_resolution_supported(std::string type_str) { return get_value_from_config>(type_str, "camera_resolution"); } + static std::vector get_compatible_machine(std::string type_str) { return get_value_from_config>(type_str, "compatible_machine"); } + static std::map> get_all_subseries(std::string type_str = ""); + + /*ams*/ + static std::string get_printer_use_ams_type(std::string type_str) { return get_value_from_config(type_str, "use_ams_type"); } + static std::string get_printer_ams_img(const std::string& type_str) { return get_value_from_config(type_str, "printer_use_ams_image"); } + static std::string get_printer_ext_img(const std::string& type_str, int pos);//printer_ext_image + + /*fan*/ + static std::string get_fan_text(const std::string& type_str, const std::string& key); + static std::string get_fan_text(const std::string& type_str, int airduct_mode, int airduct_func, int submode); + + /*extruder*/ + static bool get_printer_can_set_nozzle(std::string type_str) { return get_value_from_config(type_str, "enable_set_nozzle_info"); }// can set nozzle from studio + + /*calibration*/ + static std::vector get_unsupport_auto_cali_filaments(std::string type_str) { return get_value_from_config>(type_str, "auto_cali_not_support_filaments"); } + + /*detection*/ + static bool support_wrapping_detection(const std::string& type_str) { return get_value_from_config(type_str, "support_wrapping_detection"); } + +public: + template + static T get_value_from_config(const std::string& type_str, const std::string& item) + { + std::string config_file = m_resource_file_path + "/printers/" + type_str + ".json"; + boost::nowide::ifstream json_file(config_file.c_str()); + try + { + nlohmann::json jj; + if (json_file.is_open()) + { + json_file >> jj; + if (jj.contains("00.00.00.00")) + { + nlohmann::json const& printer = jj["00.00.00.00"]; + if (printer.contains(item)) + { + return printer[item].get(); + } + } + } + } + catch (...) { assert(0 && "get_value_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors + return T(); + }; + + static nlohmann::json get_json_from_config(const std::string& type_str, const std::string& key1, const std::string& key2 = std::string()) + { + std::string config_file = m_resource_file_path + "/printers/" + type_str + ".json"; + boost::nowide::ifstream json_file(config_file.c_str()); + try + { + nlohmann::json jj; + if (json_file.is_open()) + { + json_file >> jj; + if (jj.contains("00.00.00.00")) + { + nlohmann::json const& printer = jj["00.00.00.00"]; + if (printer.contains(key1)) + { + nlohmann::json const& key1_item = printer[key1]; + if (key2.empty()) + { + return key1_item; + } + + if (key1_item.contains(key2)) + { + return key1_item[key2]; + } + } + } + } + } + catch (...) { assert(0 && "get_json_from_config failed"); BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed"; }// there are file errors + return nlohmann::json(); + } + +private: + static std::string m_resource_file_path; // Path to the configuration file +}; + +/*special transform*/ +static std::string _parse_printer_type(const std::string& type_str) +{ + if (type_str.compare("3DPrinter-X1") == 0) + { + return "BL-P002"; + } + else if (type_str.compare("3DPrinter-X1-Carbon") == 0) + { + return "BL-P001"; + } + else if (type_str.compare("BL-P001") == 0) + { + return type_str; + } + else if (type_str.compare("BL-P002") == 0) + { + return type_str; + } + else + { + std::string result = DevPrinterConfigUtil::get_printer_type(type_str); + if (!result.empty()) + { + return result; + } + } + + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " Unsupported printer type: " << type_str; + return type_str; +} + +};// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevCtrl.cpp b/src/slic3r/GUI/DeviceCore/DevCtrl.cpp new file mode 100644 index 0000000..e3a162a --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevCtrl.cpp @@ -0,0 +1,26 @@ +#include +#include "DevCtrl.h" + +// TODO: remove this include +#include "DevUtil.h" +#include "slic3r/GUI/DeviceManager.hpp" + +using namespace nlohmann; + +namespace Slic3r +{ + int DevCtrl::command_select_extruder(int id) + { + 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 = m_obj->publish_json(j, 1); + if (rtn == 0) + { + m_obj->targ_nozzle_id_from_pc = id; + } + + return rtn; + } +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevCtrl.h b/src/slic3r/GUI/DeviceCore/DevCtrl.h new file mode 100644 index 0000000..686ac0f --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevCtrl.h @@ -0,0 +1,26 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include + +namespace Slic3r +{ + +//Previous definitions +class MachineObject; + + +class DevCtrl +{ + MachineObject* m_obj; +public: + DevCtrl(MachineObject* obj) : m_obj(obj) {}; + ~DevCtrl() = default; + +public: + /*extruder system*/ + int command_select_extruder(int id); +}; + +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevDefs.h b/src/slic3r/GUI/DeviceCore/DevDefs.h new file mode 100644 index 0000000..468ed01 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevDefs.h @@ -0,0 +1,99 @@ +/** +* @file DevDefs.h +* @brief Common definitions, macros, and constants for printer modules. +* Enhance building and including. +* +* This file provides shared macros, constants, and enumerations for all printer-related +* modules, including printer types, status, binding states, connection types, and error codes. +* It is intended to be included wherever printer-specific definitions are required. +*/ + +#pragma once +#include + +enum PrinterArch +{ + ARCH_CORE_XY, + ARCH_I3, +}; + +enum PrinterSeries +{ + SERIES_X1 = 0, + SERIES_P1P, + SERIES_UNKNOWN, +}; + +namespace Slic3r +{ + +/*AMS*/ +enum AmsStatusMain +{ + AMS_STATUS_MAIN_IDLE = 0x00, + AMS_STATUS_MAIN_FILAMENT_CHANGE = 0x01, + AMS_STATUS_MAIN_RFID_IDENTIFYING = 0x02, + AMS_STATUS_MAIN_ASSIST = 0x03, + AMS_STATUS_MAIN_CALIBRATION = 0x04, + AMS_STATUS_MAIN_SELF_CHECK = 0x10, + AMS_STATUS_MAIN_DEBUG = 0x20, + AMS_STATUS_MAIN_UNKNOWN = 0xFF, +}; + +// Slots and Tray +#define VIRTUAL_TRAY_MAIN_ID 255 +#define VIRTUAL_TRAY_DEPUTY_ID 254 + +#define VIRTUAL_AMS_MAIN_ID_STR "255" +#define VIRTUAL_AMS_DEPUTY_ID_STR "254" + +#define INVALID_AMS_TEMPERATURE std::numeric_limits::min() + +/* Extruder*/ +#define MAIN_EXTRUDER_ID 0 +#define DEPUTY_EXTRUDER_ID 1 +#define UNIQUE_EXTRUDER_ID MAIN_EXTRUDER_ID +#define INVALID_EXTRUDER_ID -1 + + +/* Nozzle*/ +enum NozzleFlowType +{ + NONE_FLOWTYPE, + S_FLOW, + H_FLOW +}; + +/*Print speed*/ +enum DevPrintingSpeedLevel +{ + SPEED_LEVEL_INVALID = 0, + SPEED_LEVEL_SILENCE = 1, + SPEED_LEVEL_NORMAL = 2, + SPEED_LEVEL_RAPID = 3, + SPEED_LEVEL_RAMPAGE = 4, + SPEED_LEVEL_COUNT +}; + +/*Upgrade*/ +enum class DevFirmwareUpgradingState : int +{ + DC = -1, + UpgradingUnavaliable = 0, + UpgradingAvaliable = 1, + UpgradingInProgress = 2, + UpgradingFinished = 3 +}; + +class devPrinterUtil +{ +public: + devPrinterUtil() = delete; + ~devPrinterUtil() = delete; + +public: + static bool IsVirtualSlot(int ams_id) { return (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID);} + static bool IsVirtualSlot(const std::string& ams_id) { return (ams_id == VIRTUAL_AMS_MAIN_ID_STR || ams_id == VIRTUAL_AMS_DEPUTY_ID_STR); } +}; + +};// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevExtruderSystem.cpp b/src/slic3r/GUI/DeviceCore/DevExtruderSystem.cpp new file mode 100644 index 0000000..1a71320 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevExtruderSystem.cpp @@ -0,0 +1,292 @@ +#include +#include "DevExtruderSystem.h" +#include "DevNozzleSystem.h" + +// TODO: remove this include +#include "slic3r/GUI/DeviceManager.hpp" +#include "slic3r/GUI/I18N.hpp" + +#include "DevUtil.h" + +using namespace nlohmann; + +namespace Slic3r +{ + wxString DevExtder::GetDisplayLoc() const + { + if (system->GetTotalExtderCount() == 2) + { + if (m_ext_id == MAIN_EXTRUDER_ID) + { + return _L("right"); + } + else + { + return _L("left"); + } + } + + return wxEmptyString; + } + + wxString DevExtder::GetDisplayName() const + { + if (system->GetTotalExtderCount() == 2) + { + if (m_ext_id == MAIN_EXTRUDER_ID) + { + return _L("right extruder"); + } + else + { + return _L("left extruder"); + } + } + + return _L("extruder"); + } + + NozzleType DevExtder::GetNozzleType() const + { + return system->Owner()->GetNozzleSystem()->GetNozzle(m_current_nozzle_id).m_nozzle_type; + } + + NozzleFlowType DevExtder::GetNozzleFlowType() const + { + return system->Owner()->GetNozzleSystem()->GetNozzle(m_current_nozzle_id).m_nozzle_flow; + } + + float DevExtder::GetNozzleDiameter() const + { + return system->Owner()->GetNozzleSystem()->GetNozzle(m_current_nozzle_id).m_diameter; + } + + DevExtderSystem::DevExtderSystem(MachineObject* obj) + : m_owner(obj) + { + // default to have one extruder + m_total_extder_count = 1; + DevExtder ext(this, MAIN_EXTRUDER_ID); + m_extders.emplace_back(ext); + } + + bool DevExtderSystem::CanQuitSwitching() const + { + if (!IsSwitchingFailed()) + { + return false; + } + return !m_owner->is_in_printing() && !m_owner->is_in_printing_pause(); + } + + std::optional DevExtderSystem::GetCurrentExtder() const + { + return GetExtderById(m_current_extder_id); + } + + std::optional DevExtderSystem::GetLoadingExtder() const + { + if (m_current_loading_extder_id != INVALID_EXTRUDER_ID) + { + return GetExtderById(m_current_loading_extder_id); + } + + return std::nullopt; + } + + std::optional DevExtderSystem::GetExtderById(int extder_id) const + { + if (extder_id >= m_extders.size()) + { + assert(false && "Invalid extruder ID"); + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "No extruder found for " << extder_id; + return std::nullopt; + } + + return m_extders[extder_id]; + } + + std::string DevExtderSystem::GetCurrentAmsId() const + { + auto cur_extder = GetCurrentExtder(); + return cur_extder ? cur_extder->GetSlotNow().ams_id : DevAmsSlotInfo().ams_id; + } + + std::string DevExtderSystem::GetCurrentSlotId() const + { + auto cur_extder = GetCurrentExtder(); + return cur_extder ? GetCurrentExtder()->GetSlotNow().slot_id : DevAmsSlotInfo().slot_id; + } + + std::string DevExtderSystem::GetTargetAmsId() const + { + auto cur_extder = GetCurrentExtder(); + return cur_extder ? GetCurrentExtder()->GetSlotTarget().ams_id : DevAmsSlotInfo().ams_id; + } + + std::string DevExtderSystem::GetTargetSlotId() const + { + auto cur_extder = GetCurrentExtder(); + return cur_extder ? GetCurrentExtder()->GetSlotTarget().slot_id : DevAmsSlotInfo().slot_id; + } + + bool DevExtderSystem::HasFilamentBackup() const + { + for (const auto& ext : m_extders) + { + if (ext.HasFilamBackup()) + { + return true; + } + } + + return false; + } + + void ExtderSystemParser::ParseV1_0(const nlohmann::json& print_json, DevExtderSystem* system) + { + if (system->GetTotalExtderCount() != 1) + { + return; + } + + if (print_json.contains("nozzle_temper") && print_json["nozzle_temper"].is_number()) + { + system->m_extders[MAIN_EXTRUDER_ID].m_cur_temp = print_json["nozzle_temper"].get(); + } + + if (print_json.contains("nozzle_target_temper") && print_json["nozzle_target_temper"].is_number()) + { + system->m_extders[MAIN_EXTRUDER_ID].m_target_temp = print_json["nozzle_target_temper"].get(); + } + + if (print_json.contains("ams") && print_json["ams"].contains("tray_tar")) + { + const std::string& tray_tar = print_json["ams"]["tray_tar"].get(); + if (!tray_tar.empty()) + { + int tray_tar_int = atoi(tray_tar.c_str()); + if (tray_tar_int == VIRTUAL_TRAY_MAIN_ID || tray_tar_int == VIRTUAL_TRAY_DEPUTY_ID) + { + system->m_extders[MAIN_EXTRUDER_ID].m_star.ams_id = std::to_string(VIRTUAL_TRAY_MAIN_ID); + system->m_extders[MAIN_EXTRUDER_ID].m_star.slot_id = "0"; + } + else + { + if (tray_tar_int >= 0x80 && tray_tar_int <= 0x87) + { + system->m_extders[MAIN_EXTRUDER_ID].m_star.ams_id = std::to_string(tray_tar_int); + } + else + { + system->m_extders[MAIN_EXTRUDER_ID].m_star.ams_id = std::to_string(tray_tar_int >> 2); + } + + system->m_extders[MAIN_EXTRUDER_ID].m_star.slot_id = std::to_string(tray_tar_int & 0x3); + } + } + } + + if (print_json.contains("ams") && print_json["ams"].contains("tray_now")) + { + const std::string& tray_now = print_json["ams"]["tray_now"].get(); + if (!tray_now.empty()) + { + int tray_now_int = atoi(tray_now.c_str()); + if (tray_now_int == VIRTUAL_TRAY_MAIN_ID) + { + system->m_extders[MAIN_EXTRUDER_ID].m_snow.ams_id = ""; + system->m_extders[MAIN_EXTRUDER_ID].m_snow.slot_id = ""; + } + else if (tray_now_int == VIRTUAL_TRAY_DEPUTY_ID) + { + system->m_extders[MAIN_EXTRUDER_ID].m_snow.ams_id = std::to_string(VIRTUAL_TRAY_MAIN_ID); + system->m_extders[MAIN_EXTRUDER_ID].m_snow.slot_id = "0"; + } + else + { + if (tray_now_int >= 0x80 && tray_now_int <= 0x87) + { + system->m_extders[MAIN_EXTRUDER_ID].m_snow.ams_id = std::to_string(tray_now_int); + } + else + { + system->m_extders[MAIN_EXTRUDER_ID].m_snow.ams_id = std::to_string(tray_now_int >> 2); + } + + system->m_extders[MAIN_EXTRUDER_ID].m_snow.slot_id = std::to_string(tray_now_int & 0x3); + } + } + } + + system->m_current_busy_for_loading = false; + system->m_current_loading_extder_id = INVALID_EXTRUDER_ID; + if (!system->m_extders[MAIN_EXTRUDER_ID].m_star.ams_id.empty()) + { + system->m_current_busy_for_loading = (system->m_extders[MAIN_EXTRUDER_ID].m_snow == system->m_extders[MAIN_EXTRUDER_ID].m_star); + if (system->m_current_busy_for_loading) + { + system->m_current_loading_extder_id = MAIN_EXTRUDER_ID; + } + } + } + + void ExtderSystemParser::ParseV2_0(const nlohmann::json& extruder_json, DevExtderSystem* system) + { + system->m_total_extder_count = DevUtil::get_flag_bits(extruder_json["state"].get(), 0, 4); + if (system->m_current_extder_id != DevUtil::get_flag_bits(extruder_json["state"].get(), 4, 4)) + { + system->Owner()->targ_nozzle_id_from_pc = INVALID_EXTRUDER_ID; + system->m_current_extder_id = DevUtil::get_flag_bits(extruder_json["state"].get(), 4, 4); + } + else if (system->m_switch_extder_state == ES_SWITCHING_FAILED) + { + system->Owner()->targ_nozzle_id_from_pc = INVALID_EXTRUDER_ID; + } + + system->m_target_extder_id = DevUtil::get_flag_bits(extruder_json["state"].get(), 8, 4); + system->m_switch_extder_state = (DevExtderSwitchState)DevUtil::get_flag_bits(extruder_json["state"].get(), 12, 3); + system->m_current_loading_extder_id = DevUtil::get_flag_bits(extruder_json["state"].get(), 15, 4); + system->m_current_busy_for_loading = DevUtil::get_flag_bits(extruder_json["state"].get(), 19); + + system->m_extders.clear(); + for (auto it = extruder_json["info"].begin(); it != extruder_json["info"].cend(); it++) + { + + DevExtder extder_obj(system); + + const auto& njon = it.value(); + extder_obj.SetExtId(njon["id"].get()); + + extder_obj.m_filam_bak.clear(); + const json& filam_bak_items = njon["filam_bak"]; + for (const auto& filam_bak_item : filam_bak_items) + { + const auto& filam_bak_val = filam_bak_item.get(); + extder_obj.m_filam_bak.emplace_back(filam_bak_val); + } + + extder_obj.m_ext_has_filament = (DevUtil::get_flag_bits(njon["info"].get(), 1) != 0); + extder_obj.m_buffer_has_filament = (DevUtil::get_flag_bits(njon["info"].get(), 2) != 0); + extder_obj.m_has_nozzle = (DevUtil::get_flag_bits(njon["info"].get(), 3) != 0); + extder_obj.m_cur_temp = DevUtil::get_flag_bits(njon["temp"].get(), 0, 16); + extder_obj.m_target_temp = DevUtil::get_flag_bits(njon["temp"].get(), 16, 16); + + extder_obj.m_spre.slot_id = std::to_string(DevUtil::get_flag_bits(njon["spre"].get(), 0, 8)); + extder_obj.m_spre.ams_id = std::to_string(DevUtil::get_flag_bits(njon["spre"].get(), 8, 8)); + + extder_obj.m_snow.slot_id = std::to_string(DevUtil::get_flag_bits(njon["snow"].get(), 0, 8)); + extder_obj.m_snow.ams_id = std::to_string(DevUtil::get_flag_bits(njon["snow"].get(), 8, 8)); + + extder_obj.m_star.slot_id = std::to_string(DevUtil::get_flag_bits(njon["star"].get(), 0, 8)); + extder_obj.m_star.ams_id = std::to_string(DevUtil::get_flag_bits(njon["star"].get(), 8, 8)); + + extder_obj.m_ams_stat = DevUtil::get_flag_bits(njon["stat"].get(), 0, 16); + extder_obj.m_rfid_stat = DevUtil::get_flag_bits(njon["stat"].get(), 16, 16); + + //current nozzle info + extder_obj.m_current_nozzle_id = njon["hnow"].get(); + system->m_extders.push_back(extder_obj); + } + } +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevExtruderSystem.h b/src/slic3r/GUI/DeviceCore/DevExtruderSystem.h new file mode 100644 index 0000000..d0f7c10 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevExtruderSystem.h @@ -0,0 +1,190 @@ +#pragma once +#include +#include "libslic3r/CommonDefs.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include + +#include "DevDefs.h" + +namespace Slic3r +{ + +//Previous definitions +class MachineObject; +class DevExtderSystem; + +struct DevAmsSlotInfo +{ + std::string ams_id; + std::string slot_id; + +public: + bool operator==(const DevAmsSlotInfo& other) const { return ams_id == other.ams_id && slot_id == other.slot_id;} +}; + +enum DevExtderSwitchState +{ + ES_IDLE = 0, + ES_BUSY, + ES_SWITCHING, + ES_SWITCHING_FAILED +}; + +class DevExtder +{ + friend class MachineObject; + friend class ExtderSystemParser; +public: + DevExtder(DevExtderSystem* owner/*should not be nullptr*/, int id = -1) : system(owner), m_ext_id(id){}; + +public: + // Ext + int GetExtId() const { return m_ext_id; } + + // display + wxString GetDisplayLoc() const; + wxString GetDisplayName() const; + + // installed nozzle info + bool HasNozzleInstalled() const = delete;//{ return m_has_nozzle; } + + int GetNozzleId() const { return m_current_nozzle_id; } + int GetTargetNozzleId() const = delete;//{ return m_target_nozzle_id; } + NozzleType GetNozzleType() const; + NozzleFlowType GetNozzleFlowType() const; + float GetNozzleDiameter() const; + + // temperature + int GetCurrentTemp() const { return m_cur_temp; } + int GetTargetTemp() const { return m_target_temp; } + + // filament + bool HasFilamentInExt() const { return m_ext_has_filament; } + bool HasFilamentInBuffer() const = delete; //{ return m_buffer_has_filament; } + bool HasFilamBackup() const { return !m_filam_bak.empty(); } + std::vector GetFilamBackup() const { return m_filam_bak; } + + // ams binding on current extruder + const DevAmsSlotInfo& GetSlotPre() const { return m_spre; } + const DevAmsSlotInfo& GetSlotNow() const { return m_snow; } + const DevAmsSlotInfo& GetSlotTarget() const { return m_star; } + +private: + void SetExtId(int val) { m_ext_id = val; } + +private: + DevExtderSystem* system = nullptr; + + // extruder id + int m_ext_id; // 0-right 1-left + + // current nozzle + bool m_has_nozzle = false; + int m_current_nozzle_id = 0; // nozzle id now. for some machine, the extruder may have serveral nozzles + int m_target_nozzle_id = 0; // target nozzle id + + // temperature + int m_cur_temp = 0; + int m_target_temp = 0; + + // filament + bool m_ext_has_filament = false; + bool m_buffer_has_filament = false; + std::vector m_filam_bak;// the refill filam + + // binded ams + DevAmsSlotInfo m_spre; // tray_pre + DevAmsSlotInfo m_snow; // tray_now + DevAmsSlotInfo m_star; // tray_tar + + int m_ams_stat = 0; + int m_rfid_stat = 0; +}; + +// ExtderSystem is the extruder management system for the device. +// It consists of multiple extruders (Extder) and nozzles. +// Each extruder can be associated with different nozzles, and the number of extruders +// does not necessarily equal the number of nozzles. +// Note: The IDs of extruders and nozzles may not match or correspond one-to-one. +class DevExtderSystem +{ + friend class MachineObject; + friend class ExtderSystemParser; +public: + DevExtderSystem(MachineObject* obj); + ~DevExtderSystem() = default; + +public: + MachineObject* Owner() const { return m_owner; } + + // access extder info + int GetTotalExtderCount() const { assert(m_extders.size() == m_total_extder_count); return m_total_extder_count; } + int GetTotalExtderSize() const { return static_cast(m_extders.size()); } + int GetCurrentExtderId() const { return m_current_extder_id; } + int GetTargetExtderId() const = delete;//{ return m_target_extder_id; } + + // switching + DevExtderSwitchState GetSwitchState() const { return m_switch_extder_state; } + bool IsSwitching() const { return m_switch_extder_state == DevExtderSwitchState::ES_SWITCHING;}; + bool IsSwitchingFailed() const { return m_switch_extder_state == DevExtderSwitchState::ES_SWITCHING_FAILED; }; + bool CanQuitSwitching() const; + bool CanRetrySwitching() const { return IsSwitchingFailed(); }; + + int CtrlRetrySwitching(); + int CtrlQuitSwitching(); + + std::optional GetCurrentExtder() const; + std::optional GetLoadingExtder() const; + std::optional GetExtderById(int extder_id) const; + const std::vector& GetExtruders() const { return m_extders;}; + + // get nozzle info which is installed on the extruder + NozzleType GetNozzleType(int extder_id) const { return GetExtderById(extder_id) ? GetExtderById(extder_id)->GetNozzleType() : NozzleType::ntUndefine; } + NozzleFlowType GetNozzleFlowType(int extder_id) const { return GetExtderById(extder_id) ? GetExtderById(extder_id)->GetNozzleFlowType() : NozzleFlowType::NONE_FLOWTYPE;; } + float GetNozzleDiameter(int extder_id) const { return GetExtderById(extder_id) ? GetExtderById(extder_id)->GetNozzleDiameter() : 0.0; } + int GetNozzleTempCurrent(int extder_id) const { return GetExtderById(extder_id) ? GetExtderById(extder_id)->GetCurrentTemp() : 0; } + int GetNozzleTempTarget(int extder_id) const { return GetExtderById(extder_id) ? GetExtderById(extder_id)->GetTargetTemp() : 0; } + + // get slot info which is connected to the extruder + std::string GetCurrentAmsId() const; + std::string GetCurrentSlotId() const; + std::string GetTargetAmsId() const; + std::string GetTargetSlotId() const; + + // filament + bool IsBusyLoading() const { return m_current_busy_for_loading; } + int GetLoadingExtderId() const { return m_current_loading_extder_id; } + bool HasFilamentBackup() const; + bool HasFilamentInExt(int exter_id) { return GetExtderById(exter_id) ? GetExtderById(exter_id)->HasFilamentInExt() : false; } + +protected: + void AddExtder(const DevExtder& ext) { m_extders[ext.GetExtId()] = ext; }; + +private: + MachineObject* m_owner = nullptr; + + // extruders + int m_total_extder_count = 1; + std::vector m_extders; + + // current extruder and swtching info + int m_current_extder_id = MAIN_EXTRUDER_ID; + + // switching + DevExtderSwitchState m_switch_extder_state = DevExtderSwitchState::ES_IDLE; + int m_target_extder_id = MAIN_EXTRUDER_ID; + + // loading extruder + bool m_current_busy_for_loading{ false }; + int m_current_loading_extder_id = INVALID_EXTRUDER_ID; +}; + +class ExtderSystemParser +{ +public: + static void ParseV1_0(const nlohmann::json& extruder_json, DevExtderSystem* system); + static void ParseV2_0(const nlohmann::json& extruder_json, DevExtderSystem* system); +}; + +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevExtruderSystemCtrl.cpp b/src/slic3r/GUI/DeviceCore/DevExtruderSystemCtrl.cpp new file mode 100644 index 0000000..38513a2 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevExtruderSystemCtrl.cpp @@ -0,0 +1,22 @@ +#include +#include "DevExtruderSystem.h" + +#include "slic3r/GUI/DeviceManager.hpp" + + +using namespace nlohmann; + +namespace Slic3r +{ + int DevExtderSystem::CtrlRetrySwitching() + { + if (m_owner) { return m_owner->command_ams_control("resume"); } + return -1; + } + + int DevExtderSystem::CtrlQuitSwitching() + { + if (m_owner) { return m_owner->command_ams_control("abort"); } + return -1; + } +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFan.cpp b/src/slic3r/GUI/DeviceCore/DevFan.cpp new file mode 100644 index 0000000..e596ef8 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFan.cpp @@ -0,0 +1,227 @@ +#include +#include "DevFan.h" +#include +#include "slic3r/GUI/DeviceManager.hpp" +#include "slic3r/GUI/GUI.hpp" +#include "slic3r/GUI/GUI_App.hpp" +using namespace nlohmann; + +void Slic3r::DevFan::converse_to_duct(bool is_suppt_part_fun, bool is_suppt_aux_fun, bool is_suppt_cham_fun) +{ + m_air_duct_data.modes.clear(); + m_air_duct_data.parts.clear(); + m_air_duct_data.curren_mode = -1; // def mode + + if (is_suppt_part_fun) { + AirParts part_fan; + part_fan.type = int(AirDuctType::AIR_FAN_TYPE); + part_fan.id = int(AIR_FUN::FAN_COOLING_0_AIRDOOR); + part_fan.func = int(AIR_FUN::FAN_COOLING_0_AIRDOOR); + part_fan.state = 0; + part_fan.range_start = 0; + part_fan.range_end = 100; + m_air_duct_data.parts.push_back(part_fan); + } + + if (is_suppt_aux_fun) { + AirParts aux_fan; + aux_fan.type = int(AirDuctType::AIR_FAN_TYPE); + aux_fan.id = int(AIR_FUN::FAN_REMOTE_COOLING_0_IDX); + aux_fan.func = int(AIR_FUN::FAN_REMOTE_COOLING_0_IDX); + aux_fan.state = 0; + aux_fan.range_start = 0; + aux_fan.range_end = 100; + m_air_duct_data.parts.push_back(aux_fan); + } + + if (is_suppt_aux_fun) { + AirParts chamber_fan; + chamber_fan.type = int(AirDuctType::AIR_FAN_TYPE); + chamber_fan.id = int(AIR_FUN::FAN_CHAMBER_0_IDX); + chamber_fan.func = int(AIR_FUN::FAN_CHAMBER_0_IDX); + chamber_fan.state = 0; + chamber_fan.range_start = 0; + chamber_fan.range_end = 100; + m_air_duct_data.parts.push_back(chamber_fan); + } +} + +static std::string _get_string_from_fantype(int type) +{ + switch (type) { + case 1: return "cooling_fan"; + case 2: return "big_cooling_fan"; + case 3: return "chamber_fan"; + default: return ""; + } + return ""; +} + +// Old protocol +int Slic3r::DevFan::command_control_fan(int fan_type, int val) +{ + std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int) fan_type % (val)).str(); + try { + json j; + j["ctrl_type"] = _get_string_from_fantype(fan_type); + j["value"] = val; + + NetworkAgent *agent = GUI::wxGetApp().getAgent(); + if (agent) agent->track_event("printer_control", j.dump()); + } catch (...) {} + return m_owner->publish_gcode(gcode); +} + +// New protocol +int Slic3r::DevFan::command_control_fan_new(int fan_id, int val) +{ + BOOST_LOG_TRIVIAL(info) << "New protocol of fan setting(set speed), fan_id = " << fan_id; + 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 m_owner->publish_json(j); +} + + +int Slic3r::DevFan::command_handle_response(const json &response) +{ + if (!response.contains("sequence_id")) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ", error reponse."; + return -1; + } + + std::string reply = response["sequence_id"].get(); + auto it = m_callback_list.find(reply); + if (it != m_callback_list.end()) { + if (it->second) it->second(response); + m_callback_list.erase(it); + } + return 0; +} + +int Slic3r::DevFan::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_owner->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 m_owner->publish_json(j); +} + +void Slic3r::DevFan::ParseV1_0(const json &print_json) +{ + if (print_json.contains("fan_gear")) { + fan_gear = print_json["fan_gear"].get(); + big_fan2_speed = (int) ((fan_gear & 0x00FF0000) >> 16); + big_fan1_speed = (int) ((fan_gear & 0x0000FF00) >> 8); + cooling_fan_speed = (int) ((fan_gear & 0x000000FF) >> 0); + } else { + if (print_json.contains("cooling_fan_speed")) { + cooling_fan_speed = stoi(print_json["cooling_fan_speed"].get()); + cooling_fan_speed = round(floor(cooling_fan_speed / float(1.5)) * float(25.5)); + } else { + cooling_fan_speed = 0; + } + if (print_json.contains("big_fan1_speed")) { + big_fan1_speed = stoi(print_json["big_fan1_speed"].get()); + big_fan1_speed = round(floor(big_fan1_speed / float(1.5)) * float(25.5)); + } else { + big_fan1_speed = 0; + } + if (print_json.contains("big_fan2_speed")) { + big_fan2_speed = stoi(print_json["big_fan2_speed"].get()); + big_fan2_speed = round(floor(big_fan2_speed / float(1.5)) * float(25.5)); + } else { + big_fan2_speed = 0; + } + } + + if (print_json.contains("heatbreak_fan_speed")) { heatbreak_fan_speed = stoi(print_json["heatbreak_fan_speed"].get()); } + + + +} + +void Slic3r::DevFan::ParseV2_0(const json &print_json) { + + if (print_json.contains("support_aux_fan")) { + if (print_json["support_aux_fan"].is_boolean()) + is_support_aux_fan = print_json["support_aux_fan"].get(); + } + + if (print_json.contains("support_chamber_fan")) { + if (print_json["support_chamber_fan"].is_boolean()) + is_support_chamber_fan = print_json["support_chamber_fan"].get(); + } +} + + + + + void Slic3r::DevFan::ParseV3_0(const json &device) +{ + if (device.contains("airduct")) { + m_air_duct_data.curren_mode = -1; + 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>(); + + for (int i = 0; i < list.size(); ++i) { + // only show 2 mode for o + if (m_owner->is_series_o() && i >= 2) { break; } + + json mode_json = list[i]; + AirMode mode; + if (mode_json.contains("modeId")) mode.id = mode_json["modeId"].get(); + if (mode_json.contains("ctrl")) { + for (auto it_mode_ctrl = mode_json["ctrl"].begin(); it_mode_ctrl != mode_json["ctrl"].end(); it_mode_ctrl++) { + mode.ctrl.push_back((*it_mode_ctrl).get() >> 4); + } + } + + if (mode_json.contains("off")) { + for (auto it_mode_off = mode_json["off"].begin(); it_mode_off != mode_json["off"].end(); *it_mode_off++) { + mode.off.push_back((*it_mode_off).get() >> 4); + } + } + + if (AIR_DUCT(mode.id) == AIR_DUCT::AIR_DUCT_EXHAUST) { continue; } /*STUDIO-12796*/ + m_air_duct_data.modes[mode.id] = mode; + } + } + + if (airduct.contains("parts") && airduct["parts"].is_array()) { + for (auto it_part = airduct["parts"].begin(); it_part != airduct["parts"].end(); it_part++) { + int state = (*it_part)["state"].get(); + int range = (*it_part)["range"].get(); + + AirParts part; + part.type = m_owner->get_flag_bits((*it_part)["id"].get(), 0, 4); + part.id = m_owner->get_flag_bits((*it_part)["id"].get(), 4, 8); + part.func = (*it_part)["func"].get(); + part.state = m_owner->get_flag_bits(state, 0, 8); + part.range_start = m_owner->get_flag_bits(range, 0, 16); + part.range_end = m_owner->get_flag_bits(range, 16, 16); + + m_air_duct_data.parts.push_back(part); + } + } + } + + } + diff --git a/src/slic3r/GUI/DeviceCore/DevFan.h b/src/slic3r/GUI/DeviceCore/DevFan.h new file mode 100644 index 0000000..5975b43 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFan.h @@ -0,0 +1,151 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" + +namespace Slic3r { + +class MachineObject; + +enum AirDuctType { AIR_FAN_TYPE, AIR_DOOR_TYPE }; +typedef std::function CommandCallBack; + + + +enum AIR_FUN : int { + FAN_HEAT_BREAK_0_IDX = 0, + FAN_COOLING_0_AIRDOOR = 1, + FAN_REMOTE_COOLING_0_IDX = 2, + FAN_CHAMBER_0_IDX = 3, + FAN_HEAT_BREAK_1_IDX = 4, + FAN_MC_BOARD_0_IDX = 5, + FAN_INNNER_LOOP_FAN_0_IDX = 6, + FAN_TOTAL_COUNT = 7, + FAN_REMOTE_COOLING_1_IDX = 10 +}; + +enum AIR_DOOR { AIR_DOOR_FUNC_CHAMBER = 0, AIR_DOOR_FUNC_INNERLOOP, AIR_DOOR_FUNC_TOP }; + + +enum AIR_DUCT : int { + AIR_DUCT_NONE = -1, + AIR_DUCT_COOLING_FILT = 0, + AIR_DUCT_HEATING_INTERNAL_FILT, + AIR_DUCT_EXHAUST, + AIR_DUCT_FULL_COOLING, + AIR_DUCT_INIT = 0xFF // Initial mode, only used within mc +}; + +struct AirParts +{ + int type{0}; + int id{0}; + int func{0}; + 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 AirMode +{ + int id{-1}; + std::vector ctrl; + // 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 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 == 1; } +}; + +class DevFan +{ +public: + DevFan(MachineObject *obj) : m_owner(obj){}; +public: + + enum FanType {//if have devPrinter , delete? + COOLING_FAN = 1, + BIG_COOLING_FAN = 2, + CHAMBER_FAN = 3, + EXHAUST_FAN, + FILTER_FAN, + }; + + bool is_at_heating_mode() const { return m_air_duct_data.curren_mode == AIR_DUCT_HEATING_INTERNAL_FILT; }; + + void SetSupportCoolingFilter(bool enable) { m_air_duct_data.m_support_cooling_filter = enable; } + AirDuctData GetAirDuctData() { return m_air_duct_data; }; + + void converse_to_duct(bool is_suppt_part_fun, bool is_suppt_aux_fun, bool is_suppt_cham_fun); // Convert the data to duct type to make the newand old protocols consistent + int command_handle_response(const json &response); + int command_control_fan(int fan_type, int val); // Old protocol + int command_control_fan_new(int fan_id, int val); // New protocol + int command_control_air_duct(int mode_id, int submode, const CommandCallBack& cb); + + void ParseV1_0(const json &print_json); + void ParseV2_0(const json &print_json); + void ParseV3_0(const json &print_json); + + public: + bool GetSupportAuxFanData() { return is_support_aux_fan; }; + bool GetSupportChamberFan() { return is_support_aux_fan; }; + int GetHeatBreakFanSpeed() { return heatbreak_fan_speed; } + int GetCoolingFanSpeed() { return cooling_fan_speed; } + int GetBigFan1Speed() { return big_fan1_speed; } + int GetBigFan2Speed() { return big_fan2_speed; } + uint32_t GetFanGear() { return fan_gear; } + + +private: + AirDuctData m_air_duct_data; + + bool is_support_aux_fan{false}; + bool is_support_chamber_fan{false}; + + int heatbreak_fan_speed = 0; + int cooling_fan_speed = 0; + int big_fan1_speed = 0; + int big_fan2_speed = 0; + uint32_t fan_gear = 0; + + std::map m_callback_list; + + MachineObject *m_owner = nullptr; +}; + + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.cpp b/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.cpp new file mode 100644 index 0000000..2b0043b --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.cpp @@ -0,0 +1,13 @@ +#include "DevFilaAmsSetting.h" + +namespace Slic3r { + +void DevAmsSystemSetting::Reset() +{ + SetDetectOnInsertEnabled(false); + SetDetectOnPowerupEnabled(false); + SetDetectRemainEnabled(false); + SetAutoRefillEnabled(false); +} + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.h b/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.h new file mode 100644 index 0000000..8798932 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaAmsSetting.h @@ -0,0 +1,35 @@ +#pragma once + +namespace Slic3r +{ + +class DevFilaSystem; +class DevAmsSystemSetting +{ +public: + DevAmsSystemSetting(DevFilaSystem* owner) : m_owner(owner) {}; + +public: + // getters + bool IsDetectOnInsertEnabled() const { return m_enable_detect_on_insert; }; + bool IsDetectOnPowerupEnabled() const { return m_enable_detect_on_powerup; } + bool IsDetectRemainEnabled() const { return m_enable_detect_remain; } + bool IsAutoRefillEnabled() const { return m_enable_auto_refill; } + + // setters + void Reset(); + void SetDetectOnInsertEnabled(bool enable) { m_enable_detect_on_insert = enable; } + void SetDetectOnPowerupEnabled(bool enable) { m_enable_detect_on_powerup = enable; } + void SetDetectRemainEnabled(bool enable) { m_enable_detect_remain = enable; } + void SetAutoRefillEnabled(bool enable) { m_enable_auto_refill = enable; } + +private: + DevFilaSystem* m_owner = nullptr; + + bool m_enable_detect_on_insert = false; + bool m_enable_detect_on_powerup = false; + bool m_enable_detect_remain = false; + bool m_enable_auto_refill = false; +}; + +}// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaBlackList.cpp b/src/slic3r/GUI/DeviceCore/DevFilaBlackList.cpp new file mode 100644 index 0000000..7fe83df --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaBlackList.cpp @@ -0,0 +1,254 @@ +#include + +#include "DevFilaBlackList.h" +#include "DevFilaSystem.h" +#include "DevManager.h" + +#include "libslic3r/Utils.hpp" + +#include "slic3r/GUI/I18N.hpp" +#include "slic3r/GUI/GUI_App.hpp" + +using namespace nlohmann; + +namespace Slic3r { + +json DevFilaBlacklist::filaments_blacklist = json::object(); + + +bool DevFilaBlacklist::load_filaments_blacklist_config() +{ + if (!filaments_blacklist.empty()) + { + return false; + } + + filaments_blacklist = json::object(); + + std::string config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json"; + boost::nowide::ifstream json_file(config_file.c_str()); + + try { + if (json_file.is_open()) { + json_file >> filaments_blacklist; + return true; + } + else { + BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed"; + } + } + catch (...) { + BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed"; + return false; + } + return true; +} + + + +static std::string _get_filament_name_from_ams(int ams_id, int slot_id) +{ + std::string name; + DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { return name; } + + MachineObject* obj = dev->get_selected_machine(); + if (obj == nullptr) { return name; } + + if (ams_id < 0 || slot_id < 0) + { + return name; + } + + const auto tray = obj->GetFilaSystem()->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id)); + if (!tray) { return name; } + + std::string filament_id = tray->setting_id; + + PresetBundle* preset_bundle = GUI::wxGetApp().preset_bundle; + auto option = preset_bundle->get_filament_by_filament_id(filament_id); + name = option ? option->filament_name : ""; + return name; +} + +// moved from tao.wang and zhimin.zeng +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 = _get_filament_name_from_ams(ams_id, slot_id); + } + + in_blacklist = false; + std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower); + std::transform(tag_type.begin(), tag_type.end(), tag_type.begin(), ::tolower); + std::transform(tag_name.begin(), tag_name.end(), tag_name.begin(), ::tolower); + + DevFilaBlacklist::load_filaments_blacklist_config(); + if (DevFilaBlacklist::filaments_blacklist.contains("blacklist")) + { + for (auto filament_item : DevFilaBlacklist::filaments_blacklist["blacklist"]) + { + + std::string vendor = filament_item.contains("vendor") ? filament_item["vendor"].get() : ""; + 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() : ""; + + // check model id + if (!model_ids.empty() && std::find(model_ids.begin(), model_ids.end(), model_id) == model_ids.end()) { continue; } + + // check vendor + std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower); + if (!vendor.empty()) + { + if ((vendor == "qidi tech" && (tag_vendor == vendor)) || + (vendor == "third party" && (tag_vendor != "qidi tech"))) + { + // Do nothing + } + else + { + continue; + } + } + + // check type + std::transform(type.begin(), type.end(), type.begin(), ::tolower); + if (!type.empty() && (type != tag_type)) { continue; } + + // check type suffix + std::transform(type_suffix.begin(), type_suffix.end(), type_suffix.begin(), ::tolower); + if (!type_suffix.empty()) + { + if (tag_type.length() < type_suffix.length()) { continue; } + if ((tag_type.substr(tag_type.length() - type_suffix.length()) != type_suffix)) { continue; } + } + + // check name + 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 = devPrinterUtil::IsVirtualSlot(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 = _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("Damp PVA is flexible and may get stuck in extruder. 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 DevFilaBlacklist::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) +{ + 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); +} + + +bool check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, const std::string& filament_id, int ams_id, bool &in_blacklist, std::string &ac, wxString &info) +{ + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { + return true; + } + + MachineObject *obj = dev->get_selected_machine(); + if (obj == nullptr || !obj->is_multi_extruders()) { + return true; + } + + Preset *printer_preset = GUI::get_printer_preset(obj); + if (!printer_preset) + return true; + + ConfigOptionInts *physical_extruder_map_op = dynamic_cast(printer_preset->config.option("physical_extruder_map")); + if (!physical_extruder_map_op) + return true; + std::vector physical_extruder_maps = physical_extruder_map_op->values; + int obj_extruder_id = obj->get_extruder_id_by_ams_id(std::to_string(ams_id)); + int extruder_idx = obj_extruder_id; + for (int index = 0; index < physical_extruder_maps.size(); ++index) { + if (physical_extruder_maps[index] == obj_extruder_id) { + extruder_idx = index; + break; + } + } + + PresetBundle *preset_bundle = GUI::wxGetApp().preset_bundle; + std::optional filament_info = preset_bundle->get_filament_by_filament_id(filament_id, printer_preset->name); + 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); + in_blacklist = true; + return false; + } + + return true; +} + +void DevFilaBlacklist::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)) + { + return; + } + + check_filaments(model_id, tag_vendor, tag_type, ams_id, slot_id, tag_name, in_blacklist, ac, info, wiki_url); +} + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaBlackList.h b/src/slic3r/GUI/DeviceCore/DevFilaBlackList.h new file mode 100644 index 0000000..7eed1f5 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaBlackList.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" + +namespace Slic3r +{ +class DevFilaBlacklist +{ +public: + static bool load_filaments_blacklist_config(); + 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); + +public: + static json filaments_blacklist; +};// class DevFilaBlacklist + +}// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp b/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp new file mode 100644 index 0000000..7ced678 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaSystem.cpp @@ -0,0 +1,691 @@ +#include +#include "DevFilaSystem.h" + +// TODO: remove this include +#include "slic3r/GUI/DeviceManager.hpp" +#include "slic3r/GUI/I18N.hpp" + +#include "DevUtil.h" + +using namespace nlohmann; + +namespace Slic3r { +static int _hex_digit_to_int(const char c) { return (c >= '0' && c <= '9') ? c - '0' : (c >= 'A' && c <= 'F') ? c - 'A' + 10 : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1; } + +wxColour DevAmsTray::decode_color(const std::string &color) +{ + std::array ret = {0, 0, 0, 0}; + const char * c = color.data(); + if (color.size() == 8) { + for (size_t j = 0; j < 4; ++j) { + int digit1 = _hex_digit_to_int(*c++); + int digit2 = _hex_digit_to_int(*c++); + if (digit1 == -1 || digit2 == -1) break; + ret[j] = static_cast(digit1 * 16 + digit2); + } + } else { return wxColour(255, 255, 255, 255); } + + return wxColour(ret[0], ret[1], ret[2], ret[3]); +} + +void DevAmsTray::UpdateColorFromStr(const std::string& color) +{ + if (color.empty()) return; + if (this->color != color) + { + wx_color = "#" + wxString::FromUTF8(color); + this->color = color; + } +} + +void DevAmsTray::reset() +{ + tag_uid = ""; + setting_id = ""; + filament_setting_id = ""; + type = ""; + sub_brands = ""; + color = ""; + weight = ""; + diameter = ""; + temp = ""; + time = ""; + bed_temp_type = ""; + bed_temp = ""; + nozzle_temp_max = ""; + nozzle_temp_min = ""; + xcam_info = ""; + uuid = ""; + k = 0.0f; + n = 0.0f; + is_qdt = false; + hold_count = 0; + remain = 0; +} + + +bool DevAmsTray::is_tray_info_ready() const +{ + if (color.empty()) return false; + if (type.empty()) return false; + //if (setting_id.empty()) return false; + return true; +} + +bool DevAmsTray::is_unset_third_filament() const +{ + if (this->is_qdt) return false; + return (color.empty() || type.empty()); +} + +std::string DevAmsTray::get_display_filament_type() const +{ + if (type == "PLA-S") return "Sup.PLA"; + if (type == "PA-S") return "Sup.PA"; + if (type == "ABS-S") return "Sup.ABS"; + return type; +} + +std::string DevAmsTray::get_filament_type() +{ + if (type == "Sup.PLA") { return "PLA-S"; } + if (type == "Sup.PA") { return "PA-S"; } + if (type == "Sup.ABS") { return "ABS-S"; } + if (type == "Support W") { return "PLA-S"; } + if (type == "Support G") { return "PA-S"; } + if (type == "Support") { if (setting_id == "GFS00") { type = "PLA-S"; } else if (setting_id == "GFS01") { type = "PA-S"; } else { return "PLA-S"; } } + + return type; +} + + +DevAms::DevAms(const std::string& ams_id, int extruder_id, AmsType type) +{ + m_ams_id = ams_id; + m_ext_id = extruder_id; + m_ams_type = type; +} + +DevAms::DevAms(const std::string& ams_id, int nozzle_id, int type) +{ + m_ams_id = ams_id; + m_ext_id = nozzle_id; + m_ams_type = (AmsType)type; + assert(DUMMY < type && m_ams_type <= N3S); +} + +DevAms::~DevAms() +{ + for (auto it = m_trays.begin(); it != m_trays.end(); it++) + { + if (it->second) + { + delete it->second; + it->second = nullptr; + } + } + m_trays.clear(); +} + +static unordered_map s_ams_display_formats = { + {DevAms::AMS, "AMS-%d"}, + {DevAms::AMS_LITE, "AMS Lite-%d"}, + {DevAms::N3F, "AMS 2 PRO-%d"}, + {DevAms::N3S, "AMS HT-%d"} +}; + +wxString DevAms::GetDisplayName() const +{ + wxString ams_display_format; + auto iter = s_ams_display_formats.find(m_ams_type); + if (iter != s_ams_display_formats.end()) + { + ams_display_format = iter->second; + } + else + { + assert(0 && __FUNCTION__); + ams_display_format = "AMS-%d"; + } + + int num_id; + try + { + num_id = std::stoi(GetAmsId()); + } + catch (const std::exception& e) + { + assert(0 && __FUNCTION__); + BOOST_LOG_TRIVIAL(error) << "Invalid AMS ID: " << GetAmsId() << ", error: " << e.what(); + num_id = 0; + } + + int loc = (num_id > 127) ? (num_id - 127) : (num_id + 1); + return wxString::Format(ams_display_format, loc); +} + +int DevAms::GetSlotCount() const +{ + if (m_ams_type == AMS || m_ams_type == AMS_LITE || m_ams_type == N3F) + { + return 4; + } + else if (m_ams_type == N3S) + { + return 1; + } + + return 1; +} + +DevAmsTray* DevAms::GetTray(const std::string& tray_id) const +{ + auto it = m_trays.find(tray_id); + if (it != m_trays.end()) + { + return it->second; + } + + return nullptr; +} + +DevFilaSystem::~DevFilaSystem() +{ + for (auto it = amsList.begin(); it != amsList.end(); it++) + { + if (it->second) + { + delete it->second; + it->second = nullptr; + } + } + amsList.clear(); +} + +DevAms* DevFilaSystem::GetAmsById(const std::string& ams_id) const +{ + auto it = amsList.find(ams_id); + if (it != amsList.end()) + { + return it->second; + } + + return nullptr; +} + +DevAmsTray* DevFilaSystem::GetAmsTray(const std::string& ams_id, const std::string& tray_id) const +{ + auto it = amsList.find(ams_id); + if (it == amsList.end()) return nullptr; + if (!it->second) return nullptr; + return it->second->GetTray(tray_id);; +} + +void DevFilaSystem::CollectAmsColors(std::vector& ams_colors) const +{ + ams_colors.clear(); + ams_colors.reserve(amsList.size()); + for (auto ams = amsList.begin(); ams != amsList.end(); ams++) + { + for (auto tray = ams->second->GetTrays().begin(); tray != ams->second->GetTrays().end(); tray++) + { + if (tray->second->is_tray_info_ready()) + { + auto ams_color = DevAmsTray::decode_color(tray->second->color); + ams_colors.emplace_back(ams_color); + } + } + } +} + +int DevFilaSystem::GetExtruderIdByAmsId(const std::string& ams_id) const +{ + auto it = amsList.find(ams_id); + if (it != amsList.end()) + { + return it->second->GetExtruderId(); + } + else if (stoi(ams_id) == VIRTUAL_TRAY_MAIN_ID) + { + return MAIN_EXTRUDER_ID; + } + else if (stoi(ams_id) == VIRTUAL_TRAY_DEPUTY_ID) + { + return DEPUTY_EXTRUDER_ID; + } + + assert(false && __FUNCTION__); + return 0; // not found +} + +bool DevFilaSystem::IsAmsSettingUp() const +{ + int setting_up_stat = DevUtil::get_flag_bits(m_ams_cali_stat, 0, 8); + if (setting_up_stat == 0x01 || setting_up_stat == 0x02 || setting_up_stat == 0x03 || setting_up_stat == 0x04) + { + return true; + } + + return false; +} + +bool DevFilaSystem::IsQDT_Filament(std::string tag_uid) +{ + if (tag_uid.empty()) + { + return false; + } + + for (int i = 0; i < tag_uid.length(); i++) + { + if (tag_uid[i] != '0') { return true; } + } + + return false; +} + +void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaSystem* system, bool key_field_only) +{ + if (jj.contains("ams")) + { + if (jj["ams"].contains("ams")) + { + if (jj["ams"].contains("ams_exist_bits")) + { + obj->ams_exist_bits = stol(jj["ams"]["ams_exist_bits"].get(), nullptr, 16); + } + + if (jj["ams"].contains("tray_exist_bits")) + { + obj->tray_exist_bits = stol(jj["ams"]["tray_exist_bits"].get(), nullptr, 16); + } + + if (jj["ams"].contains("cali_stat")) { system->m_ams_cali_stat = jj["ams"]["cali_stat"].get(); } + + if (!key_field_only) + { + if (jj["ams"].contains("tray_read_done_bits")) + { + obj->tray_read_done_bits = stol(jj["ams"]["tray_read_done_bits"].get(), nullptr, 16); + } + if (jj["ams"].contains("tray_reading_bits")) + { + obj->tray_reading_bits = stol(jj["ams"]["tray_reading_bits"].get(), nullptr, 16); + } + if (jj["ams"].contains("tray_is_qdt_bits")) + { + obj->tray_is_qdt_bits = stol(jj["ams"]["tray_is_qdt_bits"].get(), nullptr, 16); + } + if (jj["ams"].contains("version")) + { + if (jj["ams"]["version"].is_number()) + { + obj->ams_version = jj["ams"]["version"].get(); + } + } + +#if 0 + if (jj["ams"].contains("ams_rfid_status")) { } +#endif + + if (time(nullptr) - obj->ams_user_setting_start > HOLD_TIME_3SEC) + { + if (jj["ams"].contains("insert_flag")) + { + system->m_ams_system_setting.SetDetectOnInsertEnabled(jj["ams"]["insert_flag"].get()); + } + if (jj["ams"].contains("power_on_flag")) + { + system->m_ams_system_setting.SetDetectOnPowerupEnabled(jj["ams"]["power_on_flag"].get()); + } + if (jj["ams"].contains("calibrate_remain_flag")) + { + system->m_ams_system_setting.SetDetectRemainEnabled(jj["ams"]["calibrate_remain_flag"].get()); + } + } + + json j_ams = jj["ams"]["ams"]; + std::set ams_id_set; + + for (auto it = system->amsList.begin(); it != system->amsList.end(); it++) + { + ams_id_set.insert(it->first); + } + + for (auto it = j_ams.begin(); it != j_ams.end(); it++) + { + if (!it->contains("id")) continue; + std::string ams_id = (*it)["id"].get(); + + int extuder_id = MAIN_EXTRUDER_ID; // Default nozzle id + int type_id = 1; // 0:dummy 1:ams 2:ams-lite 3:n3f 4:n3s + + /*ams info*/ + if (it->contains("info")) + { + const std::string& info = (*it)["info"].get(); + type_id = DevUtil::get_flag_bits(info, 0, 4); + extuder_id = DevUtil::get_flag_bits(info, 8, 4); + } + + /*AMS without initialization*/ + if (extuder_id == 0xE) + { + ams_id_set.erase(ams_id); + system->amsList.erase(ams_id); + continue; + } + + ams_id_set.erase(ams_id); + DevAms* curr_ams = nullptr; + auto ams_it = system->amsList.find(ams_id); + if (ams_it == system->amsList.end()) + { + DevAms* new_ams = new DevAms(ams_id, extuder_id, type_id); + system->amsList.insert(std::make_pair(ams_id, new_ams)); + // new ams added event + curr_ams = new_ams; + } + else + { + if (extuder_id != ams_it->second->GetExtruderId()) + { + ams_it->second->m_ext_id = extuder_id; + } + + curr_ams = ams_it->second; + } + if (!curr_ams) continue; + + /*set ams type flag*/ + curr_ams->SetAmsType(type_id); + + + /*set ams exist flag*/ + try + { + if (!ams_id.empty()) + { + int ams_id_int = atoi(ams_id.c_str()); + + if (type_id < 4) + { + curr_ams->m_exist = (obj->ams_exist_bits & (1 << ams_id_int)) != 0 ? true : false; + } + else + { + curr_ams->m_exist = DevUtil::get_flag_bits(obj->ams_exist_bits, 4 + (ams_id_int - 128)); + } + } + } + catch (...) + { + ; + } + + if (it->contains("dry_time") && (*it)["dry_time"].is_number()) + { + curr_ams->m_left_dry_time = (*it)["dry_time"].get(); + } + + if (it->contains("humidity")) + { + try + { + std::string humidity = (*it)["humidity"].get(); + curr_ams->m_humidity_level = atoi(humidity.c_str()); + } + catch (...) + { + ; + } + } + + if (it->contains("humidity_raw")) + { + try + { + std::string humidity_raw = (*it)["humidity_raw"].get(); + curr_ams->m_humidity_percent = atoi(humidity_raw.c_str()); + } + catch (...) + { + ; + } + } + + + if (it->contains("temp")) + { + std::string temp = (*it)["temp"].get(); + try + { + curr_ams->m_current_temperature = DevUtil::string_to_float(temp); + } + catch (...) + { + curr_ams->m_current_temperature = INVALID_AMS_TEMPERATURE; + } + } + + if (it->contains("tray")) + { + std::set tray_id_set; + for (auto it = curr_ams->GetTrays().cbegin(); it != curr_ams->GetTrays().cend(); it++) + { + tray_id_set.insert(it->first); + } + for (auto tray_it = (*it)["tray"].begin(); tray_it != (*it)["tray"].end(); tray_it++) + { + if (!tray_it->contains("id")) continue; + std::string tray_id = (*tray_it)["id"].get(); + tray_id_set.erase(tray_id); + // compare tray_list + DevAmsTray* curr_tray = nullptr; + auto tray_iter = curr_ams->GetTrays().find(tray_id); + if (tray_iter == curr_ams->GetTrays().end()) + { + DevAmsTray* new_tray = new DevAmsTray(tray_id); + curr_ams->m_trays.insert(std::make_pair(tray_id, new_tray)); + curr_tray = new_tray; + } + else + { + curr_tray = tray_iter->second; + } + if (!curr_tray) continue; + + if (curr_tray->hold_count > 0) + { + curr_tray->hold_count--; + continue; + } + + curr_tray->id = (*tray_it)["id"].get(); + if (tray_it->contains("tag_uid")) + curr_tray->tag_uid = (*tray_it)["tag_uid"].get(); + else + curr_tray->tag_uid = "0"; + if (tray_it->contains("tray_info_idx") && tray_it->contains("tray_type")) + { + curr_tray->setting_id = (*tray_it)["tray_info_idx"].get(); + //std::string type = (*tray_it)["tray_type"].get(); + std::string type = MachineObject::setting_id_to_type(curr_tray->setting_id, (*tray_it)["tray_type"].get()); + if (curr_tray->setting_id == "GFS00") + { + curr_tray->type = "PLA-S"; + } + else if (curr_tray->setting_id == "GFS01") + { + curr_tray->type = "PA-S"; + } + else + { + curr_tray->type = type; + } + } + else + { + curr_tray->setting_id = ""; + curr_tray->type = ""; + } + if (tray_it->contains("tray_sub_brands")) + curr_tray->sub_brands = (*tray_it)["tray_sub_brands"].get(); + else + curr_tray->sub_brands = ""; + if (tray_it->contains("tray_weight")) + curr_tray->weight = (*tray_it)["tray_weight"].get(); + else + curr_tray->weight = ""; + if (tray_it->contains("tray_diameter")) + curr_tray->diameter = (*tray_it)["tray_diameter"].get(); + else + curr_tray->diameter = ""; + if (tray_it->contains("tray_temp")) + curr_tray->temp = (*tray_it)["tray_temp"].get(); + else + curr_tray->temp = ""; + if (tray_it->contains("tray_time")) + curr_tray->time = (*tray_it)["tray_time"].get(); + else + curr_tray->time = ""; + if (tray_it->contains("bed_temp_type")) + curr_tray->bed_temp_type = (*tray_it)["bed_temp_type"].get(); + else + curr_tray->bed_temp_type = ""; + if (tray_it->contains("bed_temp")) + curr_tray->bed_temp = (*tray_it)["bed_temp"].get(); + else + curr_tray->bed_temp = ""; + if (tray_it->contains("tray_color")) + { + auto color = (*tray_it)["tray_color"].get(); + curr_tray->UpdateColorFromStr(color); + } + else + { + curr_tray->color = ""; + } + if (tray_it->contains("nozzle_temp_max")) + { + curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get(); + } + else + curr_tray->nozzle_temp_max = ""; + if (tray_it->contains("nozzle_temp_min")) + curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get(); + else + curr_tray->nozzle_temp_min = ""; + if (tray_it->contains("xcam_info")) + curr_tray->xcam_info = (*tray_it)["xcam_info"].get(); + else + curr_tray->xcam_info = ""; + if (tray_it->contains("tray_uuid")) + curr_tray->uuid = (*tray_it)["tray_uuid"].get(); + else + curr_tray->uuid = "0"; + + if (tray_it->contains("ctype")) + curr_tray->ctype = (*tray_it)["ctype"].get(); + else + curr_tray->ctype = 0; + curr_tray->cols.clear(); + if (tray_it->contains("cols")) + { + if ((*tray_it)["cols"].is_array()) + { + for (auto it = (*tray_it)["cols"].begin(); it != (*tray_it)["cols"].end(); it++) + { + curr_tray->cols.push_back(it.value().get()); + } + } + } + + if (tray_it->contains("remain")) + { + curr_tray->remain = (*tray_it)["remain"].get(); + } + else + { + curr_tray->remain = -1; + } + int ams_id_int = 0; + int tray_id_int = 0; + try + { + if (!ams_id.empty() && !curr_tray->id.empty()) + { + ams_id_int = atoi(ams_id.c_str()); + tray_id_int = atoi(curr_tray->id.c_str()); + + if (type_id < 4) + { + curr_tray->is_exists = (obj->tray_exist_bits & (1 << (ams_id_int * 4 + tray_id_int))) != 0 ? true : false; + } + else + { + curr_tray->is_exists = DevUtil::get_flag_bits(obj->tray_exist_bits, 16 + (ams_id_int - 128)); + } + + } + } + catch (...) + { + } + if (tray_it->contains("setting_id")) + { + curr_tray->filament_setting_id = (*tray_it)["setting_id"].get(); + } + auto curr_time = std::chrono::system_clock::now(); + auto diff = std::chrono::duration_cast(curr_time - obj->extrusion_cali_set_hold_start); + if (diff.count() > HOLD_TIMEOUT || diff.count() < 0 + || ams_id_int != (obj->extrusion_cali_set_tray_id / 4) + || tray_id_int != (obj->extrusion_cali_set_tray_id % 4)) + { + if (tray_it->contains("k")) + { + curr_tray->k = (*tray_it)["k"].get(); + } + if (tray_it->contains("n")) + { + curr_tray->n = (*tray_it)["n"].get(); + } + } + + std::string temp = tray_it->dump(); + + if (tray_it->contains("cali_idx")) + { + curr_tray->cali_idx = (*tray_it)["cali_idx"].get(); + } + } + // remove not in trayList + for (auto tray_it = tray_id_set.begin(); tray_it != tray_id_set.end(); tray_it++) + { + std::string tray_id = *tray_it; + auto tray = curr_ams->GetTrays().find(tray_id); + if (tray != curr_ams->GetTrays().end()) + { + curr_ams->m_trays.erase(tray_id); + BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id << ", tray_id=" << tray_id; + } + } + } + } + // remove not in amsList + for (auto it = ams_id_set.begin(); it != ams_id_set.end(); it++) + { + std::string ams_id = *it; + auto ams = system->amsList.find(ams_id); + if (ams != system->amsList.end()) + { + BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id; + system->amsList.erase(ams_id); + } + } + } + } + } +} + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFilaSystem.h b/src/slic3r/GUI/DeviceCore/DevFilaSystem.h new file mode 100644 index 0000000..afe8000 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFilaSystem.h @@ -0,0 +1,196 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" +#include "slic3r/Utils/json_diff.hpp" + +#include "DevDefs.h" +#include "DevFilaAmsSetting.h" + +#include +#include +#include + +#define HOLD_COUNT_MAX 3 + +namespace Slic3r +{ +class MachineObject; + +class DevAmsTray +{ +public: + DevAmsTray(std::string tray_id) + { + is_qdt = false; + id = tray_id; + } + + std::string id; + std::string tag_uid; // tag_uid + std::string setting_id; // tray_info_idx + std::string filament_setting_id; // setting_id + std::string type; + std::string sub_brands; + std::string color; + std::vector cols; + std::string weight; + std::string diameter; + std::string temp; + std::string time; + std::string bed_temp_type; + std::string bed_temp; + std::string nozzle_temp_max; + std::string nozzle_temp_min; + std::string xcam_info; + std::string uuid; + int ctype = 0; + float k = 0.0f; // k range: 0 ~ 0.5 + float n = 0.0f; // k range: 0.6 ~ 2.0 + int cali_idx = -1; // - 1 means default + + wxColour wx_color; + bool is_qdt; + bool is_exists = false; + int hold_count = 0; + int remain = 0; // filament remain: 0 ~ 100 + +public: + // operators + bool operator==(DevAmsTray const& o) const + { + return id == o.id && type == o.type && filament_setting_id == o.filament_setting_id && color == o.color; + } + bool operator!=(DevAmsTray const& o) const { return !operator==(o); } + + // setters + void reset(); + void UpdateColorFromStr(const std::string& color); + void set_hold_count() { hold_count = HOLD_COUNT_MAX; } + + // getter + bool is_tray_info_ready() const; + bool is_unset_third_filament() const; + + wxColour get_color() const { return decode_color(color); }; + + std::string get_display_filament_type() const; + std::string get_filament_type(); + + // static + static wxColour decode_color(const std::string& color); +}; + +class DevAms +{ + friend class DevFilaSystemParser; +public: + enum AmsType : int + { + DUMMY = 0, + AMS = 1, // AMS + AMS_LITE = 2, // AMS-Lite + N3F = 3, // N3F + N3S = 4, // N3S + }; + +public: + DevAms(const std::string& ams_id, int extruder_id, AmsType type); + DevAms(const std::string& ams_id, int nozzle_id, int type); + ~DevAms(); + +public: + std::string GetAmsId() const { return m_ams_id; } + wxString GetDisplayName() const; // display + + void SetAmsType(int type) { m_ams_type = (AmsType)type; } + void SetAmsType(AmsType type) { m_ams_type = type; } + AmsType GetAmsType() const { return m_ams_type; } + + // exist or not + bool IsExist() const { return m_exist; } + + // slots + int GetSlotCount() const; + DevAmsTray* GetTray(const std::string& tray_id) const; + const std::map& GetTrays() const { return m_trays; } + + // installed on the extruder + int GetExtruderId() const { return m_ext_id; } + + // temperature and humidity + float GetCurrentTemperature() const { return m_current_temperature; } + + bool SupportHumidity() const { return (m_ams_type == AMS) || (m_ams_type == N3F) || (m_ams_type == N3S);} + int GetHumidityLevel() const { return m_humidity_level; } + int GetHumidityPercent() const { return m_humidity_percent; } + + bool SupportDrying() const { return m_ams_type > AMS_LITE; } + int GetLeftDryTime() const { return m_left_dry_time; } + +private: + AmsType m_ams_type = AmsType::AMS; + std::string m_ams_id; + int m_ext_id;//extruder id + bool m_exist = false; + + // slots and trays + std::map m_trays;//id -> DevAmsTray* + + // temperature and humidity + float m_current_temperature = INVALID_AMS_TEMPERATURE; // the temperature + int m_humidity_level = 5; // AmsType::AMS + int m_humidity_percent = -1; // N3F N3S, the percentage, -1 means invalid. eg. 100 means 100% + int m_left_dry_time = 0; +}; + +class DevFilaSystem +{ + friend class DevFilaSystemParser; +public: + DevFilaSystem(MachineObject* owner) { m_owner = owner;}; + ~DevFilaSystem(); + +public: + bool HasAms() const { return !amsList.empty(); } + bool IsAmsSettingUp() const; + + /* ams */ + DevAms* GetAmsById(const std::string& ams_id) const; + std::map& GetAmsList() { return amsList; } + int GetAmsCount() const { return amsList.size(); } + + /* tray*/ + DevAmsTray* GetAmsTray(const std::string& ams_id, const std::string& tray_id) const; + void CollectAmsColors(std::vector& ams_colors) const; + + // extruder + int GetExtruderIdByAmsId(const std::string& ams_id) const; + + /* AMS settings*/ + DevAmsSystemSetting& GetAmsSystemSetting() { return m_ams_system_setting; } + bool IsDetectOnInsertEnabled() const { return m_ams_system_setting.IsDetectOnInsertEnabled(); }; + bool IsDetectOnPowerupEnabled() const { return m_ams_system_setting.IsDetectOnPowerupEnabled(); } + bool IsDetectRemainEnabled() const { return m_ams_system_setting.IsDetectRemainEnabled(); } + bool IsAutoRefillEnabled() const { return m_ams_system_setting.IsAutoRefillEnabled(); } + +public: + static bool IsQDT_Filament(std::string tag_uid); + +private: + MachineObject* m_owner; + + /* ams properties */ + int m_ams_cali_stat = 0; + + std::map amsList; // key: ams[id], start with 0 + + DevAmsSystemSetting m_ams_system_setting{ this }; +};// class DevFilaSystem + + +class DevFilaSystemParser +{ +public: + static void ParseV1_0(const json& print_json, MachineObject* obj, DevFilaSystem* system, bool key_field_only); +}; + +}// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevFirmware.cpp b/src/slic3r/GUI/DeviceCore/DevFirmware.cpp new file mode 100644 index 0000000..1975bbe --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFirmware.cpp @@ -0,0 +1,2 @@ +#include "DevFirmware.h" +#include "slic3r/GUI/DeviceManager.hpp" diff --git a/src/slic3r/GUI/DeviceCore/DevFirmware.h b/src/slic3r/GUI/DeviceCore/DevFirmware.h new file mode 100644 index 0000000..2f45da4 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevFirmware.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include "slic3r/Utils/json_diff.hpp" + +namespace Slic3r { + +//Previous definitions +class MachineObject; + +enum PrinterFirmwareType +{ + FIRMWARE_TYPE_ENGINEER = 0, + FIRMWARE_TYPE_PRODUCTION, + FIRMEARE_TYPE_UKNOWN, +}; + + +class FirmwareInfo +{ +public: + std::string module_type; // ota or ams + std::string version; + std::string url; + std::string name; + std::string description; +}; + + +class DevFirmwareVersionInfo +{ +public: + std::string name; + wxString product_name; + std::string sn; + std::string hw_ver; + std::string sw_ver; + std::string sw_new_ver; + int firmware_flag = 0; + +public: + bool isValid() const { return !sn.empty(); } + bool isAirPump() const { return product_name.Contains("Air Pump"); } + bool isLaszer() const { return product_name.Contains("Laser"); } + bool isCuttingModule() const { return product_name.Contains("Cutting Module"); } + bool isExtinguishSystem() const { return product_name.Contains("Extinguishing System"); } +}; + + +class DevFirmware +{ +public: + DevFirmware(MachineObject* obj) : m_owner(obj) {} + +private: + MachineObject* m_owner = nullptr; +}; + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevHMS.cpp b/src/slic3r/GUI/DeviceCore/DevHMS.cpp new file mode 100644 index 0000000..639421c --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevHMS.cpp @@ -0,0 +1,67 @@ +//#include "D:/dev/bamboo_slicer/build_release/src/slic3r/CMakeFiles/libslic3r_gui.dir/Release/cmake_pch.hxx" +#include "DevHMS.h" + +namespace Slic3r +{ + +bool DevHMSItem::parse_hms_info(unsigned attr, unsigned code) +{ + bool result = true; + unsigned int model_id_int = (attr >> 24) & 0xFF; + this->m_module_id = (ModuleID)model_id_int; + this->m_module_num = (attr >> 16) & 0xFF; + this->m_part_id = (attr >> 8) & 0xFF; + this->m_reserved = (attr >> 0) & 0xFF; + unsigned msg_level_int = code >> 16; + if (msg_level_int < (unsigned)HMS_MSG_LEVEL_MAX) + { + this->m_msg_level = (HMSMessageLevel)msg_level_int; + } + else + { + this->m_msg_level = HMS_UNKNOWN; + } + + this->m_msg_code = code & 0xFFFF; + return result; +} + +std::string DevHMSItem::get_long_error_code() const +{ + char buf[64]; + ::sprintf(buf, "%02X%02X%02X00000%1X%04X", + this->m_module_id, + this->m_module_num, + this->m_part_id, + (int)this->m_msg_level, + this->m_msg_code); + return std::string(buf); +} + +void DevHMS::ParseHMSItems(const json& hms_json) +{ + m_hms_list.clear(); + + try + { + if (hms_json.is_array()) + { + for (auto it = hms_json.begin(); it != hms_json.end(); it++) + { + DevHMSItem item; + if ((*it).contains("attr") && (*it).contains("code")) + { + unsigned attr = (*it)["attr"].get(); + unsigned code = (*it)["code"].get(); + item.parse_hms_info(attr, code); + } + m_hms_list.push_back(item); + } + } + } + catch (const std::exception&) + { + assert(false && "Parse HMS items failed"); + } +} +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevHMS.h b/src/slic3r/GUI/DeviceCore/DevHMS.h new file mode 100644 index 0000000..205cad7 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevHMS.h @@ -0,0 +1,84 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include +#include + +namespace Slic3r +{ +// Previous definitions +class MachineObject; +class DevHMSItem; + +class DevHMS +{ +public: + DevHMS(MachineObject* obj) : m_object(obj) {} + +public: + void ParseHMSItems(const json& hms_json); + const std::vector& GetHMSItems() const { return m_hms_list; }; + +private: + MachineObject* m_object = nullptr; + + // all hms for this machine + std::vector m_hms_list; +}; + +enum HMSMessageLevel +{ + HMS_UNKNOWN = 0, + HMS_FATAL = 1, + HMS_SERIOUS = 2, + HMS_COMMON = 3, + HMS_INFO = 4, + HMS_MSG_LEVEL_MAX, +}; + +enum ModuleID +{ + MODULE_UKNOWN = 0x00, + MODULE_01 = 0x01, + MODULE_02 = 0x02, + MODULE_MC = 0x03, + MODULE_04 = 0x04, + MODULE_MAINBOARD = 0x05, + MODULE_06 = 0x06, + MODULE_AMS = 0x07, + MODULE_TH = 0x08, + MODULE_09 = 0x09, + MODULE_10 = 0x0A, + MODULE_11 = 0x0B, + MODULE_XCAM = 0x0C, + MODULE_13 = 0x0D, + MODULE_14 = 0x0E, + MODULE_15 = 0x0F, + MODULE_MAX = 0x10 +}; + +class DevHMSItem +{ +public: + std::string get_long_error_code() const; + HMSMessageLevel get_level() const { return m_msg_level; } + + void set_read() { m_already_read = true; }; + bool has_read() const { return m_already_read; }; + +protected: + friend void DevHMS::ParseHMSItems(const json& hms_json); + bool parse_hms_info(unsigned attr, unsigned code); + +private: + ModuleID m_module_id; + unsigned m_module_num; + unsigned m_part_id; + unsigned m_reserved; + HMSMessageLevel m_msg_level = HMS_UNKNOWN; + int m_msg_code = 0; + bool m_already_read = false; +}; + +};// End of namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevInfo.cpp b/src/slic3r/GUI/DeviceCore/DevInfo.cpp new file mode 100644 index 0000000..4c97ee3 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevInfo.cpp @@ -0,0 +1,7 @@ +#include "DevInfo.h" +#include "slic3r/GUI/DeviceManager.hpp" + +namespace Slic3r +{ + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevInfo.h b/src/slic3r/GUI/DeviceCore/DevInfo.h new file mode 100644 index 0000000..bc48e6c --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevInfo.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" +#include + +namespace Slic3r { + +class MachineObject; + +/* some static info of machine*/ /*TODO*/ +class DevInfo +{ +public: + DevInfo(MachineObject* obj) : m_owner(obj) {}; + +public: + //std::string GetDevName() const { return m_dev_name; } + //std::string GetDevId() const { return m_dev_id; } + //std::string GetDevIP() const { return m_dev_ip; } + //std::string GetPrinterTypeStr() const { return m_printer_type_str; } + //std::string GetPrinterSignal() const { return m_printer_signal; } + //std::string GetConnectType() const { return m_connect_type; } + //std::string GetBindState() const { return m_bind_state; } + +private: + //std::string m_dev_name; + //std::string m_dev_id; + //std::string m_dev_ip; + //std::string m_printer_type_str; + //std::string m_printer_signal; + //std::string m_connect_type; + //std::string m_bind_state; + + MachineObject* m_owner = nullptr; +}; + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevLamp.cpp b/src/slic3r/GUI/DeviceCore/DevLamp.cpp new file mode 100644 index 0000000..19fd83e --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevLamp.cpp @@ -0,0 +1,18 @@ +#include "DevLamp.h" + +static Slic3r::DevLamp::LIGHT_EFFECT _light_effect_parse(std::string effect_str) +{ + if (effect_str.compare("on") == 0) + return Slic3r::DevLamp::LIGHT_EFFECT_ON; + else if (effect_str.compare("off") == 0) + return Slic3r::DevLamp::LIGHT_EFFECT_OFF; + else if (effect_str.compare("flashing") == 0) + return Slic3r::DevLamp::LIGHT_EFFECT_FLASHING; + + return Slic3r::DevLamp::LIGHT_EFFECT_UNKOWN; +} + +void Slic3r::DevLamp::SetChamberLight(const std::string& status) +{ + m_chamber_light = _light_effect_parse(status); +} diff --git a/src/slic3r/GUI/DeviceCore/DevLamp.h b/src/slic3r/GUI/DeviceCore/DevLamp.h new file mode 100644 index 0000000..205563c --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevLamp.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +namespace Slic3r +{ + + class MachineObject; + class DevLamp + { + public: + DevLamp(MachineObject* obj) : m_owner(obj) {}; + + public: + enum LIGHT_EFFECT + { + LIGHT_EFFECT_ON, + LIGHT_EFFECT_OFF, + LIGHT_EFFECT_FLASHING, + LIGHT_EFFECT_UNKOWN, + }; + + public: + void SetChamberLight(const std::string& status); + void SetChamberLight(LIGHT_EFFECT effect) { m_chamber_light = effect; } + bool IsChamberLightOn() const { return m_chamber_light == LIGHT_EFFECT_ON || m_chamber_light == LIGHT_EFFECT_FLASHING; } + + void SetLampCloseRecheck(bool enable) { m_lamp_close_recheck = enable;}; + bool HasLampCloseRecheck() const { return m_lamp_close_recheck; } + + public: + void CtrlSetChamberLight(LIGHT_EFFECT effect); + + private: + int command_set_chamber_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); + int command_set_chamber_light2(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); + + private: + MachineObject* m_owner = nullptr; + + bool m_lamp_close_recheck = false; + LIGHT_EFFECT m_chamber_light = LIGHT_EFFECT_UNKOWN; + }; +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevLampCtrl.cpp b/src/slic3r/GUI/DeviceCore/DevLampCtrl.cpp new file mode 100644 index 0000000..b35adc5 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevLampCtrl.cpp @@ -0,0 +1,64 @@ +#include +#include "DevLamp.h" + +// TODO: remove this include +#include "slic3r/GUI/DeviceManager.hpp" + +using namespace nlohmann; + +namespace Slic3r +{ + + +static std::string _light_effect_str(DevLamp::LIGHT_EFFECT effect) +{ + switch (effect) + { + case Slic3r::DevLamp::LIGHT_EFFECT_ON: + return "on"; + case Slic3r::DevLamp::LIGHT_EFFECT_OFF: + return "off"; + case Slic3r::DevLamp::LIGHT_EFFECT_FLASHING: + return "flashing"; + default: + return "unknown"; + } + return "unknown"; +} + +void DevLamp::CtrlSetChamberLight(LIGHT_EFFECT effect) +{ + // copied from others, TODO CHECK + command_set_chamber_light(effect); + command_set_chamber_light2(effect); +} + +int DevLamp::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) +{ + json j; + j["system"]["command"] = "ledctrl"; + j["system"]["led_node"] = "chamber_light"; + j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["system"]["led_mode"] = _light_effect_str(effect); + j["system"]["led_on_time"] = on_time; + j["system"]["led_off_time"] = off_time; + j["system"]["loop_times"] = loops; + j["system"]["interval_time"] = interval; + return m_owner->publish_json(j); +} + +int DevLamp::command_set_chamber_light2(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) +{ + json j; + j["system"]["command"] = "ledctrl"; + j["system"]["led_node"] = "chamber_light2"; + j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["system"]["led_mode"] = _light_effect_str(effect); + j["system"]["led_on_time"] = on_time; + j["system"]["led_off_time"] = off_time; + j["system"]["loop_times"] = loops; + j["system"]["interval_time"] = interval; + return m_owner->publish_json(j); +} + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevManager.cpp b/src/slic3r/GUI/DeviceCore/DevManager.cpp new file mode 100644 index 0000000..6bf14a0 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevManager.cpp @@ -0,0 +1,845 @@ +#include +#include "DevManager.h" +#include "DevUtil.h" + +// TODO: remove this include +#include "slic3r/GUI/DeviceManager.hpp" +#include "slic3r/GUI/I18N.hpp" +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/Utils/QDTUtil.hpp" + +#include "libslic3r/Time.hpp" + +using namespace nlohmann; + +namespace Slic3r +{ + DeviceManager::DeviceManager(NetworkAgent* agent) + { + m_agent = agent; + m_refresher = new DeviceManagerRefresher(this); + + DevPrinterConfigUtil::InitFilePath(resources_dir()); + } + + DeviceManager::~DeviceManager() + { + delete m_refresher; + + for (auto it = localMachineList.begin(); it != localMachineList.end(); it++) + { + if (it->second) + { + delete it->second; + it->second = nullptr; + } + } + localMachineList.clear(); + + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (it->second) + { + delete it->second; + it->second = nullptr; + } + } + userMachineList.clear(); + } + + + void DeviceManager::EnableMultiMachine(bool enable) + { + m_agent->enable_multi_machine(enable); + m_enable_mutil_machine = enable; + } + + void DeviceManager::start_refresher() { m_refresher->Start(); } + void DeviceManager::stop_refresher() { m_refresher->Stop(); } + + + void DeviceManager::keep_alive() + { + MachineObject* obj = this->get_selected_machine(); + if (obj) + { + if (obj->keep_alive_count == 0) + { + obj->last_keep_alive = std::chrono::system_clock::now(); + } + obj->keep_alive_count++; + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + auto internal = std::chrono::duration_cast(start - obj->last_keep_alive); + if (internal.count() > TIMEOUT_FOR_KEEPALIVE && (internal.count() < 1000 * 60 * 60 * 300)) + { + BOOST_LOG_TRIVIAL(info) << "keep alive = " << internal.count() << ", count = " << obj->keep_alive_count; + obj->command_request_push_all(); + obj->last_keep_alive = start; + } + else if (obj->m_push_count == 0) + { + BOOST_LOG_TRIVIAL(info) << "keep alive = " << internal.count() << ", push_count = 0, count = " << obj->keep_alive_count; + obj->command_request_push_all(); + obj->last_keep_alive = start; + } + } + } + + void DeviceManager::check_pushing() + { + keep_alive(); + MachineObject* obj = this->get_selected_machine(); + + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + auto internal = std::chrono::duration_cast(start - obj->last_update_time); + + if (obj && !obj->is_support_mqtt_alive) + { + if (internal.count() > TIMEOUT_FOR_STRAT && internal.count() < 1000 * 60 * 60 * 300) + { + BOOST_LOG_TRIVIAL(info) << "command_pushing: diff = " << internal.count(); + obj->command_pushing("start"); + } + } + } + + void DeviceManager::on_machine_alive(std::string json_str) + { + try { + json j = json::parse(json_str); + std::string dev_name = j["dev_name"].get(); + std::string dev_id = j["dev_id"].get(); + std::string dev_ip = j["dev_ip"].get(); + std::string printer_type_str= j["dev_type"].get(); + std::string printer_signal = j["dev_signal"].get(); + std::string connect_type = j["connect_type"].get(); + std::string bind_state = j["bind_state"].get(); + + if (connect_type == "farm") { + connect_type ="lan"; + bind_state = "free"; + } + + std::string sec_link = ""; + std::string ssdp_version = ""; + if (j.contains("sec_link")) { + sec_link = j["sec_link"].get(); + } + if (j.contains("ssdp_version")) { + ssdp_version = j["ssdp_version"].get(); + } + std::string connection_name = ""; + if (j.contains("connection_name")) { + connection_name = j["connection_name"].get(); + } + + MachineObject* obj; + + /* update userMachineList info */ + auto it = userMachineList.find(dev_id); + if (it != userMachineList.end()) { + if (it->second->get_dev_ip() != dev_ip || + it->second->bind_state != bind_state || + it->second->bind_sec_link != sec_link || + it->second->dev_connection_type != connect_type || + it->second->bind_ssdp_version != ssdp_version) + { + if (it->second->bind_state != bind_state) { + OnMachineBindStateChanged(it->second, bind_state); + } + + it->second->set_dev_ip(dev_ip); + it->second->bind_state = bind_state; + it->second->bind_sec_link = sec_link; + it->second->dev_connection_type = connect_type; + it->second->bind_ssdp_version = ssdp_version; + 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; + } + } + + /* update localMachineList */ + it = localMachineList.find(dev_id); + if (it != localMachineList.end()) { + // update properties + /* ip changed */ + obj = it->second; + + if (obj->get_dev_ip().compare(dev_ip) != 0) { + if ( connection_name.empty() ) { + BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << QDTCrossTalk::Crosstalk_DevIP(obj->get_dev_ip()) + << " to " << QDTCrossTalk::Crosstalk_DevIP(dev_ip); + obj->set_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 " << QDTCrossTalk::Crosstalk_DevIP(obj->get_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->set_dev_ip(dev_ip); + } + } + /* ip changed reconnect mqtt */ + } + + if (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 != _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 != _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 = _parse_printer_type(printer_type_str); + } + + // U0 firmware + if (obj->dev_connection_type.empty() && obj->bind_state.empty()) + obj->bind_state = "free"; + + obj->last_alive = Slic3r::Utils::get_current_time_utc(); + obj->m_is_online = true; + + /* if (!obj->dev_ip.empty()) { + Slic3r::GUI::wxGetApp().app_config->set_str("ip_address", obj->dev_id, obj->dev_ip); + Slic3r::GUI::wxGetApp().app_config->save(); + }*/ + } + else { + /* insert a new machine */ + obj = new MachineObject(this, m_agent, dev_name, dev_id, dev_ip); + obj->printer_type = _parse_printer_type(printer_type_str); + obj->wifi_signal = printer_signal; + obj->dev_connection_type = connect_type; + obj->bind_state = bind_state; + obj->bind_sec_link = sec_link; + obj->dev_connection_name = connection_name; + obj->bind_ssdp_version = ssdp_version; + obj->m_is_online = true; + + //load access code + AppConfig* config = Slic3r::GUI::wxGetApp().app_config; + if (config) { + obj->set_access_code(Slic3r::GUI::wxGetApp().app_config->get("access_code", dev_id), false); + obj->set_user_access_code(Slic3r::GUI::wxGetApp().app_config->get("user_access_code", dev_id), false); + } + localMachineList.insert(std::make_pair(dev_id, obj)); + + /* if (!obj->dev_ip.empty()) { + 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) << __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 (...) { + ; + } + } + + MachineObject* DeviceManager::insert_local_device(std::string dev_name, std::string dev_id, + std::string dev_ip, std::string connection_type, std::string bind_state, + std::string version, std::string access_code, std::string printer_type) + { + MachineObject* obj; + obj = new MachineObject(this, m_agent, dev_name, dev_id, dev_ip); + if (printer_type.empty()) + obj->printer_type = _parse_printer_type("C11"); + else + obj->printer_type = _parse_printer_type(printer_type); + 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; + } + + int DeviceManager::query_bind_status(std::string& msg) + { + if (!m_agent) + { + msg = ""; + return -1; + } + + BOOST_LOG_TRIVIAL(trace) << "DeviceManager::query_bind_status"; + std::map::iterator it; + std::vector query_list; + for (it = localMachineList.begin(); it != localMachineList.end(); it++) + { + query_list.push_back(it->first); + } + + unsigned int http_code; + std::string http_body; + int result = m_agent->query_bind_status(query_list, &http_code, &http_body); + + if (result < 0) + { + msg = (boost::format("code=%1%,body=%2") % http_code % http_body).str(); + } + else + { + msg = ""; + try + { + json j = json::parse(http_body); + if (j.contains("bind_list")) + { + + for (auto& item : j["bind_list"]) + { + auto it = localMachineList.find(item["dev_id"].get()); + if (it != localMachineList.end()) + { + if (!item["user_id"].is_null()) + it->second->bind_user_id = item["user_id"].get(); + if (!item["user_name"].is_null()) + it->second->bind_user_name = item["user_name"].get(); + else + it->second->bind_user_name = "Free"; + } + } + } + } + catch (...) + { + ; + } + } + return result; + } + + MachineObject* DeviceManager::get_user_machine(std::string dev_id) + { + if (!m_agent || !m_agent->is_user_login()) + { + return nullptr; + } + + std::map::iterator it = userMachineList.find(dev_id); + if (it == userMachineList.end()) return nullptr; + return it->second; + } + + MachineObject* DeviceManager::get_my_machine(std::string dev_id) + { + auto list = get_my_machine_list(); + auto it = list.find(dev_id); + if (it != list.end()) + { + return it->second; + } + return nullptr; + } + + void DeviceManager::clean_user_info() + { + BOOST_LOG_TRIVIAL(trace) << "DeviceManager::clean_user_info"; + // reset selected_machine + selected_machine = ""; + local_selected_machine = ""; + + // clean user list + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (it->second) + { + it->second->set_access_code(""); + delete it->second; + it->second = nullptr; + } + } + userMachineList.clear(); + } + + bool DeviceManager::set_selected_machine(std::string 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); + + // disconnect last + auto last_selected = my_machine_list.find(selected_machine); + if (last_selected != my_machine_list.end()) + { + if (last_selected->second->connection_type() == "lan") + { + m_agent->disconnect_printer(); + } + } + + // connect curr + if (it != my_machine_list.end()) + { + if (selected_machine == dev_id) + { + if (it->second->connection_type() != "lan") + { + // only reset update time + it->second->reset_update_time(); + + // check subscribe state + Slic3r::GUI::wxGetApp().on_start_subscribe_again(dev_id); + + return true; + } + else + { + // lan mode printer reconnect printer + if (m_agent) + { + 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); +#else + it->second->connect(it->second->local_use_ssl_for_mqtt); +#endif + it->second->set_lan_mode_connection_state(true); + } + } + } + else + { + if (m_agent) + { + if (it->second->connection_type() != "lan" || it->second->connection_type().empty()) + { + if (m_agent->get_user_selected_machine() == dev_id) + { + it->second->reset_update_time(); + } + else + { + BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = " << QDTCrossTalk::Crosstalk_DevId(dev_id); + m_agent->set_user_selected_machine(dev_id); + it->second->reset(); + } + } + else + { + BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = empty"; + it->second->reset(); +#if !QDT_RELEASE_TO_PUBLIC + it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); +#else + it->second->connect(it->second->local_use_ssl_for_mqtt); +#endif + it->second->set_lan_mode_connection_state(true); + } + } + } + for (auto& data : it->second->m_nozzle_filament_data) + { + data.second.checked_filament.clear(); + } + } + selected_machine = dev_id; + return true; + } + + MachineObject* DeviceManager::get_selected_machine() + { + if (selected_machine.empty()) return nullptr; + + MachineObject* obj = get_user_machine(selected_machine); + if (obj) + return obj; + + // return local machine has access code + auto it = localMachineList.find(selected_machine); + if (it != localMachineList.end()) + { + if (it->second->has_access_right()) + return it->second; + } + 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: " << QDTCrossTalk::Crosstalk_DevId(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: " << QDTCrossTalk::Crosstalk_DevId(it->first); + } + m_agent->del_subscribe(dev_list); + } + + void DeviceManager::subscribe_device_list(std::vector dev_list) + { + std::vector unsub_list; + subscribe_list_cache.clear(); + 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 = " << QDTCrossTalk::Crosstalk_DevId(it); + } + } + BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: unsub_list size = " << unsub_list.size(); + + if (!selected_machine.empty()) + { + subscribe_list_cache.push_back(selected_machine); + } + for (auto& it : dev_list) + { + subscribe_list_cache.push_back(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()) + m_agent->del_subscribe(unsub_list); + if (!dev_list.empty()) + m_agent->add_subscribe(subscribe_list_cache); + } + + std::map DeviceManager::get_my_machine_list() + { + std::map result; + + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (it->second && !it->second->is_lan_mode_printer()) + { + result.insert(std::make_pair(it->first, it->second)); + } + } + + for (auto it = localMachineList.begin(); it != localMachineList.end(); it++) + { + if (it->second && 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()) + { + result.emplace(std::make_pair(it->first, it->second)); + } + } + } + return result; + } + + std::map DeviceManager::get_my_cloud_machine_list() + { + std::map result; + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (it->second && !it->second->is_lan_mode_printer()) { result.emplace(*it); } + } + return result; + } + + std::string DeviceManager::get_first_online_user_machine() const + { + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (it->second && it->second->is_online()) + { + return it->second->get_dev_id(); + } + } + return ""; + } + + void DeviceManager::modify_device_name(std::string dev_id, std::string dev_name) + { + BOOST_LOG_TRIVIAL(trace) << "modify_device_name"; + if (m_agent) + { + int result = m_agent->modify_printer_name(dev_id, dev_name); + if (result == 0) + { + update_user_machine_list_info(); + } + } + } + + void DeviceManager::parse_user_print_info(std::string body) + { + if (device_subseries.size() <= 0) { + device_subseries = DevPrinterConfigUtil::get_all_subseries(); + if (device_subseries.size() <= 0) { + device_subseries.insert(std::pair>("", std::vector())); + } + } + + BOOST_LOG_TRIVIAL(trace) << "DeviceManager::parse_user_print_info"; + std::lock_guard lock(listMutex); + std::set new_list; + try + { + json j = json::parse(body); + +#if !QDT_RELEASE_TO_PUBLIC + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << QDTCrossTalk::Crosstalk_JsonLog(j); +#endif + + if (j.contains("devices") && !j["devices"].is_null()) + { + for (auto& elem : j["devices"]) + { + MachineObject* obj = nullptr; + std::string dev_id; + if (!elem["dev_id"].is_null()) + { + dev_id = elem["dev_id"].get(); + new_list.insert(dev_id); + } + std::map::iterator iter = userMachineList.find(dev_id); + if (iter != userMachineList.end()) + { + /* update field */ + obj = iter->second; + obj->set_dev_id(dev_id); + } + else + { + obj = new MachineObject(this, m_agent, "", "", ""); + if (m_agent) + { + obj->set_bind_status(m_agent->get_user_name()); + } + + if (obj->get_dev_ip().empty()) + { + obj->get_dev_ip() = Slic3r::GUI::wxGetApp().app_config->get("ip_address", dev_id); + } + userMachineList.insert(std::make_pair(dev_id, obj)); + } + + if (!obj) continue; + + if (!elem["dev_id"].is_null()) + obj->set_dev_id(elem["dev_id"].get()); + if (!elem["dev_name"].is_null()) + obj->set_dev_name(elem["dev_name"].get()); + if (!elem["dev_online"].is_null()) + obj->m_is_online = elem["dev_online"].get(); + if (elem.contains("dev_model_name") && !elem["dev_model_name"].is_null()) { + auto printer_type = elem["dev_model_name"].get(); + for (const std::pair> &pair : device_subseries) { + auto it = std::find(pair.second.begin(), pair.second.end(), printer_type); + if (it != pair.second.end()) + { + obj->printer_type = Slic3r::_parse_printer_type(pair.first); + break; + } + else + { + obj->printer_type = Slic3r::_parse_printer_type(printer_type); + } + } + } + if (!elem["task_status"].is_null()) + obj->iot_print_status = elem["task_status"].get(); + if (elem.contains("dev_product_name") && !elem["dev_product_name"].is_null()) + obj->dev_product_name = elem["dev_product_name"].get(); + if (elem.contains("dev_access_code") && !elem["dev_access_code"].is_null()) + { + std::string acc_code = elem["dev_access_code"].get(); + acc_code.erase(std::remove(acc_code.begin(), acc_code.end(), '\n'), acc_code.end()); + obj->set_access_code(acc_code); + } + } + + //remove MachineObject from userMachineList + std::map::iterator iterat; + for (iterat = userMachineList.begin(); iterat != userMachineList.end(); ) + { + if (new_list.find(iterat->first) == new_list.end()) + { + iterat = userMachineList.erase(iterat); + } + else + { + iterat++; + } + } + } + } + catch (std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " exception=" << e.what(); + } + } + + void DeviceManager::update_user_machine_list_info() + { + if (!m_agent) return; + + BOOST_LOG_TRIVIAL(debug) << "update_user_machine_list_info"; + unsigned int http_code; + std::string body; + int result = m_agent->get_user_print_info(&http_code, &body); + if (result == 0) + { + parse_user_print_info(body); + } + } + + void DeviceManager::load_last_machine() + { + if (userMachineList.empty()) return; + + else if (userMachineList.size() == 1) + { + this->set_selected_machine(userMachineList.begin()->second->get_dev_id()); + } + else + { + if (m_agent) + { + std::string last_monitor_machine = m_agent->get_user_selected_machine(); + bool found = false; + for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) + { + if (last_monitor_machine == it->first) + { + this->set_selected_machine(last_monitor_machine); + found = true; + } + } + if (!found) + this->set_selected_machine(userMachineList.begin()->second->get_dev_id()); + } + } + } + + void DeviceManager::OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state) + { + if (!obj) { return; } + if (obj->get_dev_id() == selected_machine) + { + if (new_state == "free") { OnSelectedMachineLost(); } + } + } + + void DeviceManager::OnSelectedMachineLost() + { + GUI::wxGetApp().sidebar().update_sync_status(nullptr); + GUI::wxGetApp().sidebar().load_ams_list(string(), nullptr); + } + + void DeviceManager::reload_printer_settings() + { + for (auto obj : this->userMachineList) { obj.second->reload_printer_settings(); }; + } + + + DeviceManagerRefresher::DeviceManagerRefresher(DeviceManager* manger) : wxObject() + { + m_manager = manger; + m_timer = new wxTimer(); + m_timer->Bind(wxEVT_TIMER, &DeviceManagerRefresher::on_timer, this); + } + + DeviceManagerRefresher::~DeviceManagerRefresher() + { + m_timer->Stop(); + delete m_timer; + } + + void DeviceManagerRefresher::on_timer(wxTimerEvent& event) + { + if (!m_manager) { return; } + + NetworkAgent* agent = m_manager->get_agent(); + if (!agent) { return; } + + // reset to active + Slic3r::GUI::wxGetApp().reset_to_active(); + + MachineObject* obj = m_manager->get_selected_machine(); + if (!obj) { return; } + + // check valid machine + if (obj && m_manager->get_my_machine(obj->get_dev_id()) == nullptr) + { + m_manager->set_selected_machine(""); + agent->set_user_selected_machine(""); + return; + } + + // do some refresh + if (Slic3r::GUI::wxGetApp().is_user_login()) + { + m_manager->check_pushing(); + try + { + agent->refresh_connection(); + } + catch (...) + { + ; + } + } + + // certificate + agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer()); + } +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevManager.h b/src/slic3r/GUI/DeviceCore/DevManager.h new file mode 100644 index 0000000..5b267cd --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevManager.h @@ -0,0 +1,126 @@ +#pragma once +#include +#include "libslic3r/CommonDefs.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include +#include + +namespace Slic3r +{ +//Previous definitions +class MachineObject; +class NetworkAgent; + +class DeviceManagerRefresher; +class DeviceManager +{ + friend class DeviceManagerRefresher; +private: + NetworkAgent* m_agent{ nullptr }; + DeviceManagerRefresher* m_refresher{ nullptr }; + + bool m_enable_mutil_machine = false; + + std::mutex listMutex; + std::string selected_machine; /* dev_id */ + std::string local_selected_machine; /* dev_id */ + std::map localMachineList; /* dev_id -> MachineObject*, localMachine SSDP */ + std::map userMachineList; /* dev_id -> MachineObject* cloudMachine of User */ + +public: + DeviceManager(NetworkAgent* agent = nullptr); + ~DeviceManager(); + +public: + NetworkAgent* get_agent() const { return m_agent; } + void set_agent(NetworkAgent* agent) { m_agent = agent; } + + void start_refresher(); + void stop_refresher(); + + MachineObject* get_selected_machine(); + bool set_selected_machine(std::string dev_id); + + // local machine + void set_local_selected_machine(std::string dev_id) { local_selected_machine = dev_id; }; + MachineObject* get_local_selected_machine() const { return get_local_machine(local_selected_machine); } + + // local machine list + void erase_local_machine(std::string dev_id) { localMachineList.erase(dev_id); } + std::map get_local_machinelist() const { return localMachineList; } + MachineObject* get_local_machine(std::string dev_id) const + { + auto it = localMachineList.find(dev_id); + return (it != localMachineList.end()) ? it->second : nullptr; + } + + // user machine + std::map get_user_machinelist() const { return userMachineList; } + std::string get_first_online_user_machine() const; + void erase_user_machine(std::string dev_id) { userMachineList.erase(dev_id); } + void clean_user_info(); + + void load_last_machine(); + void update_user_machine_list_info(); + void parse_user_print_info(std::string body); + void reload_printer_settings(); + + MachineObject* get_user_machine(std::string dev_id); + + // subscribe + void add_user_subscribe(); + void del_user_subscribe(); + void subscribe_device_list(std::vector dev_list); + + /* my machine*/ + MachineObject* get_my_machine(std::string dev_id); + std::map get_my_machine_list(); + std::map get_my_cloud_machine_list(); + void modify_device_name(std::string dev_id, std::string dev_name); + + /* create machine or update machine properties */ + void on_machine_alive(std::string json_str); + int query_bind_status(std::string& msg); + + // mutil-device + void EnableMultiMachine(bool enable = true); + bool IsMultiMachineEnabled() const { return m_enable_mutil_machine; } + std::vector subscribe_list_cache;//multiple machine subscribe list cache + std::map> device_subseries; + +private: + void keep_alive(); + void check_pushing(); + + void OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state); + void OnSelectedMachineLost(); + + + /*TODO*/ +public: + // to remove + MachineObject* insert_local_device(std::string dev_name, std::string dev_id, std::string dev_ip, + std::string connection_type, std::string bind_state, std::string version, + std::string access_code, std::string printer_type); +}; + +class DeviceManagerRefresher : public wxObject +{ + wxTimer* m_timer{ nullptr }; + int m_timer_interval_msec = 1000; + + DeviceManager* m_manager{ nullptr }; + +public: + DeviceManagerRefresher(DeviceManager* manger); + ~DeviceManagerRefresher(); + +public: + void Start() { m_timer->Start(m_timer_interval_msec); } + void Stop() { m_timer->Stop(); } + +protected: + virtual void on_timer(wxTimerEvent& event); +}; +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevMapping.cpp b/src/slic3r/GUI/DeviceCore/DevMapping.cpp new file mode 100644 index 0000000..9dbdf3e --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevMapping.cpp @@ -0,0 +1,428 @@ +#include +#include "DevMapping.h" +#include "DevFilaSystem.h" +#include "DevUtil.h" + +// TODO: remove this include +#include "slic3r/GUI/DeviceManager.hpp" +#include "slic3r/GUI/I18N.hpp" +#include "slic3r/GUI/GuiColor.hpp" + +//y71 +#include "../GUI_App.hpp" + +using namespace nlohmann; + +namespace Slic3r +{ + bool DevMappingUtil::is_valid_mapping_result(const MachineObject* obj, std::vector& result, bool check_empty_slot) + { + if (result.empty()) return false; + + for (int i = 0; i < result.size(); i++) + { + // invalid mapping result + if (result[i].tray_id < 0) + { + if (result[i].ams_id.empty() && result[i].slot_id.empty()) + { + return false; + } + } + else + { + + auto ams_item = obj->GetFilaSystem()->GetAmsById(result[i].ams_id); + if (ams_item == nullptr) + { + if ((result[i].ams_id != std::to_string(VIRTUAL_TRAY_MAIN_ID)) && + (result[i].ams_id != std::to_string(VIRTUAL_TRAY_DEPUTY_ID))) + { + result[i].tray_id = -1; + return false; + } + } + else + { + if (check_empty_slot) + { + auto tray_item = ams_item->GetTrays().find(result[i].slot_id); + if (tray_item == ams_item->GetTrays().end()) + { + result[i].tray_id = -1; + return false; + } + else + { + if (!tray_item->second->is_exists) + { + result[i].tray_id = -1; + return false; + } + } + } + } + } + } + return true; + } + + // calc distance map + struct DisValue { + int tray_id; + float distance; + bool is_same_color = true; + bool is_type_match = true; + }; + + static void _parse_tray_info(int ams_id, int slot_id, DevAms::AmsType type, DevAmsTray tray, FilamentInfo& result) + { + result.color = tray.color; + result.type = tray.get_filament_type(); + result.filament_id = tray.setting_id; + result.ctype = tray.ctype; + result.colors = tray.cols; + + /*for new ams mapping*/ + result.ams_id = std::to_string(ams_id); + result.slot_id = std::to_string(slot_id); + + if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) + { + result.tray_id = atoi(tray.id.c_str()); + result.id = atoi(tray.id.c_str()); + } + else + { + if (type == DevAms::N3S) + { + result.id = ams_id + slot_id; + } + else + { + result.id = ams_id * 4 + slot_id; + } + } + } + + int DevMappingUtil::ams_filament_mapping(const MachineObject* obj, const std::vector& filaments, std::vector& result, std::vector map_opt, std::vector exclude_id, bool nozzle_has_ams_then_ignore_ext) + { + if (filaments.empty()) + return -1; + + ///////////////////////// + // Step 1: collect filaments in machine + std::map tray_filaments; // tray_index : tray_color + bool left_nozzle_has_ams = false, right_nozzle_has_ams = false; + + //y71 + std::vector filament_colors = GUI::wxGetApp().plater()->box_msg.filament_colors; + std::vector filament_type = GUI::wxGetApp().plater()->box_msg.filament_type; + std::vector filament_id = GUI::wxGetApp().plater()->box_msg.filament_id; + std::vector slot_id = GUI::wxGetApp().plater()->box_msg.slot_id; + int box_count = GUI::wxGetApp().plater()->box_msg.box_count; + + if (filament_colors.empty()) + return -1; + + std::vector box_filament_infos; + for (int i = 0; i < filament_colors.size(); i++) { + if (!filament_colors[i].empty() && slot_id[i] != -1) { + FilamentInfo box_fila_info; + box_fila_info.color = filament_colors[i].erase(0, 1) + "FF"; + box_fila_info.type = filament_type[i]; + box_fila_info.filament_id = filament_id[i]; + box_fila_info.slot_id = std::to_string(slot_id[i]); + box_fila_info.ams_id = std::to_string(slot_id[i] / 4 + 1); + box_filament_infos.push_back(box_fila_info); + } + } + + // const auto& ams_list = obj->GetFilaSystem()->GetAmsList(); + // for (auto ams = ams_list.begin(); ams != ams_list.end(); ams++) + // { + // std::string ams_id = ams->second->GetAmsId(); + // auto ams_type = ams->second->GetAmsType(); + // for (auto tray = ams->second->GetTrays().begin(); tray != ams->second->GetTrays().end(); tray++) + // { + // int ams_id = atoi(ams->first.c_str()); + // int tray_id = atoi(tray->first.c_str()); + // int tray_index = 0; + // if (ams_type == DevAms::AMS || ams_type == DevAms::AMS_LITE || ams_type == DevAms::N3F) + // { + // tray_index = ams_id * 4 + tray_id; + // } + // else if (ams_type == DevAms::N3S) + // { + // tray_index = ams_id + tray_id; + // } + // else + // { + // assert(0); + // } + + // // skip exclude id + // for (int i = 0; i < exclude_id.size(); i++) + // { + // if (tray_index == exclude_id[i]) + // continue; + // } + // // push + // FilamentInfo info; + // if (tray->second->is_tray_info_ready()) + // { + // _parse_tray_info(ams_id, tray_id, ams_type, *(tray->second), info); + // } + + // //first: left,nozzle=1,map=1 second: right,nozzle=0,map=2 + // bool right_ams_valid = ams->second->GetExtruderId() == 0 && map_opt[MappingOption::USE_RIGHT_AMS]; + // bool left_ams_valid = ams->second->GetExtruderId() == 1 && map_opt[MappingOption::USE_LEFT_AMS]; + // if (right_ams_valid || left_ams_valid) + // { + // tray_filaments.emplace(std::make_pair(tray_index, info)); + // if (right_ams_valid) + // { + // right_nozzle_has_ams = true; + // } + // if (left_ams_valid) + // { + // left_nozzle_has_ams = true; + // } + // } + // } + // } + + if (map_opt[MappingOption::USE_RIGHT_EXT] || map_opt[MappingOption::USE_LEFT_EXT]) + { + for (auto tray : obj->vt_slot) + { + bool right_ext_valid = (tray.id == std::to_string(VIRTUAL_TRAY_MAIN_ID) && map_opt[MappingOption::USE_RIGHT_EXT]); + bool left_ext_valid = (tray.id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID) && map_opt[MappingOption::USE_LEFT_EXT]); + if (right_ext_valid || left_ext_valid) + { + if (nozzle_has_ams_then_ignore_ext) + { + if (right_ext_valid && right_nozzle_has_ams) + { + continue; + } + if (left_ext_valid && left_nozzle_has_ams) + { + continue; + } + } + FilamentInfo info; + _parse_tray_info(atoi(tray.id.c_str()), 0, DevAms::DUMMY, tray, info); + tray_filaments.emplace(std::make_pair(info.tray_id, info)); + } + } + } + + ///////////////////////// + // Step 2: collect the distances of filaments_in_slicing to filaments_in_machine + char buffer[256]; + std::vector> distance_map; + + // print title + ::sprintf(buffer, "F(id)"); + std::string line = std::string(buffer); + for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) + { + ::sprintf(buffer, " BOX%02d", tray->second.id + 1); + line += std::string(buffer); + } + BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line;// Print the collected filaments + + //y71 + for (int i = 0; i < filaments.size(); i++) + { + std::vector rol; + ::sprintf(buffer, "F(%02d)", filaments[i].id + 1); + line = std::string(buffer); + // for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) + // { + // DisValue val; + // val.tray_id = tray->second.id; + // wxColour c = wxColour(filaments[i].color); + // wxColour tray_c = DevAmsTray::decode_color(tray->second.color); + // val.distance = GUI::calc_color_distance(c, tray_c); + // if (filaments[i].type != tray->second.type) + // { + // val.distance = 999999; + // val.is_type_match = false; + // } + // else + // { + // if (c.Alpha() != tray_c.Alpha()) + // val.distance = 999999; + // val.is_type_match = true; + // } + // ::sprintf(buffer, " %6.0f", val.distance); + // line += std::string(buffer); + // rol.push_back(val); + // } + for(int j = 0; j < box_filament_infos.size(); j++){ + DisValue val; + val.tray_id = j; + wxColour c = wxColour(filaments[i].color); + wxColour tray_c = DevAmsTray::decode_color(box_filament_infos[j].color); + val.distance = GUI::calc_color_distance(c, tray_c); + if (filaments[i].type != box_filament_infos[j].type) { + val.distance = 999999; + val.is_type_match = false; + } else { + if (c.Alpha() != tray_c.Alpha()) + val.distance = 999999; + val.is_type_match = true; + } + ::sprintf(buffer, " %6.0f", val.distance); + line += std::string(buffer); + rol.push_back(val); + } + BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line; + distance_map.push_back(rol); + } + + ///////////////////////// + // Step 3: do mapping algorithm + + // setup the mapping result + for (int i = 0; i < filaments.size(); i++) + { + FilamentInfo info; + info.id = filaments[i].id; + info.tray_id = -1; + info.type = filaments[i].type; + info.filament_id = filaments[i].filament_id; + result.push_back(info); + } + + // traverse the mapping + std::set picked_src; + std::set picked_tar; + //y59 y68 + for (int k = 0; k < distance_map.size(); k++) + { + float min_val = INT_MAX; + int picked_src_idx = -1; + int picked_tar_idx = -1; + for (int i = 0; i < distance_map.size(); i++) + { + if (picked_src.find(i) != picked_src.end()) + continue; + + // 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; + // } + continue; + } + + 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; + } + //y71 + // 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 + if (picked_src_idx >= 0 && picked_tar_idx >= 0) + { + // auto tray = tray_filaments.find(distance_map[k][picked_tar_idx].tray_id); + + // if (tray != tray_filaments.end()) + // { + // result[picked_src_idx].tray_id = tray->first; + + // result[picked_src_idx].color = tray->second.color; + // result[picked_src_idx].type = tray->second.type; + // result[picked_src_idx].distance = tray->second.distance; + // result[picked_src_idx].filament_id = tray->second.filament_id; + // //result[picked_src_idx].ctype = tray->second.ctype; + // result[picked_src_idx].colors = tray->second.colors; + + // /*for new ams mapping*/ + // result[picked_src_idx].ams_id = tray->second.ams_id; + // result[picked_src_idx].slot_id = tray->second.slot_id; + // } + + // ::sprintf(buffer, "ams_mapping, picked F(%02d) AMS(%02d), distance=%6.0f", picked_src_idx + 1, picked_tar_idx + 1, + // distance_map[picked_src_idx][picked_tar_idx].distance); + // BOOST_LOG_TRIVIAL(info) << std::string(buffer); + + result[picked_src_idx].tray_id = distance_map[k][picked_tar_idx].tray_id; + result[picked_src_idx].color = box_filament_infos[picked_tar_idx].color; + result[picked_src_idx].type = box_filament_infos[picked_tar_idx].type; + result[picked_src_idx].distance = distance_map[k][picked_tar_idx].distance; + result[picked_src_idx].filament_id = box_filament_infos[picked_tar_idx].filament_id; + result[picked_src_idx].ams_id = box_filament_infos[picked_tar_idx].ams_id; + result[picked_src_idx].slot_id = box_filament_infos[picked_tar_idx].slot_id; + + picked_src.insert(picked_src_idx); + picked_tar.insert(picked_tar_idx); + } + } + + // //check ams mapping result + // if (DevMappingUtil::is_valid_mapping_result(obj, result, true)) + // { + // return 0; + // } + + /* for (auto it = result.begin(); it != result.end(); it++) {//This code has never been effective before 2025.03.18 + if (it->distance >= 6000) { + it->tray_id = -1; + } + }*/ + return 0; + } + +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevMapping.h b/src/slic3r/GUI/DeviceCore/DevMapping.h new file mode 100644 index 0000000..e3169a0 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevMapping.h @@ -0,0 +1,33 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" +#include "libslic3r/ProjectTask.hpp" + +#include "slic3r/Utils/json_diff.hpp" +#include + +namespace Slic3r +{ +//Previous definitions +class MachineObject; + +enum MappingOption +{ + USE_LEFT_AMS = 0, + USE_RIGHT_AMS, + USE_LEFT_EXT, + USE_RIGHT_EXT +}; + +class DevMappingUtil +{ +public: + DevMappingUtil() = delete; + ~DevMappingUtil() = delete; + +public: + static bool is_valid_mapping_result(const MachineObject* obj, std::vector& result, bool check_empty_slot = false); + + static int ams_filament_mapping(const MachineObject* obj, const std::vector& filaments, std::vector& result, std::vector map_opt, std::vector exclude_id = std::vector(), bool nozzle_has_ams_then_ignore_ext = false); +}; + +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevNozzleSystem.cpp b/src/slic3r/GUI/DeviceCore/DevNozzleSystem.cpp new file mode 100644 index 0000000..24fb40b --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevNozzleSystem.cpp @@ -0,0 +1,141 @@ +#include "DevExtruderSystem.h" +#include "DevNozzleSystem.h" +#include "DevUtil.h" + +#include "slic3r/GUI/DeviceManager.hpp" + +namespace Slic3r +{ + +DevNozzle DevNozzleSystem::GetNozzle(int id) const +{ + if (m_nozzles.find(id) != m_nozzles.end()) + { + return m_nozzles.at(id); + } + + return DevNozzle(); +} + +void DevNozzleSystem::Reset() +{ + m_nozzles.clear(); + m_extder_exist = 0; + m_state = 0; // idle state +} + + +static unordered_map _str2_nozzle_flow_type = { + {"S", NozzleFlowType::S_FLOW}, + {"H", NozzleFlowType::H_FLOW}, + {"A", NozzleFlowType::S_FLOW}, + {"X", NozzleFlowType::S_FLOW} +}; + +static unordered_map _str2_nozzle_type = { + {"00", NozzleType::ntStainlessSteel}, + {"01", NozzleType::ntHardenedSteel}, + {"05", NozzleType::ntTungstenCarbide} +}; + +static void s_parse_nozzle_type(const std::string& nozzle_type_str, DevNozzle& nozzle) +{ + if (NozzleTypeStrToEumn.count(nozzle_type_str) != 0) + { + nozzle.m_nozzle_type = NozzleTypeStrToEumn[nozzle_type_str]; + } + else if (nozzle_type_str.length() >= 4) + { + const std::string& flow_type_str = nozzle_type_str.substr(1, 1); + if (_str2_nozzle_flow_type.count(flow_type_str) != 0) + { + nozzle.m_nozzle_flow = _str2_nozzle_flow_type[flow_type_str]; + } + const std::string& type_str = nozzle_type_str.substr(2, 2); + if (_str2_nozzle_type.count(type_str) != 0) + { + nozzle.m_nozzle_type = _str2_nozzle_type[type_str]; + } + } +} + + +void DevNozzleSystemParser::ParseV1_0(const nlohmann::json& nozzletype_json, + const nlohmann::json& diameter_json, + const int& nozzle_flow_type, + DevNozzleSystem* system) +{ + //Since both the old and new protocols push data. + // assert(system->m_nozzles.size() < 2); + DevNozzle nozzle; + nozzle.m_nozzle_id = 0; + nozzle.m_nozzle_flow = NozzleFlowType::S_FLOW; // default flow type + + { + float nozzle_diameter = 0.0f; + if (diameter_json.is_number_float()) + { + nozzle_diameter = diameter_json.get(); + } + else if (diameter_json.is_string()) + { + nozzle_diameter = DevUtil::string_to_float(diameter_json.get()); + } + + if (nozzle_diameter == 0.0f) + { + nozzle.m_diameter = 0.0f; + } + else + { + nozzle.m_diameter = round(nozzle_diameter * 10) / 10; + } + } + + { + if (nozzletype_json.is_string()) + { + s_parse_nozzle_type(nozzletype_json.get(), nozzle); + } + } + + { + if (nozzle_flow_type != -1) { + // 0: QDT S_FLOW; 1:E3D H_FLOW (only P) + if (nozzle_flow_type == 1) { + nozzle.m_nozzle_flow = NozzleFlowType::H_FLOW; + } else { + nozzle.m_nozzle_flow = NozzleFlowType::S_FLOW; + } + } + } + + system->m_nozzles[nozzle.m_nozzle_id] = nozzle; +} + + +void DevNozzleSystemParser::ParseV2_0(const json& nozzle_json, DevNozzleSystem* system) +{ + system->Reset(); + + if (nozzle_json.contains("exist")) + { + system->m_extder_exist = DevUtil::get_flag_bits(nozzle_json["exist"].get(), 0, 16); + } + + if (nozzle_json.contains("state")) + { + system->m_state = DevUtil::get_flag_bits(nozzle_json["state"].get(), 0, 4); + } + + for (auto it = nozzle_json["info"].begin(); it != nozzle_json["info"].end(); it++) + { + DevNozzle nozzle_obj; + const auto& njon = it.value(); + nozzle_obj.m_nozzle_id = njon["id"].get(); + nozzle_obj.m_diameter = njon["diameter"].get(); + s_parse_nozzle_type(njon["type"].get(), nozzle_obj); + system->m_nozzles[nozzle_obj.m_nozzle_id] = nozzle_obj; + } +} +} \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevNozzleSystem.h b/src/slic3r/GUI/DeviceCore/DevNozzleSystem.h new file mode 100644 index 0000000..93b3928 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevNozzleSystem.h @@ -0,0 +1,50 @@ +#pragma once +#include "libslic3r/CommonDefs.hpp" +#include "slic3r/Utils/json_diff.hpp" + +#include +#include + +namespace Slic3r +{ + // Previous definitions + class MachineObject; + + struct DevNozzle + { + int m_nozzle_id = -1; + NozzleFlowType m_nozzle_flow = NozzleFlowType::S_FLOW;// 0-common 1-high flow + NozzleType m_nozzle_type = NozzleType::ntUndefine;// 0-stainless_steel 1-hardened_steel 5-tungsten_carbide + float m_diameter = 0.4f;// 0.2mm 0.4mm 0.6mm 0.8mm + }; + + class DevNozzleSystem + { + friend class DevNozzleSystemParser; + public: + DevNozzleSystem(MachineObject* owner) : m_owner(owner) {} + + public: + bool ContainsNozzle(int id) const { return m_nozzles.find(id) != m_nozzles.end(); } + DevNozzle GetNozzle(int id) const; + const std::map& GetNozzles() const { return m_nozzles;} + + private: + void Reset(); + + private: + MachineObject* m_owner = nullptr; + + int m_extder_exist = 0; //0- none exist 1-exist, unused + int m_state = 0; //0-idle 1-checking, unused + std::map m_nozzles; + + }; + + class DevNozzleSystemParser + { + public: + static void ParseV1_0(const nlohmann::json& nozzletype_json, const nlohmann::json& diameter_json, const int& nozzle_flow_type, DevNozzleSystem* system); + static void ParseV2_0(const json& nozzle_json, DevNozzleSystem* system); + }; +}; \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevPrintOptions.cpp b/src/slic3r/GUI/DeviceCore/DevPrintOptions.cpp new file mode 100644 index 0000000..9083c75 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevPrintOptions.cpp @@ -0,0 +1,280 @@ +#include "DevPrintOptions.h" +#include "DevUtil.h" + +#include "slic3r/GUI/DeviceManager.hpp" + +namespace Slic3r +{ + +void DevPrintOptionsParser::Parse(DevPrintOptions* opts, const nlohmann::json& print_json) +{ + try + { + if (print_json.contains("spd_lvl")) + { + opts->m_speed_level = static_cast(print_json["spd_lvl"].get()); + } + + if (print_json.contains("cfg")) + { + const std::string& cfg = print_json["cfg"].get(); + opts->m_speed_level = (DevPrintingSpeedLevel)DevUtil::get_flag_bits(cfg, 8, 3); + } + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << "DevPrintOptionsParser::Parse: Failed to parse print options from JSON." << e.what(); + } +} + +void DevPrintOptionsParser::ParseDetectionV1_0(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json) +{ + try { + if (print_json.contains("xcam")) { + if (time(nullptr) - opts->xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { + if (print_json["xcam"].contains("printing_monitor")) { + // new protocol + opts->xcam_ai_monitoring = print_json["xcam"]["printing_monitor"].get(); + } else { + // old version protocol + if (print_json["xcam"].contains("spaghetti_detector")) { + opts->xcam_ai_monitoring = print_json["xcam"]["spaghetti_detector"].get(); + if (print_json["xcam"].contains("print_halt")) { + bool print_halt = print_json["xcam"]["print_halt"].get(); + if (print_halt) { opts->xcam_ai_monitoring_sensitivity = "medium"; } + } + } + } + if (print_json["xcam"].contains("halt_print_sensitivity")) { + opts->xcam_ai_monitoring_sensitivity = print_json["xcam"]["halt_print_sensitivity"].get(); + } + } + + if (time(nullptr) - opts->xcam_first_layer_hold_start > HOLD_TIME_3SEC) { + if (print_json["xcam"].contains("first_layer_inspector")) { opts->xcam_first_layer_inspector = print_json["xcam"]["first_layer_inspector"].get(); } + } + + if (time(nullptr) - opts->xcam_buildplate_marker_hold_start > HOLD_TIME_3SEC) { + if (print_json["xcam"].contains("buildplate_marker_detector")) { + opts->xcam_buildplate_marker_detector = print_json["xcam"]["buildplate_marker_detector"].get(); + obj->is_support_build_plate_marker_detect = true; + } else { + obj->is_support_build_plate_marker_detect = false; + } + } + } + } catch (...) { + ; + } + +} + +void DevPrintOptionsParser::ParseDetectionV1_1(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json,bool enable) +{ + if (print_json["module_name"].get() == "first_layer_inspector") { + if (time(nullptr) - opts->xcam_first_layer_hold_start > HOLD_TIME_3SEC) { + opts->xcam_first_layer_inspector = enable; + } + } else if (print_json["module_name"].get() == "buildplate_marker_detector") { + if (time(nullptr) - opts->xcam_buildplate_marker_hold_start > HOLD_TIME_3SEC) { + opts->xcam_buildplate_marker_detector = enable; + } + } else if (print_json["module_name"].get() == "printing_monitor") { + if (time(nullptr) - opts->xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { + opts->xcam_ai_monitoring = enable; + if (print_json.contains("halt_print_sensitivity")) { + opts->xcam_ai_monitoring_sensitivity = print_json["halt_print_sensitivity"].get(); + } + } + } else if (print_json["module_name"].get() == "spaghetti_detector") { + if (time(nullptr) - opts->xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { + // old protocol + opts->xcam_ai_monitoring = enable; + if (print_json.contains("print_halt")) { + if (print_json["print_halt"].get()) { opts->xcam_ai_monitoring_sensitivity = "medium"; } + } + } + } +} + +void DevPrintOptionsParser::ParseDetectionV1_2(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json) { + + try { + if (print_json.contains("option")) { + if (print_json["option"].is_number()) { + int option = print_json["option"].get(); + if (time(nullptr) - opts->xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { opts->xcam_auto_recovery_step_loss = ((option & 0x01) != 0); } + } + } + + + if (time(nullptr) - opts->xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { + if (print_json.contains("auto_recovery")) { opts->xcam_auto_recovery_step_loss = print_json["auto_recovery"].get(); } + } + } catch (...) {} + +} + +void DevPrintOptionsParser::ParseDetectionV2_0(DevPrintOptions *opts, std::string print_json) +{ + + if (time(nullptr) - opts->xcam_first_layer_hold_start > HOLD_TIME_3SEC) { + opts->xcam_first_layer_inspector = DevUtil::get_flag_bits(print_json, 12); + } + + if (time(nullptr) - opts->xcam_ai_monitoring_hold_start > HOLD_COUNT_MAX) { + opts->xcam_ai_monitoring = DevUtil::get_flag_bits(print_json, 15); + + switch (DevUtil::get_flag_bits(print_json, 13, 2)) { + case 0: opts->xcam_ai_monitoring_sensitivity = "never_halt"; break; + case 1: opts->xcam_ai_monitoring_sensitivity = "low"; break; + case 2: opts->xcam_ai_monitoring_sensitivity = "medium"; break; + case 3: opts->xcam_ai_monitoring_sensitivity = "high"; break; + default: break; + } + } + + if (time(nullptr) - opts->xcam_auto_recovery_hold_start > HOLD_COUNT_MAX){ + opts->xcam_auto_recovery_step_loss =DevUtil::get_flag_bits(print_json, 16); + } + + if (time(nullptr) - opts->xcam_prompt_sound_hold_start > HOLD_TIME_3SEC) { + opts->xcam_allow_prompt_sound = DevUtil::get_flag_bits(print_json, 22); + } + + if (time(nullptr) - opts->xcam_filament_tangle_detect_hold_start > HOLD_TIME_3SEC) { + opts->xcam_filament_tangle_detect = DevUtil::get_flag_bits(print_json, 23); + } + +} + +void DevPrintOptions::SetPrintingSpeedLevel(DevPrintingSpeedLevel speed_level) +{ + if (speed_level >= SPEED_LEVEL_INVALID && speed_level < SPEED_LEVEL_COUNT) + { + m_speed_level = speed_level; + } + else + { + m_speed_level = SPEED_LEVEL_INVALID; // Reset to invalid if out of range + } +} + +int DevPrintOptions::command_xcam_control_ai_monitoring(bool on_off, std::string lvl) +{ + bool print_halt = (lvl == "never_halt") ? false : true; + + xcam_ai_monitoring = on_off; + xcam_ai_monitoring_hold_start = time(nullptr); + xcam_ai_monitoring_sensitivity = lvl; + return command_xcam_control("printing_monitor", on_off, m_obj, lvl); + +} +int DevPrintOptions::command_xcam_control_buildplate_marker_detector(bool on_off) +{ + xcam_buildplate_marker_detector = on_off; + xcam_buildplate_marker_hold_start = time(nullptr); + return command_xcam_control("buildplate_marker_detector", on_off ,m_obj); +} + +int DevPrintOptions::command_xcam_control_first_layer_inspector(bool on_off, bool print_halt) +{ + xcam_first_layer_inspector = on_off; + xcam_first_layer_hold_start = time(nullptr); + return command_xcam_control("first_layer_inspector", on_off, m_obj); +} + +int DevPrintOptions::command_xcam_control_auto_recovery_step_loss(bool on_off) +{ + xcam_auto_recovery_step_loss = on_off; + xcam_auto_recovery_hold_start = time(nullptr); + return command_set_printing_option(on_off, m_obj); +} + +int DevPrintOptions::command_xcam_control_allow_prompt_sound(bool on_off) +{ + xcam_allow_prompt_sound = on_off; + xcam_prompt_sound_hold_start = time(nullptr); + return command_set_prompt_sound(on_off, m_obj); +} + +int DevPrintOptions::command_xcam_control_filament_tangle_detect(bool on_off) +{ + xcam_filament_tangle_detect = on_off; + xcam_filament_tangle_detect_hold_start = time(nullptr); + return command_set_filament_tangle_detect(on_off, m_obj); +} + +void DevPrintOptions::parse_auto_recovery_step_loss_status(int flag) { + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { + xcam_auto_recovery_step_loss = ((flag >> 4) & 0x1) != 0; + } +} + +void DevPrintOptions::parse_allow_prompt_sound_status(int flag) +{ + if (time(nullptr) - xcam_prompt_sound_hold_start > HOLD_TIME_3SEC) { + xcam_allow_prompt_sound = ((flag >> 17) & 0x1) != 0; + } +} + +void DevPrintOptions::parse_filament_tangle_detect_status(int flag) +{ + if (time(nullptr) - xcam_filament_tangle_detect_hold_start > HOLD_TIME_3SEC) { + xcam_filament_tangle_detect = ((flag >> 20) & 0x1) != 0; + } +} + +int DevPrintOptions::command_xcam_control(std::string module_name, bool on_off , MachineObject *obj, std::string lvl) +{ + json j; + j["xcam"]["command"] = "xcam_control_set"; + j["xcam"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["xcam"]["module_name"] = module_name; + j["xcam"]["control"] = on_off; + j["xcam"]["enable"] = on_off; // old protocol + j["xcam"]["print_halt"] = true; // old protocol + 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 obj->publish_json(j); +} + +int DevPrintOptions::command_set_printing_option(bool auto_recovery, MachineObject *obj) +{ + json j; + j["print"]["command"] = "print_option"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["option"] = (int) auto_recovery; + j["print"]["auto_recovery"] = auto_recovery; + + return obj->publish_json(j); +} + +int DevPrintOptions::command_set_prompt_sound(bool prompt_sound, MachineObject *obj) +{ + json j; + j["print"]["command"] = "print_option"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["sound_enable"] = prompt_sound; + + return obj->publish_json(j); +} + +int DevPrintOptions::command_set_filament_tangle_detect(bool filament_tangle_detect, MachineObject *obj) +{ + json j; + j["print"]["command"] = "print_option"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["print"]["filament_tangle_detect"] = filament_tangle_detect; + + return obj->publish_json(j); +} + + + + + + + +} +// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevPrintOptions.h b/src/slic3r/GUI/DeviceCore/DevPrintOptions.h new file mode 100644 index 0000000..0de681b --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevPrintOptions.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" +#include + +#include "DevDefs.h" + +namespace Slic3r { + +class MachineObject; + +class DevPrintOptions +{ + friend class DevPrintOptionsParser; +public: + DevPrintOptions(MachineObject* obj): m_obj(obj) {} + + +public: + void SetPrintingSpeedLevel(DevPrintingSpeedLevel speed_level); + DevPrintingSpeedLevel GetPrintingSpeedLevel() const { return m_speed_level;} + + // detect options + int command_xcam_control_ai_monitoring(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); + int command_xcam_control_allow_prompt_sound(bool on_off); + int command_xcam_control_filament_tangle_detect(bool on_off); + + + int command_xcam_control(std::string module_name, bool on_off, MachineObject *obj ,std::string lvl = ""); + // set print option + int command_set_printing_option(bool auto_recovery, MachineObject *obj); + // set prompt sound + int command_set_prompt_sound(bool prompt_sound, MachineObject *obj); + // set fliament tangle detect + int command_set_filament_tangle_detect(bool fliament_tangle_detect, MachineObject *obj); + + + void parse_auto_recovery_step_loss_status(int flag); + void parse_allow_prompt_sound_status(int flag); + void parse_filament_tangle_detect_status(int flag); + + bool GetAiMonitoring() const { return xcam_ai_monitoring; }; + bool GetFirstLayerInspector() const{ return xcam_first_layer_inspector; }; + bool GetBuildplateMarkerDetector() const { return xcam_buildplate_marker_detector; }; + bool GetAutoRecoveryStepLoss() const { return xcam_auto_recovery_step_loss; }; + bool GetAllowPromptSound() const { return xcam_allow_prompt_sound; }; + bool GetFilamentTangleDetect() const { return xcam_filament_tangle_detect; }; + + string GetAiMonitoringSensitivity() const { return xcam_ai_monitoring_sensitivity; }; + + +private: + // print option + DevPrintingSpeedLevel m_speed_level = SPEED_LEVEL_INVALID; + + // detect options + bool xcam_ai_monitoring{false}; + + std::string xcam_ai_monitoring_sensitivity; + bool xcam_buildplate_marker_detector{false}; + bool xcam_first_layer_inspector{false}; + bool xcam_auto_recovery_step_loss{false}; + bool xcam_allow_prompt_sound{false}; + bool xcam_filament_tangle_detect{false}; + time_t xcam_ai_monitoring_hold_start = 0; + time_t xcam_buildplate_marker_hold_start = 0; + time_t xcam_first_layer_hold_start = 0; + time_t xcam_auto_recovery_hold_start = 0; + time_t xcam_prompt_sound_hold_start = 0; + time_t xcam_filament_tangle_detect_hold_start = 0; + + MachineObject* m_obj;/*owner*/ +}; + +class DevPrintOptionsParser +{ +public: + static void Parse(DevPrintOptions* opts, const nlohmann::json& print_json); + + //V1 stands for parse_json; V2 stands for parse_new_json + static void ParseDetectionV1_0(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json); + static void ParseDetectionV1_1(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json, bool enable); + static void ParseDetectionV1_2(DevPrintOptions *opts, MachineObject *obj, const nlohmann::json &print_json); + + static void ParseDetectionV2_0(DevPrintOptions *opts, std::string print_json); +}; + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.cpp b/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.cpp new file mode 100644 index 0000000..a2d6391 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.cpp @@ -0,0 +1 @@ +#include "DevPrintTaskInfo.h" \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.h b/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.h new file mode 100644 index 0000000..a244692 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevPrintTaskInfo.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +// TODO classes to handle dev print task management and ratings + +namespace Slic3r +{ + +struct DevPrintTaskRatingInfo +{ + bool request_successful; + int http_code; + int rating_id; + int start_count; + bool success_printed; + std::string content; + std::vector image_url_paths; +}; + +class DevPrintTaskInfo +{ + +}; + +}// end namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevStorage.cpp b/src/slic3r/GUI/DeviceCore/DevStorage.cpp new file mode 100644 index 0000000..14623b0 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevStorage.cpp @@ -0,0 +1,34 @@ +#include "DevStorage.h" +#include "slic3r/GUI/DeviceManager.hpp" + + +namespace Slic3r { + +DevStorage::SdcardState Slic3r::DevStorage::set_sdcard_state(int state) + +{ + if (state < DevStorage::NO_SDCARD || state > DevStorage::SDCARD_STATE_NUM) { + m_sdcard_state = DevStorage::NO_SDCARD; + } else { + m_sdcard_state = DevStorage::SdcardState(state); + } + return m_sdcard_state; +} + + void DevStorage::ParseV1_0(const json &print_json, DevStorage *system) +{ + if (system) + { + if (print_json.contains("sdcard")) { + if (print_json["sdcard"].get()) + system->m_sdcard_state = DevStorage::SdcardState::HAS_SDCARD_NORMAL; + else + system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD; + } else { + system->m_sdcard_state = DevStorage::SdcardState::NO_SDCARD; + } + } +} + + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevStorage.h b/src/slic3r/GUI/DeviceCore/DevStorage.h new file mode 100644 index 0000000..e64be27 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevStorage.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include "slic3r/Utils/json_diff.hpp" + +namespace Slic3r { + +class MachineObject; + + +class DevStorage +{ +public: + DevStorage(MachineObject *obj) : m_owner(obj){} + +public: + + enum SdcardState : int { + NO_SDCARD = 0, + HAS_SDCARD_NORMAL = 1, + HAS_SDCARD_ABNORMAL = 2, + HAS_SDCARD_READONLY = 3, + SDCARD_STATE_NUM = 4 + }; + + /* sdcard */ + SdcardState get_sdcard_state() const { return m_sdcard_state; }; + SdcardState set_sdcard_state(int state); + + static void ParseV1_0(const json &print_json, DevStorage *system); + +private: + MachineObject *m_owner; + SdcardState m_sdcard_state { NO_SDCARD }; +}; + +} // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevUtil.cpp b/src/slic3r/GUI/DeviceCore/DevUtil.cpp new file mode 100644 index 0000000..27cec11 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevUtil.cpp @@ -0,0 +1,114 @@ +#include "DevUtil.h" +#include "fast_float/fast_float.h" + +namespace Slic3r +{ + +int DevUtil::get_flag_bits(std::string str, int start, int count) +{ + try + { + unsigned long long decimal_value = std::stoull(str, nullptr, 16); + unsigned long long mask = (1ULL << count) - 1; + int flag = (decimal_value >> start) & mask; + return flag; + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed"; + } + + return 0; +} + +int DevUtil::get_flag_bits(int num, int start, int count, int base) +{ + try + { + unsigned long long mask = (1ULL << count) - 1; + unsigned long long value; + if (base == 10) + { + value = static_cast(num); + } + else if (base == 16) + { + value = static_cast(std::stoul(std::to_string(num), nullptr, 16)); + } + else + { + throw std::invalid_argument("Unsupported base"); + } + + int flag = (value >> start) & mask; + return flag; + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed"; + } + + return 0; +} + +float DevUtil::string_to_float(const std::string& str_value) +{ + float value = 0.0f; + + try + { + fast_float::from_chars(str_value.c_str(), str_value.c_str() + str_value.size(), value); + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed"; + } + + return value; +} + +std::string DevUtil::convertToIp(long long ip) +{ + std::stringstream ss; + ss << ((ip >> 0) & 0xFF) << "." << ((ip >> 8) & 0xFF) << "." << ((ip >> 16) & 0xFF) << "." << ((ip >> 24) & 0xFF); + return ss.str(); +} + +std::string DevJsonValParser::get_longlong_val(const nlohmann::json& j) +{ + try + { + if (j.is_number()) + { + return std::to_string(j.get()); + } + else if (j.is_string()) + { + return j.get(); + } + } + catch (const nlohmann::json::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + catch (const std::exception& e) + { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + + return std::string(); +} + +};// namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceCore/DevUtil.h b/src/slic3r/GUI/DeviceCore/DevUtil.h new file mode 100644 index 0000000..4282d31 --- /dev/null +++ b/src/slic3r/GUI/DeviceCore/DevUtil.h @@ -0,0 +1,72 @@ +/** + * @file DevUtil.h + * @brief Provides common static utility methods for general use. + * + * This class offers a collection of static helper functions such as string manipulation, + * file operations, and other frequently used utilities. + */ + +#pragma once +#include +#include +#include + +#include +#include "nlohmann/json.hpp" + +namespace Slic3r +{ + +class DevUtil +{ +public: + DevUtil() = delete; + DevUtil(const DevUtil&) = delete; + DevUtil& operator=(const DevUtil&) = delete; + +public: + static int get_flag_bits(std::string str, int start, int count = 1); + static int get_flag_bits(int num, int start, int count = 1, int base = 10); + + static float string_to_float(const std::string& str_value); + + static std::string convertToIp(long long ip); +}; + + +class DevJsonValParser +{ +public: + template + static void ParseVal(const nlohmann::json& j, const std::string& key, T& val) + { + try + { + if (j.contains(key)) { val = j[key].get(); } + } + catch (const nlohmann::json::exception& e) + { + assert(0 && __FUNCTION__); + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + } + + template + static void ParseVal(const nlohmann::json& j, const std::string& key, T& val, T default_val) + { + try + { + j.contains(key) ? (val = j[key].get()) : (val = default_val); + } + catch (const nlohmann::json::exception& e) + { + assert(0 && __FUNCTION__); + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what(); + } + } + +public: + static std::string get_longlong_val(const nlohmann::json& j); +}; + +}; // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceErrorDialog.cpp b/src/slic3r/GUI/DeviceErrorDialog.cpp new file mode 100644 index 0000000..65699c6 --- /dev/null +++ b/src/slic3r/GUI/DeviceErrorDialog.cpp @@ -0,0 +1,496 @@ +#include "DeviceErrorDialog.hpp" +#include "HMS.hpp" + +#include "Widgets/Button.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" +#include "ReleaseNote.hpp" + +namespace Slic3r { +namespace GUI +{ + +static std::unordered_set message_containing_retry{ + "0701-8004", + "0701-8005", + "0701-8006", + "0701-8006", + "0701-8007", + "0700-8012", + "0701-8012", + "0702-8012", + "0703-8012", + "07FF-8003", + "07FF-8004", + "07FF-8005", + "07FF-8006", + "07FF-8007", + "07FF-8010", + "07FF-8011", + "07FF-8012", + "07FF-8013", + "12FF-8007", + "1200-8006" +}; + +static std::unordered_set message_containing_done{ + "07FF-8007", + "12FF-8007" +}; + +static std::unordered_set message_containing_resume{ + "0300-8013" +}; + +DeviceErrorDialog::DeviceErrorDialog(MachineObject* obj, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) + :DPIDialog(parent, id, title, pos, size, style), m_obj(obj) +{ + 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); + + SetTitle(_L("Error")); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(350), 1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + + m_scroll_area = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); + m_scroll_area->SetScrollRate(0, 5); + m_scroll_area->SetBackgroundColour(*wxWHITE); + m_scroll_area->SetMinSize(wxSize(FromDIP(320), FromDIP(250))); + + wxBoxSizer* text_sizer = new wxBoxSizer(wxVERTICAL); + + m_error_msg_label = new Label(m_scroll_area, wxEmptyString, LB_AUTO_WRAP); + m_error_picture = new wxStaticBitmap(m_scroll_area, wxID_ANY, wxBitmap(), wxDefaultPosition, wxSize(FromDIP(300), FromDIP(180))); + + //Label* dev_name = new Label(m_scroll_area, wxString::FromUTF8(obj->dev_name) + ":", LB_AUTO_WRAP); + //dev_name->SetMaxSize(wxSize(FromDIP(300), -1)); + //dev_name->SetMinSize(wxSize(FromDIP(300), -1)); + //dev_name->Wrap(FromDIP(300)); + //text_sizer->Add(dev_name, 0, wxALIGN_CENTER, FromDIP(5)); + //text_sizer->AddSpacer(5); + text_sizer->Add(m_error_picture, 0, wxALIGN_CENTER, FromDIP(5)); + text_sizer->AddSpacer(10); + text_sizer->Add(m_error_msg_label, 0, wxALIGN_CENTER, FromDIP(5)); + + m_error_code_label = new Label(m_scroll_area, wxEmptyString, LB_AUTO_WRAP); + text_sizer->AddSpacer(5); + text_sizer->Add(m_error_code_label, 0, wxALIGN_CENTER, FromDIP(5)); + m_scroll_area->SetSizer(text_sizer); + + auto bottom_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer_button = new wxBoxSizer(wxVERTICAL); + bottom_sizer->Add(m_sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, 0); + + wxBoxSizer* m_center_sizer = new wxBoxSizer(wxVERTICAL); + m_center_sizer->Add(0, 0, 1, wxTOP, FromDIP(5)); + m_center_sizer->Add(m_scroll_area, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15)); + m_center_sizer->Add(bottom_sizer, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20)); + m_center_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); + m_sizer_main->Add(m_center_sizer, 0, wxBOTTOM | wxEXPAND, FromDIP(5)); + + SetSizer(m_sizer_main); + Layout(); + m_sizer_main->Fit(this); + + init_button_list(); + + CenterOnParent(); + wxGetApp().UpdateDlgDarkUI(this); + + Bind(wxEVT_WEBREQUEST_STATE, &DeviceErrorDialog::on_webrequest_state, this); +} + +DeviceErrorDialog::~DeviceErrorDialog() +{ + if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active) + { + BOOST_LOG_TRIVIAL(info) << "web_request: cancelled"; + web_request.Cancel(); + } + m_error_picture->SetBitmap(wxBitmap()); +} + +void DeviceErrorDialog::on_webrequest_state(wxWebRequestEvent& evt) +{ + BOOST_LOG_TRIVIAL(trace) << "monitor: monitor_panel web request state = " << evt.GetState(); + switch (evt.GetState()) + { + case wxWebRequest::State_Completed: + { + wxImage img(*evt.GetResponse().GetStream()); + wxImage resize_img = img.Scale(FromDIP(320), FromDIP(180), wxIMAGE_QUALITY_HIGH); + wxBitmap error_prompt_pic = resize_img; + m_error_picture->SetBitmap(error_prompt_pic); + Layout(); + Fit(); + + break; + } + case wxWebRequest::State_Failed: + case wxWebRequest::State_Cancelled: + case wxWebRequest::State_Unauthorized: + { + m_error_picture->SetBitmap(wxBitmap()); + break; + } + case wxWebRequest::State_Active: + case wxWebRequest::State_Idle: break; + default: break; + } +} + +void DeviceErrorDialog::init_button(ActionButton style, wxString buton_text) +{ + if (btn_bg_white.count() == 0) + { + btn_bg_white = StateColor(std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + } + + Button* print_error_button = new Button(this, buton_text); + print_error_button->SetBackgroundColor(btn_bg_white); + print_error_button->SetBorderColor(wxColour(38, 46, 48)); + print_error_button->SetFont(Label::Body_14); + print_error_button->SetSize(wxSize(FromDIP(300), FromDIP(30))); + print_error_button->SetMinSize(wxSize(FromDIP(300), FromDIP(30))); + print_error_button->SetMaxSize(wxSize(-1, FromDIP(30))); + print_error_button->SetCornerRadius(FromDIP(5)); + print_error_button->Hide(); + m_button_list[style] = print_error_button; + m_button_list[style]->Bind(wxEVT_LEFT_DOWN, [this, style](wxMouseEvent& e) + { + this->on_button_click(style); + e.Skip(); + }); +} + +void DeviceErrorDialog::init_button_list() +{ + init_button(RESUME_PRINTING, _L("Resume Printing")); + init_button(RESUME_PRINTING_DEFECTS, _L("Resume (defects acceptable)")); + init_button(RESUME_PRINTING_PROBELM_SOLVED, _L("Resume (problem solved)")); + init_button(STOP_PRINTING, _L("Stop Printing"));// pop up recheck dialog? + init_button(CHECK_ASSISTANT, _L("Check Assistant")); + init_button(FILAMENT_EXTRUDED, _L("Filament Extruded, Continue")); + init_button(RETRY_FILAMENT_EXTRUDED, _L("Not Extruded Yet, Retry")); + init_button(CONTINUE, _L("Finished, Continue")); + init_button(LOAD_VIRTUAL_TRAY, _L("Load Filament")); + init_button(OK_BUTTON, _L("OK")); + init_button(FILAMENT_LOAD_RESUME, _L("Filament Loaded, Resume")); + init_button(JUMP_TO_LIVEVIEW, _L("View Liveview")); + init_button(NO_REMINDER_NEXT_TIME, _L("No Reminder Next Time")); + init_button(IGNORE_NO_REMINDER_NEXT_TIME, _L("Ignore. Don't Remind Next Time")); + init_button(IGNORE_RESUME, _L("Ignore this and Resume")); + init_button(PROBLEM_SOLVED_RESUME, _L("Problem Solved and Resume")); + init_button(TURN_OFF_FIRE_ALARM, _L("Got it, Turn off the Fire Alarm.")); + init_button(RETRY_PROBLEM_SOLVED, _L("Retry (problem solved)")); + init_button(STOP_DRYING, _L("Stop Drying")); + init_button(DBL_CHECK_CANCEL, _L("Cancle")); + init_button(DBL_CHECK_DONE, _L("Done")); + init_button(DBL_CHECK_RETRY, _L("Retry")); + init_button(DBL_CHECK_RESUME, _L("Resume")); + init_button(DBL_CHECK_OK, _L("Confirm")); +} + +void DeviceErrorDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + for (auto used_button : m_used_button) { used_button->Rescale();} + wxGetApp().UpdateDlgDarkUI(this); + Refresh(); +} + +static const std::unordered_set s_jump_liveview_error_codes = { "0300-8003", "0300-8002", "0300-800A"}; +wxString DeviceErrorDialog::show_error_code(int error_code) +{ + if (m_error_code == error_code) { return wxEmptyString;} + if (wxGetApp().get_hms_query()->is_internal_error(m_obj, error_code)) { return wxEmptyString;} + + /* error code str*/ + std::string error_str = m_obj->get_error_code_str(error_code); + + /* error code message*/ + wxString error_msg = wxGetApp().get_hms_query()->query_print_error_msg(m_obj, error_code); + if (error_msg.IsEmpty()) { error_msg = _L("Unknown error.");} + + /* error_str is old error code*/ + if (message_containing_retry.count(error_str) || message_containing_done.count(error_str) || message_containing_resume.count(error_str)) { + /* convert old error code to pseudo buttons*/ + std::vector pseudo_button = convert_to_pseudo_buttons(error_str); + + /* do update*/ + update_contents(_L("Warning"), error_msg, error_str, wxEmptyString, pseudo_button); + } else { + /* action buttons*/ + std::vector used_button; + wxString error_image_url = wxGetApp().get_hms_query()->query_print_image_action(m_obj, error_code, used_button); + if (s_jump_liveview_error_codes.count(error_str)) { used_button.emplace_back(DeviceErrorDialog::JUMP_TO_LIVEVIEW); } // special case + + /* do update*/ + update_contents(_L("Error"), error_msg, error_str, error_image_url, used_button); + } + + wxGetApp().UpdateDlgDarkUI(this); + Show(); + Raise(); + + this->RequestUserAttention(wxUSER_ATTENTION_ERROR); + + return error_msg; +} + +std::vector DeviceErrorDialog::convert_to_pseudo_buttons(std::string error_str) +{ + std::vector pseudo_button; + if (message_containing_done.count(error_str) && message_containing_retry.count(error_str)) { + pseudo_button.emplace_back(DBL_CHECK_RETRY); + pseudo_button.emplace_back(DBL_CHECK_DONE); + pseudo_button.emplace_back(DBL_CHECK_OK); + } else if (message_containing_done.count(error_str)) { + pseudo_button.emplace_back(DBL_CHECK_DONE); + pseudo_button.emplace_back(DBL_CHECK_OK); + } else if (message_containing_retry.count(error_str)) { + pseudo_button.emplace_back(DBL_CHECK_RETRY); + pseudo_button.emplace_back(DBL_CHECK_OK); + } else if (message_containing_resume.count(error_str)) { + pseudo_button.emplace_back(DBL_CHECK_RESUME); + pseudo_button.emplace_back(DBL_CHECK_OK); + } else { + pseudo_button.emplace_back(DBL_CHECK_OK); + } + + return pseudo_button; +} + +void DeviceErrorDialog::update_contents(const wxString& title, const wxString& text, const wxString& error_code, const wxString& image_url, const std::vector& btns) +{ + if (error_code.empty()) { return; } + + /* buttons*/ + { + m_sizer_button->Clear(); + m_used_button.clear(); + + // Show the used buttons + bool need_remove_close_btn = false; + std::unordered_set shown_btns; + for (int button_id : btns) + { + need_remove_close_btn |= (button_id == REMOVE_CLOSE_BTN); // special case, do not show close button + + auto iter = m_button_list.find(button_id); + if (iter != m_button_list.end()) + { + m_sizer_button->Add(iter->second, 0, wxALL, FromDIP(5)); + iter->second->Show(); + m_used_button.insert(iter->second); + } + } + + // Special case, do not show close button + if (need_remove_close_btn) + { + SetWindowStyle(GetWindowStyle() & ~wxCLOSE_BOX); + } + else + { + SetWindowStyle(GetWindowStyle() | wxCLOSE_BOX); + } + + // Hide unused buttons + for (const auto& pair : m_button_list) + { + if (m_used_button.count(pair.second) == 0) { pair.second->Hide(); } + } + } + + /* image */ + if (!image_url.empty()) + { + const wxImage& img = wxGetApp().get_hms_query()->query_image_from_local(image_url); + if (!img.IsOk() && image_url.Contains("http")) + { + web_request = wxWebSession::GetDefault().CreateRequest(this, image_url); + BOOST_LOG_TRIVIAL(trace) << "monitor: create new webrequest, state = " << web_request.GetState(); + if (web_request.GetState() == wxWebRequest::State_Idle) web_request.Start(); + BOOST_LOG_TRIVIAL(trace) << "monitor: start new webrequest, state = " << web_request.GetState(); + } + else + { + const wxImage& resize_img = img.Scale(FromDIP(320), FromDIP(180), wxIMAGE_QUALITY_HIGH); + m_error_picture->SetBitmap(wxBitmap(resize_img)); + } + + m_error_picture->Show(); + } + else + { + m_error_picture->Hide(); + } + + /* error code*/ + const wxString& show_time = wxDateTime::Now().Format("%H%M%d"); + const wxString& error_code_msg = wxString::Format("[%S %S]", error_code, show_time); + m_error_code_label->SetMaxSize(wxSize(FromDIP(300), -1)); + m_error_code_label->SetMinSize(wxSize(FromDIP(300), -1)); + m_error_code_label->SetLabelText(error_code_msg); + + /* error message*/ + m_error_msg_label->SetMaxSize(wxSize(FromDIP(300), -1)); + m_error_msg_label->SetMinSize(wxSize(FromDIP(300), -1)); + m_error_msg_label->SetLabelText(text); + + /* dialog title*/ + SetTitle(title); + + /* update layout*/ + { + m_scroll_area->Layout(); + auto text_size = m_error_msg_label->GetBestSize(); + if (text_size.y < FromDIP(360)) + { + if (!image_url.empty()) + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(220))); + } + else + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(50))); + } + } + else + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), FromDIP(340))); + } + + Layout(); + Fit(); + } +}; + +void DeviceErrorDialog::on_button_click(ActionButton btn_id) +{ + switch (btn_id) { + case DeviceErrorDialog::RESUME_PRINTING: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::RESUME_PRINTING_DEFECTS: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::RESUME_PRINTING_PROBELM_SOLVED: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::STOP_PRINTING: { + m_obj->command_hms_stop(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::CHECK_ASSISTANT: { + wxGetApp().mainframe->m_monitor->jump_to_HMS(); // go to assistant page + break; + } + case DeviceErrorDialog::FILAMENT_EXTRUDED: { + m_obj->command_ams_control("done"); + break; + } + case DeviceErrorDialog::RETRY_FILAMENT_EXTRUDED: { + m_obj->command_ams_control("resume"); + return;// do not hide the dialogs + } + case DeviceErrorDialog::CONTINUE: { + m_obj->command_ams_control("resume"); + break; + } + case DeviceErrorDialog::LOAD_VIRTUAL_TRAY: { + //m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_MAIN_ID)); + //on_ams_load_curr(); + break;/*AP, unknown what it is*/ + } + case DeviceErrorDialog::OK_BUTTON: { + m_obj->command_clean_print_error(m_obj->subtask_id_, m_error_code); + break;/*do nothing*/ + } + case DeviceErrorDialog::FILAMENT_LOAD_RESUME: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::JUMP_TO_LIVEVIEW: { + Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); + Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_LiveView(); + break; + } + case DeviceErrorDialog::NO_REMINDER_NEXT_TIME: { + m_obj->command_hms_idle_ignore(std::to_string(m_error_code), 0); /*the type is 0, supported by AP*/ + break; + } + case DeviceErrorDialog::IGNORE_NO_REMINDER_NEXT_TIME: { + m_obj->command_hms_ignore(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::IGNORE_RESUME: { + m_obj->command_hms_ignore(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::PROBLEM_SOLVED_RESUME: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::TURN_OFF_FIRE_ALARM: { + m_obj->command_stop_buzzer(); + break; + } + case DeviceErrorDialog::RETRY_PROBLEM_SOLVED: { + m_obj->command_ams_control("resume"); + break; + } + case DeviceErrorDialog::STOP_DRYING: { + m_obj->command_ams_drying_stop(); + break; + } + case DeviceErrorDialog::ERROR_BUTTON_COUNT: break; + + case DeviceErrorDialog::DBL_CHECK_CANCEL: { + // post EVT_SECONDARY_CHECK_CANCEL + // no event + break; + } + case DeviceErrorDialog::DBL_CHECK_DONE: { + // post EVT_SECONDARY_CHECK_DONE + m_obj->command_ams_control("done"); + break; + } + case DeviceErrorDialog::DBL_CHECK_RETRY: { + // post EVT_SECONDARY_CHECK_RETRY + wxCommandEvent event(EVT_SECONDARY_CHECK_RETRY); + wxPostEvent(GetParent(), event); + break; + } + case DeviceErrorDialog::DBL_CHECK_RESUME: { + // post EVT_SECONDARY_CHECK_RESUME + wxCommandEvent event(EVT_SECONDARY_CHECK_RESUME); + wxPostEvent(GetParent(), event); + break; + } + case DeviceErrorDialog::DBL_CHECK_OK: { + // post EVT_SECONDARY_CHECK_CONFIRM + m_obj->command_clean_print_error(m_obj->subtask_id_, m_error_code); + m_obj->command_clean_print_error_uiop(m_error_code); + break; + } + + default: break; + } + + Hide(); +} + +} +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/DeviceErrorDialog.hpp b/src/slic3r/GUI/DeviceErrorDialog.hpp new file mode 100644 index 0000000..6c172f9 --- /dev/null +++ b/src/slic3r/GUI/DeviceErrorDialog.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include + +#include "GUI_Utils.hpp" +#include "Widgets/StateColor.hpp" + +class Label; +class Button; + +namespace Slic3r { + +class MachineObject;//Previous definitions + +namespace GUI { + +class DeviceErrorDialog : public DPIDialog +{ +public: + enum ActionButton : int { + RESUME_PRINTING = 2, + RESUME_PRINTING_DEFECTS = 3, + RESUME_PRINTING_PROBELM_SOLVED = 4, + STOP_PRINTING = 5, + CHECK_ASSISTANT = 6, + FILAMENT_EXTRUDED = 7, + RETRY_FILAMENT_EXTRUDED = 8, + CONTINUE = 9, + LOAD_VIRTUAL_TRAY = 10, + OK_BUTTON = 11, + FILAMENT_LOAD_RESUME = 12, + JUMP_TO_LIVEVIEW, + + NO_REMINDER_NEXT_TIME = 23, + IGNORE_NO_REMINDER_NEXT_TIME = 25, + //LOAD_FILAMENT = 26*/ + IGNORE_RESUME = 27, + PROBLEM_SOLVED_RESUME = 28, + TURN_OFF_FIRE_ALARM = 29, + + RETRY_PROBLEM_SOLVED = 34, + STOP_DRYING = 35, + REMOVE_CLOSE_BTN = 39, // special case, do not show close button + + ERROR_BUTTON_COUNT, + + // old error code to pseudo action + DBL_CHECK_CANCEL = 10000, + DBL_CHECK_DONE = 10001, + DBL_CHECK_RETRY = 10002, + DBL_CHECK_RESUME = 10003, + DBL_CHECK_OK = 10004, + }; + +public: + DeviceErrorDialog(MachineObject* obj, + wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxCLOSE_BOX | wxCAPTION); + ~DeviceErrorDialog(); + +public: + wxString show_error_code(int error_code); + +protected: + void init_button_list(); + void init_button(ActionButton style, wxString buton_text); + + std::vector convert_to_pseudo_buttons(std::string error_str); + + void update_contents(const wxString& title, const wxString& text, const wxString& error_code,const wxString& image_url, const std::vector& btns); + + void on_button_click(ActionButton btn_id); + void on_webrequest_state(wxWebRequestEvent& evt); + void on_dpi_changed(const wxRect& suggested_rect); + +private: + MachineObject* m_obj; + + int m_error_code; + std::unordered_set m_used_button; + + wxWebRequest web_request; + wxStaticBitmap* m_error_picture; + Label* m_error_msg_label{ nullptr }; + Label* m_error_code_label{ nullptr }; + wxBoxSizer* m_sizer_main; + wxBoxSizer* m_sizer_button; + wxScrolledWindow* m_scroll_area{ nullptr }; + + std::map m_button_list; + StateColor btn_bg_white; +}; +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 86ba801..043fa45 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -2,10 +2,13 @@ #include "DeviceManager.hpp" #include "libslic3r/Time.hpp" #include "libslic3r/Thread.hpp" +#include "slic3r/Utils/QDTUtil.hpp" +#include "slic3r/Utils/NetworkAgent.hpp" #include "GuiColor.hpp" #include "GUI_App.hpp" #include "MsgDialog.hpp" +#include "DeviceErrorDialog.hpp" #include "Plater.hpp" #include "GUI_App.hpp" #include "ReleaseNote.hpp" @@ -20,7 +23,25 @@ #include #include "fast_float/fast_float.h" -#include "slic3r/Utils/QDTUtil.hpp" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevExtruderSystem.h" +#include "DeviceCore/DevNozzleSystem.h" +#include "DeviceCore/DevBed.h" +#include "DeviceCore/DevLamp.h" +#include "DeviceCore/DevFan.h" +#include "DeviceCore/DevStorage.h" + +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevCtrl.h" +#include "DeviceCore/DevInfo.h" +#include "DeviceCore/DevPrintOptions.h" +#include "DeviceCore/DevPrintTaskInfo.h" +#include "DeviceCore/DevHMS.h" + +#include "DeviceCore/DevMapping.h" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevUtil.h" + #define CALI_DEBUG #define MINUTE_30 1800000 //ms @@ -34,7 +55,16 @@ float string_to_float(const std::string& str_value) { return value; } -wxString get_stage_string(int stage) +int get_tray_id_by_ams_id_and_slot_id(int ams_id, int slot_id) +{ + if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) { + return ams_id; + } else { + return ams_id * 4 + slot_id; + } +} + +wxString Slic3r::get_stage_string(int stage) { switch(stage) { case 0: @@ -151,6 +181,10 @@ wxString get_stage_string(int stage) return _L("Auto Check: Material Position"); case 56: return _L("Cutting Module Offset Calibration"); + case 57: + return _L("Measuring Surface"); + case 58: + return _L("Thermal Preconditioning for first layer optimization"); default: BOOST_LOG_TRIVIAL(info) << "stage = " << stage; } @@ -244,7 +278,7 @@ void split_string(std::string s, std::vector& v) { v.push_back(t); } -wxString generate_nozzle_id(NozzleVolumeType nozzle_type, const std::string& diameter) +static wxString _generate_nozzle_id(NozzleVolumeType nozzle_type, const std::string& diameter) { // HS00-0.4 std::string nozzle_id = "H"; @@ -281,289 +315,65 @@ NozzleVolumeType convert_to_nozzle_type(const std::string &str) return res; } -PrinterArch get_printer_arch_by_str(std::string arch_str) +wxString MachineObject::get_printer_type_display_str() const { - if (arch_str == "i3") { - return PrinterArch::ARCH_I3; - } - else if (arch_str == "core_xy") { - return PrinterArch::ARCH_CORE_XY; - } - - return PrinterArch::ARCH_CORE_XY; -} - -bool check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, const std::string& filament_id, int ams_id, bool &in_blacklist, std::string &ac, wxString &info) -{ - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (!dev) { - return true; - } - - MachineObject *obj = dev->get_selected_machine(); - if (obj == nullptr || !obj->is_multi_extruders()) { - return true; - } - - Preset *printer_preset = GUI::get_printer_preset(obj); - if (!printer_preset) - return true; - - ConfigOptionInts *physical_extruder_map_op = dynamic_cast(printer_preset->config.option("physical_extruder_map")); - if (!physical_extruder_map_op) - return true; - std::vector physical_extruder_maps = physical_extruder_map_op->values; - int extruder_idx = obj->get_extruder_id_by_ams_id(std::to_string(ams_id)); - for (int index = 0; index < physical_extruder_maps.size(); ++index) { - if (physical_extruder_maps[index] == extruder_idx) { - extruder_idx = index; - break; - } - } - - PresetBundle *preset_bundle = GUI::wxGetApp().preset_bundle; - std::optional filament_info = preset_bundle->get_filament_by_filament_id(filament_id, printer_preset->name); - 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); - in_blacklist = true; - return false; - } - - return true; -} - -void AmsTray::update_color_from_str(std::string color) -{ - if (color.empty()) return; - - if (this->color.compare(color) == 0) - return; - - wx_color = "#" + wxString::FromUTF8(color); - this->color = color; -} - -wxColour AmsTray::get_color() -{ - return AmsTray::decode_color(color); -} - -void AmsTray::reset() -{ - tag_uid = ""; - setting_id = ""; - filament_setting_id = ""; - type = ""; - sub_brands = ""; - color = ""; - weight = ""; - diameter = ""; - temp = ""; - time = ""; - bed_temp_type = ""; - bed_temp = ""; - nozzle_temp_max = ""; - nozzle_temp_min = ""; - xcam_info = ""; - uuid = ""; - k = 0.0f; - n = 0.0f; - is_qdt = false; - hold_count = 0; - remain = 0; -} - - -bool AmsTray::is_tray_info_ready() -{ - if (color.empty()) - return false; - if (type.empty()) - return false; - //if (setting_id.empty()) - //return false; - return true; -} - -bool AmsTray::is_unset_third_filament() -{ - if (this->is_qdt) - return false; - - if (color.empty() || type.empty()) - return true; - return false; -} - -std::string AmsTray::get_display_filament_type() -{ - if (type == "PLA-S") - return "Sup.PLA"; - else if (type == "PA-S") - return "Sup.PA"; - else if (type == "ABS-S") - return "Sup.ABS"; - else - return type; - return type; -} - -std::string AmsTray::get_filament_type() -{ - if (type == "Sup.PLA") { - return "PLA-S"; - } else if (type == "Sup.PA") { - return "PA-S"; - } else if (type == "Sup.ABS") { - return "ABS-S"; - } else if (type == "Support W") { - return "PLA-S"; - } else if (type == "Support G") { - return "PA-S"; - } else if (type == "Support") { - if (setting_id == "GFS00") { - type = "PLA-S"; - } else if (setting_id == "GFS01") { - type = "PA-S"; - } else { - return "PLA-S"; - } - } else { - return type; - } - return type; -} - -bool HMSItem::parse_hms_info(unsigned attr, unsigned code) -{ - bool result = true; - unsigned int model_id_int = (attr >> 24) & 0xFF; - this->module_id = (ModuleID)model_id_int; - this->module_num = (attr >> 16) & 0xFF; - this->part_id = (attr >> 8) & 0xFF; - this->reserved = (attr >> 0) & 0xFF; - unsigned msg_level_int = code >> 16; - if (msg_level_int < (unsigned)HMS_MSG_LEVEL_MAX) - this->msg_level = (HMSMessageLevel)msg_level_int; - else - this->msg_level = HMS_UNKNOWN; - this->msg_code = code & 0xFFFF; - return result; -} - -std::string HMSItem::get_long_error_code() -{ - char buf[64]; - ::sprintf(buf, "%02X%02X%02X00000%1X%04X", - this->module_id, - this->module_num, - this->part_id, - (int)this->msg_level, - this->msg_code); - return std::string(buf); -} - -wxString HMSItem::get_module_name(ModuleID module_id) -{ - switch (module_id) - { - case MODULE_MC: - return "MC"; - case MODULE_MAINBOARD: - return "MainBoard"; - case MODULE_AMS: - return "BOX"; - case MODULE_TH: - return "TH"; - case MODULE_XCAM: - return "XCam"; - default: - wxString text = _L("Unknown") + wxString::Format("0x%x", (unsigned)module_id); - return text; - } - return ""; -} - -wxString HMSItem::get_hms_msg_level_str(HMSMessageLevel level) -{ - switch(level) { - case HMS_FATAL: - return _L("Fatal"); - case HMS_SERIOUS: - return _L("Serious"); - case HMS_COMMON: - return _L("Common"); - case HMS_INFO: - return _L("Info"); - default: - return _L("Unknown"); - } - return ""; -} - -std::string MachineObject::parse_printer_type(std::string type_str) -{ - if (type_str.compare("3DPrinter-X1") == 0) { - return "BL-P002"; - } else if (type_str.compare("3DPrinter-X1-Carbon") == 0) { - return "BL-P001"; - } else if (type_str.compare("BL-P001") == 0) { - return type_str; - } else if (type_str.compare("BL-P002") == 0) { - return type_str; - } else { - return DeviceManager::parse_printer_type(type_str); - } - return ""; -} -std::string MachineObject::get_preset_printer_model_name(std::string printer_type) -{ - return DeviceManager::get_printer_display_name(printer_type); -} - -std::string MachineObject::get_preset_printer_thumbnail_img(std::string printer_type) -{ - return DeviceManager::get_printer_thumbnail_img(printer_type); -} - -wxString MachineObject::get_printer_type_display_str() -{ - std::string display_name = get_preset_printer_model_name(printer_type); + std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type); if (!display_name.empty()) return display_name; else return _L("Unknown"); } -std::string MachineObject::get_printer_thumbnail_img_str() +std::string MachineObject::get_printer_thumbnail_img_str() const { - std::string img_str = get_preset_printer_thumbnail_img(printer_type); + std::string img_str = DevPrinterConfigUtil::get_printer_thumbnail_img(printer_type); std::string img_url; - if (!img_str.empty()) { - img_url = Slic3r::resources_dir() + "\\printers\\image\\" + img_str; - if (fs::exists(img_url + ".svg")) { + if (!img_str.empty()) + { + img_url = Slic3r::resources_dir() + "\\images\\" + img_str ; + if (fs::exists(img_url + ".svg")) + { return img_url; } - else { + else + { img_url = img_str; } - } - else { + } + else + { img_url = "printer_thumbnail"; - } + } return img_url; } -std::string MachineObject::get_ftp_folder() +std::string MachineObject::get_auto_pa_cali_thumbnail_img_str() const { - return DeviceManager::get_ftp_folder(printer_type); + return DevPrinterConfigUtil::get_printer_auto_pa_cali_image(printer_type); } -std::string MachineObject::get_access_code() +std::string MachineObject::get_ftp_folder() +{ + return DevPrinterConfigUtil::get_ftp_folder(printer_type); +} + +bool MachineObject::HasRecentCloudMessage() +{ + auto curr_time = std::chrono::system_clock::now(); + auto diff = std::chrono::duration_cast(curr_time - last_cloud_msg_time_); + return diff.count() < 5000; +} + +bool MachineObject::HasRecentLanMessage() +{ + auto curr_time = std::chrono::system_clock::now(); + auto diff = std::chrono::duration_cast(curr_time - last_lan_msg_time_); + return diff.count() < 5000; +} + +std::string MachineObject::get_access_code() const { if (get_user_access_code().empty()) return access_code; @@ -577,9 +387,9 @@ void MachineObject::set_access_code(std::string code, bool only_refresh) AppConfig* config = GUI::wxGetApp().app_config; if (config) { if (!code.empty()) { - GUI::wxGetApp().app_config->set_str("access_code", dev_id, code); + GUI::wxGetApp().app_config->set_str("access_code", get_dev_id(), code); } else { - GUI::wxGetApp().app_config->erase("access_code", dev_id); + GUI::wxGetApp().app_config->erase("access_code", get_dev_id()); } } } @@ -590,7 +400,7 @@ void MachineObject::erase_user_access_code() this->user_access_code = ""; AppConfig* config = GUI::wxGetApp().app_config; if (config) { - GUI::wxGetApp().app_config->erase("user_access_code", dev_id); + GUI::wxGetApp().app_config->erase("user_access_code", get_dev_id()); //GUI::wxGetApp().app_config->save(); } } @@ -601,35 +411,20 @@ void MachineObject::set_user_access_code(std::string code, bool only_refresh) if (only_refresh && !code.empty()) { AppConfig* config = GUI::wxGetApp().app_config; if (config && !code.empty()) { - GUI::wxGetApp().app_config->set_str("user_access_code", dev_id, code); + GUI::wxGetApp().app_config->set_str("user_access_code", get_dev_id(), code); } } } -std::string MachineObject::get_user_access_code() +std::string MachineObject::get_user_access_code() const { AppConfig* config = GUI::wxGetApp().app_config; if (config) { - return GUI::wxGetApp().app_config->get("user_access_code", dev_id); + return GUI::wxGetApp().app_config->get("user_access_code", get_dev_id()); } return ""; } -bool MachineObject::is_lan_mode_printer() -{ - bool result = false; - if (!dev_connection_type.empty() && dev_connection_type == "lan") - return true; - return result; -} - -std::string MachineObject::convertToIp(long long ip) -{ - std::stringstream ss; - ss << ((ip >> 0) & 0xFF) << "." << ((ip >> 8) & 0xFF) << "." << ((ip >> 16) & 0xFF) << "." << ((ip >> 24) & 0xFF); - return ss.str(); -} - std::string MachineObject::get_show_printer_type() const { std::string printer_type = this->printer_type; @@ -637,10 +432,9 @@ std::string MachineObject::get_show_printer_type() const printer_type = "C12"; return printer_type; } - PrinterSeries MachineObject::get_printer_series() const { - std::string series = DeviceManager::get_printer_series(printer_type); + std::string series = DevPrinterConfigUtil::get_printer_series_str(printer_type); if (series == "series_x1" || series == "series_o") return PrinterSeries::SERIES_X1; else if (series == "series_p1p") @@ -651,17 +445,12 @@ PrinterSeries MachineObject::get_printer_series() const PrinterArch MachineObject::get_printer_arch() const { - return DeviceManager::get_printer_arch(printer_type); + return DevPrinterConfigUtil::get_printer_arch(printer_type); } std::string MachineObject::get_printer_ams_type() const { - return DeviceManager::get_printer_ams_type(printer_type); -} - -bool MachineObject::get_printer_is_enclosed() const -{ - return DeviceManager::get_printer_is_enclosed(printer_type); + return DevPrinterConfigUtil::get_printer_use_ams_type(printer_type); } bool MachineObject::is_series_n(const std::string& series_str) { return series_str == "series_n"; } @@ -669,12 +458,12 @@ bool MachineObject::is_series_p(const std::string& series_str) { return series_s bool MachineObject::is_series_x(const std::string& series_str) { return series_str == "series_x1"; } bool MachineObject::is_series_o(const std::string& series_str) { return series_str == "series_o"; } -bool MachineObject::is_series_n() const { return is_series_n(DeviceManager::get_printer_series(printer_type)); } -bool MachineObject::is_series_p() const { return is_series_p(DeviceManager::get_printer_series(printer_type)); } -bool MachineObject::is_series_x() const { return is_series_x(DeviceManager::get_printer_series(printer_type)); } -bool MachineObject::is_series_o() const { return is_series_o(DeviceManager::get_printer_series(printer_type)); } +bool MachineObject::is_series_n() const { return is_series_n(DevPrinterConfigUtil::get_printer_series_str(printer_type)); } +bool MachineObject::is_series_p() const { return is_series_p(DevPrinterConfigUtil::get_printer_series_str(printer_type)); } +bool MachineObject::is_series_x() const { return is_series_x(DevPrinterConfigUtil::get_printer_series_str(printer_type)); } +bool MachineObject::is_series_o() const { return is_series_o(DevPrinterConfigUtil::get_printer_series_str(printer_type)); } -std::string MachineObject::get_printer_series_str() const{ return DeviceManager::get_printer_series(printer_type);}; +std::string MachineObject::get_printer_series_str() const{ return DevPrinterConfigUtil::get_printer_series_str(printer_type);}; void MachineObject::reload_printer_settings() { @@ -701,7 +490,7 @@ MachineObject::MachineObject(std::string name, std::string url, std::string ip, { } -MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip) +MachineObject::MachineObject(DeviceManager* manager, NetworkAgent* agent, std::string name, std::string id, std::string ip) :dev_name(name), dev_id(id), dev_ip(ip), @@ -710,13 +499,13 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string slice_info(nullptr), m_is_online(false) { + m_manager = manager; m_agent = agent; reset(); /* temprature fields */ - bed_temp = 0.0f; - bed_temp_target = 0.0f; + chamber_temp = 0.0f; chamber_temp_target = 0.0f; frame_temp = 0.0f; @@ -725,11 +514,6 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string ams_exist_bits = 0; tray_exist_bits = 0; tray_is_qdt_bits = 0; - ams_rfid_status = 0; - is_ams_need_update = false; - ams_insert_flag = false; - ams_power_on_flag = false; - ams_calibrate_remain_flag = false; /* signals */ wifi_signal = ""; @@ -739,12 +523,6 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string upgrade_new_version = false; upgrade_consistency_request = false; - /* cooling */ - heatbreak_fan_speed = 0; - cooling_fan_speed = 0; - big_fan1_speed = 0; - big_fan2_speed = 0; - fan_gear = 0; /* printing */ mc_print_stage = 0; @@ -754,24 +532,28 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string mc_print_percent = 0; mc_print_sub_stage = 0; mc_left_time = 0; - home_flag = -1; hw_switch_state = 0; - printing_speed_lvl = PrintingSpeedLevel::SPEED_LEVEL_INVALID; has_ipcam = true; // default true - auto vslot = AmsTray(std::to_string(VIRTUAL_TRAY_MAIN_ID)); + auto vslot = DevAmsTray(std::to_string(VIRTUAL_TRAY_MAIN_ID)); vt_slot.push_back(vslot); - m_extder_data.current_extder_id = MAIN_NOZZLE_ID; - m_extder_data.target_extder_id = MAIN_NOZZLE_ID; - m_extder_data.total_extder_count = 1; - Extder nozzle; - nozzle.id = MAIN_NOZZLE_ID; - nozzle.nozzle_id = MAIN_NOZZLE_ID; - nozzle.target_nozzle_id = MAIN_NOZZLE_ID; - m_extder_data.extders.push_back(nozzle); + { + m_lamp = new DevLamp(this); + m_fan = new DevFan(this); + m_bed = new DevBed(this); + m_storage = new DevStorage(this); + m_extder_system = new DevExtderSystem(this); + m_nozzle_system = new DevNozzleSystem(this); + m_fila_system = new DevFilaSystem(this); + m_hms_system = new DevHMS(this); + m_config = new DevConfig(this); + + m_ctrl = new DevCtrl(this); + m_print_options = new DevPrintOptions(this); + } } MachineObject::~MachineObject() @@ -788,31 +570,40 @@ MachineObject::~MachineObject() free_slice_info(); - for (auto it = amsList.begin(); it != amsList.end(); it++) { - for (auto tray_it = it->second->trayList.begin(); tray_it != it->second->trayList.end(); tray_it++) { - if (tray_it->second) { - delete tray_it->second; - tray_it->second = nullptr; - } - } - it->second->trayList.clear(); - } - amsList.clear(); -} - -bool MachineObject::check_valid_ip() -{ - if (dev_ip.empty()) { - return false; + while (!m_command_error_code_dlgs.empty()) { + delete *m_command_error_code_dlgs.begin();/*element will auto remove from m_command_error_code_dlgs on deleted*/ } - return true; -} + { + delete m_lamp; + m_lamp = nullptr; -void MachineObject::_parse_print_option_ack(int option) -{ - if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { - xcam_auto_recovery_step_loss = ((option >> (int)PRINT_OP_AUTO_RECOVERY) & 0x01) != 0; + delete m_fan; + m_fan = nullptr; + + delete m_bed; + m_bed = nullptr; + + delete m_extder_system; + m_extder_system = nullptr; + + delete m_nozzle_system; + m_nozzle_system = nullptr; + + delete m_ctrl; + m_ctrl = nullptr; + + delete m_fila_system; + m_fila_system = nullptr; + + delete m_hms_system; + m_hms_system = nullptr; + + delete m_config; + m_config = nullptr; + + delete m_print_options; + m_print_options = nullptr; } } @@ -850,94 +641,26 @@ bool MachineObject::is_extrusion_cali_finished() return false; } -void MachineObject::_parse_tray_now(std::string tray_now) + +DevAmsTray *MachineObject::get_curr_tray() { - if (tray_now.empty()) { - return; - } else { - try { - int tray_now_int = atoi(tray_now.c_str()); - - if (tray_now_int == VIRTUAL_TRAY_MAIN_ID) { - m_ams_id = "0"; - m_tray_id = "0"; - m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id = ""; - m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id = ""; - - if (m_tray_now == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id = std::to_string(VIRTUAL_TRAY_MAIN_ID); - m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id = "0"; - } - } - else if (tray_now_int == VIRTUAL_TRAY_DEPUTY_ID) { - m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id = std::to_string(VIRTUAL_TRAY_MAIN_ID); - m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id = "0"; - } - else { - if (tray_now_int >= 0x80 && tray_now_int <= 0x87) { - m_ams_id = std::to_string(tray_now_int); - } else { - m_ams_id = std::to_string(tray_now_int >> 2); - } - - m_tray_id = std::to_string(tray_now_int & 0x3); - m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id = m_ams_id; - m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id = m_tray_id; - } - } - catch(...) { - } - } - - m_tray_now = tray_now; -} - -Ams *MachineObject::get_curr_Ams() -{ - auto it = amsList.find(m_ams_id); - if (it != amsList.end()) - return it->second; - return nullptr; -} - -AmsTray *MachineObject::get_curr_tray() -{ - if (m_tray_now.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0) { + const std::string& cur_ams_id = m_extder_system->GetCurrentAmsId(); + if (cur_ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0) { return &vt_slot[0]; } - Ams* curr_ams = get_curr_Ams(); + DevAms* curr_ams = get_curr_Ams(); if (!curr_ams) return nullptr; - try { - int tray_index = atoi(m_tray_now.c_str()); - int ams_index = atoi(curr_ams->id.c_str()); - - std::string tray_now_index = std::to_string(tray_index - ams_index * 4); - auto it = curr_ams->trayList.find(tray_now_index); - if (it != curr_ams->trayList.end()) - return it->second; - } - catch (...) { - ; + auto it = curr_ams->GetTrays().find(m_extder_system->GetCurrentSlotId()); + if (it != curr_ams->GetTrays().end()) + { + return it->second; } return nullptr; } -AmsTray *MachineObject::get_ams_tray(std::string ams_id, std::string tray_id) -{ - auto it = amsList.find(ams_id); - if (it == amsList.end()) return nullptr; - if (!it->second) return nullptr; - - auto iter = it->second->trayList.find(tray_id); - if (iter != it->second->trayList.end()) - return iter->second; - else - return nullptr; -} - std::string MachineObject::get_filament_id(std::string ams_id, std::string tray_id) const { return this->get_tray(ams_id, tray_id).setting_id; } @@ -974,30 +697,15 @@ void MachineObject::_parse_ams_status(int ams_status) bool MachineObject::can_unload_filament() { bool result = false; - if (!has_ams()) + if (!HasAms()) return true; - if (ams_status_main == AMS_STATUS_MAIN_IDLE && hw_switch_state == 1 && m_tray_now == "255") { + if (ams_status_main == AMS_STATUS_MAIN_IDLE && hw_switch_state == 1 && m_extder_system->GetCurrentAmsId() == "255") { return true; } return result; } -bool MachineObject::is_support_amx_ext_mix_mapping() { - return true; -} - -bool MachineObject::is_ams_on_settingup() const -{ - int setting_up_stat = this->get_flag_bits(ams_cali_stat, 0, 8); - if (setting_up_stat == 0x01 || setting_up_stat == 0x02 || setting_up_stat == 0x03 || setting_up_stat == 0x04) - { - return true; - } - - return false; -} - static float calc_color_distance(wxColour c1, wxColour c2) { float lab[2][3]; @@ -1008,435 +716,9 @@ static float calc_color_distance(wxColour c1, wxColour c2) } void MachineObject::get_ams_colors(std::vector &ams_colors) { - ams_colors.clear(); - ams_colors.reserve(amsList.size()); - for (auto ams = amsList.begin(); ams != amsList.end(); ams++) { - for (auto tray = ams->second->trayList.begin(); tray != ams->second->trayList.end(); tray++) { - if (tray->second->is_tray_info_ready()) { - auto ams_color = AmsTray::decode_color(tray->second->color); - ams_colors.emplace_back(ams_color); - } - } - } + m_fila_system->CollectAmsColors(ams_colors); } -void MachineObject::parse_tray_info(int ams_id, int slot_id, AmsTray tray, FilamentInfo& result) { - result.color = tray.color; - result.type = tray.get_filament_type(); - result.filament_id = tray.setting_id; - result.ctype = tray.ctype; - result.colors = tray.cols; - - /*for new ams mapping*/ - result.ams_id = std::to_string(ams_id); - result.slot_id = std::to_string(slot_id); - - if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID){ - result.tray_id = atoi(tray.id.c_str()); - result.id = atoi(tray.id.c_str()); - } - else{ - result.id = ams_id * 4 + slot_id; - } - -} - -int MachineObject::ams_filament_mapping( - std::vector filaments, std::vector &result, std::vector map_opt, std::vector exclude_id, bool nozzle_has_ams_then_ignore_ext) -{ - if (filaments.empty()) - return -1; - - ///////////////////////// - // Step 1: collect filaments in machine - std::map tray_filaments; // tray_index : tray_color - bool left_nozzle_has_ams = false, right_nozzle_has_ams = false; - - //y59 - std::vector filament_colors = GUI::wxGetApp().plater()->box_msg.filament_colors; - std::vector filament_type = GUI::wxGetApp().plater()->box_msg.filament_type; - std::vector filament_id = GUI::wxGetApp().plater()->box_msg.filament_id; - std::vector slot_id = GUI::wxGetApp().plater()->box_msg.slot_id; - int box_count = GUI::wxGetApp().plater()->box_msg.box_count; - - if (filament_colors.empty()) - return -1; - - std::vector box_filament_infos; - for (int i = 0; i < filament_colors.size(); i++) { - if (!filament_colors[i].empty() && slot_id[i] != -1) { - FilamentInfo box_fila_info; - box_fila_info.color = filament_colors[i].erase(0, 1) + "FF"; - box_fila_info.type = filament_type[i]; - box_fila_info.filament_id = filament_id[i]; - box_fila_info.slot_id = std::to_string(slot_id[i]); - box_fila_info.ams_id = std::to_string(slot_id[i] / 4 + 1); - box_filament_infos.push_back(box_fila_info); - } - } - - for (auto ams = amsList.begin(); ams != amsList.end(); ams++) { - std::string ams_id = ams->second->id; - for (auto tray = ams->second->trayList.begin(); tray != ams->second->trayList.end(); tray++) { - int ams_id = atoi(ams->first.c_str()); - int tray_id = atoi(tray->first.c_str()); - int tray_index = ams_id * 4 + tray_id; - // skip exclude id - for (int i = 0; i < exclude_id.size(); i++) { - if (tray_index == exclude_id[i]) - continue; - } - // push - FilamentInfo info; - if (tray->second->is_tray_info_ready()) - parse_tray_info(ams_id, tray_id, *(tray->second), info); - - //first: left,nozzle=1,map=1 second: right,nozzle=0,map=2 - bool right_ams_valid = ams->second->nozzle == 0 && map_opt[MappingOption::USE_RIGHT_AMS]; - bool left_ams_valid = ams->second->nozzle == 1 && map_opt[MappingOption::USE_LEFT_AMS]; - if (right_ams_valid || left_ams_valid) { - tray_filaments.emplace(std::make_pair(tray_index, info)); - if (right_ams_valid) { - right_nozzle_has_ams = true; - } - if (left_ams_valid) { - left_nozzle_has_ams = true; - } - } - } - //y59 - } - - if (map_opt[MappingOption::USE_RIGHT_EXT] || map_opt[MappingOption::USE_LEFT_EXT]){ - for (auto tray : vt_slot){ - bool right_ext_valid = (tray.id == std::to_string(VIRTUAL_TRAY_MAIN_ID) && map_opt[MappingOption::USE_RIGHT_EXT]); - bool left_ext_valid = (tray.id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID) && map_opt[MappingOption::USE_LEFT_EXT]); - if (right_ext_valid || left_ext_valid) { - if (nozzle_has_ams_then_ignore_ext) { - if (right_ext_valid && right_nozzle_has_ams) { - continue; - } - if (left_ext_valid && left_nozzle_has_ams) { - continue; - } - } - FilamentInfo info; - parse_tray_info(atoi(tray.id.c_str()), 0, tray, info); - tray_filaments.emplace(std::make_pair(info.tray_id, info)); - } - } - } - - ///////////////////////// - // Step 2: collect the distances of filaments_in_slicing to filaments_in_machine - char buffer[256]; - std::vector> distance_map; - - // print title - ::sprintf(buffer, "F(id)"); - std::string line = std::string(buffer); - for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) { - ::sprintf(buffer, " BOX%02d", tray->second.id+1); - line += std::string(buffer); - } - BOOST_LOG_TRIVIAL(info) << "box_mapping_distance:" << line;// Print the collected filaments - - for (int i = 0; i < filaments.size(); i++) { - std::vector rol; - ::sprintf(buffer, "F(%02d)", filaments[i].id+1); - line = std::string(buffer); - //y59 - // for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) { - // DisValue val; - // val.tray_id = tray->second.id; - // wxColour c = wxColour(filaments[i].color); - // wxColour tray_c = AmsTray::decode_color(tray->second.color); - // val.distance = GUI::calc_color_distance(c, tray_c); - // if (filaments[i].type != tray->second.type) { - // val.distance = 999999; - // val.is_type_match = false; - // } else { - // if (c.Alpha() != tray_c.Alpha()) - // val.distance = 999999; - // val.is_type_match = true; - // } - // ::sprintf(buffer, " %6.0f", val.distance); - // line += std::string(buffer); - // rol.push_back(val); - // } - for(int j = 0; j < box_filament_infos.size(); j++){ - DisValue val; - val.tray_id = j; - wxColour c = wxColour(filaments[i].color); - wxColour tray_c = AmsTray::decode_color(box_filament_infos[j].color); - val.distance = GUI::calc_color_distance(c, tray_c); - if (filaments[i].type != box_filament_infos[j].type) { - val.distance = 999999; - val.is_type_match = false; - } else { - if (c.Alpha() != tray_c.Alpha()) - val.distance = 999999; - val.is_type_match = true; - } - ::sprintf(buffer, " %6.0f", val.distance); - line += std::string(buffer); - rol.push_back(val); - } - BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line; - distance_map.push_back(rol); - } - - ///////////////////////// - // Step 3: do mapping algorithm - - // setup the mapping result - for (int i = 0; i < filaments.size(); i++) { - FilamentInfo info; - info.id = filaments[i].id; - info.tray_id = -1; - info.type = filaments[i].type; - info.filament_id = filaments[i].filament_id; - result.push_back(info); - } - - // traverse the mapping - std::set picked_src; - std::set picked_tar; - //y59 y68 - for (int k = 0; k < distance_map.size(); k++) { - float min_val = INT_MAX; - int picked_src_idx = -1; - int picked_tar_idx = -1; - for (int i = 0; i < distance_map.size(); i++) { - if (picked_src.find(i) != picked_src.end()) - continue; - - // 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; - //} - continue; - } - - 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[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; - // } - // } - // } - // } - } - - //y59 - if (picked_src_idx >= 0 && picked_tar_idx >= 0) { - result[picked_src_idx].tray_id = distance_map[k][picked_tar_idx].tray_id; - result[picked_src_idx].color = box_filament_infos[picked_tar_idx].color; - result[picked_src_idx].type = box_filament_infos[picked_tar_idx].type; - result[picked_src_idx].distance = distance_map[k][picked_tar_idx].distance; - result[picked_src_idx].filament_id = box_filament_infos[picked_tar_idx].filament_id; - //result[picked_src_idx].ctype = tray->second.ctype; - - - /*for new ams mapping*/ - result[picked_src_idx].ams_id = box_filament_infos[picked_tar_idx].ams_id; - result[picked_src_idx].slot_id = box_filament_infos[picked_tar_idx].slot_id; - } - //::sprintf(buffer, "ams_mapping, picked F(%02d) AMS(%02d), distance=%6.0f", picked_src_idx+1, picked_tar_idx+1, - // distance_map[picked_src_idx][picked_tar_idx].distance); - //BOOST_LOG_TRIVIAL(info) << std::string(buffer); - picked_src.insert(picked_src_idx); - picked_tar.insert(picked_tar_idx); - } - - ////check ams mapping result - //if (is_valid_mapping_result(result, true)) { - // return 0; - //} - - /* for (auto it = result.begin(); it != result.end(); it++) {//This code has never been effective before 2025.03.18 - if (it->distance >= 6000) { - it->tray_id = -1; - } - }*/ - return 0; -} - -bool MachineObject::is_valid_mapping_result(std::vector& result, bool check_empty_slot) -{ - bool valid_ams_mapping_result = true; - if (result.empty()) return false; - - for (int i = 0; i < result.size(); i++) { - // invalid mapping result - if (result[i].tray_id < 0) { - if (result[i].ams_id.empty() && result[i].slot_id.empty()) { - valid_ams_mapping_result = false; - } - } - else { - auto ams_item = amsList.find(result[i].ams_id); - if (ams_item == amsList.end()) { - if ( (result[i].ams_id != std::to_string(VIRTUAL_TRAY_MAIN_ID)) && - (result[i].ams_id != std::to_string(VIRTUAL_TRAY_DEPUTY_ID))) { - result[i].tray_id = -1; - valid_ams_mapping_result = false; - } - } else { - if (check_empty_slot) { - auto tray_item = ams_item->second->trayList.find(result[i].slot_id); - if (tray_item == ams_item->second->trayList.end()) { - result[i].tray_id = -1; - valid_ams_mapping_result = false; - } else { - if (!tray_item->second->is_exists) { - result[i].tray_id = -1; - valid_ams_mapping_result = false; - } - } - } - } - } - } - return valid_ams_mapping_result; -} - -bool MachineObject::is_mapping_exceed_filament(std::vector & result, int &exceed_index) -{ - bool is_exceed = false; - for (int i = 0; i < result.size(); i++) { - int ams_id = result[i].tray_id / 4; - if (amsList.find(std::to_string(ams_id)) == amsList.end()) { - exceed_index = result[i].tray_id; - result[i].tray_id = -1; - is_exceed = true; - break; - } - if (result[i].mapping_result == MappingResult::MAPPING_RESULT_EXCEED) { - exceed_index = result[i].id; - is_exceed = true; - break; - } - } - return is_exceed; -} - -void MachineObject::reset_mapping_result(std::vector& result) -{ - for (int i = 0; i < result.size(); i++) { - result[i].tray_id = -1; - result[i].distance = 99999; - result[i].mapping_result = 0; - } -} - -bool MachineObject::is_main_extruder_on_left() const -{ - // only means the extruder is on the left hand when extruder id is 0 - return false; -} - -bool MachineObject::is_multi_extruders() const -{ - return m_extder_data.total_extder_count > 1; -} - -bool MachineObject::need_SD_card() const -{ - // todo: check whether need SD card - return !is_multi_extruders(); -} - -int MachineObject::get_extruder_id_by_ams_id(const std::string &ams_id) -{ - if (ams_id.empty() || (ams_id == "-1")) - return 0; - - auto it = amsList.find(ams_id); - if (it != amsList.end()) - return it->second->nozzle; - else if (stoi(ams_id) == VIRTUAL_TRAY_MAIN_ID) - return 0; - else if (stoi(ams_id) == VIRTUAL_TRAY_DEPUTY_ID) - return 1; - - assert(false); - return 0; -} - -bool MachineObject::is_qdt_filament(std::string tag_uid) -{ - if (tag_uid.empty()) - return false; - - for (int i = 0; i < tag_uid.length(); i++) { - if (tag_uid[i] != '0') - return true; - } - - return false; -} - -std::string MachineObject::light_effect_str(LIGHT_EFFECT effect) -{ - switch (effect) - { - case LIGHT_EFFECT::LIGHT_EFFECT_ON: - return "on"; - case LIGHT_EFFECT::LIGHT_EFFECT_OFF: - return "off"; - case LIGHT_EFFECT::LIGHT_EFFECT_FLASHING: - return "flashing"; - default: - return "unknown"; - } - return "unknown"; -} - -MachineObject::LIGHT_EFFECT MachineObject::light_effect_parse(std::string effect_str) -{ - if (effect_str.compare("on") == 0) - return LIGHT_EFFECT::LIGHT_EFFECT_ON; - else if (effect_str.compare("off") == 0) - return LIGHT_EFFECT::LIGHT_EFFECT_OFF; - else if (effect_str.compare("flashing") == 0) - return LIGHT_EFFECT::LIGHT_EFFECT_FLASHING; - else - return LIGHT_EFFECT::LIGHT_EFFECT_UNKOWN; - return LIGHT_EFFECT::LIGHT_EFFECT_UNKOWN; -} - - std::string MachineObject::get_firmware_type_str() { /*if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) @@ -1463,12 +745,12 @@ std::string MachineObject::get_lifecycle_type_str() bool MachineObject::is_in_upgrading() { - return upgrade_display_state == (int)UpgradingInProgress; + return upgrade_display_state == DevFirmwareUpgradingState::UpgradingInProgress; } bool MachineObject::is_upgrading_avalable() { - return upgrade_display_state == (int)UpgradingAvaliable; + return upgrade_display_state == DevFirmwareUpgradingState::UpgradingAvaliable; } int MachineObject::get_upgrade_percent() @@ -1530,10 +812,10 @@ wxString MachineObject::get_upgrade_result_str(int err_code) return ""; } -std::map MachineObject::get_ams_version() +std::map MachineObject::get_ams_version() { std::vector multi_tray_ams_type = {"ams", "n3f"}; - std::map result; + std::map result; for (int i = 0; i < 8; i++) { std::string ams_id; for (auto type : multi_tray_ams_type) @@ -1561,25 +843,23 @@ std::map MachineObject::get_ams_version() void MachineObject::clear_version_info() { - air_pump_version_info = ModuleVersionInfo(); - laser_version_info = ModuleVersionInfo(); - cutting_module_version_info = ModuleVersionInfo(); + air_pump_version_info = DevFirmwareVersionInfo(); + laser_version_info = DevFirmwareVersionInfo(); + cutting_module_version_info = DevFirmwareVersionInfo(); + extinguish_version_info = DevFirmwareVersionInfo(); module_vers.clear(); } -void MachineObject::store_version_info(const ModuleVersionInfo& info) +void MachineObject::store_version_info(const DevFirmwareVersionInfo& info) { - if (info.isAirPump()) - { + if (info.isAirPump()) { air_pump_version_info = info; - } - else if (info.isLaszer()) - { + } else if (info.isLaszer()) { laser_version_info = info; - } - else if (info.isCuttingModule()) - { + } else if (info.isCuttingModule()) { cutting_module_version_info = info; + } else if (info.isExtinguishSystem()) { + extinguish_version_info = info; } module_vers.emplace(info.name, info); @@ -1605,18 +885,17 @@ bool MachineObject::check_pa_result_validation(PACalibResult& result) bool MachineObject::is_axis_at_home(std::string axis) { - if (home_flag < 0) - return true; + if (m_home_flag == 0) { return true; } if (axis == "X") { - return home_flag & 1 == 1; + return (m_home_flag & 1) == 1; } else if (axis == "Y") { - return home_flag >> 1 & 1 == 1; + return ((m_home_flag >> 1) & 1) == 1; } else if (axis == "Z") { - return home_flag >> 2 & 1 == 1; - } else { - return true; + return ((m_home_flag >> 2) & 1) == 1; } + + return true; } bool MachineObject::is_filament_at_extruder() @@ -1690,8 +969,10 @@ void MachineObject::parse_state_changed_event() last_mc_print_stage = mc_print_stage; } -void MachineObject::parse_status(int flag) +void MachineObject::parse_home_flag(int flag) { + m_home_flag = flag; + is_220V_voltage = ((flag >> 3) & 0x1) != 0; if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { xcam_auto_recovery_step_loss = ((flag >> 4) & 0x1) != 0; @@ -1701,14 +982,16 @@ void MachineObject::parse_status(int flag) if (time(nullptr) - ams_user_setting_start > HOLD_COUNT_MAX) { - ams_calibrate_remain_flag = ((flag >> 7) & 0x1) != 0; + m_fila_system->GetAmsSystemSetting().SetDetectRemainEnabled(((flag >> 7) & 0x1) != 0); } - sdcard_state = MachineObject::SdcardState(get_flag_bits(flag, 8, 2)); + // sdcard_state = MachineObject::SdcardState(get_flag_bits(flag, 8, 2)); + m_storage->set_sdcard_state(get_flag_bits(flag, 8, 2)); + if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_3SEC) { - ams_auto_switch_filament_flag = ((flag >> 10) & 0x1) != 0; + m_fila_system->GetAmsSystemSetting().SetAutoRefillEnabled(((flag >> 10) & 0x1) != 0); } is_support_flow_calibration = ((flag >> 15) & 0x1) != 0; @@ -1764,14 +1047,6 @@ void MachineObject::parse_status(int flag) is_support_tunnel_mqtt = false; } -PrintingSpeedLevel MachineObject::_parse_printing_speed_lvl(int lvl) -{ - if (lvl < (int)SPEED_LEVEL_COUNT) - return PrintingSpeedLevel(lvl); - - return PrintingSpeedLevel::SPEED_LEVEL_INVALID; -} - int MachineObject::get_bed_temperature_limit() { if (get_printer_series() == PrinterSeries::SERIES_X1) { @@ -1789,17 +1064,17 @@ int MachineObject::get_bed_temperature_limit() bool MachineObject::is_filament_installed() { - if (m_extder_data.extders.size() > 0) { + if (m_extder_system->GetTotalExtderCount() > 0) { // right//or single - auto ext = m_extder_data.extders[MAIN_NOZZLE_ID]; - if (ext.ext_has_filament) { + auto ext = m_extder_system->m_extders[MAIN_EXTRUDER_ID]; + if (ext.m_ext_has_filament) { return true; } } /*left*/ - if (m_extder_data.extders.size() > 1) { - auto ext = m_extder_data.extders[DEPUTY_NOZZLE_ID]; - if (ext.ext_has_filament) { + if (m_extder_system->GetTotalExtderCount() > 1) { + auto ext = m_extder_system->m_extders[DEPUTY_EXTRUDER_ID]; + if (ext.m_ext_has_filament) { return true; } } @@ -1826,10 +1101,7 @@ bool MachineObject::is_sdcard_printing() return false; } -MachineObject::SdcardState MachineObject::get_sdcard_state() -{ - return sdcard_state; -} + bool MachineObject::is_timelapse() { @@ -1900,12 +1172,12 @@ bool MachineObject::canEnableTimelapse(wxString &error_message) const return true; } - if (sdcard_state != MachineObject::SdcardState::HAS_SDCARD_NORMAL) { - if (sdcard_state == MachineObject::SdcardState::NO_SDCARD) { + if (m_storage->get_sdcard_state() != DevStorage::SdcardState::HAS_SDCARD_NORMAL) { + if (m_storage->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { error_message = _L("Timelapse is not supported while the storage does not exist."); - } else if (sdcard_state == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL) { + } else if (m_storage->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL) { error_message = _L("Timelapse is not supported while the storage is unavailable."); - } else if (sdcard_state == MachineObject::SdcardState::HAS_SDCARD_READONLY) { + } else if (m_storage->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_READONLY) { error_message = _L("Timelapse is not supported while the storage is readonly."); } @@ -1915,21 +1187,6 @@ bool MachineObject::canEnableTimelapse(wxString &error_message) const return true; } -int MachineObject::command_select_extruder(int id) -{ - 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, 1); - if (rtn == 0) - { - targ_nozzle_id_from_pc = id; - } - - return rtn; -} - int MachineObject::command_get_version(bool with_retry) { json j; @@ -2009,6 +1266,24 @@ int MachineObject::command_clean_print_error(std::string subtask_id, int print_e return this->publish_json(j); } +int MachineObject::command_clean_print_error_uiop(int print_error) +{ + json j; + j["system"]["command"] = "uiop"; + j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["system"]["name"] = "print_error"; + j["system"]["action"] = "close"; + j["system"]["source"] = 1;// 0-Mushu 1-Studio + j["system"]["type"] = "dialog"; + + // the error to be cleaned + char buf[32]; + ::sprintf(buf, "%08X", print_error); + j["system"]["err"] = std::string(buf); + + return this->publish_json(j); +} + int MachineObject::command_upgrade_confirm() { json j; @@ -2069,61 +1344,18 @@ int MachineObject::command_auto_leveling() int MachineObject::command_go_home() { - if (this->is_in_printing()) { - return this->publish_gcode("G28 X\n"); - } - else { - return this->publish_gcode("G28 \n"); - } -} - -int MachineObject::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); -} - -// Old protocol -int MachineObject::command_control_fan(int fan_type, int val) -{ - std::string gcode = (boost::format("M106 P%1% S%2% \n") % (int)fan_type % (val)).str(); - try { + if (m_support_mqtt_homing) + { json j; - j["ctrl_type"] = get_string_from_fantype(fan_type); - j["value"] = val; - - NetworkAgent* agent = GUI::wxGetApp().getAgent(); - if (agent) agent->track_event("printer_control", j.dump()); + j["print"]["command"] = "back_to_center"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + return this->publish_json(j); } - catch (...) {} - return this->publish_gcode(gcode); + + // gcode command + return this->is_in_printing() ? this->publish_gcode("G28 X\n") : this->publish_gcode("G28 \n"); } -// New protocol -int MachineObject::command_control_fan_new(int fan_id, int val, const CommandCallBack &cb) -{ - 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; - return this->publish_json(j); -} - -int MachineObject::command_control_air_duct(int mode_id, int submode, const CommandCallBack &cb) -{ - 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); -} int MachineObject::command_task_partskip(std::vector part_ids) { @@ -2318,7 +1550,6 @@ int MachineObject::command_ams_change_filament(bool load, std::string ams_id, st tray_id = atoi(ams_id.c_str()) * 4 + atoi(slot_id.c_str()); } - j["print"]["command"] = "ams_change_filament"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["curr_temp"] = old_temp; @@ -2338,8 +1569,8 @@ int MachineObject::command_ams_change_filament(bool load, std::string ams_id, st j["print"]["slot_id"] = atoi(slot_id.c_str()); } - } catch (const std::exception &) {} + } catch (const std::exception &) {} return this->publish_json(j); } @@ -2353,9 +1584,9 @@ int MachineObject::command_ams_user_settings(int ams_id, bool start_read_opt, bo j["print"]["tray_read_option"] = tray_read_opt; j["print"]["calibrate_remain_flag"] = remain_flag; - ams_insert_flag = tray_read_opt; - ams_power_on_flag = start_read_opt; - ams_calibrate_remain_flag = remain_flag; + m_fila_system->GetAmsSystemSetting().SetDetectOnInsertEnabled(tray_read_opt); + m_fila_system->GetAmsSystemSetting().SetDetectOnPowerupEnabled(start_read_opt); + m_fila_system->GetAmsSystemSetting().SetDetectRemainEnabled(remain_flag); ams_user_setting_start = time(nullptr); return this->publish_json(j); @@ -2437,80 +1668,19 @@ int MachineObject::command_ams_control(std::string action) return -1; } -int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) +int MachineObject::command_ams_drying_stop() { json j; - j["system"]["command"] = "ledctrl"; - j["system"]["led_node"] = "chamber_light"; - j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["system"]["led_mode"] = light_effect_str(effect); - j["system"]["led_on_time"] = on_time; - j["system"]["led_off_time"] = off_time; - j["system"]["loop_times"] = loops; - j["system"]["interval_time"] = interval; - return this->publish_json(j); -} - - -int MachineObject::command_set_chamber_light2(LIGHT_EFFECT effect, int on_time /*= 500*/, int off_time /*= 500*/, int loops /*= 1*/, int interval /*= 1000*/) -{ - json j; - j["system"]["command"] = "ledctrl"; - j["system"]["led_node"] = "chamber_light2"; - j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["system"]["led_mode"] = light_effect_str(effect); - j["system"]["led_on_time"] = on_time; - j["system"]["led_off_time"] = off_time; - j["system"]["loop_times"] = loops; - j["system"]["interval_time"] = interval; - 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; - - 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); -} - -int MachineObject::command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter) -{ - nozzle_setting_hold_count = HOLD_COUNT_MAX * 2; - - json j; - j["print"]["command"] = "set_nozzle"; - j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["print"]["id"] = id; - j["print"]["type"] = nozzle_type; - j["print"]["diameter"] = diameter; - j["print"]["wear"] = 0; - return this->publish_json(j); -} - - -int MachineObject::command_set_work_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) -{ - json j; - j["system"]["command"] = "ledctrl"; - j["system"]["led_node"] = "work_light"; - j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); - j["system"]["led_mode"] = light_effect_str(effect); - j["system"]["led_on_time"] = on_time; - j["system"]["led_off_time"] = off_time; - j["system"]["loop_times"] = loops; - j["system"]["interval_time"] = interval; - + j["print"]["command"] = "auto_stop_ams_dry"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); 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++); @@ -2555,7 +1725,7 @@ int MachineObject::command_extrusion_cali_set(int tray_index, std::string settin } -int MachineObject::command_set_printing_speed(PrintingSpeedLevel lvl) +int MachineObject::command_set_printing_speed(DevPrintingSpeedLevel lvl) { json j; j["print"]["command"] = "print_speed"; @@ -2613,7 +1783,8 @@ int MachineObject::command_ams_switch_filament(bool switch_filament) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["auto_switch_filament"] = switch_filament; - ams_auto_switch_filament_flag = switch_filament; + m_fila_system->GetAmsSystemSetting().SetAutoRefillEnabled(switch_filament); + BOOST_LOG_TRIVIAL(trace) << "command_ams_filament_settings:" << switch_filament; ams_switch_filament_start = time(nullptr); return this->publish_json(j); @@ -2661,7 +1832,6 @@ int MachineObject::command_axis_control(std::string axis, double unit, double in } else if (axis.compare("E") == 0) { sprintf(cmd, "M83 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed); - extruder_axis_status = (value >= 0.0f)? LOAD : UNLOAD; } else { return -1; @@ -2745,7 +1915,7 @@ int MachineObject::command_start_pa_calibration(const X1CCalibInfos &pa_data, in j["print"]["filaments"][i]["nozzle_temp"] = pa_data.calib_datas[i].nozzle_temp; j["print"]["filaments"][i]["ams_id"] = pa_data.calib_datas[i].ams_id; j["print"]["filaments"][i]["slot_id"] = pa_data.calib_datas[i].slot_id; - j["print"]["filaments"][i]["nozzle_id"] = generate_nozzle_id(pa_data.calib_datas[i].nozzle_volume_type,to_string_nozzle_diameter(pa_data.calib_datas[i].nozzle_diameter)).ToStdString(); + j["print"]["filaments"][i]["nozzle_id"] = _generate_nozzle_id(pa_data.calib_datas[i].nozzle_volume_type,to_string_nozzle_diameter(pa_data.calib_datas[i].nozzle_diameter)).ToStdString(); j["print"]["filaments"][i]["nozzle_diameter"] = to_string_nozzle_diameter(pa_data.calib_datas[i].nozzle_diameter); j["print"]["filaments"][i]["max_volumetric_speed"] = std::to_string(pa_data.calib_datas[i].max_volumetric_speed); @@ -2783,7 +1953,7 @@ int MachineObject::command_set_pa_calibration(const std::vector & j["print"]["filaments"][i]["cali_idx"] = pa_calib_values[i].cali_idx; j["print"]["filaments"][i]["tray_id"] = pa_calib_values[i].tray_id; j["print"]["filaments"][i]["extruder_id"] = pa_calib_values[i].extruder_id; - j["print"]["filaments"][i]["nozzle_id"] = generate_nozzle_id(pa_calib_values[i].nozzle_volume_type, to_string_nozzle_diameter(pa_calib_values[i].nozzle_diameter)).ToStdString(); + j["print"]["filaments"][i]["nozzle_id"] = _generate_nozzle_id(pa_calib_values[i].nozzle_volume_type, to_string_nozzle_diameter(pa_calib_values[i].nozzle_diameter)).ToStdString(); j["print"]["filaments"][i]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib_values[i].nozzle_diameter); j["print"]["filaments"][i]["ams_id"] = pa_calib_values[i].ams_id; j["print"]["filaments"][i]["slot_id"] = pa_calib_values[i].slot_id; @@ -2809,7 +1979,7 @@ int MachineObject::command_delete_pa_calibration(const PACalibIndexInfo& pa_cali j["print"]["command"] = "extrusion_cali_del"; j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["extruder_id"] = pa_calib.extruder_id; - j["print"]["nozzle_id"] = generate_nozzle_id(pa_calib.nozzle_volume_type, to_string_nozzle_diameter(pa_calib.nozzle_diameter)).ToStdString(); + j["print"]["nozzle_id"] = _generate_nozzle_id(pa_calib.nozzle_volume_type, to_string_nozzle_diameter(pa_calib.nozzle_diameter)).ToStdString(); j["print"]["filament_id"] = pa_calib.filament_id; j["print"]["cali_idx"] = pa_calib.cali_idx; j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(pa_calib.nozzle_diameter); @@ -2827,7 +1997,6 @@ int MachineObject::command_get_pa_calibration_tab(float nozzle_diameter, const s j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["filament_id"] = filament_id; j["print"]["nozzle_diameter"] = to_string_nozzle_diameter(nozzle_diameter); - return this->publish_json(j); } @@ -2842,7 +2011,7 @@ int MachineObject::command_get_pa_calibration_tab(const PACalibExtruderInfo &cal if (calib_info.use_extruder_id) j["print"]["extruder_id"] = calib_info.extruder_id; if (calib_info.use_nozzle_volume_type) - j["print"]["nozzle_id"] = generate_nozzle_id(calib_info.nozzle_volume_type, to_string_nozzle_diameter(calib_info.nozzle_diameter)).ToStdString(); + 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); request_tab_from_qds = true; @@ -3019,7 +2188,6 @@ int MachineObject::command_xcam_control_nozzleclumping_detection(bool on_off, st 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; @@ -3030,7 +2198,6 @@ int MachineObject::command_xcam_control_airprinting_detection(bool on_off, std:: 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; @@ -3188,14 +2355,12 @@ void MachineObject::reset() print_status = ""; last_mc_print_stage = -1; m_new_ver_list_exist = false; - extruder_axis_status = LOAD; network_wired = false; dev_connection_name = ""; job_id_ = ""; jobState_ = 0; m_plate_index = -1; - - nt_reset_data(); + device_cert_installed = false; // reset print_json json empty_j; @@ -3212,14 +2377,6 @@ void MachineObject::reset() m_partskip_ids.clear(); } -void MachineObject::nt_reset_data() -{ - nt_try_local_tunnel = false; - nt_use_local_tunnel = false; - nt_cloud_full_msg_count = 0; - nt_local_full_msg_count = 0; -} - void MachineObject::set_print_state(std::string status) { print_status = status; @@ -3227,13 +2384,13 @@ void MachineObject::set_print_state(std::string status) int MachineObject::connect(bool use_openssl) { - if (dev_ip.empty()) return -1; + if (get_dev_ip().empty()) return -1; std::string username = "qdtp"; std::string password = get_access_code(); if (m_agent) { try { - return m_agent->connect_printer(dev_id, dev_ip, username, password, use_openssl); + return m_agent->connect_printer(get_dev_id(), get_dev_ip(), username, password, use_openssl); } catch (...) { ; } @@ -3281,17 +2438,31 @@ void MachineObject::set_online_state(bool on_off) bool MachineObject::is_info_ready(bool check_version) const { if (check_version && module_vers.empty()) + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": not ready, failed to check version"; return false; + } std::chrono::system_clock::time_point curr_time = std::chrono::system_clock::now(); auto diff = std::chrono::duration_cast(last_push_time - curr_time); if (m_full_msg_count > 0 && m_push_count > 0 && diff.count() < PUSHINFO_TIMEOUT) { return true; } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ + << ": not ready, m_full_msg_count=" << m_full_msg_count + << ", m_push_count=" << m_push_count + << ", diff.count()=" << diff.count() + << ", dev_id=" << QDTCrossTalk::Crosstalk_DevId(dev_id); return false; } +bool MachineObject::is_security_control_ready() const +{ + return device_cert_installed; +} + std::vector MachineObject::get_resolution_supported() { return camera_resolution_supported; @@ -3299,7 +2470,7 @@ std::vector MachineObject::get_resolution_supported() std::vector MachineObject::get_compatible_machine() { - return DeviceManager::get_compatible_machine(printer_type); + return DevPrinterConfigUtil::get_compatible_machine(printer_type); } bool MachineObject::is_camera_busy_off() @@ -3331,7 +2502,7 @@ int MachineObject::cloud_publish_json(std::string json_str, int qos, int flag) { int result = -1; if (m_agent) - result = m_agent->send_message(dev_id, json_str, qos, flag); + result = m_agent->send_message(get_dev_id(), json_str, qos, flag); return result; } @@ -3340,7 +2511,7 @@ int MachineObject::local_publish_json(std::string json_str, int qos, int flag) { int result = -1; if (m_agent) { - result = m_agent->send_message_to_printer(dev_id, json_str, qos, flag); + result = m_agent->send_message_to_printer(get_dev_id(), json_str, qos, flag); } return result; } @@ -3378,6 +2549,9 @@ static ENUM enum_index_of(char const *key, char const **enum_names, int enum_cou int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_field_only) { + if (tunnel == "lan") last_lan_msg_time_ = std::chrono::system_clock::now(); + if (tunnel == "cloud") last_cloud_msg_time_ = std::chrono::system_clock::now(); + parse_msg_count++; std::chrono::system_clock::time_point clock_start = std::chrono::system_clock::now(); this->set_online_state(true); @@ -3420,10 +2594,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ m_push_count++; m_full_msg_count++; - if (tunnel == "cloud") {nt_cloud_full_msg_count++;} - if (tunnel == "lan") {nt_local_full_msg_count++;} - nt_condition_local_tunnel(); - if (!printer_type.empty()) print_json.load_compatible_settings(printer_type, ""); print_json.diff2all_base_reset(j_pre); @@ -3448,9 +2618,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } else { if (!printer_type.empty()) { - nt_local_full_msg_count++; m_full_msg_count++;/* all message package is full at LAN mode*/ - nt_condition_local_tunnel(); print_json.load_compatible_settings(printer_type, ""); } @@ -3591,7 +2759,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ json j_module = j["info"]["module"]; clear_version_info(); for (auto it = j_module.begin(); it != j_module.end(); it++) { - ModuleVersionInfo ver_info; + DevFirmwareVersionInfo ver_info; ver_info.name = (*it)["name"].get(); if ((*it).contains("product_name")) ver_info.product_name = wxString::FromUTF8((*it)["product_name"].get()); @@ -3607,13 +2775,13 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if ((*it).contains("hw_ver")) ver_info.hw_ver = (*it)["hw_ver"].get(); if((*it).contains("flag")) - ver_info.firmware_status= (*it)["flag"].get(); + ver_info.firmware_flag= (*it)["flag"].get(); store_version_info(ver_info); if (ver_info.name == "ota") { NetworkAgent* agent = GUI::wxGetApp().getAgent(); if (agent) { - std::string dev_ota_str = "dev_ota_ver:" + this->dev_id; + std::string dev_ota_str = "dev_ota_ver:" + this->get_dev_id(); agent->track_update_property(dev_ota_str, ver_info.sw_ver); } } @@ -3663,7 +2831,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } if (!key_field_only) { - if (!DeviceManager::EnableMultiMachine && !is_support_agora) { + if (!m_manager->IsMultiMachineEnabled() && !is_support_agora) { if (jj.contains("support_tunnel_mqtt")) { if (jj["support_tunnel_mqtt"].is_boolean()) { is_support_tunnel_mqtt = jj["support_tunnel_mqtt"].get(); @@ -3692,67 +2860,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } //supported function - if (jj.contains("support_chamber_temp_edit")) { - if (jj["support_chamber_temp_edit"].is_boolean()) { - is_support_chamber_edit = jj["support_chamber_temp_edit"].get(); - } - - const auto& support_champer_range = jj["support_chamber_temp_edit_range"]; - if (support_champer_range.is_array() && !support_champer_range.empty()) - { - chamber_temp_edit_min = support_champer_range[0]; - chamber_temp_edit_max = support_champer_range[1]; - } - - if (jj.contains("support_chamber_temp_switch_heating")) - { - const auto& support_chamber_temp_switch_heating = jj["support_chamber_temp_switch_heating"]; - if (support_chamber_temp_switch_heating.is_number()) - { - chamber_temp_switch_heat = support_chamber_temp_switch_heating.get(); - } - } - } - - if (jj.contains("support_extrusion_cali")) { - if (jj["support_extrusion_cali"].is_boolean()) { - is_support_extrusion_cali = jj["support_extrusion_cali"].get(); - } - } - - if (jj.contains("support_first_layer_inspect")) { - if (jj["support_first_layer_inspect"].is_boolean()) { - is_support_first_layer_inspect = jj["support_first_layer_inspect"].get(); - } - } - - if (jj.contains("support_save_remote_print_file_to_storage")) { - if (jj["support_save_remote_print_file_to_storage"].is_boolean()) { - is_support_save_remote_print_file_to_storage = jj["support_save_remote_print_file_to_storage"].get(); - } - } - - if (jj.contains("support_ai_monitoring")) { - if (jj["support_ai_monitoring"].is_boolean()) { - is_support_ai_monitoring = jj["support_ai_monitoring"].get(); - } - } - - if (jj.contains("support_lidar_calibration")) { - if (jj["support_lidar_calibration"].is_boolean()) { - is_support_lidar_calibration = jj["support_lidar_calibration"].get(); - } - } - - if (jj.contains("support_nozzle_offset_calibration") && jj["support_nozzle_offset_calibration"].is_boolean()) - { - is_support_nozzle_offset_cali = jj["support_nozzle_offset_calibration"].get(); - } - - if (jj.contains("support_high_tempbed_calibration") && jj["support_high_tempbed_calibration"].is_boolean()) - { - is_support_high_tempbed_cali = jj["support_high_tempbed_calibration"].get(); - } + m_config->ParseConfig(jj); if (jj.contains("support_build_plate_marker_detect")) { if (jj["support_build_plate_marker_detect"].is_boolean()) { @@ -3769,39 +2877,13 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ is_support_pa_calibration = jj["support_flow_calibration"].get(); } - if (jj.contains("support_auto_flow_calibration") && jj["support_auto_flow_calibration"].is_boolean()) - { - is_support_auto_flow_calibration = jj["support_auto_flow_calibration"].get(); - } - - if (jj.contains("support_print_without_sd")) { - if (jj["support_print_without_sd"].is_boolean()) { - is_support_print_without_sd = jj["support_print_without_sd"].get(); - } - } - - if (jj.contains("support_print_all")) { - if (jj["support_print_all"].is_boolean()) { - is_support_print_all = jj["support_print_all"].get(); - } - } if (jj.contains("support_send_to_sd")) { if (jj["support_send_to_sd"].is_boolean()) { is_support_send_to_sdcard = jj["support_send_to_sd"].get(); } } - if (jj.contains("support_aux_fan")) { - if (jj["support_aux_fan"].is_boolean()) { - is_support_aux_fan = jj["support_aux_fan"].get(); - } - } - - if (jj.contains("support_chamber_fan")) { - if (jj["support_chamber_fan"].is_boolean()) { - is_support_chamber_fan = jj["support_chamber_fan"].get(); - } - } + m_fan->ParseV2_0(jj); if (jj.contains("support_filament_backup")) { if (jj["support_filament_backup"].is_boolean()) { @@ -3938,6 +3020,15 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } + + if (!key_field_only) + { + if (is_studio_cmd(sequence_id) && jj.contains("command") && jj.contains("err_code") && jj.contains("result")) + { + if (jj["err_code"].is_number()) { add_command_error_code_dlg(jj["err_code"].get());} + } + } + if (jj["command"].get() == "push_status") { m_push_count++; last_push_time = last_update_time; @@ -3978,25 +3069,15 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ print_error = jj["print_error"].get(); } - if (jj.contains("sdcard")) { - if (jj["sdcard"].get()) - sdcard_state = MachineObject::SdcardState::HAS_SDCARD_NORMAL; - else - sdcard_state = MachineObject::SdcardState::NO_SDCARD; - } else { - sdcard_state = MachineObject::SdcardState::NO_SDCARD; - } + DevStorage::ParseV1_0(jj, m_storage); if (!key_field_only) { - if (jj.contains("home_flag")) { - home_flag = jj["home_flag"].get(); - parse_status(home_flag); - } + if (jj.contains("home_flag")) { parse_home_flag(jj["home_flag"].get());} /*the param is invalid in np for Yeshu*/ if (jj.contains("hw_switch_state")) { hw_switch_state = jj["hw_switch_state"].get(); - m_extder_data.extders[MAIN_NOZZLE_ID].ext_has_filament = hw_switch_state; + m_extder_system->m_extders[MAIN_EXTRUDER_ID].m_ext_has_filament = hw_switch_state; } if (jj.contains("mc_print_line_number")) { if (jj["mc_print_line_number"].is_string() && !jj["mc_print_line_number"].is_null()) @@ -4023,7 +3104,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (tmp_dev_ip == 0) continue ; else { - set_dev_ip(convertToIp(tmp_dev_ip)); + set_dev_ip(DevUtil::convertToIp(tmp_dev_ip)); } } else { break; @@ -4054,7 +3135,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(); } @@ -4077,7 +3158,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } if (jj.contains("job_id")) { is_support_wait_sending_finish = true; - this->job_id_ = JsonValParser::get_longlong_val(jj["job_id"]); + this->job_id_ = DevJsonValParser::get_longlong_val(jj["job_id"]); } else { is_support_wait_sending_finish = false; @@ -4089,7 +3170,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (!key_field_only) { if (jj.contains("printer_type")) { - printer_type = parse_printer_type(jj["printer_type"].get()); + printer_type = _parse_printer_type(jj["printer_type"].get()); } if (jj.contains("layer_num")) { @@ -4172,35 +3253,17 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ #pragma region status if (!key_field_only) { /* temperature */ - if (jj.contains("bed_temper")) { - if (jj["bed_temper"].is_number()) { - bed_temp = jj["bed_temper"].get(); - } - } - if (jj.contains("bed_target_temper")) { - if (jj["bed_target_temper"].is_number()) { - bed_temp_target = jj["bed_target_temper"].get(); - } - } + + DevBed::ParseV1_0(jj,m_bed); + if (jj.contains("frame_temper")) { if (jj["frame_temper"].is_number()) { frame_temp = jj["frame_temper"].get(); } } - if (jj.contains("nozzle_temper")) { - if (jj["nozzle_temper"].is_number()) { - if (m_extder_data.extders.size() == 1) { - m_extder_data.extders[MAIN_NOZZLE_ID].temp = jj["nozzle_temper"].get(); - } - } - } - if (jj.contains("nozzle_target_temper")) { - if (jj["nozzle_target_temper"].is_number()) { - if (m_extder_data.extders.size() == 1) { - m_extder_data.extders[MAIN_NOZZLE_ID].target_temp = jj["nozzle_target_temper"].get(); - } - } - } + + ExtderSystemParser::ParseV1_0(jj, m_extder_system); + if (jj.contains("chamber_temper")) { if (jj["chamber_temper"].is_number()) { chamber_temp = jj["chamber_temper"].get(); @@ -4220,51 +3283,15 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ wifi_signal = jj["wifi_signal"].get(); /* cooling */ - if (jj.contains("fan_gear")) { - fan_gear = jj["fan_gear"].get(); - big_fan2_speed = (int)((fan_gear & 0x00FF0000) >> 16); - big_fan1_speed = (int)((fan_gear & 0x0000FF00) >> 8); - cooling_fan_speed = (int)((fan_gear & 0x000000FF) >> 0); - } - else { - if (jj.contains("cooling_fan_speed")) { - cooling_fan_speed = stoi(jj["cooling_fan_speed"].get()); - cooling_fan_speed = round(floor(cooling_fan_speed / float(1.5)) * float(25.5)); - } - else { - cooling_fan_speed = 0; - } - if (jj.contains("big_fan1_speed")) { - big_fan1_speed = stoi(jj["big_fan1_speed"].get()); - big_fan1_speed = round( floor(big_fan1_speed / float(1.5)) * float(25.5) ); - } - else { - big_fan1_speed = 0; - } - if (jj.contains("big_fan2_speed")) { - big_fan2_speed = stoi(jj["big_fan2_speed"].get()); - big_fan2_speed = round( floor(big_fan2_speed / float(1.5)) * float(25.5) ); - } - else { - big_fan2_speed = 0; - } - } - - if (jj.contains("heatbreak_fan_speed")) { - heatbreak_fan_speed = stoi(jj["heatbreak_fan_speed"].get()); - } + m_fan->ParseV1_0(jj); /* parse speed */ + DevPrintOptionsParser::Parse(m_print_options, jj); + try { - if (jj.contains("spd_lvl")) { - printing_speed_lvl = (PrintingSpeedLevel)jj["spd_lvl"].get(); - } if (jj.contains("spd_mag")) { printing_speed_mag = jj["spd_mag"].get(); } - if (jj.contains("heatbreak_fan_speed")) { - heatbreak_fan_speed = stoi(jj["heatbreak_fan_speed"].get()); - } } catch (...) { ; @@ -4293,20 +3320,16 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (!key_field_only) { /*get filam_bak*/ try { - m_extder_data.extders[MAIN_NOZZLE_ID].filam_bak.clear(); + m_extder_system->m_extders[MAIN_EXTRUDER_ID].m_filam_bak.clear(); if (jj.contains("filam_bak")) { - is_support_show_filament_backup = true; if (jj["filam_bak"].is_array()) { for (auto it = jj["filam_bak"].begin(); it != jj["filam_bak"].end(); it++) { const auto& filam_bak_val = it.value().get(); - m_extder_data.extders[MAIN_NOZZLE_ID].filam_bak.push_back(filam_bak_val); + m_extder_system->m_extders[MAIN_EXTRUDER_ID].m_filam_bak.push_back(filam_bak_val); } } } - else { - is_support_show_filament_backup = false; - } } catch (...) { ; @@ -4342,9 +3365,9 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj.contains("lights_report") && jj["lights_report"].is_array()) { for (auto it = jj["lights_report"].begin(); it != jj["lights_report"].end(); it++) { if ((*it)["node"].get().compare("chamber_light") == 0) - chamber_light = light_effect_parse((*it)["mode"].get()); - if ((*it)["node"].get().compare("work_light") == 0) - work_light = light_effect_parse((*it)["mode"].get()); + { + m_lamp->SetChamberLight((*it)["mode"].get()); + } } } } @@ -4354,49 +3377,17 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } #pragma endregion if (!key_field_only) { - try { - if (jj.contains("nozzle_diameter")) { - if (nozzle_setting_hold_count > 0) { - nozzle_setting_hold_count--; - } else { - float nozzle_diameter = 0.0f; - if (jj["nozzle_diameter"].is_number_float()) { - nozzle_diameter = jj["nozzle_diameter"].get(); - } - else if (jj["nozzle_diameter"].is_string()) { - nozzle_diameter = string_to_float(jj["nozzle_diameter"].get()); - } - if (nozzle_diameter == 0.0f) {m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_diameter = 0.0f;} - else { m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_diameter = round(nozzle_diameter * 10) / 10;} - } + if (jj.contains("nozzle_diameter") && jj.contains("nozzle_type")) + { + int nozzle_flow_type = -1; + + if(jj.contains("flag3")){ + int flag3 = jj["flag3"].get(); + nozzle_flow_type = get_flag_bits(flag3, 10, 3); } - } - catch(...) { - ; - } - try { - if (jj.contains("nozzle_type")) { - - if (nozzle_setting_hold_count > 0) { - nozzle_setting_hold_count--; - } - else { - if (jj["nozzle_type"].is_string()) { - auto nozzle_type = jj["nozzle_type"].get(); - if (nozzle_type.empty()) { - m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_type = NozzleType::ntUndefine; - } - else { - m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_type = NozzleTypeStrToEumn[nozzle_type]; - } - } - } - } - } - catch (...) { - ; + DevNozzleSystemParser::ParseV1_0(jj["nozzle_type"], jj["nozzle_diameter"], nozzle_flow_type, m_nozzle_system); } } @@ -4426,7 +3417,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj["upgrade_state"].contains("err_code")) upgrade_err_code = jj["upgrade_state"]["err_code"].get(); if (jj["upgrade_state"].contains("dis_state")) { - if (upgrade_display_state != jj["upgrade_state"]["dis_state"].get() + if ((int)upgrade_display_state != jj["upgrade_state"]["dis_state"].get() && jj["upgrade_state"]["dis_state"].get() == 3) { GUI::wxGetApp().CallAfter([this] { this->command_get_version(); @@ -4438,10 +3429,10 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } else { - upgrade_display_state = jj["upgrade_state"]["dis_state"].get(); - if ((upgrade_display_state == 1) && is_lan_mode_printer()) + upgrade_display_state = (DevFirmwareUpgradingState)jj["upgrade_state"]["dis_state"].get(); + if ((upgrade_display_state == DevFirmwareUpgradingState::UpgradingAvaliable) && is_lan_mode_printer()) { - upgrade_display_state = (int) UpgradingDisplayState::UpgradingUnavaliable; + upgrade_display_state = DevFirmwareUpgradingState::UpgradingUnavaliable; } } } @@ -4455,21 +3446,21 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ || upgrade_status == "UPGRADE_REQUEST" || upgrade_status == "PRE_FLASH_START" || upgrade_status == "PRE_FLASH_SUCCESS") { - upgrade_display_state = (int)UpgradingDisplayState::UpgradingInProgress; + upgrade_display_state = DevFirmwareUpgradingState::UpgradingInProgress; } else if (upgrade_status == "UPGRADE_SUCCESS" || upgrade_status == "DOWNLOAD_FAIL" || upgrade_status == "FLASH_FAIL" || upgrade_status == "PRE_FLASH_FAIL" || upgrade_status == "UPGRADE_FAIL") { - upgrade_display_state = (int)UpgradingDisplayState::UpgradingFinished; + upgrade_display_state = DevFirmwareUpgradingState::UpgradingFinished; } else { if (upgrade_new_version) { - upgrade_display_state = (int)UpgradingDisplayState::UpgradingAvaliable; + upgrade_display_state = DevFirmwareUpgradingState::UpgradingAvaliable; } else { - upgrade_display_state = (int)UpgradingDisplayState::UpgradingUnavaliable; + upgrade_display_state = DevFirmwareUpgradingState::UpgradingUnavaliable; } } } @@ -4479,7 +3470,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ m_new_ver_list_exist = true; new_ver_list.clear(); for (auto ver_item = jj["upgrade_state"]["new_ver_list"].begin(); ver_item != jj["upgrade_state"]["new_ver_list"].end(); ver_item++) { - ModuleVersionInfo ver_info; + DevFirmwareVersionInfo ver_info; if (ver_item->contains("name")) ver_info.name = (*ver_item)["name"].get(); else @@ -4671,27 +3662,8 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ #pragma endregion #pragma region hms - if (!key_field_only) { - // parse hms msg - try { - hms_list.clear(); - if (jj.contains("hms")) { - if (jj["hms"].is_array()) { - for (auto it = jj["hms"].begin(); it != jj["hms"].end(); it++) { - HMSItem item; - if ((*it).contains("attr") && (*it).contains("code")) { - unsigned attr = (*it)["attr"].get(); - unsigned code = (*it)["code"].get(); - item.parse_hms_info(attr, code); - } - hms_list.push_back(item); - } - } - } - } - catch (...) { - ; - } + if (!key_field_only && jj.contains("hms")) { + m_hms_system->ParseHMSItems(jj["hms"]); } #pragma endregion @@ -4703,13 +3675,14 @@ 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 (...) { ; @@ -4717,389 +3690,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ update_printer_preset_name(); update_filament_list(); if (jj.contains("ams")) { - if (jj["ams"].contains("ams")) { - long int last_ams_exist_bits = ams_exist_bits; - long int last_tray_exist_bits = tray_exist_bits; - long int last_is_qdt_bits = tray_is_qdt_bits; - long int last_read_done_bits = tray_read_done_bits; - long int last_ams_version = ams_version; - if (jj["ams"].contains("ams_exist_bits")) { - ams_exist_bits = stol(jj["ams"]["ams_exist_bits"].get(), nullptr, 16); - } - - if (jj["ams"].contains("tray_exist_bits")) { - tray_exist_bits = stol(jj["ams"]["tray_exist_bits"].get(), nullptr, 16); - } - - if (jj["ams"].contains("cali_id")) - { - ams_cali_id = jj["ams"]["cali_id"].get(); - } - - if (jj["ams"].contains("cali_stat")) - { - ams_cali_stat = jj["ams"]["cali_stat"].get(); - } - - if (!key_field_only) { - if (jj["ams"].contains("tray_read_done_bits")) { - tray_read_done_bits = stol(jj["ams"]["tray_read_done_bits"].get(), nullptr, 16); - } - if (jj["ams"].contains("tray_reading_bits")) { - tray_reading_bits = stol(jj["ams"]["tray_reading_bits"].get(), nullptr, 16); - } - if (jj["ams"].contains("tray_is_qdt_bits")) { - tray_is_qdt_bits = stol(jj["ams"]["tray_is_qdt_bits"].get(), nullptr, 16); - } - if (jj["ams"].contains("version")) { - if (jj["ams"]["version"].is_number()) - ams_version = jj["ams"]["version"].get(); - } - if (jj["ams"].contains("tray_tar")) { - m_tray_tar = jj["ams"]["tray_tar"].get(); - } - if (jj["ams"].contains("tray_now")) { - _parse_tray_now(jj["ams"]["tray_now"].get()); - } - if (jj["ams"].contains("ams_rfid_status")) - ams_rfid_status = jj["ams"]["ams_rfid_status"].get(); - - if (jj["ams"].contains("insert_flag") || jj["ams"].contains("power_on_flag") - || jj["ams"].contains("calibrate_remain_flag")) { - if (time(nullptr) - ams_user_setting_start > HOLD_TIME_3SEC) - { - if (jj["ams"].contains("insert_flag")) { - ams_insert_flag = jj["ams"]["insert_flag"].get(); - } - if (jj["ams"].contains("power_on_flag")) { - ams_power_on_flag = jj["ams"]["power_on_flag"].get(); - } - if (jj["ams"].contains("calibrate_remain_flag")) { - ams_calibrate_remain_flag = jj["ams"]["calibrate_remain_flag"].get(); - } - } - } - if (ams_exist_bits != last_ams_exist_bits - || last_tray_exist_bits != last_tray_exist_bits - || tray_is_qdt_bits != last_is_qdt_bits - || tray_read_done_bits != last_read_done_bits - || last_ams_version != ams_version) { - is_ams_need_update = true; - } - else { - is_ams_need_update = false; - } - - json j_ams = jj["ams"]["ams"]; - std::set ams_id_set; - - for (auto it = amsList.begin(); it != amsList.end(); it++) { - ams_id_set.insert(it->first); - } - - for (auto it = j_ams.begin(); it != j_ams.end(); it++) { - if (!it->contains("id")) continue; - std::string ams_id = (*it)["id"].get(); - - int nozzle_id = MAIN_NOZZLE_ID; // Default nozzle id - int type_id = 1; // 0:dummy 1:ams 2:ams-lite 3:n3f 4:n3s - - /*ams info*/ - std::string info; - if (it->contains("info")) { - info = (*it)["info"].get(); - type_id = get_flag_bits(info, 0, 4); - nozzle_id = get_flag_bits(info, 8, 4); - } - - /*AMS without initialization*/ - if (nozzle_id == 0xE) { - ams_id_set.erase(ams_id); - amsList.erase(ams_id); - continue; - } - - ams_id_set.erase(ams_id); - Ams* curr_ams = nullptr; - auto ams_it = amsList.find(ams_id); - if (ams_it == amsList.end()) { - Ams* new_ams = new Ams(ams_id, nozzle_id, type_id); - new_ams->info = info; - amsList.insert(std::make_pair(ams_id, new_ams)); - // new ams added event - curr_ams = new_ams; - } else { - - if (nozzle_id != ams_it->second->nozzle) { - ams_it->second->nozzle = nozzle_id; - } - - curr_ams = ams_it->second; - } - if (!curr_ams) continue; - - /*set ams type flag*/ - curr_ams->type = type_id; - - - /*set ams exist flag*/ - try { - if (!ams_id.empty()) { - int ams_id_int = atoi(ams_id.c_str()); - - if (type_id < 4) { - curr_ams->is_exists = (ams_exist_bits & (1 << ams_id_int)) != 0 ? true : false; - } else { - curr_ams->is_exists = get_flag_bits(ams_exist_bits, 4 + (ams_id_int - 128)); - } - } - } catch (...) { - ; - } - - if (it->contains("dry_time") && (*it)["dry_time"].is_number()) - { - curr_ams->left_dry_time = (*it)["dry_time"].get(); - } - - if (it->contains("humidity")) { - std::string humidity = (*it)["humidity"].get(); - - try { - curr_ams->humidity = atoi(humidity.c_str()); - } - catch (...) { - ; - } - } - - if (it->contains("humidity_raw")) - { - std::string humidity_raw = (*it)["humidity_raw"].get(); - - try { - curr_ams->humidity_raw = atoi(humidity_raw.c_str()); - } catch (...) { - ; - } - - if (curr_ams->humidity_raw != -1) - { - if (curr_ams->humidity_raw < 20) - { - curr_ams->humidity = 5; - } - else if (curr_ams->humidity_raw < 40) - { - curr_ams->humidity = 4; - } - else if (curr_ams->humidity_raw < 60) - { - curr_ams->humidity = 3; - } - else if (curr_ams->humidity_raw < 80) - { - curr_ams->humidity = 2; - } - else - { - curr_ams->humidity = 1; - } - } - } - - - if (it->contains("temp")) - { - std::string temp = (*it)["temp"].get(); - try - { - curr_ams->current_temperature = string_to_float(temp); - } - catch (...) - { - curr_ams->current_temperature = INVALID_AMS_TEMPERATURE; - } - } - - if (it->contains("tray")) { - std::set tray_id_set; - for (auto it = curr_ams->trayList.begin(); it != curr_ams->trayList.end(); it++) { - tray_id_set.insert(it->first); - } - for (auto tray_it = (*it)["tray"].begin(); tray_it != (*it)["tray"].end(); tray_it++) { - if (!tray_it->contains("id")) continue; - std::string tray_id = (*tray_it)["id"].get(); - tray_id_set.erase(tray_id); - // compare tray_list - AmsTray* curr_tray = nullptr; - auto tray_iter = curr_ams->trayList.find(tray_id); - if (tray_iter == curr_ams->trayList.end()) { - AmsTray* new_tray = new AmsTray(tray_id); - curr_ams->trayList.insert(std::make_pair(tray_id, new_tray)); - curr_tray = new_tray; - } - else { - curr_tray = tray_iter->second; - } - if (!curr_tray) continue; - - if (curr_tray->hold_count > 0) { - curr_tray->hold_count--; - continue; - } - - curr_tray->id = (*tray_it)["id"].get(); - if (tray_it->contains("tag_uid")) - curr_tray->tag_uid = (*tray_it)["tag_uid"].get(); - else - curr_tray->tag_uid = "0"; - if (tray_it->contains("tray_info_idx") && tray_it->contains("tray_type")) { - curr_tray->setting_id = (*tray_it)["tray_info_idx"].get(); - //std::string type = (*tray_it)["tray_type"].get(); - std::string type = setting_id_to_type(curr_tray->setting_id, (*tray_it)["tray_type"].get()); - if (curr_tray->setting_id == "GFS00") { - curr_tray->type = "PLA-S"; - } - else if (curr_tray->setting_id == "GFS01") { - curr_tray->type = "PA-S"; - } else { - curr_tray->type = type; - } - } else { - curr_tray->setting_id = ""; - curr_tray->type = ""; - } - if (tray_it->contains("tray_sub_brands")) - curr_tray->sub_brands = (*tray_it)["tray_sub_brands"].get(); - else - curr_tray->sub_brands = ""; - if (tray_it->contains("tray_weight")) - curr_tray->weight = (*tray_it)["tray_weight"].get(); - else - curr_tray->weight = ""; - if (tray_it->contains("tray_diameter")) - curr_tray->diameter = (*tray_it)["tray_diameter"].get(); - else - curr_tray->diameter = ""; - if (tray_it->contains("tray_temp")) - curr_tray->temp = (*tray_it)["tray_temp"].get(); - else - curr_tray->temp = ""; - if (tray_it->contains("tray_time")) - curr_tray->time = (*tray_it)["tray_time"].get(); - else - curr_tray->time = ""; - if (tray_it->contains("bed_temp_type")) - curr_tray->bed_temp_type = (*tray_it)["bed_temp_type"].get(); - else - curr_tray->bed_temp_type = ""; - if (tray_it->contains("bed_temp")) - curr_tray->bed_temp = (*tray_it)["bed_temp"].get(); - else - curr_tray->bed_temp = ""; - if (tray_it->contains("tray_color")) { - auto color = (*tray_it)["tray_color"].get(); - curr_tray->update_color_from_str(color); - } else { - curr_tray->color = ""; - } - if (tray_it->contains("nozzle_temp_max")) { - curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get(); - } - else - curr_tray->nozzle_temp_max = ""; - if (tray_it->contains("nozzle_temp_min")) - curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get(); - else - curr_tray->nozzle_temp_min = ""; - if (tray_it->contains("xcam_info")) - curr_tray->xcam_info = (*tray_it)["xcam_info"].get(); - else - curr_tray->xcam_info = ""; - if (tray_it->contains("tray_uuid")) - curr_tray->uuid = (*tray_it)["tray_uuid"].get(); - else - curr_tray->uuid = "0"; - - if (tray_it->contains("ctype")) - curr_tray->ctype = (*tray_it)["ctype"].get(); - else - curr_tray->ctype = 0; - curr_tray->cols.clear(); - if (tray_it->contains("cols")) { - if ((*tray_it)["cols"].is_array()) { - for (auto it = (*tray_it)["cols"].begin(); it != (*tray_it)["cols"].end(); it++) { - curr_tray->cols.push_back(it.value().get()); - } - } - } - - if (tray_it->contains("remain")) { - curr_tray->remain = (*tray_it)["remain"].get(); - } else { - curr_tray->remain = -1; - } - int ams_id_int = 0; - int tray_id_int = 0; - try { - if (!ams_id.empty() && !curr_tray->id.empty()) { - ams_id_int = atoi(ams_id.c_str()); - tray_id_int = atoi(curr_tray->id.c_str()); - - if (type_id < 4) { - curr_tray->is_exists = (tray_exist_bits & (1 << (ams_id_int * 4 + tray_id_int))) != 0 ? true : false; - } - else { - curr_tray->is_exists = get_flag_bits(tray_exist_bits, 16 + (ams_id_int - 128)); - } - - } - } - catch (...) { - } - if (tray_it->contains("setting_id")) { - curr_tray->filament_setting_id = (*tray_it)["setting_id"].get(); - } - auto curr_time = std::chrono::system_clock::now(); - auto diff = std::chrono::duration_cast(curr_time - extrusion_cali_set_hold_start); - if (diff.count() > HOLD_TIMEOUT || diff.count() < 0 - || ams_id_int != (extrusion_cali_set_tray_id / 4) - || tray_id_int != (extrusion_cali_set_tray_id % 4)) { - if (tray_it->contains("k")) { - curr_tray->k = (*tray_it)["k"].get(); - } - if (tray_it->contains("n")) { - curr_tray->n = (*tray_it)["n"].get(); - } - } - - if (tray_it->contains("cali_idx")) { - curr_tray->cali_idx = (*tray_it)["cali_idx"].get(); - } - } - // remove not in trayList - for (auto tray_it = tray_id_set.begin(); tray_it != tray_id_set.end(); tray_it++) { - std::string tray_id = *tray_it; - auto tray = curr_ams->trayList.find(tray_id); - if (tray != curr_ams->trayList.end()) { - curr_ams->trayList.erase(tray_id); - BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id << ", tray_id=" << tray_id; - } - } - } - } - // remove not in amsList - for (auto it = ams_id_set.begin(); it != ams_id_set.end(); it++) { - std::string ams_id = *it; - auto ams = amsList.find(ams_id); - if (ams != amsList.end()) { - BOOST_LOG_TRIVIAL(trace) << "parse_json: remove ams_id=" << ams_id; - amsList.erase(ams_id); - } - } - } - } + DevFilaSystemParser::ParseV1_0(jj, this, m_fila_system, key_field_only); } /* vitrual tray*/ @@ -5113,22 +3704,18 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (vslot.id == std::to_string(VIRTUAL_TRAY_MAIN_ID)) { auto it = std::next(vt_slot.begin(), 0); if (it != vt_slot.end()) { - is_ams_need_update |= vt_slot[0] != vslot; vt_slot[0] = vslot; } else { - is_ams_need_update = true; vt_slot.push_back(vslot); } } else if (vslot.id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { auto it = std::next(vt_slot.begin(), 1); if (it != vt_slot.end()) { - is_ams_need_update |= vt_slot[1] != vslot; vt_slot[1] = vslot; } else { - is_ams_need_update = true; vt_slot.push_back(vslot); } } @@ -5142,17 +3729,14 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ auto it = std::next(vt_slot.begin(), 0); if (it != vt_slot.end()) { - is_ams_need_update |= vt_slot[0] != main_slot; vt_slot[0] = main_slot; } else { - is_ams_need_update = true; vt_slot.push_back(main_slot); } } else { ams_support_virtual_tray = false; - is_support_extrusion_cali = false; } } catch (...) { @@ -5168,7 +3752,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } else if (jj["command"].get() == "gcode_line") { if (m_agent && is_studio_cmd(sequence_id)) { json t; - t["dev_id"] = this->dev_id; + t["dev_id"] = this->get_dev_id(); t["signal"] = this->wifi_signal; t["gcode"] = j.dump(); m_agent->track_event("ack_cmd_gcode_line", t.dump()); @@ -5176,14 +3760,14 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } else if (jj["command"].get() == "project_prepare") { if (m_agent) { if (jj.contains("job_id")) { - this->job_id_ = JsonValParser::get_longlong_val(jj["job_id"]); + this->job_id_ = DevJsonValParser::get_longlong_val(jj["job_id"]); } } } else if (jj["command"].get() == "project_file") { if (m_agent) { json t; - t["dev_id"] = this->dev_id; + t["dev_id"] = this->get_dev_id(); t["signal"] = this->wifi_signal; m_agent->track_event("ack_cmd_project_file", t.dump()); } @@ -5196,16 +3780,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } else if (jj["command"].get() == "ams_filament_setting" && !key_field_only) { - if (jj.contains("result") && jj.contains("reason")) { - if (jj["result"].get() == "fail") { - if (jj.contains("err_code")) { - auto err_code = jj["err_code"].get(); - print_error = err_code; - } - } - } - - // QDS trigger ams UI update ams_version = -1; @@ -5226,11 +3800,11 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ // delay update vt_slot[0].set_hold_count(); } else { - auto ams_it = amsList.find(std::to_string(ams_id)); - if (ams_it != amsList.end()) { + auto ams = m_fila_system->GetAmsById(std::to_string(ams_id)); + if (ams) { tray_id = jj["tray_id"].get(); - auto tray_it = ams_it->second->trayList.find(std::to_string(tray_id)); - if (tray_it != ams_it->second->trayList.end()) { + auto tray_it = ams->GetTrays().find(std::to_string(tray_id)); + if (tray_it != ams->GetTrays().end()) { BOOST_LOG_TRIVIAL(trace) << "ams_filament_setting, parse tray info"; tray_it->second->nozzle_temp_max = std::to_string(jj["nozzle_temp_max"].get()); tray_it->second->nozzle_temp_min = std::to_string(jj["nozzle_temp_min"].get()); @@ -5306,7 +3880,9 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj.contains("option")) { if (jj["option"].is_number()) { int option = jj["option"].get(); - _parse_print_option_ack(option); + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { + xcam_auto_recovery_step_loss = ((option >> (int)PRINT_OP_AUTO_RECOVERY) & 0x01) != 0; + } } } @@ -5347,14 +3923,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } else if (jj["command"].get() == "extrusion_cali_set") { - if (jj.contains("result") && jj.contains("reason")) { - if (jj["result"].get() == "fail") { - if (jj.contains("err_code")) { - auto err_code = jj["err_code"].get(); - print_error = err_code; - } - } - } int ams_id = -1; int tray_id = -1; int curr_tray_id = -1; @@ -5380,10 +3948,11 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj.contains("n_coef")) vt_slot[0].n = jj["n_coef"].get(); } else { - auto ams_item = this->amsList.find(std::to_string(ams_id)); - if (ams_item != this->amsList.end()) { - auto tray_item = ams_item->second->trayList.find(std::to_string(tray_id)); - if (tray_item != ams_item->second->trayList.end()) { + + auto ams_item = m_fila_system->GetAmsById(std::to_string(ams_id)); + if (ams_item) { + auto tray_item = ams_item->GetTrays().find(std::to_string(tray_id)); + if (tray_item != ams_item->GetTrays().end()) { if (jj.contains("k_value")) tray_item->second->k = jj["k_value"].get(); if (jj.contains("n_coef")) @@ -5395,15 +3964,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ extrusion_cali_set_hold_start = std::chrono::system_clock::now(); } else if (jj["command"].get() == "extrusion_cali_sel") { - if (jj.contains("result") && jj.contains("reason")) { - if (jj["result"].get() == "fail") { - if (jj.contains("err_code")) { - auto err_code = jj["err_code"].get(); - print_error = err_code; - } - } - } - int ams_id = -1; int slot_id = -1; int tray_id = -1; @@ -5436,25 +3996,23 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (ams_id == VIRTUAL_TRAY_MAIN_ID && vt_slot.size() > 0) { - vt_slot[MAIN_NOZZLE_ID].cali_idx = jj["cali_idx"].get(); - vt_slot[MAIN_NOZZLE_ID].set_hold_count(); + vt_slot[MAIN_EXTRUDER_ID].cali_idx = jj["cali_idx"].get(); + vt_slot[MAIN_EXTRUDER_ID].set_hold_count(); } else if (ams_id == VIRTUAL_TRAY_DEPUTY_ID && vt_slot.size() > 1) { - vt_slot[DEPUTY_NOZZLE_ID].cali_idx = jj["cali_idx"].get(); - vt_slot[DEPUTY_NOZZLE_ID].set_hold_count(); + vt_slot[DEPUTY_EXTRUDER_ID].cali_idx = jj["cali_idx"].get(); + vt_slot[DEPUTY_EXTRUDER_ID].set_hold_count(); } } else { - auto ams_item = this->amsList.find(std::to_string(ams_id)); - if (ams_item != this->amsList.end()) { - auto tray_item = ams_item->second->trayList.find(std::to_string(slot_id)); - if (tray_item != ams_item->second->trayList.end()) { - tray_item->second->cali_idx = jj["cali_idx"].get(); - tray_item->second->set_hold_count(); - } + auto tray_item = m_fila_system->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id)); + if (tray_item) + { + tray_item->cali_idx = jj["cali_idx"].get(); + tray_item->set_hold_count(); } } } @@ -5467,10 +4025,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ bool is_succeed = true; if (jj.contains("result") && jj.contains("reason")) { if (jj["result"].get() == "fail") { - if (jj.contains("err_code")) { - auto err_code = jj["err_code"].get(); - print_error = err_code; - } is_succeed = false; } } @@ -5529,8 +4083,6 @@ 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: "; } } else if (jj["command"].get() == "extrusion_cali_get_result") { @@ -5539,8 +4091,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (jj.contains("result") && jj.contains("reason")) { if (jj["result"].get() == "fail") { if (jj.contains("err_code")) { - auto err_code = jj["err_code"].get(); - print_error = err_code; is_succeed = false; } } @@ -5553,7 +4103,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ try { for (auto it = jj["filaments"].begin(); it != jj["filaments"].end(); it++) { PACalibResult pa_calib_result; - pa_calib_result.tray_id = (*it)["tray_id"].get(); pa_calib_result.filament_id = (*it)["filament_id"].get(); if ((*it).contains("setting_id")) { @@ -5606,6 +4155,11 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ pa_calib_result.confidence = 0; } + if (this->is_support_new_auto_cali_method) + pa_calib_result.tray_id = get_tray_id_by_ams_id_and_slot_id(pa_calib_result.ams_id, pa_calib_result.slot_id); + else + pa_calib_result.tray_id = (*it)["tray_id"].get(); + if (check_pa_result_validation(pa_calib_result)) pa_calib_results.push_back(pa_calib_result); else { @@ -5644,7 +4198,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } catch (...) {} } } - command_handle_response(jj); + m_fan->command_handle_response(jj); } } @@ -5689,10 +4243,26 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (j.contains("upgrade")) { if (j["upgrade"].contains("command")) { if (j["upgrade"]["command"].get() == "upgrade_confirm") { - this->upgrade_display_state = UpgradingInProgress; + this->upgrade_display_state = DevFirmwareUpgradingState::UpgradingInProgress; upgrade_display_hold_count = HOLD_COUNT_MAX; BOOST_LOG_TRIVIAL(info) << "ack of upgrade_confirm"; } + + bool check_studio_cmd = true; + if (j["upgrade"].contains("sequence_id")) { + try + { + std::string str_seq = j["upgrade"]["sequence_id"].get(); + check_studio_cmd = is_studio_cmd(stoi(str_seq)); + } + catch (...) { } + } + + if (check_studio_cmd && j["upgrade"].contains("err_code")) { + if (j["upgrade"]["err_code"].is_number()) { + add_command_error_code_dlg(j["upgrade"]["err_code"].get()); + } + } } } } @@ -5716,16 +4286,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ if (!key_field_only) { BOOST_LOG_TRIVIAL(trace) << "parse_json m_active_state =" << m_active_state; - //if (m_active_state == Active && !is_camera_busy_off()) { - // if (is_support_tunnel_mqtt && connection_type() != "lan") { - // m_active_state = UpdateToDate; - // m_agent->start_subscribe("tunnel"); - // } - //} else if (m_active_state == UpdateToDate && is_camera_busy_off()) { - // m_active_state = Active; - // m_agent->stop_subscribe("tunnel"); - //} - parse_state_changed_event(); } } @@ -5774,7 +4334,7 @@ int MachineObject::publish_gcode(std::string gcode_str) if (m_agent) { j["print"]["user_id"] = m_agent->get_user_id(); json t; - t["dev_id"] = this->dev_id; + t["dev_id"] = this->get_dev_id(); t["signal"] = this->wifi_signal; t["gcode"] = j.dump(); m_agent->track_event("cmd_gcode_line", t.dump()); @@ -5783,6 +4343,11 @@ int MachineObject::publish_gcode(std::string gcode_str) return publish_json(j); } +void MachineObject::update_device_cert_state(bool ready) +{ + device_cert_installed = ready; +} + QDTSubTask* MachineObject::get_subtask() { if (!subtask_) @@ -5845,7 +4410,7 @@ void MachineObject::update_model_task() res = m_agent->get_model_mall_rating_result(curr_instance_id, rating_result, http_code, http_error); request_model_result++; BOOST_LOG_TRIVIAL(info) << "request times: " << request_model_result << " http code: " << http_code; - auto rating_info = new RatingInfo(); + auto rating_info = new DevPrintTaskRatingInfo(); rating_info->http_code = http_code; if (0 == res && 200 == http_code) { try { @@ -6033,7 +4598,7 @@ void MachineObject::get_firmware_info() unsigned int http_code; std::string http_body; if (!m_agent) return; - result = m_agent->get_printer_firmware(dev_id, &http_code, &http_body); + result = m_agent->get_printer_firmware(get_dev_id(), &http_code, &http_body); if (result < 0) { // get upgrade list failed return; @@ -6043,7 +4608,7 @@ void MachineObject::get_firmware_info() if (j.contains("devices") && !j["devices"].is_null()) { firmware_list.clear(); for (json::iterator it = j["devices"].begin(); it != j["devices"].end(); it++) { - if ((*it)["dev_id"].get() == this->dev_id) { + if ((*it)["dev_id"].get() == this->get_dev_id()) { try { json firmware = (*it)["firmware"]; for (json::iterator firmware_it = firmware.begin(); firmware_it != firmware.end(); firmware_it++) { @@ -6111,112 +4676,10 @@ bool MachineObject::is_firmware_info_valid() return m_firmware_valid; } -std::string MachineObject::get_string_from_fantype(int type) + +DevAmsTray MachineObject::parse_vt_tray(json vtray) { - switch (type) { - case 1: - return "cooling_fan"; - case 2: - return "big_cooling_fan"; - case 3: - return "chamber_fan"; - default: - return ""; - } - return ""; -} - -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); - nt_try_local_tunnel = true; - } - - if (!nt_use_local_tunnel && nt_try_local_tunnel && nt_local_full_msg_count == full_msg_count_limit) { - std::vector dev_list{dev_id}; - Slic3r::GUI::wxGetApp().getAgent()->del_subscribe(dev_list); - nt_use_local_tunnel = true; - } -} - -void MachineObject::nt_restore_cloud_tunnel() -{ - if (is_connected()) { - disconnect(); - std::vector dev_list{dev_id}; - Slic3r::GUI::wxGetApp().getAgent()->add_subscribe(dev_list); - nt_use_local_tunnel = false; - } -} - -NozzleFlowType MachineObject::get_nozzle_flow_type(int extruder_id) const -{ - if (is_nozzle_flow_type_supported() && m_extder_data.extders.size() > extruder_id) - { - return m_extder_data.extders[extruder_id].current_nozzle_flow_type; - } - - return NozzleFlowType::NONE_FLOWTYPE; -} - -Extder MachineObject::get_current_extruder() const -{ - if (m_extder_data.extders.size() <= m_extder_data.current_extder_id) - { - BOOST_LOG_TRIVIAL(error) << "get_current_extruder() failed"; - return Extder(); - } - - return m_extder_data.extders[m_extder_data.current_extder_id]; -} - -void MachineObject::converse_to_duct(bool is_suppt_part_fun, bool is_suppt_aux_fun, bool is_suppt_cham_fun) -{ - m_air_duct_data.modes.clear(); - m_air_duct_data.parts.clear(); - m_air_duct_data.curren_mode = -1; //def mode - - - if (is_suppt_part_fun) { - AirParts part_fan; - part_fan.type = int(AirDuctType::AIR_FAN_TYPE); - part_fan.id = int(AIR_FUN::FAN_COOLING_0_AIRDOOR); - part_fan.func = int(AIR_FUN::FAN_COOLING_0_AIRDOOR); - part_fan.state = 0; - part_fan.range_start = 0; - part_fan.range_end = 100; - m_air_duct_data.parts.push_back(part_fan); - } - - if (is_suppt_aux_fun) { - AirParts aux_fan; - aux_fan.type = int(AirDuctType::AIR_FAN_TYPE); - aux_fan.id = int(AIR_FUN::FAN_REMOTE_COOLING_0_IDX); - aux_fan.func = int(AIR_FUN::FAN_REMOTE_COOLING_0_IDX); - aux_fan.state = 0; - aux_fan.range_start = 0; - aux_fan.range_end = 100; - m_air_duct_data.parts.push_back(aux_fan); - } - - if (is_suppt_aux_fun) { - AirParts chamber_fan; - chamber_fan.type = int(AirDuctType::AIR_FAN_TYPE); - chamber_fan.id = int(AIR_FUN::FAN_CHAMBER_0_IDX); - chamber_fan.func = int(AIR_FUN::FAN_CHAMBER_0_IDX); - chamber_fan.state = 0; - chamber_fan.range_start = 0; - chamber_fan.range_end = 100; - m_air_duct_data.parts.push_back(chamber_fan); - } -} - -AmsTray MachineObject::parse_vt_tray(json vtray) -{ - auto vt_tray = AmsTray(std::to_string(VIRTUAL_TRAY_MAIN_ID)); + auto vt_tray = DevAmsTray(std::to_string(VIRTUAL_TRAY_MAIN_ID)); if (vtray.contains("id")) vt_tray.id = vtray["id"].get(); @@ -6287,7 +4750,7 @@ AmsTray MachineObject::parse_vt_tray(json vtray) vt_tray.bed_temp = ""; if (vtray.contains("tray_color")) { auto color = vtray["tray_color"].get(); - vt_tray.update_color_from_str(color); + vt_tray.UpdateColorFromStr(color); } else { vt_tray.color = ""; @@ -6344,11 +4807,8 @@ AmsTray MachineObject::parse_vt_tray(json vtray) bool MachineObject::contains_tray(const std::string &ams_id, const std::string &tray_id) const { if (ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) { - auto ams_iter = amsList.find(ams_id); - if (ams_iter != amsList.end()) { - auto tray_iter = ams_iter->second->trayList.find(tray_id); - if (tray_iter != ams_iter->second->trayList.end()) { return true;} - } + + return m_fila_system->GetAmsTray(ams_id, tray_id) != nullptr; } else { for (const auto& tray : vt_slot) { if (tray.id == ams_id) { return true; } @@ -6358,14 +4818,16 @@ bool MachineObject::contains_tray(const std::string &ams_id, const std::string & return false; } -AmsTray MachineObject::get_tray(const std::string &ams_id, const std::string &tray_id) const +DevAmsTray MachineObject::get_tray(const std::string &ams_id, const std::string &tray_id) const { + if (ams_id.empty() && tray_id.empty()) + { + return DevAmsTray(tray_id); + } + if (ams_id != VIRTUAL_AMS_MAIN_ID_STR && ams_id != VIRTUAL_AMS_DEPUTY_ID_STR) { - auto ams_iter = amsList.find(ams_id); - if (ams_iter != amsList.end()) { - auto tray_iter = ams_iter->second->trayList.find(tray_id); - if (tray_iter != ams_iter->second->trayList.end()) { return *tray_iter->second; } - } + auto tray = m_fila_system->GetAmsTray(ams_id, tray_id); + if (tray) { return *tray;}; } else { for (const auto &tray : vt_slot) { @@ -6374,7 +4836,7 @@ AmsTray MachineObject::get_tray(const std::string &ams_id, const std::string &tr } assert(0);/*use contains_tray() check first*/ - return AmsTray(tray_id); + return DevAmsTray(tray_id); } bool MachineObject::check_enable_np(const json& print) const @@ -6405,14 +4867,12 @@ void MachineObject::parse_new_info(json print) if(!cfg.empty()){ if (camera_resolution_hold_count > 0) camera_resolution_hold_count--; if (camera_timelapse_hold_count > 0) camera_timelapse_hold_count--; - //if (xcam_buildplate_marker_hold_count > 0) xcam_buildplate_marker_hold_count--;first_layer_inspector - if (nozzle_setting_hold_count > 0)nozzle_setting_hold_count--; if (time(nullptr) - ams_user_setting_start > HOLD_COUNT_MAX) { - ams_insert_flag = get_flag_bits(cfg, 0); - ams_power_on_flag = get_flag_bits(cfg, 1); + m_fila_system->GetAmsSystemSetting().SetDetectOnInsertEnabled(get_flag_bits(cfg, 0)); + m_fila_system->GetAmsSystemSetting().SetDetectOnPowerupEnabled(get_flag_bits(cfg, 1)); } upgrade_force_upgrade = get_flag_bits(cfg, 2); @@ -6441,8 +4901,7 @@ void MachineObject::parse_new_info(json print) } tutk_state = get_flag_bits(cfg, 6) == 1 ? "disable" : ""; - chamber_light = get_flag_bits(cfg, 7) == 1 ? LIGHT_EFFECT::LIGHT_EFFECT_ON : LIGHT_EFFECT::LIGHT_EFFECT_OFF; - printing_speed_lvl = (PrintingSpeedLevel)get_flag_bits(cfg, 8, 3); + m_lamp->SetChamberLight(get_flag_bits(cfg, 7) == 1 ? DevLamp::LIGHT_EFFECT_ON : DevLamp::LIGHT_EFFECT_OFF); //is_support_build_plate_marker_detect = get_flag_bits(cfg, 12); todo yangcong if (time(nullptr) - xcam_first_layer_hold_start > HOLD_TIME_3SEC) { @@ -6468,11 +4927,11 @@ void MachineObject::parse_new_info(json print) } if (time(nullptr) - ams_user_setting_start > HOLD_COUNT_MAX){ - ams_calibrate_remain_flag = get_flag_bits(cfg, 17); + m_fila_system->GetAmsSystemSetting().SetDetectRemainEnabled(get_flag_bits(cfg, 17)); } if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_3SEC){ - ams_auto_switch_filament_flag = get_flag_bits(cfg, 18); + m_fila_system->GetAmsSystemSetting().SetAutoRefillEnabled(get_flag_bits(cfg, 18)); } if (time(nullptr) - xcam__save_remote_print_file_to_storage_start_time > HOLD_TIME_3SEC){ @@ -6520,17 +4979,16 @@ void MachineObject::parse_new_info(json print) is_support_nozzle_blob_detection = get_flag_bits(fun, 13); is_support_upgrade_kit = get_flag_bits(fun, 14); is_support_internal_timelapse = get_flag_bits(fun, 28); - is_support_command_homing = get_flag_bits(fun, 32); + m_support_mqtt_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_new_auto_cali_method = get_flag_bits(fun, 40); 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); + m_fan->SetSupportCoolingFilter(get_flag_bits(fun, 46)); is_support_ext_change_assist = get_flag_bits(fun, 48); is_support_partskip = get_flag_bits(fun, 49); } @@ -6541,7 +4999,8 @@ void MachineObject::parse_new_info(json print) BOOST_LOG_TRIVIAL(info) << "new print data aux = " << aux; if (!aux.empty()) { - sdcard_state = MachineObject::SdcardState(get_flag_bits(aux, 12, 2)); + m_storage->set_sdcard_state(get_flag_bits(aux, 12, 2)); + //sdcard_state = MachineObject::SdcardState(get_flag_bits(aux, 12, 2)); } /*stat*/ @@ -6551,261 +5010,38 @@ void MachineObject::parse_new_info(json print) if (!stat.empty()) { camera_recording = get_flag_bits(stat, 7); - m_lamp_close_recheck = (get_flag_bits(stat, 36) == 1); + m_lamp->SetLampCloseRecheck((get_flag_bits(stat, 36) == 1)); } /*device*/ if (print.contains("device")) { json const& device = print["device"]; + //new fan data - if (device.contains("airduct")) { - m_air_duct_data.curren_mode = -1; - m_air_duct_data.modes.clear(); - m_air_duct_data.parts.clear(); - - 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>(); - - for (int i = 0; i < list.size(); ++i) { - // only show 2 mode for o - if (is_series_o() && i >= 2) { break; } - - json mode_json = list[i]; - AirMode mode; - if (mode_json.contains("modeId")) - mode.id = mode_json["modeId"].get(); - if (mode_json.contains("ctrl")) { - for (auto it_mode_ctrl = mode_json["ctrl"].begin(); it_mode_ctrl != mode_json["ctrl"].end(); it_mode_ctrl++) { - mode.ctrl.push_back((*it_mode_ctrl).get() >> 4); - } - } - - if (mode_json.contains("off")) { - for (auto it_mode_off = mode_json["off"].begin(); it_mode_off != mode_json["off"].end(); *it_mode_off++) { - mode.off.push_back((*it_mode_off).get() >> 4); - } - } - - if (AIR_DUCT(mode.id) == AIR_DUCT::AIR_DUCT_EXHAUST) { continue; } /*STUDIO-12796*/ - m_air_duct_data.modes[mode.id] = mode; - } - } - - if (airduct.contains("parts") && airduct["parts"].is_array()) { - for (auto it_part = airduct["parts"].begin(); it_part != airduct["parts"].end(); it_part++) { - int state = (*it_part)["state"].get(); - int range = (*it_part)["range"].get(); - - AirParts part; - part.type = get_flag_bits((*it_part)["id"].get(), 0, 4); - part.id = get_flag_bits((*it_part)["id"].get(), 4, 9); - part.func = (*it_part)["func"].get(); - part.state = get_flag_bits(state, 0, 8); - part.range_start = get_flag_bits(range, 0, 16); - part.range_end = get_flag_bits(range, 16, 16); - - m_air_duct_data.parts.push_back(part); - } - } - } + m_fan->ParseV3_0(device); if (device.contains("type")) { m_device_mode = (DeviceMode)device["type"].get();// FDM:1<<0 Laser:1<< Cut:1<<2 } - if (device.contains("bed_temp")) { - bed_temp = get_flag_bits(device["bed_temp"].get(), 0, 16); - bed_temp_target = get_flag_bits(device["bed_temp"].get(), 16, 16); - } + DevBed::ParseV2_0(device,m_bed); - if (device.contains("nozzle")) { - json const &nozzle = device["nozzle"]; - - m_nozzle_data = NozzleData(); - - m_nozzle_data.extder_exist = get_flag_bits(nozzle["exist"].get(), 0, 16); - m_nozzle_data.cut_exist = get_flag_bits(nozzle["exist"].get(), 16, 16); - m_nozzle_data.state = get_flag_bits(nozzle["state"].get(), 0, 4); - - for (auto it = nozzle["info"].begin(); it != nozzle["info"].end(); it++) { - Nozzle nozzle_obj; - auto njon = it.value(); - std::string type = njon["type"].get(); - nozzle_obj.id = njon["id"].get(); - - if (type.length() >= 4) { - if (type.substr(0, 1) == std::string("H")) { - nozzle_obj.tool_type = NozzleToolType::H_TOOL; - } - else if (type.substr(0, 1) == std::string("C")) { - nozzle_obj.tool_type = NozzleToolType::C_TOOL; - } - - if (type.substr(1, 1) == std::string("S")) { - nozzle_obj.nozzle_flow = NozzleFlowType::S_FLOW; - } else if (type.substr(1, 1) == std::string("H")) { - nozzle_obj.nozzle_flow = NozzleFlowType::H_FLOW; - } else if (type.substr(1, 1) == std::string("A")) { - nozzle_obj.nozzle_flow = NozzleFlowType::S_FLOW; - } else if (type.substr(1, 1) == std::string("X")) { - nozzle_obj.nozzle_flow = NozzleFlowType::S_FLOW; - } - - if (type.substr(2, 2) == std::string("00")) { - nozzle_obj.nozzle_type = NozzleType::ntStainlessSteel; - } else if (type.substr(2, 2) == std::string("01")) { - nozzle_obj.nozzle_type = NozzleType::ntHardenedSteel; - } else if (type.substr(2, 2) == std::string("05")) { - nozzle_obj.nozzle_type = NozzleType::ntTungstenCarbide; - } - } else { - nozzle_obj.tool_type = NozzleToolType::NONE_TOOLTYPE; - nozzle_obj.nozzle_flow = NozzleFlowType::NONE_FLOWTYPE; - nozzle_obj.nozzle_type = NozzleType::ntUndefine; - } - - nozzle_obj.diameter = njon["diameter"].get(); - nozzle_obj.max_temp = njon["tm"].get(); - nozzle_obj.wear = njon["wear"].get(); - if (nozzle_obj.diameter == 0.0f) {nozzle_obj.diameter = 0.4f;} - m_nozzle_data.nozzles.push_back(nozzle_obj); - } - } - - if (device.contains("extruder")) { - json const& extruder = device["extruder"]; - - auto extder_data = ExtderData(); - extder_data.total_extder_count = get_flag_bits(extruder["state"].get(), 0, 4); - - - extder_data.current_extder_id = get_flag_bits(extruder["state"].get(), 4, 4); - extder_data.target_extder_id = get_flag_bits(extruder["state"].get(), 8, 4); - extder_data.switch_extder_state = (ExtruderSwitchState) get_flag_bits(extruder["state"].get(), 12, 3); - - if (m_extder_data.current_extder_id != extder_data.current_extder_id) - { - flag_update_nozzle = true; - targ_nozzle_id_from_pc = INVALID_NOZZLE_ID; - } - else if (extder_data.switch_extder_state == ES_SWITCHING_FAILED) - { - flag_update_nozzle = true; - targ_nozzle_id_from_pc = INVALID_NOZZLE_ID; - } - - extder_data.current_loading_extder_id = get_flag_bits(extruder["state"].get(), 15, 4); - extder_data.current_busy_for_loading = get_flag_bits(extruder["state"].get(), 19); - - for (auto it = extruder["info"].begin(); it != extruder["info"].end(); it++) { - - Extder extder_obj; - auto njon = it.value(); - - extder_obj.id = njon["id"].get(); - - extder_obj.filam_bak.clear(); - is_support_show_filament_backup = njon.contains("filam_bak"); - if (is_support_show_filament_backup) - { - const json& filam_bak_items = njon["filam_bak"]; - for (const auto& filam_bak_item : filam_bak_items) - { - const auto& filam_bak_val = filam_bak_item.get(); - extder_obj.filam_bak.emplace_back(filam_bak_val); - } - } - - extder_obj.enable_change_nozzle= get_flag_bits(njon["info"].get(), 0); - extder_obj.ext_has_filament = get_flag_bits(njon["info"].get(), 1); - extder_obj.buffer_has_filament = get_flag_bits(njon["info"].get(), 2); - extder_obj.nozzle_exist = get_flag_bits(njon["info"].get(), 3); - extder_obj.temp = get_flag_bits(njon["temp"].get(), 0, 16); - extder_obj.target_temp = get_flag_bits(njon["temp"].get(), 16, 16); - - AmsSlot spre; - spre.slot_id = std::to_string(get_flag_bits(njon["spre"].get(), 0, 8)); - spre.ams_id = std::to_string(get_flag_bits(njon["spre"].get(), 8, 8)); - - AmsSlot snow; - snow.slot_id = std::to_string(get_flag_bits(njon["snow"].get(), 0, 8)); - snow.ams_id = std::to_string(get_flag_bits(njon["snow"].get(), 8, 8)); - - AmsSlot star; - star.slot_id = std::to_string(get_flag_bits(njon["star"].get(), 0, 8)); - star.ams_id = std::to_string(get_flag_bits(njon["star"].get(), 8, 8)); - - extder_obj.nozzle_id = njon["hnow"].get(); - extder_obj.target_nozzle_id = njon["htar"].get(); - - extder_obj.spre = spre; - extder_obj.snow = snow; - extder_obj.star = star; - extder_obj.ams_stat = get_flag_bits(njon["stat"].get(), 0, 16); - extder_obj.rfid_stat = get_flag_bits(njon["stat"].get(), 16, 16); - - //current nozzle info - if (extder_obj.nozzle_id == 0xff) { - extder_obj.current_nozzle_type = NozzleType::ntUndefine; - extder_obj.current_nozzle_diameter = 0.4f; - extder_obj.current_nozzle_flow_type = NozzleFlowType::NONE_FLOWTYPE; - } else { - for (auto i = 0; i < m_nozzle_data.nozzles.size(); i++) { - if (m_nozzle_data.nozzles[i].id == extder_obj.nozzle_id) { - extder_obj.current_nozzle_type = m_nozzle_data.nozzles[i].nozzle_type; - extder_obj.current_nozzle_diameter = m_nozzle_data.nozzles[i].diameter; - extder_obj.current_nozzle_flow_type = m_nozzle_data.nozzles[i].nozzle_flow; - } - } - } - extder_data.extders.push_back(extder_obj); - } - - if (extder_data.extders.size() <= 0) { - // def data - extder_data.current_extder_id = 0; - extder_data.target_extder_id = 0; - extder_data.total_extder_count = 1; - Extder nozzle; - extder_data.extders.push_back(nozzle); - } - - m_extder_data = extder_data; - } + if (device.contains("nozzle")) { DevNozzleSystemParser::ParseV2_0(device["nozzle"], m_nozzle_system); } + if (device.contains("extruder")) { ExtderSystemParser::ParseV2_0(device["extruder"], m_extder_system);} if (device.contains("ctc")) { json const& ctc = device["ctc"]; int state = get_flag_bits(ctc["state"].get(), 0, 4); - if (ctc.contains("info")) { json const &info = ctc["info"]; chamber_temp = get_flag_bits(info["temp"].get(), 0, 16); chamber_temp_target = get_flag_bits(info["temp"].get(), 16, 16); } - - } } } -bool MachineObject::is_nozzle_data_invalid() -{ - for (const auto &ext : m_extder_data.extders) - { - if (ext.current_nozzle_type == NozzleType::ntUndefine || - ext.current_nozzle_diameter <= 0.0f || - ext.current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { - return true; - } - } - - return false; -} - int MachineObject::get_flag_bits(std::string str, int start, int count) const { try { @@ -6898,7 +5134,7 @@ void MachineObject::update_filament_list() } } - for (auto it = m_filament_list.begin(); it != m_filament_list.end(); it++) { m_checked_filament.erase(it->first); } + for (auto it = m_filament_list.begin(); it != m_filament_list.end(); it++) { m_checked_filament.insert(it->first); } m_filament_list = filament_list; } @@ -6909,10 +5145,10 @@ void MachineObject::update_printer_preset_name() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "start update preset_name"; PresetBundle * preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle; if (!preset_bundle) return; - auto printer_model = MachineObject::get_preset_printer_model_name(this->printer_type); + auto printer_model = DevPrinterConfigUtil::get_printer_display_name(this->printer_type); std::set diameter_set; - for (auto &nozzle : m_extder_data.extders) { - float diameter = nozzle.current_nozzle_diameter; + for (auto &nozzle : m_extder_system->m_extders) { + float diameter = nozzle.GetNozzleDiameter(); std::ostringstream stream; stream << std::fixed << std::setprecision(1) << diameter; std::string nozzle_diameter_str = stream.str(); @@ -6944,16 +5180,16 @@ void MachineObject::update_printer_preset_name() void MachineObject::check_ams_filament_valid() { PresetBundle * preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle; - auto printer_model = MachineObject::get_preset_printer_model_name(this->printer_type); + auto printer_model = DevPrinterConfigUtil::get_printer_display_name(this->printer_type); std::map> need_checked_filament_id; - for (auto &ams_pair : amsList) { + for (auto &ams_pair : m_fila_system->GetAmsList()) { auto ams_id = ams_pair.first; auto &ams = ams_pair.second; std::ostringstream stream; - if (ams->nozzle < 0 || ams->nozzle >= m_extder_data.extders.size()) { + if (ams->GetExtruderId() < 0 || ams->GetExtruderId() >= m_extder_system->GetTotalExtderCount()) { return; } - stream << std::fixed << std::setprecision(1) << m_extder_data.extders[ams->nozzle].current_nozzle_diameter; + stream << std::fixed << std::setprecision(1) << m_extder_system->GetNozzleDiameter(ams->GetExtruderId()); std::string nozzle_diameter_str = stream.str(); assert(nozzle_diameter_str.size() == 3); if (m_nozzle_filament_data.find(nozzle_diameter_str) == m_nozzle_filament_data.end()) { @@ -6963,16 +5199,16 @@ void MachineObject::check_ams_filament_valid() auto &data = m_nozzle_filament_data[nozzle_diameter_str]; auto &filament_list = data.filament_list; auto &checked_filament = data.checked_filament; - for (const auto &[slot_id, curr_tray] : ams->trayList) { + for (const auto &[slot_id, curr_tray] : ams->GetTrays()) { 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()) { + if (checked_filament.find(curr_tray->setting_id) != checked_filament.end()) { need_checked_filament_id[nozzle_diameter_str].insert(curr_tray->setting_id); wxColour color = *wxWHITE; char col_buf[10]; sprintf(col_buf, "%02X%02X%02XFF", (int) color.Red(), (int) color.Green(), (int) color.Blue()); try { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " box settings_id is not exist in filament_list and reset, ams_id: " << ams_id << " tray_id" + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " ams settings_id is not exist in filament_list and reset, ams_id: " << ams_id << " tray_id" << slot_id << "filament_id: " << curr_tray->setting_id; command_ams_filament_settings(std::stoi(ams_id), std::stoi(slot_id), "", "", std::string(col_buf), "", 0, 0); @@ -6983,7 +5219,7 @@ void MachineObject::check_ams_filament_valid() } } if (curr_tray->setting_id.size() == 8 && curr_tray->setting_id[0] == 'P' && curr_tray->nozzle_temp_min != "" && curr_tray->nozzle_temp_max != "") { - if (checked_filament.find(curr_tray->setting_id) == checked_filament.end()) { + if (checked_filament.find(curr_tray->setting_id) != checked_filament.end()) { need_checked_filament_id[nozzle_diameter_str].insert(curr_tray->setting_id); try { std::string preset_setting_id; @@ -6992,7 +5228,7 @@ void MachineObject::check_ams_filament_valid() curr_tray->nozzle_temp_min, curr_tray->nozzle_temp_max, preset_setting_id); if (!is_equation) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " box filament is not match min max temp and reset, ams_id: " << ams_id << " tray_id" + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " ams filament is not match min max temp and reset, ams_id: " << ams_id << " tray_id" << slot_id << "filament_id: " << curr_tray->setting_id; @@ -7011,11 +5247,11 @@ void MachineObject::check_ams_filament_valid() for (auto vt_tray : vt_slot) { int vt_id = std::stoi(vt_tray.id); int index = 255 - vt_id; - if (index >= m_extder_data.total_extder_count) { - BOOST_LOG_TRIVIAL(error) << " vt_tray id map for nozzle id is not exist, index is: " << index << " nozzle count" << m_extder_data.total_extder_count; + if (index >= m_extder_system->GetTotalExtderCount()) { + BOOST_LOG_TRIVIAL(error) << " vt_tray id map for nozzle id is not exist, index is: " << index << " nozzle count" << m_extder_system->GetTotalExtderCount(); continue; } - auto diameter = m_extder_data.extders[index].current_nozzle_diameter; + auto diameter = m_extder_system->GetNozzleDiameter(index); std::ostringstream stream; stream << std::fixed << std::setprecision(1) << diameter; std::string nozzle_diameter_str = stream.str(); @@ -7026,7 +5262,7 @@ void MachineObject::check_ams_filament_valid() auto &checked_filament = data.checked_filament; auto &filament_list = data.filament_list; if (vt_tray.setting_id.size() == 8 && vt_tray.setting_id[0] == 'P' && filament_list.find(vt_tray.setting_id) == filament_list.end()) { - if (checked_filament.find(vt_tray.setting_id) == checked_filament.end()) { + if (checked_filament.find(vt_tray.setting_id) != checked_filament.end()) { need_checked_filament_id[nozzle_diameter_str].insert(vt_tray.setting_id); wxColour color = *wxWHITE; char col_buf[10]; @@ -7041,15 +5277,15 @@ void MachineObject::check_ams_filament_valid() } } if (vt_tray.setting_id.size() == 8 && vt_tray.setting_id[0] == 'P' && vt_tray.nozzle_temp_min != "" && vt_tray.nozzle_temp_max != "") { - if (checked_filament.find(vt_tray.setting_id) == checked_filament.end()) { + if (checked_filament.find(vt_tray.setting_id) != checked_filament.end()) { need_checked_filament_id[nozzle_diameter_str].insert(vt_tray.setting_id); try { std::string preset_setting_id; PresetBundle * preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle; std::ostringstream stream; - stream << std::fixed << std::setprecision(1) << m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_diameter; + stream << std::fixed << std::setprecision(1) << m_extder_system->GetNozzleDiameter(MAIN_EXTRUDER_ID); std::string nozzle_diameter_str = stream.str(); - bool is_equation = preset_bundle->check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray(MachineObject::get_preset_printer_model_name( + bool is_equation = preset_bundle->check_filament_temp_equation_by_printer_type_and_nozzle_for_mas_tray(DevPrinterConfigUtil::get_printer_display_name( this->printer_type), nozzle_diameter_str, vt_tray.setting_id, vt_tray.tag_uid, vt_tray.nozzle_temp_min, @@ -7072,28 +5308,11 @@ void MachineObject::check_ams_filament_valid() auto &diameter = diameter_pair.first; auto &data = diameter_pair.second; for (auto &filament_id : need_checked_filament_id[diameter]) { - data.checked_filament.insert(filament_id); + data.checked_filament.erase(filament_id); } } } -int MachineObject::command_handle_response(const json &response) -{ - if (!response.contains("sequence_id")) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ", error reponse."; - return -1; - } - - std::string reply = response["sequence_id"].get(); - auto it = m_callback_list.find(reply); - if (it != m_callback_list.end()) { - if (it->second) - it->second(response); - m_callback_list.erase(it); - } - - return 0; -} void MachineObject::command_set_door_open_check(DoorOpenCheckState state) { @@ -7138,7 +5357,7 @@ 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"); + const json& link_map = DevPrinterConfigUtil::get_json_from_config(printer_type, "print", "nozzle_replace_wiki"); if (link_map.contains(lan_code.ToStdString())) { return link_map[lan_code.ToStdString()].get(); } @@ -7150,1179 +5369,75 @@ wxString MachineObject::get_nozzle_replace_url() const return "https://wiki.qidi3d.com/"; } -bool DeviceManager::EnableMultiMachine = false; -bool DeviceManager::key_field_only = false; - -std::vector nozzle_diameter_list{ 0.2f,0.4f,0.6f,0.8f }; -std::vector nozzle_type_list {"hardened_steel", "stainless_steel", "tungsten_carbide"}; - -DeviceManager::DeviceManager(NetworkAgent* agent) +std::string MachineObject::get_error_code_str(int error_code) { - m_agent = agent; - m_refresher = new DeviceManagerRefresher(this); + if (error_code < 0) { return std::string();} + + char buf[32]; + ::sprintf(buf, "%08X", error_code); + std::string print_error_str = std::string(buf); + if (print_error_str.size() > 4) { print_error_str.insert(4, "-"); } + return print_error_str; } -DeviceManager::~DeviceManager() +void MachineObject::add_command_error_code_dlg(int command_err) { - delete m_refresher; - - for (auto it = localMachineList.begin(); it != localMachineList.end(); it++) { - if (it->second) { - delete it->second; - it->second = nullptr; - } - } - localMachineList.clear(); - - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (it->second) { - delete it->second; - it->second = nullptr; - } - } - userMachineList.clear(); -} - - -float DeviceManager::nozzle_diameter_conver(int diame) -{ - if (diame < nozzle_diameter_list.size() && diame >= 0) { - return nozzle_diameter_list[diame]; - } - return 0.4f; -} - -int DeviceManager::nozzle_diameter_conver(float diame) -{ - int index = -1; - for (int i = 0; i < nozzle_diameter_list.size(); i++) { - if (nozzle_diameter_list[i] == diame) { - index = i; - } - } - return index; -} - -std::string DeviceManager::nozzle_type_conver(int type) -{ - if (type < nozzle_type_list.size() && type >= 0) { - return nozzle_type_list[type]; - } - return ""; -} - -int DeviceManager::nozzle_type_conver(std::string& type) -{ - int index = -1; - for (int i = 0; i < nozzle_type_list.size(); i++) { - if (nozzle_type_list[i] == type) { - index = i; - } - } - return index; -} - -void DeviceManager::set_agent(NetworkAgent* agent) -{ - m_agent = agent; -} - -void DeviceManager::start_refresher() { m_refresher->Start(); } -void DeviceManager::stop_refresher() { m_refresher->Stop(); } -void DeviceManager::keep_alive() -{ - MachineObject* obj = this->get_selected_machine(); - if (obj) { - if (obj->keep_alive_count == 0) { - obj->last_keep_alive = std::chrono::system_clock::now(); - } - obj->keep_alive_count++; - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - auto internal = std::chrono::duration_cast(start - obj->last_keep_alive); - if (internal.count() > TIMEOUT_FOR_KEEPALIVE && (internal.count() < 1000 * 60 * 60 * 300) ) { - BOOST_LOG_TRIVIAL(info) << "keep alive = " << internal.count() << ", count = " << obj->keep_alive_count; - obj->command_request_push_all(); - obj->last_keep_alive = start; - } - else if(obj->m_push_count == 0){ - BOOST_LOG_TRIVIAL(info) << "keep alive = " << internal.count() << ", push_count = 0, count = " << obj->keep_alive_count; - obj->command_request_push_all(); - obj->last_keep_alive = start; - } - } -} - -void DeviceManager::check_pushing() -{ - keep_alive(); - MachineObject* obj = this->get_selected_machine(); - - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - auto internal = std::chrono::duration_cast(start - obj->last_update_time); - - if (obj && !obj->is_support_mqtt_alive) { - if (internal.count() > TIMEOUT_FOR_STRAT && internal.count() < 1000 * 60 * 60 * 300) { - BOOST_LOG_TRIVIAL(info) << "command_pushing: diff = " << internal.count(); - obj->command_pushing("start"); - } - } - - /*check local tunnel state*/ - if (obj && obj->nt_use_local_tunnel && internal.count() > PUSHINFO_TIMEOUT) { - obj->nt_restore_cloud_tunnel(); - BOOST_LOG_TRIVIAL(info) << "Unable to receive more data in LAN tunnel"; - } -} - -void DeviceManager::on_machine_alive(std::string json_str) -{ - try { - json j = json::parse(json_str); - std::string dev_name = j["dev_name"].get(); - std::string dev_id = j["dev_id"].get(); - std::string dev_ip = j["dev_ip"].get(); - std::string printer_type_str= j["dev_type"].get(); - std::string printer_signal = j["dev_signal"].get(); - std::string connect_type = j["connect_type"].get(); - std::string bind_state = j["bind_state"].get(); - - if (connect_type == "farm") { - connect_type ="lan"; - bind_state = "free"; - } - - std::string sec_link = ""; - std::string ssdp_version = ""; - if (j.contains("sec_link")) { - sec_link = j["sec_link"].get(); - } - if (j.contains("ssdp_version")) { - ssdp_version = j["ssdp_version"].get(); - } - std::string connection_name = ""; - if (j.contains("connection_name")) { - connection_name = j["connection_name"].get(); - } - - MachineObject* obj; - - /* update userMachineList info */ - auto it = userMachineList.find(dev_id); - if (it != userMachineList.end()) { - if (it->second->dev_ip != dev_ip || - it->second->bind_state != bind_state || - it->second->bind_sec_link != sec_link || - it->second->dev_connection_type != connect_type || - it->second->bind_ssdp_version != ssdp_version) - { - if (it->second->bind_state != bind_state) { - OnMachineBindStateChanged(it->second, bind_state); - } - - it->second->dev_ip = dev_ip; - it->second->bind_state = bind_state; - it->second->bind_sec_link = sec_link; - it->second->dev_connection_type = connect_type; - it->second->bind_ssdp_version = ssdp_version; - 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; - } - } - - /* update localMachineList */ - it = localMachineList.find(dev_id); - if (it != localMachineList.end()) { - // update properties - /* ip changed */ - obj = it->second; - - if (obj->dev_ip.compare(dev_ip) != 0) { - if ( connection_name.empty() ) { - 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 " << 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; - } - - } - /* ip changed reconnect mqtt */ - } - - if (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)) - { - 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)) + if (command_err > 0 && !Slic3r::GUI::wxGetApp().get_hms_query()->is_internal_error(this, command_err)) + { + GUI::wxGetApp().CallAfter([this, command_err, token = std::weak_ptr(m_token)] + { + if (token.expired()) { return;} + GUI::DeviceErrorDialog* device_error_dialog = new GUI::DeviceErrorDialog(this, (wxWindow*)GUI::wxGetApp().mainframe); + device_error_dialog->Bind(wxEVT_DESTROY, [this, token = std::weak_ptr(m_token)](auto& event) { - 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; - } + if (!token.expired()) { m_command_error_code_dlgs.erase((GUI::DeviceErrorDialog*)event.GetEventObject());} + event.Skip(); + }); - 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); - } - - // U0 firmware - if (obj->dev_connection_type.empty() && obj->bind_state.empty()) - obj->bind_state = "free"; - - obj->last_alive = Slic3r::Utils::get_current_time_utc(); - obj->m_is_online = true; - - /* if (!obj->dev_ip.empty()) { - Slic3r::GUI::wxGetApp().app_config->set_str("ip_address", obj->dev_id, obj->dev_ip); - Slic3r::GUI::wxGetApp().app_config->save(); - }*/ - } - else { - /* insert a new machine */ - obj = new MachineObject(m_agent, dev_name, dev_id, dev_ip); - obj->printer_type = MachineObject::parse_printer_type(printer_type_str); - obj->wifi_signal = printer_signal; - obj->dev_connection_type = connect_type; - obj->bind_state = bind_state; - obj->bind_sec_link = sec_link; - obj->dev_connection_name = connection_name; - obj->bind_ssdp_version = ssdp_version; - obj->m_is_online = true; - - //load access code - AppConfig* config = Slic3r::GUI::wxGetApp().app_config; - if (config) { - obj->set_access_code(Slic3r::GUI::wxGetApp().app_config->get("access_code", dev_id)); - obj->set_user_access_code(Slic3r::GUI::wxGetApp().app_config->get("user_access_code", dev_id)); - } - localMachineList.insert(std::make_pair(dev_id, obj)); - - /* if (!obj->dev_ip.empty()) { - 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) << __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 (...) { - ; - } + device_error_dialog->show_error_code(command_err); + m_command_error_code_dlgs.insert(device_error_dialog); + }); + }; } -MachineObject* DeviceManager::insert_local_device(std::string dev_name, std::string dev_id, std::string dev_ip, std::string connection_type, std::string bind_state, std::string version, std::string access_code) +bool MachineObject::is_multi_extruders() const { - 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 == "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; + return m_extder_system->GetTotalExtderCount() > 1; } -void DeviceManager::disconnect_all() +int MachineObject::get_extruder_id_by_ams_id(const std::string& ams_id) { - + return m_fila_system->GetExtruderIdByAmsId(ams_id); } -int DeviceManager::query_bind_status(std::string &msg) +Slic3r::DevPrintingSpeedLevel MachineObject::GetPrintingSpeedLevel() const { - if (!m_agent) { - msg = ""; - return -1; - } - - BOOST_LOG_TRIVIAL(trace) << "DeviceManager::query_bind_status"; - std::map::iterator it; - std::vector query_list; - for (it = localMachineList.begin(); it != localMachineList.end(); it++) { - query_list.push_back(it->first); - } - - unsigned int http_code; - std::string http_body; - int result = m_agent->query_bind_status(query_list, &http_code, &http_body); - - if (result < 0) { - msg = (boost::format("code=%1%,body=%2") % http_code % http_body).str(); - } else { - msg = ""; - try { - json j = json::parse(http_body); - if (j.contains("bind_list")) { - - for (auto& item : j["bind_list"]) { - auto it = localMachineList.find(item["dev_id"].get()); - if (it != localMachineList.end()) { - if (!item["user_id"].is_null()) - it->second->bind_user_id = item["user_id"].get(); - if (!item["user_name"].is_null()) - it->second->bind_user_name = item["user_name"].get(); - else - it->second->bind_user_name = "Free"; - } - } - } - } catch(...) { - ; - } - } - return result; + return m_print_options->GetPrintingSpeedLevel(); } -MachineObject* DeviceManager::get_local_selected_machine() +bool MachineObject::is_ams_unload() { - return get_local_machine(local_selected_machine); + return m_extder_system->GetTargetAmsId().compare("255") == 0; } -void DeviceManager::reload_printer_settings() +Slic3r::DevAms* MachineObject::get_curr_Ams() { - for (auto obj : this->userMachineList) - obj.second->reload_printer_settings(); + return m_fila_system->GetAmsById(m_extder_system->GetCurrentAmsId()); } -MachineObject* DeviceManager::get_default_machine() { - - std::string dev_id; - if (m_agent) { - m_agent->get_user_selected_machine(); - } - if (dev_id.empty()) return nullptr; - - auto it = userMachineList.find(dev_id); - if (it == userMachineList.end()) return nullptr; - return it->second; -} - -MachineObject* DeviceManager::get_local_machine(std::string dev_id) +Slic3r::DevAmsTray* MachineObject::get_ams_tray(std::string ams_id, std::string tray_id) { - if (dev_id.empty()) return nullptr; - auto it = localMachineList.find(dev_id); - if (it == localMachineList.end()) return nullptr; - return it->second; + return m_fila_system->GetAmsTray(ams_id, tray_id); } -void DeviceManager::erase_user_machine(std::string dev_id) +bool MachineObject::HasAms() const { - userMachineList.erase(dev_id); + return m_fila_system->HasAms(); } -MachineObject* DeviceManager::get_user_machine(std::string dev_id) +bool MachineObject::IsDetectOnInsertEnabled() const { - if (!Slic3r::GUI::wxGetApp().is_user_login()) - return nullptr; - - std::map::iterator it = userMachineList.find(dev_id); - if (it == userMachineList.end()) return nullptr; - return it->second; -} - -MachineObject* DeviceManager::get_my_machine(std::string dev_id) -{ - auto list = get_my_machine_list(); - auto it = list.find(dev_id); - if (it != list.end()) { - return it->second; - } - return nullptr; -} - -void DeviceManager::clean_user_info() -{ - BOOST_LOG_TRIVIAL(trace) << "DeviceManager::clean_user_info"; - // reset selected_machine - selected_machine = ""; - local_selected_machine = ""; - - // clean access code - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - it->second->set_access_code(""); - } - // clean user list - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (it->second) { - delete it->second; - it->second = nullptr; - } - } - userMachineList.clear(); -} - -bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnect) -{ - 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); - - // disconnect last - auto last_selected = my_machine_list.find(selected_machine); - if (last_selected != my_machine_list.end()) { - last_selected->second->m_active_state = MachineObject::NotActive; - if (last_selected->second->connection_type() == "lan") { - if (last_selected->second->is_connecting() && !need_disconnect) - return false; - } - } - - // connect curr - if (it != my_machine_list.end()) { - if (selected_machine == dev_id) { - if (it->second->connection_type() != "lan") { - // only reset update time - it->second->reset_update_time(); - - // check subscribe state - Slic3r::GUI::wxGetApp().on_start_subscribe_again(dev_id); - - return true; - } else { - // lan mode printer reconnect printer - if (m_agent) { - it->second->reset(); -#if !QDT_RELEASE_TO_PUBLIC - it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); -#else - it->second->connect(it->second->local_use_ssl_for_mqtt); -#endif - it->second->set_lan_mode_connection_state(true); - } - } - } else { - if (m_agent) { - if (it->second->connection_type() != "lan" || it->second->connection_type().empty()) { - if (m_agent->get_user_selected_machine() == dev_id) { - it->second->reset_update_time(); - it->second->nt_reset_data(); - } - else { - BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = " << dev_id; - m_agent->set_user_selected_machine(dev_id); - it->second->reset(); - } - } else { - BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = empty"; - it->second->reset(); -#if !QDT_RELEASE_TO_PUBLIC - it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); -#else - it->second->connect(it->second->local_use_ssl_for_mqtt); -#endif - it->second->set_lan_mode_connection_state(true); - } - } - } - for (auto& data : it->second->m_nozzle_filament_data) { - data.second.checked_filament.clear(); - } - } - selected_machine = dev_id; - return true; -} - -MachineObject* DeviceManager::get_selected_machine() -{ - if (selected_machine.empty()) return nullptr; - - MachineObject* obj = get_user_machine(selected_machine); - if (obj) - return obj; - - // return local machine has access code - auto it = localMachineList.find(selected_machine); - if (it != localMachineList.end()) { - if (it->second->has_access_right()) - return it->second; - } - return nullptr; -} - -void DeviceManager::subscribe_device_list(std::vector dev_list) -{ - std::vector unsub_list; - subscribe_list_cache.clear(); - 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 = " << QDTCrossTalk::Crosstalk_DevId(it); - } - } - BOOST_LOG_TRIVIAL(trace) << "subscribe_device_list: unsub_list size = " << unsub_list.size(); - - if (!selected_machine.empty()) { - subscribe_list_cache.push_back(selected_machine); - } - for (auto& it : dev_list) { - subscribe_list_cache.push_back(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()) - m_agent->del_subscribe(unsub_list); - if (!dev_list.empty()) - m_agent->add_subscribe(subscribe_list_cache); -} - -std::map DeviceManager::get_my_machine_list() -{ - std::map result; - - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (!it->second) - continue; - if (!it->second->is_lan_mode_printer()) - result.insert(std::make_pair(it->first, it->second)); - } - - 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()) { - result.emplace(std::make_pair(it->first, it->second)); - } - } - } - return result; -} - -std::map DeviceManager::get_my_cloud_machine_list() -{ - std::map result; - - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (!it->second) - continue; - if (!it->second->is_lan_mode_printer()) - result.emplace(*it); - } - return result; -} - -std::string DeviceManager::get_first_online_user_machine() { - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (it->second && it->second->is_online()) { - return it->second->dev_id; - } - } - return ""; -} - -void DeviceManager::modify_device_name(std::string dev_id, std::string dev_name) -{ - BOOST_LOG_TRIVIAL(trace) << "modify_device_name"; - if (m_agent) { - int result = m_agent->modify_printer_name(dev_id, dev_name); - if (result == 0) { - update_user_machine_list_info(); - } - } -} - -void DeviceManager::parse_user_print_info(std::string body) -{ - BOOST_LOG_TRIVIAL(trace) << "DeviceManager::parse_user_print_info"; - std::lock_guard lock(listMutex); - std::set new_list; - try { - json j = json::parse(body); - if (j.contains("devices") && !j["devices"].is_null()) { - for (auto& elem : j["devices"]) { - MachineObject* obj = nullptr; - std::string dev_id; - if (!elem["dev_id"].is_null()) { - dev_id = elem["dev_id"].get(); - new_list.insert(dev_id); - } - std::map::iterator iter = userMachineList.find(dev_id); - if (iter != userMachineList.end()) { - /* update field */ - obj = iter->second; - obj->dev_id = dev_id; - } - else { - obj = new MachineObject(m_agent, "", "", ""); - if (m_agent) { - obj->set_bind_status(m_agent->get_user_name()); - } - - if (obj->dev_ip.empty()) { - obj->dev_ip = Slic3r::GUI::wxGetApp().app_config->get("ip_address", dev_id); - } - userMachineList.insert(std::make_pair(dev_id, obj)); - } - - if (!obj) continue; - - if (!elem["dev_id"].is_null()) - obj->dev_id = elem["dev_id"].get(); - if (!elem["dev_name"].is_null()) - obj->dev_name = elem["dev_name"].get(); - if (!elem["dev_online"].is_null()) - obj->m_is_online = elem["dev_online"].get(); - if (elem.contains("dev_model_name") && !elem["dev_model_name"].is_null()) - obj->printer_type = elem["dev_model_name"].get(); - if (!elem["task_status"].is_null()) - obj->iot_print_status = elem["task_status"].get(); - if (elem.contains("dev_product_name") && !elem["dev_product_name"].is_null()) - obj->product_name = elem["dev_product_name"].get(); - if (elem.contains("dev_access_code") && !elem["dev_access_code"].is_null()) { - std::string acc_code = elem["dev_access_code"].get(); - acc_code.erase(std::remove(acc_code.begin(), acc_code.end(), '\n'), acc_code.end()); - obj->set_access_code(acc_code); - } - } - - //remove MachineObject from userMachineList - std::map::iterator iterat; - for (iterat = userMachineList.begin(); iterat != userMachineList.end(); ) { - if (new_list.find(iterat->first) == new_list.end()) { - iterat = userMachineList.erase(iterat); - } - else { - iterat++; - } - } - } - } - catch (std::exception&) { - ; - } -} - -void DeviceManager::update_user_machine_list_info() -{ - if (!m_agent) return; - - BOOST_LOG_TRIVIAL(debug) << "update_user_machine_list_info"; - unsigned int http_code; - std::string body; - int result = m_agent->get_user_print_info(&http_code, &body); - if (result == 0) { - parse_user_print_info(body); - } -} - - -std::map DeviceManager::get_local_machine_list() -{ - std::map result; - std::map::iterator it; - - for (it = localMachineList.begin(); it != localMachineList.end(); it++) { - if (it->second->m_is_online) { - result.insert(std::make_pair(it->first, it->second)); - } - } - - return result; -} - -void DeviceManager::load_last_machine() -{ - if (userMachineList.empty()) return; - - else if (userMachineList.size() == 1) { - this->set_selected_machine(userMachineList.begin()->second->dev_id); - } else { - if (m_agent) { - std::string last_monitor_machine = m_agent->get_user_selected_machine(); - bool found = false; - for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) { - if (last_monitor_machine == it->first) { - this->set_selected_machine(last_monitor_machine); - found = true; - } - } - if (!found) - this->set_selected_machine(userMachineList.begin()->second->dev_id); - } - } -} - -json DeviceManager::filaments_blacklist = json::object(); - - -std::string DeviceManager::parse_printer_type(std::string type_str) -{ - return get_value_from_config(type_str, "printer_type"); -} -std::string DeviceManager::get_printer_display_name(std::string type_str) -{ - return get_value_from_config(type_str, "display_name"); -} -std::string DeviceManager::get_ftp_folder(std::string type_str) -{ - return get_value_from_config(type_str, "ftp_folder"); -} -PrinterArch DeviceManager::get_printer_arch(std::string type_str) -{ - return get_printer_arch_by_str(get_value_from_config(type_str, "printer_arch")); -} -std::string DeviceManager::get_printer_thumbnail_img(std::string type_str) -{ - return get_value_from_config(type_str, "printer_thumbnail_image"); -} -std::string DeviceManager::get_printer_ams_type(std::string type_str) -{ - return get_value_from_config(type_str, "use_ams_type"); -} -std::string DeviceManager::get_printer_series(std::string type_str) -{ - return get_value_from_config(type_str, "printer_series"); -} -std::string DeviceManager::get_printer_diagram_img(std::string type_str) -{ - return get_value_from_config(type_str, "printer_connect_help_image"); -} -std::string DeviceManager::get_printer_ams_img(std::string type_str) -{ - return get_value_from_config(type_str, "printer_use_ams_image"); } - -std::string DeviceManager::get_printer_ext_img(std::string type_str, int pos) { - const auto& vec = get_value_from_config>(type_str, "printer_ext_image"); - if (vec.size() > pos) { return vec[pos];} - return std::string(); -} - -bool DeviceManager::get_printer_is_enclosed(std::string type_str) { - return get_value_from_config(type_str, "printer_is_enclosed"); } - -bool DeviceManager::get_printer_can_set_nozzle(std::string type_str) -{ - return get_value_from_config(type_str, "enable_set_nozzle_info"); -} - -std::vector DeviceManager::get_resolution_supported(std::string type_str) -{ - std::vector resolution_supported; - - 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("camera_resolution")) { - for (auto res : printer["camera_resolution"]) - resolution_supported.emplace_back(res.get()); - } - } - } - } - catch (...) {} - return resolution_supported; -} - -std::vector DeviceManager::get_compatible_machine(std::string type_str) -{ - std::vector compatible_machine; - 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("compatible_machine")) { - for (auto res : printer["compatible_machine"]) - compatible_machine.emplace_back(res.get()); - } - } - } - } - catch (...) {} - return compatible_machine; -} - -std::vector DeviceManager::get_unsupport_auto_cali_filaments(std::string type_str) -{ - 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("auto_cali_not_support_filaments")) { - for (auto res : printer["auto_cali_not_support_filaments"]) - filaments.emplace_back(res.get()); - } - } - } - } catch (...) {} - return filaments; -} - -boost::bimaps::bimap DeviceManager::get_all_model_id_with_name() -{ - boost::bimaps::bimap models; - std::vector m_files; - - wxDir dir(Slic3r::resources_dir() + "/printers/"); - if (!dir.IsOpened()) { - return models; - } - - wxString filename; - bool hasFile = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES); - while (hasFile) { - m_files.push_back(filename); - hasFile = dir.GetNext(&filename); - } - - for (wxString file : m_files) { - std::string config_file = Slic3r::resources_dir() + "/printers/" + file.ToStdString(); - 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"]; - - std::string model_id; - std::string display_name; - if (printer.contains("model_id")) {model_id = printer["model_id"].get();} - if (printer.contains("display_name")) {display_name = printer["display_name"].get();} - - if (!model_id.empty() && !display_name.empty()) { - models.left.insert(make_pair(model_id, display_name)); - } - } - } - } catch (...) {} - } - - return models; -} - -bool DeviceManager::load_filaments_blacklist_config() -{ - filaments_blacklist = json::object(); - - std::string config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json"; - boost::nowide::ifstream json_file(config_file.c_str()); - - try { - if (json_file.is_open()) { - json_file >> filaments_blacklist; - return true; - } - else { - BOOST_LOG_TRIVIAL(error) << "load filaments blacklist config failed, file = filaments_blacklist.json"; - } - } - catch (...) { - 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) - return true; - return false; -} - -std::string DeviceManager::get_filament_name_from_ams(int ams_id, int slot_id) -{ - std::string name; - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (!dev) { return name; } - - MachineObject *obj = dev->get_selected_machine(); - if (obj == nullptr) { return name; } - - if (ams_id < 0 || slot_id < 0 ) { - return name; - } - - if (obj->amsList.find(std::to_string(ams_id)) == obj->amsList.end()) {return name;} - - if (obj->amsList[std::to_string(ams_id)]->trayList.find(std::to_string(slot_id)) == obj->amsList[std::to_string(ams_id)]->trayList.end()) { return name; } - - std::string filament_id = obj->amsList[std::to_string(ams_id)]->trayList[std::to_string(slot_id)]->setting_id; - - PresetBundle *preset_bundle = GUI::wxGetApp().preset_bundle; - auto option = preset_bundle->get_filament_by_filament_id(filament_id); - name = option ? option->filament_name : ""; - return name; -} - -void DeviceManager::OnMachineBindStateChanged(MachineObject *obj, const std::string &new_state) { - if (!obj) { return; } - if (obj->dev_id == selected_machine) { - if (new_state == "free") { OnSelectedMachineLost();} - } -} - -void DeviceManager::OnSelectedMachineLost() { - GUI::wxGetApp().sidebar().update_sync_status(nullptr); - GUI::wxGetApp().sidebar().load_ams_list(string(), nullptr); -} - - -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); - } - - in_blacklist = false; - - std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower); - std::transform(tag_type.begin(), tag_type.end(), tag_type.begin(), ::tolower); - std::transform(tag_name.begin(), tag_name.end(), tag_name.begin(), ::tolower); - if (DeviceManager::filaments_blacklist.contains("blacklist")) { - for (auto filament_item : DeviceManager::filaments_blacklist["blacklist"]) { - - std::string vendor = filament_item.contains("vendor") ? filament_item["vendor"].get() : ""; - 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() : ""; - - // check model id - if (!model_ids.empty() && std::find(model_ids.begin(), model_ids.end(), model_id) == model_ids.end()) { continue;} - - // check vendor - std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower); - if (!vendor.empty()) { - if ((vendor == "qidi tech" && (tag_vendor == vendor)) || - (vendor == "third party" && (tag_vendor != "qidi tech"))){ - // Do nothing - } else { - continue; - } - } - - // check type - std::transform(type.begin(), type.end(), type.begin(), ::tolower); - if (!type.empty() && (type != tag_type)) { continue; } - - // check type suffix - std::transform(type_suffix.begin(), type_suffix.end(), type_suffix.begin(), ::tolower); - if (!type_suffix.empty()) { - if (tag_type.length() < type_suffix.length()) { continue; } - if ((tag_type.substr(tag_type.length() - type_suffix.length()) != type_suffix)) { continue; } - } - - // check name - 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 = _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, - 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; - 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)) - { - return; - } - - 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) -{ - std::string gcode_full_path = Slic3r::resources_dir() + "/printers/" + gcode_file; - std::ifstream gcode(encode_path(gcode_full_path.c_str()).c_str()); - try { - std::stringstream gcode_str; - if (gcode.is_open()) { - gcode_str << gcode.rdbuf(); - gcode.close(); - return gcode_str.str(); - } - } catch(...) { - BOOST_LOG_TRIVIAL(error) << "load gcode file failed, file = " << gcode_file; - } - - - return ""; -} - -DeviceManagerRefresher::DeviceManagerRefresher(DeviceManager *manger) : wxObject() { - m_manager = manger; - m_timer = new wxTimer(); - m_timer->Bind(wxEVT_TIMER, &DeviceManagerRefresher::on_timer, this); -} - -DeviceManagerRefresher::~DeviceManagerRefresher() { - m_timer->Stop(); - delete m_timer; -} - -void DeviceManagerRefresher::on_timer(wxTimerEvent &event) { - if (!m_manager) { return;} - - NetworkAgent *agent = m_manager->get_agent(); - if (!agent) { return; } - - // reset to active - Slic3r::GUI::wxGetApp().reset_to_active(); - - MachineObject *obj = m_manager->get_selected_machine(); - if (!obj) { return; } - - // check valid machine - if (obj && m_manager->get_my_machine(obj->dev_id) == nullptr) { - m_manager->set_selected_machine(""); - agent->set_user_selected_machine(""); - return; - } - - // do some refresh - if (Slic3r::GUI::wxGetApp().is_user_login()) - { - m_manager->check_pushing(); - try { - agent->refresh_connection(); - } catch (...) { - ; - } - } - - // certificate - agent->install_device_cert(obj->dev_id, obj->is_lan_mode_printer()); + return m_fila_system->GetAmsSystemSetting().IsDetectOnInsertEnabled(); } void change_the_opacity(wxColour& colour) @@ -8332,27 +5447,4 @@ void change_the_opacity(wxColour& colour) } } - -//************************************ -// Method: get_longlong_val -// FullName: Slic3r::JsonValParser::get_longlong_val -// Access: public static -// Returns: std::string -// Qualifier: -// Parameter: const json & j -//************************************ -std::string JsonValParser::get_longlong_val(const json& j) -{ - if (j.is_number()) - { - return std::to_string(j.get()); - } - else if (j.is_string()) - { - return j.get(); - } - - return string(); -} - } // namespace Slic3r diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index b860a87..565c7e7 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -7,17 +7,22 @@ #include #include #include +#include #include #include #include "nlohmann/json.hpp" #include "libslic3r/ProjectTask.hpp" #include "slic3r/Utils/json_diff.hpp" -#include "slic3r/Utils/NetworkAgent.hpp" #include "boost/bimap/bimap.hpp" #include "CameraPopup.hpp" #include "libslic3r/Calib.hpp" #include "libslic3r/Utils.hpp" +#include "DeviceCore/DevDefs.h" +#include "DeviceCore/DevConfigUtil.h" +#include "DeviceCore/DevFirmware.h" + + #include #define USE_LOCAL_SOCKET_BIND 0 @@ -31,9 +36,6 @@ #define EXTRUSION_OMIT_TIME 20000.f // milliseconds #define HOLD_TIMEOUT 10000.f // milliseconds -#define FILAMENT_MAX_TEMP 300 -#define FILAMENT_DEF_TEMP 220 -#define FILAMENT_MIN_TEMP 120 #define BED_TEMP_LIMIT 120 #define HOLD_COUNT_MAX 3 @@ -45,491 +47,24 @@ #define GET_VERSION_RETRYS 10 #define RETRY_INTERNAL 2000 -#define MAIN_NOZZLE_ID 0 -#define DEPUTY_NOZZLE_ID 1 -#define UNIQUE_NOZZLE_ID MAIN_NOZZLE_ID -#define INVALID_NOZZLE_ID -1 - -#define VIRTUAL_TRAY_MAIN_ID 255 -#define VIRTUAL_TRAY_DEPUTY_ID 254 - -#define VIRTUAL_AMS_MAIN_ID_STR "255" -#define VIRTUAL_AMS_DEPUTY_ID_STR "254" - #define START_SEQ_ID 20000 #define END_SEQ_ID 30000 #define SUBSCRIBE_RETRY_COUNT 5 -inline int correct_filament_temperature(int filament_temp) -{ - int temp = std::min(filament_temp, FILAMENT_MAX_TEMP); - temp = std::max(temp, FILAMENT_MIN_TEMP); - return temp; -} - -wxString get_stage_string(int stage); - using namespace nlohmann; - namespace Slic3r { -class SecondaryCheckDialog; -enum PrinterArch { - ARCH_CORE_XY, - ARCH_I3, -}; - -enum PrinterSeries { - SERIES_X1 = 0, - SERIES_P1P, - SERIES_UNKNOWN, -}; - -enum PrinterFunction { - FUNC_MAX -}; - - -enum PrintingSpeedLevel { - SPEED_LEVEL_INVALID = 0, - SPEED_LEVEL_SILENCE = 1, - SPEED_LEVEL_NORMAL = 2, - SPEED_LEVEL_RAPID = 3, - SPEED_LEVEL_RAMPAGE = 4, - SPEED_LEVEL_COUNT -}; +namespace GUI +{ +class DeviceErrorDialog; // Previous definitions +} class NetworkAgent; - - -enum AmsRfidState { - AMS_RFID_INIT, - AMS_RFID_LOADING, - AMS_REID_DONE, -}; - -enum AmsStep { - AMS_STEP_INIT, - AMS_STEP_HEAT_EXTRUDER, - AMS_STEP_LOADING, - AMS_STEP_COMPLETED, -}; - -enum AmsRoadPosition { - AMS_ROAD_POSITION_TRAY, // filament at tray - AMS_ROAD_POSITION_TUBE, // filament at tube - AMS_ROAD_POSITION_HOTEND, // filament at hotend -}; - -enum AmsStatusMain { - AMS_STATUS_MAIN_IDLE = 0x00, - AMS_STATUS_MAIN_FILAMENT_CHANGE = 0x01, - AMS_STATUS_MAIN_RFID_IDENTIFYING = 0x02, - AMS_STATUS_MAIN_ASSIST = 0x03, - AMS_STATUS_MAIN_CALIBRATION = 0x04, - AMS_STATUS_MAIN_SELF_CHECK = 0x10, - AMS_STATUS_MAIN_DEBUG = 0x20, - AMS_STATUS_MAIN_UNKNOWN = 0xFF, -}; - -enum AmsRfidStatus { - AMS_RFID_IDLE = 0, - AMS_RFID_READING = 1, - AMS_RFID_GCODE_TRANS = 2, - AMS_RFID_GCODE_RUNNING = 3, - AMS_RFID_ASSITANT = 4, - AMS_RFID_SWITCH_FILAMENT= 5, - AMS_RFID_HAS_FILAMENT = 6 -}; - -enum AmsOptionType { - AMS_OP_STARTUP_READ, - AMS_OP_TRAY_READ, - AMS_OP_CALIBRATE_REMAIN -}; - enum ManualPaCaliMethod { PA_LINE = 0, PA_PATTERN, }; -enum ExtruderSwitchState { - ES_IDLE = 0, - ES_BUSY, - ES_SWITCHING, - ES_SWITCHING_FAILED -}; - -enum AirDuctType { - AIR_FAN_TYPE, - AIR_DOOR_TYPE -}; - -enum NozzleFlowType{ - NONE_FLOWTYPE, - S_FLOW, - H_FLOW -}; - -enum NozzleToolType { - NONE_TOOLTYPE, - H_TOOL, - C_TOOL -}; - -struct AmsSlot -{ - std::string ams_id; - std::string slot_id; -}; - -struct Nozzle -{ - int id; - NozzleToolType tool_type; // H nozzle or Cut - NozzleFlowType nozzle_flow; // 0-common 1-high flow - NozzleType nozzle_type; // 0-stainless_steel 1-hardened_steel 5-tungsten_carbide - float diameter = {0.4f}; // 0-0.2mm 1-0.4mm 2-0.6 mm3-0.8mm - int max_temp = 0; - int wear = 0; -}; - -struct NozzleData -{ - int extder_exist; //0- none exist 1-exist - int cut_exist; - int state; //0-idle 1-checking - std::vector nozzles; -}; - -struct Extder -{ - int id; // 0-right 1-left - - int enable_change_nozzle{0}; - int ext_has_filament{0}; - int buffer_has_filament{0}; - int nozzle_exist{0}; - - std::vector filam_bak;// the refill filam - - int temp{0}; - int target_temp{0}; - - AmsSlot spre; // tray_pre - AmsSlot snow; // tray_now - AmsSlot star; // tray_tar - int ams_stat{0}; - - int rfid_stat{0}; - - int nozzle_id; // nozzle id now - int target_nozzle_id; // target nozzle id - - //current nozzle - NozzleType current_nozzle_type{NozzleType::ntUndefine}; // 0-hardened_steel 1-stainless_steel - float current_nozzle_diameter = {0.4f}; // 0-0.2mm 1-0.4mm 2-0.6 mm3-0.8mm - NozzleFlowType current_nozzle_flow_type{NozzleFlowType::NONE_FLOWTYPE};//0-common 1-high flow -}; - -struct ExtderData -{ - int current_extder_id{0}; - int target_extder_id{0}; - int total_extder_count {0}; - int current_loading_extder_id {-1}; - bool current_busy_for_loading{false}; - ExtruderSwitchState switch_extder_state; - std::vector extders; -}; - -struct AirMode -{ - int id{-1}; - std::vector ctrl; - // 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 -{ - int type{ 0 }; - int id{ 0 }; - int func{ 0 }; - 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 -{ - 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 { - bool request_successful; - int http_code; - int rating_id; - int start_count; - bool success_printed; - std::string content; - std::vector image_url_paths; -}; - -class AmsTray { -public: - AmsTray(std::string tray_id) { - is_qdt = false; - id = tray_id; - road_position = AMS_ROAD_POSITION_TRAY; - step_state = AMS_STEP_INIT; - rfid_state = AMS_RFID_INIT; - } - - static int hex_digit_to_int(const char c) - { - return (c >= '0' && c <= '9') ? int(c - '0') : (c >= 'A' && c <= 'F') ? int(c - 'A') + 10 : (c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1; - } - - static wxColour decode_color(const std::string &color) - { - std::array ret = {0, 0, 0, 0}; - const char * c = color.data(); - if (color.size() == 8) { - for (size_t j = 0; j < 4; ++j) { - int digit1 = hex_digit_to_int(*c++); - int digit2 = hex_digit_to_int(*c++); - if (digit1 == -1 || digit2 == -1) break; - ret[j] = float(digit1 * 16 + digit2); - } - } else { - return wxColour(255, 255, 255, 255); - } - return wxColour(ret[0], ret[1], ret[2], ret[3]); - } - - bool operator==(AmsTray const &o) const - { - return id == o.id && type == o.type && filament_setting_id == o.filament_setting_id && color == o.color; - } - bool operator!=(AmsTray const &o) const { return !operator==(o); } - - std::string id; - std::string tag_uid; // tag_uid - std::string setting_id; // tray_info_idx - std::string filament_setting_id; // setting_id - std::string type; - std::string sub_brands; - std::string color; - std::vector cols; - std::string weight; - std::string diameter; - std::string temp; - std::string time; - std::string bed_temp_type; - std::string bed_temp; - std::string nozzle_temp_max; - std::string nozzle_temp_min; - std::string xcam_info; - std::string uuid; - int ctype = 0; - float k = 0.0f; // k range: 0 ~ 0.5 - float n = 0.0f; // k range: 0.6 ~ 2.0 - int cali_idx = -1; // - 1 means default - - wxColour wx_color; - bool is_qdt; - bool is_exists = false; - int hold_count = 0; - int remain = 0; // filament remain: 0 ~ 100 - - AmsRoadPosition road_position; - AmsStep step_state; - AmsRfidState rfid_state; - - void set_hold_count() { hold_count = HOLD_COUNT_MAX; } - void update_color_from_str(std::string color); - wxColour get_color(); - - void reset(); - - bool is_tray_info_ready(); - bool is_unset_third_filament(); - std::string get_display_filament_type(); - std::string get_filament_type(); -}; - -#define INVALID_AMS_TEMPERATURE std::numeric_limits::min() - -class Ams -{ -public: - Ams(std::string ams_id, int nozzle_id, int type_id) - { - id = ams_id; - nozzle = nozzle_id; - type = type_id; - } - std::string id; - std::string info; - int left_dry_time = 0; - int humidity = 5; - int humidity_raw = -1; // the percentage, -1 means invalid. eg. 100 means 100% - float current_temperature = INVALID_AMS_TEMPERATURE; // the temperature - bool startup_read_opt{true}; - bool tray_read_opt{false}; - bool is_exists{false}; - std::map trayList; - - int nozzle; - int type{1}; // 0:dummy 1:ams 2:ams-lite 3:n3f 4:n3s - -public: - wxString get_ams_device_name() const - { - wxString ams_device_name; - if (type == 1) { - ams_device_name = "BOX-%d"; - } else if (type == 2) { - ams_device_name = "BOX Lite-%d"; - } else if (type == 3) { - ams_device_name = "BOX 2 PRO-%d"; - } else if (type == 4) { - ams_device_name = "BOX HT-%d"; - } else { - assert(0); - ams_device_name = "BOX-%d"; - } - - int num_id; - try { - num_id = std::stoi(id); - } catch (...) {} - - int loc = (num_id > 127) ? (num_id - 127) : (num_id + 1); - return wxString::Format(ams_device_name, loc); - }; -}; - -enum PrinterFirmwareType { - FIRMWARE_TYPE_ENGINEER = 0, - FIRMWARE_TYPE_PRODUCTION, - FIRMEARE_TYPE_UKNOWN, -}; - - -class FirmwareInfo -{ -public: - std::string module_type; // ota or ams - std::string version; - std::string url; - std::string name; - std::string description; -}; - -enum ModuleID { - MODULE_UKNOWN = 0x00, - MODULE_01 = 0x01, - MODULE_02 = 0x02, - MODULE_MC = 0x03, - MODULE_04 = 0x04, - MODULE_MAINBOARD = 0x05, - MODULE_06 = 0x06, - MODULE_AMS = 0x07, - MODULE_TH = 0x08, - MODULE_09 = 0x09, - MODULE_10 = 0x0A, - MODULE_11 = 0x0B, - MODULE_XCAM = 0x0C, - MODULE_13 = 0x0D, - MODULE_14 = 0x0E, - MODULE_15 = 0x0F, - MODULE_MAX = 0x10 -}; - -enum HMSMessageLevel { - HMS_UNKNOWN = 0, - HMS_FATAL = 1, - HMS_SERIOUS = 2, - HMS_COMMON = 3, - HMS_INFO = 4, - HMS_MSG_LEVEL_MAX, -}; - - -enum AIR_FUN { - FAN_HEAT_BREAK_0_IDX = 0, - FAN_COOLING_0_AIRDOOR = 1, - FAN_REMOTE_COOLING_0_IDX = 2, - FAN_CHAMBER_0_IDX = 3, - FAN_HEAT_BREAK_1_IDX = 4, - FAN_MC_BOARD_0_IDX = 5, - FAN_INNNER_LOOP_FAN_0_IDX = 6, - FAN_TOTAL_COUNT = 7 -}; - -enum AIR_DOOR { - AIR_DOOR_FUNC_CHAMBER = 0, - AIR_DOOR_FUNC_INNERLOOP, - AIR_DOOR_FUNC_TOP -}; - -enum AIR_DUCT { - AIR_DUCT_NONE = -1, - AIR_DUCT_COOLING_FILT = 0, - AIR_DUCT_HEATING_INTERNAL_FILT, - AIR_DUCT_EXHAUST, - AIR_DUCT_FULL_COOLING, - AIR_DUCT_INIT = 0xFF //Initial mode, only used within mc -}; - -class HMSItem -{ -public: - ModuleID module_id; - unsigned module_num; - unsigned part_id; - unsigned reserved; - HMSMessageLevel msg_level = HMS_UNKNOWN; - int msg_code = 0; - bool already_read = false; - bool parse_hms_info(unsigned attr, unsigned code); - std::string get_long_error_code(); - - static wxString get_module_name(ModuleID module_id); - static wxString get_hms_msg_level_str(HMSMessageLevel level); -}; - #define UpgradeNoError 0 #define UpgradeDownloadFailed -1 @@ -537,135 +72,92 @@ public: #define UpgradeFlashFailed -3 #define UpgradePrinting -4 -// calc distance map -struct DisValue { - int tray_id; - float distance; - bool is_same_color = true; - bool is_type_match = true; -}; +// Previous definitions +class DevAms; +class DevAmsTray; +class DevBed; +class DevConfig; +class DevCtrl; +class DevExtderSystem; +class DevFan; +class DevFilaSystem; +class DevPrintOptions; +class DevHMS; +class DevLamp; +class DevNozzleSystem; +class DeviceManager; +class DevStorage; +struct DevPrintTaskRatingInfo; + -class Preset; class MachineObject { private: - NetworkAgent * m_agent{nullptr}; + NetworkAgent * m_agent{nullptr}; + DeviceManager* m_manager{ nullptr }; std::shared_ptr m_token = std::make_shared(1); - bool check_valid_ip(); - void _parse_print_option_ack(int option); - + /* properties */ + std::string dev_id; + std::string dev_name; + std::string dev_ip; std::string access_code; std::string user_access_code; // type, time stamp, delay std::vector> message_delay; + /*parts*/ + DevLamp* m_lamp; + DevExtderSystem* m_extder_system; + DevNozzleSystem* m_nozzle_system; + DevFilaSystem* m_fila_system; + DevFan* m_fan; + DevBed * m_bed; + DevStorage* m_storage; + + /*Ctrl*/ + DevCtrl* m_ctrl; + + /*Print Options/Speed*/ + DevPrintOptions* m_print_options; + + /*HMS*/ + DevHMS* m_hms_system; + + /*Config*/ + DevConfig* m_config; + public: + MachineObject(DeviceManager* manager, NetworkAgent* agent, std::string name, std::string id, std::string ip); + ~MachineObject(); - typedef std::function CommandCallBack; - - enum LIGHT_EFFECT { - LIGHT_EFFECT_ON, - LIGHT_EFFECT_OFF, - LIGHT_EFFECT_FLASHING, - LIGHT_EFFECT_UNKOWN, - }; - - enum FanType { - COOLING_FAN = 1, - BIG_COOLING_FAN = 2, - CHAMBER_FAN = 3, - EXHAUST_FAN, - FILTER_FAN, - }; - - enum UpgradingDisplayState { - UpgradingUnavaliable = 0, - UpgradingAvaliable = 1, - UpgradingInProgress = 2, - UpgradingFinished = 3 - }; - - enum ExtruderAxisStatus { - LOAD = 0, - UNLOAD =1, - STATUS_NUMS = 2 - }; - enum ExtruderAxisStatus extruder_axis_status = LOAD; - - enum PrintOption { - PRINT_OP_AUTO_RECOVERY = 0, - PRINT_OP_MAX, - }; - - class ModuleVersionInfo - { - public: - std::string name; - wxString product_name; - std::string sn; - std::string hw_ver; - std::string sw_ver; - std::string sw_new_ver; - int firmware_status; - ModuleVersionInfo() :firmware_status(0) { - - }; - - public: - bool isValid() const { return !sn.empty(); } - bool isAirPump() const { return product_name.Contains("Air Pump"); } - bool isLaszer() const { return product_name.Contains("Laser"); } - bool isCuttingModule() const { return product_name.Contains("Cutting Module"); } - }; - - enum SdcardState { - NO_SDCARD = 0, - HAS_SDCARD_NORMAL = 1, - HAS_SDCARD_ABNORMAL = 2, - HAS_SDCARD_READONLY = 3, - SDCARD_STATE_NUM = 4 - }; - +public: enum ActiveState { NotActive, Active, UpdateToDate }; - enum MappingOption { - USE_LEFT_AMS = 0, - USE_RIGHT_AMS, - USE_LEFT_EXT, - USE_RIGHT_EXT + enum PrintOption { + PRINT_OP_AUTO_RECOVERY = 0, + PRINT_OP_MAX, }; - class ExtrusionRatioInfo - { - public: - std::string name; - std::string setting_id; - float k = 0.0; - float n = 0.0; - }; +public: /* static members and functions */ static inline int m_sequence_id = START_SEQ_ID; - static std::string parse_printer_type(std::string type_str); - static std::string get_preset_printer_model_name(std::string printer_type); - static std::string get_preset_printer_thumbnail_img(std::string printer_type); - static bool is_qdt_filament(std::string tag_uid); - - typedef std::function UploadedFn; - typedef std::function UploadProgressFn; - typedef std::function ErrorFn; - typedef std::function ResultFn; /* properties */ - std::string dev_name; - std::string dev_ip; - std::string dev_id; + std::string get_dev_name() const { return dev_name; } + void set_dev_name(std::string val) { dev_name = val; } + + std::string get_dev_ip() const { return dev_ip; } + void set_dev_ip(std::string ip) { dev_ip = ip; } + + std::string get_dev_id() const { return dev_id; } + void set_dev_id(std::string val) { dev_id = val; } //y std::string dev_url; std::string dev_apikey; @@ -673,23 +165,32 @@ public: bool local_use_ssl_for_mqtt { true }; bool local_use_ssl_for_ftp { true }; - bool m_busy_for_select_extruder {false}; + std::string get_ftp_folder(); + int subscribe_counter{3}; + std::string dev_connection_type; /* lan | cloud */ - std::string connection_type() { return dev_connection_type; } + std::string connection_type() const { return dev_connection_type; } + bool is_lan_mode_printer() { return dev_connection_type == "lan"; } + bool is_cloud_mode_printer() { return dev_connection_type == "cloud"; } + + std::chrono::system_clock::time_point last_cloud_msg_time_; + std::chrono::system_clock::time_point last_lan_msg_time_; + + bool HasRecentCloudMessage(); + bool HasRecentLanMessage(); std::string dev_connection_name; /* lan | eth */ - void set_dev_ip(std::string ip) {dev_ip = ip;} - std::string get_ftp_folder(); - bool has_access_right() { return !get_access_code().empty(); } - std::string get_access_code(); + /*access code*/ + bool has_access_right() const { return !get_access_code().empty(); } + std::string get_access_code() const; void set_access_code(std::string code, bool only_refresh = true); + + /*user access code*/ void set_user_access_code(std::string code, bool only_refresh = true); void erase_user_access_code(); - std::string get_user_access_code(); - bool is_lan_mode_printer(); - std::string convertToIp(long long ip); + std::string get_user_access_code() const; //PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN; std::string printer_type; /* model_id */ @@ -697,9 +198,12 @@ public: PrinterSeries get_printer_series() const; PrinterArch get_printer_arch() const; std::string get_printer_ams_type() const; - bool get_printer_is_enclosed() const; + wxString get_printer_type_display_str() const; + std::string get_auto_pa_cali_thumbnail_img_str() const; // check printer device series + std::string get_printer_series_str() const; + static bool is_series_n(const std::string& series_str); static bool is_series_p(const std::string& series_str); static bool is_series_x(const std::string& series_str); @@ -710,24 +214,18 @@ public: bool is_series_x() const; bool is_series_o() const; - std::string get_printer_series_str() const; - void reload_printer_settings(); + std::string get_printer_thumbnail_img_str() const; - std::string printer_thumbnail_img; - std::string monitor_upgrade_printer_img; - - wxString get_printer_type_display_str(); - std::string get_printer_thumbnail_img_str(); - - std::string product_name; // set by iot service, get /user/print + std::string dev_product_name; // set by iot service, get /user/print std::string bind_user_name; std::string bind_user_id; - std::string bind_state; /* free | occupied */ std::string bind_sec_link; std::string bind_ssdp_version; + std::string bind_state; /* free | occupied */ bool is_avaliable() { return bind_state == "free"; } + time_t last_alive; bool m_is_online; bool m_lan_mode_connection_state{false}; @@ -744,26 +242,17 @@ public: std::chrono::system_clock::time_point last_request_push; /* last received print push from machine */ std::chrono::system_clock::time_point last_request_start; /* last received print push from machine */ + bool device_cert_installed = false; + int m_active_state = 0; // 0 - not active, 1 - active, 2 - update-to-date bool is_tunnel_mqtt = false; - /* ams properties */ - std::map amsList; // key: ams[id], start with 0 - - int ams_cali_id = 0; - int ams_cali_stat = 0; - //AmsTray vt_tray; // virtual tray long ams_exist_bits = 0; long tray_exist_bits = 0; long tray_is_qdt_bits = 0; long tray_read_done_bits = 0; long tray_reading_bits = 0; - int ams_rfid_status = 0; - bool ams_insert_flag { false }; - bool ams_power_on_flag { false }; - bool ams_calibrate_remain_flag { false }; - bool ams_auto_switch_filament_flag { false }; bool ams_air_print_status { false }; bool ams_support_virtual_tray { true }; time_t ams_user_setting_start = 0; @@ -771,10 +260,6 @@ public: AmsStatusMain ams_status_main; int ams_status_sub; int ams_version = 0; - std::string m_ams_id; // local ams : "0" ~ "3" - std::string m_tray_id; // local tray id : "0" ~ "3" - std::string m_tray_now; // tray_now : "0" ~ "15" or "254", "255" - std::string m_tray_tar; // tray_tar : "0" ~ "15" or "255" int extrusion_cali_hold_count = 0; std::chrono::system_clock::time_point last_extrusion_cali_start_time; @@ -782,40 +267,39 @@ public: std::chrono::system_clock::time_point extrusion_cali_set_hold_start; std::string extrusion_cali_filament_name; - bool only_exist_ext_spool() { return amsList.empty(); } bool is_in_extrusion_cali(); bool is_extrusion_cali_finished(); - void _parse_tray_now(std::string tray_now); - bool is_filament_move() { return atoi(m_tray_now.c_str()) == 255 ? false : true; }; - bool is_ams_need_update; - inline bool is_ams_unload() { return m_tray_tar.compare("255") == 0; } - [[nodiscard]] bool is_ams_on_settingup() const; - - Ams* get_curr_Ams(); - AmsTray* get_curr_tray(); - AmsTray *get_ams_tray(std::string ams_id, std::string tray_id); + /* AMS */ + DevAms* get_curr_Ams(); + DevAmsTray* get_curr_tray(); + DevAmsTray* 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); - bool has_ams() { return ams_exist_bits != 0; } + + bool is_ams_unload(); bool can_unload_filament(); - bool is_support_amx_ext_mix_mapping(); + bool is_support_amx_ext_mix_mapping() const { return true;} void get_ams_colors(std::vector& ams_colors); - void parse_tray_info(int ams_id, int sot_id, AmsTray tray, FilamentInfo& result); - int ams_filament_mapping(std::vector filaments, std::vector &result, std::vector map_opt, std::vector exclude_id = std::vector(),bool nozzle_has_ams_then_ignore_ext =false); - bool is_valid_mapping_result(std::vector& result, bool check_empty_slot = false); - // exceed index start with 0 - bool is_mapping_exceed_filament(std::vector& result, int &exceed_index); - void reset_mapping_result(std::vector& result); - bool is_main_extruder_on_left() const; + + /*extruder*/ + bool is_main_extruder_on_left() const { return false; } // only means the extruder is on the left hand when extruder id is 0 bool is_multi_extruders() const; - bool need_SD_card() const; - int get_extruder_id_by_ams_id(const std::string &ams_id); + int get_extruder_id_by_ams_id(const std::string& ams_id); + + /* ams settings*/ + bool IsDetectOnInsertEnabled() const;; + //bool IsDetectOnPowerupEnabled() const { return m_enable_detect_on_powerup; } + //bool IsDetectRemainEnabled() const { return m_enable_detect_remain; } + //bool IsAutoRefillEnabled() const { return m_enable_auto_refill; } + + [[nodiscard]] bool is_nozzle_flow_type_supported() const { return is_enable_np; }; + [[nodiscard]] wxString get_nozzle_replace_url() const; /*online*/ bool online_rfid; @@ -824,52 +308,40 @@ public: int last_online_version = -1; /* temperature */ - //float nozzle_temp; - //float nozzle_temp_target; - float bed_temp; - float bed_temp_target; float chamber_temp; float chamber_temp_target; - float chamber_temp_edit_min = 0; - float chamber_temp_edit_max = 60; - long chamber_temp_switch_heat = LONG_MAX;/*default to LONG_MAX*/ float frame_temp; - /* cooling */ - int heatbreak_fan_speed = 0; - int cooling_fan_speed = 0; - int big_fan1_speed = 0; - int big_fan2_speed = 0; - uint32_t fan_gear = 0; - - /*extruder*/ - [[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; - bool is_at_heating_mode() const { return m_air_duct_data.curren_mode == AIR_DUCT_HEATING_INTERNAL_FILT; }; - void converse_to_duct(bool is_suppt_part_fun, bool is_suppt_aux_fun, bool is_suppt_cham_fun); // Convert the data to duct type to make the newand old protocols consistent - /* signals */ std::string wifi_signal; std::string link_th; std::string link_ams; bool network_wired { false }; - /* lights */ - LIGHT_EFFECT chamber_light; - LIGHT_EFFECT work_light; - std::string light_effect_str(LIGHT_EFFECT effect); - LIGHT_EFFECT light_effect_parse(std::string effect_str); + /* parts */ + DevExtderSystem* GetExtderSystem() const { return m_extder_system; } + DevNozzleSystem* GetNozzleSystem() const { return m_nozzle_system;} + + DevFilaSystem* GetFilaSystem() const { return m_fila_system;} + bool HasAms() const; + + DevLamp* GetLamp() const { return m_lamp; } + DevFan* GetFan() const { return m_fan; } + DevBed * GetBed() const { return m_bed; }; + DevStorage *GetStorage() const { return m_storage; } + + DevCtrl* GetCtrl() const { return m_ctrl; } /* ctrl*/ + DevHMS* GetHMS() const { return m_hms_system; } /* hms*/ + DevConfig* GetConfig() const { return m_config; } /* config*/ + + DevPrintOptions* GetPrintOptions() const { return m_print_options; } /* print options */ + DevPrintingSpeedLevel GetPrintingSpeedLevel() const; /* print speed */ /* upgrade */ bool upgrade_force_upgrade { false }; bool upgrade_new_version { false }; bool upgrade_consistency_request { false }; - int upgrade_display_state = 0; // 0 : upgrade unavailable, 1: upgrade idle, 2: upgrading, 3: upgrade_finished + DevFirmwareUpgradingState upgrade_display_state; int upgrade_display_hold_count = 0; PrinterFirmwareType firmware_type; // engineer|production PrinterFirmwareType lifecycle { PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION }; @@ -882,12 +354,12 @@ public: std::string ahb_new_version_number; int get_version_retry = 0; - ModuleVersionInfo air_pump_version_info; - ModuleVersionInfo laser_version_info; - ModuleVersionInfo cutting_module_version_info; - std::map module_vers; - std::map new_ver_list; - std::map extrusion_ratio_map; + DevFirmwareVersionInfo air_pump_version_info; + DevFirmwareVersionInfo laser_version_info; + DevFirmwareVersionInfo cutting_module_version_info; + DevFirmwareVersionInfo extinguish_version_info; + std::map module_vers; + std::map new_ver_list; bool m_new_ver_list_exist = false; int upgrade_err_code = 0; std::vector firmware_list; @@ -901,14 +373,14 @@ public: bool check_version_valid(); wxString get_upgrade_result_str(int upgrade_err_code); // key: ams_id start as 0,1,2,3 - std::map get_ams_version(); + std::map get_ams_version(); void clear_version_info(); - void store_version_info(const ModuleVersionInfo& info); + void store_version_info(const DevFirmwareVersionInfo& info); /* printing */ std::string print_type; - float nozzle { 0.0f }; // default is 0.0f as initial value + //float nozzle { 0.0f }; // default is 0.0f as initial value bool is_220V_voltage { false }; int mc_print_stage; @@ -918,16 +390,24 @@ public: int mc_print_percent; /* left print progess in percent */ int mc_left_time; /* left time in seconds */ int last_mc_print_stage; - int home_flag; + int m_home_flag = 0; int hw_switch_state; bool is_system_printing(); + int print_error; + static std::string get_error_code_str(int error_code); + std::string get_print_error_str() const { return MachineObject::get_error_code_str(this->print_error); } + + std::unordered_set m_command_error_code_dlgs; + void add_command_error_code_dlg(int command_err); + int curr_layer = 0; int total_layers = 0; bool is_support_layer_num { false }; bool nozzle_blob_detection_enabled{ false }; time_t nozzle_blob_detection_hold_start = 0; + bool is_support_new_auto_cali_method{false}; int last_cali_version = -1; int cali_version = -1; float cali_selected_nozzle_dia { 0.0 }; @@ -976,28 +456,23 @@ public: bool is_filament_at_extruder(); wxString get_curr_stage(); - // return curr stage index of stage list int get_curr_stage_idx(); + bool is_in_calibration(); bool is_calibration_running(); bool is_calibration_done(); void parse_state_changed_event(); - void parse_status(int flag); + void parse_home_flag(int flag); /* printing status */ std::string print_status; /* enum string: FINISH, SLICING, RUNNING, PAUSE, INIT, FAILED */ int queue_number = 0; std::string iot_print_status; /* iot */ - PrintingSpeedLevel printing_speed_lvl; int printing_speed_mag = 100; - PrintingSpeedLevel _parse_printing_speed_lvl(int lvl); int get_bed_temperature_limit(); bool is_filament_installed(); - /*stat*/ - bool m_lamp_close_recheck = false; - /* camera */ bool has_ipcam { false }; bool camera_recording { false }; @@ -1059,9 +534,6 @@ public: bool file_model_download{false}; bool virtual_camera{false}; - 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}; @@ -1084,35 +556,25 @@ public: time_t xcam_auto_recovery_hold_start = 0; time_t xcam_prompt_sound_hold_start = 0; time_t xcam_filament_tangle_detect_hold_start = 0; - 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; + int targ_nozzle_id_from_pc = INVALID_EXTRUDER_ID; //supported features - bool is_support_chamber_edit{false}; - 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};// the lidar calibration for 3D Studio bool is_support_build_plate_marker_detect{false}; PlateMakerDectect m_plate_maker_detect_type{ POS_CHECK }; + /*PA flow calibration is using in sending print*/ bool is_support_pa_calibration{false}; bool is_support_flow_calibration{false}; - bool is_support_auto_flow_calibration{false};/*The flag is used to distinguish auto/on/off or on/off */ - bool is_support_print_without_sd{false}; - bool is_support_print_all{false}; + bool is_support_send_to_sdcard {false}; - bool is_support_aux_fan {false}; - bool is_support_chamber_fan{false}; + bool is_support_filament_backup{false}; - bool is_support_show_filament_backup{false};/*the filament is not supported shown in some previous hardware*/ bool is_support_timelapse{false}; bool is_support_update_remain{false}; int is_support_bed_leveling = 0;/*0: false; 1; on/off 2: auto/on/off*/ @@ -1126,18 +588,15 @@ public: bool is_support_mqtt_alive {false}; bool is_support_tunnel_mqtt{false}; bool is_support_motor_noise_cali{false}; - bool is_support_nozzle_offset_cali{ false }; - bool is_support_high_tempbed_cali{ false }; bool is_support_wait_sending_finish{false}; bool is_support_user_preset{false}; - //bool is_support_p1s_plus{false}; bool is_support_nozzle_blob_detection{false}; bool is_support_air_print_detection{false}; bool is_support_agora{false}; bool is_support_upgrade_kit{false}; bool is_support_filament_setting_inprinting{false}; bool is_support_internal_timelapse { false };// fun[28], support timelapse without SD card - bool is_support_command_homing { false };// fun[32] + bool m_support_mqtt_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}; @@ -1157,12 +616,7 @@ public: /*temp temp range*/ std::vector bed_temp_range; - /* sdcard */ - MachineObject::SdcardState sdcard_state { NO_SDCARD }; - MachineObject::SdcardState get_sdcard_state(); - /* HMS */ - std::vector hms_list; /* machine mqtt apis */ int connect(bool use_openssl = true); @@ -1185,7 +639,6 @@ public: int jobState_ = 0; /* key: sequence id, value: callback */ - std::map m_callback_list; bool is_makeworld_subtask(); @@ -1198,7 +651,7 @@ public: int gcode_file_prepare_percent = 0; QDTSubTask* subtask_; QDTModelTask *model_task { nullptr }; - RatingInfo* rating_info { nullptr }; + DevPrintTaskRatingInfo* rating_info { nullptr }; int request_model_result = 0; bool get_model_mall_result_need_retry = false; @@ -1218,7 +671,6 @@ public: MachineObject(std::string name); MachineObject(std::string name, std::string url, std::string ip, std::string apikey = ""); MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip); - ~MachineObject(); std::string parse_version(); void parse_version_func(); @@ -1232,10 +684,10 @@ public: int command_request_push_all(bool request_now = false); int command_pushing(std::string cmd); int command_clean_print_error(std::string task_id, int print_error); + int command_clean_print_error_uiop(int print_error); int command_set_printer_nozzle(std::string nozzle_type, float diameter); int command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter); int command_get_access_code(); - int command_select_extruder(int id); /* command upgrade */ int command_upgrade_confirm(); @@ -1247,10 +699,7 @@ public: int command_xyz_abs(); int command_auto_leveling(); int command_go_home(); - 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, int submode, const CommandCallBack& cb); + int command_task_abort(); /* cancelled the job_id */ int command_task_partskip(std::vector part_ids); @@ -1284,15 +733,13 @@ public: int command_ams_refresh_rfid(std::string tray_id); int command_ams_refresh_rfid2(int ams_id, int slot_id); int command_ams_control(std::string action); - int command_set_chamber_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); - int command_set_chamber_light2(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); - int command_set_work_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); + int command_ams_drying_stop(); int command_start_extrusion_cali(int tray_index, int nozzle_temp, int bed_temp, float max_volumetric_speed, std::string setting_id = ""); int command_stop_extrusion_cali(); int command_extrusion_cali_set(int tray_index, std::string setting_id, std::string name, float k, float n, int bed_temp = -1, int nozzle_temp = -1, float max_volumetric_speed = -1); // set printing speed - int command_set_printing_speed(PrintingSpeedLevel lvl); + int command_set_printing_speed(DevPrintingSpeedLevel lvl); //set prompt sound int command_set_prompt_sound(bool prompt_sound); @@ -1351,7 +798,7 @@ public: int command_xcam_control_filament_tangle_detect(bool on_off); /* common apis */ - inline bool is_local() { return !dev_ip.empty(); } + inline bool is_local() { return !get_dev_ip().empty(); } void set_bind_status(std::string status); std::string get_bind_str(); bool can_print(); @@ -1374,6 +821,7 @@ public: void set_online_state(bool on_off); bool is_online() { return m_is_online; } bool is_info_ready(bool check_version = true) const; + bool is_security_control_ready() const; bool is_camera_busy_off(); std::vector get_resolution_supported(); @@ -1387,8 +835,9 @@ public: 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); int publish_gcode(std::string gcode_str); + void update_device_cert_state(bool ready); - std::string setting_id_to_type(std::string setting_id, std::string tray_type); + static std::string setting_id_to_type(std::string setting_id, std::string tray_type); QDTSubTask* get_subtask(); QDTModelTask* get_modeltask(); void set_modeltask(QDTModelTask* task); @@ -1402,36 +851,22 @@ public: bool m_firmware_thread_started { false }; void get_firmware_info(); bool is_firmware_info_valid(); - std::string get_string_from_fantype(int type); - - /*for local mqtt tunnel try*/ - bool nt_try_local_tunnel { false }; - bool nt_use_local_tunnel { false }; - int nt_cloud_full_msg_count { 0 }; - int nt_local_full_msg_count { 0 }; - void nt_condition_local_tunnel(); - void nt_restore_cloud_tunnel(); - void nt_reset_data(); /*for more extruder*/ bool is_enable_np{ false }; bool is_enable_ams_np{ false }; - ExtderData m_extder_data; - NozzleData m_nozzle_data; - /*vi slot data*/ - std::vector vt_slot; - AmsTray parse_vt_tray(json vtray); + std::vector vt_slot; + DevAmsTray parse_vt_tray(json vtray); /*get ams slot info*/ bool contains_tray(const std::string &ams_id, const std::string &tray_id) const; - AmsTray get_tray(const std::string &ams_id, const std::string &tray_id) const;/*use contains_tray() check first*/ + DevAmsTray get_tray(const std::string &ams_id, const std::string &tray_id) const;/*use contains_tray() check first*/ /*for parse new info*/ bool check_enable_np(const json& print) const; void parse_new_info(json print); - bool is_nozzle_data_invalid(); int get_flag_bits(std::string str, int start, int count = 1) const; int get_flag_bits(int num, int start, int count = 1, int base = 10) const; @@ -1447,7 +882,7 @@ public: void update_printer_preset_name(); void check_ams_filament_valid(); - int command_handle_response(const json &response); + /* xcam door open check*/ bool support_door_open_check() const { return is_support_door_open_check;}; @@ -1455,7 +890,6 @@ public: void command_set_door_open_check(DoorOpenCheckState state); /* xcam save remove print file to local*/ - bool support_save_remote_print_file_to_storage() const { return is_support_save_remote_print_file_to_storage; }; bool get_save_remote_print_file_to_storage() const { return xcam__save_remote_print_file_to_storage; }; void command_set_save_remote_print_file_to_storage(bool save); @@ -1467,193 +901,14 @@ private: time_t xcam_door_open_check_start_time = 0; /* xcam save remove print file to local*/ - bool is_support_save_remote_print_file_to_storage = false; bool xcam__save_remote_print_file_to_storage = false; time_t xcam__save_remote_print_file_to_storage_start_time = 0; }; -class DeviceManagerRefresher; -class DeviceManager -{ -private: - NetworkAgent* m_agent { nullptr }; - DeviceManagerRefresher* m_refresher{nullptr}; - -public: - static bool EnableMultiMachine; - - DeviceManager(NetworkAgent* agent = nullptr); - ~DeviceManager(); - NetworkAgent *get_agent() const{ return m_agent; } - void set_agent(NetworkAgent* agent); - - std::mutex listMutex; - std::string selected_machine; /* dev_id */ - std::string local_selected_machine; /* dev_id */ - std::map localMachineList; /* dev_id -> MachineObject*, localMachine SSDP */ - std::map userMachineList; /* dev_id -> MachineObject* cloudMachine of User */ - - void start_refresher(); - void stop_refresher(); - - void keep_alive(); - void check_pushing(); - - static float nozzle_diameter_conver(int diame); - static int nozzle_diameter_conver(float diame); - static std::string nozzle_type_conver(int type); - static int nozzle_type_conver(std::string& type); - - MachineObject* get_default_machine(); - MachineObject* get_local_selected_machine(); - MachineObject* get_local_machine(std::string dev_id); - MachineObject* get_user_machine(std::string dev_id); - MachineObject* get_my_machine(std::string dev_id); - void erase_user_machine(std::string dev_id); - void clean_user_info(); - void reload_printer_settings(); - - bool set_selected_machine(std::string dev_id, bool need_disconnect = false); - MachineObject* get_selected_machine(); - - void subscribe_device_list(std::vector dev_list); - - /* return machine has access code and user machine if login*/ - std::map get_my_machine_list(); - std::map get_my_cloud_machine_list(); - std::string get_first_online_user_machine(); - void modify_device_name(std::string dev_id, std::string dev_name); - void update_user_machine_list_info(); - void parse_user_print_info(std::string body); - - /* create machine or update machine properties */ - void on_machine_alive(std::string json_str); - MachineObject* insert_local_device(std::string dev_name, std::string dev_id, std::string dev_ip, std::string connection_type, std::string bind_state, std::string version, std::string access_code); - /* disconnect all machine connections */ - void disconnect_all(); - int query_bind_status(std::string &msg); - - // get alive machine - std::map get_local_machine_list(); - void load_last_machine(); - - std::vector subscribe_list_cache; - - static void set_key_field_parsing(bool enable) { DeviceManager::key_field_only = enable; } - - static bool key_field_only; - static json function_table; - static json filaments_blacklist; - static json filaments_printable_blacklist; - - template - static T get_value_from_config(std::string type_str, std::string item){ - 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(item)) { - return printer[item].get(); - } - } - } - } - catch (...) {} - 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); - static std::string get_printer_ams_type(std::string type_str); - static std::string get_printer_series(std::string type_str); - static std::string get_printer_diagram_img(std::string type_str); - static std::string get_printer_ams_img(std::string type_str); - static std::string get_printer_ext_img(std::string type_str, int pos); - static PrinterArch get_printer_arch(std::string type_str); - static std::string get_ftp_folder(std::string type_str); - 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); - static std::string get_filament_name_from_ams(int ams_id, int slot_id); - -private: - void OnMachineBindStateChanged(MachineObject* obj, const std::string &new_state); - void OnSelectedMachineLost(); -}; - -class DeviceManagerRefresher : public wxObject -{ - wxTimer *m_timer{nullptr}; - int m_timer_interval_msec = 1000; - - DeviceManager *m_manager{nullptr}; - -public: - DeviceManagerRefresher(DeviceManager* manger); - ~DeviceManagerRefresher(); - -public: - void Start() { m_timer->Start(m_timer_interval_msec); } - void Stop() { m_timer->Stop(); } - -protected: - virtual void on_timer(wxTimerEvent &event); -}; - // change the opacity void change_the_opacity(wxColour& colour); - -wxString generate_nozzle_id(NozzleVolumeType nozzle_type); - - -class JsonValParser -{ -public: - static std::string get_longlong_val(const json& j); -}; +wxString get_stage_string(int stage); }; // namespace Slic3r diff --git a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp index c075485..b752d3c 100644 --- a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp +++ b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp @@ -1,6 +1,6 @@ //**********************************************************/ /* File: uiAmsHumidityPopup.cpp -* Description: The popup with Ams Humidity +* Description: The popup with DevAms Humidity * * \n class uiAmsHumidityPopup //**********************************************************/ @@ -43,7 +43,7 @@ void uiAmsPercentHumidityDryPopup::Create() title->SetFont(Label::Head_18); title_sizer->AddStretchSpacer(); - title_sizer->Add(title, 0, wxALIGN_CENTER_HORIZONTAL); + title_sizer->Add(title, 0); title_sizer->AddStretchSpacer(); // create humidity image diff --git a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h index 7fd5a98..ad000fb 100644 --- a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h +++ b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h @@ -6,6 +6,7 @@ //**********************************************************/ #pragma once +#include "slic3r/GUI/Widgets/AMSItem.hpp" #include "slic3r/GUI/Widgets/Label.hpp" #include "slic3r/GUI/Widgets/PopupWindow.hpp" @@ -19,14 +20,15 @@ namespace Slic3r { namespace GUI { struct uiAmsHumidityInfo { std::string ams_id; - int humidity_level = -1; + AMSModel ams_type; + int humidity_display_idx = -1; int humidity_percent = -1; float current_temperature; int left_dry_time = -1; }; /// -/// Note: The popup of Ams Humidity with percentage and dry time +/// Note: The popup of DevAms Humidity with percentage and dry time /// Author: xin.zhang /// class uiAmsPercentHumidityDryPopup : public wxDialog @@ -36,7 +38,7 @@ public: ~uiAmsPercentHumidityDryPopup() = default; public: - void Update(uiAmsHumidityInfo *info) { m_ams_id = info->ams_id; Update(info->humidity_level, info->humidity_percent, info->left_dry_time, info->current_temperature); }; + void Update(uiAmsHumidityInfo *info) { m_ams_id = info->ams_id; Update(info->humidity_display_idx, info->humidity_percent, info->left_dry_time, info->current_temperature); }; std::string get_owner_ams_id() const { return m_ams_id; } diff --git a/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp b/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp index 3d0feac..6232fe7 100644 --- a/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp +++ b/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.cpp @@ -28,7 +28,7 @@ uiDeviceUpdateVersion::uiDeviceUpdateVersion(wxWindow* parent, CreateWidgets(); } -void uiDeviceUpdateVersion::UpdateInfo(const MachineObject::ModuleVersionInfo& info) +void uiDeviceUpdateVersion::UpdateInfo(const DevFirmwareVersionInfo& info) { SetName(I18N::translate(info.product_name)); SetSerial(info.sn); @@ -71,33 +71,40 @@ void uiDeviceUpdateVersion::CreateWidgets() wxStaticText* serial_text = new wxStaticText(this, wxID_ANY, _L(SERIAL_STR)); wxStaticText* version_text = new wxStaticText(this, wxID_ANY, _L(VERSION_STR)); - // The main sizer - wxFlexGridSizer* main_sizer = new wxFlexGridSizer(3, 3, 0, 0); - main_sizer->AddGrowableCol(1); - main_sizer->SetFlexibleDirection(wxHORIZONTAL); - main_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + // Use bold font + wxFont font = this->GetFont(); + font.SetWeight(wxFONTWEIGHT_BOLD); + m_dev_name->SetFont(font); + serial_text->SetFont(font); + version_text->SetFont(font); - main_sizer->Add(m_dev_name, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); - main_sizer->Add(0, 0, wxALL, wxEXPAND); - main_sizer->Add(0, 0, wxALL, wxEXPAND); + // The grid sizer + wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, 3, 0, 0); + //grid_sizer->AddGrowableCol(1); + grid_sizer->SetFlexibleDirection(wxHORIZONTAL); + grid_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); - main_sizer->Add(serial_text, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); - main_sizer->Add(m_dev_snl, 0, wxALIGN_LEFT | wxALL, FromDIP(5)); - main_sizer->Add(0, 0, wxALL, wxEXPAND); + grid_sizer->Add(serial_text, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); + grid_sizer->Add(m_dev_snl, 0, wxALIGN_LEFT | wxALL, FromDIP(5)); + grid_sizer->Add(0, 0, wxALL, wxEXPAND); m_dev_upgrade_indicator = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(5), FromDIP(5))); m_dev_upgrade_indicator->SetBitmap(ScalableBitmap(this, "monitor_upgrade_online", 5).bmp()); wxBoxSizer* version_hsizer = new wxBoxSizer(wxHORIZONTAL); - version_hsizer->Add(m_dev_upgrade_indicator, 0, wxALIGN_CENTER_VERTICAL); - version_hsizer->AddSpacer(FromDIP(5)); - version_hsizer->Add(version_text, 0); + version_hsizer->Add(m_dev_upgrade_indicator, 0, wxALL, FromDIP(5)); + version_hsizer->Add(version_text, 0, wxLEFT | wxBOTTOM|wxALIGN_RIGHT, FromDIP(5)); - main_sizer->Add(version_hsizer, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); - main_sizer->Add(m_dev_version, 0, wxALIGN_LEFT | wxALL, FromDIP(5)); - main_sizer->Add(0, 0, wxALL, wxEXPAND); + grid_sizer->Add(version_hsizer, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); + grid_sizer->Add(m_dev_version, 0, wxALIGN_LEFT | wxALL, FromDIP(5)); + grid_sizer->Add(0, 0, wxALL, wxEXPAND); // Updating + wxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->AddSpacer(FromDIP(20)); + main_sizer->Add(m_dev_name, 0, wxALIGN_LEFT | wxALL, FromDIP(5)); + main_sizer->Add(grid_sizer, 0, wxALIGN_LEFT, FromDIP(5)); + SetSizer(main_sizer); Layout(); } \ No newline at end of file diff --git a/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h b/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h index a4ffc52..100280d 100644 --- a/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h +++ b/src/slic3r/GUI/DeviceTab/uiDeviceUpdateVersion.h @@ -29,7 +29,7 @@ public: ~uiDeviceUpdateVersion() = default; public: - void UpdateInfo(const MachineObject::ModuleVersionInfo& info); + void UpdateInfo(const DevFirmwareVersionInfo& info); private: void CreateWidgets(); diff --git a/src/slic3r/GUI/EncodedFilament.hpp b/src/slic3r/GUI/EncodedFilament.hpp index d65b000..020ea96 100644 --- a/src/slic3r/GUI/EncodedFilament.hpp +++ b/src/slic3r/GUI/EncodedFilament.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include diff --git a/src/slic3r/GUI/FilamentBitmapUtils.cpp b/src/slic3r/GUI/FilamentBitmapUtils.cpp index 4f4b9f8..5e1cbcc 100644 --- a/src/slic3r/GUI/FilamentBitmapUtils.cpp +++ b/src/slic3r/GUI/FilamentBitmapUtils.cpp @@ -4,6 +4,7 @@ #include #include "EncodedFilament.hpp" +#include "GUI_App.hpp" namespace Slic3r { namespace GUI { @@ -12,7 +13,11 @@ struct BitmapDC { wxBitmap bitmap; wxMemoryDC dc; - BitmapDC(const wxSize& size) : bitmap(size), dc(bitmap) { + BitmapDC(const wxSize& size) : bitmap(size){ +#ifdef __WXOSX__ + bitmap.UseAlpha(); +#endif + dc.SelectObject(bitmap); // Don't set white background - let the color patterns fill the entire area dc.SetPen(*wxTRANSPARENT_PEN); } @@ -22,6 +27,51 @@ static BitmapDC init_bitmap_dc(const wxSize& size) { return BitmapDC(size); } +// Check if a color is transparent (alpha == 0) +static bool is_transparent_color(const wxColour& color) { + return color.Alpha() == 0; +} + +// Create transparent bitmap +static wxBitmap create_transparent_bitmap(const wxSize& size) { + BitmapDC bdc = init_bitmap_dc(size); + if (!bdc.dc.IsOk()) return wxNullBitmap; + + // Create checkerboard pattern + wxColour light_gray(217, 217, 217); // #D9D9D9 + wxColour white(255, 255, 255); + + bool is_dark_mode = wxGetApp().dark_mode(); + + // Calculate parameters based on mode + int start_pos = is_dark_mode ? 0 : 1; + int end_width = is_dark_mode ? size.GetWidth() : size.GetWidth() - 1; + int end_height = is_dark_mode ? size.GetHeight() : size.GetHeight() - 1; + int square_size = std::max(6, std::min(end_width - start_pos, end_height - start_pos) / 8); + + // Draw checkerboard + for (int x = start_pos; x < end_width; x += square_size) { + for (int y = start_pos; y < end_height; y += square_size) { + bool is_light = ((x / square_size) + (y / square_size)) % 2 == 0; + bdc.dc.SetBrush(wxBrush(is_light ? white : light_gray)); + + int width = std::min(square_size, size.GetWidth() - x); + int height = std::min(square_size, size.GetHeight() - y); + bdc.dc.DrawRectangle(x, y, width, height); + } + } + + // Add border only in light mode + if (!is_dark_mode) { + bdc.dc.SetPen(wxPen(wxColour(130, 130, 128), 1, wxPENSTYLE_SOLID)); + bdc.dc.SetBrush(*wxTRANSPARENT_BRUSH); + bdc.dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); + } + + bdc.dc.SelectObject(wxNullBitmap); + return bdc.bitmap; +} + // 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; @@ -37,15 +87,30 @@ static void sort_colors_by_hsv(std::vector& colors) { static wxBitmap create_single_filament_bitmap(const wxColour& color, const wxSize& size) { + // Check if color is transparent + if (is_transparent_color(color)) { + return create_transparent_bitmap(size); + } + BitmapDC bdc = init_bitmap_dc(size); if (!bdc.dc.IsOk()) return wxNullBitmap; + bdc.dc.SetBackground(wxBrush(color)); + bdc.dc.Clear(); + 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); + // Add gray border for light colors (similar to wxExtensions.cpp logic) - only in light mode + if (!wxGetApp().dark_mode() && color.Red() > 224 && color.Blue() > 224 && color.Green() > 224) { + bdc.dc.SetPen(wxPen(wxColour(130, 130, 128), 1, wxPENSTYLE_SOLID)); + bdc.dc.SetBrush(*wxTRANSPARENT_BRUSH); + bdc.dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); + } + + // Add white border for dark colors - only in dark mode + if(wxGetApp().dark_mode() && color.Red() < 45 && color.Blue() < 45 && color.Green() < 45) { + bdc.dc.SetPen(wxPen(wxColour(207, 207, 207), 1, wxPENSTYLE_SOLID)); bdc.dc.SetBrush(*wxTRANSPARENT_BRUSH); bdc.dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); } diff --git a/src/slic3r/GUI/FilamentGroupPopup.cpp b/src/slic3r/GUI/FilamentGroupPopup.cpp index cbf746a..588059a 100644 --- a/src/slic3r/GUI/FilamentGroupPopup.cpp +++ b/src/slic3r/GUI/FilamentGroupPopup.cpp @@ -160,7 +160,7 @@ FilamentGroupPopup::FilamentGroupPopup(wxWindow *parent) : PopupWindow(parent, w detail_infos[idx]->Wrap(FromDIP(320)); label_sizer->AddSpacer(radio_btns[idx]->GetRect().width + ratio_spacing); - label_sizer->Add(detail_infos[idx], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL); + label_sizer->Add(detail_infos[idx], 1, wxALIGN_CENTER_VERTICAL); top_sizer->Add(button_sizer, 0, wxLEFT | wxRIGHT, horizontal_margin); top_sizer->Add(label_sizer, 0, wxLEFT | wxRIGHT, horizontal_margin); diff --git a/src/slic3r/GUI/FilamentPickerDialog.cpp b/src/slic3r/GUI/FilamentPickerDialog.cpp index e8aeec4..756e931 100644 --- a/src/slic3r/GUI/FilamentPickerDialog.cpp +++ b/src/slic3r/GUI/FilamentPickerDialog.cpp @@ -13,6 +13,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + #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)) @@ -37,6 +41,21 @@ void FilamentPickerDialog::on_dpi_changed(const wxRect &suggested_rect) Layout(); } +// Flash effect implementation +void FilamentPickerDialog::StartFlashing() +{ + // Stop any existing flash timer + if (m_flash_timer) { + m_flash_timer->Stop(); + delete m_flash_timer; + } + + m_flash_timer = new wxTimer(this, wxID_ANY + 1); + Bind(wxEVT_TIMER, &FilamentPickerDialog::OnFlashTimer, this, m_flash_timer->GetId()); + m_flash_step = 0; + m_flash_timer->Start(50); +} + FilamentPickerDialog::FilamentPickerDialog(wxWindow *parent, const wxString& fila_id, const FilamentColor& fila_color, const std::string& fila_type) : DPIDialog(parent ? parent : wxGetApp().mainframe, wxID_ANY, @@ -118,10 +137,16 @@ FilamentPickerDialog::FilamentPickerDialog(wxWindow *parent, const wxString& fil // Set window transparency SetTransparent(255); BindEvents(); + + // Start click detection timer for outside click detection + StartClickDetection(); } FilamentPickerDialog::~FilamentPickerDialog() { + // Clean up all timers + CleanupTimers(); + delete m_color_query; m_color_query = nullptr; @@ -585,19 +610,12 @@ wxColourData FilamentPickerDialog::GetSingleColorData() void FilamentPickerDialog::BindEvents() { - // Bind mouse events + // Bind mouse events for window dragging 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(); - }); - + // Essential window events Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) { if (HasCapture()) { ReleaseMouse(); @@ -608,9 +626,15 @@ void FilamentPickerDialog::BindEvents() // Bind more colors button event if (m_more_btn) { m_more_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + // Pause click detection while color picker is open + StopClickDetection(); + wxColourData original_data = GetSingleColorData(); wxColourData result = show_sys_picker_dialog(this, original_data); + // Resume click detection after color picker closes + StartClickDetection(); + // Check if user actually selected a different color if (result.GetColour() != original_data.GetColour()) { wxColour selected_color = result.GetColour(); @@ -729,5 +753,132 @@ void FilamentPickerDialog::OnButtonPaint(wxPaintEvent& event) dc.DrawRectangle(1, 1, COLOR_BTN_SIZE.GetWidth() - 1, COLOR_BTN_SIZE.GetHeight() - 1); } +bool FilamentPickerDialog::IsClickOnTopMostWindow(const wxPoint& mouse_pos) +{ + wxWindow* main_window = wxGetApp().mainframe; + if (!main_window) { + return false; + } + + wxRect main_rect = main_window->GetScreenRect(); + bool in_main_app = main_rect.Contains(mouse_pos); + + if (!in_main_app) { + return false; + } + +#ifdef _WIN32 + // Windows: Use WindowFromPoint to check actual topmost window + POINT pt = {mouse_pos.x, mouse_pos.y}; + HWND hwnd_at_point = WindowFromPoint(pt); + HWND main_hwnd = (HWND)main_window->GetHandle(); + + // Check if clicked window belongs to our main window hierarchy + HWND parent_hwnd = hwnd_at_point; + while (parent_hwnd != NULL) { + if (parent_hwnd == main_hwnd) { + return true; + } + parent_hwnd = ::GetParent(parent_hwnd); + } + return false; + +#elif defined(__WXOSX__) + // macOS: Use focus and active window check + return (wxGetActiveWindow() == main_window) || main_window->HasFocus(); + +#else + // Linux: Use focus check (similar to macOS) + return (wxGetActiveWindow() == main_window) || main_window->HasFocus(); +#endif +} + +void FilamentPickerDialog::StartClickDetection() +{ + if (m_click_timer) { + StopClickDetection(); + } + + m_click_timer = new wxTimer(this, wxID_ANY); + Bind(wxEVT_TIMER, &FilamentPickerDialog::OnTimerCheck, this, m_click_timer->GetId()); + m_click_timer->Start(50); +} + +void FilamentPickerDialog::StopClickDetection() +{ + if (m_click_timer) { + m_click_timer->Stop(); + delete m_click_timer; + m_click_timer = nullptr; + } +} + +void FilamentPickerDialog::CleanupTimers() +{ + StopClickDetection(); + + if (m_flash_timer) { + m_flash_timer->Stop(); + delete m_flash_timer; + m_flash_timer = nullptr; + } +} + +// Only perform complex detection when the mouse state actually changes +void FilamentPickerDialog::OnTimerCheck(wxTimerEvent& event) +{ + static wxPoint last_mouse_pos(-1, -1); + wxPoint current_pos = wxGetMousePosition(); + + // If the mouse position and button state haven't changed, skip the detection + if (current_pos == last_mouse_pos && + wxGetMouseState().LeftIsDown() == m_last_mouse_down) { + return; + } + + last_mouse_pos = current_pos; + + wxPoint mouse_pos = wxGetMousePosition(); + wxRect window_rect = GetScreenRect(); + + // Check if mouse button state changed + bool mouse_down = wxGetMouseState().LeftIsDown(); + + if (mouse_down != m_last_mouse_down) { + if (mouse_down) { + bool in_dialog = window_rect.Contains(mouse_pos); + bool is_valid_click = IsClickOnTopMostWindow(mouse_pos); + + if (is_valid_click && !in_dialog) { + StartFlashing(); + } + } + + m_last_mouse_down = mouse_down; + } +} + +void FilamentPickerDialog::OnFlashTimer(wxTimerEvent& event) +{ + // 5 flashes = 10 steps (semi-transparent -> opaque for each flash) + if (m_flash_step < 10) { + if (m_flash_step % 2 == 0) { + // Even steps: semi-transparent + SetTransparent(120); + } else { + // Odd steps: opaque + SetTransparent(255); + } + + m_flash_step++; + } else { + // Complete flash sequence + SetTransparent(255); + m_flash_timer->Stop(); + delete m_flash_timer; + m_flash_timer = nullptr; + } +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/FilamentPickerDialog.hpp b/src/slic3r/GUI/FilamentPickerDialog.hpp index 89c934e..c17875c 100644 --- a/src/slic3r/GUI/FilamentPickerDialog.hpp +++ b/src/slic3r/GUI/FilamentPickerDialog.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,14 @@ protected: void OnMouseMove(wxMouseEvent& event); void OnMouseLeftUp(wxMouseEvent& event); void OnButtonPaint(wxPaintEvent& event); + void OnTimerCheck(wxTimerEvent& event); + void OnFlashTimer(wxTimerEvent& event); + + // Platform-independent window detection + bool IsClickOnTopMostWindow(const wxPoint& mouse_pos); + void StartClickDetection(); + void StopClickDetection(); + void CleanupTimers(); private: // UI creation methods @@ -67,6 +76,9 @@ private: bool LoadFilamentData(const wxString& fila_id); wxColourData GetSingleColorData(); + // Flash effect + void StartFlashing(); + // UI elements wxStaticBitmap* m_color_demo{nullptr}; wxStaticText* m_label_preview_color{nullptr}; @@ -90,6 +102,14 @@ private: // Mouse drag members wxPoint m_drag_delta; + + // Click detection timers + wxTimer* m_click_timer{nullptr}; + bool m_last_mouse_down{false}; + + // Flash effect timer + wxTimer* m_flash_timer{nullptr}; + int m_flash_step{0}; }; }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 234634f..7f6fe80 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -13,6 +13,7 @@ #include "libslic3r/Geometry/ConvexHull.hpp" #include "slic3r/GUI/OpenGLManager.hpp" +#include "../Utils/HelioDragon.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +77,12 @@ static std::string get_view_type_string(GCodeViewer::EViewType view_type) return _u8L("Fan Speed"); else if (view_type == GCodeViewer::EViewType::Temperature) return _u8L("Temperature"); + else if (view_type == GCodeViewer::EViewType::ThermalIndexMin) + return _u8L("Thermal Index (min)"); + else if (view_type == GCodeViewer::EViewType::ThermalIndexMax) + return _u8L("Thermal Index (max)"); + else if (view_type == GCodeViewer::EViewType::ThermalIndexMean) + return _u8L("Thermal Index (mean)"); else if (view_type == GCodeViewer::EViewType::VolumetricRate) return _u8L("Flow"); else if (view_type == GCodeViewer::EViewType::Tool) @@ -86,13 +94,9 @@ static std::string get_view_type_string(GCodeViewer::EViewType view_type) return ""; } -static unsigned char buffer_id(EMoveType type) { - return static_cast(type) - static_cast(EMoveType::Retract); -} +static unsigned char buffer_id(EMoveType type) { return static_cast(type) - static_cast(EMoveType::Retract); } -static EMoveType buffer_type(unsigned char id) { - return static_cast(static_cast(EMoveType::Retract) + id); -} +static EMoveType buffer_type(unsigned char id) { return static_cast(static_cast(EMoveType::Retract) + id); } static std::array decode_color(const std::string& color) { static const float INV_255 = 1.0f / 255.0f; @@ -122,11 +126,10 @@ static std::array decode_color(const std::string& color) { return ret; } -static std::vector> decode_colors(const std::vector& colors) { - std::vector> output(colors.size(), { 0.0f, 0.0f, 0.0f, 1.0f }); - for (size_t i = 0; i < colors.size(); ++i) { - output[i] = decode_color(colors[i]); - } +static std::vector> decode_colors(const std::vector &colors) +{ + std::vector> output(colors.size(), {0.0f, 0.0f, 0.0f, 1.0f}); + for (size_t i = 0; i < colors.size(); ++i) { output[i] = decode_color(colors[i]); } return output; } @@ -134,10 +137,10 @@ static std::vector> decode_colors(const std::vector 0); - constexpr float const scale [5] = { 100.f, 1000.f, 10000.f, 100000.f, 1000000.f }; - constexpr float const invscale [5] = { 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f }; - constexpr float const threshold[5] = { 0.095f, 0.0095f, 0.00095f, 0.000095f, 0.0000095f }; + // assert(value > 0); + constexpr float const scale[5] = {100.f, 1000.f, 10000.f, 100000.f, 1000000.f}; + constexpr float const invscale[5] = {0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f}; + constexpr float const threshold[5] = {0.095f, 0.0095f, 0.00095f, 0.000095f, 0.0000095f}; // Scaling factor, pointer to the tables above. int i = 0; // While the scaling factor is not yet large enough to get two integer digits after scaling and rounding: @@ -210,14 +213,11 @@ void GCodeViewer::IBuffer::reset() count = 0; } -bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move) const +bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex &move) const { - auto matches_percent = [](float value1, float value2, float max_percent) { - return std::abs(value2 - value1) / value1 <= max_percent; - }; + auto matches_percent = [](float value1, float value2, float max_percent) { return std::abs(value2 - value1) / value1 <= max_percent; }; - switch (move.type) - { + switch (move.type) { case EMoveType::Tool_change: case EMoveType::Color_change: case EMoveType::Pause_Print: @@ -228,9 +228,8 @@ bool GCodeViewer::Path::matches(const GCodeProcessorResult::MoveVertex& move) co case EMoveType::Extrude: { // use rounding to reduce the number of generated paths return type == move.type && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id && role == move.extrusion_role && - move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed && - height == round_to_bin(move.height) && width == round_to_bin(move.width) && - matches_percent(volumetric_rate, move.volumetric_rate(), 0.05f) && layer_time == move.layer_duration; + move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed && height == round_to_bin(move.height) && + width == round_to_bin(move.width) && matches_percent(volumetric_rate, move.volumetric_rate(), 0.05f) && layer_time == move.layer_duration; } case EMoveType::Travel: { return type == move.type && feedrate == move.feedrate && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id; @@ -257,71 +256,88 @@ void GCodeViewer::TBuffer::reset() model.reset(); } -void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id) +void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex &move, unsigned int b_id, size_t i_id, size_t s_id) { - Path::Endpoint endpoint = { b_id, i_id, s_id, move.position }; + Path::Endpoint endpoint = {b_id, i_id, s_id, move.position}; // use rounding to reduce the number of generated paths - paths.push_back({ move.type, move.extrusion_role, move.delta_extruder, - round_to_bin(move.height), round_to_bin(move.width), - move.feedrate, move.fan_speed, move.temperature, - move.volumetric_rate(), move.layer_duration, move.extruder_id, move.cp_color_id, { { endpoint, endpoint } } }); + paths.push_back({move.type, + move.extrusion_role, + move.delta_extruder, + round_to_bin(move.height), + round_to_bin(move.width), + move.feedrate, + move.fan_speed, + move.temperature, + move.thermal_index_min, + move.thermal_index_max, + move.thermal_index_mean, + move.volumetric_rate(), + move.layer_duration, + move.extruder_id, + move.cp_color_id, + {{endpoint, endpoint}}}); } -GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value, EType type) const +ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value) const { - float global_t = 0.0f; - const float step = step_size(type); - if (step > 0.0f) { - switch (type) { - default: - case EType::Linear: { - global_t = (value > min) ? (value - min) / step : 0.0f; - break; - } - case EType::Logarithmic: { - global_t = (value > min && min > 0.0f) ? ::log(value / min) / step : 0.0f; - break; - } + // Input value scaled to the colors range + const float step = step_size(); + float _min = min; + if (log_scale) { + value = std::log(value); + _min = std::log(min); + } + if (value > max) { + return range_colors[range_colors.size() -1]; + } + if (value < _min) { + if (value < _min - 0.01f) { + return ColorRGBA::GRAY(); // for helio + } else { + return range_colors[0]; } } - const size_t color_max_idx = Range_Colors.size() - 1; + const float global_t = (step != 0.0f) ? std::max(0.0f, value - _min) / step : 0.0f; // lower limit of 0.0f + + const size_t color_max_idx = range_colors.size() - 1; // Compute the two colors just below (low) and above (high) the input value const size_t color_low_idx = std::clamp(static_cast(global_t), 0, color_max_idx); const size_t color_high_idx = std::clamp(color_low_idx + 1, 0, color_max_idx); - // Compute how far the value is between the low and high colors so that they can be interpolated const float local_t = std::clamp(global_t - static_cast(color_low_idx), 0.0f, 1.0f); // Interpolate between the low and high colors to find exactly which color the input value should get - auto color = lerp(ColorRGBA(Range_Colors[color_low_idx]), ColorRGBA(Range_Colors[color_high_idx]), local_t); - return color.get_data(); + return lerp(range_colors[color_low_idx], range_colors[color_high_idx], local_t); } -float GCodeViewer::Extrusions::Range::step_size(EType type) const { - switch (type) { - default: - case EType::Linear: { - return (max > min) ? (max - min) / (static_cast(Range_Colors.size()) - 1.0f) : 0.0f; - } - case EType::Logarithmic: { - return (max > min && min > 0.0f) ? ::log(max / min) / (static_cast(Range_Colors.size()) - 1.0f) : 0.0f; - } +float GCodeViewer::Extrusions::Range::step_size() const +{ + if (log_scale) { + float min_range = min; + if (min_range == 0) min_range = 0.001f; + return std::log(max / min_range) / get_color_size(); + } else { + return (max - min) / get_color_size(); } } float GCodeViewer::Extrusions::Range::get_value_at_step(int step) const { if (!log_scale) return min + static_cast(step) * step_size(); - else - // calculate log-average + else// calculate log-average { float min_range = min; if (min_range == 0) min_range = 0.0001f; - float step_size = std::log(max / min_range) / (static_cast(Range_Colors.size()) - 1.0f); + float step_size = std::log(max / min_range) / get_color_size(); return std::exp(std::log(min) + static_cast(step) * step_size); } } + +float GCodeViewer::Extrusions::Range::get_color_size() const { + return (static_cast(range_colors.size()) - 1.0f); +} + GCodeViewer::SequentialRangeCap::~SequentialRangeCap() { if (ibo > 0) glsafe(::glDeleteBuffers(1, &ibo)); @@ -415,6 +431,10 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he std::string layer_time = ImGui::ColorMarkerStart + _u8L("Layer Time: ") + ImGui::ColorMarkerEnd; std::string fanspeed = ImGui::ColorMarkerStart + _u8L("Fan Speed: ") + ImGui::ColorMarkerEnd; std::string temperature = ImGui::ColorMarkerStart + _u8L("Temperature: ") + ImGui::ColorMarkerEnd; + std::string thermal_index = ImGui::ColorMarkerStart + _u8L("Thermal Index") + ImGui::ColorMarkerEnd; + std::string min = ImGui::ColorMarkerStart + _u8L("Min: ") + ImGui::ColorMarkerEnd; + std::string max = ImGui::ColorMarkerStart + _u8L("Max: ") + ImGui::ColorMarkerEnd; + std::string mean = ImGui::ColorMarkerStart + _u8L("Mean: ") + ImGui::ColorMarkerEnd; const float item_size = imgui.calc_text_size("X: 000.000 ").x; const float item_spacing = imgui.get_item_spacing().x; const float window_padding = ImGui::GetStyle().WindowPadding.x; @@ -428,8 +448,12 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he // Feedrate and LayerTime shall always show extra text else if (view_type == EViewType::Feedrate || view_type == EViewType::LayerTime) show_extra_text = true; + if (show_extra_text) { + float startx2 = window_padding + item_size + item_spacing; + float startx3 = window_padding + 2 * (item_size + item_spacing); + sprintf(buf, "%s%.3f", x.c_str(), position.x() - plate->get_origin().x()); ImGui::PushItemWidth(item_size); imgui.text(buf); @@ -443,6 +467,12 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he ImGui::PushItemWidth(item_size); imgui.text(buf); + if (view_type == EViewType::ThermalIndexMin || view_type == EViewType::ThermalIndexMax || view_type == EViewType::ThermalIndexMean) { + sprintf(buf, "%s", thermal_index.c_str()); + ImGui::PushItemWidth(item_size); + imgui.text(buf); + } + switch (view_type) { case EViewType::Height: { ImGui::SameLine(window_padding + item_size + item_spacing); @@ -486,6 +516,37 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he imgui.text(buf); break; } + case EViewType::ThermalIndexMin: + case EViewType::ThermalIndexMax: + case EViewType::ThermalIndexMean: + { + if (m_curr_move.thermal_index_min < -100) + sprintf(buf, "%snull", min.c_str()); + else + sprintf(buf, "%s%.1f", min.c_str(), m_curr_move.thermal_index_min); + + ImGui::PushItemWidth(item_size); + imgui.text(buf); + + ImGui::SameLine(startx2); + + if (m_curr_move.thermal_index_max < -100) + sprintf(buf, "%snull", max.c_str()); + else + sprintf(buf, "%s%.1f", max.c_str(), m_curr_move.thermal_index_max); + ImGui::PushItemWidth(item_size); + imgui.text(buf); + + ImGui::SameLine(startx3); + + if (m_curr_move.thermal_index_mean < -100) + sprintf(buf, "%snull", mean.c_str()); + else + sprintf(buf, "%s%.1f", mean.c_str(), m_curr_move.thermal_index_mean); + ImGui::PushItemWidth(item_size); + imgui.text(buf); + break; + } case EViewType::LayerTime:{ ImGui::SameLine(window_padding + item_size + item_spacing); sprintf(buf, "%s%.1f", layer_time.c_str(), m_curr_move.layer_duration); @@ -556,6 +617,80 @@ void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& fil } } +void GCodeViewer::SequentialView::GCodeWindow::render_thermal_index_windows( + std::vector thermal_indexes, float top, float right, float wnd_height, float f_lines_count, uint64_t start_id, uint64_t end_id) const +{ + const float text_height = ImGui::CalcTextSize("0").y; + static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT; + + float previousWindowWidth = right; + + auto place_window = [text_height, thermal_indexes, top, wnd_height, f_lines_count, start_id, end_id](std::string heading, size_t index_id, float right) { + ImGuiWrapper & imgui = *wxGetApp().imgui(); + const ImGuiStyle &style = ImGui::GetStyle(); + imgui.set_next_window_pos(right - 0.4f, top, ImGuiCond_Always, 1.0f, 0.0f); + imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::SetNextWindowBgAlpha(0.8f); + imgui.begin(std::string("Thermal-Index-" + heading), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); + + ImDrawList *draw_list = ImGui::GetWindowDrawList(); + ImVec2 pos_rect = ImGui::GetCursorScreenPos(); + ImVec2 windowPadding = ImGui::GetStyle().WindowPadding; + ImVec2 framePadding = ImGui::GetStyle().FramePadding; + + float textHeight = ImGui::GetTextLineHeight() + 4.0f; + + ImVec2 rectMin = ImVec2(pos_rect.x - windowPadding.x - framePadding.x, pos_rect.y - windowPadding.y - framePadding.y); + + ImVec2 rectMax = ImVec2(pos_rect.x + ImGui::GetContentRegionAvail().x, pos_rect.y + textHeight); + + draw_list->AddRectFilled(rectMin, rectMax, ImGui::GetColorU32(ImVec4(0, 0, 0, 0.3))); + ImGui::SetCursorPosY(0.5f * (wnd_height - f_lines_count * text_height - (f_lines_count - 1.0f) * style.ItemSpacing.y)); + + const float item_size = imgui.calc_text_size_new(std::string_view{"X: 000.000 "}).x; + const float item_spacing = imgui.get_item_spacing().x; + + ImGui::SameLine(0.0f, 0.0f); + + // render text lines + imgui.bold_text(" " + heading); + + char buf[1024]; + for (uint64_t id = start_id; id <= end_id; ++id) { + auto thermal_index = thermal_indexes[id - start_id]; + + ImGui::PushStyleColor(ImGuiCol_Text, LINE_NUMBER_COLOR); + + float ti_value; + + switch (index_id) { + case 0: ti_value = thermal_index.min; break; + case 1: ti_value = thermal_index.max; break; + case 2: ti_value = thermal_index.mean; break; + }; + + if (thermal_index.isNull) + sprintf(buf, "%s ", " null "); + else + sprintf(buf, "%8.2f ", ti_value); + + imgui.text(buf); + ImGui::PopStyleColor(); + } + + float previousWindowWidth = ImGui::GetCurrentWindow()->Pos.x; + imgui.end(); + ImGui::PopStyleVar(); + + return previousWindowWidth; + }; + + previousWindowWidth = place_window("Mean", 2, previousWindowWidth); + previousWindowWidth = place_window("Max", 1, previousWindowWidth); + previousWindowWidth = place_window("Min", 0, previousWindowWidth); +} + //QDS: GUI refactor: move to right void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, float right, uint64_t curr_line_id) const //void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, uint64_t curr_line_id) const @@ -563,22 +698,32 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f auto update_lines = [this](uint64_t start_id, uint64_t end_id) { std::vector ret; ret.reserve(end_id - start_id + 1); + size_t length_of_line = 40; for (uint64_t id = start_id; id <= end_id; ++id) { // read line from file const size_t start = id == 1 ? 0 : m_lines_ends[id - 2]; - const size_t len = m_lines_ends[id - 1] - start; + const size_t original_len = m_lines_ends[id - 1] - start; + const size_t len = std::min(original_len, (size_t) length_of_line); std::string gline(m_file.data() + start, len); - + if (boost::contains(gline, "helio")) { + length_of_line = 90; + m_sequential_view.m_gcode_viewer.set_show_horizontal_slider(true); + } std::string command; std::string parameters; std::string comment; + // If original line is longer than 55 characters, truncate and append "..." + if (original_len > length_of_line) + gline = gline.substr(0, length_of_line - 3) + "..."; + // extract comment std::vector tokens; boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on); command = tokens.front(); - if (tokens.size() > 1) + if (tokens.size() > 1) { comment = ";" + tokens.back(); + } // extract gcode command and parameters if (!command.empty()) { @@ -590,6 +735,10 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f } } } + + boost::trim(command); + boost::trim(parameters); + boost::trim(comment); ret.push_back({ command, parameters, comment }); } return ret; @@ -647,16 +796,42 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f //QDS: GUI refactor: move to right //imgui.set_next_window_pos(0.0f, top, ImGuiCond_Always, 0.0f, 0.0f); imgui.set_next_window_pos(right, top, ImGuiCond_Always, 1.0f, 0.0f); - imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always); + if (m_sequential_view.m_gcode_viewer.is_show_horizontal_slider()) { + auto imgui_window_width = ImGui::CalcTextSize("10000 G1 X191.55 Y166.478 E.07946; helio").x; + imgui.set_next_window_size(imgui_window_width, wnd_height, ImGuiCond_Always); + } else { + imgui.set_next_window_size(0.0f, wnd_height, ImGuiCond_Always); + } ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::SetNextWindowBgAlpha(0.8f); - imgui.begin(std::string("G-code"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); + if (m_sequential_view.m_gcode_viewer.is_show_horizontal_slider()) { + imgui.begin(std::string("G-code"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + } else { + imgui.begin(std::string("G-code"),ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); + } + ImDrawList *draw_list = ImGui::GetWindowDrawList(); + ImVec2 pos_rect = ImGui::GetCursorScreenPos(); + ImVec2 windowPadding = ImGui::GetStyle().WindowPadding; + ImVec2 framePadding = ImGui::GetStyle().FramePadding; + + float textHeight = ImGui::GetTextLineHeight() + 4.0f; + + ImVec2 rectMin = ImVec2(pos_rect.x - windowPadding.x - framePadding.x, pos_rect.y - windowPadding.y - framePadding.y); + + ImVec2 rectMax = ImVec2(pos_rect.x + ImGui::GetContentRegionAvail().x, pos_rect.y + textHeight); + + draw_list->AddRectFilled(rectMin, rectMax, ImGui::GetColorU32(ImVec4(0, 0, 0, 0.3))); // center the text in the window by pushing down the first line const float f_lines_count = static_cast(lines_count); ImGui::SetCursorPosY(0.5f * (wnd_height - f_lines_count * text_height - (f_lines_count - 1.0f) * style.ItemSpacing.y)); + const float window_padding = ImGui::GetStyle().WindowPadding.x; + + ImGui::SameLine(0.0f, 0.0f); + // render text lines + imgui.text("GCode"); for (uint64_t id = start_id; id <= end_id; ++id) { const Line& line = m_lines[id - start_id]; @@ -712,8 +887,37 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, f } } + float gcodeWindowWidth = ImGui::GetCurrentWindow() -> Pos.x; + imgui.end(); ImGui::PopStyleVar(); + + if (m_sequential_view.m_gcode_viewer.is_helio_option()) { + auto get_thermal_index = [this](uint64_t start_id, uint64_t end_id) { + std::vector ret; + ret.reserve(end_id - start_id + 1); + for (uint64_t id = start_id; id <= end_id; ++id) { + // read line from file + const size_t start = id == 1 ? 0 : m_lines_ends[id - 2]; + const size_t len = m_lines_ends[id - 1] - start; + std::string gline(m_file.data() + start, len); + + std::string command, comment; + // extract comment + std::vector tokens; + boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on); + command = tokens.front(); + if (tokens.size() > 1) comment = ";" + tokens.back(); + bool is_helio_gcode{false}; + ret.push_back(GCodeProcessor::parse_helioadditive_comment(comment, is_helio_gcode)); + } + return ret; + }; + + std::vector thermal_indexes = get_thermal_index(start_id, end_id); + + render_thermal_index_windows(thermal_indexes, top, gcodeWindowWidth, wnd_height, f_lines_count, start_id, end_id); + } } void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file() @@ -739,6 +943,10 @@ void GCodeViewer::SequentialView::render(float legend_height, int canvas_width, gcode_window.render(legend_height, (float)canvas_height, (float)canvas_width - (float)right_margin, static_cast(gcode_ids[current.last])); } +Slic3r::GUI::GCodeViewer::SequentialView::SequentialView(const GCodeViewer &outer_viewer) : m_gcode_viewer(outer_viewer) { + +} + const std::vector GCodeViewer::Extrusion_Role_Colors {{ { 0.90f, 0.70f, 0.70f, 1.0f }, // erNone { 1.00f, 0.90f, 0.30f, 1.0f }, // erPerimeter @@ -780,7 +988,7 @@ const std::vector GCodeViewer::Travel_Colors {{ // Normal ranges // blue to red -const std::vector GCodeViewer::Range_Colors{{ +const std::vector GCodeViewer::Range_Colors{{ decode_color_to_float_array("#FF00FF"), // bluish decode_color_to_float_array("#FF55A9"), decode_color_to_float_array("#FE8778"), @@ -793,19 +1001,19 @@ const std::vector GCodeViewer::Range_Colors{{ decode_color_to_float_array("#00FF00") // reddish }}; -//const std::vector GCodeViewer::Range_Colors {{ -// {0.043f, 0.173f, 0.478f, 1.0f}, // bluish -// {0.075f, 0.349f, 0.522f, 1.0f}, -// {0.110f, 0.533f, 0.569f, 1.0f}, -// {0.016f, 0.839f, 0.059f, 1.0f}, -// {0.667f, 0.949f, 0.000f, 1.0f}, -// {0.988f, 0.975f, 0.012f, 1.0f}, -// {0.961f, 0.808f, 0.039f, 1.0f}, -// //{0.890f, 0.533f, 0.125f, 1.0f}, -// {0.820f, 0.408f, 0.188f, 1.0f}, -// {0.761f, 0.322f, 0.235f, 1.0f}, -// {0.581f, 0.149f, 0.087f, 1.0f} // reddish -//}}; +const std::vector GCodeViewer::Thermal_Index_Range_Colors{{ + decode_color_to_float_array("#0b2c7a"), // bluish + decode_color_to_float_array("#005478"), + decode_color_to_float_array("#006f86"), + decode_color_to_float_array("#008e8f"), + decode_color_to_float_array("#00b27c"), + decode_color_to_float_array("#04d70f"), + decode_color_to_float_array("#75b400"), + decode_color_to_float_array("#949100"), + decode_color_to_float_array("#a16c00"), + decode_color_to_float_array("#a04800"), + decode_color_to_float_array("#922616") // reddish +}}; const GCodeViewer::Color GCodeViewer::Wipe_Color = { 1.0f, 1.0f, 0.0f, 1.0f }; @@ -817,8 +1025,13 @@ GCodeViewer::GCodeViewer() m_layers_slider = new IMSlider(0, 0, 0, 100, wxSL_VERTICAL); m_extrusions.reset_role_visibility_flags(); - -// m_sequential_view.skip_invisible_moves = true; + if (GUI::wxGetApp().app_config->get_bool("enable_record_gcodeviewer_option_item")) { + auto back_gcodeviewer_option_item = wxGetApp().app_config->get("gcodeviewer_option_item"); + if (!back_gcodeviewer_option_item.empty()) { + m_last_non_helio_option_item = std::atoi(back_gcodeviewer_option_item.c_str()); + } + } + // m_sequential_view.skip_invisible_moves = true; } GCodeViewer::~GCodeViewer() @@ -834,6 +1047,38 @@ GCodeViewer::~GCodeViewer() } } +bool Slic3r::GUI::GCodeViewer::is_show_horizontal_slider() const { + return m_show_horizontal_slider; +} + +bool GCodeViewer::is_helio_option() const +{ + if (m_view_type == EViewType::ThermalIndexMin || + m_view_type == EViewType::ThermalIndexMax || + m_view_type == EViewType::ThermalIndexMean) + return true; + return false; +} + +bool GCodeViewer::curr_plate_has_ok_helio_slice(int plate_idx) const +{ + if (m_helio_slice_map_oks.find(plate_idx) != m_helio_slice_map_oks.end() && m_helio_slice_map_oks.at(plate_idx)) { + return true; + } + return false; +} + +void GCodeViewer::update_option_item_when_load_gcode() +{ + auto curr_plate_index = wxGetApp().plater()->get_partplate_list().get_curr_plate_index(); + if (curr_plate_has_ok_helio_slice(curr_plate_index)) { + update_thermal_options(true); + } else { + update_thermal_options(false); + update_default_view_type(); + } +} + void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle) { if (m_gl_data_initialized) @@ -925,18 +1170,30 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle) if (preset_bundle) m_nozzle_nums = preset_bundle->get_printer_extruder_count(); + init_thermal_icons(); // set to color print by default if use multi extruders - if (m_nozzle_nums > 1) { - m_view_type_sel = std::distance(view_type_items.begin(),std::find(view_type_items.begin(), view_type_items.end(), EViewType::Summary)); - set_view_type(EViewType::Summary); - } else { - m_view_type_sel = std::distance(view_type_items.begin(),std::find(view_type_items.begin(), view_type_items.end(), EViewType::ColorPrint)); - set_view_type(EViewType::ColorPrint); - } + update_default_view_type(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": finished"); } -void GCodeViewer::on_change_color_mode(bool is_dark) { +void GCodeViewer::update_default_view_type() +{ + if (view_type_items.empty()) { return; } + if (m_last_non_helio_option_item >= (int)view_type_items.size()) { return; } + EViewType cur_type = m_nozzle_nums > 1 ? EViewType::Summary : EViewType::ColorPrint; + if (m_last_non_helio_option_item < 0) {//not set + m_view_type_sel = std::distance(view_type_items.begin(), std::find(view_type_items.begin(), view_type_items.end(), cur_type)); + m_last_non_helio_option_item = m_view_type_sel; + record_record_gcodeviewer_option_item(); + } else { + m_view_type_sel = m_last_non_helio_option_item; + cur_type = view_type_items[m_view_type_sel]; + } + set_view_type(cur_type); +} + +void GCodeViewer::on_change_color_mode(bool is_dark) +{ m_is_dark = is_dark; m_sequential_view.marker.on_change_color_mode(m_is_dark); m_sequential_view.gcode_window.on_change_color_mode(m_is_dark); @@ -954,9 +1211,8 @@ void GCodeViewer::set_scale(float scale) void GCodeViewer::update_by_mode(ConfigOptionMode mode) { view_type_items.clear(); - view_type_items_str.clear(); + view_type_image_names.clear(); options_items.clear(); - // QDS initialzed view_type items view_type_items.push_back(EViewType::Summary); view_type_items.push_back(EViewType::FeatureType); @@ -968,17 +1224,14 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode) view_type_items.push_back(EViewType::LayerTime); view_type_items.push_back(EViewType::FanSpeed); view_type_items.push_back(EViewType::Temperature); - //if (mode == ConfigOptionMode::comDevelop) { - // view_type_items.push_back(EViewType::Tool); - //} - for (int i = 0; i < view_type_items.size(); i++) { - view_type_items_str.push_back(get_view_type_string(view_type_items[i])); + if (view_type_items[i] == EViewType::FilamentId) { + continue; + } + ImageName temp = {get_view_type_string(view_type_items[i]), nullptr, nullptr}; + view_type_image_names.push_back(temp); } - - // QDS for first layer inspection - view_type_items.push_back(EViewType::FilamentId); - + view_type_items.push_back(EViewType::FilamentId); // QDS for first layer inspection options_items.push_back(EMoveType::Travel); options_items.push_back(EMoveType::Retract); options_items.push_back(EMoveType::Unretract); @@ -990,8 +1243,63 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode) options_items.push_back(EMoveType::Seam); } -std::vector GCodeViewer::get_plater_extruder() +void GCodeViewer::init_thermal_icons() { + if (!m_helio_icon_dark_texture) { + ImVec2 icon_size(16, 16); + IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/helio_icon_dark.svg", icon_size.x, icon_size.y, m_helio_icon_dark_texture); + IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/helio_icon.svg", icon_size.x, icon_size.y, m_helio_icon_texture); + } +} + +void GCodeViewer::update_thermal_options(bool add) { + + if (add) { + for (int i = view_type_items.size() - 1; i >= 0; i--) { + if (view_type_items[i] == EViewType::ThermalIndexMean) { + return; + } + } + view_type_items.pop_back();//delete EViewType::FilamentId + auto index = view_type_items.size(); + + view_type_items.push_back(EViewType::ThermalIndexMin); + view_type_items.push_back(EViewType::ThermalIndexMax); + view_type_items.push_back(EViewType::ThermalIndexMean); + for (int i = index; i < view_type_items.size(); i++) { + ImageName temp = {get_view_type_string(view_type_items[i]), m_helio_icon_texture, m_helio_icon_dark_texture}; + view_type_image_names.push_back(temp); + } + view_type_items.push_back(EViewType::FilamentId); + } else { + for (int i = view_type_items.size() - 1; i >= 0; i--) { + if (view_type_items[i] == EViewType::ThermalIndexMean || view_type_items[i] == EViewType::ThermalIndexMin|| view_type_items[i] == EViewType::ThermalIndexMax) { + view_type_items.erase(view_type_items.begin() + i); + view_type_image_names.erase(view_type_image_names.begin() + i); + } + } + } +} + +void GCodeViewer::reset_curr_plate_thermal_options() { + auto curr_plate_index = wxGetApp().plater()->get_partplate_list().get_curr_plate_index(); + reset_curr_plate_thermal_options(curr_plate_index); +} + +void GCodeViewer::reset_curr_plate_thermal_options(int plate_idx) { + update_thermal_options(false); + update_default_view_type(); + m_helio_slice_map_oks[plate_idx] = false; +} + +void GCodeViewer::record_record_gcodeviewer_option_item() { + if (GUI::wxGetApp().app_config->get_bool("enable_record_gcodeviewer_option_item")) { + wxGetApp().app_config->set("gcodeviewer_option_item", std::to_string(m_last_non_helio_option_item)); + wxGetApp().app_config->save(); + } +} + +std::vector GCodeViewer::get_plater_extruder() { return m_plater_extruder; } @@ -1074,6 +1382,7 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr Pointfs printable_area; //QDS: add bed exclude area Pointfs bed_exclude_area = Pointfs(); + Pointfs wrapping_exclude_area = Pointfs(); std::vector extruder_areas; std::vector extruder_heights; std::string texture; @@ -1095,12 +1404,15 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr if (!gcode_result.bed_exclude_area.empty()) bed_exclude_area = gcode_result.bed_exclude_area; + if (!gcode_result.wrapping_exclude_area.empty()) + wrapping_exclude_area = gcode_result.wrapping_exclude_area; + if (!gcode_result.extruder_areas.empty()) extruder_areas = gcode_result.extruder_areas; if (!gcode_result.extruder_heights.empty()) extruder_heights = gcode_result.extruder_heights; - wxGetApp().plater()->set_bed_shape(printable_area, bed_exclude_area, gcode_result.printable_height, extruder_areas, extruder_heights, texture, model, gcode_result.printable_area.empty()); + wxGetApp().plater()->set_bed_shape(printable_area, bed_exclude_area, wrapping_exclude_area, gcode_result.printable_height, extruder_areas, extruder_heights, texture, model, gcode_result.printable_area.empty()); } /*else { // adjust printbed size in dependence of toolpaths bbox @@ -1220,8 +1532,10 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v { case EMoveType::Extrude: { - m_extrusions.ranges.height.update_from(round_to_bin(curr.height)); - m_extrusions.ranges.width.update_from(round_to_bin(curr.width)); + if (curr.extrusion_role != ExtrusionRole::erCustom) { + m_extrusions.ranges.height.update_from(round_to_bin(curr.height)); + m_extrusions.ranges.width.update_from(round_to_bin(curr.width)); + } // prevent the start code extrude extreme height/width and make the range deviate from the normal range m_extrusions.ranges.fan_speed.update_from(curr.fan_speed); m_extrusions.ranges.temperature.update_from(curr.temperature); if (curr.extrusion_role != erCustom || is_visible(erCustom)) @@ -1253,6 +1567,8 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v // update buffers' render paths refresh_render_paths(); log_memory_used("Refreshed G-code extrusion paths, "); + + update_option_item_when_load_gcode(); } void GCodeViewer::refresh_render_paths() @@ -1865,6 +2181,16 @@ void GCodeViewer::update_marker_curr_move() { } } +void GCodeViewer::set_view_type(EViewType type, bool reset_feature_type_visible ) +{ + if (type == EViewType::Count) + type = EViewType::FeatureType; + m_view_type = (EViewType) type; + if (reset_feature_type_visible && type == EViewType::ColorPrint) { + reset_visible(EViewType::FeatureType); + } +} + bool GCodeViewer::is_toolpath_move_type_visible(EMoveType type) const { size_t id = static_cast(buffer_id(type)); @@ -2554,6 +2880,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const } const unsigned char id = buffer_id(curr.type); + if (id >= m_buffers.size()) {//Add an array protection + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " m_buffers array bound"; + continue; + } TBuffer& t_buffer = m_buffers[id]; MultiVertexBuffer& v_multibuffer = vertices[id]; InstanceBuffer& inst_buffer = instances[id]; @@ -3328,25 +3658,28 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": enter, m_buffers size %1%!")%m_buffers.size(); auto extrusion_color = [this](const Path& path) { - Color color; + ColorRGBA color; switch (m_view_type) { - case EViewType::FeatureType: { color = Extrusion_Role_Colors[static_cast(path.role)]; break; } - case EViewType::Height: { color = m_extrusions.ranges.height.get_color_at(path.height); break; } - case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; } - case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; } - case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } - case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; } - case EViewType::LayerTime: { color = m_extrusions.ranges.layer_duration.get_color_at(path.layer_time, Extrusions::Range::EType::Logarithmic); break; } - case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } - case EViewType::Tool: { color = m_tools.m_tool_colors[path.extruder_id]; break; } + case EViewType::FeatureType: {color = Extrusion_Role_Colors[static_cast(path.role)];break;} + case EViewType::Height: {color = m_extrusions.ranges.height.get_color_at(path.height);break;} + case EViewType::Width: {color = m_extrusions.ranges.width.get_color_at(path.width);break;} + case EViewType::Feedrate: {color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate);break;} + case EViewType::FanSpeed: {color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed);break;} + case EViewType::Temperature: {color = m_extrusions.ranges.temperature.get_color_at(path.temperature);break;} + case EViewType::ThermalIndexMin: {color = m_extrusions.ranges.thermal_index_min.get_color_at(path.thermal_index_min);break;} + case EViewType::ThermalIndexMax: {color = m_extrusions.ranges.thermal_index_max.get_color_at(path.thermal_index_max);break;} + case EViewType::ThermalIndexMean: {color = m_extrusions.ranges.thermal_index_mean.get_color_at(path.thermal_index_mean);break;} + case EViewType::LayerTime: {color = m_extrusions.ranges.layer_duration.get_color_at(path.layer_time);break;} + case EViewType::VolumetricRate: {color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate);break;} + case EViewType::Tool: {color = m_tools.m_tool_colors[path.extruder_id];break;} case EViewType::Summary: case EViewType::ColorPrint: { if (path.cp_color_id >= static_cast(m_tools.m_tool_colors.size())) color = { 0.5f, 0.5f, 0.5f, 1.0f }; else { color = m_tools.m_tool_colors[path.cp_color_id]; - color = adjust_color_for_rendering(color); + color = adjust_color_for_rendering(color.get_data()); } break; } @@ -3555,17 +3888,20 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool offset += static_cast(sub_path.first.i_id); // gets the vertex index from the index buffer on gpu - const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; - unsigned int index = 0; - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); - glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - // gets the position from the vertices buffer on gpu - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + if (sub_path.first.b_id >= 0 && sub_path.first.b_id < buffer.indices.size()) { + const IBuffer &i_buffer = buffer.indices[sub_path.first.b_id]; + unsigned int index = 0; + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); + glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), + static_cast(sizeof(IBufferType)), static_cast(&index))); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + // gets the position from the vertices buffer on gpu + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), + static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } sequential_view->current_offset = Vec3f::Zero(); found = true; break; @@ -3587,7 +3923,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (m_sequential_view.current.last < sub_path.first.s_id || sub_path.last.s_id < m_sequential_view.current.first) continue; - Color color; + ColorRGBA color; switch (path.type) { case EMoveType::Tool_change: @@ -3619,7 +3955,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool default: { color = { 0.0f, 0.0f, 0.0f, 1.0f }; break; } } - RenderPath key{ tbuffer_id, color, static_cast(ibuffer_id), path_id }; + RenderPath key{ tbuffer_id, color.get_data(), static_cast(ibuffer_id), path_id }; if (render_path == nullptr || !RenderPathPropertyEqual()(*render_path, key)) { buffer.render_paths.emplace_back(key); render_path = const_cast(&buffer.render_paths.back()); @@ -3948,6 +4284,7 @@ void GCodeViewer::render_toolpaths() shader.set_uniform("light_intensity", light_intensity); }; + auto render_as_instanced_model = [ #if ENABLE_GCODE_VIEWER_STATISTICS this @@ -4949,8 +5286,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0,0.0)); ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f,1.0f,1.0f,0.6f)); - ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); // change color - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); // change color + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.27f, 0.47f, 0.98f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f)); @@ -4992,7 +5329,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImVec2(pos_rect.x + ImGui::GetWindowWidth() + ImGui::GetFrameHeight(),pos_rect.y + ImGui::GetFrameHeight() + window_padding * 2.5), ImGui::GetColorU32(ImVec4(0,0,0,0.3))); - auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, &checkbox_offset, this]( + auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, &checkbox_offset,this]( EItemType type, const Color& color, const std::vector>& columns_offsets, @@ -5035,10 +5372,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv if (callback) { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * m_scale); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0 * m_scale, 0.0)); - //y - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(1.00f, 0.47f, 0.98f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(1.00f, 0.47f, 0.98f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.27f, 0.47f, 0.98f, 1.00f)); // change color + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(1.00f, 0.68f, 0.26f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(1.00f, 0.68f, 0.26f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); float max_height = 0.f; for (auto column_offset : columns_offsets) { if (ImGui::CalcTextSize(column_offset.first.c_str()).y > max_height) @@ -5081,22 +5417,22 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv }; auto append_range = [append_item](const Extrusions::Range& range, unsigned int decimals) { - auto append_range_item = [append_item](int i, float value, unsigned int decimals) { + auto append_range_item = [append_item, range](int i, float value, unsigned int decimals) { char buf[1024]; ::sprintf(buf, "%.*f", decimals, value); - append_item(EItemType::Rect, Range_Colors[i], { { buf , 0} }); + append_item(EItemType::Rect, range.range_colors[i].get_data(), {{buf, 0}}); }; if (range.count == 1) // single item use case append_range_item(0, range.min, decimals); else if (range.count == 2) { - append_range_item(static_cast(Range_Colors.size()) - 1, range.max, decimals); + append_range_item(static_cast(range.range_colors.size()) - 1, range.max, decimals); append_range_item(0, range.min, decimals); } else { const float step_size = range.step_size(); - for (int i = static_cast(Range_Colors.size()) - 1; i >= 0; --i) { + for (int i = static_cast(range.range_colors.size()) - 1; i >= 0; --i) { append_range_item(i, range.get_value_at_step(i), decimals); } } @@ -5231,17 +5567,79 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv return ret; }; - //QDS display Color Scheme - ImGui::Dummy({ window_padding, window_padding }); - ImGui::Dummy({ window_padding, window_padding }); + + // QDS Slicing Result title + ImGui::Dummy({window_padding, window_padding}); + ImGui::Dummy({window_padding, window_padding}); ImGui::SameLine(); - std::string title = _u8L("Slicing Result"); + ImVec2 title_start_pos = ImGui::GetCursorPos(); + std::string title = _u8L("Slicing Result"); imgui.bold_text(title); - // QDS Set the width of the 8 "ABCD" words minus the "sliced result" to the spacing between the buttons and the title - float single_word_width = imgui.calc_text_size("ABCD").x; - float title_width = imgui.calc_text_size(title).x; - float spacing = 18.0f * m_scale; - ImGui::SameLine(0, (single_word_width + spacing) * 8.0f - title_width); + + //y71 + bool is_use_helio = false; + //if (wxGetApp().app_config->get("helio_enable") == "true") + if (is_use_helio){ + auto line_height = ImGui::GetFrameHeight(); + auto image_height = line_height * 0.6; + imgui.disabled_begin(!wxGetApp().is_helio_enable()); + float single_word_width = imgui.calc_text_size("ABCD").x; + float title_width = imgui.calc_text_size(title).x; + float spacing = 18.0f * m_scale; + float icon_spacing = 20.0f * m_scale; + float icon_width = image_height; + float text_width = imgui.calc_text_size(_u8L("Helio Simulation").c_str()).x + imgui.calc_text_size("A").x; + float helio_button_width = icon_width + text_width + 30 * m_scale; + float helio_button_height = ImGui::GetFrameHeight(); + ImGui::SameLine(0, (single_word_width + spacing) * 8.0f - title_width - helio_button_width); + ImVec2 button_pos = ImGui::GetCursorScreenPos(); + ImVec2 original_cursor_pos = ImGui::GetCursorPos(); + float vertical_offset = (ImGui::GetStyle().WindowPadding.y + ImGui::GetFrameHeight() + window_padding * 2.5 - helio_button_height) / 2.f; + ImGui::SetCursorPosY(vertical_offset); + bool button_clicked = ImGui::InvisibleButton("HelioButton", ImVec2(helio_button_width, helio_button_height)); + ImVec2 button_min = ImGui::GetItemRectMin(); + ImVec2 button_max = ImGui::GetItemRectMax(); + ImU32 color_default = ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); + ImU32 color_hovered = ImGui::GetColorU32(ImVec4(0.808f, 0.808f, 0.808f, 1.0f)); + ImU32 color_active = ImGui::GetColorU32(ImVec4(0.808f, 0.808f, 0.808f, 1.0f)); + ImU32 color_text = ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.0f * m_scale); + ImGui::GetWindowDrawList()->AddRectFilled(button_min, button_max, ImGui::IsItemHovered() ? (ImGui::IsItemActive() ? color_active : color_hovered) : color_default, + ImGui::GetStyle().FrameRounding); + ImGui::GetWindowDrawList()->AddRect(button_min, button_max, ImGui::GetColorU32(ImGuiCol_Border), ImGui::GetStyle().FrameRounding); + float content_height = button_max.y - button_min.y; + float text_y = button_min.y + (content_height - ImGui::GetTextLineHeight()) * 0.5f; + + ImRect bb_image; + bb_image.Min = button_min; + bb_image.Min.x += std::min(10.f, line_height * 0.45f); + bb_image.Min.y += line_height * 0.2; + bb_image.Max.x = bb_image.Min.x + image_height; + bb_image.Max.y = bb_image.Min.y + image_height; + ImGui::GetWindowDrawList()->AddImage(m_helio_icon_dark_texture, bb_image.Min, bb_image.Max); + ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), + ImVec2(button_min.x + ImGui::GetStyle().FramePadding.x + icon_width + 10 * m_scale, text_y), + color_text, + _u8L("Helio Simulation").c_str()); + ImGui::PopStyleVar(); + if (button_clicked) { + BOOST_LOG_TRIVIAL(info) << "Helio button clicked"; + Plater * plater = wxGetApp().plater(); + wxCommandEvent evt(EVT_HELIO_INPUT_CHAMBER_TEMP); + evt.SetEventObject(plater); + wxPostEvent(plater, evt); + } + imgui.disabled_end(); + ImGui::SameLine(); + } else { + // QDS Set the width of the 8 "ABCD" words minus the "sliced result" to the spacing between the buttons and the title + float single_word_width = imgui.calc_text_size("ABCD").x; + float title_width = imgui.calc_text_size(title).x; + float spacing = 18.0f * m_scale; + ImGui::SameLine(0, (single_word_width + spacing) * 8.0f - title_width); + } + // QDS support helio + std::wstring btn_name; if (m_fold) btn_name = ImGui::UnfoldButtonIcon + boost::nowide::widen(std::string("")); @@ -5252,9 +5650,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.0f, 0.47f, 0.98f, 0.78f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); float button_width = ImGui::CalcTextSize(into_u8(btn_name).c_str()).x; - if (ImGui::Button(into_u8(btn_name).c_str(), ImVec2(button_width, 0))) { - m_fold = !m_fold; - } + ImGui::SetCursorPosY(8.f); + if (ImGui::Button(into_u8(btn_name).c_str(), ImVec2(button_width, 0))) { m_fold = !m_fold; } + ImGui::PopStyleColor(3); ImGui::PopStyleVar(1); @@ -5271,10 +5669,35 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.bold_text(_u8L("Color Scheme")); - push_combo_style(); - ImGui::SameLine(); - const char* view_type_value = view_type_items_str[m_view_type_sel].c_str(); + auto curr_plate_index = wxGetApp().plater()->get_partplate_list().get_curr_plate_index(); + if (wxGetApp().plater()->get_helio_process_status() != m_last_helio_process_status || m_gcode_result->update_imgui_flag) { + auto load_only_gcode = wxGetApp().plater()->only_gcode_mode(); + auto load_gcode3mf = wxGetApp().plater()->is_gcode_3mf(); + if (load_only_gcode || load_gcode3mf) { + wxGetApp().plater()->clear_helio_process_status(); + } + m_last_helio_process_status = wxGetApp().plater()->get_helio_process_status(); + m_show_horizontal_slider = false; + if ((int) Slic3r::HelioBackgroundProcess::State::STATE_FINISHED == m_last_helio_process_status || (m_gcode_result->update_imgui_flag &&m_gcode_result->is_helio_gcode)) { + update_thermal_options(true); + for (int i = 0; i < view_type_items.size(); i++) { + if (view_type_items[i] == EViewType::ThermalIndexMean) { + m_view_type_sel = i; + break; + } + } + set_view_type(EViewType::ThermalIndexMean); + wxGetApp().plater()->get_notification_manager()->close_notification_of_type(NotificationType::HelioSlicingError); + m_helio_slice_map_oks[curr_plate_index] = true; + } else if ((int) Slic3r::HelioBackgroundProcess::State::STATE_CANCELED == m_last_helio_process_status || + (m_gcode_result->update_imgui_flag && !m_gcode_result->is_helio_gcode && curr_plate_has_ok_helio_slice(curr_plate_index))) { + reset_curr_plate_thermal_options(curr_plate_index); + } + const_cast(m_gcode_result)->update_imgui_flag = false; + } + + push_combo_style(); ImGuiComboFlags flags = 0; //55 if (is_show_speed) { @@ -5287,13 +5710,18 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); is_show_speed = false; } + const char *view_type_value = view_type_image_names[m_view_type_sel].option_name.c_str(); if (ImGui::QDTBeginCombo("", view_type_value, flags)) { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); - for (int i = 0; i < view_type_items_str.size(); i++) { + for (int i = 0; i < view_type_image_names.size(); i++) { const bool is_selected = (m_view_type_sel == i); - if (ImGui::QDTSelectable(view_type_items_str[i].c_str(), is_selected)) { + if (ImGui::QDTSelectable_LeftImage(view_type_image_names[i].option_name.c_str(), is_selected, view_type_image_names[i].texture_id)) { m_fold = false; m_view_type_sel = i; + if (!is_helio_option()) { + m_last_non_helio_option_item = i; + record_record_gcodeviewer_option_item(); + } set_view_type(view_type_items[m_view_type_sel]); reset_visible(view_type_items[m_view_type_sel]); // update buffers' render paths @@ -5464,19 +5892,16 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } case EViewType::Height: { imgui.title(_u8L("Layer Height (mm)")); break; } case EViewType::Width: { imgui.title(_u8L("Line Width (mm)")); break; } - case EViewType::Feedrate: - { - imgui.title(_u8L("Speed (mm/s)")); - break; - } - - case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } - case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } - case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } - case EViewType::LayerTime: { imgui.title(_u8L("Layer Time (s)")); break; } - + case EViewType::Feedrate:{imgui.title(_u8L("Speed (mm/s)"));break;} + case EViewType::FanSpeed: {imgui.title(_u8L("Fan Speed (%)"));break;} + case EViewType::Temperature: {imgui.title(_u8L("Temperature (°C)"));break;} + case EViewType::ThermalIndexMin: {imgui.title(_u8L("Thermal Index (min)"));break;} + case EViewType::ThermalIndexMax: {imgui.title(_u8L("Thermal Index (max)"));break;} + case EViewType::ThermalIndexMean: {imgui.title(_u8L("Thermal Index (mean)"));break;} + case EViewType::VolumetricRate: {imgui.title(_u8L("Volumetric flow rate (mm³/s)"));break;} + case EViewType::LayerTime: {imgui.title(_u8L("Layer Time"));break;} case EViewType::Tool: - { +{ // calculate used filaments data for (size_t extruder_id : m_extruder_ids) { if (m_print_statistics.model_volumes_per_extruder.find(extruder_id) == m_print_statistics.model_volumes_per_extruder.end()) @@ -5625,10 +6050,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::PopStyleVar(1); break; } - case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } - case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; } - case EViewType::LayerTime: { append_range(m_extrusions.ranges.layer_duration, 1); break; } - case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 2); break; } + case EViewType::FanSpeed: {append_range(m_extrusions.ranges.fan_speed, 0);break;} + case EViewType::Temperature: {append_range(m_extrusions.ranges.temperature, 0);break;} + case EViewType::ThermalIndexMin: {append_range(m_extrusions.ranges.thermal_index_min, 0);break;} + case EViewType::ThermalIndexMax: {append_range(m_extrusions.ranges.thermal_index_max, 0);break;} + case EViewType::ThermalIndexMean: {append_range(m_extrusions.ranges.thermal_index_mean, 0);break;} + case EViewType::LayerTime: {append_range(m_extrusions.ranges.layer_duration, 1);break;} + case EViewType::VolumetricRate: {append_range(m_extrusions.ranges.volumetric_rate, 2);break;} case EViewType::Tool: { // shows only extruders actually used diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index bc8ce19..e2688a3 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -41,7 +41,9 @@ class GCodeViewer static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; static const std::vector Travel_Colors; - static const std::vector Range_Colors; + static const std::vector Range_Colors; + static const std::vector Default_Range_Colors; + static const std::vector Thermal_Index_Range_Colors; static const Color Wipe_Color; static const Color Neutral_Color; @@ -215,6 +217,9 @@ class GCodeViewer float feedrate{ 0.0f }; float fan_speed{ 0.0f }; float temperature{ 0.0f }; + float thermal_index_min{0.0f}; + float thermal_index_max{0.0f}; + float thermal_index_mean{0.0f}; float volumetric_rate{ 0.0f }; float layer_time{ 0.0f }; unsigned char extruder_id{ 0 }; @@ -386,28 +391,47 @@ class GCodeViewer { struct Range { - enum class EType : unsigned char { - Linear, - Logarithmic - }; float min; float max; + bool is_fixed_range; unsigned int count; bool log_scale; + std::vector range_colors; + + Range(std::vector range_colors_a = Range_Colors) : is_fixed_range(false), range_colors(range_colors_a) { reset(); } + + /*Sometimes we want min and max of the range to be fixed to have consistent color later*/ + Range(float min_a, float max_a, std::vector range_colors_a = Range_Colors) + : min(min_a), max(max_a), is_fixed_range(true), range_colors(range_colors_a) + { + reset(); + } - Range() { reset(); } void update_from(const float value) { if (value != max && value != min) ++count; - min = std::min(min, value); - max = std::max(max, value); + if (!is_fixed_range) { + min = std::min(min, value); + max = std::max(max, value); + } + } + void reset(bool log = false) + { + if (!is_fixed_range) { + min = FLT_MAX; + max = -FLT_MAX; + count = 0; + log_scale = log; + } else { + count = 0; + log_scale = log; + } } - void reset(bool log = false) { min = FLT_MAX; max = -FLT_MAX; count = 0; log_scale = log; } - - float step_size(EType type = EType::Linear) const; - Color get_color_at(float value, EType type = EType::Linear) const; - float get_value_at_step(int step) const; + float step_size() const; + ColorRGBA get_color_at(float value) const; + float get_value_at_step(int step) const; + float get_color_size() const; }; struct Ranges @@ -426,6 +450,12 @@ class GCodeViewer Range temperature; // Color mapping by layer time. Range layer_duration; + // Color mapping by thermal index min + Range thermal_index_min{-100.0f, 100.0f, Thermal_Index_Range_Colors}; + // Color mapping by thermal index max + Range thermal_index_max{-100.0f, 100.0f, Thermal_Index_Range_Colors}; + // Color mapping by thermal index mean + Range thermal_index_mean{-100.0f, 100.0f, Thermal_Index_Range_Colors}; void reset() { height.reset(); width.reset(); @@ -434,6 +464,9 @@ class GCodeViewer volumetric_rate.reset(); temperature.reset(); layer_duration.reset(true); + thermal_index_min.reset(); + thermal_index_max.reset(); + thermal_index_mean.reset(); } }; @@ -659,7 +692,8 @@ public: std::vector m_lines; public: - GCodeWindow() = default; + const SequentialView &m_sequential_view; + GCodeWindow(const SequentialView &outer_view) : m_sequential_view(outer_view) {} ~GCodeWindow() { stop_mapping_file(); } void load_gcode(const std::string& filename, const std::vector &lines_ends); void reset() { @@ -678,7 +712,14 @@ public: //void render(float top, float bottom, uint64_t curr_line_id) const; void render(float top, float bottom, float right, uint64_t curr_line_id) const; void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; } - + void render_thermal_index_windows( + std::vector thermal_indexes, + float top, + float right, + float wnd_height, + float f_lines_count, + uint64_t start_id, + uint64_t end_id) const; void stop_mapping_file(); }; @@ -696,12 +737,14 @@ public: Vec3f current_position{ Vec3f::Zero() }; Vec3f current_offset{ Vec3f::Zero() }; Marker marker; - GCodeWindow gcode_window; + GCodeWindow gcode_window{*this}; + const GCodeViewer & m_gcode_viewer; std::vector gcode_ids; float m_scale = 1.0; //QDS: GUI refactor: add canvas size void render(float legend_height, int canvas_width, int canvas_height, int right_margin, const EViewType& view_type) const; + SequentialView(const GCodeViewer &outer_viewer); }; struct ETools @@ -727,6 +770,9 @@ public: Feedrate, FanSpeed, Temperature, + ThermalIndexMin, + ThermalIndexMax, + ThermalIndexMean, VolumetricRate, Tool, ColorPrint, @@ -753,6 +799,10 @@ public: private: std::vector m_plater_extruder; bool m_gl_data_initialized{ false }; + int m_last_non_helio_option_item{-1}; + int m_last_helio_process_status{0}; + std::map m_helio_slice_map_oks; + int m_last_back_process_status{0}; unsigned int m_last_result_id{ 0 }; size_t m_moves_count{ 0 }; //QDS: save m_gcode_result as well @@ -788,16 +838,23 @@ private: std::vector m_filament_diameters; std::vector m_filament_densities; Extrusions m_extrusions; - SequentialView m_sequential_view; + SequentialView m_sequential_view = SequentialView(*this); IMSlider* m_moves_slider; IMSlider* m_layers_slider; /*QDS GUI refactor, store displayed items in color scheme combobox */ std::vector view_type_items; - std::vector view_type_items_str; + struct ImageName + { + std::string option_name; + ImTextureID texture_id{nullptr}; + ImTextureID texture_id_dark{nullptr}; + }; + std::vector view_type_image_names; int m_view_type_sel = 0; EViewType m_view_type{ EViewType::FeatureType }; std::vector options_items; + mutable bool m_show_horizontal_slider{false}; bool m_legend_enabled{ true }; float m_legend_height; @@ -810,7 +867,8 @@ private: std::array m_sequential_range_caps; std::vector m_custom_gcode_per_print_z; - + ImTextureID m_helio_icon_dark_texture{nullptr}; + ImTextureID m_helio_icon_texture{nullptr}; bool m_contained_in_bed{ true }; bool m_is_dark = false; @@ -818,12 +876,22 @@ public: GCodeViewer(); ~GCodeViewer(); + bool is_show_horizontal_slider() const; + void set_show_horizontal_slider(bool flag)const { m_show_horizontal_slider = flag; } + bool is_helio_option() const; + bool curr_plate_has_ok_helio_slice(int plate_idx) const; + void update_option_item_when_load_gcode(); void on_change_color_mode(bool is_dark); float m_scale = 1.0; void set_scale(float scale = 1.0); void init(ConfigOptionMode mode, Slic3r::PresetBundle* preset_bundle); + void update_default_view_type(); void update_by_mode(ConfigOptionMode mode); - + void update_thermal_options(bool add); + void reset_curr_plate_thermal_options(); + void reset_curr_plate_thermal_options(int plate_idx); + void record_record_gcodeviewer_option_item(); + void init_thermal_icons(); // extract rendering data from the given parameters //QDS: add only gcode mode void load(const GCodeProcessorResult& gcode_result, const Print& print, const BuildVolume& build_volume, @@ -875,14 +943,7 @@ public: bool is_only_gcode_in_preview() const { return m_only_gcode_in_preview; } EViewType get_view_type() const { return m_view_type; } - void set_view_type(EViewType type, bool reset_feature_type_visible = true) { - if (type == EViewType::Count) - type = EViewType::FeatureType; - m_view_type = (EViewType)type; - if (reset_feature_type_visible && type == EViewType::ColorPrint) { - reset_visible(EViewType::FeatureType); - } - } + void set_view_type(EViewType type, bool reset_feature_type_visible = true); void reset_visible(EViewType type) { if (type == EViewType::FeatureType) { for (size_t i = 0; i < m_roles.size(); ++i) { diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1dd199a..c21e3d7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -40,6 +40,7 @@ #include "DailyTips.hpp" #include "FilamentMapDialog.hpp" #include "../Utils/CpuMemory.hpp" +#include "../Utils/HelioDragon.hpp" #if ENABLE_RETINA_GL #include "slic3r/Utils/RetinaHelper.hpp" #endif @@ -163,6 +164,12 @@ std::string& get_nozzle_filament_incompatible_text() { return nozzle_filament_incompatible_text; } +std::string& get_filament_mixture_warning_text(){ + static std::string filament_mixture_warning_text; + return filament_mixture_warning_text; +} + + static std::string format_number(float value) { std::ostringstream oss; @@ -3201,9 +3208,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config; auto timelapse_type = dconfig.option>("timelapse_type"); - bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false; + bool need_wipe_tower = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false; - if (wt && (timelapse_enabled || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) { + if (dconfig.has("enable_wrapping_detection")) { + need_wipe_tower |= dynamic_cast(dconfig.option("enable_wrapping_detection"))->value; + } + + if (wt && (need_wipe_tower || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) { for (int plate_id = 0; plate_id < n_plates; plate_id++) { // If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated. PartPlate* part_plate = ppl.get_plate(plate_id); @@ -3224,14 +3235,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const Print* print = m_process->fff_print(); const Print* current_print = part_plate->fff_print(); - if (!timelapse_enabled && part_plate->get_extruders(true).size() < 2) continue; + if (!need_wipe_tower && part_plate->get_extruders(true).size() < 2) continue; if (part_plate->get_objects_on_this_plate().empty()) continue; float brim_width = print->wipe_tower_data(filaments_count).brim_width; const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; double wipe_vol = get_max_element(v); int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count(); - Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums); + Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 0, false, dynamic_cast(dconfig.option("enable_wrapping_detection"))->value); { const float margin = WIPE_TOWER_MARGIN; @@ -3366,6 +3377,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re 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 filament_mixture_compatible = cur_plate->check_mixture_filament_compatible(full_config_temp, get_filament_mixture_warning_text()); + _set_warning_notification(EWarning::MixtureFilamentIncompatible, !filament_mixture_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); @@ -3384,6 +3398,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re _set_warning_notification(EWarning::MultiExtruderPrintableError,false); _set_warning_notification(EWarning::MultiExtruderHeightOutside,false); _set_warning_notification(EWarning::NozzleFilamentIncompatible,false); + _set_warning_notification(EWarning::MixtureFilamentIncompatible,false); post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } @@ -3474,8 +3489,8 @@ static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume& //QDS: always load shell at preview void GLCanvas3D::load_shells(const Print& print, bool force_previewing) { - if (m_initialized) - { + if (m_initialized) { + m_gcode_viewer.set_show_horizontal_slider(false); m_gcode_viewer.load_shells(print, m_initialized, force_previewing); m_gcode_viewer.update_shells_color_by_extruder(m_config); } @@ -5291,6 +5306,10 @@ void GLCanvas3D::on_set_focus(wxFocusEvent& evt) m_tooltip_enabled = true; } +void GLCanvas3D::on_back_slice_begin() { + m_gcode_viewer.reset_curr_plate_thermal_options(); +} + Size GLCanvas3D::get_canvas_size() const { int w = 0; @@ -7016,7 +7035,7 @@ bool GLCanvas3D::_update_imgui_select_plate_toolbar() return false; } - if (!p_plater->is_gcode_3mf()) { + if (!p_plater->is_gcode_3mf()) { p_plater->update_all_plate_thumbnails(true); } @@ -8217,8 +8236,6 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() auto canvas_w = float(cnv_size.get_width()); auto canvas_h = float(cnv_size.get_height()); - bool is_hovered = false; - m_sel_plate_toolbar.set_icon_size(100.0f * f_scale, 100.0f * f_scale); float button_width = m_sel_plate_toolbar.icon_width; @@ -8318,7 +8335,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() text_clr = ImVec4(68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255.0f, 1); btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_texture.get_id()); } - + imgui.disabled_begin(wxGetApp().plater()->get_helio_process_status() == Slic3r::HelioBackgroundProcess::State::STATE_RUNNING); if (ImGui::ImageButton2(btn_texture_id, size, {0,0}, {1,1}, frame_padding, bg_col, tint_col, margin)) { if (all_plates_stats_item->slice_state != IMToolbarItem::SliceState::SLICE_FAILED) { if (m_process && !m_process->running()) { @@ -8332,6 +8349,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() } } } + imgui.disabled_end(); if (!all_plates_stats_item->selected) { m_can_show_navigator = true; } @@ -8409,6 +8427,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(.0f, .0f, .0f, .0f)); } } + imgui.disabled_begin(wxGetApp().plater()->get_helio_process_status() == Slic3r::HelioBackgroundProcess::State::STATE_RUNNING); if(ImGui::Button("##invisible_button", button_size)){ if (m_process && !m_process->running()) { all_plates_stats_item->selected = false; @@ -8421,6 +8440,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() wxQueueEvent(wxGetApp().plater(), evt); } } + imgui.disabled_end(); ImGui::PopStyleColor(4); ImGui::PopStyleVar(); @@ -8462,7 +8482,11 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() ImGui::PopStyleColor(8); ImGui::PopStyleVar(5); - if (ImGui::IsWindowHovered() || is_hovered) { + ImVec2 window_pos = ImGui::GetWindowPos(); + ImVec2 window_size = ImGui::GetWindowSize(); + ImVec2 window_max = ImVec2(window_pos.x + window_size.x + 25, window_pos.y + window_size.y); + ImRect window_rect(window_pos, window_max); + if (ImGui::IsWindowHovered() || window_rect.Contains(ImGui::GetMousePos())) { m_sel_plate_toolbar.is_display_scrollbar = true; } else { m_sel_plate_toolbar.is_display_scrollbar = false; @@ -10911,6 +10935,10 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) text = _u8L(get_nozzle_filament_incompatible_text()); break; } + case EWarning::MixtureFilamentIncompatible: { + text = _u8L(get_filament_mixture_warning_text()); + break; + } } //QDS: this may happened when exit the app, plater is null if (!wxGetApp().plater()) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index ca7ce00..932923b 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -410,6 +410,7 @@ class GLCanvas3D MixUsePLAAndPETG, PrimeTowerOutside, NozzleFilamentIncompatible, + MixtureFilamentIncompatible, AsemblyInvalid // for asembly view only }; @@ -1020,6 +1021,7 @@ public: void on_paint(wxPaintEvent& evt); void on_kill_focus(wxFocusEvent &evt); void on_set_focus(wxFocusEvent& evt); + void on_back_slice_begin(); void force_set_focus(); Size get_canvas_size() const; diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index b05e0c0..116368b 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -214,7 +214,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt } break; case coPoints:{ - if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "thumbnail_size") { + if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key=="thumbnail_size" || opt_key == "wrapping_exclude_area" ) { config.option(opt_key)->values = boost::any_cast>(value); break; } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 14626a7..7c3c078 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -70,12 +70,15 @@ #include "GLCanvas3D.hpp" #include "EncodedFilament.hpp" +#include "DeviceCore/DevManager.h" + #include "../Utils/PresetUpdater.hpp" #include "../Utils/PrintHost.hpp" #include "../Utils/Process.hpp" #include "../Utils/MacDarkMode.hpp" #include "../Utils/Http.hpp" #include "../Utils/UndoRedo.hpp" +#include "../Utils/HelioDragon.hpp" #include "slic3r/Config/Snapshot.hpp" #include "Preferences.hpp" #include "Tab.hpp" @@ -1078,16 +1081,23 @@ void GUI_App::post_init() throw Slic3r::RuntimeError("Calling post_init() while not yet initialized"); if (app_config->get("sync_user_preset") == "true") { - // QDS loading user preset - // Always async, not such startup step - // BOOST_LOG_TRIVIAL(info) << "Loading user presets..."; - // scrn->SetText(_L("Loading user presets...")); if (m_agent) { start_sync_user_preset(); } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " sync_user_preset: true"; } else { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " sync_user_preset: false"; } + /*request helio config*/ + if (app_config->get("helio_enable") == "true") { + if (!Slic3r::HelioQuery::get_helio_api_url().empty() && !Slic3r::HelioQuery::get_helio_pat().empty()) { + wxGetApp().request_helio_supported_data(); + } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " sync helio config: true"; + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " sync helio config: false"; + } + m_open_method = "double_click"; bool switch_to_3d = false; if (!this->init_params->input_files.empty()) { @@ -1140,7 +1150,7 @@ void GUI_App::post_init() } catch (...){} - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", download_url %1%") % download_url; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", download_url %1%") % PathSanitizer::sanitize(download_url); if (!download_url.empty()) { m_download_file_url = from_u8(download_url); @@ -1268,7 +1278,7 @@ void GUI_App::post_init() }*/ //QDS: check crash log - auto log_dir_path = boost::filesystem::path(data_dir()) / "log"; + /*auto log_dir_path = boost::filesystem::path(data_dir()) / "log"; if (boost::filesystem::exists(log_dir_path)) { boost::filesystem::directory_iterator end_iter; @@ -1298,7 +1308,7 @@ void GUI_App::post_init() } } } - } + }*/ if (m_networking_need_update) { //updating networking @@ -1366,8 +1376,6 @@ void GUI_App::post_init() mainframe->refresh_plugin_tips(); }); - DeviceManager::load_filaments_blacklist_config(); - // remove old log files over LOG_FILES_MAX_NUM std::string log_addr = data_dir(); if (!log_addr.empty()) { @@ -2072,13 +2080,6 @@ void GUI_App::init_networking_callbacks() MachineObject *obj = dev->get_selected_machine(); if (!obj) return; - if (obj->nt_try_local_tunnel && obj->connection_type() == "cloud") { - if (obj->is_connected()) { - obj->disconnect(); - } - obj->nt_reset_data(); - } - /* resubscribe the cache dev list */ if (this->is_enable_multi_machine()) { @@ -2113,8 +2114,8 @@ void GUI_App::init_networking_callbacks() obj->erase_user_access_code(); obj->command_get_access_code(); if (m_agent) - m_agent->install_device_cert(obj->dev_id, obj->is_lan_mode_printer()); - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + m_agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer()); + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } }); }); @@ -2152,11 +2153,11 @@ void GUI_App::init_networking_callbacks() obj->command_request_push_all(true); obj->command_get_version(); event.SetInt(0); - event.SetString(obj->dev_id); - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + event.SetString(obj->get_dev_id()); + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } else if (state == ConnectStatus::ConnectStatusFailed) { - m_device_manager->localMachineList.erase(obj->dev_id); - m_device_manager->set_selected_machine("", true); + m_device_manager->erase_local_machine(obj->get_dev_id()); + m_device_manager->set_selected_machine(""); wxString text; if (msg == "5") { obj->set_access_code(""); @@ -2164,15 +2165,15 @@ void GUI_App::init_networking_callbacks() text = wxString::Format(_L("Incorrect password")); wxGetApp().show_dialog(text); } else { - text = wxString::Format(_L("Connect %s failed! [SN:%s, code=%s]"), from_u8(obj->dev_name), obj->dev_id, msg); + text = wxString::Format(_L("Connect %s failed! [SN:%s, code=%s]"), from_u8(obj->get_dev_name()), obj->get_dev_id(), msg); wxGetApp().show_dialog(text); } event.SetInt(-1); } else if (state == ConnectStatus::ConnectStatusLost) { //obj->set_access_code(""); //obj->erase_user_access_code(); - //m_device_manager->localMachineList.erase(obj->dev_id); - m_device_manager->set_selected_machine("", true); + //m_device_manager->localMachineList.erase(obj->get_dev_id()); + m_device_manager->set_selected_machine(""); event.SetInt(-1); BOOST_LOG_TRIVIAL(info) << "set_on_local_connect_fn: state = lost"; } else { @@ -2185,15 +2186,15 @@ void GUI_App::init_networking_callbacks() else { if (state == ConnectStatus::ConnectStatusOk) { event.SetInt(1); - event.SetString(obj->dev_id); + event.SetString(obj->get_dev_id()); } else if(msg == "5") { event.SetInt(5); - event.SetString(obj->dev_id); + event.SetString(obj->get_dev_id()); } else { event.SetInt(-2); - event.SetString(obj->dev_id); + event.SetString(obj->get_dev_id()); } } } @@ -2217,7 +2218,8 @@ void GUI_App::init_networking_callbacks() if (obj) { auto sel = this->m_device_manager->get_selected_machine(); - if (sel && sel->dev_id == dev_id) { + if (sel && sel->get_dev_id() == dev_id) + { obj->parse_json("cloud", msg); } else { @@ -2225,9 +2227,8 @@ void GUI_App::init_networking_callbacks() } - if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) { - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); - obj->is_ams_need_update = false; + if (sel == obj || sel == nullptr) { + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } } @@ -2269,9 +2270,9 @@ void GUI_App::init_networking_callbacks() MachineObject* obj = m_device_manager->get_my_machine(dev_id); if (obj) { - obj->parse_json("lan", msg, DeviceManager::key_field_only); - if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) { - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + obj->parse_json("lan", msg); + if (this->m_device_manager->get_selected_machine() == obj) { + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } } @@ -2316,7 +2317,7 @@ bool GUI_App::is_blocking_printing(MachineObject *obj_) if (!dev) return true; std::string target_model; if (obj_ == nullptr) { - auto obj_ = dev->get_selected_machine(); + obj_ = dev->get_selected_machine(); if (obj_) { target_model = obj_->printer_type; } @@ -2324,11 +2325,15 @@ bool GUI_App::is_blocking_printing(MachineObject *obj_) target_model = obj_->printer_type; } + if (!obj_) + { + return false; + } PresetBundle *preset_bundle = wxGetApp().preset_bundle; std::string source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); if (source_model != target_model) { - std::vector compatible_machine = dev->get_compatible_machine(target_model); + std::vector compatible_machine = obj_->get_compatible_machine(); vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); if (it == compatible_machine.end()) { return true; @@ -2560,10 +2565,10 @@ void GUI_App::on_start_subscribe_again(std::string dev_id) MachineObject* obj = dev->get_selected_machine(); if (!obj) return; - if ( (dev_id == obj->dev_id) && obj->is_connecting() && obj->subscribe_counter > 0) { + if ( (dev_id == obj->get_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=" << QDTCrossTalk::Crosstalk_DevId(obj->dev_id); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": dev_id=" << QDTCrossTalk::Crosstalk_DevId(obj->get_dev_id()); } }); start_subscribe_timer->Start(5000, wxTIMER_ONE_SHOT); @@ -2608,7 +2613,7 @@ void GUI_App::MacPowerCallBack(void* refcon, io_service_t service, natural_t mes if (dev_manager) { MachineObject* obj = dev_manager->get_selected_machine(); - last_selected_machine = obj ? obj->dev_id : ""; + last_selected_machine = obj ? obj->get_dev_id() : ""; BOOST_LOG_TRIVIAL(info) << "MacPowerCallBack save selected machine:" << last_selected_machine; } @@ -2618,7 +2623,7 @@ void GUI_App::MacPowerCallBack(void* refcon, io_service_t service, natural_t mes { if (dev_manager && !last_selected_machine.empty()) { - dev_manager->set_selected_machine(last_selected_machine, true); + dev_manager->set_selected_machine(last_selected_machine); BOOST_LOG_TRIVIAL(info) << "MacPowerCallBack restore selected machine:" << last_selected_machine; } }; @@ -2769,7 +2774,7 @@ bool GUI_App::on_init_inner() #ifdef WIN32 //QDS set crash log folder - CBaseException::set_log_folder(data_dir()); + //CBaseException::set_log_folder(data_dir()); #endif wxGetApp().Bind(wxEVT_QUERY_END_SESSION, [this](auto & e) { @@ -2806,6 +2811,11 @@ bool GUI_App::on_init_inner() #endif BOOST_LOG_TRIVIAL(info) << get_system_info(); +// initialize label colors and fonts + init_label_colours(); + init_fonts(); + wxGetApp().Update_dark_mode_flag(); + #if defined(__WINDOWS__) HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); m_is_arm64 = false; @@ -2880,11 +2890,6 @@ bool GUI_App::on_init_inner() #endif // __WINDOWS__ #endif - // initialize label colors and fonts - init_label_colours(); - init_fonts(); - wxGetApp().Update_dark_mode_flag(); - #ifdef _MSW_DARK_MODE // app_config can be updated in check_older_app_config(), so check if dark_color_mode and sys_menu_enabled was changed @@ -3397,11 +3402,10 @@ __retry: m_task_manager = new Slic3r::TaskManager(m_agent); m_task_manager->start(); } - m_agent->enable_multi_machine(true); - DeviceManager::EnableMultiMachine = true; + + m_device_manager->EnableMultiMachine(true); } else { - m_agent->enable_multi_machine(false); - DeviceManager::EnableMultiMachine = false; + m_device_manager->EnableMultiMachine(false); } //QDS set config dir @@ -4078,6 +4082,41 @@ bool GUI_App::catch_error(std::function cb, return false; } +bool GUI_App::is_helio_enable() +{ + if (!plater_) return false; + auto cfg = plater_->get_partplate_list().get_curr_plate()->config(); + PrintSequence print_sequence = PrintSequence::ByLayer; + if (cfg->has("print_sequence")) { + print_sequence = cfg->option>("print_sequence")->value; + } + else { + print_sequence = wxGetApp().global_print_sequence(); + } + + if (print_sequence == PrintSequence::ByObject) { + return false; + } + + return true; +} + +void GUI_App::request_helio_pat(std::function func) +{ + Slic3r::HelioQuery::request_pat_token(func); +} + +void GUI_App::request_helio_supported_data() +{ + std:;string helio_api_url = Slic3r::HelioQuery::get_helio_api_url(); + std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + + if (HelioQuery::global_supported_printers.size() <= 0 || HelioQuery::global_supported_materials.size() <= 0) { + Slic3r::HelioQuery::request_all_support_machine(helio_api_url, helio_api_key); + Slic3r::HelioQuery::request_all_support_materials(helio_api_url, helio_api_key); + } +} + // static method accepting a wxWindow object as first parameter void fatal_error(wxWindow* parent) { @@ -4232,27 +4271,17 @@ wxString GUI_App::transition_tridid(int trid_id) const int id_index = trid_id / 4; return wxString::Format("%s", maping_dict[id_index]); } - else { - // int id_index = ceil(trid_id / 4); - // int id_suffix = trid_id % 4 + 1; - //return wxString::Format("%s%d", maping_dict[id_index], id_suffix); - int group = trid_id / 4 + 1; - char suffix = 'A' + trid_id % 4; - return wxString::Format("%d%c", group, suffix); - } -} - -wxString GUI_App::transition_tridid(int trid_id, bool is_n3s) const -{ - if (is_n3s) - { + else if (trid_id >= 0x80 && trid_id <= 0x87) { // n3s const char base = 'A' + (trid_id - 128); wxString prefix("HT-"); prefix.append(base); return prefix; } - - return transition_tridid(trid_id); + else { + int id_index = std::clamp((int)ceil(trid_id / 4), 0, 25); + int id_suffix = trid_id % 4 + 1; + return wxString::Format("%s%d", maping_dict[id_index], id_suffix); + } } //QDS @@ -4833,8 +4862,10 @@ void GUI_App::request_open_project(std::string project_id) return; } - if (project_id == "") + if (project_id == "") { + plater()->show_wrapping_detect_dialog_if_necessary(); plater()->new_project(); + } else if (project_id.empty()) plater()->load_project(); else if (std::find_if_not(project_id.begin(), project_id.end(), @@ -5368,7 +5399,7 @@ void GUI_App::process_network_msg(std::string dev_id, std::string msg) return; MachineObject* obj = dev->get_selected_machine(); if (obj) - m_agent->install_device_cert(obj->dev_id, obj->is_lan_mode_printer()); + m_agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer()); if (!m_show_error_msgdlg) { MessageDialog msg_dlg(nullptr, _L("Retrieving printer information, please try again later."), "", wxAPPLY | wxOK); m_show_error_msgdlg = true; @@ -5429,6 +5460,15 @@ void GUI_App::process_network_msg(std::string dev_id, std::string msg) m_show_error_msgdlg = false; } } + else if (msg == "device_cert_installed") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, device_cert_installed"; + Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) return; + MachineObject* obj = dev->get_my_machine(dev_id); + if (obj) { + obj->update_device_cert_state(true); + } + } } void GUI_App::no_new_version() @@ -6362,10 +6402,10 @@ bool GUI_App::show_modal_ip_address_enter_dialog(bool input_sn, wxString title) BOOST_LOG_TRIVIAL(info) << "User enter IP address is " << format_IP(ip_address.ToStdString()); if (!ip_address.empty()) { - wxGetApp().app_config->set_str("ip_address", obj->dev_id, ip_address.ToStdString()); + wxGetApp().app_config->set_str("ip_address", obj->get_dev_id(), ip_address.ToStdString()); wxGetApp().app_config->save(); - obj->dev_ip = ip_address.ToStdString(); + obj->set_dev_ip(ip_address.ToStdString()); obj->set_user_access_code(access_code.ToStdString()); } } @@ -7831,7 +7871,7 @@ bool has_filaments(const std::vector& model_filaments) { return false; } -bool is_support_filament(int extruder_id) +bool is_support_filament(int extruder_id, bool strict_check) { auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets; auto &filaments = Slic3r::GUI::wxGetApp().preset_bundle->filaments; @@ -7845,7 +7885,7 @@ bool is_support_filament(int extruder_id) Slic3r::ConfigOptionBools *support_option = dynamic_cast(filament->config.option("filament_is_support")); - if (filament_type == "PETG" || filament_type == "PLA") { + if(!strict_check &&(filament_type == "PETG" || filament_type == "PLA")) { std::vector model_filaments; if (filament_type == "PETG") model_filaments.emplace_back("PLA"); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index dbb42ff..c813de3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -462,7 +462,6 @@ public: void load_gcode(wxWindow* parent, wxString& input_file) const; wxString transition_tridid(int trid_id) const; - wxString transition_tridid(int trid_id, bool is_n3s) const; void ShowUserGuide(); void ShowDownNetPluginDlg(bool post_login = false); void ShowUserLogin(bool show = true); @@ -535,7 +534,13 @@ public: static bool catch_error(std::function cb, const std::string& err); - void persist_window_geometry(wxTopLevelWindow *window, bool default_maximized = false); + //for helio slice + bool is_helio_enable(); + static void request_helio_pat(std::function func); + static void request_helio_supported_data(); + //static std::vector get_helio_support_printer_model(); + + void persist_window_geometry(wxTopLevelWindow *window, bool default_maximized = false); void update_ui_from_settings(); bool switch_language(); @@ -772,7 +777,7 @@ private: DECLARE_APP(GUI_App) wxDECLARE_EVENT(EVT_CONNECT_LAN_MODE_PRINT, wxCommandEvent); -bool is_support_filament(int extruder_id); +bool is_support_filament(int extruder_id, bool strict_check = true); 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); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 441f834..a4accb4 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -1311,6 +1311,7 @@ void MenuFactory::create_text_part_menu() append_menu_item_delete(menu); append_menu_item_fix_through_netfabb(menu); append_menu_item_simplify(menu); + append_menu_item_center(menu); append_menu_items_mirror(menu); menu->AppendSeparator(); append_menu_item_per_object_process(menu); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 258542d..95140a9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2123,12 +2123,7 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false take_snapshot((type == ModelVolumeType::MODEL_PART) ? "Load Part" : "Load Modifier"); std::vector volumes; - // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common - /* - if (type == ModelVolumeType::MODEL_PART) - load_part(*(*m_objects)[obj_idx], volumes, type, from_galery); - else*/ - load_modifier(input_files, *(*m_objects)[obj_idx], volumes, type, from_galery); + load_from_files(input_files, *(*m_objects)[obj_idx], volumes, type, from_galery); if (volumes.empty()) return; @@ -2151,73 +2146,9 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false //QDS: notify partplate the modify notify_instance_updated(obj_idx); } -/* -void ObjectList::load_part(ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false) + +void ObjectList::load_from_files(const wxArrayString &input_files, ModelObject &model_object, std::vector &added_volumes, ModelVolumeType type, bool from_galery) { - if (type != ModelVolumeType::MODEL_PART) - return; - - wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); - - wxArrayString input_files; - - if (from_galery) { - GalleryDialog dlg(this); - if (dlg.ShowModal() == wxID_CLOSE) - return; - dlg.get_input_files(input_files); - if (input_files.IsEmpty()) - return; - } - else - wxGetApp().import_model(parent, input_files); - - ProgressDialog dlg(_L("Loading") + dots, "", 100, wxGetApp().mainframe wxPD_AUTO_HIDE); - wxBusyCursor busy; - - for (size_t i = 0; i < input_files.size(); ++i) { - std::string input_file = input_files.Item(i).ToUTF8().data(); - - dlg.Update(static_cast(100.0f * static_cast(i) / static_cast(input_files.size())), - _L("Loading file") + ": " + from_path(boost::filesystem::path(input_file).filename())); - dlg.Fit(); - - Model model; - try { - model = Model::read_from_file(input_file); - } - catch (std::exception &e) { - auto msg = _L("Error!") + " " + input_file + " : " + e.what() + "."; - show_error(parent, msg); - exit(1); - } - - for (auto object : model.objects) { - Vec3d delta = Vec3d::Zero(); - if (model_object.origin_translation != Vec3d::Zero()) { - object->center_around_origin(); - delta = model_object.origin_translation - object->origin_translation; - } - for (auto volume : object->volumes) { - volume->translate(delta); - auto new_volume = model_object.add_volume(*volume, type); - new_volume->name = boost::filesystem::path(input_file).filename().string(); - // set a default extruder value, since user can't add it manually - // QDS - new_volume->config.set_key_value("extruder", new ConfigOptionInt(1)); - - added_volumes.push_back(new_volume); - } - } - } -} -*/ -void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery) -{ - // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common - //if (type == ModelVolumeType::MODEL_PART) - // return; - wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); ProgressDialog dlg(_L("Loading") + dots, "", 100, wxGetApp().mainframe, wxPD_AUTO_HIDE); @@ -2264,14 +2195,25 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo show_error(parent, msg); return; } - + wxGetApp().plater()->statistics_burial_data(input_files[0].utf8_string()); + bool has_instance = false; + bool has_origin_translation = model_object.origin_translation != Vec3d::Zero(); if (from_galery) model.center_instances_around_point(Vec2d::Zero()); else { for (auto object : model.objects) { - if (model_object.origin_translation != Vec3d::Zero()) { + if (object->instances.size() > 0) { + has_instance = true; + } + if (has_origin_translation) { object->center_around_origin(); - const Vec3d delta = model_object.origin_translation - object->origin_translation; + Vec3d delta ; + if (model_object.volumes.size() == 1) { + delta = model_object.origin_translation - object->origin_translation; + } else { + auto _plate_origin = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_origin(); + delta = instance_offset - _plate_origin - object->origin_translation; + } for (auto volume : object->volumes) { volume->translate(delta); } @@ -2280,7 +2222,7 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo } model.add_default_instances(); - TriangleMesh mesh = model.mesh(); + TriangleMesh mesh = model.mesh();//world mesh // Mesh will be centered when loading. ModelVolume* new_volume = model_object.add_volume(std::move(mesh), type); new_volume->name = boost::filesystem::path(input_file).filename().string(); @@ -2295,20 +2237,32 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo new_volume->source.input_file = input_file; new_volume->source.object_idx = obj_idx; new_volume->source.volume_idx = int(model_object.volumes.size()) - 1; - if (model.objects.size() == 1 && model.objects.front()->volumes.size() == 1) + if (model.objects.size() == 1 && model.objects.front()->volumes.size() == 1) { new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset; - - if (from_galery) { - // 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(inst_transform, mesh_bb)); - // Set the modifier position. - // Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed. - const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset; - new_volume->set_offset(inv_inst_transform * offset); } - else - new_volume->set_offset(new_volume->source.mesh_offset - model_object.volumes.front()->source.mesh_offset); + + auto update_new_volume_tran_ignore_scale = [](ModelVolume *new_volume, const BoundingBoxf3 &mesh_bb, const BoundingBoxf3 &instance_bb, + const Geometry::Transformation& inst_transform, Vec3d instance_offset) { + new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(inst_transform, mesh_bb)); + const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset; + new_volume->set_offset(inst_transform.get_matrix_no_offset().inverse() * offset); + }; + const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); + if (from_galery) { + update_new_volume_tran_ignore_scale(new_volume, mesh_bb, instance_bb, inst_transform, instance_offset); + } + else { + if (has_instance || has_origin_translation == false) { //1. load 3mf //2. one 3mf load stl + update_new_volume_tran_ignore_scale(new_volume, mesh_bb, instance_bb, inst_transform, instance_offset); + } else { + Vec3d offset = Vec3d::Zero(); + offset = new_volume->source.mesh_offset - model_object.volumes.front()->source.mesh_offset; + if (model_object.volumes.size() > 1) { + offset += model_object.volumes.front()->get_offset(); + } + new_volume->set_offset(offset); + } + } added_volumes.push_back(new_volume); } @@ -6414,7 +6368,9 @@ void ObjectList::update_after_undo_redo() wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(int obj_idx, std::function add_to_selection/* = nullptr*/) { wxDataViewItemArray items; - + if (obj_idx < 0 || obj_idx >= m_objects->size()) { + return items; + } ModelObject* object = (*m_objects)[obj_idx]; if (object->volumes.size() <= 1) return items; diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index c89c8f1..1d47faa 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -285,9 +285,7 @@ public: bool is_instance_or_object_selected(); void load_subobject(ModelVolumeType type, bool from_galery = false); - // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common - //void load_part(ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); - void load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); + void load_from_files(const wxArrayString &input_files, ModelObject &model_object, std::vector &added_volumes, ModelVolumeType type, bool from_galery = false); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); void add_new_model_object_from_old_object(); void load_shape_object(const std::string &type_name); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 3a2e935..4738475 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -171,8 +171,9 @@ 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()) + 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 @@ -263,13 +264,16 @@ BoundingBoxf3 GLGizmoAdvancedCut::transformed_bounding_box(const Vec3d &plane_ce const Selection &selection = m_parent.get_selection(); const auto first_volume = selection.get_first_volume(); + BoundingBoxf3 ret; + if (!first_volume) { + return ret; + } Vec3d instance_offset = first_volume->get_instance_offset(); instance_offset[Z] += first_volume->get_sla_shift_z(); const auto cut_matrix = Transform3d::Identity() * rotation_m.inverse() * Geometry::translation_transform(instance_offset - plane_center); const Selection::IndicesList &idxs = selection.get_volume_idxs(); - BoundingBoxf3 ret; for (unsigned int i : idxs) { const GLVolume *volume = selection.get_volume(i); // respect just to the solid parts for FFF and ignore pad and supports for SLA @@ -2370,7 +2374,11 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b render_part_action_line( "A", "##upper", m_keep_upper, m_place_on_cut_upper, m_rotate_upper); render_part_action_line( "B", "##lower", m_keep_lower, m_place_on_cut_lower, m_rotate_lower); - m_imgui->disabled_begin(has_connectors || m_cut_mode == CutMode::cutTongueAndGroove); + if (m_part_selection && m_part_selection->has_modified_cut_parts()) { + m_cut_to_parts = false; + } + m_imgui->disabled_begin(has_connectors || (m_part_selection && m_part_selection->has_modified_cut_parts() && m_part_selection->valid()) || + m_cut_mode == CutMode::cutTongueAndGroove); m_imgui->qdt_checkbox(_L("Cut to parts"), m_cut_to_parts); if (m_cut_to_parts) { m_keep_upper = m_keep_lower = true; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 8bde014..a4c12e6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -111,7 +111,7 @@ bool GLGizmoFdmSupports::on_init() m_desc["smart_fill_angle"] = _L("Smart fill angle"); m_desc["on_overhangs_only"] = _L("On overhangs only"); - memset(&m_print_instance, sizeof(m_print_instance), 0); + memset(&m_print_instance, 0, sizeof(m_print_instance)); return true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp index 794be57..ee1f858 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp @@ -90,7 +90,7 @@ bool GLGizmoFuzzySkin::on_init() m_desc["smart_fill_angle_caption"] = ctrl + _L("Mouse wheel"); m_desc["smart_fill_angle"] = _L("Smart fill angle"); - memset(&m_print_instance, sizeof(m_print_instance), 0); + memset(&m_print_instance, 0, sizeof(m_print_instance)); return true; } @@ -304,14 +304,13 @@ void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_lim } } - 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) { + ImGui::Separator(); m_cursor_type = TriangleSelector::CursorType::CIRCLE; m_tool_type = ToolType::BRUSH; @@ -324,6 +323,7 @@ void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_lim 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) { + ImGui::Separator(); m_cursor_type = TriangleSelector::CursorType::SPHERE; m_tool_type = ToolType::BRUSH; @@ -336,6 +336,7 @@ void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_lim 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) { + ImGui::Separator(); m_cursor_type = TriangleSelector::CursorType::POINTER; m_tool_type = ToolType::SMART_FILL; @@ -385,7 +386,6 @@ void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_lim 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); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 92668af..0fc9fe5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -533,6 +533,9 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons } void GLGizmoRotate::init_data_from_selection(const Selection &selection) { + if (selection.is_empty()) { + return; + } const auto [box, box_trafo] = m_force_local_coordinate ? selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system(); m_bounding_box = box; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp index 733c992..b2701b2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp @@ -1335,7 +1335,7 @@ void GLGizmoSVG::draw_window() if (m_volume == nullptr) return; ImGui::Separator(); - + ImGui::Indent(m_gui_cfg->icon_width); draw_depth(); draw_size(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 694f47e..f7c42c9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -1187,7 +1187,8 @@ void GLGizmoText::draw_model_type(int caption_width) 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()); + 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 @@ -1282,8 +1283,20 @@ void GLGizmoText::draw_rotation(int caption_size, int slider_width, int drag_lef 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 need_deal = false; + if (abs(m_rotate_angle - 180.f) < 0.01f || abs(m_rotate_angle + 180) < 0.01f) { + if (abs(m_rotate_angle - m_rotate_angle_min_max) > 0.01f) { + m_rotate_angle_min_max = m_rotate_angle; + need_deal = true; + } + } else { + need_deal = true; + m_rotate_angle_min_max = 0.f; + } + if (need_deal) { + 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; @@ -1294,6 +1307,7 @@ void GLGizmoText::draw_rotation(int caption_size, int slider_width, int drag_lef 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 + update_trafo_matrices(); volume_transformation_changed(); } } @@ -1478,12 +1492,13 @@ bool GLGizmoText::on_shortcut_key() { 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 + Vec3d offset_tr(0, -instance_bb.size().y() / 2.f - 2.f, -instance_bb.size().z() / 2.f + 0.015f); // lay on bed// 0.015f is from SAFE_SURFACE_OFFSET auto mo_tran = mo->instances[instance_index]->get_transformation(); + Transform3d inv_tr = mo_tran.get_matrix_no_offset().inverse(); 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_tran_in_object.set_offset(inv_tr * offset_tr); + m_text_position_in_world = (mo_tran * m_text_tran_in_object).get_offset(); m_text_normal_in_world = Vec3f::UnitZ(); m_need_update_text = true; m_volume_idx = -1; @@ -1561,8 +1576,14 @@ void GLGizmoText::load_init_text(bool first_open_text) if (m_last_text_mv == model_volume && !m_is_serializing) { return; } + if (m_last_text_mv != model_volume) { + first_open_text = true; + } m_last_text_mv = model_volume; m_is_direct_create_text = is_only_text_case(); + if (first_open_text) { + m_c->update(get_requirements()); + } if (!m_is_serializing && plater && first_open_text && !is_old_text_info(model_volume->get_text_info())) { plater->take_snapshot("enter Text"); } @@ -1670,14 +1691,14 @@ void GLGizmoText::load_init_text(bool first_open_text) 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(); + Vec3f local_center = m_text_tran_in_world.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()); + text_attach_mesh.transform(m_model_object_in_world_tran.get_matrix() * 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); @@ -1696,13 +1717,16 @@ void GLGizmoText::load_init_text(bool first_open_text) if (m_trafo_matrices.empty()) { update_trafo_matrices(); } + Geometry::Transformation temp__tran(m_trafo_matrices[m_rr.mesh_id]); + m_rr.normal = temp__tran.get_matrix_no_offset().cast().inverse() * closest_normal; + m_rr.hit = temp__tran.get_matrix().cast().inverse() * closest_pt; 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(); + m_fix_text_position_in_world = closest_pt.cast(); + m_fix_text_normal_in_world = closest_normal; if (is_old_text_info(text_info)) { int face_id; Vec3f direction = m_text_tran_in_world.get_matrix().linear().col(2).cast(); @@ -1952,6 +1976,7 @@ void GLGizmoText::on_stop_dragging() 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 + update_trafo_matrices(); m_need_update_text = true; } else { m_rotate_gizmo.stop_dragging(); @@ -2297,8 +2322,21 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit) ImGui::SameLine(drag_left_width); ImGui::PushItemWidth(1.5 * slider_icon_width); - if (ImGui::QDTDragFloat("##text_gap_input", &m_text_gap, 0.05f, -10.f, 100.f, "%.2f")) - m_need_update_text = true; + if (ImGui::QDTDragFloat("##text_gap_input", &m_text_gap, 0.05f, -10.f, 100.f, "%.2f")) { + bool need_deal = false; + if (abs(m_text_gap_min_max - 100.f) < 0.01f || abs(m_text_gap_min_max + 10) < 0.01f) { + if (abs(m_text_gap - m_text_gap_min_max) > 0.01f) { + m_text_gap_min_max = m_text_gap; + need_deal = true; + } + } else { + need_deal = true; + m_text_gap_min_max = 0.f; + } + if (need_deal) { + m_need_update_text = true; + } + } draw_rotation(caption_size, slider_width, drag_left_width, slider_icon_width); #if QDT_RELEASE_TO_PUBLIC @@ -2334,6 +2372,10 @@ 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_font_version == NEW_FONT_BEGIN_VERSION) { + m_imgui->warning_text_wrapped(_L("Warning:current text spacing is not very reasonable. If you continue editing, a more reasonable text spacing will be generated.") + ,full_width); + } /* 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); @@ -2888,26 +2930,14 @@ void GLGizmoText::reset_text_info() void GLGizmoText::update_text_pos_normal() { if (m_rr.mesh_id < 0) { return; } if (m_rr.normal.norm() < 0.1) { return; } - const Selection &selection = m_parent.get_selection(); - auto mo = selection.get_model()->objects[m_object_idx]; - if (mo == nullptr) { - BOOST_LOG_TRIVIAL(info) << boost::format("Text: selected object is null"); - return; - } - const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - - std::vector w_matrices; - std::vector mv_trans; - 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())); - } + if (m_rr.mesh_id >= m_trafo_matrices.size()) { return; } #ifdef DEBUG_TEXT_VALUE m_rr.hit = Vec3f(-0.58, -1.70, -12.8); m_rr.normal = Vec3f(0,0,-1);//just rotate cube #endif - m_text_position_in_world = w_matrices[m_rr.mesh_id].get_matrix() * m_rr.hit.cast(); - m_text_normal_in_world = (w_matrices[m_rr.mesh_id].get_matrix_no_offset().cast() * m_rr.normal).normalized(); + Geometry::Transformation cur_tran(m_trafo_matrices[m_rr.mesh_id]); + m_text_position_in_world = cur_tran.get_matrix() * m_rr.hit.cast(); + m_text_normal_in_world = (cur_tran.get_matrix_no_offset().cast() * m_rr.normal).normalized(); } bool GLGizmoText::filter_model_volume(ModelVolume *mv) { @@ -3103,7 +3133,7 @@ bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera if (m_rr.mouse_position == mouse_position) { return false; } - + if (m_object_idx < 0) { return false; } Vec3f normal = Vec3f::Zero(); Vec3f hit = Vec3f::Zero(); size_t facet = 0; @@ -3112,10 +3142,15 @@ bool GLGizmoText::update_raycast_cache(const Vec2d &mouse_position, const Camera double closest_hit_squared_distance = std::numeric_limits::max(); int closest_hit_mesh_id = -1; + const Selection &selection = m_parent.get_selection(); + auto mo = selection.get_model()->objects[m_object_idx]; // 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 (exclude_last && mesh_id == int(trafo_matrices.size()) - 1) continue; + if (!filter_model_volume(mo->volumes[mesh_id])) { + continue; + } 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)) { @@ -3429,7 +3464,7 @@ void init_face_names(CurFacenames &face_names) 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 + if (face_names.faces_names.size() == 0) {//FIX by qds 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++) { @@ -3739,9 +3774,9 @@ EmbossShape &TextDataBase::create_shape() }; 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); + text2vshapes(shape, m_font_file, text_w, fp, shape.scale, was_canceled, ft_fn); } else { - text2vshapes(shape, m_font_file, text_w, fp, was_canceled); + text2vshapes(shape, m_font_file, text_w, fp, shape.scale, was_canceled); } return shape; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp index 27c2c94..ad15e6c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.hpp @@ -24,7 +24,9 @@ enum class SLAGizmoEventType : unsigned char; //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"; +//2.2 mean v2.2 qidi version(20250815) +const std::string NEW_FONT_BEGIN_VERSION = "2.0"; +const std::string CUR_FONT_VERSION = "2.2"; class GLGizmoText : public GLGizmoBase { private: @@ -151,6 +153,9 @@ private: const std::string move_snapshot_name = "Text move"; const std::string rotation_snapshot_name = "Text rotate"; + float m_rotate_angle_min_max = 0.f; + float m_text_gap_min_max = 0.f; + public: GLGizmoText(GLCanvas3D& parent, unsigned int sprite_id); ~GLGizmoText(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index abcbeb9..737f0bd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -186,6 +186,11 @@ bool GLGizmosManager::init_icon_textures() else return false; + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/helio_icon.svg", 16, 16, texture_id)) + icon_list.insert(std::make_pair((int) IC_HELIO_ICON, texture_id)); + else + return false; + 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 diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index b0ebe10..24f2321 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -138,6 +138,7 @@ public: IC_FIT_CAMERA_HOVER, IC_FIT_CAMERA_DARK, IC_FIT_CAMERA_DARK_HOVER, + IC_HELIO_ICON, }; explicit GLGizmosManager(GLCanvas3D& parent); diff --git a/src/slic3r/GUI/HMS.cpp b/src/slic3r/GUI/HMS.cpp index 14a9e5d..bc81982 100644 --- a/src/slic3r/GUI/HMS.cpp +++ b/src/slic3r/GUI/HMS.cpp @@ -1,5 +1,8 @@ #include "HMS.hpp" + #include "DeviceManager.hpp" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevUtil.h" #include @@ -7,8 +10,7 @@ static const char* HMS_PATH = "hms"; static const char* HMS_LOCAL_IMG_PATH = "hms/local_image"; // the local HMS info -static unordered_set package_dev_id_types {"094"}; -//static unordered_set cloud_dev_id_types{"00M", "00W", "03W", "01P", "01S", "030", "039", "094"}; +static unordered_set package_dev_id_types {"094", "239", "093"}; namespace Slic3r { namespace GUI { @@ -34,7 +36,7 @@ int get_hms_info_version(std::string& version) try { json j = json::parse(body); if (j.contains("ver")) { - version = JsonValParser::get_longlong_val(j["ver"]); + version = DevJsonValParser::get_longlong_val(j["ver"]); } } catch (...) { ; @@ -88,7 +90,7 @@ int HMSQuery::download_hms_related(const std::string& hms_type, const std::strin return; } - const std::string& remote_ver = JsonValParser::get_longlong_val(j["ver"]); + const std::string& remote_ver = DevJsonValParser::get_longlong_val(j["ver"]); if (remote_ver <= local_version) { return; @@ -201,10 +203,10 @@ int HMSQuery::load_from_local(const std::string& hms_type, const std::string& de } if (j.contains("version")) { - load_version = JsonValParser::get_longlong_val(j["version"]); + load_version = DevJsonValParser::get_longlong_val(j["version"]); } else if (j.contains("ver")) { - load_version = JsonValParser::get_longlong_val(j["ver"]); + load_version = DevJsonValParser::get_longlong_val(j["ver"]); } else { @@ -311,7 +313,7 @@ string HMSQuery::get_dev_id_type(const MachineObject* obj) const { if (obj) { - return obj->dev_id.substr(0, 3); + return obj->get_dev_id().substr(0, 3); } return string(); @@ -613,7 +615,14 @@ void HMSQuery::init_hms_info(const std::string& dev_type_id) /*download from cloud*/ time_t info_last_update_time = m_cloud_hms_last_update_time[dev_type_id]; - if (time(nullptr) - info_last_update_time > (60 * 60 * 24))/*do not update in one day to reduce waiting*/ + + /* check hms is valid or not */ + bool retry = false; + if(m_hms_info_jsons[dev_type_id].empty() || m_hms_action_jsons[dev_type_id].empty()){ + retry =time(nullptr) - info_last_update_time > (60 * 1); // retry after 1 minute + } + + if (time(nullptr) - info_last_update_time > (60 * 60 * 24) || retry)/*do not update in one day to reduce waiting*/ { download_hms_related(QUERY_HMS_INFO, dev_type_id, &m_hms_info_jsons[dev_type_id]); download_hms_related(QUERY_HMS_ACTION, dev_type_id, &m_hms_action_jsons[dev_type_id]); @@ -638,11 +647,11 @@ std::string get_hms_wiki_url(std::string error_code) MachineObject* obj = dev->get_selected_machine(); if (!obj) return url; - if (!obj->dev_id.empty()) { + if (!obj->get_dev_id().empty()) { url = (boost::format("https://%1%/index.php?e=%2%&d=%3%&s=device_hms&lang=%4%") % hms_host % error_code - % obj->dev_id + % obj->get_dev_id() % lang_code).str(); } return url; diff --git a/src/slic3r/GUI/HMSPanel.cpp b/src/slic3r/GUI/HMSPanel.cpp index 8494faa..fe99d55 100644 --- a/src/slic3r/GUI/HMSPanel.cpp +++ b/src/slic3r/GUI/HMSPanel.cpp @@ -16,7 +16,7 @@ namespace GUI { wxDEFINE_EVENT(EVT_ALREADY_READ_HMS, wxCommandEvent); -HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, HMSItem& item) +HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMSItem& item) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL) , m_hms_item(item) , dev_id(dev_id) @@ -140,7 +140,7 @@ void HMSNotifyItem::init_bitmaps() { wxBitmap & HMSNotifyItem::get_notify_bitmap() { - switch (m_hms_item.msg_level) { + switch (m_hms_item.get_level()) { case (HMS_FATAL): return m_img_notify_lv1; break; @@ -153,8 +153,6 @@ wxBitmap & HMSNotifyItem::get_notify_bitmap() case (HMS_INFO): //return m_img_notify_lv4; break; - case (HMS_UNKNOWN): - case (HMS_MSG_LEVEL_MAX): default: break; } return wxNullBitmap; @@ -187,7 +185,7 @@ HMSPanel::~HMSPanel() { ; } -void HMSPanel::append_hms_panel(const std::string& dev_id, HMSItem& item) { +void HMSPanel::append_hms_panel(const std::string& dev_id, DevHMSItem& item) { wxString msg = wxGetApp().get_hms_query()->query_hms_msg(dev_id, item.get_long_error_code()); if (!msg.empty()) { HMSNotifyItem *notify_item = new HMSNotifyItem(dev_id, m_scrolledWindow, item); @@ -214,7 +212,7 @@ void HMSPanel::update(MachineObject *obj) this->Freeze(); delete_hms_panels(); wxString hms_text; - for (auto item : obj->hms_list) { + for (auto item : obj->GetHMS()->GetHMSItems()) { if (wxGetApp().get_hms_query()) { auto key = item.get_long_error_code(); @@ -223,14 +221,14 @@ void HMSPanel::update(MachineObject *obj) temp_hms_list[key] = item; } - append_hms_panel(obj->dev_id, item); + append_hms_panel(obj->get_dev_id(), item); } } for (auto it = temp_hms_list.begin(); it != temp_hms_list.end(); ) { auto key = it->second.get_long_error_code(); bool inr = false; - for (auto hms : obj->hms_list) { + for (auto hms : obj->GetHMS()->GetHMSItems()) { if (hms.get_long_error_code() == key) { inr = true; break; diff --git a/src/slic3r/GUI/HMSPanel.hpp b/src/slic3r/GUI/HMSPanel.hpp index 098fb22..4991059 100644 --- a/src/slic3r/GUI/HMSPanel.hpp +++ b/src/slic3r/GUI/HMSPanel.hpp @@ -9,12 +9,14 @@ #include #include +#include "DeviceCore/DevHMS.h" + namespace Slic3r { namespace GUI { class HMSNotifyItem : public wxPanel { - HMSItem & m_hms_item; + DevHMSItem & m_hms_item; std::string m_url; std::string dev_id; std::string long_error_code; @@ -35,7 +37,7 @@ class HMSNotifyItem : public wxPanel wxBitmap & get_notify_bitmap(); public: - HMSNotifyItem(const std::string& dev_id, wxWindow *parent, HMSItem& item); + HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMSItem& item); ~HMSNotifyItem(); void msw_rescale() {} @@ -50,7 +52,7 @@ protected: int last_status; - void append_hms_panel(const std::string& dev_id, HMSItem &item); + void append_hms_panel(const std::string& dev_id, DevHMSItem &item); void delete_hms_panels(); @@ -69,7 +71,7 @@ public: void clear_hms_tag(); MachineObject *obj { nullptr }; - std::map temp_hms_list; + std::map temp_hms_list; }; wxDECLARE_EVENT(EVT_ALREADY_READ_HMS, wxCommandEvent); diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index 7f39d7b..560d767 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -288,20 +288,13 @@ namespace { } //namespace HintDatabase::~HintDatabase() { - if (m_initialized) { - write_used_binary(m_used_ids); - } } void HintDatabase::uninit() { - if (m_initialized) { - write_used_binary(m_used_ids); - } m_initialized = false; m_loaded_hints.clear(); - m_sorted_hints = false; - m_used_ids.clear(); - m_used_ids_loaded = false; + //m_sorted_hints = false; + m_loaded_helio_hints.clear(); } void HintDatabase::reinit() { @@ -311,16 +304,20 @@ void HintDatabase::reinit() } void HintDatabase::init() { - load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini")); + load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini"), m_loaded_hints); + load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "helio_hints.ini"), m_loaded_helio_hints); m_initialized = true; init_random_hint_id(); } void HintDatabase::init_random_hint_id() { srand(time(NULL)); - m_hint_id = rand() % m_loaded_hints.size(); + if (!m_loaded_hints.empty()) + m_hint_id = rand() % m_loaded_hints.size(); + if (!m_loaded_helio_hints.empty()) + m_helio_hint_id = rand() % m_loaded_helio_hints.size(); } -void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) +void HintDatabase::load_hints_from_file(const boost::filesystem::path& path, std::vector& hints_vector) { namespace pt = boost::property_tree; pt::ptree tree; @@ -355,7 +352,7 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) std::string img_url; // randomized weighted order variables size_t weight = 1; - bool was_displayed = is_used(id_string); + bool was_displayed = false; //unescape text1 unescape_string_cstyle(dict["text"], fulltext); fulltext = _utf8(fulltext); @@ -431,7 +428,7 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) if (dict["hypertext_type"] == "link") { std::string hypertext_link = dict["hypertext_link"]; HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [hypertext_link]() { launch_browser_if_allowed(hypertext_link); } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); // highlight settings } else if (dict["hypertext_type"] == "settings") { @@ -439,24 +436,24 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) Preset::Type type = static_cast(std::atoi(dict["hypertext_settings_type"].c_str())); std::wstring category = boost::nowide::widen(dict["hypertext_settings_category"]); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); // open preferences } else if (dict["hypertext_type"] == "preferences") { std::string page = dict["hypertext_preferences_page"]; std::string item = dict["hypertext_preferences_item"]; HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [page, item]() { wxGetApp().open_preferences(1, page); } };// 1 is to modify - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } else if (dict["hypertext_type"] == "plater") { std::string item = dict["hypertext_plater_item"]; HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_toolbar_item(item); } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } else if (dict["hypertext_type"] == "gizmo") { std::string item = dict["hypertext_gizmo_item"]; HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_gizmo(item); } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } else if (dict["hypertext_type"] == "gallery") { HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, []() { @@ -464,42 +461,57 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) wxGetApp().plater()->canvas3D()->deselect_all(); //wxGetApp().obj_list()->load_shape_object_from_gallery(); } } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } else if (dict["hypertext_type"] == "menubar") { wxString menu(_("&" + dict["hypertext_menubar_menu_name"])); wxString item(_(dict["hypertext_menubar_item_name"])); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } } else { // plain text without hypertext HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url }; - m_loaded_hints.emplace_back(hint_data); + hints_vector.emplace_back(hint_data); } } } } -HintData* HintDatabase::get_hint(HintDataNavigation nav) +HintData* HintDatabase::get_hint(HintDataNavigation nav, bool is_helio) { if (!m_initialized) { init(); nav = HintDataNavigation::Random; } - if (m_loaded_hints.empty()) - { - BOOST_LOG_TRIVIAL(error) << "There were no hints loaded from hints.ini file."; - return nullptr; + + if (is_helio) { + if (m_loaded_helio_hints.empty()) { + BOOST_LOG_TRIVIAL(error) << "There were no hints loaded from helio_hints.ini file."; + return nullptr; + } + } + else { + if (m_loaded_hints.empty()) + { + BOOST_LOG_TRIVIAL(error) << "There were no hints loaded from hints.ini file."; + return nullptr; + } } try { - if (nav == HintDataNavigation::Next) - m_hint_id = get_next_hint_id(); - if(nav == HintDataNavigation::Prev) - m_hint_id = get_prev_hint_id(); - if (nav == HintDataNavigation::Curr) { + if (nav == HintDataNavigation::Next) { + if (is_helio) + m_helio_hint_id = m_helio_hint_id < m_loaded_helio_hints.size() - 1 ? m_helio_hint_id + 1 : 0; + else + m_hint_id = m_hint_id < m_loaded_hints.size() - 1 ? m_hint_id + 1 : 0; + } + if (nav == HintDataNavigation::Prev) { + if (is_helio) + m_helio_hint_id = m_helio_hint_id > 0 ? m_helio_hint_id - 1 : m_loaded_helio_hints.size() - 1; + else + m_hint_id = m_hint_id > 0 ? m_hint_id - 1 : m_loaded_hints.size() - 1; } if (nav == HintDataNavigation::Random) init_random_hint_id(); @@ -509,116 +521,59 @@ HintData* HintDatabase::get_hint(HintDataNavigation nav) return nullptr; } - return &m_loaded_hints[m_hint_id]; + return is_helio ? &m_loaded_helio_hints[m_helio_hint_id] : &m_loaded_hints[m_hint_id]; } -size_t HintDatabase::get_next_hint_id() -{ - return m_hint_id < m_loaded_hints.size() - 1 ? m_hint_id + 1 : 0; -} +// bool HintDatabase::is_used(const std::string& id) +// { +// // load used ids from file +// if (!m_used_ids_loaded) { +// read_used_binary(m_used_ids); +// m_used_ids_loaded = true; +// } +// // check if id is in used +// for (const std::string& used_id : m_used_ids) { +// if (used_id == id) +// { +// return true; +// } +// } +// return false; +// } +// void HintDatabase::set_used(const std::string& id) +// { +// // check needed? +// if (!is_used(id)) +// { +// m_used_ids.emplace_back(id); +// } +// } +// void HintDatabase::clear_used() +// { +// m_used_ids.clear(); +// } -size_t HintDatabase::get_prev_hint_id() -{ - return m_hint_id > 0 ? m_hint_id - 1 : m_loaded_hints.size() - 1; -} - -size_t HintDatabase::get_random_next() -{ - if (!m_sorted_hints) - { - auto compare_wieght = [](const HintData& a, const HintData& b) { return a.weight < b.weight; }; - std::sort(m_loaded_hints.begin(), m_loaded_hints.end(), compare_wieght); - m_sorted_hints = true; - srand(time(NULL)); - } - std::vector candidates; // index in m_loaded_hints - // total weight - size_t total_weight = 0; - for (size_t i = 0; i < m_loaded_hints.size(); i++) { - if (!m_loaded_hints[i].was_displayed && tags_check(m_loaded_hints[i].disabled_tags, m_loaded_hints[i].enabled_tags)) { - candidates.emplace_back(i); - total_weight += m_loaded_hints[i].weight; - } - } - // all were shown - if (total_weight == 0) { - clear_used(); - for (size_t i = 0; i < m_loaded_hints.size(); i++) { - m_loaded_hints[i].was_displayed = false; - if (tags_check(m_loaded_hints[i].disabled_tags, m_loaded_hints[i].enabled_tags)) { - candidates.emplace_back(i); - total_weight += m_loaded_hints[i].weight; - } - } - } - if (total_weight == 0) { - BOOST_LOG_TRIVIAL(error) << "Hint notification random number generator failed. No suitable hint was found."; - throw std::exception(); - } - size_t random_number = rand() % total_weight + 1; - size_t current_weight = 0; - for (size_t i = 0; i < candidates.size(); i++) { - current_weight += m_loaded_hints[candidates[i]].weight; - if (random_number <= current_weight) { - set_used(m_loaded_hints[candidates[i]].id_string); - m_loaded_hints[candidates[i]].was_displayed = true; - return candidates[i]; - } - } - BOOST_LOG_TRIVIAL(error) << "Hint notification random number generator failed."; - throw std::exception(); -} - -bool HintDatabase::is_used(const std::string& id) -{ - // load used ids from file - if (!m_used_ids_loaded) { - read_used_binary(m_used_ids); - m_used_ids_loaded = true; - } - // check if id is in used - for (const std::string& used_id : m_used_ids) { - if (used_id == id) - { - return true; - } - } - return false; -} -void HintDatabase::set_used(const std::string& id) -{ - // check needed? - if (!is_used(id)) - { - m_used_ids.emplace_back(id); - } -} -void HintDatabase::clear_used() -{ - m_used_ids.clear(); -} - -void NotificationManager::HintNotification::count_spaces() -{ - //determine line width - m_line_height = ImGui::CalcTextSize("A").y; +// void NotificationManager::HintNotification::count_spaces() +// { +// //determine line width +// m_line_height = ImGui::CalcTextSize("A").y; - std::string text; - text = ImGui::WarningMarker; - float picture_width = ImGui::CalcTextSize(text.c_str()).x; - m_left_indentation = picture_width * 1.5f + m_line_height / 2; +// std::string text; +// text = ImGui::WarningMarker; +// float picture_width = ImGui::CalcTextSize(text.c_str()).x; +// m_left_indentation = picture_width * 1.5f + m_line_height / 2; - // no left button picture - //m_left_indentation = m_line_height; +// // no left button picture +// //m_left_indentation = m_line_height; - if (m_documentation_link.empty()) - m_window_width_offset = m_left_indentation + m_line_height * 3.f; - else - m_window_width_offset = m_left_indentation + m_line_height * 5.5f; +// if (m_documentation_link.empty()) +// m_window_width_offset = m_left_indentation + m_line_height * 3.f; +// else +// m_window_width_offset = m_left_indentation + m_line_height * 5.5f; - m_window_width = m_line_height * 25; -} +// m_window_width = m_line_height * 25; +// } static int get_utf8_seq_length(const char* seq, size_t size) { @@ -690,476 +645,5 @@ static int get_utf8_seq_length(const std::string& text, size_t pos) return get_utf8_seq_length(text.c_str() + pos, text.size() - pos); } -void NotificationManager::HintNotification::count_lines() -{ - std::string text = m_text1; - size_t last_end = 0; - m_lines_count = 0; - - if (text.empty()) - return; - - m_endlines.clear(); - while (last_end < text.length() - 1) - { - size_t next_hard_end = text.find_first_of('\n', last_end); - if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) { - //next line is ended by '/n' - m_endlines.push_back(next_hard_end); - last_end = next_hard_end + 1; - } - else { - // find next suitable endline - if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) { - // more than one line till end - size_t next_space = text.find_first_of(' ', last_end); - if (next_space > 0 && next_space < text.length()) { - size_t next_space_candidate = text.find_first_of(' ', next_space + 1); - while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset) { - next_space = next_space_candidate; - next_space_candidate = text.find_first_of(' ', next_space + 1); - } - } - else { - next_space = text.length(); - } - // when one word longer than line. - if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset || - ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x < (m_window_width - m_window_width_offset) / 5 * 3 - ) { - float width_of_a = ImGui::CalcTextSize("a").x; - int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a); - while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) { - letter_count += get_utf8_seq_length(text, last_end + letter_count); - } - m_endlines.push_back(last_end + letter_count); - last_end += letter_count; - } - else { - m_endlines.push_back(next_space); - last_end = next_space + 1; - } - } - else { - m_endlines.push_back(text.length()); - last_end = text.length(); - } - - } - m_lines_count++; - } - int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; - int size_of_last_line = ImGui::CalcTextSize(text.substr(prev_end, last_end - prev_end).c_str()).x; - // hypertext calculation - if (!m_hypertext.empty()) { - if (size_of_last_line + ImGui::CalcTextSize(m_hypertext.c_str()).x > m_window_width - m_window_width_offset) { - // hypertext on new line - size_of_last_line = ImGui::CalcTextSize((m_hypertext + " ").c_str()).x; - m_endlines.push_back(last_end); - m_lines_count++; - } - else { - size_of_last_line += ImGui::CalcTextSize((m_hypertext + " ").c_str()).x; - } - } - if (!m_text2.empty()) { - text = m_text2; - last_end = 0; - m_endlines2.clear(); - // if size_of_last_line too large to fit anything - size_t first_end = std::min(text.find_first_of('\n'), text.find_first_of(' ')); - if (size_of_last_line >= m_window_width - m_window_width_offset - ImGui::CalcTextSize(text.substr(0, first_end).c_str()).x) { - m_endlines2.push_back(0); - size_of_last_line = 0; - } - while (last_end < text.length() - 1) - { - size_t next_hard_end = text.find_first_of('\n', last_end); - if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { - //next line is ended by '/n' - m_endlines2.push_back(next_hard_end); - last_end = next_hard_end + 1; - } - else { - // find next suitable endline - if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset - size_of_last_line) { - // more than one line till end - size_t next_space = text.find_first_of(' ', last_end); - if (next_space > 0) { - size_t next_space_candidate = text.find_first_of(' ', next_space + 1); - while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { - next_space = next_space_candidate; - next_space_candidate = text.find_first_of(' ', next_space + 1); - } - } - else { - next_space = text.length(); - } - // when one word longer than line. - if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset - size_of_last_line || - ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x + size_of_last_line < (m_window_width - m_window_width_offset) / 5 * 3 - ) { - float width_of_a = ImGui::CalcTextSize("a").x; - int letter_count = (int)((m_window_width - m_window_width_offset - size_of_last_line) / width_of_a); - while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { - letter_count += get_utf8_seq_length(text, last_end + letter_count); - } - m_endlines2.push_back(last_end + letter_count); - last_end += letter_count; - } - else { - m_endlines2.push_back(next_space); - last_end = next_space + 1; - } - } - else { - m_endlines2.push_back(text.length()); - last_end = text.length(); - } - - } - if (size_of_last_line == 0) // if first line is continuation of previous text, do not add to line count. - m_lines_count++; - size_of_last_line = 0; // should countain value only for first line (with hypertext) - - } - } -} - -void NotificationManager::HintNotification::init() -{ - // Do not init closing notification - if (is_finished()) - return; - - count_spaces(); - count_lines(); - - m_multiline = true; - - m_notification_start = GLCanvas3D::timestamp_now(); - if (m_state == EState::Unknown) - m_state = EState::Shown; -} - -void NotificationManager::HintNotification::set_next_window_size(ImGuiWrapper& imgui) -{ - /* - m_window_height = m_multiline ? - (m_lines_count + 1.f) * m_line_height : - 4.f * m_line_height; - m_window_height += 1 * m_line_height; // top and bottom - */ - - m_window_height = std::max((m_lines_count + 1.f) * m_line_height, 5.f * m_line_height); -} - -bool NotificationManager::HintNotification::on_text_click() -{ - if (m_hypertext_callback != nullptr && (!m_runtime_disable || tags_check(m_disabled_tags, m_enabled_tags))) - m_hypertext_callback(); - return false; -} - -void NotificationManager::HintNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - if (!m_has_hint_data) { - retrieve_data(); - } - - float x_offset = m_left_indentation; - int last_end = 0; - float starting_y = (/*m_lines_count < 4 ? m_line_height / 2 * (4 - m_lines_count + 1) :*/ m_line_height / 2); - float shift_y = m_line_height; - std::string line; - - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_HyperTextColor); - for (size_t i = 0; i < (m_multiline ? /*m_lines_count*/m_endlines.size() : 2); i++) { - line.clear(); - ImGui::SetCursorPosX(x_offset); - ImGui::SetCursorPosY(starting_y + i * shift_y); - if (m_endlines.size() > i && m_text1.size() >= m_endlines[i]) { - if (i == 1 && m_endlines.size() > 2 && !m_multiline) { - // second line with "more" hypertext - line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0)); - while (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x) { - line = line.substr(0, line.length() - 1); - } - line += ".."; - } - else { - // regural line - line = m_text1.substr(last_end, m_endlines[i] - last_end); - } - // first line is headline (for hint notification it must be divided by \n) - if (m_text1.find('\n') >= m_endlines[i]) { - line = ImGui::ColorMarkerStart + line + ImGui::ColorMarkerEnd; - } - // Add ImGui::ColorMarkerStart if there is ImGui::ColorMarkerEnd first (start was at prev line) - if (line.find_first_of(ImGui::ColorMarkerEnd) < line.find_first_of(ImGui::ColorMarkerStart)) { - line = ImGui::ColorMarkerStart + line; - } - - last_end = m_endlines[i]; - if (m_text1.size() > m_endlines[i]) - last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0); - imgui.text(line.c_str()); - } - - } - //hyperlink text - if (!m_multiline && m_lines_count > 2) { - render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + " ").c_str()).x, starting_y + shift_y, _u8L("More"), true); - } - else if (!m_hypertext.empty()) { - render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext); - } - - // text2 - if (!m_text2.empty() && m_multiline) { - starting_y += (m_endlines.size() - 1) * shift_y; - last_end = 0; - for (size_t i = 0; i < (m_multiline ? m_endlines2.size() : 2); i++) { - if (i == 0) //first line X is shifted by hypertext - ImGui::SetCursorPosX(x_offset + ImGui::CalcTextSize((line + m_hypertext + (line.empty() ? " " : " ")).c_str()).x); - else - ImGui::SetCursorPosX(x_offset); - - ImGui::SetCursorPosY(starting_y + i * shift_y); - line.clear(); - if (m_endlines2.size() > i && m_text2.size() >= m_endlines2[i]) { - - // regural line - line = m_text2.substr(last_end, m_endlines2[i] - last_end); - - // Add ImGui::ColorMarkerStart if there is ImGui::ColorMarkerEnd first (start was at prev line) - if (line.find_first_of(ImGui::ColorMarkerEnd) < line.find_first_of(ImGui::ColorMarkerStart)) { - line = ImGui::ColorMarkerStart + line; - } - - last_end = m_endlines2[i]; - if (m_text2.size() > m_endlines2[i]) - last_end += (m_text2[m_endlines2[i]] == '\n' || m_text2[m_endlines2[i]] == ' ' ? 1 : 0); - imgui.text(line.c_str()); - } - - } - } - ImGui::PopStyleColor(1); -} - -void NotificationManager::HintNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - ImVec2 win_size(win_size_x, win_size_y); - ImVec2 win_pos(win_pos_x, win_pos_y); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); - push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); - - - std::wstring button_text; - button_text = m_is_dark ? ImGui::CloseNotifDarkButton : ImGui::CloseNotifButton; - - ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str()); - ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); - m_close_b_w = button_size.y; - if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y + win_size.y / 2 - button_pic_size.y), - ImVec2(win_pos.x, win_pos.y + win_size.y / 2 + button_pic_size.y), - true)) - { - button_text = m_is_dark ? ImGui::CloseNotifHoverDarkButton : ImGui::CloseNotifHoverButton; - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - close(); - } - ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f); - ImGui::SetCursorPosY(win_size.y / 2 - button_size.y); - if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) - { - close(); - } - - - ImGui::PopStyleColor(5); - - - render_right_arrow_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - //render_logo(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - render_preferences_button(imgui, win_pos_x, win_pos_y); - if (!m_documentation_link.empty() && wxGetApp().app_config->get("suppress_hyperlinks") != "1") - { - render_documentation_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - } - -} - -void NotificationManager::HintNotification::render_preferences_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) -{ - auto scale = wxGetApp().plater()->get_current_canvas3D()->get_scale(); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); - push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - - std::wstring button_text; - button_text = m_is_dark ? ImGui::PreferencesDarkButton : ImGui::PreferencesButton; - //hover - if (ImGui::IsMouseHoveringRect(ImVec2(win_pos_x - m_window_width / 15.f, win_pos_y + m_window_height - 1.5f * m_line_height), - ImVec2(win_pos_x, win_pos_y + m_window_height), - true)) { - button_text = m_is_dark ? ImGui::PreferencesHoverDarkButton : ImGui::PreferencesHoverButton; - // tooltip - ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND); - ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 }); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8 * scale, 1 * scale }); - ImGui::BeginTooltip(); - imgui.text(_u8L("Open Preferences.")); - ImGui::EndTooltip(); - ImGui::PopStyleColor(2); - ImGui::PopStyleVar(); - } - - ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str()); - ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); - ImGui::SetCursorPosX(m_window_width - m_line_height * 1.75f); - ImGui::SetCursorPosY(m_window_height - button_size.y - m_close_b_w / 4.f); - if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) - { - wxGetApp().open_preferences(); - } - - ImGui::PopStyleColor(5); - // preferences button is in place of minimize button - m_minimize_b_visible = true; -} -void NotificationManager::HintNotification::render_right_arrow_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - // Used for debuging - auto scale = wxGetApp().plater()->get_current_canvas3D()->get_scale(); - ImVec2 win_size(win_size_x, win_size_y); - ImVec2 win_pos(win_pos_x, win_pos_y); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); - push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); - - std::wstring button_text; - button_text = m_is_dark ? ImGui::RightArrowDarkButton : ImGui::RightArrowButton; - - ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str()); - ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); - if (ImGui::IsMouseHoveringRect(ImVec2(win_pos_x - m_window_width / 7.5f, win_pos_y + m_window_height - 1.5f * m_line_height), - ImVec2(win_pos_x - m_window_width / 15.f, win_pos_y + m_window_height), - true)) - { - button_text = m_is_dark ? ImGui::RightArrowHoverDarkButton : ImGui::RightArrowHoverButton; - // tooltip - ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND); - ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 }); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8 * scale, 1 * scale }); - ImGui::BeginTooltip(); - imgui.text(_u8L("Open next tip.")); - ImGui::EndTooltip(); - ImGui::PopStyleColor(2); - ImGui::PopStyleVar(); - } - ImGui::SetCursorPosX(m_window_width - m_line_height * 3.f); - ImGui::SetCursorPosY(m_window_height - button_size.y - m_close_b_w / 4.f); - if (imgui.button(button_text.c_str(), button_size.x * 0.8f, button_size.y * 1.f)) - { - retrieve_data(); - } - - ImGui::PopStyleColor(5); -} -void NotificationManager::HintNotification::render_logo(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - //std::string placeholder_text; - //placeholder_text = ImGui::EjectButton; - //ImVec2 button_pic_size = ImGui::CalcTextSize(placeholder_text.c_str()); - //std::wstring text; - //text = ImGui::ClippyMarker; - //ImGui::SetCursorPosX(button_pic_size.x / 3); - //ImGui::SetCursorPosY(win_size_y / 2 - button_pic_size.y * 2.f); - //imgui.text(text.c_str()); -} -void NotificationManager::HintNotification::render_documentation_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - auto scale = wxGetApp().plater()->get_current_canvas3D()->get_scale(); - ImVec2 win_size(win_size_x, win_size_y); - ImVec2 win_pos(win_pos_x, win_pos_y); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); - push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); - - std::wstring button_text; - button_text = m_is_dark ? ImGui::DocumentationDarkButton : ImGui::DocumentationButton; - std::string placeholder_text; - placeholder_text = ImGui::EjectButton; - - ImVec2 button_pic_size = ImGui::CalcTextSize(placeholder_text.c_str()); - ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); - if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 5.f, win_pos.y + win_size.y / 2 - button_pic_size.y), - ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y / 2 + button_pic_size.y), - true)) - { - button_text = m_is_dark ? ImGui::DocumentationHoverDarkButton : ImGui::DocumentationHoverButton; - // tooltip - ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND); - ImGui::PushStyleColor(ImGuiCol_Border, { 0,0,0,0 }); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8 * scale, 1 * scale }); - ImGui::BeginTooltip(); - imgui.text(_u8L("Open Documentation in web browser.")); - ImGui::EndTooltip(); - ImGui::PopStyleColor(2); - ImGui::PopStyleVar(); - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - open_documentation(); - } - ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f); - ImGui::SetCursorPosY(win_size.y / 2 - button_size.y); - if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) - { - open_documentation(); - } - - ImGui::PopStyleColor(5); -} - -void NotificationManager::HintNotification::open_documentation() -{ - if (!m_documentation_link.empty()) - { - launch_browser_if_allowed(m_documentation_link); - } -} -void NotificationManager::HintNotification::retrieve_data(bool new_hint/* = true*/) -{ - HintData* hint_data = HintDatabase::get_instance().get_hint(new_hint ? HintDataNavigation::Next : HintDataNavigation::Curr); - if (hint_data == nullptr) - close(); - - if (hint_data != nullptr) - { - NotificationData nd{ NotificationType::DidYouKnowHint, - NotificationLevel::HintNotificationLevel, - 0, - hint_data->text, - hint_data->hypertext, nullptr, - hint_data->follow_text }; - m_hypertext_callback = hint_data->callback; - m_disabled_tags = hint_data->disabled_tags; - m_enabled_tags = hint_data->enabled_tags; - m_runtime_disable = hint_data->runtime_disable; - m_documentation_link = hint_data->documentation_link; - m_has_hint_data = true; - update(nd); - } -} } //namespace Slic3r } //namespace GUI diff --git a/src/slic3r/GUI/HintNotification.hpp b/src/slic3r/GUI/HintNotification.hpp index 89a2871..5cf69b3 100644 --- a/src/slic3r/GUI/HintNotification.hpp +++ b/src/slic3r/GUI/HintNotification.hpp @@ -41,6 +41,7 @@ public: private: HintDatabase() : m_hint_id(0) + , m_helio_hint_id(0) {} public: ~HintDatabase(); @@ -48,13 +49,9 @@ public: void operator=(HintDatabase const&) = delete; // return true if HintData filled; - HintData* get_hint(HintDataNavigation nav); - size_t get_index() { return m_hint_id; } - size_t get_count() { - if (!m_initialized) - return 0; - return m_loaded_hints.size(); - } + HintData* get_hint(HintDataNavigation nav, bool is_helio); + size_t get_index(bool is_helio) { return is_helio ? m_helio_hint_id : m_hint_id; } + size_t get_count(bool is_helio) { return is_helio ? m_loaded_helio_hints.size() : m_loaded_hints.size(); } // resets m_initiailized to false and writes used if was initialized // used when reloading in runtime - like change language void uninit(); @@ -62,72 +59,17 @@ public: private: void init(); void init_random_hint_id(); - void load_hints_from_file(const boost::filesystem::path& path); - bool is_used(const std::string& id); - void set_used(const std::string& id); - void clear_used(); + void load_hints_from_file(const boost::filesystem::path& path, std::vector& hints_vector); // Returns position in m_loaded_hints with next hint chosed randomly with weights - size_t get_next_hint_id(); - size_t get_prev_hint_id(); - size_t get_random_next(); - size_t m_hint_id; + //size_t get_random_next(); bool m_initialized{ false }; + + size_t m_hint_id; std::vector m_loaded_hints; - bool m_sorted_hints{ false }; - std::vector m_used_ids; - bool m_used_ids_loaded{ false }; -}; -// Notification class - shows current Hint ("Did you know") -class NotificationManager::HintNotification : public NotificationManager::PopNotification -{ -public: - HintNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool new_hint) - : PopNotification(n, id_provider, evt_handler) - { - retrieve_data(new_hint); - } - virtual void init() override; - void open_next() { retrieve_data(); } -protected: - virtual void set_next_window_size(ImGuiWrapper& imgui) override; - virtual void count_spaces() override; - virtual void count_lines() override; - virtual bool on_text_click() override; - virtual void render_text(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y) override; - virtual void render_close_button(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y) override; - virtual void render_minimize_button(ImGuiWrapper& imgui, - const float win_pos_x, const float win_pos_y) override {} + //bool m_sorted_hints{ false }; - void render_preferences_button(ImGuiWrapper& imgui, - const float win_pos_x, const float win_pos_y); - void render_right_arrow_button(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y); - void render_documentation_button(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y); - void render_logo(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y); - // recursion counter -1 tells to retrieve same hint as last time - void retrieve_data(bool new_hint = true); - void open_documentation(); - - bool m_has_hint_data{ false }; - std::function m_hypertext_callback; - std::string m_disabled_tags; - std::string m_enabled_tags; - bool m_runtime_disable; - std::string m_documentation_link; - float m_close_b_y{ 0 }; - float m_close_b_w{ 0 }; - // hover of buttons - long m_docu_hover_time{ 0 }; - long m_prefe_hover_time{ 0 }; + size_t m_helio_hint_id; + std::vector m_loaded_helio_hints; }; } //namespace Slic3r diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index d986684..7170b13 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -68,6 +68,7 @@ static const std::map font_icons = { {ImGui::GapFillIcon , "gap_fill" }, {ImGui::FoldButtonIcon , "im_fold" }, {ImGui::UnfoldButtonIcon , "im_unfold" }, + {ImGui::HelioIcon , "helio_icon" }, {ImGui::SphereButtonIcon , "toolbar_modifier_sphere" }, // dark mode icon {ImGui::MinimalizeDarkButton , "notification_minimalize_dark" }, diff --git a/src/slic3r/GUI/ImageGrid.cpp b/src/slic3r/GUI/ImageGrid.cpp index 5e3df24..ea66402 100644 --- a/src/slic3r/GUI/ImageGrid.cpp +++ b/src/slic3r/GUI/ImageGrid.cpp @@ -389,7 +389,7 @@ void Slic3r::GUI::ImageGrid::changedEvent(wxCommandEvent& evt) { evt.Skip(); BOOST_LOG_TRIVIAL(debug) << "ImageGrid::changedEvent: " << evt.GetEventType() << " index: " << evt.GetInt() - << " name: " << evt.GetString().ToUTF8().data() << " extra: " << evt.GetExtraLong(); + << " name: " << PathSanitizer::sanitize(evt.GetString().ToUTF8().data()) << " extra: " << evt.GetExtraLong(); if (evt.GetEventType() == EVT_FILE_CHANGED) { if (evt.GetInt() == -1) m_file_sys->DownloadCheckFiles(wxGetApp().app_config->get("download_path")); diff --git a/src/slic3r/GUI/ImageMessageDialog.cpp b/src/slic3r/GUI/ImageMessageDialog.cpp new file mode 100644 index 0000000..d4a54f1 --- /dev/null +++ b/src/slic3r/GUI/ImageMessageDialog.cpp @@ -0,0 +1,102 @@ +#include "ImageMessageDialog.hpp" +#include "HMS.hpp" + +#include "Widgets/Button.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" + +namespace Slic3r { +namespace GUI +{ + +ImageMessageDialog::ImageMessageDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxString &message, const wxPoint &pos, const wxSize &size, long style) + :DPIDialog(parent, id, title, pos, size, style) +{ + 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); + + SetTitle(_L("Parameter recommendation")); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(380), 1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + + m_scroll_area = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); + m_scroll_area->SetBackgroundColour(*wxWHITE); + + wxBoxSizer* text_sizer = new wxBoxSizer(wxVERTICAL); + + int target_w = FromDIP(380); + int target_h = FromDIP(270); + std::string image_path = (boost::format("%1%/images/clumping.png") % resources_dir()).str(); + wxImage* image = new wxImage(image_path, wxBITMAP_TYPE_PNG); + if (image && image->IsOk()) { + *image = image->Scale(target_w, target_h, wxIMAGE_QUALITY_HIGH); + } + wxBitmap bitmap = wxBitmap(*image); + m_error_msg_label = new Label(m_scroll_area, message, LB_AUTO_WRAP); + m_error_picture = new wxStaticBitmap(m_scroll_area, wxID_ANY, bitmap, wxDefaultPosition, wxSize(target_w, target_h)); + + text_sizer->Add(m_error_picture, 0, wxALIGN_CENTER, FromDIP(5)); + text_sizer->AddSpacer(10); + text_sizer->Add(m_error_msg_label, 0, wxEXPAND, FromDIP(5)); + + m_scroll_area->SetSizer(text_sizer); + + Button *msg_button = new Button(this, _L("Click for more details")); + msg_button->SetBackgroundColor(btn_bg_white); + msg_button->SetBorderColor(wxColour(38, 46, 48)); + msg_button->SetFont(Label::Body_14); + msg_button->SetSize(wxSize(FromDIP(300), FromDIP(30))); + msg_button->SetMinSize(wxSize(FromDIP(300), FromDIP(30))); + msg_button->SetMaxSize(wxSize(-1, FromDIP(30))); + msg_button->SetCornerRadius(FromDIP(5)); + + msg_button->Bind(wxEVT_LEFT_DOWN, [this, style](wxMouseEvent &e) { + std::string language = wxGetApp().app_config->get("language"); + wxString region = L"en"; + if (language.find("zh") == 0) + region = L"zh"; + const wxString wiki_link = wxString::Format(L"https://wiki.qidi3d.com/%s/software/qidi-studio", region); + wxGetApp().open_browser_with_warning_dialog(wiki_link); + e.Skip(); + }); + + auto bottom_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer_button = new wxBoxSizer(wxVERTICAL); + m_sizer_button->Add(msg_button, 0, wxALIGN_CENTER, FromDIP(5)); + bottom_sizer->Add(m_sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, 0); + + wxBoxSizer* m_center_sizer = new wxBoxSizer(wxVERTICAL); + m_center_sizer->Add(0, 0, 1, wxTOP, FromDIP(5)); + m_center_sizer->Add(m_scroll_area, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15)); + m_center_sizer->Add(bottom_sizer, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20)); + m_center_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); + m_sizer_main->Add(m_center_sizer, 0, wxBOTTOM | wxEXPAND, FromDIP(5)); + + SetSizer(m_sizer_main); + Layout(); + m_sizer_main->Fit(this); + m_sizer_main->SetSizeHints(this); + + CenterOnParent(); + wxGetApp().UpdateDlgDarkUI(this); +} + +ImageMessageDialog::~ImageMessageDialog() +{ + m_error_picture->SetBitmap(wxBitmap()); +} + +void ImageMessageDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + for (auto used_button : m_used_button) { used_button->Rescale();} + wxGetApp().UpdateDlgDarkUI(this); + Refresh(); +} +} +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/ImageMessageDialog.hpp b/src/slic3r/GUI/ImageMessageDialog.hpp new file mode 100644 index 0000000..7b5f003 --- /dev/null +++ b/src/slic3r/GUI/ImageMessageDialog.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include + +#include "GUI_Utils.hpp" +#include "Widgets/StateColor.hpp" + +class Label; +class Button; + +namespace Slic3r { + +class MachineObject;//Previous definitions + +namespace GUI { + +class ImageMessageDialog : public DPIDialog +{ +public: + ImageMessageDialog(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxString &message = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxCLOSE_BOX | wxCAPTION); + ~ImageMessageDialog(); + + void on_dpi_changed(const wxRect& suggested_rect); + +private: + std::unordered_set m_used_button; + + wxStaticBitmap* m_error_picture; + Label* m_error_msg_label{ nullptr }; + Label* m_error_code_label{ nullptr }; + wxBoxSizer* m_sizer_main; + wxBoxSizer* m_sizer_button; + wxPanel* m_scroll_area{ nullptr }; + + std::map m_button_list; + StateColor btn_bg_white; +}; +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index e5f3f80..c06cb90 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -256,10 +256,13 @@ void ArrangeJob::prepare_all() { NotificationManager::NotificationLevel::WarningNotificationLevel, into_u8(msg)); } + const DynamicPrintConfig& current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + bool enable_wrapping = current_config.option("enable_wrapping_detection")->value; + prepare_wipe_tower(); // add the virtual object into unselect list if has - plate_list.preprocess_exclude_areas(m_unselected, MAX_NUM_PLATES); + plate_list.preprocess_exclude_areas(m_unselected, enable_wrapping, MAX_NUM_PLATES); } arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set& extruder_ids) @@ -432,8 +435,11 @@ void ArrangeJob::prepare_partplate() { m_unselected.emplace_back(std::move(ap)); } + const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + bool enable_wrapping = current_config.option("enable_wrapping_detection")->value; + // add the virtual object into unselect list if has - plate_list.preprocess_exclude_areas(m_unselected, current_plate_index + 1); + plate_list.preprocess_exclude_areas(m_unselected, enable_wrapping, current_plate_index + 1); } void ArrangeJob::prepare_outside_plate() { @@ -523,8 +529,11 @@ void ArrangeJob::prepare_outside_plate() { prepare_wipe_tower(true); + const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + bool enable_wrapping = current_config.option("enable_wrapping_detection")->value; + // add the virtual object into unselect list if has - plate_list.preprocess_exclude_areas(m_unselected, current_plate_index + 1); + plate_list.preprocess_exclude_areas(m_unselected, enable_wrapping, current_plate_index + 1); } //QDS: add partplate logic @@ -655,7 +664,8 @@ void ArrangeJob::process() Points bedpts = get_shrink_bedpts(global_config,params); - partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scale_(1)); + bool enable_wrapping = global_config.option("enable_wrapping_detection")->value; + partplate_list.preprocess_exclude_areas(params.excluded_regions, enable_wrapping, 1, scale_(1)); ARRANGE_LOG(debug) << "bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose(); diff --git a/src/slic3r/GUI/Jobs/BindJob.cpp b/src/slic3r/GUI/Jobs/BindJob.cpp index 52dfad6..95ab519 100644 --- a/src/slic3r/GUI/Jobs/BindJob.cpp +++ b/src/slic3r/GUI/Jobs/BindJob.cpp @@ -4,6 +4,8 @@ #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { diff --git a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp index 3e6d093..5fbe57e 100644 --- a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp +++ b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp @@ -61,12 +61,12 @@ void CreateFontImageJob::process(Ctl &ctl) 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); + ExPolygons shapes = support_backup_fonts ? Emboss::text2shapes(emboss_shape, font_file_with_cache, text.c_str(), fp, standard_scale, was_canceled, ft_fn) : + Emboss::text2shapes(emboss_shape, font_file_with_cache, text.c_str(), fp, standard_scale, 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); + shapes = Emboss::text2shapes(emboss_shape, font_file_with_cache, default_text.c_str(), fp, standard_scale, was_canceled, ft_fn); } if (shapes.empty()) { @@ -190,7 +190,8 @@ void Slic3r::GUI::BackupFonts::generate_backup_fonts() { font_names.emplace_back(wxString::FromUTF8("Arial")); // Arabic #endif #ifdef __linux__ - font_names.emplace_back(wxString(L"宋体")); // chinese confirm + font_names.emplace_back(wxString(L"宋体")); // chinese confirm + font_names.emplace_back(wxString("AR PL UMing CN"));// 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 diff --git a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp index 2276f4f..b3cdae5 100644 --- a/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp +++ b/src/slic3r/GUI/Jobs/CreateFontStyleImagesJob.cpp @@ -42,8 +42,8 @@ void CreateFontStyleImagesJob::process(Ctl &ctl) 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); + shapes = support_backup_fonts ? text2shapes(emboss_shape, item.font, m_input.text.c_str(), item.prop, standard_scale, was_canceled, ft_fn) : + text2shapes(emboss_shape, item.font, m_input.text.c_str(), item.prop, standard_scale, was_canceled); // create image description StyleManager::StyleImage &image = m_images[index]; BoundingBox &bounding_box = image.bounding_box; diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index f72f2aa..c7087c3 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -3,6 +3,7 @@ #include #include // +#include #include #include #include // load_obj for default mesh @@ -1275,7 +1276,7 @@ ProjectTransform calc_project_tran(DataBase &input, double real_scale) return project_tr; } -void create_all_char_mesh(DataBase &input, std::vector &result, EmbossShape &shape) +void create_all_char_mesh(DataBase &input, std::vector &result, std::vector &text_cursors, EmbossShape &shape) { shape = input.create_shape();//this will call letter2shapes if (shape.shapes_with_ids.empty()) @@ -1317,6 +1318,7 @@ void create_all_char_mesh(DataBase &input, std::vector &result, Em result.emplace_back(mesh); } } + text_cursors = shape.text_cursors; } float get_single_char_width(const std::vector &chars_mesh_result) @@ -1332,20 +1334,11 @@ float get_single_char_width(const std::vector &chars_mesh_result) return 0.f; } -bool calc_text_lengths(std::vector &text_lengths, const std::vector &chars_mesh_result) +bool calc_text_lengths(std::vector &text_lengths, const std::vector &text_cursors) { 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); - } + for (int i = 0; i < text_cursors.size(); i++) { + text_lengths.emplace_back(text_cursors[i]/2.f); } return true; } @@ -1403,7 +1396,7 @@ 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); + create_all_char_mesh(*m_input.m_data_update.base, m_input.m_chars_mesh_result, m_input.m_text_cursors,m_input.m_text_shape); if (m_input.m_chars_mesh_result.empty()) { return; } @@ -1457,10 +1450,10 @@ bool GenerateTextJob::update_text_positions(InputInfo &input_info) return false; } std::vector text_lengths; - if (!calc_text_lengths(text_lengths, input_info.m_chars_mesh_result)) { + if (!calc_text_lengths(text_lengths, input_info.m_text_cursors)) { return false; } - int text_num = input_info.m_chars_mesh_result.size(); // FIX by BBS 20250109 + int text_num = input_info.m_chars_mesh_result.size(); // FIX by QDS 20250109 input_info.m_position_points.clear(); input_info.m_normal_points.clear(); /*auto mouse_position_world = m_text_position_in_world.cast(); @@ -1844,6 +1837,9 @@ void GenerateTextJob::get_text_mesh(TriangleMesh &result_mesh, std::vector= chars_mesh.size() || i< 0) { + return; + } TriangleMesh mesh = chars_mesh[i]; // m_cur_font_name auto box = mesh.bounding_box(); mesh.translate(-box.center().x(), 0, 0); @@ -1949,12 +1945,12 @@ void GenerateTextJob::generate_mesh_according_points(InputInfo &input_info) 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); + create_all_char_mesh(*m_input.base, m_input.m_chars_mesh_result, m_input.m_text_cursors, 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_text_lengths(text_lengths, m_input.m_text_cursors); calc_position_points(m_input.m_position_points, text_lengths, m_input.text_info.m_text_gap, Vec3d(1, 0, 0)); } diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp index 21d1480..8713110 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.hpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp @@ -264,6 +264,7 @@ public: struct CreateTextInput { std::vector m_chars_mesh_result; + std::vector m_text_cursors; EmbossShape m_text_shape; TextInfo text_info; DataBasePtr base; @@ -281,9 +282,9 @@ public: }; 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); +void create_all_char_mesh(DataBase &input, std::vector &result,std::vector& text_cursors, 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); +bool calc_text_lengths(std::vector &text_lengths, const std::vector & text_cursors); void calc_position_points(std::vector &position_points, std::vector &text_lengths, float text_gap, const Vec3d &temp_pos_dir); struct Texture @@ -353,6 +354,7 @@ public: 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; + std::vector m_text_cursors; Vec3d m_text_position_in_world; Vec3f m_text_normal_in_world; float m_text_gap; diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index bfcc061..c7fb57f 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -120,10 +120,11 @@ void FillBedJob::prepare() if (m_selected.empty()) return; + bool enable_wrapping = global_config.option("enable_wrapping_detection")->value; //add the virtual object into unselect list if has double scaled_exclusion_gap = scale_(1); - plate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap); - plate_list.preprocess_exclude_areas(m_unselected); + plate_list.preprocess_exclude_areas(params.excluded_regions, enable_wrapping, 1, scaled_exclusion_gap); + plate_list.preprocess_exclude_areas(m_unselected, enable_wrapping); m_bedpts = get_bed_shape(global_config); diff --git a/src/slic3r/GUI/Jobs/PrintJob.cpp b/src/slic3r/GUI/Jobs/PrintJob.cpp index d6ba4c7..560e62c 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.cpp +++ b/src/slic3r/GUI/Jobs/PrintJob.cpp @@ -9,6 +9,8 @@ #include "slic3r/GUI/MainFrame.hpp" #include "qidi_networking.hpp" +#include "slic3r/GUI/DeviceCore/DevManager.h" +#include "slic3r/GUI/DeviceCore/DevUtil.h" namespace Slic3r { namespace GUI { @@ -256,6 +258,8 @@ void PrintJob::process() 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; + //y71 + params.enable_multi_box = this->enable_multi_box; if (m_print_type == "from_sdcard_view") { params.dst_file = m_dst_path; @@ -286,22 +290,20 @@ void PrintJob::process() catch (...) {} } - auto model_name = model_info->metadata_items.find(QDT_DESIGNER_MODEL_TITLE_TAG); - if (model_name != model_info->metadata_items.end()) { - try { + if (m_print_type != "from_sdcard_view") { + auto model_name = model_info->metadata_items.find(QDT_DESIGNER_MODEL_TITLE_TAG); + if (model_name != model_info->metadata_items.end()) { + try { + std::string mall_model_name = model_name->second; + std::replace(mall_model_name.begin(), mall_model_name.end(), ' ', '_'); + const char *unusable_symbols = "<>[]:/\\|?*\" "; + for (const char *symbol = unusable_symbols; *symbol != '\0'; ++symbol) { std::replace(mall_model_name.begin(), mall_model_name.end(), *symbol, '_'); } - std::string mall_model_name = model_name->second; - std::replace(mall_model_name.begin(), mall_model_name.end(), ' ', '_'); - const char* unusable_symbols = "<>[]:/\\|?*\" "; - for (const char* symbol = unusable_symbols; *symbol != '\0'; ++symbol) { - std::replace(mall_model_name.begin(), mall_model_name.end(), *symbol, '_'); - } - - std::regex pattern("_+"); - params.project_name = std::regex_replace(mall_model_name, pattern, "_"); - params.project_name = truncate_string(params.project_name, 100); + std::regex pattern("_+"); + params.project_name = std::regex_replace(mall_model_name, pattern, "_"); + params.project_name = truncate_string(params.project_name, 100); + } catch (...) {} } - catch (...) {} } } @@ -486,7 +488,7 @@ void PrintJob::process() try { job_info_j.parse(job_info); if (job_info_j.contains("job_id")) { - curr_job_id = JsonValParser::get_longlong_val(job_info_j["job_id"]); + curr_job_id = DevJsonValParser::get_longlong_val(job_info_j["job_id"]); } BOOST_LOG_TRIVIAL(trace) << "print_job: curr_obj_id=" << curr_job_id; diff --git a/src/slic3r/GUI/Jobs/PrintJob.hpp b/src/slic3r/GUI/Jobs/PrintJob.hpp index 75d8925..f1c81eb 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.hpp +++ b/src/slic3r/GUI/Jobs/PrintJob.hpp @@ -89,9 +89,12 @@ public: int auto_bed_leveling{0}; int auto_flow_cali{0}; int auto_offset_cali{0}; + //y71 + int enable_multi_box{0}; 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_enable_multi_box, int auto_flow_calit, int auto_offset_calit) { @@ -104,6 +107,7 @@ public: task_ext_change_assist = ext_change_assist; auto_bed_leveling = auto_bed_levelingt; + enable_multi_box = auto_enable_multi_box; auto_flow_cali = auto_flow_calit; auto_offset_cali = auto_offset_calit; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 56fbc1f..d8dc8d2 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -63,6 +63,8 @@ #include "DailyTips.hpp" #include "FilamentMapDialog.hpp" +#include "DeviceCore/DevManager.h" + #ifdef _WIN32 #include #include @@ -942,6 +944,8 @@ void MainFrame::update_layout() m_plater->update(true); + m_plater->show_wrapping_detect_dialog_if_necessary(); + if (!preview_only_hint()) return; } @@ -961,7 +965,7 @@ void MainFrame::update_layout() { m_main_sizer->Add(m_plater, 1, wxEXPAND); //QDS: add bed exclude area - m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, {}, 0.0, {}, {}, {}, {}, true); + m_plater->set_bed_shape({{0.0, 0.0}, {200.0, 0.0}, {200.0, 200.0}, {0.0, 200.0}}, {}, {}, 0.0, {}, {}, {}, {}, true); m_plater->get_collapse_toolbar().set_enabled(false); m_plater->enable_sidebar(false); m_plater->Show(); @@ -1081,7 +1085,7 @@ void MainFrame::update_title() return; } -void MainFrame::show_calibration_button(bool show) +void MainFrame::show_calibration_button(bool show, bool is_QDT) { #ifdef __APPLE__ bool shown = m_menubar->FindMenu(_L("Calibration")) != wxNOT_FOUND; @@ -1094,7 +1098,7 @@ void MainFrame::show_calibration_button(bool show) #else topbar()->ShowCalibrationButton(show); #endif - show = !show; + show = is_QDT; auto shown2 = m_tabpanel->FindPage(m_calibration) != wxNOT_FOUND; if (shown2 == show) ; @@ -1650,8 +1654,10 @@ bool MainFrame::can_send_gcode() const { // y //auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config; - //if (const auto *print_host_opt = cfg.option("print_host"); print_host_opt) - // return !print_host_opt->value.empty(); + + // const auto *print_host_opt = cfg.option("print_host"); + // if (! print_host_opt) return false; + // else return !print_host_opt->value.empty(); } return true; } @@ -1855,10 +1861,29 @@ wxBoxSizer* MainFrame::create_side_tools() } } + if (printer_model == "Bambu Lab H2S") { + if ((wxGetApp().app_config->get("prompt_for_brittle_filaments") == "true") ) { + auto used_filaments = curr_plate->get_extruders(); + std::transform(used_filaments.begin(), used_filaments.end(), used_filaments.begin(), [](auto i) {return i - 1; }); + auto full_config = wxGetApp().preset_bundle->full_config(); + auto filament_types = full_config.option("filament_type")->values; + if (std::any_of(used_filaments.begin(), used_filaments.end(), [filament_types](int idx) { return filament_types[idx] == "PPA-CF" || filament_types[idx] == "PPS-CF"; })) { + MessageDialog dlg(this, _L("PPS-CF/PPA-CF is brittle and could break in bended PTFE tube above Toolhead. Please refer to Wiki before use. "), _L("Tips"), wxYES_NO); + auto res = dlg.ShowModal(); + if (res == wxID_YES) { + wxLaunchDefaultBrowser("https://e.bambulab.com/t?c=UC64kdlpHxN3Mb15"); + slice = false; + } + wxGetApp().app_config->set("prompt_for_brittle_filaments", "false"); + } + } + } + + if (slice) { if (m_slice_select == eSliceAll) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL)); - else + else if (m_slice_select == eSlicePlate) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); this->m_tabpanel->SetSelection(tpPreview); } @@ -1918,6 +1943,7 @@ wxBoxSizer* MainFrame::create_side_tools() slice_plate_btn->SetCornerRadius(0); slice_all_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + plater()->get_notification_manager()->close_notification_of_type(NotificationType::HelioSlicingError); m_slice_btn->SetLabel(_L("Slice all")); m_slice_select = eSliceAll; m_slice_enable = get_enable_slice_status(); @@ -1928,6 +1954,7 @@ wxBoxSizer* MainFrame::create_side_tools() }); slice_plate_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + plater()->get_notification_manager()->close_notification_of_type(NotificationType::HelioSlicingError); m_slice_btn->SetLabel(_L("Slice plate")); m_slice_select = eSlicePlate; m_slice_enable = get_enable_slice_status(); @@ -1936,6 +1963,7 @@ wxBoxSizer* MainFrame::create_side_tools() if(m_slice_option_pop_up) m_slice_option_pop_up->Dismiss(); }); + m_slice_option_pop_up->append_button(slice_all_btn); m_slice_option_pop_up->append_button(slice_plate_btn); m_slice_option_pop_up->Popup(m_slice_btn); @@ -2281,12 +2309,6 @@ void MainFrame::update_side_button_style() // QDS int em = em_unit(); - /*m_slice_btn->SetLayoutStyle(1); - m_slice_btn->SetTextLayout(SideButton::EHorizontalOrientation::HO_Center, FromDIP(15)); - 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("#3B4446"));*/ StateColor m_btn_bg_enable = StateColor( std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), @@ -3650,7 +3672,7 @@ void MainFrame::update_calibration_button_status() 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); + wxGetApp().mainframe->show_calibration_button(show_calibration, isQDT); } void MainFrame::reslice_now() @@ -3896,7 +3918,9 @@ void MainFrame::select_tab(wxPanel* panel) void MainFrame::jump_to_monitor(std::string dev_id) { m_tabpanel->SetSelection(tpMonitor); - ((MonitorPanel*)m_monitor)->select_machine(dev_id); + if (!dev_id.empty()) { + ((MonitorPanel*)m_monitor)->select_machine(dev_id); + } } void MainFrame::jump_to_multipage() @@ -4134,8 +4158,9 @@ void MainFrame::open_recent_project(size_t file_id, wxString const & filename) } if (wxFileExists(filename)) { CallAfter([this, filename] { - if (wxGetApp().can_load_project()) + if (wxGetApp().can_load_project()) { m_plater->load_project(filename); + } }); } else diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index c7a4683..91a33dd 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -280,7 +280,7 @@ public: void update_title(); void set_max_recent_count(int max); - void show_calibration_button(bool show); + void show_calibration_button(bool show, bool is_QDT); void update_title_colour_after_set_title(); void show_option(bool show); diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index e28206c..cfe8d39 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "DeviceCore/DevStorage.h" #ifdef __WXMSW__ #include @@ -212,35 +213,45 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent) MediaFilePanel::~MediaFilePanel() { - SetMachineObject(nullptr); + UpdateByObj(nullptr); } -void MediaFilePanel::SetMachineObject(MachineObject* obj) +void MediaFilePanel::UpdateByObj(MachineObject* obj) { - std::string machine = obj ? obj->dev_id : ""; + bool sdcard_state_changed = false; + std::string machine = obj ? obj->get_dev_id() : ""; if (obj) { m_lan_mode = obj->is_lan_mode_printer(); - m_lan_ip = obj->dev_ip; + m_lan_ip = obj->get_dev_ip(); m_lan_passwd = obj->get_access_code(); m_dev_ver = obj->get_ota_version(); m_device_busy = obj->is_camera_busy_off(); - m_sdcard_exist = obj->sdcard_state == MachineObject::SdcardState::HAS_SDCARD_NORMAL; m_local_proto = obj->file_local; m_remote_proto = obj->get_file_remote(); m_model_download_support = obj->file_model_download; + + if (m_sdcard_exist != (obj->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL)) { + m_sdcard_exist = obj->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL; + sdcard_state_changed = true; + } } else { m_lan_mode = false; m_lan_ip.clear(); m_lan_passwd.clear(); m_dev_ver.clear(); - m_sdcard_exist = false; m_device_busy = false; m_local_proto = 0; m_remote_proto = 0; m_model_download_support = false; + + if (m_sdcard_exist) { + m_sdcard_exist = false; // reset sdcard state when no object + sdcard_state_changed = true; + } } + Enable(obj && obj->is_info_ready() && obj->m_push_count > 0); - if (machine == m_machine) { + if (machine == m_machine && !sdcard_state_changed) { if ((m_waiting_enable && IsEnabled()) || (m_waiting_support && (m_local_proto || m_remote_proto))) { auto fs = m_image_grid->GetFileSystem(); if (fs) fs->Retry(); @@ -470,11 +481,6 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr wfs) fs->SetUrl("0"); return; } - if (!m_sdcard_exist) { - m_image_grid->SetStatus(m_bmp_failed, _L("Please check if the storage is inserted into the printer.\nIf it still cannot be read, you can try formatting the storage.")); - fs->SetUrl("0"); - return; - } if (m_device_busy) { m_image_grid->SetStatus(m_bmp_failed, _L("The printer is currently busy downloading. Please try again after it finishes.")); fs->SetUrl("0"); diff --git a/src/slic3r/GUI/MediaFilePanel.h b/src/slic3r/GUI/MediaFilePanel.h index 270542c..72fbc96 100644 --- a/src/slic3r/GUI/MediaFilePanel.h +++ b/src/slic3r/GUI/MediaFilePanel.h @@ -33,10 +33,10 @@ class MediaFilePanel : public wxPanel { public: MediaFilePanel(wxWindow * parent); - + ~MediaFilePanel(); - void SetMachineObject(MachineObject * obj); + void UpdateByObj(MachineObject * obj); void SwitchStorage(bool external); diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index b239b3d..094d4b2 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -40,8 +40,9 @@ static std::map error_messages = { namespace Slic3r { namespace GUI { -//1.9.5 + static int SecondsSinceLastInput(); + MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size) : wxPanel(parent, wxID_ANY, pos, size) , m_media_ctrl(media_ctrl) @@ -62,7 +63,6 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w m_media_ctrl->Bind(EVT_MEDIA_CTRL_STAT, [this](auto & e) { #if !QDT_RELEASE_TO_PUBLIC wxSize size = m_media_ctrl->GetVideoSize(); - //1.9.7.52 m_label_stat->SetLabel(e.GetString() + wxString::Format(" VS:%ix%i LD:%i", size.x, size.y, m_load_duration)); #endif wxString str = e.GetString(); @@ -148,18 +148,20 @@ MediaPlayCtrl::~MediaPlayCtrl() while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) { wxEventLoopBase::GetActive()->Yield(); } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << this; } void MediaPlayCtrl::SetMachineObject(MachineObject* obj) { - std::string machine = obj ? obj->dev_id : ""; + std::string machine = obj ? obj->get_dev_id() : ""; if (obj) { m_camera_exists = obj->has_ipcam; m_dev_ver = obj->get_ota_version(); m_lan_mode = obj->is_lan_mode_printer(); m_lan_proto = obj->liveview_local; m_remote_proto = obj->get_liveview_remote(); - m_lan_ip = obj->dev_ip; + m_lan_ip = obj->get_dev_ip(); m_lan_passwd = obj->get_access_code(); m_device_busy = obj->is_camera_busy_off(); m_tutk_state = obj->tutk_state; @@ -345,9 +347,8 @@ void MediaPlayCtrl::Play() m_disable_lan = false; m_failed_code = 0; m_last_state = MEDIASTATE_IDLE; - //1.9.5 m_button_play->SetIcon("media_stop"); - + if (!m_remote_proto) { // not support tutk m_failed_code = -1; m_url = "qidi:///local/"; @@ -361,7 +362,12 @@ void MediaPlayCtrl::Play() if (agent) { std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""}; agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto], - [this, m = m_machine, v = agent_version, dv = m_dev_ver](std::string url) { + [this, m = m_machine, v = agent_version, dv = m_dev_ver, token = std::weak_ptr(m_token)](std::string url) { + if (token.expired()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": token has been expired"; + return; + } + if (boost::algorithm::starts_with(url, "qidi:///")) { url += "&device=" + into_u8(m); url += "&net_ver=" + v; @@ -422,7 +428,7 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2) : _L(iter->second.c_str()); if (m_failed_code == 1) { if (m_last_state == wxMEDIASTATE_PLAYING) - msg2 = _L("The printer has been logged out and cannot connect."); + msg2 = _L("Multi-device/client simultaneous liveview is not supported. Please close the liveview on other devices/clients and try again."); } #if !QDT_RELEASE_TO_PUBLIC && defined(__WINDOWS__) if (m_failed_code < 0) @@ -645,8 +651,8 @@ void MediaPlayCtrl::ToggleStream() }); } -void MediaPlayCtrl::msw_rescale() { - m_button_play->Rescale(); +void MediaPlayCtrl::msw_rescale() { + m_button_play->Rescale(); } void MediaPlayCtrl::jump_to_play() @@ -683,12 +689,11 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) m_last_state = state; m_failed_code = 0; SetStatus(_L("Playing..."), false); - //1.9.7.52 m_print_idle = 0; auto now = std::chrono::system_clock::now(); m_load_duration = std::chrono::duration_cast(now - m_play_timer).count(); m_play_timer = now + 1min; - + // track event json j; j["stage"] = std::to_string(m_last_state); @@ -866,22 +871,25 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install) if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2)) boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists); } - boost::process::child process_source(file_source, file_url2.ToStdWstring(), boost::process::start_dir(tools_dir), - boost::process::windows::create_no_window, + boost::process::child process_source(file_source, file_url2.ToStdWstring(), boost::process::start_dir(tools_dir), + boost::process::windows::create_no_window, boost::process::std_out > intermediate, boost::process::limit_handles); - boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window, + boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window, boost::process::std_in < intermediate, boost::process::limit_handles); #else boost::filesystem::permissions(file_source, boost::filesystem::owner_exe | boost::filesystem::add_perms); boost::filesystem::permissions(file_ffmpeg, boost::filesystem::owner_exe | boost::filesystem::add_perms); - boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir), + boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir), boost::process::std_out > intermediate, boost::process::limit_handles); boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::std_in < intermediate, boost::process::limit_handles); #endif process_source.detach(); process_ffmpeg.detach(); } catch (std::exception &e) { +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl failed to start camera stream: " << decode_path(e.what()); +#endif + return false; } return true; @@ -923,7 +931,6 @@ bool MediaPlayCtrl::get_stream_url(std::string *url) return url == nullptr; } -//1.9.5 static int SecondsSinceLastInput() { #ifdef _WIN32 diff --git a/src/slic3r/GUI/MediaPlayCtrl.h b/src/slic3r/GUI/MediaPlayCtrl.h index 8a338a4..05a5395 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.h +++ b/src/slic3r/GUI/MediaPlayCtrl.h @@ -81,6 +81,9 @@ private: // static constexpr wxMediaState MEDIASTATE_LOADING = (wxMediaState) 5; // static constexpr wxMediaState MEDIASTATE_BUFFERING = (wxMediaState) 6; + // token + std::shared_ptr m_token = std::make_shared(0); + wxMediaCtrl3 * m_media_ctrl; wxMediaState m_last_state = MEDIASTATE_IDLE; std::string m_machine; diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index 69ab573..36c9429 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -29,6 +29,8 @@ #include "Plater.hpp" #include "BindDialog.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -94,9 +96,9 @@ AddMachinePanel::~AddMachinePanel() { m_button_add_machine->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AddMachinePanel::on_add_machine), NULL, this); } - MonitorPanel::MonitorPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +MonitorPanel::MonitorPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxPanel(parent, id, pos, size, style), - m_select_machine(SelectMachinePopup(this)) + m_select_machine(SelectMachinePopup(this)) { #ifdef __WINDOWS__ SetDoubleBuffered(true); @@ -126,7 +128,7 @@ AddMachinePanel::~AddMachinePanel() { auto key = e.GetString().ToStdString(); auto iter = m_hms_panel->temp_hms_list.find(key); if (iter != m_hms_panel->temp_hms_list.end()) { - m_hms_panel->temp_hms_list[key].already_read = true; + m_hms_panel->temp_hms_list[key].set_read(); } update_hms_tag(); @@ -143,7 +145,7 @@ MonitorPanel::~MonitorPanel() delete m_refresh_timer; } - void MonitorPanel::init_bitmap() +void MonitorPanel::init_bitmap() { m_signal_strong_img = create_scaled_bitmap("monitor_signal_strong", nullptr, 24); m_signal_middle_img = create_scaled_bitmap("monitor_signal_middle", nullptr, 24); @@ -153,7 +155,7 @@ MonitorPanel::~MonitorPanel() m_arrow_img = create_scaled_bitmap("monitor_arrow",nullptr, 14); } - void MonitorPanel::init_timer() +void MonitorPanel::init_timer() { m_refresh_timer = new wxTimer(); m_refresh_timer->SetOwner(this); @@ -164,10 +166,10 @@ MonitorPanel::~MonitorPanel() if (!dev) return; MachineObject *obj_ = dev->get_selected_machine(); if (obj_) - GUI::wxGetApp().sidebar().load_ams_list(obj_->dev_id, obj_); + GUI::wxGetApp().sidebar().load_ams_list(obj_->get_dev_id(), obj_); } - void MonitorPanel::init_tabpanel() +void MonitorPanel::init_tabpanel() { m_side_tools = new SideTools(this, wxID_ANY); wxBoxSizer* sizer_side_tools = new wxBoxSizer(wxVERTICAL); @@ -182,6 +184,7 @@ MonitorPanel::~MonitorPanel() m_media_file_panel->SwitchStorage(title == _L("Storage")); } page->SetFocus(); + update_all(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " select :" << get_string_from_tab(PrinterTab(m_tabpanel->GetSelection())) << " wxString:" << m_tabpanel->GetPageText(m_tabpanel->GetSelection()).ToStdString(); NetworkAgent* agent = GUI::wxGetApp().getAgent(); @@ -284,20 +287,20 @@ void MonitorPanel::select_machine(std::string machine_sn) } - void MonitorPanel::on_timer(wxTimerEvent& event) +void MonitorPanel::on_timer(wxTimerEvent& event) { - if (update_flag) { - update_all(); - //Layout(); - } + if (update_flag) { + update_all(); + //Layout(); + } } - void MonitorPanel::on_select_printer(wxCommandEvent& event) +void MonitorPanel::on_select_printer(wxCommandEvent& event) { Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; - if ( dev->get_selected_machine() && (dev->get_selected_machine()->dev_id != event.GetString().ToStdString()) && m_hms_panel) { + if ( dev->get_selected_machine() && (dev->get_selected_machine()->get_dev_id() != event.GetString().ToStdString()) && m_hms_panel) { m_hms_panel->clear_hms_tag(); } @@ -313,7 +316,7 @@ void MonitorPanel::select_machine(std::string machine_sn) obj_->reset_pa_cali_history_result(); obj_->reset_pa_cali_result(); Sidebar &sidebar = GUI::wxGetApp().sidebar(); - sidebar.load_ams_list(obj_->dev_id, obj_); + sidebar.load_ams_list(obj_->get_dev_id(), obj_); sidebar.update_sync_status(obj_); sidebar.set_need_auto_sync_after_connect_printer(sidebar.need_auto_sync_extruder_list_after_connect_priner(obj_)); } @@ -351,17 +354,14 @@ void MonitorPanel::on_size(wxSizeEvent &event) void MonitorPanel::update_all() { + if (!m_initialized) + return; + NetworkAgent* m_agent = wxGetApp().getAgent(); Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; obj = dev->get_selected_machine(); - m_status_info_panel->obj = obj; - m_upgrade_panel->update(obj); - m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj); - m_media_file_panel->SetMachineObject(obj); - m_side_tools->update_status(obj); - if (!obj) { show_status((int)MONITOR_NO_PRINTER); m_hms_panel->clear_hms_tag(); @@ -371,6 +371,9 @@ void MonitorPanel::update_all() } if (obj->connection_type() != last_conn_type) { last_conn_type = obj->connection_type(); } + + m_side_tools->update_status(obj); + if (obj->is_connecting()) { show_status(MONITOR_CONNECTING); return; @@ -388,20 +391,21 @@ void MonitorPanel::update_all() show_status(MONITOR_NORMAL); - if (m_status_info_panel->IsShown()) { + auto current_page = m_tabpanel->GetCurrentPage(); + if (current_page == m_status_info_panel) { + m_status_info_panel->obj = obj; + m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj); m_status_info_panel->update(obj); + } else if (current_page == m_upgrade_panel) { + m_upgrade_panel->update(obj); + } else if (current_page == m_media_file_panel) { + m_media_file_panel->UpdateByObj(obj); } - if (m_hms_panel->IsShown() || (obj->hms_list.size() != m_hms_panel->temp_hms_list.size())) { + if (current_page == m_hms_panel || (obj->GetHMS()->GetHMSItems().size() != m_hms_panel->temp_hms_list.size())) { m_hms_panel->update(obj); } -#if !QDT_RELEASE_TO_PUBLIC - if (m_upgrade_panel->IsShown()) { - m_upgrade_panel->update(obj); - } -#endif - update_hms_tag(); } @@ -411,10 +415,10 @@ void MonitorPanel::update_hms_tag() if (!obj) { break;} - const wxString &msg = wxGetApp().get_hms_query()->query_hms_msg(obj->dev_id, hmsitem.second.get_long_error_code()); + const wxString &msg = wxGetApp().get_hms_query()->query_hms_msg(obj->get_dev_id(), hmsitem.second.get_long_error_code()); if (msg.empty()){ continue;} /*STUDIO-10363 it's hidden message*/ - if (!hmsitem.second.already_read) { + if (!hmsitem.second.has_read()) { //show HMS new tag m_tabpanel->GetBtnsListCtrl()->showNewTag(3, true); return; @@ -446,10 +450,10 @@ bool MonitorPanel::Show(bool show) dev->load_last_machine(); obj = dev->get_selected_machine(); if (obj && obj->is_info_ready(false)) - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); } else { obj->reset_update_time(); - //select_machine(obj->dev_id); + //select_machine(obj->get_dev_id()); } } } else { @@ -463,17 +467,17 @@ void MonitorPanel::show_status(int status) { if (!m_initialized) return; if (last_status == status)return; - if (last_status & (int)MonitorStatus::MONITOR_CONNECTING != 0) { + if ((last_status & (int)MonitorStatus::MONITOR_CONNECTING) != 0) { NetworkAgent* agent = wxGetApp().getAgent(); json j; - j["dev_id"] = obj ? obj->dev_id : "obj_nullptr"; - if (status & (int)MonitorStatus::MONITOR_DISCONNECTED != 0) { + j["dev_id"] = obj ? obj->get_dev_id() : "obj_nullptr"; + if ((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0) { j["result"] = "failed"; if (agent) { agent->track_event("connect_dev", j.dump()); } } - else if (status & (int)MonitorStatus::MONITOR_NORMAL != 0) { + else if ((status & (int)MonitorStatus::MONITOR_NORMAL) != 0) { j["result"] = "success"; if (agent) { agent->track_event("connect_dev", j.dump()); @@ -484,7 +488,7 @@ void MonitorPanel::show_status(int status) BOOST_LOG_TRIVIAL(info) << "monitor: show_status = " << status; -//Freeze(); + //Freeze(); // update panels if (m_side_tools) { m_side_tools->show_status(status); }; m_status_info_panel->show_status(status); @@ -509,7 +513,7 @@ void MonitorPanel::show_status(int status) m_tabpanel->Layout(); } Layout(); -//Thaw(); + //Thaw(); } std::string MonitorPanel::get_string_from_tab(PrinterTab tab) @@ -531,7 +535,7 @@ std::string MonitorPanel::get_string_from_tab(PrinterTab tab) return ""; } -void MonitorPanel::jump_to_HMS(wxCommandEvent& e) +void MonitorPanel::jump_to_HMS() { if (!this->IsShown()) return; @@ -540,6 +544,18 @@ void MonitorPanel::jump_to_HMS(wxCommandEvent& e) m_tabpanel->SetSelection(PT_HMS); } +void MonitorPanel::jump_to_LiveView() +{ + if (!this->IsShown()) { return; } + + auto page = m_tabpanel->GetCurrentPage(); + if (page && page != m_hms_panel) + { + m_tabpanel->SetSelection(PT_STATUS); + } + + m_status_info_panel->get_media_play_ctrl()->jump_to_play(); +} } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index 7d2846f..a7f7126 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -154,7 +154,9 @@ public: void stop_update() {update_flag = false;}; void start_update() {update_flag = true;}; - void jump_to_HMS(wxCommandEvent& e); + + void jump_to_HMS(); + void jump_to_LiveView(); }; diff --git a/src/slic3r/GUI/MultiMachine.cpp b/src/slic3r/GUI/MultiMachine.cpp index 9223923..2d53fee 100644 --- a/src/slic3r/GUI/MultiMachine.cpp +++ b/src/slic3r/GUI/MultiMachine.cpp @@ -19,10 +19,6 @@ DeviceItem::DeviceItem(wxWindow* parent, MachineObject* obj) : wxWindow(parent, wxID_ANY) , obj_(obj) { - obj_->dev_name = obj->dev_name; - obj_->dev_url = obj->dev_url; - obj_->dev_ip = obj->dev_ip; - obj_->dev_apikey = obj->dev_apikey; //y70 sync_state(); Bind(EVT_MULTI_REFRESH, &DeviceItem::on_refresh, this); } @@ -36,7 +32,7 @@ void DeviceItem::sync_state() { if (obj_) { state_online = obj_->is_online(); - state_dev_name = obj_->dev_name; + state_dev_name = obj_->get_dev_name(); //printable if (obj_->print_status == "IDLE") { @@ -133,7 +129,7 @@ bool DeviceItem::is_blocking_printing(MachineObject* obj_) //source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); //if (source_model != target_model) { - // std::vector compatible_machine = dev->get_compatible_machine(target_model); + // std::vector compatible_machine = obj_->get_compatible_machine(); // vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); // if (it == compatible_machine.end()) { // return true; @@ -232,8 +228,8 @@ std::vector selected_machines(const std::vector& dev_i std::vector res; for (const auto& item : dev_item_list) { const MachineObject* dev = item->get_obj(); - const std::string& dev_name = dev->dev_name; - const std::string& dev_ip = dev->dev_ip; + const std::string& dev_name = dev->get_dev_name(); + const std::string& dev_ip = dev->get_dev_ip(); auto name_it = dev_name.find(search_text); auto ip_it = dev_ip.find(search_text); diff --git a/src/slic3r/GUI/MultiMachineManagerPage.cpp b/src/slic3r/GUI/MultiMachineManagerPage.cpp index 669ca6c..66b70cb 100644 --- a/src/slic3r/GUI/MultiMachineManagerPage.cpp +++ b/src/slic3r/GUI/MultiMachineManagerPage.cpp @@ -2,6 +2,8 @@ #include "GUI_App.hpp" #include "MainFrame.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -18,7 +20,7 @@ MultiMachineItem::MultiMachineItem(wxWindow* parent, MachineObject* obj) Bind(wxEVT_LEFT_DOWN, &MultiMachineItem::OnLeftDown, this); Bind(wxEVT_MOTION, &MultiMachineItem::OnMove, this); Bind(EVT_MULTI_DEVICE_VIEW, [this, obj](auto& e) { - wxGetApp().mainframe->jump_to_monitor(obj->dev_id); + wxGetApp().mainframe->jump_to_monitor(obj->get_dev_id()); if (wxGetApp().mainframe->m_monitor->get_status_panel()->get_media_play_ctrl()) { wxGetApp().mainframe->m_monitor->get_status_panel()->get_media_play_ctrl()->jump_to_play(); } @@ -152,7 +154,7 @@ void MultiMachineItem::doRender(wxDC& dc) if (obj_) { //dev name - wxString dev_name = wxString::FromUTF8(obj_->dev_name); + wxString dev_name = wxString::FromUTF8(obj_->get_dev_name()); if (!obj_->is_online()) { dev_name = dev_name + "(" + _L("Offline") + ")"; } @@ -235,7 +237,7 @@ void MultiMachineItem::doRender(wxDC& dc) void MultiMachineItem::post_event(wxCommandEvent&& event) { event.SetEventObject(this); - event.SetString(obj_->dev_id); + event.SetString(obj_->get_dev_id()); event.SetInt(state_selected); wxPostEvent(this, event); } @@ -620,8 +622,8 @@ void MultiMachineManagerPage::sync_state(MachineObject* obj_) ObjState state_obj; if (obj_) { - state_obj.dev_id = obj_->dev_id; - state_obj.state_dev_name = obj_->dev_name; + state_obj.dev_id = obj_->get_dev_id(); + state_obj.state_dev_name = obj_->get_dev_name(); if (obj_->print_status == "IDLE") { state_obj.state_device = 0; diff --git a/src/slic3r/GUI/MultiMachinePage.cpp b/src/slic3r/GUI/MultiMachinePage.cpp index 5843794..873f270 100644 --- a/src/slic3r/GUI/MultiMachinePage.cpp +++ b/src/slic3r/GUI/MultiMachinePage.cpp @@ -2,6 +2,8 @@ #include "GUI_App.hpp" #include "MainFrame.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -279,13 +281,13 @@ void DevicePickItem::doRender(wxDC& dc) left += FromDIP(PICK_LEFT_PRINTABLE); //dev names - DrawTextWithEllipsis(dc, wxString::FromUTF8(get_obj()->dev_name), FromDIP(PICK_LEFT_DEV_NAME), left); + DrawTextWithEllipsis(dc, wxString::FromUTF8(get_obj()->get_dev_name()), FromDIP(PICK_LEFT_DEV_NAME), left); left += FromDIP(PICK_LEFT_DEV_NAME); } void DevicePickItem::post_event(wxCommandEvent&& event) { event.SetEventObject(this); - event.SetString(obj_->dev_id); + event.SetString(obj_->get_dev_id()); event.SetInt(state_selected); wxPostEvent(this, event); } @@ -366,7 +368,7 @@ void MultiMachinePickPage::update_selected_count() int count = 0; for (auto it = m_device_items.begin(); it != m_device_items.end(); it++) { if (it->second->state_selected == 1 ) { - selected_multi_devices.push_back(it->second->obj_->dev_id); + selected_multi_devices.push_back(it->second->obj_->get_dev_id()); count++; } } @@ -426,7 +428,7 @@ void MultiMachinePickPage::refresh_user_device() std::vector subscribe_list; for (auto it = user_machine.begin(); it != user_machine.end(); ++it) { - if (it->second->m_extder_data.total_extder_count > 1) { continue; } + if (it->second->GetExtderSystem()->GetTotalExtderCount() > 1) { continue; } if (it->second->printer_type == "O1D") { continue;} /*maybe total_extder_count is not valid, hard codes here. to be moved to printers json*/ DevicePickItem* di = new DevicePickItem(scroll_macine_list, it->second); @@ -454,7 +456,7 @@ void MultiMachinePickPage::refresh_user_device() } //update selected - auto dev_it = std::find(selected_multi_devices.begin(), selected_multi_devices.end(), it->second->dev_id ); + auto dev_it = std::find(selected_multi_devices.begin(), selected_multi_devices.end(), it->second->get_dev_id() ); if (dev_it != selected_multi_devices.end()) { di->state_selected = 1; } diff --git a/src/slic3r/GUI/MultiSendMachineModel.cpp b/src/slic3r/GUI/MultiSendMachineModel.cpp index 101a3f1..3103b51 100644 --- a/src/slic3r/GUI/MultiSendMachineModel.cpp +++ b/src/slic3r/GUI/MultiSendMachineModel.cpp @@ -20,7 +20,7 @@ void MultiSendMachineModel::Init() wxDataViewItem MultiSendMachineModel::AddMachine(MachineObject* obj) { - wxString name = from_u8(obj->dev_name); + wxString name = from_u8(obj->get_dev_name()); wxDataViewItem new_item; diff --git a/src/slic3r/GUI/MultiTaskManagerPage.cpp b/src/slic3r/GUI/MultiTaskManagerPage.cpp index bb806ca..1477f1a 100644 --- a/src/slic3r/GUI/MultiTaskManagerPage.cpp +++ b/src/slic3r/GUI/MultiTaskManagerPage.cpp @@ -8,6 +8,8 @@ #include #include "QDTUtil.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -177,7 +179,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 =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); + BOOST_LOG_TRIVIAL(info) << "MultiTask: pause current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->get_dev_id()); get_obj()->command_task_pause(); m_button_pause->Hide(); m_button_resume->Show(); @@ -188,7 +190,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 =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); + BOOST_LOG_TRIVIAL(info) << "MultiTask: resume current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->get_dev_id()); get_obj()->command_task_resume(); m_button_pause->Show(); m_button_resume->Hide(); @@ -199,7 +201,7 @@ void MultiTaskItem::onResume() void MultiTaskItem::onStop() { if (get_obj()) { - BOOST_LOG_TRIVIAL(info) << "MultiTask: abort current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->dev_id); + BOOST_LOG_TRIVIAL(info) << "MultiTask: abort current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(get_obj()->get_dev_id()); get_obj()->command_task_abort(); m_button_pause->Hide(); m_button_resume->Hide(); diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index c41d250..9c6d1d0 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1730,6 +1730,14 @@ void NotificationManager::push_slicing_error_notification(const std::string &tex push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text, link, callback }, 0); set_slicing_progress_hidden(); } + +void NotificationManager::push_helio_error_notification(const std::string &text) +{ + set_all_slicing_errors_gray(false); + push_notification_data({NotificationType::HelioSlicingError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text, ""}, 0); + set_slicing_progress_hidden(); +} + void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ModelObject const * obj, ObjectID oid, int warning_step, int warning_msg_id, NotificationLevel level/* = NotificationLevel::WarningNotificationLevel*/) { std::function callback; @@ -2146,11 +2154,12 @@ void NotificationManager::update_slicing_notif_dailytips(bool need_change) // Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended wxGetApp().plater()->init_notification_manager(); } -void NotificationManager::set_slicing_progress_began() +void NotificationManager::set_slicing_progress_began(bool is_helio) { for (std::unique_ptr & notification : m_pop_notifications) { if (notification->get_type() == NotificationType::SlicingProgress) { SlicingProgressNotification* spn = dynamic_cast(notification.get()); + spn->get_dailytips_panel()->set_is_helio(is_helio); spn->set_progress_state(SlicingProgressNotification::SlicingProgressState::SP_BEGAN); return; } @@ -2192,6 +2201,7 @@ void NotificationManager::set_slicing_progress_hidden() for (std::unique_ptr& notification : m_pop_notifications) { if (notification->get_type() == NotificationType::SlicingProgress) { SlicingProgressNotification* notif = dynamic_cast(notification.get()); + notif->get_dailytips_panel()->set_is_helio(false); notif->set_progress_state(SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING); wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); return; @@ -2301,40 +2311,6 @@ int NotificationManager::progress_indicator_get_range() const return 0; } -void NotificationManager::push_hint_notification(bool open_next) -{ - return; - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::DidYouKnowHint) { - (dynamic_cast(notification.get()))->open_next(); - return; - } - } - - NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::HintNotificationLevel, 300, "" }; - // from user - open now - if (!open_next) { - push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); - stop_delayed_notifications_of_type(NotificationType::DidYouKnowHint); - // at startup - delay for half a second to let other notification pop up, than try every 30 seconds - // show only if no notifications are shown - } - else { - auto condition = [&self = std::as_const(*this)]() { - return self.get_notification_count() == 0; - }; - push_delayed_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), condition, 500, 30000); - } -} - -bool NotificationManager::is_hint_notification_open() -{ - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::DidYouKnowHint) - return true; - } - return false; -} void NotificationManager::deactivate_loaded_hints() { ; diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index c89277d..a05960a 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -76,6 +76,8 @@ enum class NotificationType // thread thowing a SlicingError exception. SlicingError, //Gcode conflict generates slicing severe warning + HelioSlicingError, + // Gcode conflict generates slicing severe warning SlicingSeriousWarning, // Slicing warnings, issued by the slicing process. // Slicing warnings are registered for a particular Print milestone or a PrintObject and its milestone. @@ -223,7 +225,8 @@ public: void close_slicing_serious_warning_notification(const std::string &text); // Creates Slicing Error notification with a custom text and no fade out. void push_slicing_error_notification(const std::string &text, std::vector objs); - // Creates Slicing Warning notification with a custom text and no fade out. + void push_helio_error_notification(const std::string &text); + // Creates Slicing Warning notification with a custom text and no fade out. void push_slicing_warning_notification(const std::string &text, bool gray, ModelObject const *obj, ObjectID oid, int warning_step, int warning_msg_id, NotificationLevel level = NotificationLevel::WarningNotificationLevel); // marks slicing errors as gray void set_all_slicing_errors_gray(bool g); @@ -278,7 +281,7 @@ public: // slicing progress void init_slicing_progress_notification(std::function cancel_callback); void update_slicing_notif_dailytips(bool need_change); - void set_slicing_progress_began(); + void set_slicing_progress_began(bool is_helio = false); // percentage negative = canceled, <0-1) = progress, 1 = completed void set_slicing_progress_percentage(const std::string& text, float percentage); void set_slicing_progress_canceled(const std::string& text); @@ -296,10 +299,6 @@ public: void progress_indicator_set_progress(int pr); void progress_indicator_set_status_text(const char*); // utf8 char array int progress_indicator_get_range() const; - // Hint (did you know) notification - void push_hint_notification(bool open_next); - bool is_hint_notification_open(); - // Forces Hints to reload its content when next hint should be showed void deactivate_loaded_hints(); // Adds counter to existing UpdatedItemsInfo notification or opens new one void push_updated_item_info_notification(InfoItemType type); diff --git a/src/slic3r/GUI/ObjColorDialog.cpp b/src/slic3r/GUI/ObjColorDialog.cpp index 0605342..80836d5 100644 --- a/src/slic3r/GUI/ObjColorDialog.cpp +++ b/src/slic3r/GUI/ObjColorDialog.cpp @@ -673,7 +673,7 @@ ComboBox *ObjColorPanel::CreateEditorCtrl(wxWindow *parent, int id) // wxRect la wxCB_READONLY | CB_NO_DROP_ICON | CB_NO_TEXT); c_editor->SetMinSize(wxSize(FromDIP(m_combox_width), -1)); c_editor->SetMaxSize(wxSize(FromDIP(m_combox_width), -1)); - c_editor->GetDropDown().SetUseContentWidth(true); + c_editor->GetDropDown().SetUseContentWidth(false); for (size_t i = 0; i < icons.size(); i++) { c_editor->Append(wxString::Format("%d", i), *icons[i]); if (i == 0) { @@ -691,9 +691,6 @@ ComboBox *ObjColorPanel::CreateEditorCtrl(wxWindow *parent, int id) // wxRect la m_cluster_map_filaments[i] = com_box->GetSelection(); m_new_add_colors[i] = com_box->GetItemTooltip(com_box->GetSelection()); deal_thumbnail(); - if (m_cluster_map_filaments[i] > m_max_filament_index) { - m_max_filament_index = m_cluster_map_filaments[i]; - } } evt.StopPropagation(); }); @@ -706,7 +703,6 @@ void ObjColorPanel::deal_approximate_match_btn() if (m_result_icon_list.size() == 0) { return; } auto map_count = m_result_icon_list[0]->bitmap_combox->GetCount() -1; if (map_count < 1) { return; } - m_max_filament_index = 0; for (size_t i = 0; i < m_cluster_colours.size(); i++) { auto c = m_cluster_colours[i]; std::vector color_dists; @@ -724,9 +720,6 @@ void ObjColorPanel::deal_approximate_match_btn() m_result_icon_list[i]->bitmap_combox->SetSelection(new_index); m_new_add_colors[i] = m_result_icon_list[i]->bitmap_combox->GetItemTooltip(new_index); m_cluster_map_filaments[i] = new_index; - if (new_index > m_max_filament_index) { - m_max_filament_index = new_index; - } } } @@ -820,10 +813,27 @@ void ObjColorPanel::draw_new_table() void ObjColorPanel::update_new_add_final_colors() { m_new_add_final_colors = m_new_add_colors; + if (!m_cluster_map_filaments.empty()) { + m_max_filament_index = *std::max_element(m_cluster_map_filaments.begin(), m_cluster_map_filaments.end()); + } else { + m_max_filament_index = 0; + } + if (m_max_filament_index <= m_colours.size()) { // Fix 20240904 m_new_add_final_colors.clear(); - } else { + } + else { m_new_add_final_colors.resize(m_max_filament_index - m_colours.size()); + for (int ii = m_colours.size() ; ii < m_max_filament_index; ii++) { + for (int j = 0; j < m_cluster_map_filaments.size(); j++) { + if (m_cluster_map_filaments[j] == (ii+ 1) && j < m_new_add_colors.size()) { + auto index = ii - m_colours.size(); + if (index < m_new_add_final_colors.size()) { + m_new_add_final_colors[index] = m_new_add_colors[j]; + } + } + } + } } if (m_new_add_final_colors.size() > 0) { m_is_add_filament = true; @@ -979,7 +989,6 @@ bool ObjColorPanel::deal_add_btn() new_index++; } new_index = m_colours.size() + 1; - m_max_filament_index = 0; for (size_t i = 0; i < m_result_icon_list.size(); i++) { auto item = m_result_icon_list[i]; for (size_t k = 0; k < new_icons.size(); k++) { @@ -988,9 +997,6 @@ bool ObjColorPanel::deal_add_btn() } item->bitmap_combox->SetSelection(new_index); m_cluster_map_filaments[i] = new_index; - if (new_index > m_max_filament_index) { - m_max_filament_index = new_index; - } new_index++; } if (is_exceed) { diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index ea00fe8..646d421 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -970,7 +970,12 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config { case coPercents: case coFloats: { - if (opt_index < 0 ? config.option(opt_key)->is_nil() : dynamic_cast(config.option(opt_key))->is_nil(opt_index)) + const ConfigOptionVectorBase *option = dynamic_cast(config.option(opt_key)); + if (!option) { + ret = _(L("N/A")); + break; + } + if (opt_index < 0 || opt_index >= option->size() ? config.option(opt_key)->is_nil() : option->is_nil(opt_index)) ret = _(L("N/A")); else { double val = opt->type == coFloats ? @@ -978,10 +983,15 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config config.option(opt_key)->get_at(idx); ret = double_to_string(val); } + break; } - break; case coFloatsOrPercents: { - if (opt_index < 0 ? config.option(opt_key)->is_nil() : dynamic_cast(config.option(opt_key))->is_nil(opt_index)) + const ConfigOptionVectorBase *option = dynamic_cast(config.option(opt_key)); + if (!option) { + ret = _(L("N/A")); + break; + } + if (opt_index < 0 || opt_index >= option->size() ? config.option(opt_key)->is_nil() : option->is_nil(opt_index)) ret = _(L("N/A")); else { const auto& value = config.option(opt_key)->get_at(idx); @@ -1124,6 +1134,10 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config ret = get_thumbnails_string(config.option(opt_key)->values); else if (opt_key == "bed_exclude_area") ret = get_thumbnails_string(config.option(opt_key)->values); + else if (opt_key == "thumbnail_size") + ret = get_thumbnails_string(config.option(opt_key)->values); + else if (opt_key == "wrapping_exclude_area") + ret = get_thumbnails_string(config.option(opt_key)->values); //w12 else ret = config.option(opt_key)->get_at(idx); @@ -1260,6 +1274,10 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi ret = get_thumbnails_string(config.option(opt_key)->values); else if (opt_key == "bed_exclude_area") ret = get_thumbnails_string(config.option(opt_key)->values); + else if (opt_key == "thumbnail_size") + ret = get_thumbnails_string(config.option(opt_key)->values); + else if (opt_key == "wrapping_exclude_area") + ret = get_thumbnails_string(config.option(opt_key)->values); //w12 else ret = config.option(opt_key)->get_at(idx); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 545c2b3..05aa083 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1389,6 +1389,48 @@ bool PartPlate::check_mixture_of_pla_and_petg(const DynamicPrintConfig &config) return true; } +bool PartPlate::check_mixture_filament_compatible(const DynamicPrintConfig &config, std::string &error_msg) +{ + static std::unordered_map> incompatible_filament_pairs; + + auto add_incompatibility = [&](std::string filament_type1, std::string filament_type2) { + incompatible_filament_pairs[filament_type1].insert(filament_type2); + incompatible_filament_pairs[filament_type2].insert(filament_type1); + }; + + if (incompatible_filament_pairs.empty()) { add_incompatibility("PVA", "PETG"); } + + std::vector used_filaments = get_extruders(true); // 1 based idx + std::vector filament_types; + auto filament_type_opt = config.option("filament_type"); + for (auto filament : used_filaments) { + int filament_idx = filament - 1; + filament_types.push_back(filament_type_opt->values[filament_idx]); + }; + + { + std::unordered_set seen; + filament_types.erase(std::remove_if(filament_types.begin(), filament_types.end(), [&](const std::string &s) { return !seen.insert(s).second; }), filament_types.end()); + } + + std::vector> conflicts; + + for (size_t i = 0; i < filament_types.size(); i++) { + auto it = incompatible_filament_pairs.find(filament_types[i]); + if (it == incompatible_filament_pairs.end()) continue; + for (size_t j = i + 1; j < filament_types.size(); ++j) { + if (it->second.count(filament_types[j])) { conflicts.emplace_back(filament_types[i], filament_types[j]); } + } + } + + if (!conflicts.empty()) { + // TODO: add the full text if has multi conflict + auto conflict = conflicts.front(); + error_msg = GUI::format(_L("Mixing %1% with %2% in printing is not recommended.\n"), conflict.first, conflict.second); + } + return conflicts.empty(); +} + 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]; @@ -1507,7 +1549,7 @@ bool PartPlate::check_compatible_of_nozzle_and_filament(const DynamicPrintConfig return wipe_tower_size; }*/ -Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects) const +Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects, bool enable_wrapping_detection) const { Vec3d wipe_tower_size; double layer_height = 0.08f; // hard code layer height @@ -1537,7 +1579,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con wipe_tower_size(2) = max_height; //const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config; auto timelapse_type = config.option>("timelapse_type"); - bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false; + bool need_wipe_tower = (timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false) | enable_wrapping_detection; double extra_spacing = config.option("prime_tower_infill_gap")->getFloat() / 100.; const ConfigOptionBool* use_rib_wall_opt = config.option("prime_tower_rib_wall"); bool use_rib_wall = use_rib_wall_opt ? use_rib_wall_opt->value: true; @@ -1560,7 +1602,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con if (extruder_count == 2) volume += filament_change_volume * (int) (plate_extruder_size / 2); if (use_rib_wall) { depth = std::sqrt(volume / layer_height * extra_spacing); - if (timelapse_enabled || plate_extruder_size > 1) { + if (need_wipe_tower || plate_extruder_size > 1) { float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height); depth = std::max((double) min_wipe_tower_depth, depth); depth += rib_width / std::sqrt(2) + m_print->config().prime_tower_extra_rib_length.value; @@ -1569,7 +1611,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con } else { depth = volume/ (layer_height * w) *extra_spacing; - if (timelapse_enabled || depth > EPSILON) { + if (need_wipe_tower || depth > EPSILON) { float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height); depth = std::max((double)min_wipe_tower_depth, depth); } @@ -1587,7 +1629,9 @@ arrangement::ArrangePolygon PartPlate::estimate_wipe_tower_polygon(const Dynamic float w = dynamic_cast(config.option("prime_tower_width"))->value; //float a = dynamic_cast(config.option("wipe_tower_rotation_angle"))->value; std::vector v = dynamic_cast(config.option("filament_prime_volume"))->values; - wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects); + const ConfigOptionBool * wrapping_opt = dynamic_cast(config.option("enable_wrapping_detection")); + bool enable_wrapping = (wrapping_opt != nullptr) && wrapping_opt->value; + wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects, enable_wrapping); int plate_width=m_width, plate_depth=m_depth; float depth = wt_size(1); float margin = WIPE_TOWER_MARGIN, wp_brim_width = 0.f; @@ -1826,6 +1870,12 @@ void PartPlate::get_print(PrintBase** print, GCodeResult** result, int* index) return; } +GCodeProcessorResult *PartPlate::get_gcode_result() +{ + return m_gcode_result; +} + + //set the print object, result and it's index void PartPlate::set_print(PrintBase* print, GCodeResult* result, int index) { @@ -3373,6 +3423,18 @@ void PartPlateList::calc_exclude_triangles(const ExPolygon &poly) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n"; } +void PartPlateList::calc_triangles_from_polygon(const ExPolygon &poly, GLModel &render_model){ + if (poly.empty()) { + render_model.reset(); + return; + } + auto triangles = triangulate_expolygon_2f(poly, NORMALS_UP); + render_model.reset(); + if (!render_model.init_model_from_poly(triangles, GROUND_Z)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "calc_triangles_from_polygon fail"; + } +} + void PartPlateList::calc_gridlines(const ExPolygon &poly, const BoundingBox &pp_bbox) { Polylines axes_lines, axes_lines_bolder; @@ -3798,12 +3860,13 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool ini const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; float w = dynamic_cast(print_cfg.option("prime_tower_width"))->value; std::vector v = dynamic_cast(full_config.option("filament_prime_volume"))->values; + bool enable_wrapping = dynamic_cast(full_config.option("enable_wrapping_detection"))->value; int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count(); double wipe_vol = get_max_element(v); - Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, init_pos ? 2 : 0); + Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, init_pos ? 2 : 0, false, enable_wrapping); if (!init_pos && (is_approx(wipe_tower_size(0), 0.0) || is_approx(wipe_tower_size(1), 0.0))) { - wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 2); + wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 2, false, enable_wrapping); } // update for wipe tower position @@ -3843,7 +3906,7 @@ void PartPlateList::reset_size(int width, int depth, int height, bool reload_obj m_plate_height = height; update_all_plates_pos_and_size(false, false, true); if (update_shapes) { - set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); + set_shapes(m_shape, m_exclude_areas, m_wrapping_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); } if (reload_objects) reload_all_objects(); @@ -3988,7 +4051,7 @@ int PartPlateList::create_plate(bool adjust_position) BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":old_cols %1% -> new_cols %2%") % old_cols % cols; //update the origin of each plate update_all_plates_pos_and_size(adjust_position, false); - set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); + set_shapes(m_shape, m_exclude_areas, m_wrapping_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); if (m_plater) { Vec2d pos = compute_shape_position(m_current_plate, cols); @@ -4158,7 +4221,7 @@ int PartPlateList::delete_plate(int index) { //update the origin of each plate update_all_plates_pos_and_size(); - set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); + set_shapes(m_shape, m_exclude_areas, m_wrapping_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); } else { @@ -4877,6 +4940,16 @@ int PartPlateList::construct_objects_list_for_new_plate(int plate_index) return ret; } +std::vector PartPlateList::get_plate_wrapping_detection_area() +{ + DynamicPrintConfig gconfig = wxGetApp().preset_bundle->printers.get_edited_preset().config; + ConfigOptionPoints *wrapping_exclude_area_opt = gconfig.option("wrapping_exclude_area"); + if (wrapping_exclude_area_opt) { + return wrapping_exclude_area_opt->values; + } + + return std::vector(); +} //compute the plate index int PartPlateList::compute_plate_index(arrangement::ArrangePolygon& arrange_polygon) @@ -4968,10 +5041,40 @@ bool PartPlateList::preprocess_arrange_polygon_other_locked(int obj_index, int i return locked; } -bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates, float inflation) +bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons &unselected, bool enable_wrapping_detect, int num_plates, float inflation) { bool added = false; + // wrapping detection area + if (enable_wrapping_detect) + { + if (!m_wrapping_exclude_areas.empty()) + { + Polygon ap{}; + for (const Vec2d &p : m_wrapping_exclude_areas) + { + ap.append({scale_(p(0)), scale_(p(1))}); + } + + for(int j = 0; j < num_plates; j++) + { + arrangement::ArrangePolygon ret; + ret.poly.contour = ap; + ret.translation = Vec2crd(0, 0); + ret.rotation = 0.0f; + ret.is_virt_object = true; + ret.bed_idx = j; + ret.height = 1; + ret.name = "WrappingRegion"; + ret.inflation = inflation; + + unselected.emplace_back(std::move(ret)); + } + } + added = true; + } + + // excluded area if (m_exclude_areas.size() > 0) { //has exclude areas @@ -5196,6 +5299,23 @@ void PartPlateList::render_instance(bool bottom, bool only_current, bool only_bo shader->set_uniform("projection_matrix", proj_mat); if (!bottom) { // draw background render_exclude_area(force_background_color); // for selected_plate + if(wxGetApp().plater()->get_enable_wrapping_detection()){ + if(!m_wrapping_detection_triangles.is_initialized()){ + auto points = get_plate_wrapping_detection_area(); + if (points.size() > 0) {//wrapping_detection_area + ExPolygon temp_poly; + for (const Vec2d &p : points) { + temp_poly.contour.append({scale_(p(0)), scale_(p(1))}); + } + auto result = intersection(m_print_polygon, temp_poly); + if (result.size() > 0) { + ExPolygon wrapp_poly(result[0]); + calc_triangles_from_polygon(wrapp_poly, m_wrapping_detection_triangles); + } + } + } + render_wrapping_detection_area(force_background_color); + } } if (show_grid) render_grid(bottom); // for selected_plate @@ -5321,6 +5441,15 @@ void PartPlateList::render_unselected_background(bool force_default_color) m_triangles.render_geometry(); } +void PartPlateList::render_wrapping_detection_area(bool force_default_color) +{ + if (force_default_color || !m_wrapping_detection_triangles.is_initialized()) + return; + ColorRGBA select_color{0.765f, 0.7686f, 0.7686f, 1.0f}; + m_wrapping_detection_triangles.set_color(select_color); + m_wrapping_detection_triangles.render_geometry(); +} + void PartPlateList::render_exclude_area(bool force_default_color) { if (force_default_color || !m_exclude_triangles.is_initialized()) // for thumbnail case @@ -5482,11 +5611,19 @@ void PartPlateList::select_plate_view() m_plater->get_camera().select_view("topfront"); } -bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector& extruder_areas, const std::vector& extruder_heights, const std::string& texture_filename, float height_to_lid, float height_to_rod) +bool PartPlateList::set_shapes(const Pointfs &shape, + const Pointfs &exclude_areas, + const Pointfs &wrapping_exclude_areas, + const std::vector &extruder_areas, + const std::vector &extruder_heights, + const std::string &texture_filename, + float height_to_lid, + float height_to_rod) { const std::lock_guard local_lock(m_plates_mutex); m_shape = shape; m_exclude_areas = exclude_areas; + m_wrapping_exclude_areas = wrapping_exclude_areas; m_extruder_areas = extruder_areas; m_extruder_heights = extruder_heights; m_height_to_lid = height_to_lid; @@ -5516,6 +5653,10 @@ bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_area generate_print_polygon(poly); calc_triangles(poly); + // reset m_wrapping_detection_triangles when change printer + m_print_polygon = poly; + m_wrapping_detection_triangles.reset(); + ExPolygon exclude_poly; generate_exclude_polygon(exclude_poly); calc_exclude_triangles(exclude_poly); @@ -5701,7 +5842,7 @@ int PartPlateList::rebuild_plates_after_deserialize(std::vector& previous_ for (unsigned int i = 0; i < (unsigned int) m_plate_list.size(); ++i) { m_plate_list[i]->m_partplate_list = this; }//set_shapes api: every plate use m_partplate_list - set_shapes(m_shape, m_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); + set_shapes(m_shape, m_exclude_areas, m_wrapping_exclude_areas, m_extruder_areas, m_extruder_heights, m_logo_texture_filename, m_height_to_lid, m_height_to_rod); for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i){ bool need_reset_print = false; m_plate_list[i]->m_plater = this->m_plater; @@ -5891,8 +6032,9 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w plate_data_item->pattern_bbox_file = "valid_pattern_bbox"; plate_data_item->gcode_file = m_plate_list[i]->m_gcode_result->filename; plate_data_item->is_sliced_valid = true; + //y71 plate_data_item->gcode_prediction = std::to_string( - (int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time); + (int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time + 600); plate_data_item->toolpath_outside = m_plate_list[i]->m_gcode_result->toolpath_outside; plate_data_item->timelapse_warning_code = m_plate_list[i]->m_gcode_result->timelapse_warning_code; m_plate_list[i]->set_timelapse_warning_code(plate_data_item->timelapse_warning_code); diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 6577133..c763ebc 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -103,6 +103,7 @@ private: bool m_ready_for_slice; bool m_slice_result_valid; bool m_apply_invalid {false}; + bool m_helio_apply_invalid {false}; float m_slice_percent; Print *m_print; //Print reference, not own it, no need to serialize @@ -282,6 +283,9 @@ public: //set the print object, result and it's index void set_print(PrintBase *print, GCodeResult* result = nullptr, int index = -1); + // get gcode result + GCodeProcessorResult* get_gcode_result(); + //get gcode filename std::string get_gcode_filename(); @@ -304,7 +308,7 @@ public: Vec3d get_origin() { return m_origin; } //Vec3d calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const; - Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const; + Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false, bool enable_wrapping_detection = false) const; arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, Vec3d& wt_pos, Vec3d& wt_size, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const; bool check_objects_empty_and_gcode3mf(std::vector &result) const; // get used filaments from config, 1 based idx @@ -317,6 +321,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_mixture_filament_compatible(const DynamicPrintConfig& config, std::string &error_msg); bool check_compatible_of_nozzle_and_filament(const DynamicPrintConfig & config, const std::vector& filament_presets, std::string& error_msg); /* instance related operations*/ @@ -406,6 +411,11 @@ public: { return m_ready_for_slice && !m_apply_invalid; } + + bool can_helio_slice() const { + return m_ready_for_slice && !m_apply_invalid && !m_helio_apply_invalid; + } + void update_slice_ready_status(bool ready_slice) { m_ready_for_slice = ready_slice; @@ -416,11 +426,18 @@ public: { return m_apply_invalid; } + bool is_helio_apply_result_invalid() const { + return m_helio_apply_invalid; + } void update_apply_result_invalid(bool invalid) { m_apply_invalid = invalid; } + void update_helio_apply_result_invalid(bool invalid) { + m_helio_apply_invalid = invalid; + } + //is slice result valid or not bool is_slice_result_valid() const { @@ -558,6 +575,7 @@ class PartPlateList : public ObjectBase PartPlate unprintable_plate; Pointfs m_shape; Pointfs m_exclude_areas; + Pointfs m_wrapping_exclude_areas; std::vector m_extruder_areas; std::vector m_extruder_heights; BoundingBoxf3 m_bounding_box; @@ -613,6 +631,7 @@ private: void calc_triangles(const ExPolygon &poly); void calc_vertex_for_icons(int index, GLModel &gl_model); void calc_exclude_triangles(const ExPolygon &poly); + void calc_triangles_from_polygon(const ExPolygon &poly, GLModel& render_model); void calc_gridlines(const ExPolygon &poly, const BoundingBox &pp_bbox); void calc_vertex_for_number(int index, bool one_number, GLModel &gl_model); private: @@ -626,9 +645,10 @@ private: std::vector m_unselected_plate_trans; unsigned int m_unselected_plate_mats_vbo{0}; bool m_update_unselected_plate_mats_vbo{true}; - + ExPolygon m_print_polygon; GLModel m_triangles; GLModel m_exclude_triangles; + GLModel m_wrapping_detection_triangles; GLModel m_gridlines; GLModel m_gridlines_bolder; GLModel m_del_icon; @@ -767,6 +787,7 @@ public: Vec3d get_current_plate_origin() { return compute_origin(m_current_plate, m_plate_cols); } Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); } Pointfs get_exclude_area() { return m_exclude_areas; } + Pointfs get_wrapping_exclude_area() const { return m_wrapping_exclude_areas; } std::set get_extruders(bool conside_custom_gcode = false) const; @@ -821,14 +842,14 @@ public: //reload objects for newly created plate int construct_objects_list_for_new_plate(int plate_index); - + std::vector get_plate_wrapping_detection_area(); /* arrangement related functions */ //compute the plate index int compute_plate_index(arrangement::ArrangePolygon& arrange_polygon); //preprocess an arrangement::ArrangePolygon, return true if it is in a locked plate bool preprocess_arrange_polygon(int obj_index, int instance_index, arrangement::ArrangePolygon& arrange_polygon, bool selected); bool preprocess_arrange_polygon_other_locked(int obj_index, int instance_index, arrangement::ArrangePolygon& arrange_polygon, bool selected); - bool preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates = 16, float inflation = 0); + bool preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, bool enable_wrapping_detect, int num_plates = 16, float inflation = 0); bool preprocess_nonprefered_areas(arrangement::ArrangePolygons& regions, int num_plates = 1, float inflation=0); void postprocess_bed_index_for_selected(arrangement::ArrangePolygon& arrange_polygon); @@ -851,6 +872,7 @@ public: void render_instance_background(bool force_default_color = false); void render_unselected_background(bool force_default_color); void render_grid(bool bottom); + void render_wrapping_detection_area(bool force_default_color); void render_exclude_area(bool force_default_color); void render_instance_exclude_area(bool force_default_color); void render_unselected_exclude_area(bool force_default_color); @@ -865,7 +887,14 @@ public: int select_plate_by_obj(int obj_index, int instance_index); void calc_bounding_boxes(); void select_plate_view(); - bool set_shapes(const Pointfs& shape, const Pointfs& exclude_areas, const std::vector& extruder_areas, const std::vector& extruder_heights, const std::string& custom_texture, float height_to_lid, float height_to_rod); + bool set_shapes(const Pointfs &shape, + const Pointfs &exclude_areas, + const Pointfs &wrapping_exclude_areas, + const std::vector &extruder_areas, + const std::vector &extruder_heights, + const std::string &custom_texture, + float height_to_lid, + float height_to_rod); void set_hover_id(int id); void reset_hover_id(); bool intersects(const BoundingBoxf3 &bb); diff --git a/src/slic3r/GUI/PartSkipDialog.cpp b/src/slic3r/GUI/PartSkipDialog.cpp index 698a7d8..9b16328 100644 --- a/src/slic3r/GUI/PartSkipDialog.cpp +++ b/src/slic3r/GUI/PartSkipDialog.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "Widgets/CheckBox.hpp" #include "Widgets/Label.hpp" @@ -27,6 +28,8 @@ #include "SkipPartCanvas.hpp" #include "MediaPlayCtrl.h" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { extern wxString hide_passwd(wxString url, std::vector const &passwords); @@ -388,7 +391,9 @@ std::string PartSkipDialog::create_tmp_path() buf << "/bamboo_task/"; buf << m_timestamp; if (m_obj) { - buf << m_obj->dev_id << "_"; + const auto& dev_id = m_obj->get_dev_id(); + buf << dev_id.substr(0, 3) << "_"; + buf << dev_id.substr(dev_id.length() - 3, 3) << "_"; buf << m_obj->job_id_ << "/"; } else { buf << 1 << "_" << 1 << "/"; @@ -461,7 +466,7 @@ void PartSkipDialog::fetchUrl(boost::weak_ptr wfs) return; } std::string dev_ver = obj->get_ota_version(); - std::string dev_id = obj->dev_id; + std::string dev_id = obj->get_dev_id(); // int remote_proto = obj->get_file_remote(); NetworkAgent *agent = wxGetApp().getAgent(); @@ -473,7 +478,7 @@ void PartSkipDialog::fetchUrl(boost::weak_ptr wfs) if (agent) { switch (url_state) { case URL_TCP: { - std::string devIP = obj->dev_ip; + std::string devIP = obj->get_dev_ip(); std::string accessCode = obj->get_access_code(); std::string tcp_url = "qidi:///local/" + devIP + "?port=6000&user=" + "qdtp" + "&passwd=" + accessCode; CallAfter([=] { @@ -489,7 +494,8 @@ void PartSkipDialog::fetchUrl(boost::weak_ptr wfs) } 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) { + agent->get_camera_url(obj->get_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; diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index 2cf3869..b132285 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -51,8 +51,6 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ { SetFont(wxGetApp().normal_font()); SetBackgroundColour(*wxWHITE); - // y3 modify Dialog - empty_flag = printer_name.empty(); Tab *tab = wxGetApp().get_tab(Preset::TYPE_PRINTER); m_presets = tab->get_presets(); @@ -83,12 +81,12 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ m_input_ctrl = new wxTextCtrl(this, wxID_ANY, input_name); m_input_ctrl->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3C"))); - m_valid_label = new wxStaticText(this, wxID_ANY, ""); - m_valid_label->SetForegroundColour(wxColor(255, 111, 0)); + // m_valid_label = new wxStaticText(this, wxID_ANY, ""); + // m_valid_label->SetForegroundColour(wxColor(255, 111, 0)); input_sizer_name->Add(label_top, 0, wxEXPAND | wxTOP, BORDER_W); input_sizer_name->Add(m_input_ctrl, 0, wxEXPAND , BORDER_W); - input_sizer_name->Add(m_valid_label, 0, wxEXPAND | wxBOTTOM, BORDER_W); + // input_sizer_name->Add(m_valid_label, 0, wxEXPAND | wxBOTTOM, BORDER_W); wxStaticText* pret_combo_text = new wxStaticText(this, wxID_ANY, _L("Choice your physical printer preset") + ":"); pret_combo_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#323A3C"))); @@ -180,7 +178,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ Bind(wxEVT_CLOSE_WINDOW, [this](auto& e) {this->EndModal(wxID_NO);}); - m_input_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent &) { update(); }); + //m_input_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent &) { update(); }); build_printhost_settings(m_optgroup); topSizer->Add(input_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W); @@ -279,7 +277,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr { wxTextCtrl* temp = dynamic_cast(printhost_field->getWindow()); if (temp) - temp->Bind(wxEVT_TEXT, ([printhost_field, temp](wxEvent& e) + temp->Bind(wxEVT_TEXT, ([printhost_field, temp, this](wxEvent& e) { #ifndef __WXGTK__ e.Skip(); @@ -308,7 +306,7 @@ void PhysicalPrinterDialog::update_printhost_buttons() } } -void PhysicalPrinterDialog::update_preset_input() { +bool PhysicalPrinterDialog::update_preset_input() { m_printer_name = into_u8(m_input_ctrl->GetValue()); m_valid_type = Valid; @@ -345,14 +343,7 @@ void PhysicalPrinterDialog::update_preset_input() { m_valid_type = NoValid; } - // y3 - if(empty_flag) - { - empty_flag = false; - m_valid_type = NoValid; - } - - else if(m_valid_type == Valid && m_printer_name.empty()) { + if(m_valid_type == Valid && m_printer_name.empty()) { info_line = _L("The name is not allowed to be empty."); m_valid_type = NoValid; } @@ -377,34 +368,39 @@ void PhysicalPrinterDialog::update_preset_input() { m_valid_type = NoValid; } - m_valid_label->SetLabel(info_line); - // m_input_area->Refresh(); - m_input_ctrl->Refresh(); - m_valid_label->Show(!info_line.IsEmpty()); + //m_valid_label->SetLabel(info_line); + //// m_input_area->Refresh(); + //m_input_ctrl->Refresh(); + //m_valid_label->Show(!info_line.IsEmpty()); + //if (m_valid_type == NoValid) { + // if (m_button_ok) + // { + // m_button_ok->Disable(); + // m_button_ok->SetBackgroundColor(wxColour(200, 200, 200)); + // } + //} + //else { + // if (m_button_ok) + // { + // m_button_ok->Enable(); + // StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + // std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + // m_button_ok->SetBackgroundColor(btn_bg_blue); + // } + // + //} if (m_valid_type == NoValid) { - if (m_button_ok) - { - m_button_ok->Disable(); - m_button_ok->SetBackgroundColor(wxColour(200, 200, 200)); - } - } - else { - if (m_button_ok) - { - m_button_ok->Enable(); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), - std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); - m_button_ok->SetBackgroundColor(btn_bg_blue); - } - + MessageDialog msg_wingow(nullptr, info_line, "", wxICON_WARNING | wxOK); + msg_wingow.ShowModal(); + return false; } + return true; } void PhysicalPrinterDialog::update(bool printer_change) { m_optgroup->reload_config(); - update_preset_input(); // update_printhost_buttons(); @@ -484,6 +480,10 @@ void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect) void PhysicalPrinterDialog::OnOK(wxMouseEvent& event) { + bool input_result = update_preset_input(); + if (!input_result) + return; + //y25 std::string now_host = boost::any_cast(m_optgroup->get_field("print_host")->get_value()); if (now_host.empty()) diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.hpp b/src/slic3r/GUI/PhysicalPrinterDialog.hpp index 8c41434..a6fc044 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.hpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.hpp @@ -77,7 +77,7 @@ public: void update(bool printer_change = false); void update_host_type(bool printer_change); - void update_preset_input(); + bool update_preset_input(); void update_printhost_buttons(); void update_printers(); diff --git a/src/slic3r/GUI/PhysicalPrinterDialog_1.cpp b/src/slic3r/GUI/PhysicalPrinterDialog_1.cpp index 0d6bff9..a24e51f 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog_1.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog_1.cpp @@ -77,6 +77,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent) : input_sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); m_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config); + check_host_key_valid(); build_printhost_settings(m_optgroup); auto button_sizer = new wxBoxSizer(wxHORIZONTAL); StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), @@ -533,6 +534,16 @@ void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect) Refresh(); } +void PhysicalPrinterDialog::check_host_key_valid() +{ + std::vector keys = {"print_host", "print_host_webui", "printhost_apikey", "printhost_cafile", "printhost_user", "printhost_password", "printhost_port"}; + for (auto &key : keys) { + auto it = m_config->option(key); + if (!it) m_config->set_key_value(key, new ConfigOptionString("")); + } + return; +} + void PhysicalPrinterDialog::OnOK(wxMouseEvent& event) { wxGetApp().get_tab(Preset::TYPE_PRINTER)->save_preset("", false, false, true, m_preset_name ); diff --git a/src/slic3r/GUI/PhysicalPrinterDialog_1.hpp b/src/slic3r/GUI/PhysicalPrinterDialog_1.hpp index 1c0473a..8aea146 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog_1.hpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog_1.hpp @@ -68,6 +68,7 @@ public: protected: void on_dpi_changed(const wxRect& suggested_rect) override; void on_sys_color_changed() override {}; + void check_host_key_valid(); }; } // namespace GUI diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9f5cf19..c532e44 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,7 @@ #include "../Utils/UndoRedo.hpp" #include "../Utils/PresetUpdater.hpp" #include "../Utils/Process.hpp" +#include "../Utils/HelioDragon.hpp" #include "RemovableDriveManager.hpp" #include "InstanceCheck.hpp" #include "NotificationManager.hpp" @@ -150,6 +152,10 @@ #include "StepMeshDialog.hpp" #include "FilamentMapDialog.hpp" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevManager.h" +#include "ImageMessageDialog.hpp" + #include "SyncBoxInfoDialog.hpp" using boost::optional; @@ -192,6 +198,7 @@ wxDEFINE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent); wxDEFINE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent); //QDS: change light/dark mode wxDEFINE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent); +wxDEFINE_EVENT(EVT_ENABLE_GCODE_OPTION_ITEM_CHANGED, SimpleEvent); //QDS: print wxDEFINE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent); @@ -202,6 +209,11 @@ wxDEFINE_EVENT(EVT_DEL_FILAMENT, SimpleEvent); wxDEFINE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent); wxDEFINE_EVENT(EVT_NOTICE_CHILDE_SIZE_CHANGED, SimpleEvent); wxDEFINE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent); + +wxDEFINE_EVENT(EVT_HELIO_PROCESSING_COMPLETED, HelioCompletionEvent); +wxDEFINE_EVENT(EVT_HELIO_PROCESSING_STARTED, SimpleEvent); +wxDEFINE_EVENT(EVT_HELIO_INPUT_CHAMBER_TEMP, SimpleEvent); + #define PRINTER_THUMBNAIL_SIZE (wxSize(FromDIP(48), FromDIP(48))) #define PRINTER_PANEL_SIZE (wxSize(FromDIP(96), FromDIP(96))) #define BTN_SYNC_SIZE (wxSize(FromDIP(96), FromDIP(98))) @@ -390,7 +402,7 @@ struct ExtruderGroup : StaticGroup void update_ams(); - void sync_ams(MachineObject const *obj, std::vector const &ams4, std::vector const &ams1); + void sync_ams(MachineObject const *obj, std::vector const &ams4, std::vector const &ams1); void Rescale() { @@ -764,14 +776,27 @@ static struct DynamicFilamentList : DynamicList if (!cb) { return; } - int n = cb->GetSelection(); + wxString old_selection = cb->GetStringSelection(); + int old_index = cb->GetSelection(); cb->Clear(); cb->Append(_L("Default")); for (auto i : items) { - cb->Append(i.first, i.second ? wxNullBitmap : * i.second); + cb->Append(i.first, i.second ? *i.second : wxNullBitmap); + } + + if (old_index >= 0 && (unsigned int) old_index < cb->GetCount()) { + cb->SetSelection(old_index); + return; + } + + int new_index = cb->FindString(old_selection); + if (old_index == cb->GetCount()) { + cb->SetSelection(old_index - 1); + } else if (new_index != wxNOT_FOUND) { + cb->SetSelection(new_index); + } else { + cb->SetSelection(0); } - if ((unsigned int)n < cb->GetCount()) - cb->SetSelection(n); } wxString get_value(int index) override { @@ -1103,16 +1128,17 @@ void ExtruderGroup::update_ams() sizer->Layout(); } -void ExtruderGroup::sync_ams(MachineObject const *obj, std::vector const &ams4, std::vector const &ams1) +void ExtruderGroup::sync_ams(MachineObject const *obj, std::vector const &ams4, std::vector const &ams1) { if (ams_4.empty() && ams4.empty() && ams_1.empty() && ams1.empty()) return; - auto sync = [obj](std::vector &infos, std::vector const &ams) -> bool { + auto sync = [obj](std::vector &infos, std::vector const &ams) -> bool { std::vector infos2; for (auto a : ams) { AMSinfo ams_info; - ams_info.parse_ams_info(const_cast(obj), a, obj->ams_calibrate_remain_flag, obj->is_support_ams_humidity); + //y71 + ams_info.parse_ams_info(const_cast(obj), a, false, obj->is_support_ams_humidity); infos2.push_back(ams_info); } if (infos == infos2) @@ -1172,7 +1198,7 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::NOT_CONNECTED, _L("Sync printer information")); return false; } - // if (obj->m_extder_data.extders.size() != 2) {//wxString(obj->get_preset_printer_model_name(machine_print_name)) + //if (obj->get_extder_system()->extders.size() != 2) {//wxString(obj->get_preset_printer_model_name(machine_print_name)) // plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::INCONSISTENT, _L("Sync printer information")); // return false; // } @@ -1215,17 +1241,17 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) assert(physical_extruder_map->values.size() == extruder_nums); extruder_map = physical_extruder_map->values; } - assert(obj->m_extder_data.extders.size() == extruder_nums); + assert(obj->GetExtderSystem()->GetTotalExtderCount() == extruder_nums); std::vector nozzle_diameters; nozzle_diameters.resize(extruder_nums); for (size_t index = 0; index < extruder_nums; ++index) { int extruder_id = extruder_map[index]; - nozzle_diameters[extruder_id] = obj->m_extder_data.extders[index].current_nozzle_diameter; + nozzle_diameters[extruder_id] = obj->GetExtderSystem()->GetNozzleDiameter(index); NozzleVolumeType target_type = NozzleVolumeType::nvtStandard; auto printer_tab = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_PRINTER)); if (obj->is_nozzle_flow_type_supported()) { - if (obj->m_extder_data.extders[index].current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { + if (obj->GetExtderSystem()->GetNozzleFlowType(index) == NozzleFlowType::NONE_FLOWTYPE) { MessageDialog dlg(this->plater, _L("There are unset nozzle types. Please set the nozzle types of all extruders before synchronizing."), _L("Sync extruder infomation"), wxICON_WARNING | wxOK); dlg.ShowModal(); @@ -1233,30 +1259,27 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) } // hack code, only use standard flow for 0.2 if (std::fabs(nozzle_diameters[extruder_id] - 0.2) > EPSILON) - target_type = NozzleVolumeType(obj->m_extder_data.extders[extruder_id].current_nozzle_flow_type - 1); + target_type = NozzleVolumeType(obj->GetExtderSystem()->GetNozzleFlowType(extruder_id) - 1); } printer_tab->set_extruder_volume_type(index, target_type); } int deputy_4 = 0, main_4 = 0, deputy_1 = 0, main_1 = 0; - for (auto ams : obj->amsList) { + for (auto ams : obj->GetFilaSystem()->GetAmsList()) { // Main (first) extruder at right - if (ams.second->nozzle == 0) { - if (ams.second->type == 4) // N3S + if (ams.second->GetExtruderId() == 0) { + if (ams.second->GetAmsType() == DevAms::N3S) // N3S ++main_1; else ++main_4; - } else if (ams.second->nozzle == 1) { - if (ams.second->type == 4) // N3S + } else if (ams.second->GetExtruderId() == 1) { + if (ams.second->GetAmsType() == DevAms::N3S) // N3S ++deputy_1; else ++deputy_4; } } - only_external_material = false; - if (obj->amsList.size() == 0) { - only_external_material = true; - } + only_external_material = !obj->GetFilaSystem()->HasAms(); int main_index = obj->is_main_extruder_on_left() ? 0 : 1; int deputy_index = obj->is_main_extruder_on_left() ? 1 : 0; @@ -1338,8 +1361,8 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) int nozzle_volue_type{0}; int ams_4{0}; int ams_1{0}; - std::vector ams_v4; - std::vector ams_v1; + std::vector ams_v4; + std::vector ams_v1; bool operator==(const ExtruderInfo &other) const { @@ -1359,7 +1382,7 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) // 2. update extruder status int extruder_nums = preset_bundle->get_printer_extruder_count(); - //if (extruder_nums != obj->m_extder_data.extders.size()) + //if (extruder_nums != obj->GetExtderSystem()->GetTotalExtderCount()) // return; std::vector extruder_infos(extruder_nums); @@ -1396,22 +1419,25 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) } //y59 - //std::vector machine_extruder_infos(obj->m_extder_data.extders.size()); - //for (const Extder &extruder : obj->m_extder_data.extders) { - // machine_extruder_infos[extruder.id].nozzle_volue_type = int(extruder.current_nozzle_flow_type) - 1; - // machine_extruder_infos[extruder.id].diameter = extruder.current_nozzle_diameter; - //} - //for (auto &item : obj->amsList) { - // if (item.second->nozzle >= machine_extruder_infos.size()) + // std::vector machine_extruder_infos(obj->GetExtderSystem()->GetTotalExtderCount()); + + // const auto& extruders = obj->GetExtderSystem()->GetExtruders(); + // for (const DevExtder &extruder : extruders) { + // machine_extruder_infos[extruder.GetExtId()].nozzle_volue_type = int(extruder.GetNozzleFlowType()) - 1; + // machine_extruder_infos[extruder.GetExtId()].diameter = extruder.GetNozzleDiameter(); + // } + // for (auto &item : obj->GetFilaSystem()->GetAmsList()) { + // if (item.second->GetExtruderId() >= machine_extruder_infos.size()) // continue; - // if (item.second->type == 4) { // N3S - // machine_extruder_infos[item.second->nozzle].ams_1++; - // machine_extruder_infos[item.second->nozzle].ams_v1.push_back(item.second); - // } else { - // machine_extruder_infos[item.second->nozzle].ams_4++; - // machine_extruder_infos[item.second->nozzle].ams_v4.push_back(item.second); - // } + // if (item.second->GetAmsType() == DevAms::N3S) + // { // N3S + // machine_extruder_infos[item.second->GetExtruderId()].ams_1++; + // machine_extruder_infos[item.second->GetExtruderId()].ams_v1.push_back(item.second); + // } else { + // machine_extruder_infos[item.second->GetExtruderId()].ams_4++; + // machine_extruder_infos[item.second->GetExtruderId()].ams_v4.push_back(item.second); + // } //} //std::reverse(machine_extruder_infos.begin(), machine_extruder_infos.end()); @@ -2454,8 +2480,8 @@ void Sidebar::update_presets(Preset::Type preset_type) //wxGetApp().mainframe->update_calibration_button_status(); - //B y58 - wxGetApp().mainframe->show_calibration_button(false); + //B y71 + wxGetApp().mainframe->show_calibration_button(false, true); if (auto printer_structure_opt = printer_preset.config.option>("printer_structure")) { wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3); @@ -3082,7 +3108,7 @@ std::map Sidebar::build_filament_ams_list(MachineObject std::map filament_ams_list; if (!obj) return filament_ams_list; - auto build_tray_config = [](AmsTray const &tray, std::string const &name, std::string ams_id, std::string slot_id) { + auto build_tray_config = [](DevAmsTray const &tray, std::string const &name, std::string ams_id, std::string slot_id) { BOOST_LOG_TRIVIAL(info) << boost::format("build_filament_ams_list: name %1% setting_id %2% type %3% color %4%") % name % tray.setting_id % tray.type % tray.color; DynamicPrintConfig tray_config; @@ -3127,11 +3153,11 @@ std::map Sidebar::build_filament_ams_list(MachineObject return std::string(); }; - auto list = obj->amsList; + auto list = obj->GetFilaSystem()->GetAmsList(); for (auto ams : list) { int ams_id = std::stoi(ams.first); - int extruder = ams.second->nozzle ? 0 : 0x10000; // Main (first) extruder at right - for (auto tray : ams.second->trayList) { + int extruder = ams.second->GetExtruderId() ? 0 : 0x10000; // Main (first) extruder at right + for (auto tray : ams.second->GetTrays()) { int slot_id = std::stoi(tray.first); filament_ams_list.emplace(extruder + (ams_id * 4 + slot_id), build_tray_config(*tray.second, get_ams_name(ams_id, slot_id), std::to_string(ams_id), std::to_string(slot_id))); @@ -3208,8 +3234,10 @@ void Sidebar::load_ams_list(std::string const &device, MachineObject* obj) device_change = true; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1% items") % filament_ams_list.size(); - if (wxGetApp().preset_bundle->filament_ams_list == filament_ams_list) + if (wxGetApp().preset_bundle->filament_ams_list == filament_ams_list && !device_change) + { return; + } wxGetApp().preset_bundle->filament_ams_list = filament_ams_list; for (auto c : p->combos_filament){ @@ -3228,7 +3256,7 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) // Force load ams list auto obj = wxGetApp().getDeviceManager()->get_selected_machine(); if (obj) - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); auto & list = wxGetApp().preset_bundle->filament_ams_list; if (list.empty() || obj == nullptr || !obj->is_online()) { @@ -3680,11 +3708,11 @@ void Sidebar::sync_box_list() } } } + Layout(); wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); dynamic_filament_list.update(); - Layout(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "begin pop_finsish_sync_ams_dialog"; pop_finsish_sync_ams_dialog(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish pop_finsish_sync_ams_dialog"; @@ -4273,6 +4301,7 @@ public: ProjectDirtyStateManager dirty_state; BackgroundSlicingProcess background_process; + HelioBackgroundProcess helio_background_process; bool suppressed_backround_processing_update { false }; // UIThreadWorker can be used as a replacement for BoostThreadWorker if // no additional worker threads are desired (useful for debugging or profiling) @@ -4611,6 +4640,8 @@ public: void on_export_finished(wxCommandEvent&); void on_slicing_began(); + int update_helio_background_process(std::string& printer_id, std::string& material_id); + void clear_warnings(); void add_warning(const Slic3r::PrintStateBase::Warning &warning, size_t oid); // Update notification manager with the current state of warnings produced by the background process (slicing). @@ -4653,6 +4684,10 @@ public: void on_action_open_project(SimpleEvent&); void on_action_slice_plate(SimpleEvent&); void on_action_slice_all(SimpleEvent&); + void on_helio_processing_complete(HelioCompletionEvent &); + void on_helio_processing_start(SimpleEvent &); + void on_helio_input_dlg(SimpleEvent &); + void on_helio_process(); void on_action_publish(wxCommandEvent &evt); void on_action_print_plate(SimpleEvent&); void on_action_print_all(SimpleEvent&); @@ -4681,7 +4716,15 @@ public: // fills the m_bed.m_grid_lines and sets m_bed.m_origin. // Sets m_bed.m_polygon to limit the object placement. //QDS: add bed exclude area - void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false); + void set_bed_shape(const Pointfs &shape, + const Pointfs &exclude_areas, + const Pointfs &wrapping_exclude_areas, + const double printable_height, + std::vector extruder_areas, + std::vector extruder_heights, + const std::string &custom_texture, + const std::string &custom_model, + bool force_as_custom = false); bool can_delete() const; bool can_delete_all() const; @@ -4817,7 +4860,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , main_frame(main_frame) //QDS: add bed_exclude_area , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ - "printable_area", "bed_exclude_area", "extruder_printable_area", "bed_custom_texture", "bed_custom_model", "print_sequence", + "printable_area", "bed_exclude_area", "wrapping_exclude_area", "extruder_printable_area", "bed_custom_texture", "bed_custom_model", "print_sequence", "extruder_clearance_dist_to_rod", "extruder_clearance_max_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "nozzle_height", "skirt_loops", "skirt_distance", @@ -4886,11 +4929,17 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_INSTALL_PLUGIN_HINT, &priv::show_install_plugin_hint, this); this->q->Bind(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, &priv::update_plugin_when_launch, this); this->q->Bind(EVT_PREVIEW_ONLY_MODE_HINT, &priv::show_preview_only_hint, this); + this->q->Bind(EVT_ENABLE_GCODE_OPTION_ITEM_CHANGED, [this](SimpleEvent &) { + if (preview) { + preview->get_canvas3d()->get_gcode_viewer().record_record_gcodeviewer_option_item(); + }}); this->q->Bind(EVT_GLCANVAS_COLOR_MODE_CHANGED, &priv::on_change_color_mode, this); this->q->Bind(wxEVT_SYS_COLOUR_CHANGED, &priv::on_apple_change_color_mode, this); this->q->Bind(EVT_CREATE_FILAMENT, &priv::on_create_filament, this); this->q->Bind(EVT_MODIFY_FILAMENT, &priv::on_modify_filament, this); +#ifndef __linux__ this->q->Bind(EVT_NOTICE_CHILDE_SIZE_CHANGED, &Sidebar::on_size, sidebar); +#endif this->q->Bind(EVT_NOTICE_FULL_SCREEN_CHANGED, &Sidebar::on_full_screen, sidebar); this->q->Bind(EVT_ADD_FILAMENT, &priv::on_add_filament, this); this->q->Bind(EVT_DEL_FILAMENT, &priv::on_delete_filament, this); @@ -4931,7 +4980,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) .TopDockable(false) .BottomDockable(false) .Floatable(wxGetApp().app_config->get_bool("enable_sidebar_floatable")) - .Resizable(wxGetApp().app_config->get_bool("enable_sidebar_resizable")) + .Resizable(true) .MinSize(wxSize(15 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit())) .BestSize(wxSize(42 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); @@ -4950,8 +4999,24 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) const auto cfg = wxGetApp().app_config; wxString layout = wxString::FromUTF8(cfg->get("window_layout")); if (!layout.empty()) { - m_aui_mgr.LoadPerspective(layout, false); - sidebar_layout.is_collapsed = !sidebar.IsShown(); + bool is_new_window_layout = true; + std::vector parts; + boost::split(parts, layout, boost::is_any_of(";")); + for (const std::string &part : parts) { + std::vector keyValues; + boost::split(keyValues, part, boost::is_any_of("=")); + if (keyValues.size() == 2 && keyValues[0] == "minh") { + auto minh_value = std::stof(keyValues[1]); + if (minh_value < 0) { + is_new_window_layout = false; + } + break; + } + } + if (is_new_window_layout) { + m_aui_mgr.LoadPerspective(layout, false); + sidebar_layout.is_collapsed = !sidebar.IsShown(); + } } // Keep tracking the current sidebar size, by storing it using `best_size`, which will be stored @@ -5113,7 +5178,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) preview->get_canvas3d()->set_as_dirty(); }); if (wxGetApp().is_editor()) { - preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent &) { select_next_view_3D(); }); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); }); preview->get_wxglcanvas()->Bind(EVT_CUSTOMEVT_TICKSCHANGED, [this](wxCommandEvent& event) { Type tick_event_type = (Type)event.GetInt(); @@ -5188,6 +5253,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) q->Bind(EVT_OPEN_PLATESETTINGSDIALOG, [q](wxCommandEvent& evt) { q->open_platesettings_dialog(evt);}); q->Bind(EVT_OPEN_FILAMENT_MAP_SETTINGS_DIALOG, [q](wxCommandEvent &evt) { q->open_filament_map_setting_dialog(evt); }); //q->Bind(EVT_GLVIEWTOOLBAR_ASSEMBLE, [q](SimpleEvent&) { q->select_view_3D("Assemble"); }); + + q->Bind(EVT_HELIO_PROCESSING_COMPLETED, &priv::on_helio_processing_complete, this); + q->Bind(EVT_HELIO_PROCESSING_STARTED, &priv::on_helio_processing_start, this); + q->Bind(EVT_HELIO_INPUT_CHAMBER_TEMP, &priv::on_helio_input_dlg, this); } // Drop target: @@ -5284,7 +5353,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) std::string last_backup = last; std::string originfile; if (Slic3r::has_restore_data(last_backup, originfile)) { - auto result = MessageDialog(this->q, _L("Previous unsaved project detected, do you want to restore it?"), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Restore"), wxYES_NO | wxYES_DEFAULT | wxCENTRE).ShowModal(); + BOOST_LOG_TRIVIAL(info) << "test101: Restoring project from: " << PathSanitizer::sanitize(last_backup); + auto log_string = _L("It seems that you have projects that were not closed properly. Would you like to restore your last unsaved project?\nIf you have a currently opened project and click \"Restore\", the current project will be closed."); + MessageDialog dlg(this->q, log_string, wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Restore"), wxYES_NO | wxYES_DEFAULT | wxCENTRE); + dlg.SetButtonLabel(wxID_YES, _L("Restore")); + dlg.SetButtonLabel(wxID_NO, _L("Cancel")); + auto result = dlg.ShowModal(); if (result == wxID_YES) { this->q->load_project(from_path(last_backup), from_path(originfile)); Slic3r::backup_soon(); @@ -5296,9 +5370,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) boost::filesystem::remove_all(last); } catch (...) {} - int skip_confirm = e.GetInt(); - this->q->new_project(skip_confirm, true); - }); + if (this->q->get_project_filename().IsEmpty() && this->q->is_empty_project()) { + int skip_confirm = e.GetInt(); + this->q->new_project(skip_confirm, true); + } + }); //wxPostEvent(this->q, wxCommandEvent{EVT_RESTORE_PROJECT}); } @@ -5435,6 +5511,13 @@ int Plater::get_right_icon_offset_bed() return 0; } +bool Plater::get_enable_wrapping_detection() +{ + const DynamicPrintConfig & print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const ConfigOptionBool * wrapping_detection = print_config.option("enable_wrapping_detection"); + return (wrapping_detection != nullptr) && wrapping_detection->value; +} + wxColour Plater::get_next_color_for_filament() { static int curr_color_filamenet = 0; @@ -6074,6 +6157,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ this->preview->update_gcode_result(partplate_list.get_current_slice_result()); release_PlateData_list(plate_data); sidebar->obj_list()->reload_all_plates(); + q->suppress_background_process(true); } else { partplate_list.reload_all_objects(); } @@ -6821,6 +6905,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ is_mw = "true"; } } + q->schedule_background_process(true); return obj_idxs; } @@ -6980,6 +7065,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& mode // QDS void Plater::priv::load_auxiliary_files() { + wxLogNull suppress_log; std::string auxiliary_path = encode_path(q->model().get_auxiliary_file_temp_path().c_str()); //wxGetApp().mainframe->m_project->Reload(auxiliary_path); } @@ -7931,7 +8017,8 @@ unsigned int Plater::priv::update_restart_background_process(bool force_update_s switch_print = false; } // bitmask of UpdateBackgroundProcessReturnState - unsigned int state = this->update_background_process(false, false, switch_print); + unsigned int state = update_background_process(false, false, switch_print); + if (force_update_scene || (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0) view3D->reload_scene(false); @@ -9049,8 +9136,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) 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) { - if (!is_approx(extruder.current_nozzle_diameter, float(preset_nozzle_diameter))) { + + const auto& extruders = obj->GetExtderSystem()->GetExtruders(); + for (const DevExtder &extruder : extruders) { + if (!is_approx(extruder.GetNozzleDiameter(), float(preset_nozzle_diameter))) { same_nozzle_diameter = false; } } @@ -9547,6 +9636,9 @@ void Plater::priv::on_action_open_project(SimpleEvent&) void Plater::priv::on_action_slice_plate(SimpleEvent&) { if (q != nullptr) { + + helio_background_process.reset(); + if (!q->check_ams_status(false)) return; @@ -9565,10 +9657,209 @@ void Plater::priv::on_action_slice_plate(SimpleEvent&) } } + +int Plater::priv::update_helio_background_process(std::string& printer_id, std::string& material_id) +{ + notification_manager->close_notification_of_type(NotificationType::HelioSlicingError); + PresetBundle * preset_bundle = wxGetApp().preset_bundle; + std::string preset_name = preset_bundle->printers.get_edited_preset().get_printer_name(preset_bundle); + std::vector preset_name_array = wxGetApp().split_str(preset_name, "QIDI Tech "); + std::string preset_pure_name = preset_name_array.size() >= 2 ? preset_name_array[1] : ""; + + /*invalid printer preset*/ + if (preset_pure_name.empty()) { + GUI::MessageDialog msgdialog(nullptr, _L("Invalid printer preset. Unable to slice with Helio."), "", wxICON_WARNING | wxOK); + msgdialog.ShowModal(); + return -1; + } + + bool helio_support = false; + for (HelioQuery::SupportedData pdata : HelioQuery::global_supported_printers) { + if (!pdata.native_name.empty()) { + std::string native_name = pdata.native_name; + boost::algorithm::to_lower(native_name); + boost::algorithm::to_lower(preset_pure_name); + if (native_name.find(preset_pure_name) != std::string::npos) { + helio_support = true; + printer_id = pdata.id; + break; + } + } + } + + /*unsupported helio printers*/ + if (!helio_support) { + GUI::MessageDialog msgdialog(nullptr, _L("The current printer preset cannot be sliced using Helio."), "", wxICON_WARNING | wxOK); + msgdialog.ShowModal(); + return -1; + } + + /*check total number of materials*/ + auto extruders = q->get_partplate_list().get_curr_plate()->get_extruders(); + if (extruders.size() <= 0) { + return -1; + } + + /*Check the materials supported by helio*/ + auto preset_filaments = q->get_current_filaments_preset_names(); + if (extruders.front() > preset_filaments.size()) { + return -1; + } + + + if (extruders.size() > 1) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": The number of consumables used is > 1"; + GUI::MessageDialog msgdialog(nullptr, _L("Helio does not support using a number of materials greater than 1."), "", wxICON_WARNING | wxOK); + msgdialog.ShowModal(); + return -1; + } + + std::string used_filament = preset_filaments[extruders.front() - 1]; + bool is_supported_by_helio = false; + + for (HelioQuery::SupportedData pdata : HelioQuery::global_supported_materials) { + if (!pdata.native_name.empty()) { + std::string native_name = pdata.native_name; + boost::algorithm::to_lower(native_name); + boost::algorithm::to_lower(used_filament); + if (used_filament.find(native_name) != std::string::npos) { + is_supported_by_helio = true; + material_id = pdata.id; + break; + } + } + } + + if (!is_supported_by_helio) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("Helio does not support materials %1%") % used_filament; + GUI::MessageDialog msgdialog(nullptr, wxString::Format(_L("Helio does not support materials %s"), used_filament), "", wxICON_WARNING | wxOK); + msgdialog.ShowModal(); + return -1; + } + + + //partplate_list.get_curr_plate()->update_helio_apply_result_invalid(false); + notification_manager->close_notification_of_type(NotificationType::HelioSlicingError); + return 0; +} + +void Plater::priv::on_helio_processing_complete(HelioCompletionEvent &a) +{ + if (a.is_successful) { + this->reset_gcode_toolpaths(); + + int deleted = boost::nowide::remove(a.tmp_path.c_str()); + + if (deleted != 0) { BOOST_LOG_TRIVIAL(error) << boost::format("Failed to delete file %1%") % a.tmp_path; } + + std::string copied; + copy_file(a.simulated_path, a.tmp_path, copied); + + BOOST_LOG_TRIVIAL(debug) << boost::format("Failed to delete file %1%") % copied; + + GCodeProcessorResult *res1 = partplate_list.get_curr_plate()->get_gcode_result(); + res1->lines_ends = helio_background_process.m_gcode_result->lines_ends; + res1->moves = helio_background_process.m_gcode_result->moves; + + GCodeProcessorResult *res2 = background_process.get_current_gcode_result(); + res2->lines_ends = helio_background_process.m_gcode_result->lines_ends; + res2->moves = helio_background_process.m_gcode_result->moves; + + this->update(); + } else { + notification_manager->push_helio_error_notification(a.error_message); + } +} + +void Plater::priv::on_helio_processing_start(SimpleEvent &a) +{ + notification_manager->close_notification_of_type(GUI::NotificationType::SignDetected); + notification_manager->close_notification_of_type(GUI::NotificationType::ExportFinished); + notification_manager->set_slicing_progress_began(true); + notification_manager->update_slicing_notif_dailytips(true); +} + +//QDS: GUI refactor: slice with helio + +void Plater::priv::on_helio_process() +{ + std::string printer_id; + std::string material_id; + if (update_helio_background_process(printer_id, material_id) > -1) { + HelioInputDialog dlg; + if (dlg.ShowModal() == wxID_OK) + { + float chamber_temp = dlg.get_input_data(); + + if (chamber_temp >= -1) { + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":helio process called"; + //on_action_slice_plate(a); + + if (!(partplate_list.get_curr_plate()->empty())) { + + std:; string helio_api_url = Slic3r::HelioQuery::get_helio_api_url(); + std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + const Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config(); + auto g_result = background_process.get_current_gcode_result(); + + //set user input + HelioBackgroundProcess::SimulationInput data; + data.chamber_temp = chamber_temp; + helio_background_process.set_simulation_input_data(data); + helio_background_process.init(helio_api_key, helio_api_url, printer_id, material_id, g_result, preview, + [this]() {}); + + helio_background_process.helio_thread_start(background_process.m_mutex, background_process.m_condition, background_process.m_state, notification_manager); + } + } + } + } +} + +void Plater::priv::on_helio_input_dlg(SimpleEvent& a) +{ + std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + + if (helio_api_key.empty()) { + auto dlg = MessageDialog(nullptr, _L("No valid Helio-PAT detected. Helio simulation & optimization cannot proceed. \nPlease request a new Helio-PAT."), + _L("Execution Blocked"), wxYES_NO | wxICON_WARNING | wxCENTRE); + dlg.SetButtonLabel(wxID_YES, _L("Regenerate PAT")); + auto result = dlg.ShowModal(); + if (result == wxID_YES) { + wxGetApp().request_helio_pat([this](std::string pat) { + wxTheApp->CallAfter([=]() { + if (pat == "not_enough") { + HelioPatNotEnoughDialog dlg; + dlg.ShowModal(); + } + else if (pat == "error") { + MessageDialog dlg(nullptr, _L("Failed to obtain Helio PAT, Click Refresh to obtain it again."), wxString("Helio Additive"), wxYES | wxICON_WARNING); + dlg.ShowModal(); + } + else { + Slic3r::HelioQuery::set_helio_pat(pat); + on_helio_process(); + } + }); + }); + } + else { + return; + } + } + else { + if (!Slic3r::HelioQuery::get_helio_api_url().empty() && !Slic3r::HelioQuery::get_helio_pat().empty()) { + wxGetApp().request_helio_supported_data(); + } + on_helio_process(); + } +} + //QDS: GUI refactor: slice all void Plater::priv::on_action_slice_all(SimpleEvent&) { if (q != nullptr) { + helio_background_process.reset(); BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received slice project event\n" ; //QDS update extruder params and speed table before slicing const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config(); @@ -10015,7 +10306,7 @@ void Plater::priv::update_plugin_when_launch(wxCommandEvent &event) std::string data_dir_str = data_dir(); boost::filesystem::path data_dir_path(data_dir_str); auto cache_folder = data_dir_path / "ota"; - std::string changelog_file = cache_folder.string() + "/network_plugins.json"; + std::string changelog_file = cache_folder.string() + "/plugins/network_plugins.json"; UpdatePluginDialog dlg(wxGetApp().mainframe); dlg.update_info(changelog_file); @@ -10426,10 +10717,25 @@ void Plater::priv::init_notification_manager() notification_manager->init(); auto cancel_callback = [this]() { + bool res1; + bool res2; + + if (!this->helio_background_process.is_running()) + res1 = false; + + else { + this->helio_background_process.stop(); + res1 = true; + } + if (this->background_process.idle()) - return false; - this->background_process.stop(); - return true; + res2 = false; + else { + this->background_process.stop(); + res2 = true; + } + + return res1 || res2; }; notification_manager->init_slicing_progress_notification(cancel_callback); notification_manager->set_fff(printer_technology == ptFFF); @@ -10509,6 +10815,8 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio } update(); + q->show_wrapping_detect_dialog_if_necessary(); + // QDS:Model reset by plate center PartPlate *cur_plate = cur_plate_list.get_curr_plate(); Vec3d cur_plate_pos = cur_plate->get_center_origin(); @@ -10703,10 +11011,10 @@ bool Plater::priv::check_ams_status_impl(bool is_slice_all) 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); - if (obj->m_extder_data.extders.size() == 2 && nozzle_volumes_values.size() == 2) { - NozzleVolumeType right_nozzle_type = NozzleVolumeType(obj->m_extder_data.extders[0].current_nozzle_flow_type - 1); - NozzleVolumeType left_nozzle_type = NozzleVolumeType(obj->m_extder_data.extders[1].current_nozzle_flow_type - 1); + assert(obj->GetExtderSystem()->GetTotalExtderCount() == 2 && nozzle_volumes_values.size() == 2); + if (obj->GetExtderSystem()->GetTotalExtderCount() == 2 && nozzle_volumes_values.size() == 2) { + NozzleVolumeType right_nozzle_type = NozzleVolumeType(obj->GetExtderSystem()->GetNozzleFlowType(0) - 1); + NozzleVolumeType left_nozzle_type = NozzleVolumeType(obj->GetExtderSystem()->GetNozzleFlowType(1) - 1); NozzleVolumeType preset_left_type = NozzleVolumeType(nozzle_volumes_values[0]); NozzleVolumeType preset_right_type = NozzleVolumeType(nozzle_volumes_values[1]); is_same_as_printer = (left_nozzle_type == preset_left_type && right_nozzle_type == preset_right_type); @@ -10715,15 +11023,15 @@ bool Plater::priv::check_ams_status_impl(bool is_slice_all) std::vector> ams_count_info; ams_count_info.resize(2); int deputy_4 = 0, main_4 = 0, deputy_1 = 0, main_1 = 0; - for (auto ams : obj->amsList) { + for (auto ams : obj->GetFilaSystem()->GetAmsList()) { // Main (first) extruder at right - if (ams.second->nozzle == 0) { - if (ams.second->type == 4) // N3S + if (ams.second->GetExtruderId() == 0) { + if (ams.second->GetAmsType() == DevAms::N3S) // N3S ++main_1; else ++main_4; - } else if (ams.second->nozzle == 1) { - if (ams.second->type == 4) // N3S + } else if (ams.second->GetExtruderId() == 1) { + if (ams.second->GetAmsType() == DevAms::N3S) // N3S ++deputy_1; else ++deputy_4; @@ -11031,7 +11339,15 @@ bool Plater::priv::show_publish_dlg(bool show) } //QDS: add bed exclude area -void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) +void Plater::priv::set_bed_shape(const Pointfs &shape, + const Pointfs &exclude_areas, + const Pointfs &wrapping_exclude_areas, + const double printable_height, + std::vector extruder_areas, + std::vector extruder_heights, + const std::string &custom_texture, + const std::string &custom_model, + bool force_as_custom) { //QDS: add shape position Vec2d shape_position = partplate_list.get_current_shape_position(); @@ -11043,7 +11359,9 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar double height_to_rod = config->opt_float("extruder_clearance_height_to_rod"); Pointfs prev_exclude_areas = partplate_list.get_exclude_area(); - new_shape |= (height_to_lid != prev_height_lid) || (height_to_rod != prev_height_rod) || (prev_exclude_areas != exclude_areas); + Pointfs prev_wrapping_exclude_areas = partplate_list.get_wrapping_exclude_area(); + new_shape |= (height_to_lid != prev_height_lid) || (height_to_rod != prev_height_rod) || (prev_exclude_areas != exclude_areas) + || (prev_wrapping_exclude_areas != wrapping_exclude_areas); if (!new_shape && partplate_list.get_logo_texture_filename() != custom_texture) { partplate_list.update_logo_texture_filename(custom_texture); } @@ -11059,7 +11377,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar //Pointfs& exclude_areas = config->option("bed_exclude_area")->values; partplate_list.reset_size(max.x() - min.x() - Bed3D::Axes::DefaultTipRadius, max.y() - min.y() - Bed3D::Axes::DefaultTipRadius, z); - partplate_list.set_shapes(shape, exclude_areas, extruder_areas, extruder_heights, custom_texture, height_to_lid, height_to_rod); + partplate_list.set_shapes(shape, exclude_areas, wrapping_exclude_areas, extruder_areas, extruder_heights, custom_texture, height_to_lid, height_to_rod); Vec2d new_shape_position = partplate_list.get_current_shape_position(); if (shape_position != new_shape_position) @@ -11834,6 +12152,9 @@ void Plater::reset_flags_when_new_or_close_project() int Plater::new_project(bool skip_confirm, bool silent, const wxString &project_name) { + model().calib_pa_pattern.reset(nullptr); + model().plates_custom_gcodes.clear(); + bool transfer_preset_changes = false; // QDS: save confirm auto check = [this,&transfer_preset_changes](bool yes_or_no) { @@ -11907,7 +12228,7 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) return false; MachineObject* obj = dev->get_selected_machine(); - if (!obj || !obj->is_info_ready() || obj->m_extder_data.extders.size() <= 0) { + if (!obj || !obj->is_info_ready() || obj->GetExtderSystem()->GetTotalExtderCount() <= 0) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " obj may empty"; return false; } @@ -11923,7 +12244,7 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) if (auto opt = printer_preset.config.option("nozzle_diameter"); opt) { preset_nozzle_diameter = static_cast(opt)->values[0]; } - float machine_nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + float machine_nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); std::string printer_type = obj->get_show_printer_type(); @@ -11942,10 +12263,10 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) if (printer_preset.get_current_printer_type(preset_bundle) != printer_type || !is_approx((float)(preset_nozzle_diameter), machine_nozzle_diameter)) { wxString tips; if (printer_preset.get_current_printer_type(preset_bundle) != printer_type) - tips = from_u8((boost::format(_u8L("The currently connected printer '%s', is a %s model.\nTo use this printer for printing, please switch the printer model of project file to %s.")) % obj->dev_name % printer_model % printer_model).str()); + tips = from_u8((boost::format(_u8L("The currently connected printer '%s', is a %s model.\nTo use this printer for printing, please switch the printer model of project file to %s.")) % obj->get_dev_name() % printer_model % printer_model).str()); else if (!is_approx((float) (preset_nozzle_diameter), machine_nozzle_diameter)) tips = from_u8((boost::format(_u8L("The currently connected printer '%s', is a %s model but not consistent with preset in project file.\n" - "To use this printer for printing, please switch the preset first.")) % obj->dev_name % printer_model).str()); + "To use this printer for printing, please switch the preset first.")) % obj->get_dev_name() % printer_model).str()); std::mapoption_map = { {wxID_YES,_L("Switch now")}, @@ -11983,7 +12304,11 @@ 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: " << PathSanitizer::sanitize(filename2.mb_str()) << "and originfile is: " << PathSanitizer::sanitize(originfile.mb_str()); + model().calib_pa_pattern.reset(nullptr); + model().plates_custom_gcodes.clear(); + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "filename is: " << PathSanitizer::sanitize(filename2.ToUTF8().data()) + << "and originfile is: " << PathSanitizer::sanitize(originfile.ToUTF8().data()); 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"), @@ -12107,6 +12432,9 @@ int Plater::load_project(wxString const &filename2, sidebar().pop_sync_nozzle_and_ams_dialog(); } } + statistics_burial_data(filename.utf8_string()); + + show_wrapping_detect_dialog_if_necessary(); return wx_dlg_id; } @@ -12376,9 +12704,10 @@ void Plater::import_model_id(wxString download_info) #endif if (download_ok) { - BOOST_LOG_TRIVIAL(trace) << "import_model_id: target_path = " << target_path.string(); + BOOST_LOG_TRIVIAL(trace) << "import_model_id: target_path = " << PathSanitizer::sanitize(target_path); /* load project */ auto result = this->load_project(target_path.wstring()); + statistics_burial_data_form_mw(); if (result == (int)wxID_CANCEL) { return; } @@ -12752,6 +13081,8 @@ void Plater::_calib_pa_pattern(const Calib_Params ¶ms) print_config.set_key_value(SuggestedConfigCalibPAPattern().brim_pair.first, new ConfigOptionEnum(SuggestedConfigCalibPAPattern().brim_pair.second)); + print_config.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); + wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); wxGetApp().get_tab(Preset::TYPE_PRINT)->reload_config(); @@ -12985,6 +13316,7 @@ void Plater::_calib_pa_tower(const Calib_Params ¶ms) const float nozzle_diameter = printer_config->option("nozzle_diameter")->get_at(0); + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionInts{1}); //print_config->set_key_value("default_jerk", new ConfigOptionFloat(1.0f)); //print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(1.0f)); @@ -13168,6 +13500,7 @@ void Plater::calib_flowrate(int pass,double input_value) //print_config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); //print_config->set_key_value("initial_layer_print_height", new ConfigOptionFloat(first_layer_height)); //print_config->set_key_value("reduce_crossing_wall", new ConfigOptionBool(true)); + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); // filament_config->set_key_value("filament_max_volumetric_speed", new ConfigOptionFloats{ 9. }); //w29 //print_config->set_key_value("resonance_avoidance", new ConfigOptionBool(false)); @@ -13233,6 +13566,9 @@ void Plater::calib_temp(const Calib_Params ¶ms) model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(5.0)); model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); + auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); + changed_objects({0}); wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_dirty(); @@ -13322,6 +13658,7 @@ void Plater::calib_max_vol_speed(const Calib_Params ¶ms) print_config->set_key_value("outer_wall_line_width", new ConfigOptionFloat(line_width)); print_config->set_key_value("initial_layer_print_height", new ConfigOptionFloat(layer_height)); print_config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); obj->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterAndInner)); obj->config.set_key_value("brim_width", new ConfigOptionFloat(3.0)); obj->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); @@ -13466,6 +13803,8 @@ void Plater::calib_retraction(const Calib_Params ¶ms) auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; auto obj = model().objects[0]; + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); + double layer_height = 0.2; auto max_lh = printer_config->option("max_layer_height"); @@ -13527,6 +13866,7 @@ void Plater::calib_VFA(const Calib_Params ¶ms) print_config->set_key_value("bottom_shell_layers", new ConfigOptionInt(1)); print_config->set_key_value("sparse_infill_density", new ConfigOptionPercent(0)); print_config->set_key_value("spiral_mode", new ConfigOptionBool(true)); + print_config->set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterOnly)); model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0)); model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); @@ -14134,11 +14474,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__ << PathSanitizer::sanitize(filename.mb_str()); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << PathSanitizer::sanitize(filename.ToUTF8().data()); emboss_svg(filename, from_toolbar_or_file_menu); return true; } else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << ",fail:" << PathSanitizer::sanitize(filename.mb_str()); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << ",fail:" << PathSanitizer::sanitize(filename.ToUTF8().data()); } } else { @@ -14204,6 +14544,7 @@ bool Plater::load_files(const wxArrayString& filenames) } } if (load_svg(filenames)) { + statistics_burial_data(filenames[0].utf8_string()); return true; } @@ -14230,6 +14571,7 @@ bool Plater::load_files(const wxArrayString& filenames) return false; } load_gcode(from_path(gcode_paths.front())); + statistics_burial_data(gcode_paths[0].string()); return true; } @@ -14293,12 +14635,16 @@ bool Plater::load_files(const wxArrayString& filenames) switch (loadfiles_type) { case LoadFilesType::Single3MF: - open_3mf_file(normal_paths[0]); + open_3mf_file(normal_paths[0]);//will call load_project break; case LoadFilesType::SingleOther: { Plater::TakeSnapshot snapshot(this, snapshot_label); - if (load_files(normal_paths, LoadStrategy::LoadModel, false).empty()) { res = false; } + if (load_files(normal_paths, LoadStrategy::LoadModel, false).empty()) { + res = false; + } else { + statistics_burial_data(normal_paths[0].string()); + } break; } case LoadFilesType::Multiple3MF: @@ -14308,15 +14654,22 @@ bool Plater::load_files(const wxArrayString& filenames) }; open_3mf_file(first_file[0]); - if (load_files(other_file, LoadStrategy::LoadModel).empty()) { res = false; } + if (load_files(other_file, LoadStrategy::LoadModel).empty()) { + res = false; + } else { + statistics_burial_data(normal_paths[0].string()); + } break; case LoadFilesType::MultipleOther: { Plater::TakeSnapshot snapshot(this, snapshot_label); - if (load_files(normal_paths, LoadStrategy::LoadModel, true).empty()) { res = false; } + if (load_files(normal_paths, LoadStrategy::LoadModel, true).empty()) { + res = false; + } else { + statistics_burial_data(normal_paths[0].string()); + } break; } - case LoadFilesType::Multiple3MFOther: for (const auto &path : normal_paths) { if (boost::iends_with(path.filename().string(), ".3mf")){ @@ -14330,8 +14683,16 @@ bool Plater::load_files(const wxArrayString& filenames) } open_3mf_file(first_file[0]); - if (load_files(tmf_file, LoadStrategy::LoadModel).empty()) { res = false; } - if (load_files(other_file, LoadStrategy::LoadModel, false).empty()) { res = false; } + if (load_files(tmf_file, LoadStrategy::LoadModel).empty()) { + res = false; + } else { + statistics_burial_data(normal_paths[0].string()); + } + if (load_files(other_file, LoadStrategy::LoadModel, false).empty()) { + res = false; + } else { + statistics_burial_data(normal_paths[0].string()); + } break; default: break; } @@ -14339,6 +14700,52 @@ bool Plater::load_files(const wxArrayString& filenames) return res; } +void Plater::statistics_burial_data_once(std::string json_str) +{ + NetworkAgent *agent = GUI::wxGetApp().getAgent(); + if (agent) { + agent->track_event("import_file_type", json_str); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " import_file_type:" << json_str; + } +} + +void Plater::statistics_burial_data(std::string file_path) +{ + json j; + std::string name; + if (boost::algorithm::iends_with(file_path, ".gcode")) { + name = "pure_gcode"; + } else if (boost::algorithm::iends_with(file_path, ".gcode.3mf")) { + name = "gcode_3mf"; + } else if (boost::algorithm::iends_with(file_path, ".3mf")) { + name = "3mf"; + } else if (boost::algorithm::iends_with(file_path, ".amf")) { + name = "amf"; + } else if (boost::algorithm::iends_with(file_path, ".stp") || boost::algorithm::iends_with(file_path, ".step")) { + name = "stp_step"; + } else if (boost::algorithm::iends_with(file_path, ".oltp")) { + name = "oltp"; + } else if (boost::algorithm::iends_with(file_path, ".stl")) { + name = "stl"; + } else if (boost::algorithm::iends_with(file_path, ".svg")) { + name = "svg"; + } else if (boost::algorithm::iends_with(file_path, ".obj")) { + name = "obj"; + } else { + name = "other"; + } + if (name.size() > 0) { + j["type"] = name; + statistics_burial_data_once(j.dump()); + } +} + +void Plater::statistics_burial_data_form_mw() +{ + json j; + j["type"] = "download_from_mw_and_open"; + statistics_burial_data_once(j.dump()); +} bool Plater::open_3mf_file(const fs::path &file_path) { @@ -14440,35 +14847,40 @@ void Plater::add_file() switch (loadfiles_type) { - case LoadFilesType::Single3MF: + case LoadFilesType::Single3MF: { open_3mf_file(paths[0]); - break; - + statistics_burial_data(paths[0].string()); + break; + } case LoadFilesType::SingleOther: { Plater::TakeSnapshot snapshot(this, snapshot_label); if (load_svg(input_files,true)) { + statistics_burial_data(input_files[0].utf8_string()); return; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "," << __FILE__ << ","<< "LoadFilesType::SingleOther"; if (!load_files(paths, LoadStrategy::LoadModel, false).empty()) { if (get_project_name() == _L("Untitled") && paths.size() > 0) { p->set_project_filename(wxString::FromUTF8(paths[0].string())); - } wxGetApp().mainframe->update_title(); + statistics_burial_data(paths[0].string()); } break; } - case LoadFilesType::Multiple3MF: + case LoadFilesType::Multiple3MF:{ first_file = std::vector{paths[0]}; for (auto i = 0; i < paths.size(); i++) { if (i > 0) { other_file.push_back(paths[i]); } }; open_3mf_file(first_file[0]); - if (!load_files(other_file, LoadStrategy::LoadModel).empty()) { wxGetApp().mainframe->update_title(); } + if (!load_files(other_file, LoadStrategy::LoadModel).empty()) { + wxGetApp().mainframe->update_title(); + statistics_burial_data(paths[0].string()); + } break; - + } case LoadFilesType::MultipleOther: { Plater::TakeSnapshot snapshot(this, snapshot_label); wxArrayString filenames; @@ -14482,6 +14894,7 @@ void Plater::add_file() } } if (boost::iends_with(paths[0].string(), ".svg")&& load_svg(filenames)) { + statistics_burial_data(paths[0].string()); return; } if (!load_files(paths, LoadStrategy::LoadModel, true).empty()) { @@ -14489,10 +14902,11 @@ void Plater::add_file() p->set_project_filename(wxString::FromUTF8(paths[0].string())); } wxGetApp().mainframe->update_title(); + statistics_burial_data(paths[0].string()); } break; } - case LoadFilesType::Multiple3MFOther: + case LoadFilesType::Multiple3MFOther:{ for (const auto &path : paths) { if (boost::iends_with(path.filename().string(), ".3mf")) { if (first_file.size() <= 0) @@ -14506,8 +14920,12 @@ void Plater::add_file() open_3mf_file(first_file[0]); load_files(tmf_file, LoadStrategy::LoadModel); - if (!load_files(other_file, LoadStrategy::LoadModel, false).empty()) { wxGetApp().mainframe->update_title();} + if (!load_files(other_file, LoadStrategy::LoadModel, false).empty()) { + wxGetApp().mainframe->update_title(); + statistics_burial_data(paths[0].string()); + } break; + } default:break; } } @@ -15338,13 +15756,13 @@ void Plater::export_core_3mf() export_3mf(path_u8, SaveStrategy::Silence); } -Preset *get_printer_preset(MachineObject *obj) +Preset *get_printer_preset(const MachineObject *obj) { if (!obj) return nullptr; Preset *printer_preset = nullptr; - float machine_nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + float machine_nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); PresetBundle *preset_bundle = wxGetApp().preset_bundle; for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) { // only use system printer preset @@ -15370,14 +15788,16 @@ bool Plater::check_printer_initialized(MachineObject *obj, bool only_warning, bo return false; bool has_been_initialized = true; - for (const Extder& extruder : obj->m_extder_data.extders) { + + const auto& extruders = obj->GetExtderSystem()->GetExtruders(); + for (const DevExtder& extruder : extruders) { if (obj->is_multi_extruders()) { - if (extruder.current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { + if (extruder.GetNozzleFlowType() == NozzleFlowType::NONE_FLOWTYPE) { has_been_initialized = false; break; } } - if (extruder.current_nozzle_type == NozzleType::ntUndefine) { + if (extruder.GetNozzleFlowType() == NozzleType::ntUndefine) { has_been_initialized = false; break; } @@ -15386,7 +15806,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->get_show_printer_type())) { + if (DevPrinterConfigUtil::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 { @@ -16175,6 +16595,7 @@ void Plater::reslice() // Only restarts if the state is valid. //QDS: jusdge the result bool result = this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART); + p->preview->get_canvas3d()->on_back_slice_begin(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: restart background,state=%2%, result=%3%")%__LINE__%state %result; if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) != 0) { @@ -16687,7 +17108,7 @@ bool Plater::on_filament_change(size_t filament_idx) return true; } -// BBS. +// QDS. void Plater::on_filament_count_change(size_t num_filaments) { // only update elements in plater @@ -16996,6 +17417,7 @@ void Plater::set_bed_shape() const set_bed_shape(p->config->option("printable_area")->values, //QDS: add bed exclude areas p->config->option("bed_exclude_area")->values, + p->config->option("wrapping_exclude_area")->values, p->config->option("printable_height")->value, p->config->option("extruder_printable_area")->values, p->config->option("extruder_printable_height")->values, @@ -17004,9 +17426,9 @@ void Plater::set_bed_shape() const } //QDS: add bed exclude area -void Plater::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) const +void Plater::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const Pointfs& wrapping_exclude_area, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) const { - p->set_bed_shape(shape, exclude_area, printable_height, extruder_areas, extruder_heights, custom_texture, custom_model, force_as_custom); + p->set_bed_shape(shape, exclude_area, wrapping_exclude_area, printable_height, extruder_areas, extruder_heights, custom_texture, custom_model, force_as_custom); } void Plater::force_filament_colors_update() @@ -17472,10 +17894,9 @@ void Plater::pop_warning_and_go_to_device_page(wxString printer_name, PrinterWar printer_name.Replace("QIDI Tech", "", false); wxString content; if (type == PrinterWarningType::NOT_CONNECTED) { - content = _L("Box not connected. Please check the printer and box connect."); - + content = wxString::Format(_L("Printer not connected. Please go to the device page to connect %s before syncing."), printer_name); } else if (type == PrinterWarningType::INCONSISTENT) { - content = wxString::Format(_L("The currently connected printer on the device page is not an %s. Please switch to an %s before syncing."), printer_name, printer_name); + content = wxString::Format(_L("The currently connected printer on the device page is not %s. Please switch to %s before syncing."), printer_name, printer_name); } else if (type == PrinterWarningType::UNINSTALL_FILAMENT) { content = _L("There are no filaments on the printer. Please load the filaments on the printer first."); } else if (type == PrinterWarningType::EMPTY_FILAMENT) { @@ -18383,6 +18804,22 @@ bool Plater::is_background_process_slicing() const return p->m_is_slicing; } +// returns the state enum. The header file could not be imported here so the return type is int. +int Plater::get_helio_process_status() const +{ + int helio_state = p->helio_background_process.get_state(); + return helio_state; +} + +void Plater::clear_helio_process_status() const { + p->helio_background_process.stop(); +} + +void Plater::update_helio_background_process(std::string& printer_id, std::string& material_id) +{ + p->update_helio_background_process(printer_id, material_id); +} + //QDS: update slicing context void Plater::update_slicing_context_to_current_partplate() { @@ -18581,6 +19018,37 @@ bool Plater::show_publish_dialog(bool show) return p->show_publish_dlg(show); } +std::vector Plater::get_current_filaments_preset_names() +{ + std::vector filaments_names; + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + for (auto filament_name : preset_bundle->filament_presets) { + for (int f_index = 0; f_index < preset_bundle->filaments.size(); f_index++) { + PresetCollection *filament_presets = &wxGetApp().preset_bundle->filaments; + Preset * preset = &filament_presets->preset(f_index); + int size = preset_bundle->filaments.size(); + if (preset && filament_name.compare(preset->name) == 0) { + // std::string display_filament_type; + // std::string filament_type = preset->config.get_filament_type(display_filament_type); + // std::string m_filament_id = preset->filament_id; + + // //display_materials.push_back(display_filament_type); + // //materials.push_back(filament_type); + //// m_filaments_id.push_back(m_filament_id); + + // std::string m_vendor_name = ""; + // auto vendor = dynamic_cast(preset->config.option("filament_vendor")); + // if (vendor && (vendor->values.size() > 0)) { + // std::string vendor_name = vendor->values[0]; + // m_vendor_name = vendor_name; + // } + filaments_names.push_back(filament_name); + } + } + } + return filaments_names; +} + void Plater::post_process_string_object_exception(StringObjectException &err) { PresetBundle* preset_bundle = wxGetApp().preset_bundle; @@ -18651,6 +19119,19 @@ void Plater::update_machine_sync_status() GUI::wxGetApp().sidebar().update_sync_status(obj); } +void Plater::show_wrapping_detect_dialog_if_necessary() +{ + if ((wxGetApp().app_config->get("show_wrapping_detect_dialog") == "true")) { + std::string printer_type = wxGetApp().preset_bundle->printers.get_edited_preset().get_printer_type(wxGetApp().preset_bundle); + if (DevPrinterConfigUtil::support_wrapping_detection(printer_type)) { + ImageMessageDialog dlg(this, wxID_ANY, _L("Parameter recommendation"), _L("In the process preset, under \"Others-Advanced\", check \"Enable clumping detection by probing\". This feature generates a small wipe " + "tower and performs probing detection to identify clumping issues early in the print and stop printing, preventing print failures or printer damage.\n")); + dlg.ShowModal(); + wxGetApp().app_config->set("show_wrapping_detect_dialog", "false"); + } + } +} + bool Plater::get_machine_sync_status() { return p->get_machine_sync_status(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 57657ec..00b17a2 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -47,6 +47,7 @@ class Button; namespace Slic3r { class BackgroundSlicingProcess; +class HelioBackgroundProcess; class BuildVolume; class Model; class ModelObject; @@ -58,9 +59,10 @@ class SLAPrint; //QDS: add partplatelist and SlicingStatusEvent class PartPlateList; class SlicingStatusEvent; +class HelioCompletionEvent; enum SLAPrintObjectStep : unsigned int; enum class ConversionType : int; -class Ams; +class DevAms; namespace csg { enum class BooleanFailReason; } @@ -117,6 +119,7 @@ wxDECLARE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent); wxDECLARE_EVENT(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, wxCommandEvent); wxDECLARE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent); wxDECLARE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent); +wxDECLARE_EVENT(EVT_ENABLE_GCODE_OPTION_ITEM_CHANGED, SimpleEvent); wxDECLARE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent); wxDECLARE_EVENT(EVT_CREATE_FILAMENT, SimpleEvent); wxDECLARE_EVENT(EVT_MODIFY_FILAMENT, SimpleEvent); @@ -126,6 +129,12 @@ wxDECLARE_EVENT(EVT_NOTICE_CHILDE_SIZE_CHANGED, SimpleEvent); wxDECLARE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent); using ColorEvent = Event; wxDECLARE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent); + +wxDECLARE_EVENT(EVT_HELIO_PROCESSING_COMPLETED, HelioCompletionEvent); +wxDECLARE_EVENT(EVT_HELIO_PROCESSING_STARTED, SimpleEvent); +wxDECLARE_EVENT(EVT_HELIO_INPUT_CHAMBER_TEMP, SimpleEvent); +wxDECLARE_EVENT(EVT_GCODE_VIEWER_CHANGED, SimpleEvent); + const wxString DEFAULT_PROJECT_NAME = "Untitled"; //y59 @@ -377,6 +386,10 @@ public: void calib_retraction(const Calib_Params ¶ms); void calib_VFA(const Calib_Params ¶ms); + // for helio slice + void update_helio_background_process(std::string& printer_id, std::string& material_id); + std::vector get_current_filaments_preset_names(); + //w29 std::string move_to(const Vec2d& point, double speed, double retract_length, double retract_speed, double height, double retract_lift); std::string move_to(const Vec2d& point, double speed, double retract_length, double retract_speed); @@ -407,6 +420,7 @@ public: const VendorProfile::PrinterModel * get_curr_printer_model(); std::map get_bed_texture_maps(); int get_right_icon_offset_bed(); + bool get_enable_wrapping_detection(); static wxColour get_next_color_for_filament(); static wxString get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning); @@ -420,6 +434,9 @@ public: bool load_svg(const wxArrayString &filenames, bool from_toolbar_or_file_menu = false); bool load_same_type_files(const wxArrayString &filenames); bool load_files(const wxArrayString& filenames); + void statistics_burial_data_once(std::string json_str);//Upload to the cloud immediately + void statistics_burial_data(std::string file_path); + void statistics_burial_data_form_mw(); const wxString& get_last_loaded_gcode() const { return m_last_loaded_gcode; } void update(bool conside_update_flag = false, bool force_background_processing_update = false); @@ -751,6 +768,11 @@ public: //QDS: show object info void show_object_info(); void show_assembly_info(); + + //QDS Helio slice + int get_helio_process_status() const; + void clear_helio_process_status() const; + //QDS bool show_publish_dialog(bool show = true); //QDS: post process string object exception strings by warning types @@ -763,6 +785,8 @@ public: void update_machine_sync_status(); + void show_wrapping_detect_dialog_if_necessary(); + #if ENABLE_ENVIRONMENT_MAP void init_environment_texture(); unsigned int get_environment_texture_id() const; @@ -795,7 +819,15 @@ public: void update_flush_volume_matrix(size_t old_nozzle_size, size_t new_nozzle_size); //QDS: add bed exclude area void set_bed_shape() const; - void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_area, const double printable_height, std::vector extruder_areas, std::vector extruder_heights, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const; + void set_bed_shape(const Pointfs &shape, + const Pointfs &exclude_area, + const Pointfs &wrapping_exclude_area, + const double printable_height, + std::vector extruder_areas, + std::vector extruder_heights, + const std::string &custom_texture, + const std::string &custom_model, + bool force_as_custom = false) const; const NotificationManager* get_notification_manager() const; NotificationManager* get_notification_manager(); @@ -1019,7 +1051,7 @@ private: std::vector get_min_flush_volumes(const DynamicPrintConfig &full_config, size_t nozzle_id); std::string check_boolean_possible(const std::vector &volumes, csg::BooleanFailReason& fail_reason); -Preset *get_printer_preset(MachineObject *obj); +Preset *get_printer_preset(const MachineObject *obj); wxArrayString get_all_camera_view_type(); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 2b6ecaa..55c2f8a 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -8,16 +8,15 @@ #include "libslic3r/AppConfig.hpp" #include #include "Notebook.hpp" +#include "ReleaseNote.hpp" #include "OG_CustomCtrl.hpp" #include "wx/graphics.h" -#include "Widgets/CheckBox.hpp" -#include "Widgets/ComboBox.hpp" -#include "Widgets/RadioBox.hpp" -#include "Widgets/TextInput.hpp" + #include #include #include "Gizmos/GLGizmoBase.hpp" #include "OpenGLManager.hpp" +#include "../Utils/HelioDragon.hpp" #ifdef __WINDOWS__ #ifdef _MSW_DARK_MODE #include "dark_mode.hpp" @@ -29,7 +28,7 @@ namespace Slic3r { namespace GUI { WX_DEFINE_LIST(RadioSelectorList); wxDEFINE_EVENT(EVT_PREFERENCES_SELECT_TAB, wxCommandEvent); - +#define PreferenceBtnSize wxSize(FromDIP(58), FromDIP(22)) class MyscrolledWindow : public wxScrolledWindow { public: MyscrolledWindow(wxWindow* parent, @@ -66,7 +65,8 @@ wxBoxSizer *PreferencesDialog::create_item_title(wxString title, wxWindow *paren return m_sizer_title; } -wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxWindow *parent, wxString tooltip, std::string param, const std::vector& label_list, const std::vector& value_list, std::function callback) + +wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxWindow *parent, wxString tooltip, std::string param, const std::vector& label_list, const std::vector& value_list, std::function callback, int title_width, int combox_width) { auto get_value_idx = [value_list](const std::string value) { size_t idx = 0; @@ -79,14 +79,15 @@ wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxWindow *pa wxBoxSizer *m_sizer_combox = new wxBoxSizer(wxHORIZONTAL); m_sizer_combox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); - auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, DESIGN_TITLE_SIZE, 0); + auto combo_title = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, title_width == 0?DESIGN_TITLE_SIZE:wxSize(title_width, -1), 0); combo_title->SetForegroundColour(DESIGN_GRAY900_COLOR); combo_title->SetFont(::Label::Body_13); combo_title->SetToolTip(tooltip); combo_title->Wrap(-1); m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); - auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, combox_width == 0?DESIGN_LARGE_COMBOBOX_SIZE:wxSize(combox_width, -1), 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox; combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); @@ -131,6 +132,7 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox( auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox; combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); auto language = app_config->get(param); @@ -291,6 +293,7 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_LARGE_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox; combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); m_sizer_combox->Add(combobox, 0, wxALIGN_CENTER, 0); @@ -315,19 +318,6 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin auto region_index = e.GetSelection(); auto region = local_regions[region_index]; - /*auto area = ""; - if (region == "CHN" || region == "China") - area = "CN"; - else if (region == "USA") - area = "US"; - else if (region == "Asia-Pacific") - area = "Others"; - else if (region == "Europe") - area = "US"; - else if (region == "North America") - area = "US"; - else - area = "Others";*/ combobox->SetSelection(region_index); NetworkAgent* agent = wxGetApp().getAgent(); AppConfig* config = GUI::wxGetApp().app_config; @@ -350,8 +340,33 @@ wxBoxSizer *PreferencesDialog::create_item_region_combobox(wxString title, wxWin config->set("region", region.ToStdString()); } + /*request helio data*/ + if (config->get("helio_enable") == "true") { + std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + if (helio_api_key.empty()) { + wxGetApp().request_helio_pat([this](std::string pat) { + CallAfter([=]() { + if (pat != "not_enough" && pat != "error") { + Slic3r::HelioQuery::set_helio_pat(pat); + helio_input_pat->SetLabel(Slic3r::HelioQuery::get_helio_pat()); + if (!Slic3r::HelioQuery::get_helio_pat().empty()) { helio_pat_refresh->Hide(); } + else { helio_pat_refresh->Show(); } + + + if (!Slic3r::HelioQuery::get_helio_api_url().empty() && !Slic3r::HelioQuery::get_helio_pat().empty()) { + wxGetApp().request_helio_supported_data(); + } + } + }); + }); + } + helio_input_pat->SetLabel(Slic3r::HelioQuery::get_helio_pat()); + if (!Slic3r::HelioQuery::get_helio_pat().empty()) { helio_pat_refresh->Hide(); } + else { helio_pat_refresh->Show(); } + + } wxGetApp().update_publish_status(); - e.Skip(); + //e.Skip(); }); return m_sizer_combox; @@ -370,6 +385,7 @@ wxBoxSizer *PreferencesDialog::create_item_loglevel_combobox(wxString title, wxW m_sizer_combox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox; combobox->SetFont(::Label::Body_13); combobox->GetDropDown().SetFont(::Label::Body_13); @@ -412,6 +428,7 @@ wxBoxSizer *PreferencesDialog::create_item_multiple_combobox( m_sizer_tcombox->Add(combo_title, 0, wxALIGN_CENTER | wxALL, 3); auto combobox_left = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox_left; combobox_left->SetFont(::Label::Body_13); combobox_left->GetDropDown().SetFont(::Label::Body_13); @@ -427,6 +444,7 @@ wxBoxSizer *PreferencesDialog::create_item_multiple_combobox( m_sizer_tcombox->Add(combo_title_add, 0, wxALIGN_CENTER | wxALL, 3); auto combobox_right = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, DESIGN_COMBOBOX_SIZE, 0, nullptr, wxCB_READONLY); + m_combobox_list[m_combobox_list.size()] = combobox_right; combobox_right->SetFont(::Label::Body_13); combobox_right->GetDropDown().SetFont(::Label::Body_13); @@ -658,6 +676,7 @@ wxBoxSizer* PreferencesDialog::create_item_darkmode_checkbox(wxString title, wxW m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto checkbox = new ::CheckBox(parent); + m_checkbox_list[m_checkbox_list.size()] = checkbox; checkbox->SetValue((app_config->get(param) == "1") ? true : false); m_dark_mode_ckeckbox = checkbox; @@ -715,6 +734,7 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 23); auto checkbox = new ::CheckBox(parent); + m_checkbox_list[m_checkbox_list.size()] = checkbox; //ZY2 /*if (param == "privacyuse") { checkbox->SetValue((app_config->get("firstguide", param) == "true") ? true : false); @@ -869,6 +889,57 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa } } + if (param == "enable_record_gcodeviewer_option_item"){ + SimpleEvent evt(EVT_ENABLE_GCODE_OPTION_ITEM_CHANGED); + wxPostEvent(wxGetApp().plater(), evt); + } + + if (param == "helio_enable") { + if (checkbox->GetValue()) { + HelioStatementDialog dlg; + auto res = dlg.ShowModal(); + + if (res == wxID_OK) { + std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + if (helio_api_key.empty()) { + wxGetApp().request_helio_pat([this](std::string pat) { + CallAfter([=]() { + if (pat == "not_enough") { + HelioPatNotEnoughDialog dlg; + dlg.ShowModal(); + } + else if (pat == "error") { + MessageDialog dlg(nullptr, _L("Failed to obtain Helio PAT, Click Refresh to obtain it again."), wxString("Helio Additive"), wxYES | wxICON_WARNING); + dlg.ShowModal(); + } + else { + Slic3r::HelioQuery::set_helio_pat(pat); + helio_input_pat->SetLabel(Slic3r::HelioQuery::get_helio_pat()); + if (!Slic3r::HelioQuery::get_helio_pat().empty()) { helio_pat_refresh->Hide(); } + else { helio_pat_refresh->Show(); } + if (!Slic3r::HelioQuery::get_helio_api_url().empty() && !Slic3r::HelioQuery::get_helio_pat().empty()) { + wxGetApp().request_helio_supported_data(); + } + } + }); + }); + } + } + else { + wxGetApp().app_config->set_bool("helio_enable", false); + checkbox->SetValue(false); + } + } + + if (GUI::wxGetApp().app_config->get("helio_enable") == "true") { helio_pat_panel->Show(); } + else { helio_pat_panel->Hide(); } + + helio_fun_panel->Layout(); + helio_fun_panel->Fit(); + m_scrolledWindow->Layout(); + m_scrolledWindow->FitInside(); + } + if (param == "enable_high_low_temp_mixed_printing") { if (checkbox->GetValue()) { const wxString warning_title = _L("Bed Temperature Difference Warning"); @@ -928,26 +999,30 @@ wxBoxSizer *PreferencesDialog::create_item_button(wxString title, wxString title m_staticTextPath->SetFont(::Label::Body_13); m_staticTextPath->Wrap(-1); - auto m_button_download = new Button(parent, title2); - + auto temp_button = new Button(parent, title2); + m_button_list[m_button_list.size()] = temp_button; StateColor abort_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)); - m_button_download->SetBackgroundColor(abort_bg); - StateColor abort_bd(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); - m_button_download->SetBorderColor(abort_bd); - StateColor abort_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); - m_button_download->SetTextColor(abort_text); - m_button_download->SetFont(Label::Body_10); - m_button_download->SetMinSize(wxSize(FromDIP(58), FromDIP(22))); - m_button_download->SetSize(wxSize(FromDIP(58), FromDIP(22))); - m_button_download->SetCornerRadius(FromDIP(12)); - m_button_download->SetToolTip(tooltip); - m_button_download->Bind(wxEVT_BUTTON, [this, onclick](auto &e) { onclick(); }); + temp_button->SetBackgroundColor(abort_bg); + StateColor abort_bd(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); + + temp_button->SetBorderColor(abort_bd); + StateColor abort_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); + + temp_button->SetTextColor(abort_text); + temp_button->SetFont(Label::Body_10); + temp_button->SetMinSize(PreferenceBtnSize); + temp_button->SetSize(wxSize(FromDIP(58), FromDIP(22))); + temp_button->SetCornerRadius(FromDIP(12)); + temp_button->SetToolTip(tooltip); + + + temp_button->Bind(wxEVT_BUTTON, [this, onclick](auto &e) { onclick(); }); m_sizer_checkbox->Add(m_staticTextPath, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); - m_sizer_checkbox->Add(m_button_download, 0, wxALL, FromDIP(5)); + m_sizer_checkbox->Add(temp_button, 0, wxALL, FromDIP(5)); return m_sizer_checkbox; } @@ -967,7 +1042,7 @@ wxWindow* PreferencesDialog::create_item_downloads(wxWindow* parent, int padding m_staticTextPath->Wrap(-1); auto m_button_download = new Button(item_panel, _L("Browse")); - + m_button_list[m_button_list.size()] = m_button_download; StateColor abort_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)); @@ -977,7 +1052,7 @@ wxWindow* PreferencesDialog::create_item_downloads(wxWindow* parent, int padding StateColor abort_text(std::pair(wxColour(144, 144, 144), StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); m_button_download->SetTextColor(abort_text); m_button_download->SetFont(Label::Body_10); - m_button_download->SetMinSize(wxSize(FromDIP(58), FromDIP(22))); + m_button_download->SetMinSize(PreferenceBtnSize); m_button_download->SetSize(wxSize(FromDIP(58), FromDIP(22))); m_button_download->SetCornerRadius(FromDIP(12)); @@ -1009,6 +1084,7 @@ wxWindow *PreferencesDialog ::create_item_radiobox(wxString title, wxWindow *par item->SetBackgroundColour(*wxWHITE); RadioBox *radiobox = new RadioBox(item); + m_radiobox_list[m_radiobox_list.size()] = radiobox; radiobox->SetPosition(wxPoint(padding_left, (item->GetSize().GetHeight() - radiobox->GetSize().GetHeight()) / 2)); radiobox->Bind(wxEVT_LEFT_DOWN, &PreferencesDialog::OnSelectRadio, this); @@ -1088,9 +1164,8 @@ void PreferencesDialog::create() SetSizer(main_sizer); Layout(); Fit(); - int screen_height = wxGetDisplaySize().GetY(); - if (this->GetSize().GetY() > screen_height) - this->SetSize(this->GetSize().GetX() + FromDIP(40), screen_height * 4 / 5); + m_screen_height = wxGetDisplaySize().GetY(); + this->SetSize(this->GetSize().GetX() + FromDIP(40), m_screen_height * 0.7); CenterOnParent(); wxPoint start_pos = this->GetPosition(); @@ -1109,7 +1184,35 @@ PreferencesDialog::~PreferencesDialog() m_hash_selector.clear(); } -void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect) { this->Refresh(); } +void PreferencesDialog::on_dpi_changed(const wxRect &suggested_rect) { + for (auto item : m_button_list) { + item.second->Rescale(); + item.second->SetMinSize(PreferenceBtnSize); + item.second->SetCornerRadius(FromDIP(12)); + } + for (auto item : m_checkbox_list) { + item.second->Rescale(); + } + for (auto item : m_radiobox_list) { + item.second->Rescale(); + } + for (auto item : m_combobox_list) { + item.second->Rescale(); + } + this->Refresh(); + Layout(); + Fit(); + int displayIndex = wxDisplay::GetFromWindow(this); + if (displayIndex != wxNOT_FOUND) { + wxDisplay display(displayIndex); + wxRect screenRect = display.GetGeometry(); + if (m_screen_height != screenRect.GetHeight()) { + m_screen_height = screenRect.GetHeight(); + this->SetSize(this->GetSize().GetX() + FromDIP(40), m_screen_height * 0.7); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " The display screen has switched"; + } + } +} void PreferencesDialog::Split(const std::string &src, const std::string &separator, std::vector &dest) { @@ -1204,6 +1307,9 @@ wxWindow* PreferencesDialog::create_general_page() auto item_gamma_correct_in_import_obj = create_item_checkbox(_L("Enable gamma correction for the imported obj file"), page, _L("Perform gamma correction on color after importing the obj model."), 50, "gamma_correct_in_import_obj"); + auto item_enable_record_gcodeviewer_option_item = create_item_checkbox(_L("Remember last used color scheme"), page, + _L("When enabled, the last used color scheme (e.g., Line Type, Speed) will be automatically applied on next startup."), 50, + "enable_record_gcodeviewer_option_item"); auto enable_lod_settings = create_item_checkbox(_L("Improve rendering performance by lod"), page, _L("Improved rendering performance under the scene of multiple plates and many models."), 50, "enable_lod"); @@ -1248,6 +1354,127 @@ wxWindow* PreferencesDialog::create_general_page() //auto item_modelmall = create_item_checkbox(_L("Show online staff-picked models on the home page"), page, _L("Show online staff-picked models on the home page"), 50, "staff_pick_switch"); // auto item_show_history = create_item_checkbox(_L("Show history on the home page"), page, _L("Show history on the home page"), 50, "show_print_history"); +// y71 Helio + // // helio options + // helio_fun_panel = new wxPanel(page); + // helio_fun_panel->SetBackgroundColour(wxColour(248, 248, 248)); + // helio_fun_panel->SetMinSize(wxSize(FromDIP(568), -1)); + // //helio_fun_panel->SetMaxSize(wxSize(FromDIP(568), -1)); + // wxBoxSizer *sizer_helio_fun = new wxBoxSizer(wxVERTICAL); + // wxBoxSizer *sizer_helio_fun_link = new wxBoxSizer(wxHORIZONTAL); + // wxBoxSizer *sizer_helio_title = new wxBoxSizer(wxHORIZONTAL); + // wxBoxSizer *sizer_helio_pat = new wxBoxSizer(wxHORIZONTAL); + + // auto helio_icon_helio = new wxStaticBitmap(helio_fun_panel, wxID_ANY, create_scaled_bitmap("helio_icon_dark", helio_fun_panel, 16), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)), 0); + + // auto helio_title_slice = create_item_title(_L("Helio Options"), helio_fun_panel, _L("Helio Options")); + // auto helio_item_switch_slice = create_item_checkbox(_L("Enable Helio"), helio_fun_panel, _L("Enable Helio"), 50, "helio_enable"); + // auto helio_split_line = new wxPanel(helio_fun_panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + // helio_split_line->SetMaxSize(wxSize(-1, 1)); + // helio_split_line->SetBackgroundColour(DESIGN_GRAY400_COLOR); + + // helio_pat_panel = new wxPanel(helio_fun_panel); + // helio_pat_panel->SetBackgroundColour(helio_fun_panel->GetBackgroundColour()); + // auto helio_title_pat = new Label(helio_pat_panel, _L("Helio-PAT")); + // helio_input_pat = new ::TextInput(helio_pat_panel, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, DESIGN_INPUT_SIZE, wxTE_PROCESS_ENTER|wxTE_RIGHT); + // helio_input_pat->SetFont(Label::Body_13); + // helio_input_pat->SetMinSize(wxSize(FromDIP(410), FromDIP(22))); + // helio_input_pat->SetMaxSize(wxSize(FromDIP(410), FromDIP(22))); + // helio_input_pat->Disable(); + // helio_input_pat->SetLabel(Slic3r::HelioQuery::get_helio_pat()); + + // helio_pat_refresh = new wxStaticBitmap(helio_pat_panel, wxID_ANY, create_scaled_bitmap("ams_refresh_selected", helio_fun_panel, 20), wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), 0); + // helio_pat_refresh->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); + // helio_pat_refresh->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); + // helio_pat_refresh->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { + // std::string helio_api_key = Slic3r::HelioQuery::get_helio_pat(); + // if (!helio_api_key.empty()) { + // return; + // } + // wxGetApp().request_helio_pat([this](std::string pat) { + // CallAfter([=]() { + // if (pat == "not_enough") { + // HelioPatNotEnoughDialog dlg; + // dlg.ShowModal(); + // } + // else if (pat == "error") { + // MessageDialog dlg(nullptr, _L("Failed to obtain Helio PAT, Click Refresh to obtain it again."), wxString("Helio Additive"), wxYES | wxICON_WARNING); + // dlg.ShowModal(); + // } + // else { + // Slic3r::HelioQuery::set_helio_pat(pat); + // helio_input_pat->SetLabel(Slic3r::HelioQuery::get_helio_pat()); + // if (!Slic3r::HelioQuery::get_helio_pat().empty()) { helio_pat_refresh->Hide(); } + // else { helio_pat_refresh->Show(); } + + + // if (!Slic3r::HelioQuery::get_helio_api_url().empty() && !Slic3r::HelioQuery::get_helio_pat().empty()) { + // wxGetApp().request_helio_supported_data(); + // } + // } + // }); + // }); + // }); + + // if (!Slic3r::HelioQuery::get_helio_pat().empty()) { helio_pat_refresh->Hide(); } + // else { helio_pat_refresh->Show(); } + + // sizer_helio_pat->Add(0, 0, 0, wxLEFT, FromDIP(50)); + // sizer_helio_pat->Add(helio_title_pat, 0, wxALIGN_CENTER, 0); + // sizer_helio_pat->Add(0, 0, 0, wxLEFT, FromDIP(10)); + // sizer_helio_pat->Add(helio_input_pat, 0, wxALIGN_CENTER, 0); + // sizer_helio_pat->Add(0, 0, 0, wxLEFT, FromDIP(4)); + // sizer_helio_pat->Add(helio_pat_refresh, 0, wxALIGN_CENTER, 0); + // helio_pat_panel->SetSizer(sizer_helio_pat); + + // if (GUI::wxGetApp().app_config->get("helio_enable") == "true") { helio_pat_panel->Show(); } + // else { helio_pat_panel->Hide(); } + + // auto helio_about_link = new LinkLabel(helio_fun_panel, _L("About Helio"), "https://www.helioadditive.com/"); + // LinkLabel* helio_privacy_link = nullptr; + + // if (GUI::wxGetApp().app_config->get("region") == "China") { + // helio_privacy_link = new LinkLabel(helio_fun_panel, _L("Helio Privacy Policy"), "https://www.helioadditive.com/zh-cn/policies/privacy"); + // } else { + // helio_privacy_link = new LinkLabel(helio_fun_panel, _L("Helio Privacy Policy"), "https://www.helioadditive.com/en-us/policies/privacy"); + // } + + // helio_about_link->getLabel()->SetFont(::Label::Body_13); + // helio_privacy_link->getLabel()->SetFont(::Label::Body_13); + + // helio_about_link->SeLinkLabelFColour(wxColour(0, 119, 250)); + // helio_privacy_link->SeLinkLabelFColour(wxColour(0, 119, 250)); + + // helio_about_link->SeLinkLabelBColour(wxColour(248, 248, 248)); + // helio_privacy_link->SeLinkLabelBColour(wxColour(248, 248, 248)); + // ; + // sizer_helio_fun_link->Add(helio_about_link, 0, wxLEFT, FromDIP(50)); + // sizer_helio_fun_link->Add(helio_privacy_link, 0, wxLEFT, FromDIP(35)); + + // helio_about_link->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); }); + // helio_about_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_ARROW); }); + // helio_privacy_link->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); }); + // helio_privacy_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_ARROW); }); + + // sizer_helio_title->Add(0, 0, 0, wxLEFT, FromDIP(5)); + // sizer_helio_title->Add(helio_icon_helio, 0, wxALIGN_CENTER, FromDIP(0)); + // sizer_helio_title->Add(0, 0, 0, wxLEFT, FromDIP(3)); + // sizer_helio_title->Add(helio_title_slice, 0, wxALIGN_CENTER, FromDIP(0)); + // sizer_helio_title->Add(helio_split_line, 1, wxALIGN_CENTER, 0); + + // sizer_helio_fun->Add(0, 0, 0, wxTOP, FromDIP(9)); + // sizer_helio_fun->Add(sizer_helio_title, 0, wxEXPAND, FromDIP(0)); + // sizer_helio_fun->Add(helio_item_switch_slice, 0, wxTOP, FromDIP(5)); + // sizer_helio_fun->Add(helio_pat_panel, 0, wxTOP, FromDIP(7)); + // sizer_helio_fun->Add(sizer_helio_fun_link, 0, wxTOP, FromDIP(7)); + // sizer_helio_fun->Add(0, 0, 0, wxTOP, FromDIP(9)); + // helio_fun_panel->SetSizer(sizer_helio_fun); + // helio_fun_panel->Layout(); + // helio_fun_panel->Fit(); + + std::vector air_temp_timing_list = {_L("Reminder During Slicing"), _L("Automatic mode")}; + std::vector air_temp_timing_value_list = {"slicing", "auto"}; + auto title_project = create_item_title(_L("Project"), page, ""); auto item_max_recent_count = create_item_input(_L("Maximum recent projects"), "", page, _L("Maximum count of recent projects"), "max_recent_count", [](wxString value) { long max = 0; @@ -1314,6 +1541,7 @@ wxWindow* PreferencesDialog::create_general_page() sizer_page->Add(item_show_shells_in_preview_settings, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_import_single_svg_and_split, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_gamma_correct_in_import_obj, 0, wxTOP, FromDIP(3)); + sizer_page->Add(item_enable_record_gcodeviewer_option_item, 0, wxTOP, FromDIP(3)); sizer_page->Add(enable_lod_settings, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_toolbar_style, 0, wxTOP, FromDIP(3)); @@ -1343,6 +1571,14 @@ wxWindow* PreferencesDialog::create_general_page() wxCommandEvent eee(wxEVT_COMBOBOX); update_modelmall(eee); item_region->GetItem(size_t(2))->GetWindow()->Bind(wxEVT_COMBOBOX, update_modelmall);*/ + + + sizer_page->Add(0, 0, 0, wxTOP, FromDIP(20)); + //y71 + //sizer_page->Add(helio_fun_panel, 0, wxEXPAND, 0); + + //sizer_page->Add(helio_item_switch_slice, 0, wxTOP, FromDIP(3)); + sizer_page->Add(title_project, 0, wxTOP| wxEXPAND, FromDIP(20)); sizer_page->Add(item_max_recent_count, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_save_choise, 0, wxTOP, FromDIP(3)); @@ -1496,6 +1732,7 @@ wxWindow* PreferencesDialog::create_debug_page() StateColor btn_bd_white(std::pair(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair(wxColour(38, 46, 48), StateColor::Enabled)); Button* debug_button = new Button(page, _L("debug save button")); + m_button_list[m_button_list.size()] = debug_button; debug_button->SetBackgroundColor(btn_bg_white); debug_button->SetBorderColor(btn_bd_white); debug_button->SetFont(Label::Body_13); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 2d0f0e1..f59e1c0 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -13,7 +13,9 @@ #include "Widgets/ComboBox.hpp" #include "Widgets/CheckBox.hpp" #include "Widgets/TextInput.hpp" - +#include "Widgets/Button.hpp" +#include "Widgets/RadioBox.hpp" +#include "Widgets/LinkLabel.hpp" namespace Slic3r { namespace GUI { @@ -86,7 +88,6 @@ public: wxString m_backup_interval_time; void create(); - wxWindow *create_tab_button(int id, wxString text); // debug mode ::CheckBox * m_developer_mode_ckeckbox = {nullptr}; @@ -103,8 +104,13 @@ public: RadioSelectorList m_radio_group; // ComboBoxSelectorList m_comxbo_group; + ::TextInput* helio_input_pat = { nullptr }; + wxStaticBitmap* helio_pat_refresh = { nullptr }; + wxPanel* helio_pat_panel = { nullptr }; + wxPanel* helio_fun_panel = { nullptr }; + wxBoxSizer *create_item_title(wxString title, wxWindow *parent, wxString tooltip); - wxBoxSizer *create_item_combobox(wxString title, wxWindow *parent, wxString tooltip, std::string param,const std::vector& label_list, const std::vector& value_list, std::function callback = nullptr); + wxBoxSizer *create_item_combobox(wxString title, wxWindow *parent, wxString tooltip, std::string param,const std::vector& label_list, const std::vector& value_list, std::function callback = nullptr, int title_width = 0, int combox_width = 0); wxBoxSizer *create_item_region_combobox(wxString title, wxWindow *parent, wxString tooltip, std::vector vlist); wxBoxSizer *create_item_language_combobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left, std::string param, std::vector vlist); wxBoxSizer *create_item_loglevel_combobox(wxString title, wxWindow *parent, wxString tooltip, std::vector vlist); @@ -136,6 +142,12 @@ public: void Split(const std::string &src, const std::string &separator, std::vector &dest); int m_current_language_selected = {0}; + std::unordered_map m_button_list; + std::unordered_map m_checkbox_list; + std::unordered_map m_radiobox_list; + std::unordered_map m_combobox_list; + int m_screen_height; + protected: void OnSelectTabel(wxCommandEvent &event); void OnSelectRadio(wxMouseEvent &event); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 89212c3..999c7ec 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -44,6 +44,8 @@ #include "FilamentPickerDialog.hpp" #include "wxExtensions.hpp" +#include "DeviceCore/DevManager.h" + // A workaround for a set of issues related to text fitting into gtk widgets: #if defined(__WXGTK20__) || defined(__WXGTK3__) #include @@ -450,7 +452,7 @@ void PresetComboBox::add_connected_printers(std::string selected, bool alias_nam } std::sort(user_machine_list.begin(), user_machine_list.end(), [&](auto &a, auto &b) { - if (a.second && b.second) { return a.second->dev_name.compare(b.second->dev_name) < 0; } + if (a.second && b.second) { return a.second->get_dev_name().compare(b.second->get_dev_name()) < 0; } return false; }); @@ -466,7 +468,7 @@ void PresetComboBox::add_connected_printers(std::string selected, bool alias_nam printer_preset->is_visible = true; auto printer_model = printer_preset->config.opt_string("printer_model"); boost::replace_all(printer_model, "QIDI TECH ", ""); - auto text = iter->second->dev_name + " (" + printer_model + ")"; + auto text = iter->second->get_dev_name() + " (" + printer_model + ")"; int item_id = Append(from_u8(text), wxNullBitmap, &m_first_printer_idx + std::distance(user_machine_list.begin(), iter)); validate_selection(m_selected_dev_id == iter->first); } @@ -560,13 +562,24 @@ bool PresetComboBox::add_box_filaments(std::string selected, bool alias_name) set_label_marker(Append(L("Box filaments"), wxNullBitmap, DD_ITEM_STYLE_SPLIT_ITEM)); m_first_ams_filament = GetCount(); auto& filaments = m_collection->get_presets(); + + int icon_width = 24; + for (auto& entry : m_preset_bundle->filament_ams_list) { + auto& tray = entry.second; + + auto name = tray.opt_string("tray_name", 0u); + if (name.size() > 3) + icon_width = 32; + } + for (auto& entry : m_preset_bundle->filament_ams_list) { auto& tray = entry.second; std::string filament_id = tray.opt_string("filament_id", 0u); + auto name = tray.opt_string("tray_name", 0u); if (filament_id.empty()) continue; auto iter = std::find_if(filaments.begin(), filaments.end(), - [&filament_id, this](auto& f) { return f.filament_id == filament_id; }); + [&filament_id, this](auto& f) { return f.is_compatible && m_collection->get_preset_base(f) == &f && f.filament_id == filament_id; }); if (iter == filaments.end()) { auto filament_type = tray.opt_string("filament_type", 0u); if (!filament_type.empty()) { @@ -582,8 +595,7 @@ bool PresetComboBox::add_box_filaments(std::string selected, bool alias_name) } const_cast(*iter).is_visible = true; auto color = tray.opt_string("filament_colour", 0u); - auto name = tray.opt_string("tray_name", 0u); - wxBitmap bmp(*get_extruder_color_icon(color, name, 24, 16)); + wxBitmap bmp(*get_extruder_color_icon(color, name, icon_width, 16)); auto text = get_preset_name(*iter); int item_id = Append(text, bmp.ConvertToImage(), &m_first_ams_filament + entry.first); SetFlag(GetCount() - 1, (int) FilamentAMSType::FROM_AMS); @@ -877,14 +889,6 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset clr_picker->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE)); clr_picker->SetToolTip(_L("Click to pick filament color")); clr_picker->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { - m_clrData.SetColour(clr_picker->GetBackgroundColour()); - m_clrData.SetChooseFull(true); - m_clrData.SetChooseAlpha(false); - - std::vector colors = wxGetApp().app_config->get_custom_color_from_config(); - for (int i = 0; i < colors.size(); i++) { - m_clrData.SetCustomColour(i, string_to_wxColor(colors[i])); - } // Check if it's an official filament auto fila_type = Preset::remove_suffix_modified(GetValue().ToUTF8().data()); @@ -928,6 +932,9 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset } else { show_default_color_picker(); } + wxCommandEvent *evt = new wxCommandEvent(EVT_FILAMENT_COLOR_CHANGED); + evt->SetInt(m_filament_idx); + wxQueueEvent(wxGetApp().plater(), evt); }); } else { @@ -1354,6 +1361,9 @@ void PlaterPresetComboBox::update() if (is_selected && selected_in_box) { SetFlag(GetCount() - 1, (int) FilamentAMSType::FROM_AMS); } + //y71 + if(!selected_in_box) + ShowBadge(selected_in_box); } } else { for (std::map::const_iterator it = presets.begin(); it != presets.end(); ++it) { @@ -1483,6 +1493,14 @@ FilamentColor PlaterPresetComboBox::get_cur_color_info() void PlaterPresetComboBox::show_default_color_picker() { + DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config; + auto colors = static_cast(cfg->option("filament_colour")->clone()); + wxColour current_clr(colors->values[m_filament_idx]); + if (!current_clr.IsOk()) + current_clr = wxColour(0, 0, 0); // Don't set alfa to transparence + + m_clrData.SetColour(current_clr); + wxColourData data = show_sys_picker_dialog(this, m_clrData); if(m_clrData.GetColour() != data.GetColour()) { std::vector color = {data.GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString()}; @@ -1525,10 +1543,6 @@ void PlaterPresetComboBox::sync_colour_config(const std::vector &cl update(); // refresh the preset combobox with new config wxGetApp().plater()->on_config_change(cfg_new); - - wxCommandEvent *evt = new wxCommandEvent(EVT_CALI_TRAY_CHANGED); - evt->SetInt(m_filament_idx); - wxQueueEvent(wxGetApp().plater(), evt); } diff --git a/src/slic3r/GUI/PrintOptionsDialog.cpp b/src/slic3r/GUI/PrintOptionsDialog.cpp index 9616319..cd39aa6 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.cpp +++ b/src/slic3r/GUI/PrintOptionsDialog.cpp @@ -5,6 +5,9 @@ #include "Widgets/SwitchButton.hpp" #include "MsgDialog.hpp" +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevExtruderSystem.h" + static const wxColour STATIC_BOX_LINE_COL = wxColour(238, 238, 238); static const wxColour STATIC_TEXT_CAPTION_COL = wxColour(100, 100, 100); static const wxColour STATIC_TEXT_EXPLAIN_COL = wxColour(100, 100, 100); @@ -249,15 +252,18 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) if (!obj_) return; if (obj_->is_support_spaghetti_detection || obj_->is_support_purgechutepileup_detection || obj_->is_support_nozzleclumping_detection || obj_->is_support_airprinting_detection) { + ai_refine_panel->Show(); text_ai_detections->Show(); text_ai_detections_caption->Show(); + m_line->Show(); } else { + ai_refine_panel->Hide(); text_ai_detections->Hide(); text_ai_detections_caption->Hide(); + m_line->Hide(); } - - if (obj_->is_support_ai_monitoring && !obj_->xcam_disable_ai_detection_display) { + if (obj_->GetConfig()->SupportAIMonitor() && !obj_->xcam_disable_ai_detection_display) { text_ai_monitoring->Show(); m_cb_ai_monitoring->Show(); text_ai_monitoring_caption->Show(); @@ -270,7 +276,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) text_ai_monitoring_caption->Hide(); ai_monitoring_level_list->Hide(); ai_monitoring_bottom_space->Show(false); - line1->Hide(); + //line1->Hide(); } //refine printer function options @@ -290,7 +296,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) text_spaghetti_detection_caption1->Hide(); spaghetti_detection_level_list->Hide(); spaghetti_bottom_space->Show(false); - line1->Hide(); + //line1->Hide(); } @@ -309,7 +315,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) text_purgechutepileup_detection_caption1->Hide(); purgechutepileup_detection_level_list->Hide(); purgechutepileup_bottom_space->Show(false); - line1->Hide(); + //line1->Hide(); } @@ -329,7 +335,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) text_nozzleclumping_detection_caption1->Hide(); nozzleclumping_detection_level_list->Hide(); nozzleclumping_bottom_space->Show(false); - line1->Hide(); + //line1->Hide(); } if (obj_->is_support_airprinting_detection) { @@ -346,7 +352,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) text_airprinting_detection_caption0->Hide(); text_airprinting_detection_caption1->Hide(); airprinting_detection_level_list->Hide(); - line1->Hide(); + //line1->Hide(); airprinting_bottom_space->Show(false); } @@ -375,7 +381,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_) //line2->Hide(); } - if (obj_->is_support_first_layer_inspect) { + if (obj_->GetConfig()->SupportFirstLayerInspect()) { text_first_layer->Show(); m_cb_first_layer->Show(); //line3->Show(); @@ -526,7 +532,7 @@ void PrintOptionsDialog::UpdateOptionOpenDoorCheck(MachineObject *obj) { void PrintOptionsDialog::UpdateOptionSavePrintFileToStorage(MachineObject *obj) { - if (obj && obj->support_save_remote_print_file_to_storage()) + if (obj && obj->GetConfig()->SupportSaveRemotePrintFileToStorage()) { m_cb_save_remote_print_file_to_storage->SetValue(obj->get_save_remote_print_file_to_storage()); } @@ -551,24 +557,28 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) //m_line->SetBackgroundColour(wxColour(166, 169, 170)); //sizer->Add(m_line, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(0)); + ai_refine_panel = new wxPanel(parent); + wxBoxSizer *ai_refine_sizer = new wxBoxSizer(wxVERTICAL); + ai_refine_panel->SetBackgroundColour(*wxWHITE); + // ai detections line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_ai_detections = new Label(parent, _L("AI Detections")); + text_ai_detections = new Label(ai_refine_panel, _L("AI Detections")); text_ai_detections->SetFont(Label::Body_14); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(text_ai_detections, 0, wxLEFT | wxRIGHT | wxDOWN | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_ai_detections_caption = new Label(parent, _L("Printer will send assistant message or pause printing if any of the following problem is detected.")); + text_ai_detections_caption = new Label(ai_refine_panel, _L("Printer will send assistant message or pause printing if any of the following problem is detected.")); text_ai_detections_caption->SetFont(Label::Body_12); text_ai_detections_caption->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_ai_detections_caption->Wrap(FromDIP(400)); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(text_ai_detections_caption, 0,wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - sizer->Add(line_sizer,0,wxEXPAND | wxLEFT | wxRIGHT,FromDIP(18)); - ai_detections_bottom_space = sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_detections_bottom_space = ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); // ai monitoring with levels line_sizer = new wxBoxSizer(wxHORIZONTAL); @@ -604,30 +614,30 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) //spaghetti detection with levels line_sizer = new wxBoxSizer(wxHORIZONTAL); - m_cb_spaghetti_detection = new CheckBox(parent); - text_spaghetti_detection = new Label(parent, _L("Spaghetti Detection")); + m_cb_spaghetti_detection = new CheckBox(ai_refine_panel); + text_spaghetti_detection = new Label(ai_refine_panel, _L("Spaghetti Detection")); text_spaghetti_detection->SetFont(Label::Body_14); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(m_cb_spaghetti_detection, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); line_sizer->Add(text_spaghetti_detection, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_spaghetti_detection_caption0 = new Label(parent, _L("Detect spaghetti failure(scattered lose filament).")); + text_spaghetti_detection_caption0 = new Label(ai_refine_panel, _L("Detect spaghetti failure(scattered lose filament).")); text_spaghetti_detection_caption0->SetFont(Label::Body_12); text_spaghetti_detection_caption0->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_spaghetti_detection_caption0->Wrap(-1); line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_spaghetti_detection_caption0, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_spaghetti_detection_caption1 = new Label(parent, _L("Pausing Sensitivity:")); + text_spaghetti_detection_caption1 = new Label(ai_refine_panel, _L("Pausing Sensitivity:")); text_spaghetti_detection_caption1->SetFont(Label::Body_12); text_spaghetti_detection_caption1->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_spaghetti_detection_caption1->Wrap(-1); - spaghetti_detection_level_list = new ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); + spaghetti_detection_level_list = new ComboBox(ai_refine_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) { wxString level_option = sensitivity_level_to_label_string(i); spaghetti_detection_level_list->Append(level_option); @@ -639,39 +649,39 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_spaghetti_detection_caption1, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); line_sizer->Add( spaghetti_detection_level_list, 0, wxEXPAND|wxALL, FromDIP(5) ); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); - line1 = new StaticLine(parent, false); + /* line1 = new StaticLine(parent, false); line1->SetLineColour(STATIC_BOX_LINE_COL); - sizer->Add(line1, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); - spaghetti_bottom_space = sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); + sizer->Add(line1, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18));*/ + spaghetti_bottom_space = ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); //purge chute pile-up detection line_sizer = new wxBoxSizer(wxHORIZONTAL); - m_cb_purgechutepileup_detection = new CheckBox(parent); - text_purgechutepileup_detection = new Label(parent, _L("Purge Chute Pile-Up Detection")); + m_cb_purgechutepileup_detection = new CheckBox(ai_refine_panel); + text_purgechutepileup_detection = new Label(ai_refine_panel, _L("Purge Chute Pile-Up Detection")); text_purgechutepileup_detection->SetFont(Label::Body_14); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(m_cb_purgechutepileup_detection, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); line_sizer->Add(text_purgechutepileup_detection, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_purgechutepileup_detection_caption0 = new Label(parent, _L("Monitor if the waste is piled up in the purge chute.")); + text_purgechutepileup_detection_caption0 = new Label(ai_refine_panel, _L("Monitor if the waste is piled up in the purge chute.")); text_purgechutepileup_detection_caption0->SetFont(Label::Body_12); text_purgechutepileup_detection_caption0->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_purgechutepileup_detection_caption0->Wrap(-1); line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_purgechutepileup_detection_caption0, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_purgechutepileup_detection_caption1 = new Label(parent, _L("Pausing Sensitivity:")); + text_purgechutepileup_detection_caption1 = new Label(ai_refine_panel, _L("Pausing Sensitivity:")); text_purgechutepileup_detection_caption1->SetFont(Label::Body_12); text_purgechutepileup_detection_caption1->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_purgechutepileup_detection_caption1->Wrap(-1); - purgechutepileup_detection_level_list = new ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); + purgechutepileup_detection_level_list = new ComboBox(ai_refine_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) { wxString level_option = sensitivity_level_to_label_string(i); purgechutepileup_detection_level_list->Append(level_option); @@ -681,37 +691,38 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_purgechutepileup_detection_caption1, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); line_sizer->Add(purgechutepileup_detection_level_list, 0, wxEXPAND | wxALL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); - purgechutepileup_bottom_space = sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + purgechutepileup_bottom_space = ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); //nozzle clumping detection line_sizer = new wxBoxSizer(wxHORIZONTAL); - m_cb_nozzleclumping_detection = new CheckBox(parent); - text_nozzleclumping_detection = new Label(parent, _L("Nozzle Clumping Detection")); + m_cb_nozzleclumping_detection = new CheckBox(ai_refine_panel); + text_nozzleclumping_detection = new Label(ai_refine_panel, _L("Nozzle Clumping Detection")); text_nozzleclumping_detection->SetFont(Label::Body_14); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(m_cb_nozzleclumping_detection, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); line_sizer->Add(text_nozzleclumping_detection, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); /* sizer->Add(0, 0, 0, wxTOP, FromDIP(10));*/ - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_nozzleclumping_detection_caption0 = new Label(parent, _L("Check if the nozzle is clumping by filaments or other foreign objects.")); + text_nozzleclumping_detection_caption0 = new Label(ai_refine_panel, _L("Check if the nozzle is clumping by filaments or other foreign objects.")); text_nozzleclumping_detection_caption0->SetFont(Label::Body_12); text_nozzleclumping_detection_caption0->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_nozzleclumping_detection_caption0->Wrap(-1); line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_nozzleclumping_detection_caption0, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_nozzleclumping_detection_caption1 = new Label(parent, _L("Pausing Sensitivity:")); + text_nozzleclumping_detection_caption1 = new Label(ai_refine_panel, _L("Pausing Sensitivity:")); text_nozzleclumping_detection_caption1->SetFont(Label::Body_12); text_nozzleclumping_detection_caption1->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_nozzleclumping_detection_caption1->Wrap(-1); - nozzleclumping_detection_level_list = new ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); + nozzleclumping_detection_level_list = new ComboBox(ai_refine_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) { wxString level_option = sensitivity_level_to_label_string(i); nozzleclumping_detection_level_list->Append(level_option); @@ -721,37 +732,37 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_nozzleclumping_detection_caption1, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); line_sizer->Add(nozzleclumping_detection_level_list, 0, wxEXPAND | wxALL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); - nozzleclumping_bottom_space = sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + nozzleclumping_bottom_space = ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); //air printing detection line_sizer = new wxBoxSizer(wxHORIZONTAL); - m_cb_airprinting_detection = new CheckBox(parent); - text_airprinting_detection = new Label(parent, _L("Air Printing Detection")); + m_cb_airprinting_detection = new CheckBox(ai_refine_panel); + text_airprinting_detection = new Label(ai_refine_panel, _L("Air Printing Detection")); text_airprinting_detection->SetFont(Label::Body_14); line_sizer->Add(FromDIP(5), 0, 0, 0); line_sizer->Add(m_cb_airprinting_detection, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); line_sizer->Add(text_airprinting_detection, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); /* sizer->Add(0, 0, 0, wxTOP, FromDIP(12));*/ - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_airprinting_detection_caption0 = new Label(parent, _L("Detects air printing caused by nozzle clogging or filament grinding.")); + text_airprinting_detection_caption0 = new Label(ai_refine_panel, _L("Detects air printing caused by nozzle clogging or filament grinding.")); text_airprinting_detection_caption0->SetFont(Label::Body_12); text_airprinting_detection_caption0->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_airprinting_detection_caption0->Wrap(-1); line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_airprinting_detection_caption0, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); line_sizer = new wxBoxSizer(wxHORIZONTAL); - text_airprinting_detection_caption1 = new Label(parent, _L("Pausing Sensitivity:")); + text_airprinting_detection_caption1 = new Label(ai_refine_panel, _L("Pausing Sensitivity:")); text_airprinting_detection_caption1->SetFont(Label::Body_12); text_airprinting_detection_caption1->SetForegroundColour(STATIC_TEXT_CAPTION_COL); text_airprinting_detection_caption1->Wrap(-1); - airprinting_detection_level_list = new ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); + airprinting_detection_level_list = new ComboBox(ai_refine_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(100), -1), 0, NULL, wxCB_READONLY); for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) { wxString level_option = sensitivity_level_to_label_string(i); airprinting_detection_level_list->Append(level_option); @@ -761,12 +772,17 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) line_sizer->Add(FromDIP(30), 0, 0, 0); line_sizer->Add(text_airprinting_detection_caption1, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); line_sizer->Add(airprinting_detection_level_list, 0, wxEXPAND | wxALL, FromDIP(5)); - sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); - airprinting_bottom_space = sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); + ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + airprinting_bottom_space = ai_refine_sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); - //m_line = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(1)), wxTAB_TRAVERSAL); - //m_line->SetBackgroundColour(wxColour(166, 169, 170)); - //sizer->Add(m_line, 0, wxEXPAND | wxALL, FromDIP(20)); + ai_refine_panel->SetSizer(ai_refine_sizer); + sizer->Add(ai_refine_panel, 0, wxEXPAND | wxRIGHT, FromDIP(18)); + + // sizer->Add(line1, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18)); + + m_line = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(400), FromDIP(1))); + m_line->SetBackgroundColour(wxColour("#A6A9AA")); + sizer->Add(m_line, 0, wxLEFT | wxBOTTOM, FromDIP(20)); // detection of build plate position line_sizer = new wxBoxSizer(wxHORIZONTAL); @@ -831,7 +847,7 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) line_sizer->Add(FromDIP(5), 0, 0, 0); line4 = new StaticLine(parent, false); - line4->SetLineColour(wxColour(255,255,255)); + line4->SetLineColour(wxColour("#FFFFFF")); sizer->Add(line4, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20)); line4->Hide(); sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); @@ -839,7 +855,7 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) //Open Door Detection line_sizer = new wxBoxSizer(wxHORIZONTAL); m_cb_open_door = new CheckBox(parent); - text_open_door = new Label(parent, _L("Open Door Dectection")); + text_open_door = new Label(parent, _L("Open Door Detection")); text_open_door->SetFont(Label::Body_14); open_door_switch_board = new SwitchBoard(parent, _L("Notification"), _L("Pause printing"), wxSize(FromDIP(200), FromDIP(26))); open_door_switch_board->Disable(); @@ -1068,7 +1084,7 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) /*single nozzle*/ auto single_line = new wxPanel(single_panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); - single_line->SetBackgroundColour(wxColour(166, 169, 170)); + single_line->SetBackgroundColour(wxColour("#A6A9AA")); //nozzle type wxBoxSizer* line_sizer_nozzle_type = new wxBoxSizer(wxHORIZONTAL); @@ -1124,7 +1140,7 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) m_wiki_link = new Label(single_panel, _L("View wiki")); m_wiki_link->SetFont(Label::Body_13); - m_wiki_link->SetForegroundColour(wxColour(0, 174, 66)); + m_wiki_link->SetForegroundColour(wxColour("#4479FB")); m_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); m_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); m_wiki_link->Bind(wxEVT_LEFT_DOWN, &PrinterPartsDialog::OnWikiClicked, this); @@ -1149,7 +1165,7 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) /*multiple nozzle*/ auto multi_line = new wxPanel(multiple_panel, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); - multi_line->SetBackgroundColour(wxColour(166, 169, 170)); + multi_line->SetBackgroundColour(wxColour("#A6A9AA")); /*left*/ auto leftTitle = new Label(multiple_panel, _L("Left Nozzle")); @@ -1225,7 +1241,7 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) multiple_wiki_link = new Label(multiple_panel, _L("View wiki")); multiple_wiki_link->SetFont(Label::Body_13); - multiple_wiki_link->SetForegroundColour(wxColour(68, 121, 251)); + multiple_wiki_link->SetForegroundColour(wxColour("#4479FB")); multiple_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); multiple_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); multiple_wiki_link->Bind(wxEVT_LEFT_DOWN, &PrinterPartsDialog::OnWikiClicked, this); @@ -1273,14 +1289,14 @@ bool PrinterPartsDialog::Show(bool show) /*disable editing*/ EnableEditing(false); - assert(DeviceManager::get_printer_can_set_nozzle(obj->printer_type) == false);/*editing is not supported*/ + assert(DevPrinterConfigUtil::get_printer_can_set_nozzle(obj->printer_type) == false);/*editing is not supported*/ - if (obj->m_extder_data.extders.size() <= 1) { + if (obj->GetExtderSystem()->GetTotalExtderSize() <= 1) { single_panel->Show(); multiple_panel->Hide(); - auto type = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_type; - auto diameter = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_diameter; + auto type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID); + auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID); nozzle_type_checkbox->SetValue(GetString(type)); nozzle_diameter_checkbox->SetValue(GetString(diameter)); @@ -1289,7 +1305,7 @@ bool PrinterPartsDialog::Show(bool show) nozzle_flow_type_checkbox->Show(obj->is_nozzle_flow_type_supported()); if (obj->is_nozzle_flow_type_supported()) { - auto flow_type = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_flow_type; + auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID); nozzle_flow_type_checkbox->SetValue(GetString(flow_type)); } } else { @@ -1297,17 +1313,17 @@ bool PrinterPartsDialog::Show(bool show) multiple_panel->Show(); //left - auto type = obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].current_nozzle_type; - auto diameter = obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].current_nozzle_diameter; - auto flow_type = obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].current_nozzle_flow_type; + auto type = obj->GetExtderSystem()->GetNozzleType(DEPUTY_EXTRUDER_ID); + auto diameter = obj->GetExtderSystem()->GetNozzleDiameter(DEPUTY_EXTRUDER_ID); + auto flow_type = obj->GetExtderSystem()->GetNozzleFlowType(DEPUTY_EXTRUDER_ID); multiple_left_nozzle_type_checkbox->SetValue(GetString(type)); multiple_left_nozzle_diameter_checkbox->SetValue(GetString(diameter)); multiple_left_nozzle_flow_checkbox->SetValue(GetString(flow_type)); //right - type = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_type; - diameter = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_diameter; - flow_type = obj->m_extder_data.extders[MAIN_NOZZLE_ID].current_nozzle_flow_type; + type = obj->GetExtderSystem()->GetNozzleType(MAIN_EXTRUDER_ID); + diameter = obj->GetExtderSystem()->GetNozzleDiameter(MAIN_EXTRUDER_ID); + flow_type = obj->GetExtderSystem()->GetNozzleFlowType(MAIN_EXTRUDER_ID); multiple_right_nozzle_type_checkbox->SetValue(GetString(type)); multiple_right_nozzle_diameter_checkbox->SetValue(GetString(diameter)); multiple_right_nozzle_flow_checkbox->SetValue(GetString(flow_type)); diff --git a/src/slic3r/GUI/PrintOptionsDialog.hpp b/src/slic3r/GUI/PrintOptionsDialog.hpp index d3cea23..fed37e0 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.hpp +++ b/src/slic3r/GUI/PrintOptionsDialog.hpp @@ -87,7 +87,7 @@ protected: Label* text_first_layer; Label* text_ai_detections; Label* text_ai_detections_caption; - + wxPanel *ai_refine_panel; wxSizerItem *ai_detections_bottom_space; wxSizerItem *ai_monitoring_bottom_space; wxSizerItem *spaghetti_bottom_space; @@ -136,6 +136,7 @@ protected: StaticLine* line7; SwitchBoard* open_door_switch_board; wxBoxSizer* create_settings_group(wxWindow* parent); + wxPanel *m_line; bool print_halt = false; diff --git a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp index 8a52ede..308a12c 100644 --- a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp +++ b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp @@ -388,10 +388,8 @@ void PrinterFileSystem::DownloadRamFile(int index, const std::string &local_path if (result == SUCCESS) { if (std::filesystem::exists(download->local_path)) { m_download_states.emplace_back(true); - //BOOST_LOG_TRIVIAL(info) <<"DownloadImageFromRam finished: " << download->local_path << "result = " << result; }else{ m_download_states.emplace_back(false); - //BOOST_LOG_TRIVIAL(warning) <<"DownloadImageFromRam finished, but file not exist: " << download->local_path << "result = " << result; } } else if (result != CONTINUE) { m_download_states.emplace_back(false); @@ -704,6 +702,7 @@ void PrinterFileSystem::Stop(bool quit) } m_stopped = true; m_cond.notify_all(); + } void PrinterFileSystem::SetUploadFile(const std::string &path, const std::string &name, const std::string &select_storage) @@ -865,7 +864,7 @@ void PrinterFileSystem::DownloadNextFile() const auto char_digest = reinterpret_cast(&digest[0]); boost::algorithm::hex(char_digest, char_digest + sizeof(digest), std::back_inserter(str_md5)); if (!boost::iequals(str_md5, md5)) { - BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::DownloadNextFile checksum error: " << str_md5 << "!=" << md5; + BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::DownloadNextFile checksum error: str_md5 != md5" ; boost::system::error_code ec; boost::filesystem::rename(download->local_path, download->local_path + ".tmp", ec); result = FILE_CHECK_ERR; @@ -1327,7 +1326,7 @@ int PrinterFileSystem::UploadFileTask(std::shared_ptr upload_file, b if (!upload->ifs.is_open()) { upload->ifs.open(upload_file->path, std::ios::binary); if (!upload_file->upload->ifs) { - BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::UploadFile open error."; + BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::UploadFile open error1."; return FILE_OPEN_ERR; } MD5_Init(&upload->ctx); @@ -1341,7 +1340,7 @@ int PrinterFileSystem::UploadFileTask(std::shared_ptr upload_file, b boost::int32_t read_size = upload->ifs.gcount(); if (read_size <= 0) { - BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::UploadFile open error."; + BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::UploadFile open error2."; upload->ifs.close(); if (buffer) { @@ -1508,7 +1507,9 @@ void PrinterFileSystem::CancelRequests2(std::vector const &seqs } l.unlock(); for (auto &c : callbacks) { +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "PrinterFileSystem::CancelRequests2:" << c.first; +#endif c.second(ERROR_CANCEL, json(), nullptr); } } @@ -1818,7 +1819,9 @@ static void* get_function(const char* name) #endif if (!function) { +#if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find function %1%") % name; +#endif } return function; } diff --git a/src/slic3r/GUI/PrinterWebView.cpp b/src/slic3r/GUI/PrinterWebView.cpp index 5813ce6..7032016 100644 --- a/src/slic3r/GUI/PrinterWebView.cpp +++ b/src/slic3r/GUI/PrinterWebView.cpp @@ -421,7 +421,12 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) if (webisNetMode == isNetWeb) { for (DeviceButton* button : m_net_buttons) { - if (button->getIPLabel() == m_ip) { + wxString button_ip = button->getIPLabel(); + if (button_ip.Lower().starts_with("http")) + button_ip.Remove(0, 7); + if (button_ip.Lower().ends_with("10088")) + button_ip.Remove(button_ip.length() - 6); + if (button_ip == m_ip) { button->SetIsSelected(true); break; } @@ -1023,7 +1028,12 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) for (DeviceButton *button : m_buttons) { //y31 - if (button->getIPLabel() == m_ip) + wxString button_ip = button->getIPLabel(); + if (button_ip.Lower().starts_with("http")) + button_ip.Remove(0, 7); + if (button_ip.Lower().ends_with("10088")) + button_ip.Remove(button_ip.length() - 6); + if (button_ip == m_ip) button->SetIsSelected(true); else button->SetIsSelected(false); @@ -1050,7 +1060,12 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) } for (DeviceButton *button : m_net_buttons) { - if (m_ip == button->getIPLabel()) + wxString button_ip = button->getIPLabel(); + if (button_ip.Lower().starts_with("http")) + button_ip.Remove(0, 7); + if (button_ip.Lower().ends_with("10088")) + button_ip.Remove(button_ip.length() - 6); + if (m_ip == button_ip) button->SetIsSelected(true); else button->SetIsSelected(false); diff --git a/src/slic3r/GUI/ReleaseNote.cpp b/src/slic3r/GUI/ReleaseNote.cpp index 556f47c..cbbba70 100644 --- a/src/slic3r/GUI/ReleaseNote.cpp +++ b/src/slic3r/GUI/ReleaseNote.cpp @@ -18,10 +18,14 @@ #include #include #include +#include #include #include "Plater.hpp" #include "BitmapCache.hpp" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevStorage.h" + namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CONFIRM, wxCommandEvent); @@ -1062,17 +1066,31 @@ void PrintErrorDialog::update_title_style(wxString title, std::vector butto m_button_list[used_button_id]->Hide(); } } + m_sizer_button->Clear(); m_used_button = button_style; + bool need_remove_close_btn = false; for (int button_id : button_style) { if (m_button_list.find(button_id) != m_button_list.end()) { m_sizer_button->Add(m_button_list[button_id], 0, wxALL, FromDIP(5)); m_button_list[button_id]->Show(); } + + need_remove_close_btn |= (button_id == REMOVE_CLOSE_BTN); // special case, do not show close button } + + // Special case, do not show close button + if (need_remove_close_btn) + { + SetWindowStyle(GetWindowStyle() & ~wxCLOSE_BOX); + } + else + { + SetWindowStyle(GetWindowStyle() | wxCLOSE_BOX); + } + Layout(); Fit(); - } void PrintErrorDialog::init_button(PrintErrorButton style,wxString buton_text) @@ -1127,9 +1145,9 @@ void PrintErrorDialog::init_button_list() init_button(PROBLEM_SOLVED_RESUME, _L("Problem Solved and Resume")); - init_button(STOP_BUZZER, _L("Stop Buzzer")); - + init_button(TURN_OFF_FIRE_ALARM, _L("Got it, Turn off the Fire Alarm.")); init_button(RETRY_PROBLEM_SOLVED, _L("Retry (problem solved)")); + init_button(STOP_DRYING, _L("Stop Drying")); } PrintErrorDialog::~PrintErrorDialog() @@ -1587,9 +1605,9 @@ InputIpAddressDialog::InputIpAddressDialog(wxWindow *parent) m_input_modelID->SetMinSize(wxSize(FromDIP(168), FromDIP(28))); m_input_modelID->SetMaxSize(wxSize(FromDIP(168), FromDIP(28))); - m_models_map = DeviceManager::get_all_model_id_with_name(); + m_models_map = DevPrinterConfigUtil::get_all_model_id_with_name(); for (auto it = m_models_map.begin(); it != m_models_map.end(); ++it) { - m_input_modelID->Append(it->right); + m_input_modelID->Append(it->first); m_input_modelID->SetSelection(0); } @@ -1815,10 +1833,10 @@ void InputIpAddressDialog::update_title(wxString title) void InputIpAddressDialog::set_machine_obj(MachineObject* obj) { m_obj = obj; - m_input_ip->GetTextCtrl()->SetLabelText(m_obj->dev_ip); + m_input_ip->GetTextCtrl()->SetLabelText(m_obj->get_dev_ip()); m_input_access_code->GetTextCtrl()->SetLabelText(m_obj->get_access_code()); - std::string img_str = DeviceManager::get_printer_diagram_img(m_obj->printer_type); + std::string img_str = DevPrinterConfigUtil::get_printer_connect_help_img(m_obj->printer_type); auto diagram_bmp = create_scaled_bitmap(img_str + "_en", this, 198); m_img_help->SetBitmap(diagram_bmp); @@ -1898,9 +1916,9 @@ void InputIpAddressDialog::on_ok(wxMouseEvent& evt) std::string str_sn = m_input_sn->GetTextCtrl()->GetValue().ToStdString(); std::string str_model_id = ""; - auto it = m_models_map.right.find(m_input_modelID->GetStringSelection().ToStdString()); - if (it != m_models_map.right.end()) { - str_model_id = it->get_left(); + auto it = m_models_map.find(m_input_modelID->GetStringSelection().ToStdString()); + if (it != m_models_map.end()) { + str_model_id = it->second; } m_button_ok->Enable(false); @@ -1961,7 +1979,7 @@ void InputIpAddressDialog::on_send_retry() } }); - m_send_job = std::make_shared(m_status_bar, wxGetApp().plater(), m_obj->dev_id); + m_send_job = std::make_shared(m_status_bar, wxGetApp().plater(), m_obj->get_dev_id()); m_send_job->m_dev_ip = ip.ToStdString(); m_send_job->m_access_code = str_access_code.ToStdString(); @@ -1975,7 +1993,7 @@ void InputIpAddressDialog::on_send_retry() m_send_job->connection_type = m_obj->connection_type(); m_send_job->cloud_print_only = true; - m_send_job->has_sdcard = m_obj->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL; + m_send_job->has_sdcard = m_obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL; m_send_job->set_check_mode(); m_send_job->set_project_name("verify_job"); @@ -2077,14 +2095,15 @@ void InputIpAddressDialog::workerThreadFunc(std::string str_ip, std::string str_ DeviceManager* dev = wxGetApp().getDeviceManager(); - m_obj = dev->insert_local_device(detectData.dev_name, detectData.dev_id, str_ip, detectData.connect_type, detectData.bind_state, detectData.version, str_access_code); - + m_obj = dev->insert_local_device(detectData.dev_name, detectData.dev_id, str_ip, + detectData.connect_type, detectData.bind_state, detectData.version, + str_access_code, detectData.model_id); if (w.expired()) return; if (m_obj) { m_obj->set_user_access_code(str_access_code); - wxGetApp().getDeviceManager()->set_selected_machine(m_obj->dev_id); + wxGetApp().getDeviceManager()->set_selected_machine(m_obj->get_dev_id()); } @@ -2277,4 +2296,381 @@ void InputIpAddressDialog::on_dpi_changed(const wxRect& suggested_rect) void SendFailedConfirm::on_dpi_changed(const wxRect &suggested_rect) {} + + HelioStatementDialog::HelioStatementDialog(wxWindow *parent /*= nullptr*/) + : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("Enable Helio"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + SetBackgroundColour(*wxWHITE); + + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + + wxPanel* line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + line->SetBackgroundColour(wxColour(166, 169, 170)); + + + + m_title = new Label(this, Label::Head_14, _L("Terms of Service")); + //m_title->SetForegroundColour(wxColour(0x26, 0x2E, 0x30)); + + + + Label* m_description_line1 = new Label(this, Label::Body_13, + _L("You are about to enable a third-party software service feature from Helio Additive! Before confirming the use of this feature, please carefully read the following statements.")); + //m_description_line1->SetForegroundColour(wxColour(144, 144, 144)); + m_description_line1->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line1->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line1->Wrap(FromDIP(680)); + + Label *m_description_line2 = new Label(this, Label::Body_13, + _L("Unless otherwise specified, QIDI Tech only provides support for the software features officially provided. The slicing evaluation and slicing optimization features based on Helio Additive's cloud service in this software will be developed, operated, provided, and maintained by Helio Additive. Helio Additive is responsible for the effectiveness and availability of this service. The optimization feature of this service may modify the default print commands, posing a risk of printer damage. These features will collect necessary user information and data to achieve relevant service functions. Subscriptions and payments may be involved. Please visit Helio Additive and refer to the Helio Additive Privacy Agreement and the Helio Additive User Agreement for detailed information.")); + + Label* m_description_line3 = new Label(this, Label::Body_13, + _L("Meanwhile, you understand that this product is provided to you \"as is\" based on Helio Additive's services, and QIDI makes no express or implied warranties of any kind, nor can it control the service effects. To the fullest extent permitted by applicable law, QIDI or its licensors/affiliates do not provide any express or implied representations or warranties, including but not limited to warranties regarding merchantability, satisfactory quality, fitness for a particular purpose, accuracy, confidentiality, and non-infringement of third-party rights. Due to the nature of network services, QIDI cannot guarantee that the service will be available at all times, and QIDI reserves the right to terminate the service based on relevant circumstances.")); + + Label* m_description_line4 = new Label(this, Label::Body_13, + _L("You agree not to use this product and its related updates to engage in the following activities:")); + + Label* m_description_line5 = new Label(this, Label::Body_13, + _L("1.Copy or use any part of this product outside the authorized scope of Helio Additive and QIDI.")); + + Label* m_description_line6 = new Label(this, Label::Body_13, + _L("2.Attempt to disrupt, bypass, alter, invalidate, or evade any Digital Rights Management system related to and/or an integral part of this product.")); + + Label* m_description_line7 = new Label(this, Label::Body_13, + _L("3.Using this software and services for any improper or illegal activities.")); + + m_description_line2->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line2->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line2->Wrap(FromDIP(680)); + + m_description_line3->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line3->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line3->Wrap(FromDIP(680)); + + m_description_line4->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line4->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line4->Wrap(FromDIP(680)); + + m_description_line5->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line5->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line5->Wrap(FromDIP(680)); + + m_description_line6->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line6->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line6->Wrap(FromDIP(680)); + + m_description_line7->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line7->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line7->Wrap(FromDIP(680)); + + auto helio_home_link = new LinkLabel(this, _L("https://www.helioadditive.com/"), "https://www.helioadditive.com/"); + LinkLabel* helio_privacy_link = nullptr; + LinkLabel* helio_tou_link = nullptr; + + if (GUI::wxGetApp().app_config->get("region") == "China") { + helio_privacy_link = new LinkLabel(this, _L("Privacy Policy of Helio Additive"), "https://www.helioadditive.com/zh-cn/policies/privacy"); + helio_tou_link = new LinkLabel(this, _L("Terms of Use of Helio Additive"), "https://www.helioadditive.com/zh-cn/policies/terms"); + } + else { + helio_privacy_link = new LinkLabel(this, _L("Privacy Policy of Helio Additive"), "https://www.helioadditive.com/en-us/policies/privacy"); + helio_tou_link = new LinkLabel(this, _L("Terms of Use of Helio Additive"), "https://www.helioadditive.com/en-us/policies/terms"); + } + + + helio_home_link->SeLinkLabelFColour(wxColour(0, 119, 250)); + helio_privacy_link->SeLinkLabelFColour(wxColour(0, 119, 250)); + helio_tou_link->SeLinkLabelFColour(wxColour(0, 119, 250)); + + helio_home_link->getLabel()->SetFont(::Label::Body_13); + helio_privacy_link->getLabel()->SetFont(::Label::Body_13); + helio_tou_link->getLabel()->SetFont(::Label::Body_13); + + Label *m_description_line8 = + new Label(this, Label::Body_13, + _L("When you confirm to enable this feature, it means that you have confirmed and agreed to the above statements.")); + m_description_line8->SetMinSize(wxSize(FromDIP(680), -1)); + m_description_line8->SetMaxSize(wxSize(FromDIP(680), -1)); + m_description_line8->Wrap(FromDIP(680)); + + + + wxBoxSizer *button_sizer; + + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + + StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + + m_button_confirm = new Button(this, _L("Agree")); + m_button_confirm->SetBackgroundColor(btn_bg_green); + m_button_confirm->SetBorderColor(*wxWHITE); + m_button_confirm->SetTextColor(wxColour(255, 255, 254)); + m_button_confirm->SetFont(Label::Body_12); + m_button_confirm->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_confirm->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_confirm->SetCornerRadius(FromDIP(12)); + m_button_confirm->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_OK); }); + + m_button_cancel = new Button(this, _L("Cancel")); + m_button_cancel->SetBackgroundColor(btn_bg_white); + m_button_cancel->SetBorderColor(*wxWHITE); + 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_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_NO); }); + + + button_sizer = new wxBoxSizer(wxHORIZONTAL); + button_sizer->Add(0, 0, 1, wxEXPAND, 0); + button_sizer->Add(m_button_confirm, 0, 0, 0); + button_sizer->Add(0, 0, 0, wxLEFT, FromDIP(20)); + button_sizer->Add(m_button_cancel, 0, 0, 0); + button_sizer->Add(0, 0, 0, wxRIGHT, FromDIP(50)); + + main_sizer->Add(line, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(m_title, 0, wxALIGN_CENTER, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(14)); + main_sizer->Add(m_description_line1, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + main_sizer->Add(m_description_line2, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + main_sizer->Add(m_description_line3, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(m_description_line4, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(m_description_line5, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(8)); + main_sizer->Add(m_description_line6, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(8)); + main_sizer->Add(m_description_line7, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(m_description_line8, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(helio_home_link, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5)); + main_sizer->Add(helio_privacy_link, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5)); + main_sizer->Add(helio_tou_link, 0, wxLEFT | wxRIGHT, FromDIP(50)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + main_sizer->Add(button_sizer, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + + SetSizer(main_sizer); + Layout(); + Fit(); + + CentreOnParent(); + wxGetApp().UpdateDlgDarkUI(this); + } + +void HelioStatementDialog::on_dpi_changed(const wxRect &suggested_rect) +{ +} + + HelioInputDialog::HelioInputDialog(wxWindow *parent /*= nullptr*/) + : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("Helio Additive"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + SetBackgroundColour(*wxWHITE); + + wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *item_sizer = new wxBoxSizer(wxHORIZONTAL); + + wxPanel *line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + line->SetBackgroundColour(wxColour(166, 169, 170)); + + Label* inout_title = new Label(this, Label::Body_13, _L("Chamber temperature")); + inout_title->SetFont(::Label::Head_14); + Label *temp_icon = new Label(this, Label::Body_13, wxT("\u00B0C")); + temp_icon->SetFont(::Label::Body_14); + + m_input_item = new ::TextInput(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(120), -1), wxTE_PROCESS_ENTER); + StateColor input_bg(std::pair(wxColour("#F0F0F1"), StateColor::Disabled), std::pair(*wxWHITE, StateColor::Enabled)); + m_input_item->SetBackgroundColor(input_bg); + wxTextValidator validator(wxFILTER_NUMERIC); + m_input_item->GetTextCtrl()->SetValidator(validator); + m_input_item->GetTextCtrl()->SetHint(wxT("5-70")); + m_input_item->GetTextCtrl()->SetMaxLength(10); + m_input_item->GetTextCtrl()->SetWindowStyle(wxTE_RIGHT); + + item_sizer->Add(inout_title, 0, wxCENTER, 0); + item_sizer->Add(0, 0, 1, wxEXPAND, 0); + item_sizer->Add(m_input_item, 0, wxCENTER, 0); + item_sizer->Add(temp_icon, 0, wxCENTER, 0); + + Label *sub = new Label(this, _L("Note: Please set the above temperature according to the actual situation. The more accurate the data is, the more precise the analysis results will be.")); + sub->SetForegroundColour(wxColour(144, 144, 144)); + sub->SetMinSize(wxSize(FromDIP(420), -1)); + sub->SetMinSize(wxSize(FromDIP(420), -1)); + sub->Wrap(FromDIP(420)); + + auto helio_wiki_link = new LinkLabel(this, _L("How to use Helio"), "https://wiki.helioadditive.com/"); + helio_wiki_link->SeLinkLabelFColour(wxColour(0, 174, 66)); + + helio_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); }); + helio_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_ARROW); }); + + wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + + + m_button_confirm = new Button(this, _L("Confirm")); + m_button_confirm->SetBackgroundColor(btn_bg_green); + m_button_confirm->SetBorderColor(*wxWHITE); + m_button_confirm->SetTextColor(wxColour(255, 255, 254)); + m_button_confirm->SetFont(Label::Body_12); + m_button_confirm->SetSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_confirm->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); + m_button_confirm->SetCornerRadius(FromDIP(12)); + m_button_confirm->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { + wxString s = m_input_item->GetTextCtrl()->GetValue(); + double val = 0.0; + if (s.ToDouble(&val)) { + + double clamped = val; + if (val < 5.0) clamped = 5.0; + if (val > 70.0) clamped = 70.0; + + if (clamped != val) { + m_isAdjusting = true; + m_input_item->GetTextCtrl()->SetValue(wxString::Format("%.2f", clamped)); + m_input_item->GetTextCtrl()->SetInsertionPointEnd(); + } + } + EndModal(wxID_OK); + }); + + button_sizer->Add(0, 0, 1, wxEXPAND, 0); + button_sizer->Add(m_button_confirm, 0, 0, 0); + button_sizer->Add(0, 0, 0, wxLEFT, FromDIP(40)); + + main_sizer->Add(line, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(item_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(sub, 0, wxLEFT | wxRIGHT, FromDIP(30)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(12)); + main_sizer->Add(helio_wiki_link, 0, wxLEFT | wxRIGHT, FromDIP(30)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + main_sizer->Add(button_sizer, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(16)); + + SetSizer(main_sizer); + Layout(); + Fit(); + + CentreOnParent(); + wxGetApp().UpdateDlgDarkUI(this); +} + +bool HelioInputDialog::IsValidFloat(const wxString &text) +{ + if (text.IsEmpty()) return true; + if (text.Length() == 1 && wxIsdigit(text[0])) { + int digit = text[0] - '0'; + return digit >= 5 && digit <= 9; + } + + if (text == ".") return true; + double value; + if (!text.ToDouble(&value)) return false; + return value >= 5.0 && value <= 70.0; +} + +double HelioInputDialog::get_input_data() +{ + wxString value = m_input_item->GetTextCtrl()->GetValue(); + + if (value == "-" || value.IsEmpty()) { + return -1; + } + + double temp = 0; + if (is_number_regex(value, temp)) { + return temp; + } + + return -1; +} + +bool HelioInputDialog::is_number_regex(const wxString &str, double &value) +{ + std::string s = str.ToStdString(); + std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+$"); + + if (std::regex_match(s, pattern)) { + return str.ToDouble(&value); + } + + return false; +} + +void HelioInputDialog::on_dpi_changed(const wxRect &suggested_rect) {} + + +HelioPatNotEnoughDialog::HelioPatNotEnoughDialog(wxWindow* parent /*= nullptr*/) + : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, wxString("Helio Additive"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + wxPanel* line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + line->SetBackgroundColour(wxColour(166, 169, 170)); + + Label* text = new Label(this, Label::Body_13, _L("Failed to obtain Helio PAT. The number of issued PATs has reached the upper limit. Please pay attention to the information on the Helio official website. Click Refresh to get it again once it is available."), LB_AUTO_WRAP); + text->SetForegroundColour(wxColour("#6C6C6C")); + text->SetMinSize(wxSize(FromDIP(450), -1)); + text->SetMaxSize(wxSize(FromDIP(450), -1)); + text->Wrap(FromDIP(450)); + + auto helio_wiki_link = new LinkLabel(this, _L("Click for more details"), wxGetApp().app_config->get("language") == "zh_CN" ? "https://wiki.helioadditive.com/zh/home" : "https://wiki.helioadditive.com/en/home"); + helio_wiki_link->SeLinkLabelFColour(wxColour(0, 174, 66)); + helio_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); + helio_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); + + StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + + + auto sizer_button = new wxBoxSizer(wxHORIZONTAL); + auto m_button_ok = new Button(this, _L("Confirm")); + m_button_ok->SetBackgroundColor(btn_bg_green); + m_button_ok->SetBorderColor(*wxWHITE); + m_button_ok->SetTextColor(wxColour(255, 255, 254)); + 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)); + + sizer_button->AddStretchSpacer(); + sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5)); + + m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + EndModal(wxID_OK); + }); + + main_sizer->Add(line, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(26)); + main_sizer->Add(text, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + main_sizer->Add(helio_wiki_link, 0, wxLEFT | wxRIGHT, FromDIP(30)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + main_sizer->Add(sizer_button, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); + + SetSizer(main_sizer); + Layout(); + Fit(); +} + +HelioPatNotEnoughDialog::~HelioPatNotEnoughDialog() {} + +void HelioPatNotEnoughDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/ReleaseNote.hpp b/src/slic3r/GUI/ReleaseNote.hpp index dcaf225..76af3b2 100644 --- a/src/slic3r/GUI/ReleaseNote.hpp +++ b/src/slic3r/GUI/ReleaseNote.hpp @@ -35,6 +35,7 @@ #include "Widgets/CheckBox.hpp" #include "Widgets/ComboBox.hpp" #include "Widgets/ScrolledWindow.hpp" +#include "Widgets/LinkLabel.hpp" #include #include @@ -184,9 +185,11 @@ public: //LOAD_FILAMENT = 26, IGNORE_RESUME = 27, PROBLEM_SOLVED_RESUME = 28, - STOP_BUZZER = 29, + TURN_OFF_FIRE_ALARM = 29, RETRY_PROBLEM_SOLVED = 34, + STOP_DRYING = 35, + REMOVE_CLOSE_BTN = 39, // special case, do not show close button ERROR_BUTTON_COUNT }; @@ -331,7 +334,7 @@ public: int current_input_index {0}; std::shared_ptr m_send_job{nullptr}; std::shared_ptr m_status_bar; - boost::bimaps::bimap m_models_map; + std::map m_models_map;// display_name -> model_id void switch_input_panel(int index); void on_cancel(); @@ -361,6 +364,50 @@ public: void on_dpi_changed(const wxRect &suggested_rect) override; }; +class HelioStatementDialog : public DPIDialog +{ +private: + Label *m_title{nullptr}; + Button *m_button_confirm{nullptr}; + Button *m_button_cancel{nullptr}; + + +public: + HelioStatementDialog(wxWindow *parent = nullptr); + ~HelioStatementDialog(){}; + + // void on_ok(wxMouseEvent &evt); + void on_dpi_changed(const wxRect &suggested_rect) override; +}; + +class HelioInputDialog : public DPIDialog +{ +private: + TextInput *m_input_item{nullptr}; + Button *m_button_confirm{nullptr}; + bool m_isAdjusting = false; + wxString m_lastValidValue = wxEmptyString; + +public: + HelioInputDialog(wxWindow *parent = nullptr); + ~HelioInputDialog(){}; + + // void on_ok(wxMouseEvent &evt); + bool IsValidFloat(const wxString &text); + double get_input_data(); + bool is_number_regex(const wxString &str, double &value); + void on_dpi_changed(const wxRect &suggested_rect) override; +}; + +class HelioPatNotEnoughDialog : public DPIDialog +{ +public: + HelioPatNotEnoughDialog(wxWindow* parent = nullptr); + ~HelioPatNotEnoughDialog(); + void on_dpi_changed(const wxRect& suggested_rect) override; +}; + + wxDECLARE_EVENT(EVT_CLOSE_IPADDRESS_DLG, wxCommandEvent); wxDECLARE_EVENT(EVT_CHECKBOX_CHANGE, wxCommandEvent); wxDECLARE_EVENT(EVT_ENTER_IP_ADDRESS, wxCommandEvent); diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index a3e54f1..46411ec 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -16,7 +16,16 @@ #include "ConnectPrinter.hpp" #include "slic3r/Utils/QDTUtil.hpp" +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevNozzleSystem.h" +#include "DeviceCore/DevExtruderSystem.h" +#include "DeviceCore/DevFilaBlackList.h" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevMapping.h" +#include "DeviceCore/DevStorage.h" +#include "../Utils/QDTUtil.hpp" #include #include #include @@ -591,12 +600,18 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) auto option_timelapse = new PrintOption(m_options_other, _L("Timelapse"), wxEmptyString, ops_no_auto, "timelapse"); - //y60 - auto option_auto_bed_level = new PrintOption( + //y60 + auto option_auto_bed_level = new PrintOption( m_options_other, _L("Auto Bed Leveling"), _L("This checks the flatness of heatbed. Leveling makes extruded height uniform.\n*Automatic mode: Run a leveling check(about 10 seconds). Skip if surface is fine."), ops_no_auto, "bed_leveling"); + //y71 + auto option_enable_multi_box = new PrintOption( + m_options_other, _L("Enable Box"), + _L("Activate the multi-color box for multi-color printing with multiple filaments."), + ops_no_auto, "enable_multi_box"); + auto option_flow_dynamics_cali = new PrintOption(m_options_other, _L("Flow Dynamics Calibration"), _L("This process determines the dynamic flow values to improve overall print quality.\n*Automatic mode: Skip if the filament was calibrated recently."), @@ -612,11 +627,13 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) m_sizer_options = new wxGridSizer(0, 2, FromDIP(5), FromDIP(28)); m_sizer_options->Add(option_timelapse, 0, wxEXPAND); m_sizer_options->Add(option_auto_bed_level, 0, wxEXPAND); + m_sizer_options->Add(option_enable_multi_box, 0, wxEXPAND); m_sizer_options->Add(option_flow_dynamics_cali, 0, wxEXPAND); m_sizer_options->Add(option_nozzle_offset_cali_cali, 0, wxEXPAND); m_checkbox_list_order.push_back(option_timelapse); m_checkbox_list_order.push_back(option_auto_bed_level); + m_checkbox_list_order.push_back(option_enable_multi_box); m_checkbox_list_order.push_back(option_flow_dynamics_cali); m_checkbox_list_order.push_back(option_nozzle_offset_cali_cali); @@ -626,6 +643,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) m_checkbox_list["timelapse"] = option_timelapse; m_checkbox_list["bed_leveling"] = option_auto_bed_level; + m_checkbox_list["enable_multi_box"] = option_enable_multi_box; m_checkbox_list["flow_cali"] = option_flow_dynamics_cali; m_checkbox_list["nozzle_offset_cali"] = option_nozzle_offset_cali_cali; for (auto print_opt : m_checkbox_list_order) { @@ -633,6 +651,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) } option_auto_bed_level->Hide(); + option_enable_multi_box->Hide(); option_flow_dynamics_cali->Hide(); option_nozzle_offset_cali_cali->Hide(); //y59 @@ -852,9 +871,9 @@ void SelectMachineDialog::init_bind() // MachineObject* obj = dev->get_selected_machine(); // if (!obj) return; - // if (obj->dev_id == e.GetString()) { - // m_printer_box->SetPrinterName(wxString::FromUTF8(obj->dev_name) + "(LAN)"); - // } + // if (obj->get_dev_id() == e.GetString()) { + // m_printer_box->SetPrinterName(wxString::FromUTF8(obj->get_dev_name()) + "(LAN)"); + // } // } // }); @@ -931,7 +950,7 @@ void SelectMachineDialog::popup_filament_backup() //y61 AmsReplaceMaterialDialog* m_replace_material_popup = new AmsReplaceMaterialDialog(this); - m_replace_material_popup->update_to_nozzle(MAIN_NOZZLE_ID); + //m_replace_material_popup->update_to_nozzle(MAIN_NOZZLE_ID); m_replace_material_popup->ShowModal(); // DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); @@ -1060,14 +1079,14 @@ void SelectMachineDialog::sync_ams_mapping_result(std::vector &res } if (!f->color.empty()) { - ams_col = AmsTray::decode_color(f->color); + ams_col = DevAmsTray::decode_color(f->color); } else { // default color ams_col = wxColour(0xCE, 0xCE, 0xCE); } std::vector cols; for (auto col : f->colors) { - cols.push_back(AmsTray::decode_color(col)); + cols.push_back(DevAmsTray::decode_color(col)); } m->set_ams_info(ams_col, ams_id,f->ctype, cols); //y59 @@ -1105,7 +1124,7 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) if (!color.empty()) { color.erase(0, 1); color += "FF"; - auto box_color = AmsTray::decode_color(color); + auto box_color = DevAmsTray::decode_color(color); m_cur_colors_in_thumbnail.emplace_back(box_color); } } @@ -1142,14 +1161,14 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) } bool has_left_ams = false, has_right_ams = false; - for (auto ams_item : obj_->amsList) { - if (ams_item.second->nozzle == 0) { + for (auto ams_item : obj_->GetFilaSystem()->GetAmsList()) { + if (ams_item.second->GetExtruderId() == 0) { if (obj_->is_main_extruder_on_left()) has_left_ams = true; else has_right_ams = true; } - else if (ams_item.second->nozzle == 1) { + else if (ams_item.second->GetExtruderId() == 1) { if (obj_->is_main_extruder_on_left()) has_right_ams = true; else @@ -1165,13 +1184,13 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) map_opt[0] = false; map_opt[2] = true; } - int result_first = obj_->ams_filament_mapping(m_filament_left, m_ams_mapping_result_left, map_opt); + int result_first = DevMappingUtil::ams_filament_mapping(obj_, m_filament_left, m_ams_mapping_result_left, map_opt); map_opt = { false, true, false, !has_right_ams }; if (!use_ams) { map_opt[1] = false; map_opt[3] = true; } - int result_second = obj_->ams_filament_mapping(m_filament_right, m_ams_mapping_result_right, map_opt); + int result_second = DevMappingUtil::ams_filament_mapping(obj_, m_filament_right, m_ams_mapping_result_right, map_opt); //m_ams_mapping_result.clear(); m_ams_mapping_result.resize(m_ams_mapping_result_left.size() + m_ams_mapping_result_right.size()); @@ -1189,7 +1208,7 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) map_opt[0] = false; map_opt[1] = false; } - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt); + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt); } //When filaments cannot be matched automatically, whether to use ext for automatic supply //auto_supply_with_ext(obj_->vt_slot); @@ -1203,7 +1222,7 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) map_opt[1] = false; map_opt[3] = true; } - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt); + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt); //auto_supply_with_ext(obj_->vt_slot); } else { @@ -1212,7 +1231,7 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) map_opt[1] = false; map_opt[3] = true; } - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt); + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt); } } @@ -1234,10 +1253,12 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams) BOOST_LOG_TRIVIAL(info) << "ams_mapping_array2=" << ams_array2; BOOST_LOG_TRIVIAL(info) << "ams_mapping_info=" << mapping_info; } - return obj_->is_valid_mapping_result(m_ams_mapping_result); + // return DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result); + return true; } else { // do not support ams mapping try to use order mapping - bool is_valid = obj_->is_valid_mapping_result(m_ams_mapping_result); + // bool is_valid = DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result); + bool is_valid = true; if (filament_result != 1 && !is_valid) { //reset invalid result for (int i = 0; i < m_ams_mapping_result.size(); i++) { @@ -1416,22 +1437,22 @@ bool SelectMachineDialog::build_nozzles_info(std::string& nozzles_info) return true; } -bool SelectMachineDialog::can_hybrid_mapping(ExtderData data) { +bool SelectMachineDialog::can_hybrid_mapping(DevExtderSystem data) { // Mixed mappings are not allowed return false; - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; //The default two extruders are left, right, but the order of the extruders on the machine is right, left. //Therefore, some adjustments need to be made. std::vectorflow_type_of_machine; - for (auto it = data.extders.rbegin(); it != data.extders.rend(); it++){ - //exist field is not updated, wait add - //if (it->exist < 3) return false; - std::string type_str = it->current_nozzle_flow_type ? "High Flow" : "Standard"; + for (const auto& ext : data.GetExtruders()) + { + std::string type_str = ext.GetNozzleFlowType() == NozzleFlowType::H_FLOW ? "High Flow" : "Standard"; flow_type_of_machine.push_back(type_str); } + //get the nozzle type of preset --> flow_types const Preset& current_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); const Preset* base_printer = wxGetApp().preset_bundle->printers.get_preset_base(current_printer); @@ -1451,13 +1472,13 @@ bool SelectMachineDialog::can_hybrid_mapping(ExtderData data) { } //When filaments cannot be matched automatically, whether to use ext for automatic supply -void SelectMachineDialog::auto_supply_with_ext(std::vector slots) { +void SelectMachineDialog::auto_supply_with_ext(std::vector slots) { if (slots.size() <= 0) return; for (int i = 0; i < m_ams_mapping_result.size(); i++) { auto it = m_ams_mapping_result[i]; if (it.ams_id == "") { - AmsTray slot(""); + DevAmsTray slot(""); if (m_filaments_map[it.id] == 1 && slots.size() > 1) slot = slots[1]; else if (m_filaments_map[it.id] == 2) slot = slots[0]; if (slot.id.empty()) continue; @@ -1471,8 +1492,8 @@ void SelectMachineDialog::auto_supply_with_ext(std::vector slots) { } } -bool SelectMachineDialog::is_nozzle_type_match(ExtderData data, wxString& error_message) const { - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) +bool SelectMachineDialog::is_nozzle_type_match(DevExtderSystem data, wxString& error_message) const { + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; const auto& project_config = wxGetApp().preset_bundle->project_config; @@ -1502,10 +1523,14 @@ bool SelectMachineDialog::is_nozzle_type_match(ExtderData data, wxString& error_ // The default two extruders are left, right, but the order of the extruders on the machine is right, left. std::vector flow_type_of_machine; - for (auto it = data.extders.begin(); it != data.extders.end(); it++) { - if (it->current_nozzle_flow_type == NozzleFlowType::H_FLOW) { + for (const auto& it : data.GetExtruders()) + { + if (it.GetNozzleFlowType() == NozzleFlowType::H_FLOW) + { flow_type_of_machine.push_back(L("High Flow")); - } else if (it->current_nozzle_flow_type == NozzleFlowType::S_FLOW){ + } + else if (it.GetNozzleFlowType() == NozzleFlowType::S_FLOW) + { flow_type_of_machine.push_back(L("Standard")); } } @@ -1518,11 +1543,11 @@ bool SelectMachineDialog::is_nozzle_type_match(ExtderData data, wxString& error_ if (flow_type_of_machine[target_machine_nozzle_id] != used_extruders_flow[it->first]) { wxString pos; - if (target_machine_nozzle_id == DEPUTY_NOZZLE_ID) + if (target_machine_nozzle_id == DEPUTY_EXTRUDER_ID) { pos = _L("left nozzle"); } - else if(target_machine_nozzle_id == MAIN_NOZZLE_ID) + else if(target_machine_nozzle_id == MAIN_EXTRUDER_ID) { pos = _L("right nozzle"); } @@ -1583,7 +1608,7 @@ bool SelectMachineDialog::check_sdcard_for_timelpase(MachineObject* obj) // must set to a status if return true if (m_checkbox_list["timelapse"]->IsShown() && m_checkbox_list["timelapse"]->getValue() == "on") { - if (obj->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { show_status(PrintDialogStatus::PrintStatusTimelapseNoSdcard); return true; } @@ -1720,8 +1745,8 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vectorget_preset_printer_model_name(target_model_id)); - //target_print_name.Replace(wxT("QIDI Tech "), wxEmptyString); + // auto target_print_name = wxString(DevPrinterConfigUtil::get_printer_display_name(target_model_id)); + // target_print_name.Replace(wxT("QIDI Tech "), wxEmptyString); PresetBundle& preset_bundle = *wxGetApp().preset_bundle; std::string target_print_name = preset_bundle.printers.get_edited_preset().get_printer_type(&preset_bundle); msg_text = wxString::Format(_L("The selected printer (%s) is incompatible with the print file configuration (%s). Please adjust the printer preset in the prepare page or choose a compatible printer on this page."), select_machine.type, target_print_name); @@ -1873,7 +1898,7 @@ bool SelectMachineDialog::is_blocking_printing(MachineObject* obj_) } if (source_model != target_model) { - std::vector compatible_machine = dev->get_compatible_machine(target_model); + std::vector compatible_machine = obj_->get_compatible_machine(); vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); if (it == compatible_machine.end()) { return true; @@ -1907,7 +1932,7 @@ static std::unordered_set _get_used_nozzle_idxes() } -static bool _is_nozzle_data_valid(MachineObject* obj_, const ExtderData &ext_data) +static bool _is_nozzle_data_valid(MachineObject* obj_, const DevExtderSystem &ext_data) { if (obj_ == nullptr) return false; @@ -1919,9 +1944,9 @@ static bool _is_nozzle_data_valid(MachineObject* obj_, const ExtderData &ext_dat for (int used_filament_idx : used_filament_idxs) { int used_nozzle_idx = cur_plate->get_physical_extruder_by_filament_id(preset_bundle->full_config(), used_filament_idx); - if (ext_data.extders[used_nozzle_idx].current_nozzle_type == NozzleType::ntUndefine || - ext_data.extders[used_nozzle_idx].current_nozzle_diameter <= 0.0f || - ext_data.extders[used_nozzle_idx].current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { + if (ext_data.GetNozzleType(used_nozzle_idx) == NozzleType::ntUndefine || + ext_data.GetNozzleDiameter(used_nozzle_idx) <= 0.0f || + ext_data.GetNozzleFlowType(used_nozzle_idx) == NozzleFlowType::NONE_FLOWTYPE) { return false; } } @@ -1963,7 +1988,7 @@ static bool _is_same_nozzle_diameters(MachineObject* obj, float &tag_nozzle_diam } tag_nozzle_diameter = float(opt_nozzle_diameters->get_at(used_nozzle_idx)); - if (tag_nozzle_diameter != obj->m_extder_data.extders[used_nozzle_idx].current_nozzle_diameter) + if (tag_nozzle_diameter != obj->GetExtderSystem()->GetNozzleDiameter(used_nozzle_idx)) { mismatch_nozzle_id = used_nozzle_idx; return false; @@ -1978,9 +2003,9 @@ static bool _is_same_nozzle_diameters(MachineObject* obj, float &tag_nozzle_diam return true; } -bool SelectMachineDialog::is_nozzle_hrc_matched(const Extder& extruder, std::string& filament_type) const +bool SelectMachineDialog::is_nozzle_hrc_matched(const DevExtder* extruder, std::string& filament_type) const { - auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(extruder.current_nozzle_type); + auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(extruder->GetNozzleType()); auto preset_bundle = wxGetApp().preset_bundle; MaterialHash::const_iterator iter = m_materialList.begin(); @@ -2009,7 +2034,7 @@ bool SelectMachineDialog::is_same_printer_model() MachineObject* obj_ = dev->get_selected_machine(); - assert(obj_->dev_id == m_printer_last_select); + assert(obj_->get_dev_id() == m_printer_last_select); if (obj_ == nullptr) { return result; } @@ -2250,13 +2275,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) //bool has_show_traditional_timelapse_waring = false; //for (auto warning : plate->get_slice_result()->warnings) { - // if (warning.msg == BED_TEMP_TOO_HIGH_THAN_FILAMENT) { - // if ((obj_->get_printer_is_enclosed())){ - // // confirm_text.push_back(Plater::get_slice_warning_string(warning) + "\n"); - // // has_slice_warnings = true; - // } - // } - // else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) { + // if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) { // if (!has_show_traditional_timelapse_waring && (m_checkbox_list["timelapse"]->getValue() == "on")) { // confirm_text.push_back(ConfirmBeforeSendInfo(Plater::get_slice_warning_string(warning))); // has_show_traditional_timelapse_waring = true; @@ -2285,8 +2304,8 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) ////check for unidentified material - //auto mapping_result = m_mapping_popup.parse_ams_mapping(obj_->amsList); - //auto has_unknown_filament = false; + // auto mapping_result = m_mapping_popup.parse_ams_mapping(obj_->GetFilaSystem()->GetAmsList()); + // auto has_unknown_filament = false; //for (auto i = 0; i < m_ams_mapping_result.size(); i++) { @@ -2416,57 +2435,47 @@ void SelectMachineDialog::start_to_send(PrintHostJob upload_job) { return; } - if(!m_ams_mapping_result.empty()){ - bool success = false; - wxString msg = _L("Box Setting.."); - m_status_bar->update_status(msg, m_is_canceled, 10, true); - - //y67 - wxString enable_commond; - bool use_box = false; - if(_HasExt(m_ams_mapping_result)) - enable_commond = "SAVE_VARIABLE VARIABLE=enable_box VALUE=0"; - else { - use_box = true; - enable_commond = "SAVE_VARIABLE VARIABLE=enable_box VALUE=1"; - } - - bool enable_box = upload_job.printhost->send_command_to_printer(check_status_msg, enable_commond); - if (!enable_box) { - show_status(PrintDialogStatus::BoxhasSomeProblem); - return; - } - - if (use_box) { - for (auto result : m_ams_mapping_result) { - wxString command = wxString::Format( - "SAVE_VARIABLE VARIABLE=value_t%d VALUE=\\\"'slot%s'\\\"", - result.id, - result.slot_id - ); - success = upload_job.printhost->send_command_to_printer(check_status_msg, command); - if (!success) { - show_status(PrintDialogStatus::BoxhasSomeProblem); - return; - } - } - } - } - - //y60 + //y71 + wxString msg = _L("Box Setting.."); + m_status_bar->update_status(msg, m_is_canceled, 10, true); for (auto item : m_checkbox_list) { wxString command = ""; - if (item.second->getParam() == "bed_leveling") { + bool success = true; + if(item.second->getParam() == "enable_multi_box"){ + bool use_box = false; + if(has_box_machine){ + if (item.second->getValue() == "on"){ + command = "SAVE_VARIABLE VARIABLE=enable_box VALUE=1"; + use_box = true; + } + else { + command = "SAVE_VARIABLE VARIABLE=enable_box VALUE=0"; + } + success &= upload_job.printhost->send_command_to_printer(check_status_msg, command); + if(use_box){ + for (auto result : m_ams_mapping_result) { + wxString command = wxString::Format( + "SAVE_VARIABLE VARIABLE=value_t%d VALUE=\\\"'slot%s'\\\"", + result.id, + result.slot_id + ); + success &= upload_job.printhost->send_command_to_printer(check_status_msg, command); + if (!success) { + show_status(PrintDialogStatus::BoxhasSomeProblem); + return; + } + } + } + } + } else if (item.second->getParam() == "bed_leveling") { if (item.second->getValue() == "on") { command = "G31"; } else { command = "G32"; } - bool success = upload_job.printhost->send_command_to_printer(check_status_msg, command); - } - //y61 - if(item.second->getParam() == "timelapse" && select_machine.timelapse){ + success &= upload_job.printhost->send_command_to_printer(check_status_msg, command); + } else if(item.second->getParam() == "timelapse" && select_machine.timelapse){ bool open_timelapse; if (item.second->getValue() == "on") { open_timelapse = true; @@ -2474,7 +2483,12 @@ void SelectMachineDialog::start_to_send(PrintHostJob upload_job) { else { open_timelapse = false; } - bool success = upload_job.printhost->send_timelapse_status(check_status_msg, select_machine.ip, open_timelapse); + success &= upload_job.printhost->send_timelapse_status(check_status_msg, select_machine.ip, open_timelapse); + } + + if (!success) { + show_status(PrintDialogStatus::BoxhasSomeProblem); + return; } } @@ -2657,6 +2671,10 @@ void SelectMachineDialog::update_option_opts(MachineObject *obj) "leveling check(about 10 seconds). Skip if surface is fine.")); } + //y71 + m_checkbox_list["enable_multi_box"]->Show(); + m_checkbox_list["enable_multi_box"]->update_options(ops_no_auto, _L("Activate the multi-color box for multi-color printing with multiple filaments.")); + if(select_machine.timelapse){ m_checkbox_list["timelapse"]->Show(); m_checkbox_list["timelapse"]->update_options(ops_no_auto, _L("This enables timelapse mode. It will take a picture every 5 seconds during printing.\n*Automatic mode: Skip if timelapse is not supported.")); @@ -2685,14 +2703,16 @@ void SelectMachineDialog::update_option_opts(MachineObject *obj) //} ///*nozzle_offset_cali*/ - //if (obj->is_support_nozzle_offset_cali) { + // bool support_cali_nozzle_offset = obj->GetConfig()->SupportCalibrationNozzleOffset(); + // if (support_cali_nozzle_offset) { // m_checkbox_list["nozzle_offset_cali"]->update_options(ops_auto, _L("Calibrate nozzle offsets to enhance print quality.\n*Automatic mode: Check for calibration before printing. Skip if unnecessary.")); //} - //m_checkbox_list["nozzle_offset_cali"]->Show(obj->is_support_nozzle_offset_cali); + // m_checkbox_list["nozzle_offset_cali"]->Show(support_cali_nozzle_offset); ///*flow_cali*/ //if (obj->is_support_pa_calibration) { - // if (obj->is_support_auto_flow_calibration && can_support_auto_cali()) { + // if (obj->GetConfig()->SupportCalibrationPA_FlowAuto() && can_support_pa_auto_cali()) + // { // m_checkbox_list["flow_cali"]->update_options(ops_auto, _L("This process determines the dynamic flow values to improve overall print quality.\n*Automatic mode: Skip if the filament was calibrated recently.")); // } else { // m_checkbox_list["flow_cali"]->update_options(ops_no_auto, _L("This process determines the dynamic flow values to improve overall print quality.")); @@ -2717,6 +2737,10 @@ bool SelectMachineDialog::is_enable_external_change_assist(std::vectorenable(true); + m_checkbox_list["enable_multi_box"]->update_tooltip(wxEmptyString); + bool useExt = _HasExt(m_ams_mapping_result); + if (useExt){ + m_checkbox_list["enable_multi_box"]->setValue("off"); + } + } else { + m_checkbox_list["enable_multi_box"]->enable(false); + m_checkbox_list["enable_multi_box"]->update_tooltip(_L("The machine is not synchronized with the box, so the box cannot be activated.")); + } + + ///*STUDIO-9197*/ //wxString error_messgae; //if (obj->canEnableTimelapse(error_messgae) && !has_timelapse_warning(error_messgae)) { @@ -2746,6 +2784,8 @@ void SelectMachineDialog::load_option_vals(MachineObject *obj) // m_checkbox_list["timelapse"]->setValue("off"); // m_checkbox_list["timelapse"]->update_tooltip(error_messgae); //} + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " end"; } void SelectMachineDialog::save_option_vals() @@ -2799,7 +2839,7 @@ void SelectMachineDialog::on_send_print() if (!dev) return; MachineObject* obj_ = dev->get_selected_machine(); - assert(obj_->dev_id == m_printer_last_select); + assert(obj_->get_dev_id() == m_printer_last_select); if (obj_ == nullptr) { return; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", print_job: for send task, current printer id = " << QDTCrossTalk::Crosstalk_DevId(m_printer_last_select) << std::endl; @@ -2876,7 +2916,7 @@ void SelectMachineDialog::on_send_print() } m_print_job = std::make_shared(m_status_bar, m_plater, m_printer_last_select); - m_print_job->m_dev_ip = obj_->dev_ip; + m_print_job->m_dev_ip = obj_->get_dev_ip(); m_print_job->m_ftp_folder = obj_->get_ftp_folder(); m_print_job->m_access_code = obj_->get_access_code(); #if !QDT_RELEASE_TO_PUBLIC @@ -2927,7 +2967,7 @@ void SelectMachineDialog::on_send_print() BOOST_LOG_TRIVIAL(error) << "build_nozzle_info errors"; } - m_print_job->has_sdcard = obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL; + m_print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL; bool timelapse_option = m_checkbox_list["timelapse"]->IsShown()?true:false; @@ -2944,11 +2984,12 @@ void SelectMachineDialog::on_send_print() true, m_ext_change_assist, m_checkbox_list["bed_leveling"]->getValueInt(), + m_checkbox_list["enable_multi_box"]->getValueInt(), m_checkbox_list["flow_cali"]->getValueInt(), m_checkbox_list["nozzle_offset_cali"]->getValueInt() ); - if (obj_->has_ams()) { + if (obj_->HasAms()) { bool has_ext = _HasExt(m_ams_mapping_result); bool has_ams = _HasAms(m_ams_mapping_result); @@ -2979,7 +3020,7 @@ void SelectMachineDialog::on_send_print() // update ota version NetworkAgent* agent = wxGetApp().getAgent(); if (agent) { - std::string dev_ota_str = "dev_ota_ver:" + obj_->dev_id; + std::string dev_ota_str = "dev_ota_ver:" + obj_->get_dev_id(); agent->track_update_property(dev_ota_str, obj_->get_ota_version()); } @@ -3096,7 +3137,7 @@ void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt) int id = m_ams_mapping_result[i].id; m_ams_mapping_result[i] = old_info; m_ams_mapping_result[i].id = id; - auto color_change = AmsTray::decode_color(m_ams_mapping_result[i].color); + auto color_change = DevAmsTray::decode_color(m_ams_mapping_result[i].color); if (m_print_type == PrintFromType::FROM_NORMAL) {//todo:support sd card change_default_normal(id, color_change); final_deal_edge_pixels_data(m_preview_thumbnail_data); @@ -3121,10 +3162,10 @@ void SelectMachineDialog::on_set_finish_mapping(wxCommandEvent &evt) wxString ams_id; wxColour ams_col; ams_id = wxGetApp().transition_tridid(std::stoi(f->slot_id)); - ams_col = AmsTray::decode_color(f->color); + ams_col = DevAmsTray::decode_color(f->color); std::vector cols; for (auto col : f->colors) { - cols.push_back(AmsTray::decode_color(col)); + cols.push_back(DevAmsTray::decode_color(col)); } m->set_ams_info(ams_col, ams_id, f->ctype, cols); break; @@ -3186,7 +3227,7 @@ void SelectMachineDialog::reset_timeout() static bool _compare_obj_names(MachineObject* obj1, MachineObject* obj2) { - return obj1->dev_name < obj2->dev_name; + return obj1->get_dev_name() < obj2->get_dev_name(); } /******************************************************************* @@ -3209,7 +3250,7 @@ _collect_sorted_machines(Slic3r::DeviceManager* dev_manager, /* Step 1 :Collect the target and compatible types*/ PresetBundle* preset_bundle = wxGetApp().preset_bundle; const std::string& printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); - const auto& compatible_types_list = dev_manager->get_compatible_machine(printer_type); + const auto& compatible_types_list = DevPrinterConfigUtil::get_compatible_machine(printer_type); std::set compatible_types_set(compatible_types_list.begin(), compatible_types_list.end()); /* Step 2: collect different machine list*/ @@ -3345,7 +3386,7 @@ void SelectMachineDialog::update_user_printer() m_printer_box->SetPrinters(m_list); if (!m_list.empty()) { - m_printer_last_select = m_list.front()->dev_id; + m_printer_last_select = m_list.front()->get_dev_id(); m_printer_box->GetPrinterComboBox()->SetSelection(0); wxCommandEvent event(wxEVT_COMBOBOX); event.SetEventObject(m_printer_box->GetPrinterComboBox()); @@ -3471,6 +3512,8 @@ void SelectMachineDialog::on_timer(wxTimerEvent &event) img_ams_backup->Hide(); } } + + load_option_vals(nullptr); Layout(); Fit(); @@ -3480,18 +3523,18 @@ void SelectMachineDialog::on_timer(wxTimerEvent &event) MachineObject* obj_ = dev->get_selected_machine(); if(!obj_) return; - if (obj_->m_extder_data.total_extder_count > 1) { + if (obj_->GetExtderSystem()->GetTotalExtderCount() > 1) + { change_materialitem_tip(false); /*mapping to both ams and ext, is supported while total_extder_count is 2*/ } else { change_materialitem_tip(true); } - if (!obj_ - || obj_->amsList.empty() + if (!obj_->GetFilaSystem()->HasAms() || obj_->ams_exist_bits == 0 || !obj_->is_support_filament_backup - || !obj_->is_support_show_filament_backup - || !obj_->ams_auto_switch_filament_flag + || !obj_->GetExtderSystem()->HasFilamentBackup() + || !obj_->GetFilaSystem()->IsAutoRefillEnabled() || !_HasAms(m_ams_mapping_result)) { if (m_ams_backup_tip->IsShown()) { m_ams_backup_tip->Hide(); @@ -3645,7 +3688,7 @@ void SelectMachineDialog::on_selection_changed(wxCommandEvent &event) // m_printer_box->GetPrinterComboBox()->Update(); // } - // m_printer_last_select = m_list[i]->dev_id; + // m_printer_last_select = m_list[i]->get_dev_id(); // obj = m_list[i]; // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "for send task, current printer id = " << QDTCrossTalk::Crosstalk_DevId(m_printer_last_select) << std::endl; @@ -3658,13 +3701,13 @@ void SelectMachineDialog::on_selection_changed(wxCommandEvent &event) // obj->command_get_version(); // obj->command_request_push_all(); // if (!dev->get_selected_machine()) { - // dev->set_selected_machine(m_printer_last_select, true); - // }else if (dev->get_selected_machine()->dev_id != m_printer_last_select) { - // dev->set_selected_machine(m_printer_last_select, true); + // dev->set_selected_machine(m_printer_last_select); + // }else if (dev->get_selected_machine()->get_dev_id() != m_printer_last_select) { + // dev->set_selected_machine(m_printer_last_select); // } // // Has changed machine unrecoverably - // GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + // GUI::wxGetApp().sidebar().load_ams_list(obj->get_dev_id(), obj); // m_check_flag = false; // } else { // BOOST_LOG_TRIVIAL(error) << "on_selection_changed dev_id not found"; @@ -3684,7 +3727,7 @@ void SelectMachineDialog::update_ams_check(MachineObject *obj) if (!obj) {return;} if (!obj->is_enable_np) { - if (obj->has_ams()) { + if (obj->HasAms()) { change_materialitem_tip(false); } else { @@ -3732,7 +3775,7 @@ void SelectMachineDialog::update_filament_change_count() int hand_changes_count = curr.filament_change_count - best.filament_change_count; int saving_weight = curr.filament_flush_weight - best.filament_flush_weight; - if (obj->m_extder_data.total_extder_count > 1) { m_link_edit_nozzle->Show(true); } + // if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) { m_link_edit_nozzle->Show(true); } if (hand_changes_count > 0 || saving_weight > 0) { m_mapping_sugs_sizer->Show(true); @@ -3775,7 +3818,7 @@ static wxString _check_kval_not_default(const MachineObject* obj, const std::vec static wxString _get_nozzle_name(int total_ext_count, int ext_id) { if (total_ext_count == 2) { - if (ext_id == MAIN_NOZZLE_ID) { + if (ext_id == MAIN_EXTRUDER_ID) { return _L("right nozzle"); } else { return _L("left nozzle"); @@ -3801,7 +3844,7 @@ static wxString _get_ext_loc_str(const std::unordered_set& extruders, int t else if (extruders.size() == 1) { auto iter = extruders.begin(); - if (*iter == MAIN_NOZZLE_ID) + if (*iter == MAIN_EXTRUDER_ID) { return _L("right extruder"); } @@ -3950,7 +3993,8 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) reset_timeout(); /*check print all*/ - if (!obj_->is_support_print_all && m_print_plate_idx == PLATE_ALL_IDX) { + if (!obj_->GetConfig()->SupportPrintAllPlates() && m_print_plate_idx == PLATE_ALL_IDX) + { show_status(PrintDialogStatus::PrintStatusNotSupportedPrintAll); return; } @@ -4013,29 +4057,29 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) } else if (obj_->is_in_printing() || obj_->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { show_status(PrintDialogStatus::PrintStatusInPrinting); return; - } else if (!obj_->is_support_print_without_sd && (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD)) { + } else if (!obj_->GetConfig()->SupportPrintWithoutSD() && (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD)) { show_status(PrintDialogStatus::PrintStatusNoSdcard); return; } /*check sdcard when if lan mode printer*/ if (obj_->is_lan_mode_printer()) { - if (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { show_status(PrintDialogStatus::PrintStatusLanModeNoSdcard); return; - } else if (obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL || obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_READONLY) { + } else if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL || obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_READONLY) { show_status(PrintDialogStatus::PrintStatusLanModeSDcardNotAvailable); return; } } - if (!can_support_auto_cali() && m_checkbox_list["flow_cali"]->IsShown() && m_checkbox_list["flow_cali"]->getValue() == "on") { + if (!can_support_pa_auto_cali() && m_checkbox_list["flow_cali"]->IsShown() && m_checkbox_list["flow_cali"]->getValue() == "on") { show_status(PrintDialogStatus::PrintStatusTPUUnsupportAutoCali); return; } /*disable print when there is no mapping*/ - if (obj_->m_extder_data.total_extder_count > 1) { + if (obj_->GetExtderSystem()->GetTotalExtderCount() > 1) { for (auto mres : m_ams_mapping_result) { if (mres.ams_id.empty() && mres.slot_id.empty()) { show_status(PrintDialogStatus::PrintStatusInvalidMapping); @@ -4049,13 +4093,13 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) /*the nozzle type of preset and machine are different*/ if (nozzle_nums > 1 && m_print_type == FROM_NORMAL) { - if (!_is_nozzle_data_valid(obj_, obj_->m_extder_data)) { + if (!_is_nozzle_data_valid(obj_, *obj_->GetExtderSystem())) { show_status(PrintDialogStatus::PrintStatusNozzleDataInvalid); return; } wxString error_message; - if (!is_nozzle_type_match(obj_->m_extder_data, error_message)) { + if (!is_nozzle_type_match(*obj_->GetExtderSystem(), error_message)) { std::vector params{error_message}; params.emplace_back(_L("Tips: If you changed your nozzle of your printer lately, Please go to 'Device -> Printer parts' to change your nozzle setting.")); show_status(PrintDialogStatus::PrintStatusNozzleMatchInvalid, params); @@ -4071,9 +4115,9 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) if (!_is_same_nozzle_diameters(obj_, nozzle_diameter, mismatch_nozzle_id)) { std::vector msg_params; - if (obj_->m_extder_data.total_extder_count == 2) { + if (obj_->GetExtderSystem()->GetTotalExtderCount() == 2) { wxString mismatch_nozzle_str; - if (mismatch_nozzle_id == MAIN_NOZZLE_ID) { + if (mismatch_nozzle_id == MAIN_EXTRUDER_ID) { mismatch_nozzle_str = _L("right nozzle"); } else { mismatch_nozzle_str = _L("left nozzle"); @@ -4082,13 +4126,13 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) const wxString &nozzle_config = wxString::Format(_L("The %s diameter(%.1fmm) of current printer doesn't match with the slicing file (%.1fmm). " "Please make sure the nozzle installed matches with settings in printer, then set the " "corresponding printer preset when slicing."), - mismatch_nozzle_str, obj_->m_extder_data.extders[mismatch_nozzle_id].current_nozzle_diameter, nozzle_diameter); + mismatch_nozzle_str, obj_->GetExtderSystem()->GetNozzleDiameter(mismatch_nozzle_id), nozzle_diameter); msg_params.emplace_back(nozzle_config); } else { const wxString &nozzle_config = wxString::Format(_L("The current nozzle diameter (%.1fmm) doesn't match with the slicing file (%.1fmm). " "Please make sure the nozzle installed matches with settings in printer, then set the " "corresponding printer preset when slicing."), - obj_->m_extder_data.extders[0].current_nozzle_diameter, nozzle_diameter); + obj_->GetExtderSystem()->GetNozzleDiameter(0), nozzle_diameter); msg_params.emplace_back(nozzle_config); } @@ -4098,14 +4142,14 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) } const auto &used_nozzle_idxes = _get_used_nozzle_idxes(); - for (const auto &extder : obj_->m_extder_data.extders) { - if (used_nozzle_idxes.count(extder.nozzle_id) == 0) { continue; } + for (const auto &extder : obj_->GetExtderSystem()->GetExtruders()) { + if (used_nozzle_idxes.count(extder.GetNozzleId()) == 0) { continue; } std::string filament_type; - if (!is_nozzle_hrc_matched(extder, filament_type)) { + if (!is_nozzle_hrc_matched(&extder, filament_type)) { std::vector error_msg; error_msg.emplace_back(wxString::Format(_L("The hardness of current material (%s) exceeds the hardness of %s(%s). Please verify the nozzle or material settings and try again."), - filament_type, _get_nozzle_name(obj_->m_extder_data.total_extder_count, extder.nozzle_id), format_steel_name(extder.current_nozzle_type))); + filament_type, _get_nozzle_name(obj_->GetExtderSystem()->GetTotalExtderCount(), extder.GetNozzleId()), format_steel_name(extder.GetNozzleType()))); show_status(PrintDialogStatus::PrintStatusNozzleTypeMismatch, error_msg); return; } @@ -4121,12 +4165,12 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) } } - if (obj_->is_ams_on_settingup()) { + if (obj_->GetFilaSystem()->IsAmsSettingUp()) { show_status(PrintDialogStatus::PrintStatusAmsOnSettingup); return; } - if (!m_ams_mapping_res && !obj_->is_valid_mapping_result(m_ams_mapping_result)) { + if (!m_ams_mapping_res && !DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result)) { show_status(PrintDialogStatus::PrintStatusAmsMappingInvalid); return; } @@ -4149,7 +4193,7 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) std::string action; wxString info; wxString wiki_url; - DeviceManager::check_filaments_in_blacklist_url(obj_->printer_type, filament_brand, filament_type, m_ams_mapping_result[i].filament_id, ams_id, slot_id, "", in_blacklist, + DevFilaBlacklist::check_filaments_in_blacklist_url(obj_->printer_type, filament_brand, filament_type, m_ams_mapping_result[i].filament_id, ams_id, slot_id, "", in_blacklist, action, info, wiki_url); if (in_blacklist) { @@ -4176,7 +4220,7 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) if (item.ams_id.empty()) continue; int extruder_id = obj_->get_extruder_id_by_ams_id(item.ams_id); - if (DeviceManager::is_virtual_slot(stoi(item.ams_id))) + if (devPrinterUtil::IsVirtualSlot(item.ams_id)) extruder_status[extruder_id].has_vt_slot = true; else extruder_status[extruder_id].has_ams = true; @@ -4193,7 +4237,7 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) // return; } } else { - if (obj_->is_valid_mapping_result(m_ams_mapping_result)) { + if (DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result)) { if (!check_sdcard_for_timelpase(obj_)) { if (has_timelapse_warning()) { show_status(PrintDialogStatus::PrintStatusTimelapseWarning); @@ -4214,13 +4258,13 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) } /*Check the tpu at right*/ - if (obj_->m_extder_data.total_extder_count == 2) { + if (obj_->GetExtderSystem()->GetTotalExtderCount() == 2) { for (const FilamentInfo& item : m_ams_mapping_result) { if (item.ams_id.empty()) continue; if (item.type.compare("TPU") != 0 && item.type.compare("TPU-Box") != 0) { continue; } int extruder_id = obj_->get_extruder_id_by_ams_id(item.ams_id); - if (extruder_id == MAIN_NOZZLE_ID) { + if (extruder_id == MAIN_EXTRUDER_ID) { show_status(PrintDialogStatus::PrintStatusWarningTpuRightColdPulling); break; } @@ -4237,22 +4281,22 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) try { int chamber_temp = chamber_temperatures->values[item.id]; - if (chamber_temp >= obj_->chamber_temp_switch_heat) {// check close door + if (chamber_temp >= obj_->GetConfig()->GetChamberTempSwitchHeat()) {// check close door show_status(PrintDialogStatus::PrintStatusFilamentWarningHighChamberTempCloseDoor); if (PrePrintChecker::is_error(PrintDialogStatus::PrintStatusFilamentWarningHighChamberTempCloseDoor)) { return; } } - for (const auto& extder : obj_->m_extder_data.extders) { // check vitrification - if (extder.ext_has_filament) { - const auto& fila_id = obj_->get_filament_id(extder.snow.ams_id, extder.snow.slot_id); + for (const auto& extder : obj_->GetExtderSystem()->GetExtruders()) { // check vitrification + if (extder.HasFilamentInExt()) { + const auto& fila_id = obj_->get_filament_id(extder.GetSlotNow().ams_id, extder.GetSlotNow().slot_id); auto filament_info = wxGetApp().preset_bundle->get_filament_by_filament_id(fila_id); if (filament_info) { if (filament_info->temperature_vitrification - chamber_temp <= 5) { - known_fila_soften_extruders.insert(extder.id); + known_fila_soften_extruders.insert(extder.GetExtId()); } } else { // the minimum temperature_vitrification of the known filaments is 43 degrees - if (43 - chamber_temp <= 5) { unknown_fila_soften_extruders.insert(extder.id); } + if (43 - chamber_temp <= 5) { unknown_fila_soften_extruders.insert(extder.GetExtId()); } } } } @@ -4262,14 +4306,14 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_) if (!known_fila_soften_extruders.empty()) { const wxString& msg = wxString::Format(_L("The filament on %s may soften. Please unload."), - _get_ext_loc_str(known_fila_soften_extruders, obj_->m_extder_data.total_extder_count)); + _get_ext_loc_str(known_fila_soften_extruders, obj_->GetExtderSystem()->GetTotalExtderCount())); show_status(PrintDialogStatus::PrintStatusFilamentWarningHighChamberTempSoft, std::vector {msg}); if (PrePrintChecker::is_error(PrintDialogStatus::PrintStatusFilamentWarningHighChamberTempSoft)) { return; } } if (!unknown_fila_soften_extruders.empty()) { const wxString& msg = wxString::Format(_L("The filament on %s is unknown and may soften. Please set filament."), - _get_ext_loc_str(unknown_fila_soften_extruders, obj_->m_extder_data.total_extder_count)); + _get_ext_loc_str(unknown_fila_soften_extruders, obj_->GetExtderSystem()->GetTotalExtderCount())); show_status(PrintDialogStatus::PrintStatusFilamentWarningUnknownHighChamberTempSoft, std::vector {msg}); if (PrePrintChecker::is_error(PrintDialogStatus::PrintStatusFilamentWarningUnknownHighChamberTempSoft)) { return; } } @@ -4298,7 +4342,7 @@ bool SelectMachineDialog::has_timelapse_warning(wxString &msg_text) return false; } -bool SelectMachineDialog::can_support_auto_cali() +bool SelectMachineDialog::can_support_pa_auto_cali() { DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) @@ -4307,7 +4351,7 @@ bool SelectMachineDialog::can_support_auto_cali() if (!obj) return true; - std::vector unsupport_auto_cali_filaments = DeviceManager::get_unsupport_auto_cali_filaments(obj->printer_type); + std::vector unsupport_auto_cali_filaments = DevPrinterConfigUtil::get_unsupport_auto_cali_filaments(obj->printer_type); if (!unsupport_auto_cali_filaments.empty()) { auto iter = std::find_if(m_filaments.begin(), m_filaments.end(), [&unsupport_auto_cali_filaments](const FilamentInfo &item) { @@ -4643,7 +4687,7 @@ void SelectMachineDialog::reset_and_sync_ams_list() size_t nozzle_nums = full_config.option("nozzle_diameter")->values.size(); if (nozzle_nums > 1) { - if (obj_ && can_hybrid_mapping(obj_->m_extder_data)) + if (obj_ && can_hybrid_mapping(*obj_->GetExtderSystem())) { m_mapping_popup.set_show_type(ShowType::LEFT_AND_RIGHT); } @@ -4776,7 +4820,7 @@ void SelectMachineDialog::record_edge_pixels_data() }; ThumbnailData &data = m_cur_no_light_thumbnail_data; ThumbnailData &origin_data = m_cur_input_thumbnail_data; - if (data.width > 0 && data.height > 0) { + if (data.width > 0 && data.height > 0 && (data.width == origin_data.width && data.height == origin_data.height) ) { m_edge_pixels.resize(data.width * data.height); for (unsigned int r = 0; r < data.height; ++r) { unsigned int rr = (data.height - 1 - r) * data.width; @@ -5024,7 +5068,7 @@ void SelectMachineDialog::set_default_from_sdcard() MachineObject *obj_ = dev_manager->get_selected_machine(); if (!obj_) { return; }; - m_printer_box->SetPrinterName(wxString::FromUTF8(obj_->dev_name)); + m_printer_box->SetPrinterName(wxString::FromUTF8(obj_->get_dev_name())); m_print_plate_total = m_required_data_plate_data_list.size(); update_page_turn_state(true); @@ -5157,7 +5201,7 @@ void SelectMachineDialog::set_default_from_sdcard() m_mapping_popup.Move(pos); if (diameters_count > 1) { - if (obj_ && can_hybrid_mapping(obj_->m_extder_data)) { + if (obj_ && can_hybrid_mapping(*obj_->GetExtderSystem())) { m_mapping_popup.set_show_type(ShowType::LEFT_AND_RIGHT); } else if (m_filaments_map[m_current_filament_id] == 1) { m_mapping_popup.set_show_type(ShowType::LEFT); @@ -5168,8 +5212,7 @@ void SelectMachineDialog::set_default_from_sdcard() m_mapping_popup.set_show_type(ShowType::RIGHT); } - if (obj_ && obj_->dev_id == m_printer_last_select) - { + if (obj_ && obj_->get_dev_id() == m_printer_last_select) { m_mapping_popup.set_parent_item(item); m_mapping_popup.set_current_filament_id(fo.id); m_mapping_popup.set_tag_texture(fo.type); @@ -5258,15 +5301,6 @@ bool SelectMachineDialog::Show(bool show) m_refresh_timer->Start(LIST_REFRESH_INTERVAL); } else { m_refresh_timer->Stop(); - - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (dev) { - MachineObject *obj_ = dev->get_selected_machine(); - if (obj_ && obj_->connection_type() == "cloud" /*&& m_print_type == FROM_SDCARD_VIEW*/) { - if (obj_->is_connected()) { obj_->disconnect(); } - } - } - return DPIDialog::Show(false); } show_init(); @@ -5564,6 +5598,7 @@ void PrintOptionItem::render(wxDC& dc) void PrintOptionItem::on_left_down(wxMouseEvent& evt) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", enable status is " << m_enable; if (!m_enable) { return; @@ -5586,6 +5621,25 @@ void PrintOptionItem::on_left_down(wxMouseEvent& evt) i++; } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", new select key= " << selected_key; + if (selected_key.empty()) /* make some log if not find*/ + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", pos.x=" << pos.x << ", rect.x=" << rect.x; + + int i = 0; + for (const auto& entry : m_ops) + { + auto left_edge = rect.x + i * select_size; + auto right_edge = rect.x + (i + 1) * select_size; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", i= " << i + << ", entry.key= " << entry.key + << ", left_edge= " << left_edge + << ", right_edge= " << right_edge; + + i++; + } + } + wxCommandEvent event(EVT_SWITCH_PRINT_OPTION); event.SetString(selected_key); event.SetEventObject(GetParent()); @@ -5825,13 +5879,13 @@ static wxString _get_tips(MachineObject* obj_) tips = obj_->get_printer_type_display_str(); wxString ext_diameter; - if (obj_->m_extder_data.total_extder_count == 1) { - ext_diameter += wxString::FromDouble(obj_->m_extder_data.extders[0].current_nozzle_diameter); + if (obj_->GetExtderSystem()->GetTotalExtderCount() == 1) { + ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(0)); ext_diameter += "mm"; - } else if (obj_->m_extder_data.total_extder_count == 2) { - ext_diameter += wxString::FromDouble(obj_->m_extder_data.extders[1].current_nozzle_diameter);//Left + } else if (obj_->GetExtderSystem()->GetTotalExtderCount() == 2) { + ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(1));//Left ext_diameter += "/"; - ext_diameter += wxString::FromDouble(obj_->m_extder_data.extders[0].current_nozzle_diameter); + ext_diameter += wxString::FromDouble(obj_->GetExtderSystem()->GetNozzleDiameter(0)); ext_diameter += "mm"; } else { assert(0); @@ -5852,7 +5906,7 @@ void PrinterInfoBox::SetPrinters(const std::vector& sorted_print std::vector drop_items; for (MachineObject* obj : sorted_printers) { - wxString shown_dev_name = wxString::FromUTF8(obj->dev_name); + wxString shown_dev_name = wxString::FromUTF8(obj->get_dev_name()); if (obj->is_lan_mode_printer()) { shown_dev_name += "(LAN)"; } diff --git a/src/slic3r/GUI/SelectMachine.hpp b/src/slic3r/GUI/SelectMachine.hpp index 0aaec6c..7e74876 100644 --- a/src/slic3r/GUI/SelectMachine.hpp +++ b/src/slic3r/GUI/SelectMachine.hpp @@ -48,6 +48,11 @@ #define PRINT_OPT_BG_GRAY 0xF8F8F8 #define PRINT_OPT_ITEM_BG_GRAY 0xEEEEEE +// Previous definitions +namespace Slic3r{ + class DevExtder; +} + namespace Slic3r { namespace GUI { std::string get_nozzle_volume_type_cloud_string(NozzleVolumeType nozzle_volume_type); @@ -145,7 +150,8 @@ struct Machine_info { std::string link_url = ""; bool is_special = false; bool bed_leveling = true; - bool timelapse = false; + bool enable_multi_box = false; + bool timelapse = true; }; #define PRINT_OPT_WIDTH FromDIP(44) @@ -513,10 +519,10 @@ public: void update_print_error_info(int code, std::string msg, std::string extra); bool has_timelapse_warning(wxString& msg); bool has_timelapse_warning() { wxString msg; return has_timelapse_warning(msg);}; - bool can_support_auto_cali(); + bool can_support_pa_auto_cali(); bool is_same_printer_model(); bool is_blocking_printing(MachineObject* obj_); - bool is_nozzle_hrc_matched(const Extder& extruder, std::string& filament_type) const; + bool is_nozzle_hrc_matched(const DevExtder* extruder, std::string& filament_type) const; bool check_sdcard_for_timelpase(MachineObject* obj); bool is_timeout(); int update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path); @@ -526,9 +532,9 @@ public: bool do_ams_mapping(MachineObject *obj_,bool use_ams); bool get_ams_mapping_result(std::string& mapping_array_str, std::string& mapping_array_str2, std::string& ams_mapping_info); bool build_nozzles_info(std::string& nozzles_info); - bool can_hybrid_mapping(ExtderData data); - void auto_supply_with_ext(std::vector slots); - bool is_nozzle_type_match(ExtderData data, wxString& error_message) const; + bool can_hybrid_mapping(DevExtderSystem data); + void auto_supply_with_ext(std::vector slots); + bool is_nozzle_type_match(DevExtderSystem data, wxString& error_message) const; int convert_filament_map_nozzle_id_to_task_nozzle_id(int nozzle_id); PrintFromType get_print_type() {return m_print_type;}; diff --git a/src/slic3r/GUI/SelectMachinePop.cpp b/src/slic3r/GUI/SelectMachinePop.cpp index c7d57d9..4bc44ea 100644 --- a/src/slic3r/GUI/SelectMachinePop.cpp +++ b/src/slic3r/GUI/SelectMachinePop.cpp @@ -28,6 +28,8 @@ #include "BitmapCache.hpp" #include "BindDialog.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { wxDEFINE_EVENT(EVT_UPDATE_WINDOWS_POSITION, wxCommandEvent); @@ -169,7 +171,7 @@ void MachineObjectPanel::doRender(wxDC &dc) dc.SetTextForeground(StateColor::darkModeColorFor(SELECT_MACHINE_GREY900)); wxString dev_name = ""; if (m_info) { - dev_name = from_u8(m_info->dev_name); + dev_name = from_u8(m_info->get_dev_name()); if (m_state == PrinterState::IN_LAN) { dev_name += _L("(LAN)"); @@ -270,7 +272,7 @@ void MachineObjectPanel::on_mouse_left_up(wxMouseEvent &evt) GetEventHandler()->ProcessEvent(event); } else { if (m_info) { - wxGetApp().mainframe->jump_to_monitor(m_info->dev_id); + wxGetApp().mainframe->jump_to_monitor(m_info->get_dev_id()); } //wxGetApp().mainframe->SetFocus(); wxCommandEvent event(EVT_DISSMISS_MACHINE_LIST); @@ -281,14 +283,14 @@ void MachineObjectPanel::on_mouse_left_up(wxMouseEvent &evt) } if (m_info && m_info->is_lan_mode_printer()) { if (m_info->has_access_right() && m_info->is_avaliable()) { - wxGetApp().mainframe->jump_to_monitor(m_info->dev_id); + wxGetApp().mainframe->jump_to_monitor(m_info->get_dev_id()); } else { wxCommandEvent event(EVT_CONNECT_LAN_PRINT); event.SetEventObject(this); wxPostEvent(this, event); } } else { - wxGetApp().mainframe->jump_to_monitor(m_info->dev_id); + wxGetApp().mainframe->jump_to_monitor(m_info->get_dev_id()); } } else { if (m_info && m_info->is_lan_mode_printer()) { @@ -498,7 +500,7 @@ void SelectMachinePopup::update_other_devices() { DeviceManager* dev = wxGetApp().getDeviceManager(); if (!dev) return; - m_free_machine_list = dev->get_local_machine_list(); + m_free_machine_list = dev->get_local_machinelist(); BOOST_LOG_TRIVIAL(trace) << "SelectMachinePopup update_other_devices start"; this->Freeze(); @@ -514,7 +516,7 @@ void SelectMachinePopup::update_other_devices() continue; /* do not show printer in my list */ - auto it = m_bind_machine_list.find(mobj->dev_id); + auto it = m_bind_machine_list.find(mobj->get_dev_id()); if (it != m_bind_machine_list.end()) continue; @@ -566,7 +568,7 @@ void SelectMachinePopup::update_other_devices() ConnectPrinterDialog dlg(wxGetApp().mainframe, wxID_ANY, _L("Input access code")); dlg.set_machine_object(mobj); if (dlg.ShowModal() == wxID_OK) { - wxGetApp().mainframe->jump_to_monitor(mobj->dev_id); + wxGetApp().mainframe->jump_to_monitor(mobj->get_dev_id()); } } } @@ -577,7 +579,7 @@ void SelectMachinePopup::update_other_devices() dlg.update_machine_info(mobj); int dlg_result = wxID_CANCEL; dlg_result = dlg.ShowModal(); - if (dlg_result == wxID_OK) { wxGetApp().mainframe->jump_to_monitor(mobj->dev_id); } + if (dlg_result == wxID_OK) { wxGetApp().mainframe->jump_to_monitor(mobj->get_dev_id()); } }); } @@ -640,7 +642,7 @@ void SelectMachinePopup::update_user_devices() std::sort(user_machine_list.begin(), user_machine_list.end(), [&](auto& a, auto&b) { if (a.second && b.second) { - return a.second->dev_name.compare(b.second->dev_name) < 0; + return a.second->get_dev_name().compare(b.second->get_dev_name()) < 0; } return false; }); @@ -740,7 +742,7 @@ void SelectMachinePopup::update_user_devices() ConnectPrinterDialog dlg(wxGetApp().mainframe, wxID_ANY, _L("Input access code")); dlg.set_machine_object(mobj); if (dlg.ShowModal() == wxID_OK) { - wxGetApp().mainframe->jump_to_monitor(mobj->dev_id); + wxGetApp().mainframe->jump_to_monitor(mobj->get_dev_id()); } } } @@ -777,14 +779,14 @@ bool SelectMachinePopup::search_for_printer(MachineObject* obj) return true; } - const auto& name = wxString::FromUTF8(obj->dev_name).ToStdString(); + const auto& name = wxString::FromUTF8(obj->get_dev_name()).ToStdString(); const auto& name_it = name.find(search_text); if (name_it != std::string::npos) { return true; } #if !QDT_RELEASE_TO_PUBLIC - const auto& ip_it = obj->dev_ip.find(search_text); + const auto& ip_it = obj->get_dev_ip().find(search_text); if (ip_it != std::string::npos) { return true; } @@ -912,7 +914,7 @@ void EditDevNameDialog::set_machine_obj(MachineObject *obj) { m_info = obj; if (m_info) - m_textCtr->GetTextCtrl()->SetValue(from_u8(m_info->dev_name)); + m_textCtr->GetTextCtrl()->SetValue(from_u8(m_info->get_dev_name())); } void EditDevNameDialog::on_dpi_changed(const wxRect &suggested_rect) @@ -978,7 +980,7 @@ void EditDevNameDialog::on_edit_name(wxCommandEvent &e) auto utf8_str = new_dev_name.ToUTF8(); auto name = std::string(utf8_str.data(), utf8_str.length()); if (m_info) - dev->modify_device_name(m_info->dev_id, name); + dev->modify_device_name(m_info->get_dev_id(), name); } DPIDialog::EndModal(wxID_CLOSE); } diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 3b7b00d..64403ca 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -543,6 +543,19 @@ void Selection::center() // calc distance Vec3d src_pos = this->get_bounding_box().center(); Vec3d tar_pos = plate->get_center_origin(); + auto mv = get_selected_volume(*this); + if (get_volume_idxs().size() == 1 && mv->is_text() && !mv->is_the_only_one_part()) { + auto index = mv->get_text_info().m_rr.mesh_id; + if (index >= 0 && index < mv->get_object()->volumes.size()) { + auto mo = mv->get_object(); + auto attach_mv = mo->volumes[index]; + if (!attach_mv->is_text() && attach_mv->is_model_part()) { + auto mo_tran = mo->instances[0]->get_transformation(); + auto world_tran = (mo_tran * attach_mv->get_transformation()).get_matrix(); + tar_pos = attach_mv->get_mesh_shared_ptr()->bounding_box().transformed(world_tran).center(); + } + } + } Vec3d distance = Vec3d(tar_pos.x() - src_pos.x(), tar_pos.y() - src_pos.y(), 0); this->move_to_center(distance); diff --git a/src/slic3r/GUI/SendMultiMachinePage.cpp b/src/slic3r/GUI/SendMultiMachinePage.cpp index ea6bb0f..50f04d5 100644 --- a/src/slic3r/GUI/SendMultiMachinePage.cpp +++ b/src/slic3r/GUI/SendMultiMachinePage.cpp @@ -7,6 +7,9 @@ #include "Widgets/RadioBox.hpp" #include +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevStorage.h" + // y21 namespace Slic3r { namespace GUI { @@ -202,7 +205,7 @@ void SendDeviceItem::doRender(wxDC& dc) left += FromDIP(SEND_LEFT_PRINTABLE); //dev names - DrawTextWithEllipsis(dc, wxString::FromUTF8(get_obj()->dev_name), FromDIP(SEND_LEFT_DEV_NAME), left); + DrawTextWithEllipsis(dc, wxString::FromUTF8(get_obj()->get_dev_name()), FromDIP(SEND_LEFT_DEV_NAME), left); left += FromDIP(SEND_LEFT_DEV_NAME); //device state @@ -224,7 +227,7 @@ void SendDeviceItem::doRender(wxDC& dc) //AMS - if (!obj_->has_ams()) { + if (!obj_->HasAms()) { DrawTextWithEllipsis(dc, _L("No BOX"), FromDIP(SEND_LEFT_DEV_NAME), left); } else { @@ -240,7 +243,7 @@ void SendDeviceItem::doRender(wxDC& dc) void SendDeviceItem::post_event(wxCommandEvent&& event) { event.SetEventObject(this); - event.SetString(obj_->dev_id); + event.SetString(obj_->get_dev_id()); event.SetInt(state_selected); wxPostEvent(this, event); } @@ -492,9 +495,9 @@ QDT::PrintParams SendMultiMachinePage::request_params(MachineObject* obj) else curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1; - params.dev_ip = obj->dev_ip; - params.dev_id = obj->dev_id; - params.dev_name = obj->dev_name; + params.dev_ip = obj->get_dev_ip(); + params.dev_id = obj->get_dev_id(); + params.dev_name = obj->get_dev_name(); params.ftp_folder = obj->get_ftp_folder(); params.connection_type = obj->connection_type(); params.print_type = "from_normal"; @@ -605,7 +608,7 @@ QDT::PrintParams SendMultiMachinePage::request_params(MachineObject* obj) params.comments = "no_ip"; else if (obj->is_support_cloud_print_only) params.comments = "low_version"; - else if (obj->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) + else if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) params.comments = "no_sdcard"; else if (params.password.empty()) params.comments = "no_password"; @@ -711,9 +714,9 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event) //y24 if (it->second->get_state_selected() == 1 && it->second->state_printable <= 2) { - std::string name = obj->dev_name; + std::string name = obj->get_dev_name(); std::string url = obj->dev_url; - std::string ip = obj->dev_ip; + std::string ip = obj->get_dev_ip(); std::string apikey = obj->dev_apikey; std::vector host_vector; host_vector.push_back(url); diff --git a/src/slic3r/GUI/SendToPrinter.cpp b/src/slic3r/GUI/SendToPrinter.cpp index 93529d9..16e62a1 100644 --- a/src/slic3r/GUI/SendToPrinter.cpp +++ b/src/slic3r/GUI/SendToPrinter.cpp @@ -22,6 +22,8 @@ #include "BitmapCache.hpp" #include "slic3r/Utils/QDTUtil.hpp" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevStorage.h" namespace Slic3r { namespace GUI { @@ -1026,7 +1028,7 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event) // m_comboBox_printer->SetTextLabel(""); // return; // } -// assert(obj_->dev_id == m_printer_last_select); +// assert(obj_->get_dev_id() == m_printer_last_select); // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", print_job: for send task, current printer id = " << QDTCrossTalk::Crosstalk_DevId(m_printer_last_select) << std::endl; @@ -1186,7 +1188,7 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event) // } else { // m_send_job = std::make_shared(m_status_bar, m_plater, m_printer_last_select); -// m_send_job->m_dev_ip = obj_->dev_ip; +// m_send_job->m_dev_ip = obj_->get_dev_ip(); // m_send_job->m_access_code = obj_->get_access_code(); // #if !QDT_RELEASE_TO_PUBLIC @@ -1199,7 +1201,7 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event) // #endif // m_send_job->connection_type = obj_->connection_type(); // m_send_job->cloud_print_only = true; -// m_send_job->has_sdcard = obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL; +// m_send_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL; // m_send_job->set_project_name(m_current_project_name.utf8_string()); // enable_prepare_mode = false; @@ -1410,15 +1412,15 @@ void SendToPrinterDialog::update_user_printer() // // same machine only appear once // for (auto it = option_list.begin(); it != option_list.end(); it++) { // if (it->second && (it->second->is_online() || it->second->is_connected())) { - // machine_list.push_back(it->second->dev_name); + // machine_list.push_back(it->second->get_dev_name()); // } // } // machine_list = sort_string(machine_list); // for (auto tt = machine_list.begin(); tt != machine_list.end(); tt++) { // for (auto it = option_list.begin(); it != option_list.end(); it++) { - // if (it->second->dev_name == *tt) { + // if (it->second->get_dev_name() == *tt) { // m_list.push_back(it->second); - // wxString dev_name_text = from_u8(it->second->dev_name); + // wxString dev_name_text = from_u8(it->second->get_dev_name()); // if (it->second->is_lan_mode_printer()) { // dev_name_text += "(LAN)"; // } @@ -1432,7 +1434,7 @@ void SendToPrinterDialog::update_user_printer() // MachineObject* obj = dev->get_selected_machine(); // if (obj) { - // m_printer_last_select = obj->dev_id; + // m_printer_last_select = obj->get_dev_id(); // } else { // m_printer_last_select = ""; // } @@ -1440,14 +1442,14 @@ void SendToPrinterDialog::update_user_printer() // if (m_list.size() > 0) { // // select a default machine // if (m_printer_last_select.empty()) { - // m_printer_last_select = m_list[0]->dev_id; + // m_printer_last_select = m_list[0]->get_dev_id(); // m_comboBox_printer->SetSelection(0); // wxCommandEvent event(wxEVT_COMBOBOX); // event.SetEventObject(m_comboBox_printer); // wxPostEvent(m_comboBox_printer, event); // } // for (auto i = 0; i < m_list.size(); i++) { - // if (m_list[i]->dev_id == m_printer_last_select) { + // if (m_list[i]->get_dev_id() == m_printer_last_select) { // m_comboBox_printer->SetSelection(i); // wxCommandEvent event(wxEVT_COMBOBOX); // event.SetEventObject(m_comboBox_printer); @@ -1548,7 +1550,7 @@ void SendToPrinterDialog::on_selection_changed(wxCommandEvent &event) // MachineObject* obj = nullptr; // for (int i = 0; i < m_list.size(); i++) { // if (i == selection) { -// m_printer_last_select = m_list[i]->dev_id; +// m_printer_last_select = m_list[i]->get_dev_id(); // obj = m_list[i]; // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "for send task, current printer id = " << QDTCrossTalk::Crosstalk_DevId(m_printer_last_select) << std::endl; // break; @@ -1559,12 +1561,12 @@ void SendToPrinterDialog::on_selection_changed(wxCommandEvent &event) // obj->command_get_version(); // obj->command_request_push_all(); // if (!dev->get_selected_machine()) { -// dev->set_selected_machine(m_printer_last_select, true); +// dev->set_selected_machine(m_printer_last_select); // if (m_file_sys) m_file_sys.reset(); -// }else if (dev->get_selected_machine()->dev_id != m_printer_last_select) { +// }else if (dev->get_selected_machine()->get_dev_id() != m_printer_last_select) { // m_ability_list.clear(); // //update_storage_list(std::vector()); -// dev->set_selected_machine(m_printer_last_select, true); +// dev->set_selected_machine(m_printer_last_select); // if (m_file_sys) m_file_sys.reset(); // } // } @@ -1683,7 +1685,7 @@ void SendToPrinterDialog::update_show_status() // check sdcard when if lan mode printer /* if (obj_->is_lan_mode_printer()) { }*/ - if (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { show_status(PrintDialogStatus::PrintStatusNoSdcard); return; } @@ -1707,7 +1709,7 @@ void SendToPrinterDialog::update_show_status() show_status(PrintDialogStatus::PrintStatusReadingFinished); return; } else/* if (obj_->connection_type() == "cloud")*/ { - std::string dev_id = obj_->dev_ip; + std::string dev_id = obj_->get_dev_ip(); if (m_file_sys) { if (dev_id == m_device_select) { if ((m_waiting_enable && IsEnabled()) || (m_waiting_support && obj_->get_file_remote())) @@ -1887,7 +1889,7 @@ bool SendToPrinterDialog::is_blocking_printing(MachineObject* obj_) auto target_model = obj_->printer_type; if (source_model != target_model) { - std::vector compatible_machine = dev->get_compatible_machine(target_model); + std::vector compatible_machine = obj_->get_compatible_machine(); vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); if (it == compatible_machine.end()) { return true; @@ -2298,7 +2300,7 @@ void SendToPrinterDialog::fetchUrl(boost::weak_ptr wfs) } std::string dev_ver = obj->get_ota_version(); - std::string dev_id = obj->dev_id; + std::string dev_id = obj->get_dev_id(); int remote_proto = obj->get_file_remote(); if (!remote_proto) { m_waiting_support = true; @@ -2319,7 +2321,7 @@ void SendToPrinterDialog::fetchUrl(boost::weak_ptr wfs) if (agent) { if (m_tcp_try_connect) { - std::string devIP = obj->dev_ip; + std::string devIP = obj->get_dev_ip(); std::string accessCode = obj->get_access_code(); std::string tcp_url = "qidi:///local/" + devIP + "?port=6000&user=" + "qdtp" + "&passwd=" + accessCode; CallAfter([=] { @@ -2334,7 +2336,7 @@ void SendToPrinterDialog::fetchUrl(boost::weak_ptr wfs) } else if (m_tutk_try_connect){ std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""}; - agent->get_camera_url(obj->dev_id + "|" + dev_ver + "|" + protocols[1], [this, wfs, m = dev_id, v = agent->get_version(), dv = dev_ver](std::string url) { + agent->get_camera_url(obj->get_dev_id() + "|" + dev_ver + "|" + protocols[1], [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; @@ -2345,7 +2347,6 @@ void SendToPrinterDialog::fetchUrl(boost::weak_ptr wfs) } #if !QDT_RELEASE_TO_PUBLIC BOOST_LOG_TRIVIAL(info) << "SendToPrinter::fetchUrl: camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="}); - std::cout << "SendToPrinter::fetchUrl: camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="}); #endif CallAfter([=] { boost::shared_ptr fs(wfs.lock()); diff --git a/src/slic3r/GUI/SkipPartCanvas.cpp b/src/slic3r/GUI/SkipPartCanvas.cpp index a9df9fd..fba3a16 100644 --- a/src/slic3r/GUI/SkipPartCanvas.cpp +++ b/src/slic3r/GUI/SkipPartCanvas.cpp @@ -4,12 +4,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include wxDEFINE_EVENT(EVT_ZOOM_PERCENT, wxCommandEvent); wxDEFINE_EVENT(EVT_CANVAS_PART, wxCommandEvent); diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 709c816..d25830b 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -13,6 +13,7 @@ #include "MsgDialog.hpp" #include "slic3r/Utils/Http.hpp" #include "libslic3r/Thread.hpp" +#include "DeviceErrorDialog.hpp" #include "RecenterDialog.hpp" #include "CalibUtils.hpp" @@ -23,6 +24,17 @@ #include #include +#include "DeviceCore/DevBed.h" +#include "DeviceCore/DevCtrl.h" +#include "DeviceCore/DevFan.h" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevLamp.h" +#include "DeviceCore/DevStorage.h" + +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevPrintTaskInfo.h" + namespace Slic3r { namespace GUI { @@ -65,38 +77,6 @@ static wxColour PAGE_TITLE_FONT_COL = wxColour(107, 107, 107); static wxColour GROUP_TITLE_FONT_COL = wxColour(172, 172, 172); static wxColour TEXT_LIGHT_FONT_COL = wxColour(107, 107, 107); -static std::vector message_containing_retry{ - "0701 8004", - "0701 8005", - "0701 8006", - "0701 8006", - "0701 8007", - "0700 8012", - "0701 8012", - "0702 8012", - "0703 8012", - "07FF 8003", - "07FF 8004", - "07FF 8005", - "07FF 8006", - "07FF 8007", - "07FF 8010", - "07FF 8011", - "07FF 8012", - "07FF 8013", - "12FF 8007", - "1200 8006" -}; - -static std::vector message_containing_done{ - "07FF 8007", - "12FF 8007" -}; - -static std::vector message_containing_resume{ - "0300 8013" -}; - static wxImage fail_image; @@ -417,43 +397,37 @@ void ExtruderSwithingStatus::updateBy(MachineObject *obj) /*do not display while command sended in a mean while*/ if ((time(nullptr) - m_last_ctrl_time) > HOLD_TIME_6SEC) { - updateBy(obj->m_extder_data); + updateBy(obj->GetExtderSystem()); } } } -void ExtruderSwithingStatus::updateBy(const ExtderData& ext_data) +void ExtruderSwithingStatus::updateBy(const DevExtderSystem* ext_system) { - Show(ext_data.total_extder_count > 1); + Show(ext_system->GetTotalExtderCount() > 1); if (!IsShown()) { return; } - updateSwitchingLabel(ext_data.switch_extder_state); - updateBtnGroup(ext_data); -} + auto state = ext_system->GetSwitchState(); + { + if (state == DevExtderSwitchState::ES_SWITCHING) + { + m_switching_status_label->SetLabel(_L("Switching...")); + m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor("#262E30")); + m_switching_status_label->Show(true); + } + else if (state == DevExtderSwitchState::ES_SWITCHING_FAILED) + { + m_switching_status_label->SetLabel(_L("Switching failed")); + m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor(*wxRED)); + m_switching_status_label->Show(true); + } + else + { + m_switching_status_label->Show(false); + } + } -void ExtruderSwithingStatus::updateSwitchingLabel(const ExtruderSwitchState &state) -{ - if (state == ExtruderSwitchState::ES_SWITCHING) - { - m_switching_status_label->SetLabel(_L("Switching...")); - m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor("#262E30")); - m_switching_status_label->Show(true); - } - else if (state == ExtruderSwitchState::ES_SWITCHING_FAILED) - { - m_switching_status_label->SetLabel(_L("Switching failed")); - m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor(*wxRED)); - m_switching_status_label->Show(true); - } - else - { - m_switching_status_label->Show(false); - } -} - -void ExtruderSwithingStatus::updateBtnGroup(const ExtderData &ext_data) -{ - if (ext_data.switch_extder_state != ExtruderSwitchState::ES_SWITCHING_FAILED) + if (state != DevExtderSwitchState::ES_SWITCHING_FAILED) { showQuitBtn(false); showRetryBtn(false); @@ -696,12 +670,10 @@ void PrintingTaskPanel::create_panel(wxWindow* parent) wxBoxSizer *bSizer_buttons = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *bSizer_text = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *bSizer_finish_time = new wxBoxSizer(wxHORIZONTAL); - wxPanel* penel_bottons = new wxPanel(parent); wxPanel* penel_text = new wxPanel(progress_lr_panel); wxPanel* penel_finish_time = new wxPanel(progress_lr_panel); penel_text->SetBackgroundColour(*wxWHITE); - penel_bottons->SetBackgroundColour(*wxWHITE); penel_finish_time->SetBackgroundColour(*wxWHITE); wxBoxSizer *sizer_percent = new wxBoxSizer(wxVERTICAL); @@ -764,7 +736,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent) m_staticText_finish_day->Hide(); bSizer_finish_time->Add(0, 0, 1, wxEXPAND, 0); bSizer_finish_time->Add(m_staticText_finish_time, 0, wxLEFT | wxEXPAND, 0); - bSizer_finish_time->Add(m_staticText_finish_day, 0, wxLEFT | wxEXPAND | wxALIGN_CENTER_VERTICAL, FromDIP(10)); + bSizer_finish_time->Add(m_staticText_finish_day, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(10)); // penel_finish_time->SetMaxSize(wxSize(FromDIP(600), -1)); penel_finish_time->SetSizer(bSizer_finish_time); penel_finish_time->Layout(); @@ -1111,6 +1083,10 @@ void PrintingTaskPanel::enable_abort_button(bool enable) void PrintingTaskPanel::update_subtask_name(wxString name) { + if (m_staticText_subtask_value->GetLabelText() != name) + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << name; + } m_staticText_subtask_value->SetLabelText(name); } @@ -1427,6 +1403,11 @@ wxBoxSizer *StatusBasePanel::create_monitoring_page() m_staticText_timelapse->Hide(); bSizer_monitoring_title->Add(m_staticText_timelapse, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); + m_mqtt_source = new wxStaticText(m_panel_monitoring_title, wxID_ANY, "MqttSource", wxDefaultPosition, wxDefaultSize, 0); + m_mqtt_source->Wrap(-1); + m_mqtt_source->Hide(); + bSizer_monitoring_title->Add(m_mqtt_source, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); + m_bmToggleBtn_timelapse = new SwitchButton(m_panel_monitoring_title); m_bmToggleBtn_timelapse->SetMinSize(SWITCH_BUTTON_SIZE); m_bmToggleBtn_timelapse->Hide(); @@ -2101,13 +2082,22 @@ void StatusBasePanel::expand_filament_loading(wxMouseEvent& e) } else if (obj->is_series_o()) { - if (obj->get_current_extruder().id == MAIN_NOZZLE_ID) + const auto& ext_system = obj->GetExtderSystem(); + if (ext_system->GetTotalExtderCount() == 2) { - m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_right", this, load_img_size)); + int cur_extder_id = ext_system->GetCurrentExtderId(); + if (cur_extder_id == MAIN_EXTRUDER_ID) + { + m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_right", this, load_img_size)); + } + else if (cur_extder_id == DEPUTY_EXTRUDER_ID) + { + m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_left", this, load_img_size)); + } } - else if (obj->get_current_extruder().id == DEPUTY_NOZZLE_ID) + else { - m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_left", this, load_img_size)); + m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series", this, load_img_size)); } } } @@ -2152,7 +2142,9 @@ void StatusBasePanel::show_filament_load_group(bool show) m_img_filament_loading->SetBitmap(create_scaled_bitmap("filament_load_fold", this, 24)); } m_scale_panel->Show(show); - m_filament_step->SetupSteps(obj->get_current_extruder().ext_has_filament); + + auto cur_ext = obj->GetExtderSystem()->GetCurrentExtder(); + m_filament_step->SetupSteps(cur_ext ? cur_ext->HasFilamentInExt() : false); m_show_filament_group = show; Layout(); @@ -2167,21 +2159,22 @@ void StatusPanel::update_camera_state(MachineObject* obj) if (!obj) return; //sdcard - if (m_last_sdcard != (int)obj->get_sdcard_state()) { - if (obj->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + auto sdcard_state = obj->GetStorage()->get_sdcard_state(); + if (m_last_sdcard != sdcard_state) { + if (sdcard_state == DevStorage::NO_SDCARD) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_no.bmp()); m_bitmap_sdcard_img->SetToolTip(_L("No Storage")); - } else if (obj->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL) { + } else if (sdcard_state == DevStorage::HAS_SDCARD_NORMAL) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp()); m_bitmap_sdcard_img->SetToolTip(_L("Storage")); - } else if (obj->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL) { + } else if (sdcard_state == DevStorage::HAS_SDCARD_ABNORMAL) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_abnormal.bmp()); m_bitmap_sdcard_img->SetToolTip(_L("Storage Abnormal")); } else { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp()); m_bitmap_sdcard_img->SetToolTip(_L("Storage")); } - m_last_sdcard = (int)obj->get_sdcard_state(); + m_last_sdcard = sdcard_state; } //recording @@ -2277,12 +2270,12 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co if (id == m_tempCtrl_bed->GetType()) { on_set_bed_temp(); } else if (id == m_tempCtrl_nozzle->GetType()) { - if (e.GetString() == wxString::Format("%d", MAIN_NOZZLE_ID)) { - on_set_nozzle_temp(MAIN_NOZZLE_ID); - } else if (e.GetString() == wxString::Format("%d", DEPUTY_NOZZLE_ID)) { - on_set_nozzle_temp(DEPUTY_NOZZLE_ID); + if (e.GetString() == wxString::Format("%d", MAIN_EXTRUDER_ID)) { + on_set_nozzle_temp(MAIN_EXTRUDER_ID); + } else if (e.GetString() == wxString::Format("%d", DEPUTY_EXTRUDER_ID)) { + on_set_nozzle_temp(DEPUTY_EXTRUDER_ID); } else { - on_set_nozzle_temp(UNIQUE_NOZZLE_ID);//there is only one nozzle + on_set_nozzle_temp(UNIQUE_EXTRUDER_ID);//there is only one nozzle } } else if (id == m_tempCtrl_chamber->GetType()) { if (!m_tempCtrl_chamber->IsOnChanging()) { @@ -2345,9 +2338,8 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co Bind(EVT_AMS_GUIDE_WIKI, &StatusPanel::on_ams_guide, this); Bind(EVT_AMS_RETRY, &StatusPanel::on_ams_retry, this); Bind(EVT_FAN_CHANGED, &StatusPanel::on_fan_changed, this); - Bind(EVT_SECONDARY_CHECK_DONE, &StatusPanel::on_print_error_done, this); Bind(EVT_SECONDARY_CHECK_RESUME, &StatusPanel::on_subtask_pause_resume, this); - Bind(EVT_ERROR_DIALOG_BTN_CLICKED, &StatusPanel::on_print_error_dlg_btn_clicked, this); + Bind(EVT_SECONDARY_CHECK_RETRY, [this](auto &e) { if (m_ams_control) { m_ams_control->on_retry(); }}); m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); @@ -2399,9 +2391,6 @@ StatusPanel::~StatusPanel() m_parts_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this); // remove warning dialogs - if (m_print_error_dlg != nullptr) - delete m_print_error_dlg; - if (abort_dlg != nullptr) delete abort_dlg; @@ -2530,19 +2519,13 @@ void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event) { if (obj) { if (obj->can_resume()) { - BOOST_LOG_TRIVIAL(info) << "monitor: resume current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->dev_id); + BOOST_LOG_TRIVIAL(info) << "monitor: resume current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->get_dev_id()); obj->command_task_resume(); } else { - BOOST_LOG_TRIVIAL(info) << "monitor: pause current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->dev_id); + BOOST_LOG_TRIVIAL(info) << "monitor: pause current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->get_dev_id()); obj->command_task_pause(); } - if (m_print_error_dlg) { - m_print_error_dlg->on_hide(); - }if (m_print_error_dlg_no_action) { - m_print_error_dlg_no_action->on_hide(); - } - } } @@ -2552,7 +2535,7 @@ void StatusPanel::on_subtask_abort(wxCommandEvent &event) abort_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Cancel print")); abort_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this](wxCommandEvent &e) { if (obj) { - BOOST_LOG_TRIVIAL(info) << "monitor: stop current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->dev_id); + BOOST_LOG_TRIVIAL(info) << "monitor: stop current print task dev_id =" << QDTCrossTalk::Crosstalk_DevId(obj->get_dev_id()); obj->command_task_abort(); } }); @@ -2679,6 +2662,14 @@ void StatusPanel::update(MachineObject *obj) m_bmToggleBtn_timelapse->SetValue(obj->is_tunnel_mqtt); #endif +#if !QDT_RELEASE_TO_PUBLIC + if (obj->HasRecentCloudMessage() && obj->HasRecentLanMessage()) m_mqtt_source->SetLabel("Cloud+Lan"); + else if (obj->HasRecentCloudMessage()) m_mqtt_source->SetLabel("Cloud"); + else if (obj->HasRecentLanMessage()) m_mqtt_source->SetLabel("Lan"); + else m_mqtt_source->SetLabel("None"); + m_mqtt_source->Show(); +#endif + //m_machine_ctrl_panel->Freeze(); if (obj->is_in_printing() && !obj->can_resume()) { show_printing_status(false, true); @@ -2713,10 +2704,9 @@ void StatusPanel::update(MachineObject *obj) calibration_dlg->update_cali(obj); } - - - if (obj->is_support_first_layer_inspect - || obj->is_support_ai_monitoring + DevConfig* config = obj->GetConfig(); + if (config->SupportFirstLayerInspect() + || config->SupportAIMonitor() || obj->is_support_build_plate_marker_detect || obj->is_support_auto_recovery_step_loss) { m_options_btn->Show(); @@ -2730,20 +2720,20 @@ void StatusPanel::update(MachineObject *obj) m_parts_btn->Show(); if (!obj->dev_connection_type.empty()) { - auto iter_connect_type = m_print_connect_types.find(obj->dev_id); + auto iter_connect_type = m_print_connect_types.find(obj->get_dev_id()); if (iter_connect_type != m_print_connect_types.end()) { if (iter_connect_type->second != obj->dev_connection_type) { if (iter_connect_type->second == "lan" && obj->dev_connection_type == "cloud") { - m_print_connect_types[obj->dev_id] = obj->dev_connection_type; + m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type; } if (iter_connect_type->second == "cloud" && obj->dev_connection_type == "lan") { - m_print_connect_types[obj->dev_id] = obj->dev_connection_type; + m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type; } } } - m_print_connect_types[obj->dev_id] = obj->dev_connection_type; + m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type; } update_error_message(); @@ -2760,109 +2750,29 @@ void StatusPanel::show_recenter_dialog() { obj->command_go_home(); } -void StatusPanel::show_error_message(MachineObject *obj, bool is_exist, wxString msg, std::string print_error_str, wxString image_url, std::vector used_button) -{ - const std::string &dev_id = obj ? obj->dev_id : string(); - - if (is_exist && msg.IsEmpty()) { - error_info_reset(); - } else { - if (msg.IsEmpty()) { msg = _L("Unknown error."); } - m_project_task_panel->show_error_msg(msg); - - if (!used_button.empty()) { - BOOST_LOG_TRIVIAL(info) << "show print error! error_msg = " << msg; - if (m_print_error_dlg != nullptr) { - delete m_print_error_dlg; - m_print_error_dlg = nullptr; - } - - m_print_error_dlg = new PrintErrorDialog(this->GetParent(), wxID_ANY, _L("Error")); - m_print_error_dlg->update_title_style(_L("Error"), used_button, this); - m_print_error_dlg->update_text_image(msg, print_error_str, image_url); - m_print_error_dlg->on_show(); - } - else { - //old error code dialog - auto it_retry = std::find(message_containing_retry.begin(), message_containing_retry.end(), print_error_str); - auto it_done = std::find(message_containing_done.begin(), message_containing_done.end(), print_error_str); - auto it_resume = std::find(message_containing_resume.begin(), message_containing_resume.end(), print_error_str); - - BOOST_LOG_TRIVIAL(info) << "show print error! error_msg = " << msg; - - wxDateTime now = wxDateTime::Now(); - wxString show_time = now.Format("%H%M%d"); - wxString error_code_msg = wxString::Format("%S\n[%S %S]", msg, print_error_str, show_time); - - if (m_print_error_dlg_no_action != nullptr) { - delete m_print_error_dlg_no_action; - m_print_error_dlg_no_action = nullptr; - } - - m_print_error_dlg_no_action = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Warning"), SecondaryCheckDialog::ButtonStyle::ONLY_CONFIRM); - if (it_done != message_containing_done.end() && it_retry != message_containing_retry.end()) { - m_print_error_dlg_no_action->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::DONE_AND_RETRY, this); - } - else if (it_done != message_containing_done.end()) { - m_print_error_dlg_no_action->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_DONE, this); - } - else if (it_retry != message_containing_retry.end()) { - m_print_error_dlg_no_action->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RETRY, this); - } - else if (it_resume != message_containing_resume.end()) { - m_print_error_dlg_no_action->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RESUME, this); - } - else { - m_print_error_dlg_no_action->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::ONLY_CONFIRM, this); - } - m_print_error_dlg_no_action->update_text(error_code_msg); - m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, dev_id](wxCommandEvent &e) { - MachineObject *the_obj = wxGetApp().getDeviceManager()->get_my_machine(dev_id); - if (the_obj) { the_obj->command_clean_print_error(the_obj->subtask_id_, the_obj->print_error); } - }); - - m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_RETRY, [this](wxCommandEvent& e) { - if (m_ams_control) { - m_ams_control->on_retry(); - } - }); - - m_print_error_dlg_no_action->on_show(); - } - wxGetApp().mainframe->RequestUserAttention(wxUSER_ATTENTION_ERROR); - } -} void StatusPanel::update_error_message() { + if (!obj) return; + + static int last_error = -1; + if (obj->print_error <= 0) { - before_error_code = obj->print_error; - show_error_message(obj, true, wxEmptyString); - return; - } else if (before_error_code != obj->print_error && obj->print_error != skip_print_error) { - before_error_code = obj->print_error; + error_info_reset(); + } else if (obj->print_error != last_error) { + /* clear old dialog */ + if (m_print_error_dlg) { delete m_print_error_dlg; } - if (wxGetApp().get_hms_query()) { - char buf[32]; - ::sprintf(buf, "%08X", obj->print_error); - std::string print_error_str = std::string(buf); - if (print_error_str.size() > 4) { print_error_str.insert(4, "-"); } + /* show device error message*/ + m_print_error_dlg = new DeviceErrorDialog(obj, this); + wxString error_msg = m_print_error_dlg->show_error_code(obj->print_error); + BOOST_LOG_TRIVIAL(info) << "print error: device error code = "<< obj->print_error; - wxString error_msg = wxGetApp().get_hms_query()->query_print_error_msg(obj, obj->print_error); - if (wxGetApp().get_hms_query()->is_internal_error(obj, obj->print_error)) - { - return; - } - - std::vector used_button; - wxString error_image_url = wxGetApp().get_hms_query()->query_print_image_action(obj, obj->print_error, used_button); - // special case - if (print_error_str == "0300-8003" || print_error_str == "0300-8002" || print_error_str == "0300-800A") { - used_button.emplace_back(PrintErrorDialog::PrintErrorButton::JUMP_TO_LIVEVIEW); - } - show_error_message(obj, !error_msg.empty(), error_msg, print_error_str, error_image_url, used_button); - } + /* show error message on task panel */ + if(!error_msg.IsEmpty()) { m_project_task_panel->show_error_msg(error_msg); } } + + last_error = obj->print_error; } void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area) @@ -2894,7 +2804,7 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area) m_bpButton_e_10->Enable(); m_bpButton_e_down_10->Enable(); - m_bpButton_z_10->SetIcon("monitor_bed_up"); + m_bpButton_z_10->SetIcon("monitor_bed_up"); m_bpButton_z_1->SetIcon("monitor_bed_up"); m_bpButton_z_down_1->SetIcon("monitor_bed_down"); m_bpButton_z_down_10->SetIcon("monitor_bed_down"); @@ -2936,7 +2846,10 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj) { if (!obj) return; - m_tempCtrl_bed->SetCurrTemp((int) obj->bed_temp); + DevBed* bed = obj->GetBed(); + int bed_cur_temp = bed->GetBedTemp(); + int bed_target_temp = bed->GetBedTempTarget(); + m_tempCtrl_bed->SetCurrTemp((int) bed_cur_temp); auto limit = obj->get_bed_temperature_limit(); if (obj->bed_temp_range.size() > 1) { @@ -2956,52 +2869,67 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj) if (m_temp_bed_timeout > 0) { m_temp_bed_timeout--; } else { - if (!bed_temp_input) { m_tempCtrl_bed->SetTagTemp((int) obj->bed_temp_target); } + if (!bed_temp_input) { m_tempCtrl_bed->SetTagTemp((int) bed_target_temp); } } - if ((obj->bed_temp_target - obj->bed_temp) >= TEMP_THRESHOLD_VAL) { + if ((bed_target_temp - bed_cur_temp) >= TEMP_THRESHOLD_VAL) { m_tempCtrl_bed->SetIconActive(); } else { m_tempCtrl_bed->SetIconNormal(); } bool to_update_layout = false; - int nozzle_num = obj->m_extder_data.total_extder_count; - if (nozzle_num == 1 && obj->m_extder_data.extders.size() > MAIN_NOZZLE_ID) + int nozzle_num = obj->GetExtderSystem()->GetTotalExtderCount(); + if (nozzle_num == 1) { + m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID)); m_tempCtrl_nozzle->SetCurrType(TEMP_OF_NORMAL_TYPE); - m_tempCtrl_nozzle->SetCurrTemp((int)obj->m_extder_data.extders[MAIN_NOZZLE_ID].temp); + + m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_NORMAL_TYPE); + m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR); + m_tempCtrl_nozzle_deputy->Hide(); + if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON) { to_update_layout = true; m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON); } - - m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_NORMAL_TYPE); - m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR); - m_tempCtrl_nozzle_deputy->Hide(); } - else if (nozzle_num == 2 && obj->m_extder_data.extders.size() > 1) + else if (nozzle_num == 2) { m_tempCtrl_nozzle->SetCurrType(TEMP_OF_MAIN_NOZZLE_TYPE); + m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID)); m_tempCtrl_nozzle->Show(); - m_tempCtrl_nozzle->SetCurrTemp((int)obj->m_extder_data.extders[MAIN_NOZZLE_ID].temp); + + m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_DEPUTY_NOZZLE_TYPE); + m_tempCtrl_nozzle_deputy->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(DEPUTY_EXTRUDER_ID)); + m_tempCtrl_nozzle_deputy->Show(); + if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON) { to_update_layout = true; m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON); } - - m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_DEPUTY_NOZZLE_TYPE); - m_tempCtrl_nozzle_deputy->Show(); - m_tempCtrl_nozzle_deputy->SetCurrTemp((int)obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].temp); } if (m_temp_nozzle_timeout > 0) { m_temp_nozzle_timeout--; } else { if (!nozzle_temp_input) { - m_tempCtrl_nozzle->SetTagTemp((int) obj->m_extder_data.extders[MAIN_NOZZLE_ID].target_temp); + auto main_extder = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); + if (main_extder) + { + m_tempCtrl_nozzle->SetTagTemp(main_extder->GetTargetTemp()); + m_tempCtrl_nozzle->SetCurrTemp((int)main_extder->GetCurrentTemp()); + if (main_extder->GetTargetTemp() - main_extder->GetCurrentTemp() > TEMP_THRESHOLD_VAL) + { + m_tempCtrl_nozzle->SetIconActive(); + } + else + { + m_tempCtrl_nozzle->SetIconNormal(); + } + } } } @@ -3010,22 +2938,20 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj) } else { if (!nozzle_temp_input && nozzle_num >= 2) { - m_tempCtrl_nozzle_deputy->SetTagTemp((int)obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].target_temp); - } - } - - if ((obj->m_extder_data.extders[MAIN_NOZZLE_ID].target_temp - obj->m_extder_data.extders[MAIN_NOZZLE_ID].temp) >= TEMP_THRESHOLD_VAL) { - m_tempCtrl_nozzle->SetIconActive(); - } else { - m_tempCtrl_nozzle->SetIconNormal(); - } - - if (nozzle_num >= 2 && obj->m_extder_data.extders.size() > 1){ - if ((obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].target_temp - obj->m_extder_data.extders[DEPUTY_NOZZLE_ID].temp) >= TEMP_THRESHOLD_VAL) { - m_tempCtrl_nozzle_deputy->SetIconActive(); - } - else { - m_tempCtrl_nozzle_deputy->SetIconNormal(); + auto deputy_extder = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID); + if (deputy_extder) + { + m_tempCtrl_nozzle_deputy->SetTagTemp(deputy_extder->GetTargetTemp()); + m_tempCtrl_nozzle_deputy->SetCurrTemp((int)deputy_extder->GetCurrentTemp()); + if (deputy_extder->GetTargetTemp() - deputy_extder->GetCurrentTemp() > TEMP_THRESHOLD_VAL) + { + m_tempCtrl_nozzle_deputy->SetIconActive(); + } + else + { + m_tempCtrl_nozzle_deputy->SetIconNormal(); + } + } } } @@ -3040,12 +2966,13 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj) } // support edit chamber temp - if (obj->is_support_chamber_edit) + DevConfig* config = obj->GetConfig(); + if (config->SupportChamberEdit()) { m_tempCtrl_chamber->SetReadOnly(false); m_tempCtrl_chamber->Enable(); - m_tempCtrl_chamber->SetMinTemp(obj->chamber_temp_edit_min); - m_tempCtrl_chamber->SetMaxTemp(obj->chamber_temp_edit_max); + m_tempCtrl_chamber->SetMinTemp(config->GetChamberTempEditMin()); + m_tempCtrl_chamber->SetMaxTemp(config->GetChamberTempEditMax()); m_tempCtrl_chamber->AddTemp(0); // zero is default temp wxCursor cursor(wxCURSOR_IBEAM); m_tempCtrl_chamber->GetTextCtrl()->SetCursor(cursor); @@ -3093,7 +3020,8 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) if (!obj) return; /*extder*/ - m_nozzle_num = obj->m_extder_data.total_extder_count; + auto extder_system = obj->GetExtderSystem(); + m_nozzle_num = extder_system->GetTotalExtderCount(); int select_index = m_nozzle_num - 1; if (m_nozzle_num >= 2) { @@ -3103,41 +3031,37 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) m_nozzle_btn_panel->Show(); m_extruderImage[select_index]->setExtruderCount(m_nozzle_num); - assert(obj->m_extder_data.extders.size() > 1); - if (obj->m_extder_data.extders.size() > 1) + if (obj->GetExtderSystem()->GetTotalExtderSize() > 1) { - const Extder& left_extder = obj->m_extder_data.extders[0]; - const Extder& right_extder = obj->m_extder_data.extders[1]; - m_extruderImage[select_index]->update(get_extder_shown_state(left_extder.ext_has_filament), - get_extder_shown_state(right_extder.ext_has_filament)); + m_extruderImage[select_index]->update(get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(0)), + get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(1))); } /*current*/ /*update when extder position changed or the machine changed*/ - if (obj->flag_update_nozzle || (m_nozzle_btn_panel->GetClientData() != obj)) + if (obj->GetExtderSystem()->GetCurrentExtderId() == 0xf) { - if (obj->m_extder_data.current_extder_id == 0xf) { - m_extruderImage[select_index]->setExtruderUsed(""); - m_nozzle_btn_panel->updateState(""); - } - else if (obj->m_extder_data.current_extder_id == MAIN_NOZZLE_ID) { - m_extruderImage[select_index]->setExtruderUsed("right"); - m_nozzle_btn_panel->updateState("right"); - } - else if (obj->m_extder_data.current_extder_id == DEPUTY_NOZZLE_ID) { - m_extruderImage[select_index]->setExtruderUsed("left"); - m_nozzle_btn_panel->updateState("left"); - } - - obj->flag_update_nozzle = false; - m_nozzle_btn_panel->SetClientData(obj); + m_extruderImage[select_index]->setExtruderUsed(""); + m_nozzle_btn_panel->updateState(""); } + else if (obj->GetExtderSystem()->GetCurrentExtderId() == MAIN_EXTRUDER_ID) + { + m_extruderImage[select_index]->setExtruderUsed("right"); + m_nozzle_btn_panel->updateState("right"); + } + else if (obj->GetExtderSystem()->GetCurrentExtderId() == DEPUTY_EXTRUDER_ID) + { + m_extruderImage[select_index]->setExtruderUsed("left"); + m_nozzle_btn_panel->updateState("left"); + } + + m_nozzle_btn_panel->SetClientData(obj); /*enable status*/ /* Can do switch while printing pause STUDIO-9789*/ if ((obj->is_in_printing() && !obj->is_in_printing_pause()) || obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE || - obj->targ_nozzle_id_from_pc != INVALID_NOZZLE_ID) + obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID) { m_nozzle_btn_panel->Disable(); } @@ -3150,19 +3074,14 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) m_extruder_book->SetSelection(m_nozzle_num); m_extruderImage[select_index]->setExtruderCount(m_nozzle_num); - assert(!obj->m_extder_data.extders.empty()); - if (!obj->m_extder_data.extders.empty()) + if (extder_system->GetTotalExtderSize() > 0) { - const Extder& extder = obj->m_extder_data.extders[0]; - ExtruderState shown_state = get_extder_shown_state(extder.ext_has_filament); + ExtruderState shown_state = get_extder_shown_state(extder_system->HasFilamentInExt(0)); m_extruderImage[select_index]->update(shown_state); } } /*switch extder*/ - /*for (auto i = 0; i < obj->m_extder_data.extders.size(); i++) { - obj->m_extder_data.extders[i].ams_stat; - }*/ m_extruder_switching_status->updateBy(obj); m_extruder_label->Show(!m_extruder_switching_status->has_content_shown());/*hide the label if there are shown infos from m_extruder_switching_status*/ @@ -3180,8 +3099,8 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) if (!m_fan_panel->IsShown()) m_fan_panel->Show(); bool is_suppt_part_fun = true; - bool is_suppt_aux_fun = obj->is_support_aux_fan; - bool is_suppt_cham_fun = obj->is_support_chamber_fan; + bool is_suppt_aux_fun = obj->GetFan()->GetSupportAuxFanData(); + bool is_suppt_cham_fun = obj->GetFan()->GetSupportChamberFan(); if (m_fan_control_popup) { m_fan_control_popup->update_fan_data(obj); } } else { if (m_fan_panel->IsShown()) { @@ -3196,7 +3115,7 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) //update cham fan /*other*/ - bool light_on = obj->chamber_light != MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_OFF; + bool light_on = obj->GetLamp()->IsChamberLightOn(); BOOST_LOG_TRIVIAL(trace) << "light: " << light_on ? "on" : "off"; if (m_switch_lamp_timeout > 0) m_switch_lamp_timeout--; @@ -3210,7 +3129,7 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj) speed_lvl_timeout--; else { // update speed - this->speed_lvl = obj->printing_speed_lvl; + this->speed_lvl = obj->GetPrintingSpeedLevel(); wxString text_speed = wxString::Format("%d%%", obj->printing_speed_mag); m_switch_speed->SetLabels(text_speed, text_speed); } @@ -3229,9 +3148,9 @@ void StatusPanel::update_ams(MachineObject *obj) if (obj && m_ams_setting_dlg->IsShown()) { update_ams_insert_material(obj); - m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag); - m_ams_setting_dlg->update_remain_mode(obj->ams_calibrate_remain_flag); - m_ams_setting_dlg->update_switch_filament(obj->ams_auto_switch_filament_flag); + m_ams_setting_dlg->update_starting_read_mode(obj->GetFilaSystem()->IsDetectOnPowerupEnabled()); + m_ams_setting_dlg->update_remain_mode(obj->GetFilaSystem()->IsDetectRemainEnabled()); + m_ams_setting_dlg->update_switch_filament(obj->GetFilaSystem()->IsAutoRefillEnabled()); m_ams_setting_dlg->update_air_printing_detection(obj->ams_air_print_status); } } @@ -3240,7 +3159,7 @@ void StatusPanel::update_ams(MachineObject *obj) if (obj && (obj->last_cali_version != obj->cali_version)) { obj->last_cali_version = obj->cali_version; PACalibExtruderInfo cali_info; - cali_info.nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + cali_info.nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0); cali_info.use_extruder_id = false; cali_info.use_nozzle_volume_type = false; CalibUtils::emit_get_PA_calib_infos(cali_info); @@ -3252,9 +3171,13 @@ void StatusPanel::update_ams(MachineObject *obj) if (obj) { if (obj->get_printer_ams_type() == "f1") { ams_mode = AMSModel::AMS_LITE; } - obj->check_ams_filament_valid(); + if (obj->is_security_control_ready()) + obj->check_ams_filament_valid(); } - if (obj->is_enable_np && obj->amsList.size() > 0) { ams_mode = AMSModel(obj->amsList.begin()->second->type); } + if (obj->is_enable_np && obj->GetFilaSystem()->GetAmsList().size() > 0) { + ams_mode = AMSModel(obj->GetFilaSystem()->GetAmsList().begin()->second->GetAmsType()); + } + if (!obj || !obj->is_connected()) { last_tray_exist_bits = -1; last_ams_exist_bits = -1; @@ -3262,7 +3185,7 @@ void StatusPanel::update_ams(MachineObject *obj) last_read_done_bits = -1; last_reading_bits = -1; last_ams_version = -1; - BOOST_LOG_TRIVIAL(trace) << "machine object" << QDTCrossTalk::Crosstalk_DevName(obj->dev_name) << " was disconnected, set show_ams_group is false"; + BOOST_LOG_TRIVIAL(trace) << "machine object" << QDTCrossTalk::Crosstalk_DevName(obj->get_dev_name()) << " was disconnected, set show_ams_group is false"; m_ams_control->SetAmsModel(AMSModel::EXT_AMS, ams_mode); show_ams_group(false); @@ -3274,7 +3197,7 @@ void StatusPanel::update_ams(MachineObject *obj) show_ams_group(true); //show_filament_load_group(true); - if (obj->amsList.empty() || obj->ams_exist_bits == 0) { + if (obj->GetFilaSystem()->GetAmsList().empty() || obj->ams_exist_bits == 0) { m_ams_control->show_auto_refill(false); m_ams_control->enable_ams_setting(false); } else { @@ -3286,12 +3209,13 @@ void StatusPanel::update_ams(MachineObject *obj) //if (is_support_virtual_tray) m_ams_control->update_vams_kn_value(obj->vt_slot[0], obj); if (m_filament_setting_dlg) m_filament_setting_dlg->update(); + std::vector ams_info; - ams_info.clear(); - for (auto ams = obj->amsList.begin(); ams != obj->amsList.end(); ams++) { + const auto& ams_list = obj->GetFilaSystem()->GetAmsList(); + for (auto ams = ams_list.begin(); ams != ams_list.end(); ams++) { AMSinfo info; info.ams_id = ams->first; - if (ams->second->is_exists && info.parse_ams_info(obj, ams->second, obj->ams_calibrate_remain_flag, obj->is_support_ams_humidity)) { + if (ams->second->IsExist() && info.parse_ams_info(obj, ams->second, false, obj->is_support_ams_humidity)) { if (ams_mode == AMSModel::AMS_LITE) { info.ams_type = AMSModel::AMS_LITE; } ams_info.push_back(info); } @@ -3305,11 +3229,9 @@ void StatusPanel::update_ams(MachineObject *obj) if (ams_mode == AMSModel::AMS_LITE) info.ext_type = AMSModelOriginType::LITE_EXT; ext_info.push_back(info); } - std::string dev_id = obj->dev_id; - ExtderData data = obj->m_extder_data; // must select a current can - m_ams_control->UpdateAms(obj->get_printer_series_str(), obj->printer_type, ams_info, ext_info, data, dev_id, false); + m_ams_control->UpdateAms(obj->get_printer_series_str(), obj->printer_type, ams_info, ext_info, *obj->GetExtderSystem(), obj->get_dev_id(), false); last_tray_exist_bits = obj->tray_exist_bits; last_ams_exist_bits = obj->ams_exist_bits; @@ -3321,7 +3243,7 @@ void StatusPanel::update_ams(MachineObject *obj) std::string curr_ams_id = m_ams_control->GetCurentAms(); std::string curr_can_id = m_ams_control->GetCurrentCan(curr_ams_id); bool is_vt_tray = false; - if (obj->m_tray_tar == std::to_string(VIRTUAL_TRAY_MAIN_ID)) is_vt_tray = true; + if (obj->GetExtderSystem()->GetCurrentAmsId() == std::to_string(VIRTUAL_TRAY_MAIN_ID)) is_vt_tray = true; // set segment 1, 2 //if (!obj->is_enable_np) { @@ -3346,41 +3268,40 @@ void StatusPanel::update_ams(MachineObject *obj) // m_ams_control->SetExtruder(obj->is_filament_at_extruder(), obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id); //} else { /*right*/ - if (obj->m_extder_data.extders.size() > 0) { - auto ext = obj->m_extder_data.extders[MAIN_NOZZLE_ID]; - if (ext.ext_has_filament) { - if (ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - m_ams_control->SetAmsStep(ext.snow.ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); - } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); - } + if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) { + auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); + if (ext->HasFilamentInExt()) { + if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); } - m_ams_control->SetExtruder(ext.ext_has_filament, MAIN_NOZZLE_ID, ext.snow.ams_id, ext.snow.slot_id); + } else { + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); } + m_ams_control->SetExtruder(ext->HasFilamentInExt(), MAIN_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id); + } - /*left*/ - if (obj->m_extder_data.extders.size() > 1) { - auto ext = obj->m_extder_data.extders[DEPUTY_NOZZLE_ID]; - if (ext.ext_has_filament) { - if (ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - m_ams_control->SetAmsStep(ext.snow.ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); - } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); - } + /*left*/ + if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) { + auto ext = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID); + if (ext->HasFilamentInExt()) { + if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); } - m_ams_control->SetExtruder(ext.ext_has_filament, DEPUTY_NOZZLE_ID, ext.snow.ams_id, ext.snow.slot_id); + } else { + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); } - //} + m_ams_control->SetExtruder(ext->HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id); + } bool ams_loading_state = false; auto ams_status_sub = obj->ams_status_sub; if (obj->is_enable_np) { - if (obj->m_extder_data.current_busy_for_loading) { + if (obj->GetExtderSystem()->IsBusyLoading()) { ams_loading_state = true; } } else if (obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { @@ -3389,26 +3310,17 @@ void StatusPanel::update_ams(MachineObject *obj) if (ams_loading_state) { update_load_with_temp(); - m_filament_step->updateID(std::atoi(obj->m_ams_id.c_str()), std::atoi(obj->m_tray_id.c_str())); - bool busy_for_vt_loading = false; - if (!obj->is_enable_np) { - busy_for_vt_loading = (obj->m_tray_tar == "254" && (obj->m_tray_now != "254" || obj->m_tray_now != "255")); - } else { - if (obj->m_extder_data.current_busy_for_loading && obj->m_extder_data.current_loading_extder_id != -1 ) { - auto tar = obj->m_extder_data.extders[obj->m_extder_data.current_loading_extder_id].star; - auto now = obj->m_extder_data.extders[obj->m_extder_data.current_loading_extder_id].snow; - - if ((tar.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || tar.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) && - (tar.slot_id == std::to_string(VIRTUAL_TRAY_MAIN_ID))) { - busy_for_vt_loading = false; - } else if ((tar.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || tar.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) && - ((now.ams_id != std::to_string(VIRTUAL_TRAY_MAIN_ID) || now.ams_id != std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) || (now.ams_id != "255"))) { - busy_for_vt_loading = true; - } - } + const std::string& cur_ams_id = obj->GetExtderSystem()->GetCurrentAmsId(); + const std::string& cur_tray_id = obj->GetExtderSystem()->GetCurrentSlotId(); + if (!cur_ams_id.empty() && !cur_tray_id.empty()) + { + m_filament_step->updateID(std::atoi(cur_ams_id.c_str()), std::atoi(cur_tray_id.c_str())); } + auto loading_ext = obj->GetExtderSystem()->GetLoadingExtder(); + auto tar = loading_ext ? loading_ext->GetSlotTarget() : DevAmsSlotInfo(); + bool busy_for_vt_loading = (tar.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || tar.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)); if (busy_for_vt_loading) { // wait to heat hotend if (ams_status_sub == 0x02) { @@ -3499,11 +3411,12 @@ void StatusPanel::update_ams(MachineObject *obj) show_filament_load_group(ams_loading_state); - for (auto ams_it = obj->amsList.begin(); ams_it != obj->amsList.end(); ams_it++) { + const auto& amslist = obj->GetFilaSystem()->GetAmsList(); + for (auto ams_it = amslist.begin(); ams_it != amslist.end(); ams_it++) { std::string ams_id = ams_it->first; try { int ams_id_int = atoi(ams_id.c_str()); - for (auto tray_it = ams_it->second->trayList.begin(); tray_it != ams_it->second->trayList.end(); tray_it++) { + for (auto tray_it = ams_it->second->GetTrays().begin(); tray_it != ams_it->second->GetTrays().end(); tray_it++) { std::string tray_id = tray_it->first; int tray_id_int = atoi(tray_id.c_str()); // new protocol @@ -3532,10 +3445,10 @@ void StatusPanel::update_ams_insert_material(MachineObject* obj) { std::string extra_ams_str = (boost::format("box_f1/%1%") % 0).str(); auto extra_ams_it = obj->module_vers.find(extra_ams_str); if (extra_ams_it != obj->module_vers.end()) { - m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag, extra_ams_it->second.sw_ver); + m_ams_setting_dlg->update_insert_material_read_mode(obj->GetFilaSystem()->IsDetectOnInsertEnabled(), extra_ams_it->second.sw_ver); } else { - m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag, ""); + m_ams_setting_dlg->update_insert_material_read_mode(obj->GetFilaSystem()->IsDetectOnInsertEnabled(), ""); } } @@ -3554,7 +3467,7 @@ void StatusPanel::update_ams_control_state(std::string ams_id, std::string slot_ bool in_switch_filament = false; if (obj->is_enable_np) { - if (obj->m_extder_data.current_busy_for_loading) { in_switch_filament = true; } + if (obj->GetExtderSystem()->IsBusyLoading()) { in_switch_filament = true; } } else if (obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { in_switch_filament = true; } @@ -3568,29 +3481,35 @@ void StatusPanel::update_ams_control_state(std::string ams_id, std::string slot_ load_error_info = _L("Choose an BOX slot then press \"Load\" or \"Unload\" button to automatically load or unload filaments."); unload_error_info = _L("Choose an BOX slot then press \"Load\" or \"Unload\" button to automatically load or unload filaments."); } else if (ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - for (auto ext : obj->m_extder_data.extders) { - if (ext.snow.ams_id == ams_id && ext.snow.slot_id == slot_id) { + for (auto ext : obj->GetExtderSystem()->GetExtruders()) { + if (ext.GetSlotNow().ams_id == ams_id && ext.GetSlotNow().slot_id == slot_id) + { load_error_info = _L("Current slot has alread been loaded"); } } } else { - for (auto ext : obj->m_extder_data.extders) { - if (ext.snow.ams_id == ams_id && ext.snow.slot_id == slot_id) { + for (auto ext : obj->GetExtderSystem()->GetExtruders()) { + if (ext.GetSlotNow().ams_id == ams_id && ext.GetSlotNow().slot_id == slot_id) + { load_error_info = _L("Current slot has alread been loaded"); } } /*empty*/ - std::map::iterator it = obj->amsList.find(ams_id); - if (it == obj->amsList.end()) { + auto ams_item = obj->GetFilaSystem()->GetAmsById(ams_id); + if (!ams_item) + { load_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filaments."); - } else { - auto tray_it = it->second->trayList.find(slot_id); - if (tray_it == it->second->trayList.end()) { + } + else + { + auto tray_item = ams_item->GetTray(slot_id); + if (!tray_item) + { load_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filaments."); } - - if (!tray_it->second->is_exists) { + else if (!tray_item->is_exists) + { load_error_info = _L("The selected slot is empty."); } } @@ -3697,16 +3616,19 @@ void StatusPanel::update_subtask(MachineObject *obj) if (m_calib_method == CALI_METHOD_AUTO) { if (m_calib_mode == CalibMode::Calib_PA_Line) { if (obj->is_multi_extruders()) { - if (obj->m_extder_data.current_extder_id == 0) { + int cur_ext_id = obj->GetExtderSystem()->GetCurrentExtderId(); + if (cur_ext_id == 0) { png_path = (boost::format("%1%/images/fd_calibration_auto_multi_extruders_right.png") % resources_dir()).str(); } else { - assert(obj->m_extder_data.current_extder_id == 1); + assert(cur_ext_id == 1); png_path = (boost::format("%1%/images/fd_calibration_auto_multi_extruders_left.png") % resources_dir()).str(); } } else if (obj->get_printer_arch() == PrinterArch::ARCH_I3) png_path = (boost::format("%1%/images/fd_calibration_auto_i3.png") % resources_dir()).str(); + else if (obj->is_series_o()) + png_path = (boost::format("%1%/images/fd_calibration_auto_single_o.png") % resources_dir()).str(); else png_path = (boost::format("%1%/images/fd_calibration_auto.png") % resources_dir()).str(); } @@ -3998,55 +3920,42 @@ void StatusPanel::reset_printing_values() void StatusPanel::on_axis_ctrl_xy(wxCommandEvent &event) { if (!obj) return; - if (event.GetInt() == 0) { obj->command_axis_control("Y", 1.0, 10.0f, 3000); } - if (event.GetInt() == 1) { obj->command_axis_control("X", 1.0, -10.0f, 3000); } - if (event.GetInt() == 2) { obj->command_axis_control("Y", 1.0, -10.0f, 3000); } - if (event.GetInt() == 3) { obj->command_axis_control("X", 1.0, 10.0f, 3000); } - if (event.GetInt() == 4) { obj->command_axis_control("Y", 1.0, 1.0f, 3000); } - if (event.GetInt() == 5) { obj->command_axis_control("X", 1.0, -1.0f, 3000); } - if (event.GetInt() == 6) { obj->command_axis_control("Y", 1.0, -1.0f, 3000); } - if (event.GetInt() == 7) { obj->command_axis_control("X", 1.0, 1.0f, 3000); } - if (event.GetInt() == 8) { + + //check is at home + static std::unordered_set s_x_ctrl_idxes { 1, 3, 5, 7}; + static std::unordered_set s_y_ctrl_idxes{ 0, 2, 4, 6 }; + if (s_x_ctrl_idxes.count(event.GetInt()) != 0 && !obj->is_axis_at_home("X")) + { + BOOST_LOG_TRIVIAL(info) << "axis x is not at home"; + show_recenter_dialog(); + return; + } + else if (s_y_ctrl_idxes.count(event.GetInt()) != 0 && !obj->is_axis_at_home("Y")) + { + BOOST_LOG_TRIVIAL(info) << "axis y is not at home"; + show_recenter_dialog(); + return; + } + + if (event.GetInt() == 0) { obj->command_axis_control("Y", 1.0, 10.0f, 3000); } + else if (event.GetInt() == 1) { obj->command_axis_control("X", 1.0, -10.0f, 3000); } + else if (event.GetInt() == 2) { obj->command_axis_control("Y", 1.0, -10.0f, 3000); } + else if (event.GetInt() == 3) { obj->command_axis_control("X", 1.0, 10.0f, 3000); } + else if (event.GetInt() == 4) { obj->command_axis_control("Y", 1.0, 1.0f, 3000); } + else if (event.GetInt() == 5) { obj->command_axis_control("X", 1.0, -1.0f, 3000); } + else if (event.GetInt() == 6) { obj->command_axis_control("Y", 1.0, -1.0f, 3000); } + else if (event.GetInt() == 7) { obj->command_axis_control("X", 1.0, 1.0f, 3000); } + else if (event.GetInt() == 8) { if (axis_go_home_dlg == nullptr) { axis_go_home_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Auto homing")); axis_go_home_dlg->update_text(_L("Are you sure you want to trigger auto homing?")); axis_go_home_dlg->m_button_ok->SetLabel(_L("Homing")); axis_go_home_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this](wxCommandEvent& e) { - if (obj) { - BOOST_LOG_TRIVIAL(info) << "Axis have go home"; - if (obj->is_support_command_homing) { - obj->command_go_home2(); - } else { - obj->command_go_home(); - } - - } + if (obj) { obj->command_go_home(); } }); } axis_go_home_dlg->on_show(); } - - //check is at home - if (event.GetInt() == 1 - || event.GetInt() == 3 - || event.GetInt() == 5 - || event.GetInt() == 7) { - if (!obj->is_axis_at_home("X")) { - BOOST_LOG_TRIVIAL(info) << "axis x is not at home"; - show_recenter_dialog(); - return; - } - } - else if (event.GetInt() == 0 - || event.GetInt() == 2 - || event.GetInt() == 4 - || event.GetInt() == 6) { - if (!obj->is_axis_at_home("Y")) { - BOOST_LOG_TRIVIAL(info) << "axis y is not at home"; - show_recenter_dialog(); - return; - } - } } bool StatusPanel::check_axis_z_at_home(MachineObject* obj) @@ -4117,10 +4026,10 @@ void StatusPanel::axis_ctrl_e_hint(bool up_down) void StatusPanel::on_axis_ctrl_e_up_10(wxCommandEvent &event) { if (obj) { - auto current_nozzle_id = obj->m_extder_data.current_extder_id; - if (obj->m_extder_data.extders[current_nozzle_id].temp >= TEMP_THRESHOLD_ALLOW_E_CTRL) + auto ext = obj->GetExtderSystem()->GetCurrentExtder(); + if (ext && ext->GetCurrentTemp() >= TEMP_THRESHOLD_ALLOW_E_CTRL) if (obj->is_enable_np) { - obj->command_extruder_control(current_nozzle_id, -10.0f); + obj->command_extruder_control(ext->GetExtId(), -10.0f); } else { obj->command_axis_control("E", 1.0, -10.0f, 900); } @@ -4133,10 +4042,10 @@ void StatusPanel::on_axis_ctrl_e_up_10(wxCommandEvent &event) void StatusPanel::on_axis_ctrl_e_down_10(wxCommandEvent &event) { if (obj) { - auto current_nozzle_id = obj->m_extder_data.current_extder_id; - if (obj->m_extder_data.extders[current_nozzle_id].temp >= TEMP_THRESHOLD_ALLOW_E_CTRL) + auto ext = obj->GetExtderSystem()->GetCurrentExtder(); + if (ext && ext->GetCurrentTemp() >= TEMP_THRESHOLD_ALLOW_E_CTRL) if (obj->is_enable_np) { - obj->command_extruder_control(current_nozzle_id, 10.0f); + obj->command_extruder_control(ext->GetExtId(), 10.0f); } else { obj->command_axis_control("E", 1.0, 10.0f, 900); } @@ -4180,7 +4089,7 @@ void StatusPanel::on_set_nozzle_temp(int nozzle_id) try { long nozzle_temp; - if (nozzle_id == MAIN_NOZZLE_ID) { + if (nozzle_id == MAIN_EXTRUDER_ID) { wxString str = m_tempCtrl_nozzle->GetTextCtrl()->GetValue(); if (str.ToLong(&nozzle_temp) && obj) { set_hold_count(m_temp_nozzle_timeout); @@ -4192,12 +4101,12 @@ void StatusPanel::on_set_nozzle_temp(int nozzle_id) if (m_tempCtrl_nozzle->GetCurrType() == TempInputType::TEMP_OF_NORMAL_TYPE) { obj->command_set_nozzle(nozzle_temp); } else { - obj->command_set_nozzle_new(MAIN_NOZZLE_ID, nozzle_temp); + obj->command_set_nozzle_new(MAIN_EXTRUDER_ID, nozzle_temp); } } } - if (nozzle_id == DEPUTY_NOZZLE_ID) { + if (nozzle_id == DEPUTY_EXTRUDER_ID) { wxString str = m_tempCtrl_nozzle_deputy->GetTextCtrl()->GetValue(); if (str.ToLong(&nozzle_temp) && obj) { set_hold_count(m_temp_nozzle_deputy_timeout); @@ -4206,7 +4115,7 @@ void StatusPanel::on_set_nozzle_temp(int nozzle_id) m_tempCtrl_nozzle_deputy->SetTagTemp(wxString::Format("%d", nozzle_temp)); m_tempCtrl_nozzle_deputy->Warning(false); } - obj->command_set_nozzle_new(DEPUTY_NOZZLE_ID, nozzle_temp); + obj->command_set_nozzle_new(DEPUTY_EXTRUDER_ID, nozzle_temp); } } } catch (...) { @@ -4229,7 +4138,7 @@ void StatusPanel::on_set_chamber_temp() m_tempCtrl_chamber->Warning(false); } - if (!obj->is_at_heating_mode() && chamber_temp >= obj->chamber_temp_switch_heat) + if (!obj->GetFan()->is_at_heating_mode() && chamber_temp >= obj->GetConfig()->GetChamberTempSwitchHeat()) { #ifndef __APPLE__ MessageDialog champer_switch_head_dlg(this, _L("If the chamber temperature exceeds 40\u2103, the system will automatically switch to heating mode. " @@ -4286,7 +4195,7 @@ void StatusPanel::on_ams_load_curr() int old_temp = -1; int new_temp = -1; - AmsTray* curr_tray = &obj->vt_slot[vt_slot_idx]; + DevAmsTray* curr_tray = &obj->vt_slot[vt_slot_idx]; if (!curr_tray) return; @@ -4311,18 +4220,18 @@ void StatusPanel::on_ams_load_curr() } } - std::map::iterator it = obj->amsList.find(curr_ams_id); - if (it == obj->amsList.end()) { + std::map::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id); + if (it == obj->GetFilaSystem()->GetAmsList().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed"; return; } - auto tray_it = it->second->trayList.find(curr_can_id); - if (tray_it == it->second->trayList.end()) { + auto tray_it = it->second->GetTrays().find(curr_can_id); + if (tray_it == it->second->GetTrays().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed"; return; } - AmsTray* curr_tray = obj->get_curr_tray(); - AmsTray* targ_tray = obj->get_ams_tray(curr_ams_id, curr_can_id); + DevAmsTray* curr_tray = obj->get_curr_tray(); + DevAmsTray* targ_tray = obj->get_ams_tray(curr_ams_id, curr_can_id); int old_temp = -1; int new_temp = -1; @@ -4358,9 +4267,6 @@ void StatusPanel::on_ams_load_vams(wxCommandEvent& event) { m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_MAIN_ID)); on_ams_load_curr(); - if (m_print_error_dlg) { - m_print_error_dlg->on_hide(); - } } void StatusPanel::on_ams_switch(SimpleEvent &event) @@ -4368,33 +4274,33 @@ void StatusPanel::on_ams_switch(SimpleEvent &event) if(obj){ /*right*/ - if (obj->m_extder_data.extders.size() > 0) { - auto ext = obj->m_extder_data.extders[MAIN_NOZZLE_ID]; - if (ext.ext_has_filament) { - if (ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - m_ams_control->SetAmsStep(ext.snow.ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); + if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) { + auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); + if (ext->HasFilamentInExt()) { + if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); } } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); + m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); } - m_ams_control->SetExtruder(ext.ext_has_filament, MAIN_NOZZLE_ID, ext.snow.ams_id, ext.snow.slot_id); + m_ams_control->SetExtruder(ext->HasFilamentInExt(), MAIN_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id); } /*left*/ - if (obj->m_extder_data.extders.size() > 1) { - auto ext = obj->m_extder_data.extders[DEPUTY_NOZZLE_ID]; - if (ext.ext_has_filament) { - if (ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.snow.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { - m_ams_control->SetAmsStep(ext.snow.ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); + if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) { + auto ext = obj->GetExtderSystem()->GetExtruders()[DEPUTY_EXTRUDER_ID]; + if (ext.HasFilamentInExt()) { + if (ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { + m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); + m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2); } } else { - m_ams_control->SetAmsStep(ext.snow.ams_id, ext.snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); + m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); } - m_ams_control->SetExtruder(ext.ext_has_filament, DEPUTY_NOZZLE_ID, ext.snow.ams_id, ext.snow.slot_id); + m_ams_control->SetExtruder(ext.HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id); } } } @@ -4407,8 +4313,8 @@ void StatusPanel::on_ams_unload(SimpleEvent &event) if (obj->is_enable_np) { try { - for (auto ext : obj->m_extder_data.extders) { - if (ext.snow.ams_id == curr_ams_id && ext.snow.slot_id == curr_can_id) { obj->command_ams_change_filament(false, curr_ams_id, "255"); } + for (auto ext : obj->GetExtderSystem()->GetExtruders()) { + if (ext.GetSlotNow().ams_id == curr_ams_id && ext.GetSlotNow().slot_id == curr_can_id) { obj->command_ams_change_filament(false, curr_ams_id, "255"); } } } catch (...) {} } else { @@ -4431,13 +4337,10 @@ void StatusPanel::on_ams_setting_click(SimpleEvent &event) if (!m_ams_setting_dlg) m_ams_setting_dlg = new AMSSetting((wxWindow *) this, wxID_ANY); if (obj) { update_ams_insert_material(obj); - m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag); - m_ams_setting_dlg->update_ams_img(DeviceManager::get_printer_ams_img(obj->printer_type)); + m_ams_setting_dlg->update_starting_read_mode(obj->GetFilaSystem()->IsDetectOnPowerupEnabled()); + m_ams_setting_dlg->update_ams_img(DevPrinterConfigUtil::get_printer_ams_img(obj->printer_type)); std::string ams_id = m_ams_control->GetCurentShowAms(); - if (obj->amsList.size() == 0) { - /* wxString txt = _L("BOX settings are not supported for external spool"); - MessageDialog msg_dlg(nullptr, txt, wxEmptyString, wxICON_WARNING | wxOK); - msg_dlg.ShowModal();*/ + if (obj->GetFilaSystem()->GetAmsList().size() == 0) { return; } else { try { @@ -4482,15 +4385,12 @@ void StatusPanel::on_filament_extrusion_cali(wxCommandEvent &event) ams_id_int = atoi(ams_id.c_str()); tray_id_int = atoi(tray_id.c_str()); - auto it = obj->amsList.find(ams_id); - if (it != obj->amsList.end()) { - auto tray_it = it->second->trayList.find(tray_id); - if (tray_it != it->second->trayList.end()) { - if (MachineObject::is_qdt_filament(tray_it->second->tag_uid)) - m_extrusion_cali_dlg->ams_filament_id = tray_it->second->setting_id; - else - m_extrusion_cali_dlg->ams_filament_id = ""; - } + auto tray = obj->GetFilaSystem()->GetAmsTray(ams_id, tray_id); + if (tray) { + if (DevFilaSystem::IsQDT_Filament(tray->tag_uid)) + m_extrusion_cali_dlg->ams_filament_id = tray->setting_id; + else + m_extrusion_cali_dlg->ams_filament_id = ""; } } @@ -4531,34 +4431,37 @@ void StatusPanel::on_filament_edit(wxCommandEvent &event) std::string temp_min; wxString k_val; wxString n_val; - auto it = obj->amsList.find(std::to_string(ams_id)); - if (it != obj->amsList.end()) { - auto tray_it = it->second->trayList.find(std::to_string(slot_id)); - if (tray_it != it->second->trayList.end()) { - k_val = wxString::Format("%.3f", tray_it->second->k); - n_val = wxString::Format("%.3f", tray_it->second->n); - wxColor color = AmsTray::decode_color(tray_it->second->color); - // m_filament_setting_dlg->set_color(color); - std::vector cols; - for (auto col : tray_it->second->cols) { cols.push_back(AmsTray::decode_color(col)); } - m_filament_setting_dlg->set_ctype(tray_it->second->ctype); - m_filament_setting_dlg->ams_filament_id = tray_it->second->setting_id; + auto tray = obj->GetFilaSystem()->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id)); + if (tray) + { + k_val = wxString::Format("%.3f", tray->k); + n_val = wxString::Format("%.3f", tray->n); + wxColor color = DevAmsTray::decode_color(tray->color); + // m_filament_setting_dlg->set_color(color); - if (m_filament_setting_dlg->ams_filament_id.empty()) { - m_filament_setting_dlg->set_empty_color(color); - } else { - m_filament_setting_dlg->set_color(color); - m_filament_setting_dlg->set_colors(cols); - } + std::vector cols; + for (auto col : tray->cols) { cols.push_back(DevAmsTray::decode_color(col)); } + m_filament_setting_dlg->set_ctype(tray->ctype); + m_filament_setting_dlg->ams_filament_id = tray->setting_id; - m_filament_setting_dlg->m_is_third = !MachineObject::is_qdt_filament(tray_it->second->tag_uid); - if (!m_filament_setting_dlg->m_is_third) { - sn_number = tray_it->second->uuid; - filament = tray_it->second->sub_brands; - temp_max = tray_it->second->nozzle_temp_max; - temp_min = tray_it->second->nozzle_temp_min; - } + if (m_filament_setting_dlg->ams_filament_id.empty()) + { + m_filament_setting_dlg->set_empty_color(color); + } + else + { + m_filament_setting_dlg->set_color(color); + m_filament_setting_dlg->set_colors(cols); + } + + m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsQDT_Filament(tray->tag_uid); + if (!m_filament_setting_dlg->m_is_third) + { + sn_number = tray->uuid; + filament = tray->sub_brands; + temp_max = tray->nozzle_temp_max; + temp_min = tray->nozzle_temp_min; } } @@ -4599,12 +4502,12 @@ void StatusPanel::on_ext_spool_edit(wxCommandEvent &event) wxString n_val; k_val = wxString::Format("%.3f", obj->vt_slot[nozzle_index].k); n_val = wxString::Format("%.3f", obj->vt_slot[nozzle_index].n); - wxColor color = AmsTray::decode_color(obj->vt_slot[nozzle_index].color); + wxColor color = DevAmsTray::decode_color(obj->vt_slot[nozzle_index].color); m_filament_setting_dlg->ams_filament_id = obj->vt_slot[nozzle_index].setting_id; std::vector cols; for (auto col : obj->vt_slot[nozzle_index].cols) { - cols.push_back(AmsTray::decode_color(col)); + cols.push_back(DevAmsTray::decode_color(col)); } m_filament_setting_dlg->set_ctype(obj->vt_slot[nozzle_index].ctype); @@ -4615,7 +4518,7 @@ void StatusPanel::on_ext_spool_edit(wxCommandEvent &event) m_filament_setting_dlg->set_color(color); } - m_filament_setting_dlg->m_is_third = !MachineObject::is_qdt_filament(obj->vt_slot[nozzle_index].tag_uid); + m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsQDT_Filament(obj->vt_slot[nozzle_index].tag_uid); if (!m_filament_setting_dlg->m_is_third) { sn_number = obj->vt_slot[nozzle_index].uuid; filament = obj->vt_slot[nozzle_index].sub_brands; @@ -4647,13 +4550,13 @@ void StatusPanel::on_ams_refresh_rfid(wxCommandEvent &event) } std::string curr_can_id = event.GetString().ToStdString(); - std::map::iterator ams_it = obj->amsList.find(curr_ams_id); - if (ams_it == obj->amsList.end()) { + std::map::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id); + if (it == obj->GetFilaSystem()->GetAmsList().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed"; return; } - auto slot_it = ams_it->second->trayList.find(curr_can_id); - if (slot_it == ams_it->second->trayList.end()) { + auto slot_it = it->second->GetTrays().find(curr_can_id); + if (slot_it == it->second->GetTrays().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed"; return; } @@ -4663,8 +4566,8 @@ void StatusPanel::on_ams_refresh_rfid(wxCommandEvent &event) if (obj->is_enable_np || obj->is_enable_ams_np) { use_new_command = true; - if (ams_it->second->nozzle < obj->m_extder_data.extders.size()) { - has_filament_at_extruder = obj->m_extder_data.extders[ams_it->second->nozzle].ext_has_filament; + if (it->second->GetExtruderId() < obj->GetExtderSystem()->GetTotalExtderSize()) { + has_filament_at_extruder = obj->GetExtderSystem()->HasFilamentInExt(it->second->GetExtruderId()); } } else { has_filament_at_extruder = obj->is_filament_at_extruder(); @@ -4704,13 +4607,13 @@ void StatusPanel::on_ams_selected(wxCommandEvent &event) return; } else { std::string curr_can_id = event.GetString().ToStdString(); - std::map::iterator it = obj->amsList.find(curr_ams_id); - if (it == obj->amsList.end()) { + std::map::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id); + if (it == obj->GetFilaSystem()->GetAmsList().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed"; return; } - auto tray_it = it->second->trayList.find(curr_can_id); - if (tray_it == it->second->trayList.end()) { + auto tray_it = it->second->GetTrays().find(curr_can_id); + if (tray_it == it->second->GetTrays().end()) { BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed"; return; } @@ -4748,129 +4651,12 @@ void StatusPanel::on_ams_retry(wxCommandEvent& event) } } -void StatusPanel::on_print_error_done(wxCommandEvent& event) -{ - BOOST_LOG_TRIVIAL(info) << "on_print_error_done"; - if (obj) { - obj->command_ams_control("done"); - if (m_print_error_dlg) { - m_print_error_dlg->on_hide(); - }if (m_print_error_dlg_no_action) { - m_print_error_dlg_no_action->on_hide(); - } - } -} - -void StatusPanel::on_print_error_dlg_btn_clicked(wxCommandEvent& event) -{ - if (obj) - { - PrintErrorDialog::PrintErrorButton btn_id = static_cast(event.GetInt()); - switch (btn_id) { - case Slic3r::GUI::PrintErrorDialog::RESUME_PRINTING: { - obj->command_hms_resume(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::RESUME_PRINTING_DEFECTS: { - obj->command_hms_resume(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::RESUME_PRINTING_PROBELM_SOLVED: { - obj->command_hms_resume(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::STOP_PRINTING: { - obj->command_hms_stop(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::CHECK_ASSISTANT: { - wxGetApp().mainframe->m_monitor->jump_to_HMS(event); // go to assistant page - break; - } - case Slic3r::GUI::PrintErrorDialog::FILAMENT_EXTRUDED: { - obj->command_ams_control("done"); - break; - } - case Slic3r::GUI::PrintErrorDialog::RETRY_FILAMENT_EXTRUDED: { - obj->command_ams_control("resume"); - return;// do not hide the dialogs - } - case Slic3r::GUI::PrintErrorDialog::CONTINUE: { - obj->command_ams_control("resume"); - break; - } - case Slic3r::GUI::PrintErrorDialog::LOAD_VIRTUAL_TRAY: { - m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_MAIN_ID)); - on_ams_load_curr(); - break;/*AP, unknown what it is*/ - } - case Slic3r::GUI::PrintErrorDialog::OK_BUTTON: { - obj->command_clean_print_error(obj->subtask_id_, obj->print_error); - break;/*do nothing*/ - } - case Slic3r::GUI::PrintErrorDialog::FILAMENT_LOAD_RESUME: { - obj->command_hms_resume(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::JUMP_TO_LIVEVIEW: { - m_media_play_ctrl->jump_to_play(); - break; - } - case Slic3r::GUI::PrintErrorDialog::NO_REMINDER_NEXT_TIME: { - obj->command_hms_idle_ignore(std::to_string(before_error_code), 0); /*the type is 0, supported by AP*/ - break; - } - case Slic3r::GUI::PrintErrorDialog::IGNORE_NO_REMINDER_NEXT_TIME: { - obj->command_hms_ignore(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::IGNORE_RESUME: { - obj->command_hms_ignore(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::PROBLEM_SOLVED_RESUME: { - obj->command_hms_resume(std::to_string(before_error_code), obj->job_id_); - break; - } - case Slic3r::GUI::PrintErrorDialog::STOP_BUZZER: { - obj->command_stop_buzzer(); - break; - } - case Slic3r::GUI::PrintErrorDialog::RETRY_PROBLEM_SOLVED: { - obj->command_ams_control("resume"); - break; - } - case Slic3r::GUI::PrintErrorDialog::ERROR_BUTTON_COUNT: break; - default: break; - } - - if (m_print_error_dlg) { m_print_error_dlg->on_hide(); } - if (m_print_error_dlg_no_action) { m_print_error_dlg_no_action->on_hide();} - } -} void StatusPanel::on_fan_changed(wxCommandEvent& event) { auto type = event.GetInt(); auto speed = atoi(event.GetString().c_str()); set_hold_count(this->m_switch_cham_fan_timeout); - return; - - if (type == MachineObject::FanType::COOLING_FAN) { - set_hold_count(this->m_switch_nozzle_fan_timeout); - /*m_switch_nozzle_fan->SetValue(speed > 0 ? true : false); - m_switch_nozzle_fan->setFanValue(speed * 10);*/ - } - else if (type == MachineObject::FanType::BIG_COOLING_FAN) { - set_hold_count(this->m_switch_printing_fan_timeout); - /*m_switch_printing_fan->SetValue(speed > 0 ? true : false); - m_switch_printing_fan->setFanValue(speed * 10);*/ - } - else if (type == MachineObject::FanType::CHAMBER_FAN) { - set_hold_count(this->m_switch_cham_fan_timeout); - /*m_switch_cham_fan->SetValue(speed > 0 ? true : false); - m_switch_cham_fan->setFanValue(speed * 10);*/ - } } void StatusPanel::on_cham_temp_kill_focus(wxFocusEvent& event) @@ -4938,7 +4724,7 @@ void StatusPanel::on_switch_speed(wxCommandEvent &event) // default speed lvl int selected_item = 1; if (obj) { - int speed_lvl_idx = obj->printing_speed_lvl - 1; + int speed_lvl_idx = obj->GetPrintingSpeedLevel() - 1; if (speed_lvl_idx >= 0 && speed_lvl_idx < 4) { selected_item = speed_lvl_idx; } @@ -4954,7 +4740,7 @@ void StatusPanel::on_switch_speed(wxCommandEvent &event) this->speed_lvl = e.GetInt() + 1; if (obj) { set_hold_count(this->speed_lvl_timeout); - obj->command_set_printing_speed((PrintingSpeedLevel)this->speed_lvl); + obj->command_set_printing_speed((DevPrintingSpeedLevel)this->speed_lvl); } }); popUp->Bind(wxEVT_SHOW, [this, popUp](auto &e) { @@ -4994,12 +4780,12 @@ void StatusPanel::on_nozzle_fan_switch(wxCommandEvent &event) } if (!obj) { return; } - if (obj->m_air_duct_data.modes.empty()) + if (obj->GetFan()->GetAirDuctData().modes.empty()) { - obj->converse_to_duct(true, obj->is_support_aux_fan, obj->is_support_chamber_fan); + obj->GetFan()->converse_to_duct(true, obj->GetFan()->GetSupportAuxFanData(), obj->GetFan()->GetSupportChamberFan()); } - m_fan_control_popup = new FanControlPopupNew(this, obj, obj->m_air_duct_data); + m_fan_control_popup = new FanControlPopupNew(this, obj, obj->GetFan()->GetAirDuctData()); auto pos = m_switch_fan->GetScreenPosition(); pos.y = pos.y + m_switch_fan->GetSize().y; @@ -5019,22 +4805,6 @@ void StatusPanel::on_nozzle_fan_switch(wxCommandEvent &event) m_fan_control_popup->SetPosition(pos); m_fan_control_popup->ShowModal(); - - - - /*if (!obj) return; - - bool value = m_switch_nozzle_fan->GetValue(); - - if (value) { - obj->command_control_fan(MachineObject::FanType::COOLING_FAN, true); - m_switch_nozzle_fan->SetValue(true); - set_hold_count(this->m_switch_nozzle_fan_timeout); - } else { - obj->command_control_fan(MachineObject::FanType::COOLING_FAN, false); - m_switch_nozzle_fan->SetValue(false); - set_hold_count(this->m_switch_nozzle_fan_timeout); - }*/ } void StatusPanel::on_lamp_switch(wxCommandEvent &event) { @@ -5046,11 +4816,10 @@ void StatusPanel::on_lamp_switch(wxCommandEvent &event) m_switch_lamp->SetValue(true); // do not update when timeout > 0 set_hold_count(this->m_switch_lamp_timeout); - obj->command_set_chamber_light(MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_ON); - obj->command_set_chamber_light2(MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_ON); + obj->GetLamp()->CtrlSetChamberLight(DevLamp::LIGHT_EFFECT_ON); } else { - if (obj->m_lamp_close_recheck) { - MessageDialog msg_dlg(nullptr, _L("Turning off the lights during the task will cause the failure of AI monitoring, like spaghetti dectection. Please choose carefully."), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL); + if (obj->GetLamp()->HasLampCloseRecheck()){ + MessageDialog msg_dlg(nullptr, _L("Turning off the lights during the task will cause the failure of AI monitoring, like spaghetti detection. Please choose carefully."), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL); msg_dlg.SetButtonLabel(wxID_OK, _L("Keep it On")); msg_dlg.SetButtonLabel(wxID_CANCEL, _L("Turn it Off")); if (msg_dlg.ShowModal() != wxID_CANCEL) { @@ -5060,8 +4829,7 @@ void StatusPanel::on_lamp_switch(wxCommandEvent &event) m_switch_lamp->SetValue(false); set_hold_count(this->m_switch_lamp_timeout); - obj->command_set_chamber_light(MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_OFF); - obj->command_set_chamber_light2(MachineObject::LIGHT_EFFECT::LIGHT_EFFECT_OFF); + obj->GetLamp()->CtrlSetChamberLight(DevLamp::LIGHT_EFFECT_OFF); } } @@ -5132,7 +4900,7 @@ void StatusPanel::on_nozzle_selected(wxCommandEvent &event) } auto nozzle_id = event.GetInt(); - if (obj->command_select_extruder(nozzle_id) == 0) + if (obj->GetCtrl()->command_select_extruder(nozzle_id) == 0) { return; } @@ -5298,11 +5066,11 @@ void StatusPanel::rescale_camera_icons() if (!obj) return; - if (obj->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_no.bmp()); - } else if (obj->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL) { + } else if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp()); - } else if (obj->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL) { + } else if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL) { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_abnormal.bmp()); } else { m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp()); @@ -5328,7 +5096,6 @@ void StatusPanel::on_sys_color_changed() m_bitmap_speed_active.msw_rescale(); m_switch_speed->SetImages(m_bitmap_speed, m_bitmap_speed); m_ams_control->msw_rescale(); - if (m_print_error_dlg) { m_print_error_dlg->msw_rescale(); } rescale_camera_icons(); } @@ -5356,7 +5123,7 @@ void StatusPanel::msw_rescale() m_bpButton_xy->Rescale(); auto size = TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON; - if (obj && obj->m_extder_data.total_extder_count >= 2) size = TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON; + if (obj && obj->GetExtderSystem()->GetTotalExtderCount() >= 2) size = TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON; m_tempCtrl_nozzle->SetMinSize(size); m_tempCtrl_nozzle->Rescale(); m_tempCtrl_nozzle_deputy->SetMinSize(size); diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 68107c2..9c8edbd 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -33,12 +33,16 @@ #include "Widgets/FanControl.hpp" #include "HMS.hpp" #include "PartSkipDialog.hpp" +#include "DeviceErrorDialog.hpp" class StepIndicator; #define COMMAND_TIMEOUT 5 namespace Slic3r { + +class DevExtderSystem; + namespace GUI { // Previous definitions @@ -156,10 +160,7 @@ public: void msw_rescale(); private: - void updateSwitchingLabel(const ExtruderSwitchState &state); - - void updateBy(const ExtderData& ext_data); - void updateBtnGroup(const ExtderData &ext_data); + void updateBy(const DevExtderSystem* ext_system); void showQuitBtn(bool show); void showRetryBtn(bool show); @@ -433,6 +434,8 @@ protected: wxStaticText * m_staticText_timelapse; SwitchButton * m_bmToggleBtn_timelapse; + wxStaticText *m_mqtt_source; + wxStaticBitmap *m_bitmap_camera_img; wxStaticBitmap *m_bitmap_recording_img; wxStaticBitmap *m_bitmap_timelapse_img; @@ -620,8 +623,7 @@ protected: CalibrationDialog* calibration_dlg {nullptr}; AMSMaterialsSetting *m_filament_setting_dlg{nullptr}; - PrintErrorDialog* m_print_error_dlg = nullptr; - SecondaryCheckDialog* m_print_error_dlg_no_action = nullptr; + DeviceErrorDialog* m_print_error_dlg = nullptr; SecondaryCheckDialog* abort_dlg = nullptr; SecondaryCheckDialog* con_load_dlg = nullptr; MessageDialog * ctrl_e_hint_dlg = nullptr; @@ -677,7 +679,6 @@ protected: void on_subtask_pause_resume(wxCommandEvent &event); void on_subtask_abort(wxCommandEvent &event); void on_print_error_clean(wxCommandEvent &event); - void show_error_message(MachineObject *obj, bool is_exist, wxString msg, std::string print_error_str = "", wxString image_url = "", std::vector used_button = std::vector()); void error_info_reset(); void show_recenter_dialog(); @@ -718,8 +719,6 @@ protected: void on_ams_selected(wxCommandEvent &event); void on_ams_guide(wxCommandEvent &event); void on_ams_retry(wxCommandEvent &event); - void on_print_error_done(wxCommandEvent& event); - void on_print_error_dlg_btn_clicked(wxCommandEvent& event); void on_fan_changed(wxCommandEvent& event); void on_cham_temp_kill_focus(wxFocusEvent& event); diff --git a/src/slic3r/GUI/SyncAmsInfoDialog.cpp b/src/slic3r/GUI/SyncAmsInfoDialog.cpp index 6a93b8a..422ebed 100644 --- a/src/slic3r/GUI/SyncAmsInfoDialog.cpp +++ b/src/slic3r/GUI/SyncAmsInfoDialog.cpp @@ -20,6 +20,12 @@ #include "CapsuleButton.hpp" #include "PrePrintChecker.hpp" +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevMapping.h" +#include "DeviceCore/DevStorage.h" + using namespace Slic3r; using namespace Slic3r::GUI; @@ -50,15 +56,6 @@ bool SyncAmsInfoDialog::Show(bool show) if (m_refresh_timer) { m_refresh_timer->Start(LIST_REFRESH_INTERVAL); } } else { m_refresh_timer->Stop(); - - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (dev) { - MachineObject *obj_ = dev->get_selected_machine(); - if (obj_ && obj_->connection_type() == "cloud" /*&& m_print_type == FROM_SDCARD_VIEW*/) { - if (obj_->is_connected()) { obj_->disconnect(); } - } - } - return DPIDialog::Show(false); } // set default value when show this dialog @@ -340,7 +337,7 @@ wxColour SyncAmsInfoDialog::decode_ams_color(const std::string &color_str) { if (temp_str.size() == 6) { temp_str += "FF"; } - return AmsTray::decode_color(temp_str); + return DevAmsTray::decode_color(temp_str); } void SyncAmsInfoDialog::update_map_when_change_map_mode() @@ -454,7 +451,6 @@ void SyncAmsInfoDialog::init_bitmaps() void SyncAmsInfoDialog::add_two_image_control() {// thumbnail m_two_thumbnail_panel = new StaticBox(m_scrolledWindow); - // m_two_thumbnail_panel->SetBackgroundColour(wxColour(0xF8F8F8)); m_two_thumbnail_panel->SetBorderWidth(0); //m_two_thumbnail_panel->SetMinSize(wxSize(FromDIP(637), -1)); //m_two_thumbnail_panel->SetMaxSize(wxSize(FromDIP(637), -1)); @@ -482,7 +478,6 @@ void SyncAmsInfoDialog::add_two_image_control() view_two_thumbnail_sizer->AddSpacer(FromDIP(24)); { m_two_image_panel = new StaticBox(m_two_thumbnail_panel); - // m_two_thumbnail_panel->SetBackgroundColour(wxColour(0xF8F8F8)); m_two_image_panel->SetBorderWidth(0); //m_two_image_panel->SetForegroundColour(wxColour(248, 248, 248, 100)); m_two_image_panel_sizer = new wxBoxSizer(wxHORIZONTAL); @@ -752,7 +747,6 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_fix_filament_panel->Fit(); /*1 extruder*/ m_filament_panel = new StaticBox(m_scrolledWindow); - //m_filament_panel->SetBackgroundColour(wxColour(0xF8F8F8)); m_filament_panel->SetBorderWidth(0); m_filament_panel->SetMinSize(wxSize(FromDIP(637), -1)); m_filament_panel->SetMaxSize(wxSize(FromDIP(637), -1)); @@ -768,7 +762,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_sizer_filament_2extruder = new wxBoxSizer(wxHORIZONTAL); m_filament_left_panel = new StaticBox(m_scrolledWindow); - m_filament_left_panel->SetBackgroundColour(wxColour(0xF8F8F8)); + m_filament_left_panel->SetBackgroundColour(wxColour("#F8F8F8")); m_filament_left_panel->SetBorderWidth(0); m_filament_left_panel->SetMinSize(wxSize(FromDIP(315), -1)); m_filament_left_panel->SetMaxSize(wxSize(FromDIP(315), -1)); @@ -777,11 +771,11 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : auto left_recommend_title_sizer = new wxBoxSizer(wxHORIZONTAL); auto left_recommend_title1 = new Label(m_filament_left_panel, _L("Left Extruder")); left_recommend_title1->SetFont(::Label::Head_13); - left_recommend_title1->SetBackgroundColour(wxColour(0xF8F8F8)); + left_recommend_title1->SetBackgroundColour(wxColour("#F8F8F8")); auto left_recommend_title2 = new Label(m_filament_left_panel, _L("(Recommended filament)")); left_recommend_title2->SetFont(::Label::Body_13); - left_recommend_title2->SetForegroundColour(wxColour(0x6B6B6B)); - left_recommend_title2->SetBackgroundColour(wxColour(0xF8F8F8)); + left_recommend_title2->SetForegroundColour(wxColour("#6B6B6B")); + left_recommend_title2->SetBackgroundColour(wxColour("#F8F8F8")); left_recommend_title_sizer->Add(left_recommend_title1, 0, wxALIGN_CENTER, 0); left_recommend_title_sizer->Add(0, 0, 0, wxLEFT, FromDIP(4)); left_recommend_title_sizer->Add(left_recommend_title2, 0, wxALIGN_CENTER, 0); @@ -794,7 +788,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_filament_right_panel = new StaticBox(m_scrolledWindow); m_filament_right_panel->SetBorderWidth(0); - m_filament_right_panel->SetBackgroundColour(wxColour(0xf8f8f8)); + m_filament_right_panel->SetBackgroundColour(wxColour("#F8F8F8")); m_filament_right_panel->SetMinSize(wxSize(FromDIP(315), -1)); m_filament_right_panel->SetMaxSize(wxSize(FromDIP(315), -1)); @@ -802,12 +796,12 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : auto right_recommend_title_sizer = new wxBoxSizer(wxHORIZONTAL); auto right_recommend_title1 = new Label(m_filament_right_panel, _L("Right Extruder")); right_recommend_title1->SetFont(::Label::Head_13); - right_recommend_title1->SetBackgroundColour(wxColour(0xF8F8F8)); + right_recommend_title1->SetBackgroundColour(wxColour("#F8F8F8")); auto right_recommend_title2 = new Label(m_filament_right_panel, _L("(Recommended filament)")); right_recommend_title2->SetFont(::Label::Body_13); - right_recommend_title2->SetForegroundColour(wxColour(0x6B6B6B)); - right_recommend_title2->SetBackgroundColour(wxColour(0xF8F8F8)); + right_recommend_title2->SetForegroundColour(wxColour("#6B6B6B")); + right_recommend_title2->SetBackgroundColour(wxColour("#F8F8F8")); right_recommend_title_sizer->Add(right_recommend_title1, 0, wxALIGN_CENTER, 0); right_recommend_title_sizer->Add(0, 0, 0, wxLEFT, FromDIP(4)); right_recommend_title_sizer->Add(right_recommend_title2, 0, wxALIGN_CENTER, 0); @@ -1002,7 +996,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_button_ok = new Button(m_show_page, _L("Synchronize now")); 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(OK_BUTTON_SIZE); m_button_ok->SetMinSize(OK_BUTTON_SIZE); @@ -1202,13 +1196,13 @@ void SyncAmsInfoDialog::sync_ams_mapping_result(std::vector &resul } if (!f->color.empty()) { - ams_col = AmsTray::decode_color(f->color); + ams_col = DevAmsTray::decode_color(f->color); } else { // default color ams_col = wxColour(0xCE, 0xCE, 0xCE); } std::vector cols; - for (auto col : f->colors) { cols.push_back(AmsTray::decode_color(col)); } + for (auto col : f->colors) { cols.push_back(DevAmsTray::decode_color(col)); } m->set_ams_info(ams_col, ams_id, f->ctype, cols,true);//sync_ams_mapping_result break; } @@ -1237,19 +1231,19 @@ bool SyncAmsInfoDialog::do_ams_mapping(MachineObject *obj_) std::vector map_opt; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext if (nozzle_nums > 1) { map_opt = {true, true, true, true}; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt, std::vector(), + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt, std::vector(), wxGetApp().app_config->get_bool("ams_sync_match_full_use_color_dist") ? false : true); } // single nozzle else { if (obj_->is_support_amx_ext_mix_mapping()) { map_opt = {false, true, false, true}; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt, std::vector(), + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt, std::vector(), wxGetApp().app_config->get_bool("ams_sync_match_full_use_color_dist") ? false : true); // auto_supply_with_ext(obj_->vt_slot); } else { map_opt = {false, true, false, false}; - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt); + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt); } } @@ -1270,11 +1264,11 @@ bool SyncAmsInfoDialog::do_ams_mapping(MachineObject *obj_) } deal_only_exist_ext_spool(obj_); show_thumbnail_page(); - return obj_->is_valid_mapping_result(m_ams_mapping_result); + return DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result); } else { BOOST_LOG_TRIVIAL(info) << "filament_result != 0"; // do not support ams mapping try to use order mapping - bool is_valid = obj_->is_valid_mapping_result(m_ams_mapping_result); + bool is_valid = DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result); if (filament_result != 1 && !is_valid) { // reset invalid result for (int i = 0; i < m_ams_mapping_result.size(); i++) { @@ -1295,7 +1289,7 @@ void SyncAmsInfoDialog::deal_only_exist_ext_spool(MachineObject *obj_) { if (!obj_) return; if (!m_append_color_text) { return; } - bool only_exist_ext_spool_flag = m_only_exist_ext_spool_flag = obj_->only_exist_ext_spool(); + bool only_exist_ext_spool_flag = m_only_exist_ext_spool_flag = !obj_->GetFilaSystem()->HasAms(); SetTitle(only_exist_ext_spool_flag ? _L("Synchronize Filament Information") : _L("Synchronize BOX Filament Information")); m_append_color_text->SetLabel(only_exist_ext_spool_flag ? _L("Add unused filaments to filaments list.") : _L("Add unused BOX filaments to filaments list.")); @@ -1452,20 +1446,20 @@ bool SyncAmsInfoDialog::build_nozzles_info(std::string &nozzles_info) return true; } -bool SyncAmsInfoDialog::can_hybrid_mapping(ExtderData data) +bool SyncAmsInfoDialog::can_hybrid_mapping(DevExtderSystem data) { // Mixed mappings are not allowed return false; - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) return false; + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; // The default two extruders are left, right, but the order of the extruders on the machine is right, left. // Therefore, some adjustments need to be made. std::vector flow_type_of_machine; - for (auto it = data.extders.rbegin(); it != data.extders.rend(); it++) { + for (auto it = data.GetExtruders().rbegin(); it != data.GetExtruders().rend(); it++) { // exist field is not updated, wait add // if (it->exist < 3) return false; - std::string type_str = it->current_nozzle_flow_type ? "High Flow" : "Standard"; + std::string type_str = it->GetNozzleFlowType() ? "High Flow" : "Standard"; flow_type_of_machine.push_back(type_str); } // get the nozzle type of preset --> flow_types @@ -1486,14 +1480,14 @@ bool SyncAmsInfoDialog::can_hybrid_mapping(ExtderData data) } // When filaments cannot be matched automatically, whether to use ext for automatic supply -void SyncAmsInfoDialog::auto_supply_with_ext(std::vector slots) +void SyncAmsInfoDialog::auto_supply_with_ext(std::vector slots) { if (slots.size() <= 0) return; for (int i = 0; i < m_ams_mapping_result.size(); i++) { auto it = m_ams_mapping_result[i]; if (it.ams_id == "") { - AmsTray slot(""); + DevAmsTray slot(""); if (m_filaments_map[it.id] == 1 && slots.size() > 1) slot = slots[1]; else if (m_filaments_map[it.id] == 2) @@ -1509,9 +1503,9 @@ void SyncAmsInfoDialog::auto_supply_with_ext(std::vector slots) } } -bool SyncAmsInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_message) const +bool SyncAmsInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &error_message) const { - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) return false; + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; const auto &project_config = wxGetApp().preset_bundle->project_config; // check nozzle used @@ -1542,10 +1536,10 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_me // The default two extruders are left, right, but the order of the extruders on the machine is right, left. std::vector flow_type_of_machine; - for (auto it = data.extders.begin(); it != data.extders.end(); it++) { - if (it->current_nozzle_flow_type == NozzleFlowType::H_FLOW) { + for (auto it = data.GetExtruders().begin(); it != data.GetExtruders().end(); it++) { + if (it->GetNozzleFlowType() == NozzleFlowType::H_FLOW) { flow_type_of_machine.push_back("High Flow"); - } else if (it->current_nozzle_flow_type == NozzleFlowType::S_FLOW) { + } else if (it->GetNozzleFlowType() == NozzleFlowType::S_FLOW) { flow_type_of_machine.push_back("Standard"); } } @@ -1558,9 +1552,9 @@ bool SyncAmsInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_me if (target_machine_nozzle_id < flow_type_of_machine.size()) { if (flow_type_of_machine[target_machine_nozzle_id] != used_extruders_flow[it->first]) { wxString pos; - if (target_machine_nozzle_id == DEPUTY_NOZZLE_ID) { + if (target_machine_nozzle_id == DEPUTY_EXTRUDER_ID) { pos = _L("left nozzle"); - } else if ((target_machine_nozzle_id == MAIN_NOZZLE_ID)) { + } else if ((target_machine_nozzle_id == MAIN_EXTRUDER_ID)) { pos = _L("right nozzle"); } @@ -1807,7 +1801,7 @@ void SyncAmsInfoDialog::show_status(PrintDialogStatus status, std::vector 0) { target_model_id = m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id; } } - auto target_print_name = wxString(obj_->get_preset_printer_model_name(target_model_id)); + auto target_print_name = wxString(DevPrinterConfigUtil::get_printer_display_name(target_model_id)); target_print_name.Replace(wxT("QIDI Tech "), wxEmptyString); msg_text = wxString::Format(_L("The selected printer (%s) is incompatible with the chosen printer profile in the slicer (%s)."), sourcet_print_name, target_print_name); @@ -1888,7 +1882,7 @@ bool SyncAmsInfoDialog::is_blocking_printing(MachineObject *obj_) } if (source_model != target_model) { - std::vector compatible_machine = dev->get_compatible_machine(target_model); + std::vector compatible_machine = obj_->get_compatible_machine(); vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); if (it == compatible_machine.end()) { return true; } } @@ -1917,8 +1911,8 @@ bool SyncAmsInfoDialog::is_same_nozzle_diameters(NozzleType &tag_nozzle_type, fl std::vector preset_nozzle_types(nozzle_type->size()); for (size_t idx = 0; idx < nozzle_type->size(); ++idx) preset_nozzle_types[idx] = NozzleTypeEumnToStr[NozzleType(nozzle_type->values[idx])]; - std::vector machine_nozzle_types(obj_->m_extder_data.extders.size()); - for (size_t idx = 0; idx < obj_->m_extder_data.extders.size(); ++idx) machine_nozzle_types[idx] = obj_->m_extder_data.extders[idx].current_nozzle_type; + std::vector machine_nozzle_types(obj_->GetExtderSystem()->GetTotalExtderCount()); + for (size_t idx = 0; idx < obj_->GetExtderSystem()->GetTotalExtderCount(); ++idx) machine_nozzle_types[idx] = obj_->GetExtderSystem()->GetNozzleType(idx); auto used_filaments = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_filaments(); // 1 based auto filament_maps = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_real_filament_maps(preset_bundle->project_config); // 1 based @@ -1931,13 +1925,13 @@ bool SyncAmsInfoDialog::is_same_nozzle_diameters(NozzleType &tag_nozzle_type, fl std::sort(used_extruders.begin(), used_extruders.end()); // TODO [tao wang] : add idx mapping - tag_nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + tag_nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); if (opt_nozzle_diameters != nullptr) { for (auto i = 0; i < used_extruders.size(); i++) { auto extruder = used_extruders[i]; preset_nozzle_diameters = float(opt_nozzle_diameters->get_at(extruder)); - if (preset_nozzle_diameters != obj_->m_extder_data.extders[0].current_nozzle_diameter) { is_same_nozzle_diameters = false; } + if (preset_nozzle_diameters != obj_->GetExtderSystem()->GetNozzleDiameter(0)) { is_same_nozzle_diameters = false; } } } @@ -1958,7 +1952,7 @@ bool SyncAmsInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleTy MachineObject *obj_ = dev->get_selected_machine(); if (obj_ == nullptr) return true; - NozzleType nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + NozzleType nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(nozzle_type); auto preset_bundle = wxGetApp().preset_bundle; @@ -1975,7 +1969,7 @@ bool SyncAmsInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleTy tag_nozzle_type = NozzleType::ntHardenedSteel; return is_same_nozzle_type; } else { - tag_nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + tag_nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); } iter++; @@ -2199,11 +2193,11 @@ void SyncAmsInfoDialog::update_user_printer() // same machine only appear once for (auto it = option_list.begin(); it != option_list.end(); it++) { - if (it->second && (it->second->is_online() || it->second->is_connected())) { machine_list.push_back(it->second->dev_name); } + if (it->second && (it->second->is_online() || it->second->is_connected())) { machine_list.push_back(it->second->get_dev_name()); } } // lan machine list - auto lan_option_list = dev->get_local_machine_list(); + auto lan_option_list = dev->get_local_machinelist(); for (auto elem : lan_option_list) { MachineObject *mobj = elem.second; @@ -2213,17 +2207,18 @@ void SyncAmsInfoDialog::update_user_printer() if (!mobj->is_online()) continue; if (!mobj->is_lan_mode_printer()) continue; if (!mobj->has_access_right()) { - option_list[mobj->dev_name] = mobj; - machine_list.push_back(mobj->dev_name); + option_list[mobj->get_dev_name()] = mobj; + machine_list.push_back(mobj->get_dev_name()); } } machine_list = sort_string(machine_list); for (auto tt = machine_list.begin(); tt != machine_list.end(); tt++) { for (auto it = option_list.begin(); it != option_list.end(); it++) { - if (it->second->dev_name == *tt) { + if (it->second->get_dev_name() == *tt) + { m_list.push_back(it->second); - wxString dev_name_text = from_u8(it->second->dev_name); + wxString dev_name_text = from_u8(it->second->get_dev_name()); if (it->second->is_lan_mode_printer()) { dev_name_text += "(LAN)"; } machine_list_name.Add(dev_name_text); break; @@ -2253,8 +2248,8 @@ void SyncAmsInfoDialog::on_timer(wxTimerEvent &event) m_check_flag = true; } - if (!obj_ || obj_->amsList.empty() || obj_->ams_exist_bits == 0 || !obj_->is_support_filament_backup || !obj_->is_support_show_filament_backup || - !obj_->ams_auto_switch_filament_flag || m_checkbox_list["use_ams"]->getValue() != "on") { + if (!obj_ || !obj_->GetFilaSystem()->HasAms() || obj_->ams_exist_bits == 0 || !obj_->is_support_filament_backup || !obj_->GetExtderSystem()->HasFilamentBackup() || + !obj_->GetFilaSystem()->IsAutoRefillEnabled() || m_checkbox_list["use_ams"]->getValue() != "on") { if (m_ams_backup_tip && m_ams_backup_tip->IsShown()) { m_ams_backup_tip->Hide(); img_ams_backup->Hide(); @@ -2326,7 +2321,7 @@ void SyncAmsInfoDialog::update_show_status() reset_timeout(); - if (!obj_->is_support_print_all && m_print_plate_idx == PLATE_ALL_IDX) { + if (!obj_->GetConfig()->SupportPrintAllPlates() && m_print_plate_idx == PLATE_ALL_IDX) { show_status(PrintDialogStatus::PrintStatusNotSupportedPrintAll); return; } @@ -2362,17 +2357,17 @@ void SyncAmsInfoDialog::update_show_status() } else if (obj_->is_in_printing() || obj_->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { show_status(PrintDialogStatus::PrintStatusInPrinting); return; - } else if (!obj_->is_support_print_without_sd && (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD)) { + } else if (!obj_->GetConfig()->SupportPrintWithoutSD() && (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD)) { show_status(PrintDialogStatus::PrintStatusNoSdcard); return; } // check sdcard when if lan mode printer if (obj_->is_lan_mode_printer()) { - if (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { show_status(PrintDialogStatus::PrintStatusLanModeNoSdcard); return; - } else if (obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL || obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_READONLY) { + } else if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL || obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_READONLY) { show_status(PrintDialogStatus::PrintStatusLanModeSDcardNotAvailable); return; } @@ -2386,13 +2381,8 @@ void SyncAmsInfoDialog::update_show_status() // the nozzle type of preset and machine are different if (nozzle_nums > 1) { - if (obj_->is_nozzle_data_invalid()) { - show_status(PrintDialogStatus::PrintStatusNozzleDataInvalid); - return; - } - wxString error_message; - if (!is_nozzle_type_match(obj_->m_extder_data, error_message)) { + if (!is_nozzle_type_match(*obj_->GetExtderSystem(), error_message)) { std::vector params{error_message}; params.emplace_back(_L("Tips: If you changed your nozzle of your printer lately, Please go to 'Device -> Printer parts' to change your nozzle setting.")); show_status(PrintDialogStatus::PrintStatusNozzleMatchInvalid, params); @@ -2425,7 +2415,7 @@ void SyncAmsInfoDialog::update_show_status() if (item.ams_id.empty()) continue; int extruder_id = obj_->get_extruder_id_by_ams_id(item.ams_id); - if (DeviceManager::is_virtual_slot(stoi(item.ams_id))) + if (devPrinterUtil::IsVirtualSlot(item.ams_id)) extruder_status[extruder_id].has_vt_slot = true; else extruder_status[extruder_id].has_ams = true; @@ -3260,7 +3250,7 @@ void SyncAmsInfoDialog::update_lan_machine_list() { DeviceManager *dev = wxGetApp().getDeviceManager(); if (!dev) return; - auto m_free_machine_list = dev->get_local_machine_list(); + auto m_free_machine_list = dev->get_local_machinelist(); BOOST_LOG_TRIVIAL(info) << "SelectMachinePopup update_other_devices start"; @@ -3273,7 +3263,7 @@ void SyncAmsInfoDialog::update_lan_machine_list() if (!mobj->is_lan_mode_printer()) continue; if (mobj->has_access_right()) { - auto b = mobj->dev_name; + auto b = mobj->get_dev_name(); // clear machine list diff --git a/src/slic3r/GUI/SyncAmsInfoDialog.hpp b/src/slic3r/GUI/SyncAmsInfoDialog.hpp index 1cdef79..3d4bcda 100644 --- a/src/slic3r/GUI/SyncAmsInfoDialog.hpp +++ b/src/slic3r/GUI/SyncAmsInfoDialog.hpp @@ -213,9 +213,9 @@ public: void show_thumbnail_page(); bool get_ams_mapping_result(std::string &mapping_array_str, std::string &mapping_array_str2, std::string &ams_mapping_info); bool build_nozzles_info(std::string &nozzles_info); - bool can_hybrid_mapping(ExtderData data); - void auto_supply_with_ext(std::vector slots); - bool is_nozzle_type_match(ExtderData data, wxString &error_message) const; + bool can_hybrid_mapping(DevExtderSystem data); + void auto_supply_with_ext(std::vector slots); + bool is_nozzle_type_match(DevExtderSystem data, wxString &error_message) const; int convert_filament_map_nozzle_id_to_task_nozzle_id(int nozzle_id); PrintFromType get_print_type() { return m_print_type; }; diff --git a/src/slic3r/GUI/SyncBoxInfoDialog.cpp b/src/slic3r/GUI/SyncBoxInfoDialog.cpp index cee9dd8..1d67b32 100644 --- a/src/slic3r/GUI/SyncBoxInfoDialog.cpp +++ b/src/slic3r/GUI/SyncBoxInfoDialog.cpp @@ -20,6 +20,12 @@ #include "CapsuleButton.hpp" #include "PrePrintChecker.hpp" +#include "DeviceCore/DevConfig.h" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevManager.h" +#include "DeviceCore/DevMapping.h" +#include "DeviceCore/DevStorage.h" + using namespace Slic3r; using namespace Slic3r::GUI; @@ -50,15 +56,6 @@ bool SyncBoxInfoDialog::Show(bool show) if (m_refresh_timer) { m_refresh_timer->Start(LIST_REFRESH_INTERVAL); } } else { m_refresh_timer->Stop(); - - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (dev) { - MachineObject *obj_ = dev->get_selected_machine(); - if (obj_ && obj_->connection_type() == "cloud" /*&& m_print_type == FROM_SDCARD_VIEW*/) { - if (obj_->is_connected()) { obj_->disconnect(); } - } - } - return DPIDialog::Show(false); } // set default value when show this dialog @@ -340,7 +337,7 @@ wxColour SyncBoxInfoDialog::decode_ams_color(const std::string &color_str) { if (temp_str.size() == 6) { temp_str += "FF"; } - return AmsTray::decode_color(temp_str); + return DevAmsTray::decode_color(temp_str); } void SyncBoxInfoDialog::update_map_when_change_map_mode() @@ -1114,10 +1111,10 @@ void SyncBoxInfoDialog::check_fcous_state(wxWindow *window) void SyncBoxInfoDialog::popup_filament_backup() { - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return; if (dev->get_selected_machine() /* && dev->get_selected_machine()->filam_bak.size() > 0*/) { - AmsReplaceMaterialDialog *m_replace_material_popup = new AmsReplaceMaterialDialog(this); + AmsReplaceMaterialDialog* m_replace_material_popup = new AmsReplaceMaterialDialog(this); m_replace_material_popup->update_machine_obj(dev->get_selected_machine()); m_replace_material_popup->ShowModal(); } @@ -1182,13 +1179,13 @@ void SyncBoxInfoDialog::sync_ams_mapping_result(std::vector &resul } if (!f->color.empty()) { - ams_col = AmsTray::decode_color(f->color); + ams_col = DevAmsTray::decode_color(f->color); } else { // default color ams_col = wxColour(0xCE, 0xCE, 0xCE); } std::vector cols; - for (auto col : f->colors) { cols.push_back(AmsTray::decode_color(col)); } + for (auto col : f->colors) { cols.push_back(DevAmsTray::decode_color(col)); } m->set_ams_info(ams_col, ams_id, f->ctype, cols,true);//sync_ams_mapping_result break; } @@ -1201,7 +1198,7 @@ void SyncBoxInfoDialog::sync_ams_mapping_result(std::vector &resul } } -bool SyncBoxInfoDialog::do_ams_mapping() +bool SyncBoxInfoDialog::do_ams_mapping(MachineObject* obj_) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " begin do_box_mapping result"; @@ -1210,7 +1207,7 @@ bool SyncBoxInfoDialog::do_ams_mapping() if (!color.empty()) { color.erase(0, 1); color += "FF"; - auto box_color = AmsTray::decode_color(color); + auto box_color = DevAmsTray::decode_color(color); m_cur_colors_in_thumbnail.emplace_back(box_color); } } @@ -1224,19 +1221,19 @@ bool SyncBoxInfoDialog::do_ams_mapping() std::vector map_opt; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext if (nozzle_nums > 1) { map_opt = {true, true, true, true}; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt, std::vector(), + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt, std::vector(), wxGetApp().app_config->get_bool("ams_sync_match_full_use_color_dist") ? false : true); } // single nozzle else { if (obj_->is_support_amx_ext_mix_mapping()) { map_opt = {false, true, false, true}; // four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt, std::vector(), + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt, std::vector(), wxGetApp().app_config->get_bool("ams_sync_match_full_use_color_dist") ? false : true); // auto_supply_with_ext(obj_->vt_slot); } else { map_opt = {false, true, false, false}; - filament_result = obj_->ams_filament_mapping(m_filaments, m_ams_mapping_result, map_opt); + filament_result = DevMappingUtil::ams_filament_mapping(obj_, m_filaments, m_ams_mapping_result, map_opt); } } @@ -1261,7 +1258,7 @@ bool SyncBoxInfoDialog::do_ams_mapping() } else { BOOST_LOG_TRIVIAL(info) << "filament_result != 0"; // do not support ams mapping try to use order mapping - bool is_valid = obj_->is_valid_mapping_result(m_ams_mapping_result); + bool is_valid = DevMappingUtil::is_valid_mapping_result(obj_, m_ams_mapping_result); if (filament_result != 1 && !is_valid) { // reset invalid result for (int i = 0; i < m_ams_mapping_result.size(); i++) { @@ -1437,20 +1434,20 @@ bool SyncBoxInfoDialog::build_nozzles_info(std::string &nozzles_info) return true; } -bool SyncBoxInfoDialog::can_hybrid_mapping(ExtderData data) +bool SyncBoxInfoDialog::can_hybrid_mapping(DevExtderSystem data) { // Mixed mappings are not allowed return false; - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) return false; + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; // The default two extruders are left, right, but the order of the extruders on the machine is right, left. // Therefore, some adjustments need to be made. std::vector flow_type_of_machine; - for (auto it = data.extders.rbegin(); it != data.extders.rend(); it++) { + for (auto it = data.GetExtruders().rbegin(); it != data.GetExtruders().rend(); it++) { // exist field is not updated, wait add // if (it->exist < 3) return false; - std::string type_str = it->current_nozzle_flow_type ? "High Flow" : "Standard"; + std::string type_str = it->GetNozzleFlowType() ? "High Flow" : "Standard"; flow_type_of_machine.push_back(type_str); } // get the nozzle type of preset --> flow_types @@ -1471,14 +1468,14 @@ bool SyncBoxInfoDialog::can_hybrid_mapping(ExtderData data) } // When filaments cannot be matched automatically, whether to use ext for automatic supply -void SyncBoxInfoDialog::auto_supply_with_ext(std::vector slots) +void SyncBoxInfoDialog::auto_supply_with_ext(std::vector slots) { if (slots.size() <= 0) return; for (int i = 0; i < m_ams_mapping_result.size(); i++) { auto it = m_ams_mapping_result[i]; if (it.ams_id == "") { - AmsTray slot(""); + DevAmsTray slot(""); if (m_filaments_map[it.id] == 1 && slots.size() > 1) slot = slots[1]; else if (m_filaments_map[it.id] == 2) @@ -1494,9 +1491,9 @@ void SyncBoxInfoDialog::auto_supply_with_ext(std::vector slots) } } -bool SyncBoxInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_message) const +bool SyncBoxInfoDialog::is_nozzle_type_match(DevExtderSystem data, wxString &error_message) const { - if (data.total_extder_count <= 1 || data.extders.size() <= 1 || !wxGetApp().preset_bundle) return false; + if (data.GetTotalExtderCount() <= 1 || !wxGetApp().preset_bundle) return false; const auto &project_config = wxGetApp().preset_bundle->project_config; // check nozzle used @@ -1527,10 +1524,10 @@ bool SyncBoxInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_me // The default two extruders are left, right, but the order of the extruders on the machine is right, left. std::vector flow_type_of_machine; - for (auto it = data.extders.begin(); it != data.extders.end(); it++) { - if (it->current_nozzle_flow_type == NozzleFlowType::H_FLOW) { + for (auto it = data.GetExtruders().begin(); it != data.GetExtruders().end(); it++) { + if (it->GetNozzleFlowType() == NozzleFlowType::H_FLOW) { flow_type_of_machine.push_back("High Flow"); - } else if (it->current_nozzle_flow_type == NozzleFlowType::S_FLOW) { + } else if (it->GetNozzleFlowType() == NozzleFlowType::S_FLOW) { flow_type_of_machine.push_back("Standard"); } } @@ -1543,9 +1540,9 @@ bool SyncBoxInfoDialog::is_nozzle_type_match(ExtderData data, wxString &error_me if (target_machine_nozzle_id < flow_type_of_machine.size()) { if (flow_type_of_machine[target_machine_nozzle_id] != used_extruders_flow[it->first]) { wxString pos; - if (target_machine_nozzle_id == DEPUTY_NOZZLE_ID) { + if (target_machine_nozzle_id == DEPUTY_EXTRUDER_ID) { pos = _L("left nozzle"); - } else if ((target_machine_nozzle_id == MAIN_NOZZLE_ID)) { + } else if ((target_machine_nozzle_id == MAIN_EXTRUDER_ID)) { pos = _L("right nozzle"); } @@ -1842,7 +1839,7 @@ bool SyncBoxInfoDialog::is_blocking_printing(MachineObject *obj_) } if (source_model != target_model) { - std::vector compatible_machine = dev->get_compatible_machine(target_model); + std::vector compatible_machine = obj_->get_compatible_machine(); vector::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model); if (it == compatible_machine.end()) { return true; } } @@ -1860,6 +1857,7 @@ bool SyncBoxInfoDialog::is_same_nozzle_diameters(NozzleType &tag_nozzle_type, fl DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (!dev) return true; + MachineObject* obj_ = dev->get_selected_machine(); if (obj_ == nullptr) return true; try { @@ -1870,8 +1868,8 @@ bool SyncBoxInfoDialog::is_same_nozzle_diameters(NozzleType &tag_nozzle_type, fl std::vector preset_nozzle_types(nozzle_type->size()); for (size_t idx = 0; idx < nozzle_type->size(); ++idx) preset_nozzle_types[idx] = NozzleTypeEumnToStr[NozzleType(nozzle_type->values[idx])]; - std::vector machine_nozzle_types(obj_->m_extder_data.extders.size()); - for (size_t idx = 0; idx < obj_->m_extder_data.extders.size(); ++idx) machine_nozzle_types[idx] = obj_->m_extder_data.extders[idx].current_nozzle_type; + std::vector machine_nozzle_types(obj_->GetExtderSystem()->GetTotalExtderCount()); + for (size_t idx = 0; idx < obj_->GetExtderSystem()->GetTotalExtderCount(); ++idx) machine_nozzle_types[idx] = obj_->GetExtderSystem()->GetNozzleType(idx); auto used_filaments = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_filaments(); // 1 based auto filament_maps = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_real_filament_maps(preset_bundle->project_config); // 1 based @@ -1884,13 +1882,13 @@ bool SyncBoxInfoDialog::is_same_nozzle_diameters(NozzleType &tag_nozzle_type, fl std::sort(used_extruders.begin(), used_extruders.end()); // TODO [tao wang] : add idx mapping - tag_nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + tag_nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); if (opt_nozzle_diameters != nullptr) { for (auto i = 0; i < used_extruders.size(); i++) { auto extruder = used_extruders[i]; preset_nozzle_diameters = float(opt_nozzle_diameters->get_at(extruder)); - if (preset_nozzle_diameters != obj_->m_extder_data.extders[0].current_nozzle_diameter) { is_same_nozzle_diameters = false; } + if (preset_nozzle_diameters != obj_->GetExtderSystem()->GetNozzleDiameter(0)) { is_same_nozzle_diameters = false; } } } @@ -1910,7 +1908,7 @@ bool SyncBoxInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleTy if (obj_ == nullptr) return true; - NozzleType nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + NozzleType nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); auto printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(nozzle_type); auto preset_bundle = wxGetApp().preset_bundle; @@ -1927,7 +1925,7 @@ bool SyncBoxInfoDialog::is_same_nozzle_type(std::string &filament_type, NozzleTy tag_nozzle_type = NozzleType::ntHardenedSteel; return is_same_nozzle_type; } else { - tag_nozzle_type = obj_->m_extder_data.extders[0].current_nozzle_type; + tag_nozzle_type = obj_->GetExtderSystem()->GetNozzleType(0); } iter++; @@ -2150,11 +2148,11 @@ void SyncBoxInfoDialog::update_user_printer() // same machine only appear once for (auto it = option_list.begin(); it != option_list.end(); it++) { - if (it->second && (it->second->is_online() || it->second->is_connected())) { machine_list.push_back(it->second->dev_name); } + if (it->second && (it->second->is_online() || it->second->is_connected())) { machine_list.push_back(it->second->get_dev_name()); } } // lan machine list - auto lan_option_list = dev->get_local_machine_list(); + auto lan_option_list = dev->get_local_machinelist(); for (auto elem : lan_option_list) { MachineObject *mobj = elem.second; @@ -2164,17 +2162,17 @@ void SyncBoxInfoDialog::update_user_printer() if (!mobj->is_online()) continue; if (!mobj->is_lan_mode_printer()) continue; if (!mobj->has_access_right()) { - option_list[mobj->dev_name] = mobj; - machine_list.push_back(mobj->dev_name); + option_list[mobj->get_dev_name()] = mobj; + machine_list.push_back(mobj->get_dev_name()); } } machine_list = sort_string(machine_list); for (auto tt = machine_list.begin(); tt != machine_list.end(); tt++) { for (auto it = option_list.begin(); it != option_list.end(); it++) { - if (it->second->dev_name == *tt) { + if (it->second->get_dev_name() == *tt) { m_list.push_back(it->second); - wxString dev_name_text = from_u8(it->second->dev_name); + wxString dev_name_text = from_u8(it->second->get_dev_name()); if (it->second->is_lan_mode_printer()) { dev_name_text += "(LAN)"; } machine_list_name.Add(dev_name_text); break; @@ -2204,8 +2202,8 @@ void SyncBoxInfoDialog::on_timer(wxTimerEvent &event) m_check_flag = true; } - if (!obj_ || obj_->amsList.empty() || obj_->ams_exist_bits == 0 || !obj_->is_support_filament_backup || !obj_->is_support_show_filament_backup || - !obj_->ams_auto_switch_filament_flag || m_checkbox_list["use_ams"]->getValue() != "on") { + if (!obj_ || !obj_->GetFilaSystem()->HasAms() || obj_->ams_exist_bits == 0 || !obj_->is_support_filament_backup || !obj_->GetExtderSystem()->HasFilamentBackup() || + !obj_->GetFilaSystem()->IsAutoRefillEnabled() || m_checkbox_list["use_ams"]->getValue() != "on") { if (m_ams_backup_tip && m_ams_backup_tip->IsShown()) { m_ams_backup_tip->Hide(); img_ams_backup->Hide(); @@ -2232,14 +2230,61 @@ void SyncBoxInfoDialog::update_show_status() if (get_status() == PrintDialogStatus::PrintStatusSendingCanceled) return; - // blank plate has no valid gcode file - if (is_must_finish_slice_then_connected_printer()) { return; } + // NetworkAgent* agent = Slic3r::GUI::wxGetApp().getAgent(); + // DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + // if (!agent) { + // return; + // } + // if (!dev) return; + + // // blank plate has no valid gcode file + // if (is_must_finish_slice_then_connected_printer()) { return; } + // MachineObject* obj_ = dev->get_selected_machine(); + // if (!obj_) { + // if (agent) { + // if (agent->is_user_login()) { + // show_status(PrintDialogStatus::PrintStatusInvalidPrinter); + // } + // } + // return; + // } + + // /* check cloud machine connections */ + // if (!obj_->is_lan_mode_printer()) { + // if (!agent->is_server_connected()) { + // show_status(PrintDialogStatus::PrintStatusConnectingServer); + // reset_timeout(); + // return; + // } + // } + + // if (!obj_->is_info_ready()) { + // if (is_timeout()) { + // BOOST_LOG_TRIVIAL(error) << "check error:machine timeout"; + // m_ams_mapping_result.clear(); + // sync_ams_mapping_result(m_ams_mapping_result); + // show_status(PrintDialogStatus::PrintStatusReadingTimeout); + // return; + // } + // else { + // m_timeout_count++; + // show_status(PrintDialogStatus::PrintStatusReading); + // return; + // } + // return; + // } reset_timeout(); + // if (!obj_->GetConfig()->SupportPrintAllPlates() && m_print_plate_idx == PLATE_ALL_IDX) { + // show_status(PrintDialogStatus::PrintStatusNotSupportedPrintAll); + // return; + // } + // do ams mapping if no ams result + if (m_ams_mapping_result.empty()) { - do_ams_mapping(); + do_ams_mapping(obj_); } @@ -2256,47 +2301,50 @@ void SyncBoxInfoDialog::update_show_status() } } - if (obj_->is_in_upgrading()) { + if (is_blocking_printing(obj_)) { + show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter); + return; + } + else if (obj_->is_in_upgrading()) { show_status(PrintDialogStatus::PrintStatusInUpgrading); return; - } else if (obj_->is_system_printing()) { + } + else if (obj_->is_system_printing()) { show_status(PrintDialogStatus::PrintStatusInSystemPrinting); return; - } else if (obj_->is_in_printing() || obj_->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { + } + else if (obj_->is_in_printing() || obj_->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { show_status(PrintDialogStatus::PrintStatusInPrinting); return; - } else if (!obj_->is_support_print_without_sd && (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD)) { + } + else if (!obj_->GetConfig()->SupportPrintWithoutSD() && (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD)) { show_status(PrintDialogStatus::PrintStatusNoSdcard); return; } // check sdcard when if lan mode printer if (obj_->is_lan_mode_printer()) { - if (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { show_status(PrintDialogStatus::PrintStatusLanModeNoSdcard); return; - } else if (obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL || obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_READONLY) { + } + else if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL || obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_READONLY) { show_status(PrintDialogStatus::PrintStatusLanModeSDcardNotAvailable); return; } } // do ams mapping if no ams result - if (m_ams_mapping_result.empty()) { do_ams_mapping(); } + if (m_ams_mapping_result.empty()) { do_ams_mapping(obj_); } - const auto &full_config = wxGetApp().preset_bundle->full_config(); + const auto& full_config = wxGetApp().preset_bundle->full_config(); size_t nozzle_nums = full_config.option("nozzle_diameter")->values.size(); // the nozzle type of preset and machine are different if (nozzle_nums > 1) { - if (obj_->is_nozzle_data_invalid()) { - show_status(PrintDialogStatus::PrintStatusNozzleDataInvalid); - return; - } - - wxString error_message; - if (!is_nozzle_type_match(obj_->m_extder_data, error_message)) { - std::vector params{error_message}; + wxString error_message; + if (!is_nozzle_type_match(*obj_->GetExtderSystem(), error_message)) { + std::vector params{ error_message }; params.emplace_back(_L("Tips: If you changed your nozzle of your printer lately, Please go to 'Device -> Printer parts' to change your nozzle setting.")); show_status(PrintDialogStatus::PrintStatusNozzleMatchInvalid, params); return; @@ -2320,15 +2368,15 @@ void SyncBoxInfoDialog::update_show_status() { struct ExtruderStatus { - bool has_ams{false}; - bool has_vt_slot{false}; + bool has_ams{ false }; + bool has_vt_slot{ false }; }; std::vector extruder_status(nozzle_nums); - for (const FilamentInfo &item : m_ams_mapping_result) { + for (const FilamentInfo& item : m_ams_mapping_result) { if (item.ams_id.empty()) continue; int extruder_id = obj_->get_extruder_id_by_ams_id(item.ams_id); - if (DeviceManager::is_virtual_slot(stoi(item.ams_id))) + if (devPrinterUtil::IsVirtualSlot(item.ams_id)) extruder_status[extruder_id].has_vt_slot = true; else extruder_status[extruder_id].has_ams = true; @@ -3151,7 +3199,7 @@ void SyncBoxInfoDialog::update_lan_machine_list() { DeviceManager *dev = wxGetApp().getDeviceManager(); if (!dev) return; - auto m_free_machine_list = dev->get_local_machine_list(); + auto m_free_machine_list = dev->get_local_machinelist(); BOOST_LOG_TRIVIAL(info) << "SelectMachinePopup update_other_devices start"; @@ -3164,7 +3212,7 @@ void SyncBoxInfoDialog::update_lan_machine_list() if (!mobj->is_lan_mode_printer()) continue; if (mobj->has_access_right()) { - auto b = mobj->dev_name; + auto b = mobj->get_dev_name(); // clear machine list diff --git a/src/slic3r/GUI/SyncBoxInfoDialog.hpp b/src/slic3r/GUI/SyncBoxInfoDialog.hpp index e131598..86875dc 100644 --- a/src/slic3r/GUI/SyncBoxInfoDialog.hpp +++ b/src/slic3r/GUI/SyncBoxInfoDialog.hpp @@ -208,14 +208,14 @@ public: bool is_timeout(); int update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path); void set_print_type(PrintFromType type) { m_print_type = type; }; - bool do_ams_mapping(); + bool do_ams_mapping(MachineObject* obj_); void deal_only_exist_ext_spool(); void show_thumbnail_page(); bool get_ams_mapping_result(std::string &mapping_array_str, std::string &mapping_array_str2, std::string &ams_mapping_info); bool build_nozzles_info(std::string &nozzles_info); - bool can_hybrid_mapping(ExtderData data); - void auto_supply_with_ext(std::vector slots); - bool is_nozzle_type_match(ExtderData data, wxString &error_message) const; + bool can_hybrid_mapping(DevExtderSystem data); + void auto_supply_with_ext(std::vector slots); + bool is_nozzle_type_match(DevExtderSystem data, wxString &error_message) const; int convert_filament_map_nozzle_id_to_task_nozzle_id(int nozzle_id); PrintFromType get_print_type() { return m_print_type; }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 8de282b..2b790f1 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -44,6 +44,8 @@ #include "Search.hpp" #include "BedShapeDialog.hpp" +#include "DeviceCore/DevManager.h" + #ifdef WIN32 #include #endif // WIN32 @@ -927,7 +929,7 @@ void Tab::init_options_list() for (const std::string& opt_key : m_config->keys()) { - if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "thumbnail_size") { + if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnail_size" || opt_key == "wrapping_exclude_area") { m_options_list.emplace(opt_key, m_opt_status_value); continue; } @@ -1475,13 +1477,31 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) if (opt_key == "enable_prime_tower") { auto timelapse_type = m_config->option>("timelapse_type"); bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth; - if (!boost::any_cast(value) && timelapse_enabled) { - MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required for smooth timeplase. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"), - _L("Warning"), wxICON_WARNING | wxYES | wxNO); - if (dlg.ShowModal() == wxID_NO) { - DynamicPrintConfig new_conf = *m_config; - new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true)); - m_config_manipulation.apply(m_config, &new_conf); + if (!boost::any_cast(value)) { + bool set_enable_prime_tower = false; + if (timelapse_enabled) { + MessageDialog + dlg(wxGetApp().plater(), + _L("Prime tower is required for smooth timeplase. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"), + _L("Warning"), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_NO) { + DynamicPrintConfig new_conf = *m_config; + new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true)); + m_config_manipulation.apply(m_config, &new_conf); + set_enable_prime_tower = true; + } + } + bool enable_wrapping = m_config->option("enable_wrapping_detection")->value; + if (enable_wrapping && !set_enable_prime_tower) { + MessageDialog dlg(wxGetApp().plater(), + _L("Prime tower is required for clumping detection. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"), + _L("Warning"), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_NO) { + DynamicPrintConfig new_conf = *m_config; + new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true)); + m_config_manipulation.apply(m_config, &new_conf); + set_enable_prime_tower = true; + } } wxGetApp().plater()->update(); } @@ -1499,6 +1519,23 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) update_wiping_button_visibility(); } + if (opt_key == "enable_wrapping_detection") { + bool wipe_tower_enabled = m_config->option("enable_prime_tower")->value; + if (boost::any_cast(value) && !wipe_tower_enabled) { + MessageDialog dlg(wxGetApp().plater(), + _L("Prime tower is required for clumping detection. There may be flaws on the model without prime tower. Do you still want to enable clumping detection?"), + _L("Warning"), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_NO) { + DynamicPrintConfig new_conf = *m_config; + new_conf.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); + m_config_manipulation.apply(m_config, &new_conf); + wxGetApp().plater()->update(); + } + } else { + wxGetApp().plater()->update(); + } + } + if (opt_key == "precise_z_height") { bool wipe_tower_enabled = m_config->option("enable_prime_tower")->value; if (boost::any_cast(value) && wipe_tower_enabled) { @@ -1567,7 +1604,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) support_TPU = filament_type == "PLA" && has_filaments({"TPU", "TPU-AMS"}); } } - if (is_support_filament(filament_id) && !is_soluble_filament(filament_id) && !has_filaments({"TPU", "TPU-Box"})) { + if (is_support_filament(filament_id, false) && !is_soluble_filament(filament_id) && !has_filaments({"TPU", "TPU-BOX"})) { wxString msg_text = _L("Non-soluble support materials are not recommended for support base. \n" "Are you sure to use them for support base? \n"); MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO); @@ -1627,7 +1664,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) } } - if ((is_support_filament(interface_filament_id) && + if ((is_support_filament(interface_filament_id, false) && !(m_config->opt_float("support_top_z_distance") == 0 && m_config->opt_float("support_interface_spacing") == 0 && m_config->opt_enum("support_interface_pattern") == SupportMaterialInterfacePattern::smipRectilinearInterlaced && (support_TPU ? m_config->opt_float("support_object_xy_distance") == 0 : -1))) || @@ -2477,6 +2514,7 @@ void TabPrint::build() optgroup->append_single_option_line("fuzzy_skin_thickness"); optgroup = page->new_optgroup(L("Advanced"), L"advanced"); + optgroup->append_single_option_line("enable_wrapping_detection", "nozzle-clumping-detection-by-probing"); optgroup->append_single_option_line("interlocking_beam"); // optgroup->append_single_option_line("mmu_segmented_region_max_width"); optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth"); @@ -3429,6 +3467,7 @@ void TabFilament::build() optgroup->append_single_option_line("pressure_advance"); optgroup->append_single_option_line("filament_density"); optgroup->append_single_option_line("filament_shrink"); + optgroup->append_single_option_line("filament_velocity_adaptation_factor"); optgroup->append_single_option_line("filament_cost"); //QDS @@ -3529,6 +3568,7 @@ void TabFilament::build() //QDS optgroup = page->new_optgroup(L("Volumetric speed limitation"), L"param_volumetric_speed"); + optgroup->append_single_option_line("filament_adaptive_volumetric_speed", "", 0); optgroup->append_single_option_line("filament_max_volumetric_speed", "", 0); optgroup->append_single_option_line("filament_ramming_volumetric_speed", "",0); @@ -3761,8 +3801,10 @@ void TabFilament::toggle_options() } if (m_active_page->title() == "Filament") { - toggle_option("filament_type", false); - toggle_option("filament_vendor", false); + //y71 + toggle_option("filament_type", true); + toggle_option("filament_vendor", true); + toggle_option("impact_strength_z", false); //QDS: hide these useless option for qidi printer toggle_line("enable_pressure_advance", !is_QDT_printer); @@ -3787,6 +3829,10 @@ void TabFilament::toggle_options() auto support_multi_bed_types = cfg.opt_bool("support_multi_bed_types"); for (auto el : {"supertack_plate_temp", "supertack_plate_temp_initial_layer", "cool_plate_temp", "cool_plate_temp_initial_layer", "eng_plate_temp", "eng_plate_temp_initial_layer", "hot_plate_temp_initial_layer","hot_plate_temp" }) toggle_line(el, support_multi_bed_types); + + std::string volumetric_speed_cos = m_config->opt_string("volumetric_speed_coefficients", (unsigned int)(m_variant_combo->GetSelection())); + bool enable_fit = volumetric_speed_cos != "0 0 0 0 0 0"; + toggle_option("filament_adaptive_volumetric_speed", enable_fit, 256 + (unsigned int) (m_variant_combo->GetSelection())); } if (m_active_page->title() == "Multi Filament") { @@ -3805,6 +3851,7 @@ void TabFilament::update() return; // ys_FIXME m_config_manipulation.check_filament_max_volumetric_speed(m_config); + m_config_manipulation.check_filament_scarf_setting(m_config); m_update_cnt++; @@ -3877,6 +3924,7 @@ void TabPrinter::build_fff() auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); + m_extruder_variant_list = m_config->option("printer_extruder_variant")->values; // QDS //wxGetApp().obj_list()->update_objects_list_filament_column(m_initial_extruders_count); @@ -4038,7 +4086,12 @@ void TabPrinter::build_fff() }); }; - optgroup->append_single_option_line("scan_first_layer"); + //y71 + //optgroup->append_single_option_line("scan_first_layer"); + + //option = optgroup->get_option("wrapping_exclude_area"); + //option.opt.full_width = true; + //optgroup->append_single_option_line(option); optgroup->append_single_option_line("use_relative_e_distances"); optgroup->append_single_option_line("use_firmware_retraction"); optgroup->append_single_option_line("bed_temperature_formula"); @@ -4127,6 +4180,16 @@ void TabPrinter::build_fff() option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); + optgroup = page->new_optgroup(L("Clumping Detection G-code"), L"param_gcode", 0); + optgroup->m_on_change = [this, optgroup](const t_config_option_key &opt_key, const boost::any &value) { + validate_custom_gcode_cb(this, optgroup, opt_key, value); + }; + option = optgroup->get_option("wrapping_detection_gcode"); + option.opt.full_width = true; + option.opt.is_code = true; + option.opt.height = gcode_field_height; // 150; + optgroup->append_single_option_line(option); + optgroup = page->new_optgroup(L("Change filament G-code"), L"param_gcode", 0); optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup, opt_key, value); @@ -4584,6 +4647,8 @@ void TabPrinter::on_preset_loaded() if (m_extruders_count != extruders_count) extruders_count_changed(extruders_count); + m_extruder_variant_list = m_config->option("printer_extruder_variant")->values; + if (base_name != m_base_preset_name) { bool use_default_nozzle_volume_type = true; m_base_preset_name = base_name; @@ -4684,6 +4749,9 @@ void TabPrinter::toggle_options() is_QDT_printer = m_preset_bundle->printers.get_edited_preset().is_qdt_vendor_preset(m_preset_bundle); } + //y71 + is_QDT_printer = true; + bool have_multiple_extruders = m_extruders_count > 1; //if (m_active_page->title() == "Custom G-code") { // toggle_option("change_filament_gcode", have_multiple_extruders); @@ -4701,8 +4769,11 @@ void TabPrinter::toggle_options() toggle_option("support_box_temp_control",!is_QDT_printer); toggle_option("use_firmware_retraction", !is_QDT_printer); - //w15 - //toggle_option("support_air_filtration",is_QDT_printer); + + //w15 y71 + bool support_air_filtration = m_preset_bundle->printers.get_edited_preset().config.opt_bool("support_air_filtration"); + toggle_option("support_air_filtration", support_air_filtration); + auto flavor = m_config->option>("gcode_flavor")->value; bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware; // Disable silent mode for non-marlin firmwares. @@ -4712,6 +4783,12 @@ void TabPrinter::toggle_options() toggle_option(el, !is_QDT_printer); } + if (m_active_page->title() == "Machine gcode") { + PresetBundle *preset_bundle = wxGetApp().preset_bundle; + std::string printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle); + toggle_line("wrapping_detection_gcode", DevPrinterConfigUtil::support_wrapping_detection(printer_type)); + } + wxString extruder_number; long val = 1; if ( m_active_page->title().IsSameAs("Extruder") || @@ -4866,14 +4943,16 @@ void Tab::load_current_preset() { BOOST_LOG_TRIVIAL(info) << __FUNCTION__<get_edited_preset(); - int previous_extruder_count = 0; + std::vector prev_variant_list; + int prev_extruder_count = 0; update_btns_enabling(); if (m_type == Slic3r::Preset::TYPE_PRINTER) { // For the printer profile, generate the extruder pages. if (preset.printer_technology() == ptFFF) { - previous_extruder_count = static_cast(this)->m_extruders_count; + prev_variant_list = static_cast(this)->m_extruder_variant_list; + prev_extruder_count = static_cast(this)->m_extruders_count; on_preset_loaded(); } else @@ -4881,9 +4960,11 @@ void Tab::load_current_preset() } if (m_type == Preset::TYPE_PRINT) { if (auto tab = wxGetApp().plate_tab) { + tab->m_config->apply(*m_config); tab->update_extruder_variants(); } for (auto tab : wxGetApp().model_tabs_list) { + tab->m_config->apply(*m_config); tab->update_extruder_variants(); } } @@ -4961,8 +5042,9 @@ void Tab::load_current_preset() } //update the object config due to extruder count change DynamicPrintConfig& new_print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + std::vector new_variant_list = wxGetApp().preset_bundle->printers.get_edited_preset().config.option("printer_extruder_variant")->values; int new_extruder_count = wxGetApp().preset_bundle->get_printer_extruder_count(); - if (previous_extruder_count != new_extruder_count) + if (prev_extruder_count != new_extruder_count || prev_variant_list.size() != new_variant_list.size()) { //process the object params here Model& model = wxGetApp().plater()->model(); @@ -4971,20 +5053,14 @@ void Tab::load_current_preset() ModelObject* object = model.objects[i]; DynamicPrintConfig object_config = object->config.get(); if (!object_config.empty()) { - if (previous_extruder_count < new_extruder_count) - object_config.update_values_from_single_to_multi_2(new_print_config, print_options_with_variant); - else - object_config.update_values_from_multi_to_single_2(print_options_with_variant); + object_config.update_values_from_multi_to_multi_2(prev_variant_list, new_variant_list, new_print_config, print_options_with_variant); object->config.assign_config(std::move(object_config)); } for (ModelVolume* v : object->volumes) { if (v->is_model_part() || v->is_modifier()) { DynamicPrintConfig volume_config = v->config.get(); if (!volume_config.empty()) { - if (previous_extruder_count < new_extruder_count) - volume_config.update_values_from_single_to_multi_2(new_print_config, print_options_with_variant); - else - volume_config.update_values_from_multi_to_single_2(print_options_with_variant); + volume_config.update_values_from_multi_to_multi_2(prev_variant_list,new_variant_list,new_print_config, print_options_with_variant); v->config.assign_config(std::move(volume_config)); } } @@ -4994,11 +5070,8 @@ void Tab::load_current_preset() ModelConfig& layer_model_config = layer_config_it.second; DynamicPrintConfig layer_config = layer_model_config.get(); if (!layer_config.empty()) { - if (previous_extruder_count < new_extruder_count) - layer_config.update_values_from_single_to_multi_2(new_print_config, print_options_with_variant); - else - layer_config.update_values_from_multi_to_single_2(print_options_with_variant); - layer_model_config.assign_config(std::move(layer_config)); + layer_config.update_values_from_multi_to_multi_2(prev_variant_list,new_variant_list,new_print_config, print_options_with_variant); + layer_model_config.assign_config(std::move(layer_config)); } } } @@ -6227,6 +6300,9 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep void TabPrinter::set_extruder_volume_type(int extruder_id, NozzleVolumeType type) { + // -1 means single extruder, so we should default use extruder id 0 + if (extruder_id == -1) + extruder_id = 0; auto nozzle_volumes = m_preset_bundle->project_config.option("nozzle_volume_type"); assert(nozzle_volumes->values.size() > (size_t)extruder_id); nozzle_volumes->values[extruder_id] = type; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index a3fabf4..d9c003c 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -603,6 +603,7 @@ public: size_t m_initial_extruders_count; size_t m_sys_extruders_count; size_t m_cache_extruder_count = 0; + std::vector m_extruder_variant_list; std::string m_base_preset_name; PrinterTechnology m_printer_technology = ptFFF; diff --git a/src/slic3r/GUI/TaskManager.hpp b/src/slic3r/GUI/TaskManager.hpp index ccd7ea4..9f03ad4 100644 --- a/src/slic3r/GUI/TaskManager.hpp +++ b/src/slic3r/GUI/TaskManager.hpp @@ -2,6 +2,8 @@ #define slic3r_TaskManager_hpp_ #include "DeviceManager.hpp" +#include "slic3r/Utils/NetworkAgent.hpp" + #include #include diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 28d9fdf..a906c20 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -1262,8 +1262,9 @@ static size_t get_id_from_opt_key(std::string opt_key) static wxString get_full_label(std::string opt_key, const DynamicPrintConfig& config) { opt_key = get_pure_opt_key(opt_key); + auto option = config.option(opt_key); - if (config.option(opt_key)->is_nil()) + if (!option || option->is_nil()) return _L("N/A"); const ConfigOptionDef* opt = config.def()->get(opt_key); @@ -1283,6 +1284,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& opt_idx = orig_opt_idx >= 0 ? orig_opt_idx : 0; opt_key = get_pure_opt_key(opt_key); auto option = config.option(opt_key); + if (!option) { + return _L("N/A"); + } auto opt_vector = dynamic_cast(option); if (option->is_scalar() && config.option(opt_key)->is_nil() || @@ -1428,6 +1432,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& else if (opt_key == "head_wrap_detect_zone") { return get_thumbnails_string(config.option(opt_key)->values); } + else if (opt_key == "wrapping_exclude_area") { + return get_thumbnails_string(config.option(opt_key)->values); + } Vec2d val = config.opt(opt_key)->get_at(opt_idx); return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str()); } diff --git a/src/slic3r/GUI/UpgradePanel.cpp b/src/slic3r/GUI/UpgradePanel.cpp index 2a79a01..13744b4 100644 --- a/src/slic3r/GUI/UpgradePanel.cpp +++ b/src/slic3r/GUI/UpgradePanel.cpp @@ -8,6 +8,9 @@ #include "GUI_App.hpp" #include "libslic3r/Thread.hpp" +#include "DeviceCore/DevFilaSystem.h" +#include "DeviceCore/DevManager.h" + namespace Slic3r { namespace GUI { @@ -23,6 +26,7 @@ static const std::unordered_map ACCESSORY_DISPLAY_STR = { {"O2L_PCM", L("Cutting Module")}, {"O2L_ACM", "Active Cutting Module"}, {"O2L_UCM", "Ultrasonic Cutting Module"}, + {"O2L-AFP", L("Auto Fire Extinguishing System")}, }; enum FIRMWARE_STASUS @@ -213,6 +217,7 @@ MachineInfoPanel::MachineInfoPanel(wxWindow* parent, wxWindowID id, const wxPoin createCuttingWidgets(m_main_left_sizer); createLaserWidgets(m_main_left_sizer); createAirPumpWidgets(m_main_left_sizer); + createExtinguishWidgets(m_main_left_sizer); m_main_sizer->Add(m_main_left_sizer, 1, wxEXPAND, 0); @@ -372,6 +377,8 @@ void MachineInfoPanel::createLaserWidgets(wxBoxSizer* main_left_sizer) main_left_sizer->Add(m_laser_line_above, 0, wxEXPAND | wxLEFT, FromDIP(40)); m_lazer_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200))); + + m_lazer_img->SetBitmap(m_img_laser.bmp()); wxBoxSizer* content_sizer = new wxBoxSizer(wxVERTICAL); @@ -386,6 +393,27 @@ void MachineInfoPanel::createLaserWidgets(wxBoxSizer* main_left_sizer) main_left_sizer->Add(m_laser_sizer, 0, wxEXPAND, 0); } +void MachineInfoPanel::createExtinguishWidgets(wxBoxSizer* main_left_sizer) +{ + m_extinguish_line_above = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL); + m_extinguish_line_above->SetBackgroundColour(wxColour(206, 206, 206)); + main_left_sizer->Add(m_extinguish_line_above, 0, wxEXPAND | wxLEFT, FromDIP(40)); + + m_extinguish_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200))); + m_extinguish_img->SetBitmap(m_img_extinguish.bmp()); + + wxBoxSizer* content_sizer = new wxBoxSizer(wxVERTICAL); + content_sizer->Add(0, 40, 0, wxEXPAND, FromDIP(5)); + m_extinguish_version = new uiDeviceUpdateVersion(this, wxID_ANY); + content_sizer->Add(m_extinguish_version, 0, wxEXPAND, 0); + + m_extinguish_sizer = new wxBoxSizer(wxHORIZONTAL); + m_extinguish_sizer->Add(m_extinguish_img, 0, wxALIGN_TOP | wxALL, FromDIP(5)); + m_extinguish_sizer->Add(content_sizer, 1, wxEXPAND, 0); + + main_left_sizer->Add(m_extinguish_sizer, 0, wxEXPAND, 0); +} + void MachineInfoPanel::msw_rescale() { rescale_bitmaps(); @@ -404,24 +432,29 @@ void MachineInfoPanel::msw_rescale() void MachineInfoPanel::init_bitmaps() { - m_img_printer = ScalableBitmap(this, "printer_thumbnail", 160); - m_img_monitor_ams = ScalableBitmap(this, "monitor_upgrade_ams", 160); - m_img_ext = ScalableBitmap(this, "monitor_upgrade_ext", 160); - if (wxGetApp().dark_mode()) { - m_img_air_pump = ScalableBitmap(this, "air_pump_dark", 160); - m_img_extra_ams = ScalableBitmap(this, "extra_icon_dark", 160); - } - else { + try { + m_img_printer = ScalableBitmap(this, "printer_thumbnail_png", 160); + m_img_monitor_ams = ScalableBitmap(this, "monitor_upgrade_ams_png", 160); + m_img_ext = ScalableBitmap(this, "monitor_upgrade_ext", 160); + m_img_air_pump = ScalableBitmap(this, "air_pump", 160); - m_img_extra_ams = ScalableBitmap(this, "extra_icon", 160); + m_img_extra_ams = ScalableBitmap(this, "extra_icon_png", 160); + + m_img_laser = ScalableBitmap(this, "laser", 160); + m_img_cutting = ScalableBitmap(this, "cut", 160); + m_img_extinguish = ScalableBitmap(this, "extinguish", 160); + + upgrade_green_icon = ScalableBitmap(this, "monitor_upgrade_online", 5); + upgrade_gray_icon = ScalableBitmap(this, "monitor_upgrade_offline", 5); + upgrade_yellow_icon = ScalableBitmap(this, "monitor_upgrade_busy", 5); + } + catch (const std::exception &e) + { + BOOST_LOG_TRIVIAL(error) << "init_bitmaps failed to load resources: " << e.what(); + } catch (...) + { + BOOST_LOG_TRIVIAL(error) << "init_bitmaps failed to load resources: unknown error"; } - - m_img_laser = ScalableBitmap(this, "laser", 160); - m_img_cutting = ScalableBitmap(this, "cut", 160); - - upgrade_green_icon = ScalableBitmap(this, "monitor_upgrade_online", 5); - upgrade_gray_icon = ScalableBitmap(this, "monitor_upgrade_offline", 5); - upgrade_yellow_icon = ScalableBitmap(this, "monitor_upgrade_busy", 5); } void MachineInfoPanel::rescale_bitmaps() @@ -451,21 +484,25 @@ void MachineInfoPanel::update_printer_imgs(MachineObject* obj) { if (!obj) {return;} auto img = obj->get_printer_thumbnail_img_str(); - if (wxGetApp().dark_mode()) { - img += "_dark"; - m_img_extra_ams = ScalableBitmap(this, "extra_icon_dark", 160); + img += "_png"; + + try + { + m_img_extra_ams = ScalableBitmap(this, "extra_icon_png", 160); + m_img_printer = ScalableBitmap(this, img, 160); + m_printer_img->SetBitmap(m_img_printer.bmp()); + m_printer_img->Refresh(); + m_extra_ams_img->SetBitmap(m_img_extra_ams.bmp()); + m_extra_ams_img->Refresh(); } - else { - m_img_extra_ams = ScalableBitmap(this, "extra_icon", 160); - + catch (const std::exception &e) + { + BOOST_LOG_TRIVIAL(error) << "update_printer_imgs error : " << e.what(); + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << "update_printer_imgs failed: unknown error"; } - - m_img_printer = ScalableBitmap(this, img, 160); - m_printer_img->SetBitmap(m_img_printer.bmp()); - m_printer_img->Refresh(); - m_extra_ams_img->SetBitmap(m_img_extra_ams.bmp()); - m_extra_ams_img->Refresh(); - } void MachineInfoPanel::update(MachineObject* obj) @@ -480,22 +517,22 @@ void MachineInfoPanel::update(MachineObject* obj) m_panel_caption->Freeze(); if (!obj->is_connected()) { m_upgrade_status_img->SetBitmap(upgrade_gray_icon.bmp()); - wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->dev_name), _L("Offline")); + wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->get_dev_name()), _L("Offline")); m_caption_text->SetLabelText(caption_text); - show_status(MachineObject::UpgradingDisplayState::UpgradingUnavaliable); + show_status((int)DevFirmwareUpgradingState::UpgradingUnavaliable); } else { - show_status(obj->upgrade_display_state, obj->upgrade_status); - if (obj->upgrade_display_state == (int) MachineObject::UpgradingDisplayState::UpgradingUnavaliable) { + show_status((int)obj->upgrade_display_state, obj->upgrade_status); + if (obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingUnavaliable) { if (obj->can_abort()) { - wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->dev_name), _L("Printing")); + wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->get_dev_name()), _L("Printing")); m_caption_text->SetLabelText(caption_text); } else { - wxString caption_text = wxString::Format("%s", from_u8(obj->dev_name)); + wxString caption_text = wxString::Format("%s", from_u8(obj->get_dev_name())); m_caption_text->SetLabelText(caption_text); } m_upgrade_status_img->SetBitmap(upgrade_yellow_icon.bmp()); } else { - wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->dev_name), _L("Idle")); + wxString caption_text = wxString::Format("%s(%s)", from_u8(obj->get_dev_name()), _L("Idle")); m_caption_text->SetLabelText(caption_text); m_upgrade_status_img->SetBitmap(upgrade_green_icon.bmp()); } @@ -513,13 +550,14 @@ void MachineInfoPanel::update(MachineObject* obj) update_air_pump(obj); update_cut(obj); update_laszer(obj); + update_extinguish(obj); //update progress int upgrade_percent = obj->get_upgrade_percent(); - if (obj->upgrade_display_state == (int) MachineObject::UpgradingDisplayState::UpgradingInProgress) { + if (obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingInProgress) { m_upgrade_progress->SetValue(upgrade_percent); m_staticText_upgrading_percent->SetLabelText(wxString::Format("%d%%", upgrade_percent)); - } else if (obj->upgrade_display_state == (int) MachineObject::UpgradingDisplayState::UpgradingFinished) { + } else if (obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingFinished) { wxString result_text = obj->get_upgrade_result_str(obj->upgrade_err_code); m_upgrade_progress->SetValue(upgrade_percent); m_staticText_upgrading_percent->SetLabelText(wxString::Format("%d%%", upgrade_percent)); @@ -527,7 +565,7 @@ void MachineInfoPanel::update(MachineObject* obj) wxString model_id_text = obj->get_printer_type_display_str(); m_staticText_model_id_val->SetLabelText(model_id_text); - wxString sn_text = obj->dev_id; + wxString sn_text = obj->get_dev_id(); m_staticText_sn_val->SetLabelText(sn_text.MakeUpper()); this->Layout(); @@ -538,7 +576,7 @@ void MachineInfoPanel::update(MachineObject* obj) void MachineInfoPanel::update_version_text(MachineObject* obj) { - if (obj->upgrade_display_state == (int)MachineObject::UpgradingDisplayState::UpgradingInProgress) { + if (obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingInProgress) { m_staticText_ver_val->SetLabelText("-"); //m_staticText_ams_ver_val->SetLabelText("-"); m_ota_new_version_img->Hide(); @@ -552,11 +590,11 @@ void MachineInfoPanel::update_version_text(MachineObject* obj) && !obj->ota_new_version_number.empty()) { if (it != obj->module_vers.end()) { wxString ver_text= it->second.sw_ver; - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { ver_text+= wxString::Format("(%s)", _L("Beta version")); } ver_text += wxString::Format("->%s", obj->ota_new_version_number); - if (((it->second.firmware_status >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { + if (((it->second.firmware_flag >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } //wxString ver_text = wxString::Format("%s->%s", it->second.sw_ver, obj->ota_new_version_number); @@ -570,7 +608,7 @@ void MachineInfoPanel::update_version_text(MachineObject* obj) else { if (it != obj->module_vers.end()) { wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { m_staticText_beta_version->Show(); } else { @@ -588,7 +626,7 @@ void MachineInfoPanel::update_version_text(MachineObject* obj) if (ota_it == obj->new_ver_list.end()) { if (it != obj->module_vers.end()) { wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { m_staticText_beta_version->Show(); } else { @@ -603,11 +641,11 @@ void MachineInfoPanel::update_version_text(MachineObject* obj) wxString ver_text = wxString::Format("%s->%s", ota_it->second.sw_ver, ota_it->second.sw_new_ver); if (it != obj->module_vers.end()) { ver_text = ota_it->second.sw_ver; - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } ver_text += wxString::Format("->%s", ota_it->second.sw_new_ver); - if (((it->second.firmware_status >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { + if (((it->second.firmware_flag >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } } @@ -616,7 +654,7 @@ void MachineInfoPanel::update_version_text(MachineObject* obj) if (it != obj->module_vers.end()) { m_ota_new_version_img->Hide(); wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { m_staticText_beta_version->Show(); } else { @@ -634,7 +672,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) { bool has_hub_model = false; - bool is_o_series = DeviceManager::get_printer_series(obj->printer_type) == "series_o"; + bool is_o_series = obj->is_series_o(); //hub if (!obj->online_ahb || obj->module_vers.find("ahb") == obj->module_vers.end() || is_o_series) @@ -730,18 +768,18 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) if (has_new_version) { m_extra_ams_panel->m_ams_new_version_img->Show(); ver_text = new_extra_ams_ver->second.sw_ver; - if ((extra_ams_it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((extra_ams_it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } ver_text += wxString::Format("->%s", new_extra_ams_ver->second.sw_new_ver); - if (((extra_ams_it->second.firmware_status >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { + if (((extra_ams_it->second.firmware_flag >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } } else { m_extra_ams_panel->m_ams_new_version_img->Hide(); ver_text = wxString::Format("%s(%s)", extra_ams_it->second.sw_ver, _L("Latest version")); - if ((extra_ams_it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((extra_ams_it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { m_extra_ams_panel->m_staticText_beta_version->Show(); } else { @@ -756,10 +794,10 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) else { show_extra_ams(false); show_ams(true); - std::map ver_list = obj->get_ams_version(); + std::map ver_list = obj->get_ams_version(); - if (obj->amsList.size() != m_amspanel_list.size()) { - int add_count = obj->amsList.size() - m_amspanel_list.size(); + if (obj->GetFilaSystem()->GetAmsList().size() != m_amspanel_list.size()) { + int add_count = obj->GetFilaSystem()->GetAmsList().size() - m_amspanel_list.size(); if (add_count > 0) { for (int i = 0; i < add_count; i++) { auto amspanel = new AmsPanel(this, wxID_ANY); @@ -782,7 +820,8 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) } auto ams_index = 0; - for (std::map::iterator iter = obj->amsList.begin(); iter != obj->amsList.end(); iter++) { + const auto& ams_list = obj->GetFilaSystem()->GetAmsList(); + for (std::map::const_iterator iter = ams_list.cbegin(); iter != ams_list.cend(); iter++) { wxString ams_name; wxString ams_sn; wxString ams_ver; @@ -796,7 +835,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) continue; } - auto ams_id = std::stoi(iter->second->id); + auto ams_id = std::stoi(iter->second->GetAmsId()); ams_id -= ams_id >= 128 ? 128 : 0; size_t pos = it->second.name.find('/'); @@ -820,7 +859,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) } else { // update ams img - if (m_obj->upgrade_display_state == (int)MachineObject::UpgradingDisplayState::UpgradingInProgress) { + if (m_obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingInProgress) { ams_ver = "-"; amspanel->m_ams_new_version_img->Hide(); } @@ -833,7 +872,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) if (obj->ams_new_version_number.empty()) { ams_ver = wxString::Format("%s", it->second.sw_ver); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { amspanel->m_staticText_beta_version->Show(); } else { @@ -844,7 +883,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) else { //ams_ver = wxString::Format("%s->%s", it->second.sw_ver, obj->ams_new_version_number); ams_ver = it->second.sw_ver; - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { ams_ver += wxString::Format("(%s)", _L("Beta version")); } ams_ver += wxString::Format("->%s", obj->ams_new_version_number); @@ -854,7 +893,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) else { amspanel->m_ams_new_version_img->Hide(); wxString ver_text = wxString::Format("%s", it->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { amspanel->m_staticText_beta_version->Show(); } @@ -876,7 +915,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) if (ver_item == obj->new_ver_list.end()) { amspanel->m_ams_new_version_img->Hide(); wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { amspanel->m_staticText_beta_version->Show(); } else { @@ -889,11 +928,11 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) amspanel->m_ams_new_version_img->Show(); //wxString ver_text = wxString::Format("%s->%s", ver_item->second.sw_ver, ver_item->second.sw_new_ver); wxString ver_text = ver_item->second.sw_ver; - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { ver_text += wxString::Format("(%s)", _L("Beta version")); } ver_text += wxString::Format("->%s", ver_item->second.sw_new_ver); - if (((it->second.firmware_status >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { + if (((it->second.firmware_flag >> 2) & 0x3) == FIRMWARE_STASUS::BETA) { amspanel->m_staticText_beta_version->Show(); } else { @@ -904,7 +943,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) else { amspanel->m_ams_new_version_img->Hide(); wxString ver_text = wxString::Format("%s(%s)", ver_item->second.sw_ver, _L("Latest version")); - if ((it->second.firmware_status & 0x3) == FIRMWARE_STASUS::BETA) { + if ((it->second.firmware_flag & 0x3) == FIRMWARE_STASUS::BETA) { amspanel->m_staticText_beta_version->Show(); } else { @@ -972,9 +1011,11 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) // STUDIO-11572 Update image bool contain_one_slot = false; bool contain_four_slot = false; - auto ams_iter = obj->amsList.begin(); - while (ams_iter != obj->amsList.end()) { - if (ams_iter->second->type == 4) { + const auto& ams_list = obj->GetFilaSystem()->GetAmsList(); + auto ams_iter = ams_list.begin(); + while (ams_iter != ams_list.end()) { + if (ams_iter->second->GetSlotCount() == 1) + { contain_one_slot = true; } else { contain_four_slot = true; @@ -984,7 +1025,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj) if (contain_four_slot) { if (m_img_monitor_ams.name() != "monitor_upgrade_ams") { - m_img_monitor_ams = ScalableBitmap(this, "monitor_upgrade_ams", 160); + m_img_monitor_ams = ScalableBitmap(this, "monitor_upgrade_ams_png", 160); m_ams_img->SetBitmap(m_img_monitor_ams.bmp()); } } else if (contain_one_slot) { @@ -1029,6 +1070,26 @@ void MachineInfoPanel::update_laszer(MachineObject* obj) if (obj && obj->laser_version_info.isValid()) { m_laser_version->UpdateInfo(obj->laser_version_info); + + std::string current_product_name = obj->laser_version_info.product_name.ToStdString(); + + if (m_last_laser_product_name != current_product_name) { + std::string laser_image_name = "laser"; + + if (current_product_name.find("10W") != std::string::npos) { + laser_image_name = "laser"; + } else if (current_product_name.find("40W") != std::string::npos) { + laser_image_name = "laser_40"; + } + + m_img_laser = ScalableBitmap(this, laser_image_name, 160); + if (m_lazer_img) { + m_lazer_img->SetBitmap(m_img_laser.bmp()); + m_lazer_img->Refresh(); + } + + m_last_laser_product_name = current_product_name; + } show_laszer(true); } else @@ -1037,6 +1098,19 @@ void MachineInfoPanel::update_laszer(MachineObject* obj) } } +void MachineInfoPanel::update_extinguish(MachineObject* obj) +{ + if (obj && obj->extinguish_version_info.isValid()) + { + m_extinguish_version->UpdateInfo(obj->extinguish_version_info); + show_extinguish(true); + } + else + { + show_extinguish(false); + } +} + void MachineInfoPanel::show_status(int status, std::string upgrade_status_str) { if (last_status == status && last_status_str == upgrade_status_str) return; @@ -1047,7 +1121,7 @@ void MachineInfoPanel::show_status(int status, std::string upgrade_status_str) Freeze(); - if (status == (int)MachineObject::UpgradingDisplayState::UpgradingUnavaliable) { + if (status == (int)DevFirmwareUpgradingState::UpgradingUnavaliable) { m_button_upgrade_firmware->Show(); m_button_upgrade_firmware->Disable(); for (size_t i = 0; i < m_upgrading_sizer->GetItemCount(); i++) { @@ -1056,14 +1130,14 @@ void MachineInfoPanel::show_status(int status, std::string upgrade_status_str) m_upgrade_retry_img->Hide(); m_staticText_upgrading_info->Hide(); m_staticText_upgrading_percent->Hide(); - } else if (status == (int) MachineObject::UpgradingDisplayState::UpgradingAvaliable) { + } else if (status == (int) DevFirmwareUpgradingState::UpgradingAvaliable) { m_button_upgrade_firmware->Show(); m_button_upgrade_firmware->Enable(); for (size_t i = 0; i < m_upgrading_sizer->GetItemCount(); i++) { m_upgrading_sizer->Show(false); } m_upgrade_retry_img->Hide(); m_staticText_upgrading_info->Hide(); m_staticText_upgrading_percent->Hide(); - } else if (status == (int) MachineObject::UpgradingDisplayState::UpgradingInProgress) { + } else if (status == (int) DevFirmwareUpgradingState::UpgradingInProgress) { m_button_upgrade_firmware->Disable(); for (size_t i = 0; i < m_upgrading_sizer->GetItemCount(); i++) { m_upgrading_sizer->Show(true); } m_upgrade_retry_img->Hide(); @@ -1072,7 +1146,7 @@ void MachineInfoPanel::show_status(int status, std::string upgrade_status_str) m_staticText_upgrading_info->SetForegroundColour(TEXT_NORMAL_CLR); m_staticText_upgrading_percent->SetForegroundColour(TEXT_NORMAL_CLR); m_staticText_upgrading_percent->Show(); - } else if (status == (int) MachineObject::UpgradingDisplayState::UpgradingFinished) { + } else if (status == (int) DevFirmwareUpgradingState::UpgradingFinished) { if (upgrade_status_str == "UPGRADE_FAIL") { m_staticText_upgrading_info->SetLabel(_L("Updating failed")); m_staticText_upgrading_info->SetForegroundColour(TEXT_FAILED_CLR); @@ -1161,6 +1235,17 @@ void MachineInfoPanel::show_laszer(bool show) } } +void MachineInfoPanel::show_extinguish(bool show) +{ + if (m_extinguish_version->IsShown() != show) + { + m_extinguish_img->Show(show); + m_extinguish_line_above->Show(show); + m_extinguish_version->Show(show); + } +} + + void MachineInfoPanel::on_sys_color_changed() { if (m_obj) { @@ -1172,10 +1257,10 @@ void MachineInfoPanel::confirm_upgrade(MachineObject* obj) { if (obj) { obj->command_upgrade_confirm(); - obj->upgrade_display_state = MachineObject::UpgradingDisplayState::UpgradingInProgress; + obj->upgrade_display_state = DevFirmwareUpgradingState::UpgradingInProgress; obj->upgrade_display_hold_count = HOLD_COUNT_MAX; // enter in progress status first - this->show_status(MachineObject::UpgradingDisplayState::UpgradingInProgress); + this->show_status((int)DevFirmwareUpgradingState::UpgradingInProgress); } } @@ -1325,7 +1410,7 @@ void UpgradePanel::update(MachineObject *obj) //force upgrade //unlock hint - if (m_obj && (m_obj->upgrade_display_state == (int) MachineObject::UpgradingDisplayState::UpgradingFinished) && (last_forced_hint_status != m_obj->upgrade_display_state)) { + if (m_obj && (m_obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingFinished) && (last_forced_hint_status != m_obj->upgrade_display_state)) { last_forced_hint_status = m_obj->upgrade_display_state; m_show_forced_hint = true; } @@ -1337,7 +1422,7 @@ void UpgradePanel::update(MachineObject *obj) force_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this](wxCommandEvent& e) { if (m_obj) { m_obj->command_upgrade_confirm(); - m_obj->upgrade_display_state = MachineObject::UpgradingDisplayState::UpgradingInProgress; + m_obj->upgrade_display_state = DevFirmwareUpgradingState::UpgradingInProgress; m_obj->upgrade_display_hold_count = HOLD_COUNT_MAX; } }); @@ -1350,7 +1435,7 @@ void UpgradePanel::update(MachineObject *obj) } //consistency upgrade - if (m_obj && (m_obj->upgrade_display_state == (int) MachineObject::UpgradingDisplayState::UpgradingFinished) && (last_consistency_hint_status != m_obj->upgrade_display_state)) { + if (m_obj && (m_obj->upgrade_display_state == DevFirmwareUpgradingState::UpgradingFinished) && (last_consistency_hint_status != m_obj->upgrade_display_state)) { last_consistency_hint_status = m_obj->upgrade_display_state; m_show_consistency_hint = true; } @@ -1369,7 +1454,7 @@ void UpgradePanel::update(MachineObject *obj) "The firmware version is abnormal. Repairing and updating are required before printing. Do you want to update now? You can also update later on printer or update next time starting the studio." )); consistency_dlg->on_show(); - } + } } //update panels @@ -1415,7 +1500,7 @@ bool UpgradePanel::Show(bool show) if (show) { DeviceManager* dev = wxGetApp().getDeviceManager(); if (dev) { - MachineObject* obj = dev->get_default_machine(); + MachineObject* obj = dev->get_selected_machine(); refresh_version_and_firmware(obj); } } diff --git a/src/slic3r/GUI/UpgradePanel.hpp b/src/slic3r/GUI/UpgradePanel.hpp index 7e9c84c..b405e77 100644 --- a/src/slic3r/GUI/UpgradePanel.hpp +++ b/src/slic3r/GUI/UpgradePanel.hpp @@ -52,11 +52,11 @@ public: long style = wxTAB_TRAVERSAL, const wxString &name = wxEmptyString); ~AmsPanel(); - + void msw_rescale(); }; -class ExtraAmsPanel : public AmsPanel +class ExtraAmsPanel : public AmsPanel { public: ExtraAmsPanel(wxWindow* parent, @@ -126,6 +126,12 @@ protected: wxStaticLine* m_laser_line_above = nullptr;; uiDeviceUpdateVersion* m_laser_version = nullptr; + /* fire extinguish*/ + wxBoxSizer* m_extinguish_sizer = nullptr; + wxStaticBitmap* m_extinguish_img = nullptr; + wxStaticLine* m_extinguish_line_above = nullptr;; + uiDeviceUpdateVersion* m_extinguish_version = nullptr; + /* upgrade widgets */ wxBoxSizer* m_upgrading_sizer; wxStaticText * m_staticText_upgrading_info; @@ -146,12 +152,15 @@ protected: ScalableBitmap m_img_air_pump; ScalableBitmap m_img_cutting; ScalableBitmap m_img_laser; + ScalableBitmap m_img_extinguish; ScalableBitmap upgrade_gray_icon; ScalableBitmap upgrade_green_icon; ScalableBitmap upgrade_yellow_icon; int last_status = -1; std::string last_status_str = ""; + std::string m_last_laser_product_name = ""; + SecondaryCheckDialog* confirm_dlg = nullptr; void upgrade_firmware_internal(); @@ -175,16 +184,10 @@ public: void update(MachineObject *obj); void update_version_text(MachineObject *obj); void update_ams_ext(MachineObject *obj); - void update_air_pump(MachineObject* obj); - void update_cut(MachineObject* obj); - void update_laszer(MachineObject* obj); void show_status(int status, std::string upgrade_status_str = ""); void show_ams(bool show = false, bool force_update = false); void show_ext(bool show = false, bool force_update = false); void show_extra_ams(bool show = false, bool force_update = false); - void show_air_pump(bool show = true); - void show_cut(bool show = true); - void show_laszer(bool show = true); void on_upgrade_firmware(wxCommandEvent &event); void on_consisitency_upgrade_firmware(wxCommandEvent &event); @@ -206,6 +209,17 @@ private: void createAirPumpWidgets(wxBoxSizer* main_left_sizer); void createCuttingWidgets(wxBoxSizer* main_left_sizer); void createLaserWidgets(wxBoxSizer* main_left_sizer); + void createExtinguishWidgets(wxBoxSizer* main_left_sizer); + + void update_air_pump(MachineObject* obj); + void update_cut(MachineObject* obj); + void update_laszer(MachineObject* obj); + void update_extinguish(MachineObject* obj); + + void show_air_pump(bool show = true); + void show_cut(bool show = true); + void show_laszer(bool show = true); + void show_extinguish(bool show = true); }; //enum UpgradeMode { @@ -226,8 +240,8 @@ protected: bool enable_select_firmware = false; bool m_need_update = false; //hint of force upgrade or consistency upgrade - int last_forced_hint_status = -1; - int last_consistency_hint_status = -1; + DevFirmwareUpgradingState last_forced_hint_status = DevFirmwareUpgradingState::DC; + DevFirmwareUpgradingState last_consistency_hint_status = DevFirmwareUpgradingState::DC; int last_status; bool m_show_forced_hint = true; bool m_show_consistency_hint = true; diff --git a/src/slic3r/GUI/UserManager.cpp b/src/slic3r/GUI/UserManager.cpp index 29f5f2d..4b14503 100644 --- a/src/slic3r/GUI/UserManager.cpp +++ b/src/slic3r/GUI/UserManager.cpp @@ -6,6 +6,8 @@ #include "GUI_App.hpp" #include "MsgDialog.hpp" +#include "DeviceCore/DevManager.h" + namespace Slic3r { diff --git a/src/slic3r/GUI/WebGuideDialog.cpp b/src/slic3r/GUI/WebGuideDialog.cpp index 382df8a..394759a 100644 --- a/src/slic3r/GUI/WebGuideDialog.cpp +++ b/src/slic3r/GUI/WebGuideDialog.cpp @@ -727,9 +727,9 @@ int GuideFrame::SaveProfile() CopyDir(rsrc_vendor_dir,vendor_dir); }*/ - std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore); + // std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "before save to app_config: "<< std::endl<GetId()) { SwitchWebContent("home"); - SendDesignStaffpick(true); + if (wxGetApp().app_config->get("staff_pick_switch") == "true") + SendDesignStaffpick(true); + else + SendDesignStaffpick(false); SendMakerlabList(); } @@ -1685,9 +1701,12 @@ void WebViewPanel::OpenMakerworldSearchPage(std::string KeyWord) wxString language_code = wxString::FromUTF8(GetStudioLanguage()).BeforeFirst('_'); - m_online_LastUrl = (boost::format("%1%%2%/studio/webview/search?keyword=%3%&from=qidistudio") % host % language_code.mb_str() % UrlEncode(KeyWord)).str(); + //m_online_LastUrl = (boost::format("%1%%2%/studio/webview/search?keyword=%3%&from=qidistudio") % host % language_code.mb_str() % UrlEncode(KeyWord)).str(); + //SwitchLeftMenu("online"); - SwitchLeftMenu("online"); + m_online_LastUrl = (boost::format("%1%%2%/studio/webview/search?from=qidistudio&keyword=%3%&from_studio_home=true") % host % language_code.mb_str() % UrlEncode(KeyWord)).str(); + SwitchWebContent("online"); + //SwitchLeftMenu("online"); } void WebViewPanel::SetMakerworldModelID(std::string ModelID) @@ -1774,7 +1793,19 @@ void WebViewPanel::SwitchWebContent(std::string modelname, int refresh) m_online_LastUrl = ""; } else { - //m_browserMW->Reload(); + std::string TmpNowUrl = m_browserMW->GetCurrentURL().ToStdString(); + // If you click Online on the search page, navigate back to the Online page. + if (auto pos = TmpNowUrl.find("/search"); pos != std::string::npos){ + TmpNowUrl.erase(pos, 7); + } + if (auto pos = TmpNowUrl.find("&from_studio_home=true"); pos != std::string::npos) { + TmpNowUrl.erase(pos, 22); + } + std::regex pattern("&keyword=[^&]*"); + TmpNowUrl = std::regex_replace(TmpNowUrl, pattern, ""); + if(TmpNowUrl != m_browserMW->GetCurrentURL().ToStdString()) { + m_browserMW->LoadURL(TmpNowUrl); + } } } diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index c4a06cc..3f205b7 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -125,6 +125,7 @@ public: bool m_onlinefirst; // Online Page First Load wxString m_online_type; // recommend & browse wxString m_online_LastUrl; // PageLastError Url + std::string m_online_last_url; //last url void SendDesignStaffpick(bool on); void get_design_staffpick(int offset, int limit, std::function callback); diff --git a/src/slic3r/GUI/Widgets/AMSControl.cpp b/src/slic3r/GUI/Widgets/AMSControl.cpp index 125af26..02fdf69 100644 --- a/src/slic3r/GUI/Widgets/AMSControl.cpp +++ b/src/slic3r/GUI/Widgets/AMSControl.cpp @@ -7,6 +7,9 @@ #include "slic3r/GUI/MsgDialog.hpp" #include "slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h" +#include "slic3r/GUI/DeviceCore/DevManager.h" +#include "slic3r/GUI/DeviceCore/DevFilaSystem.h" + #include #include @@ -33,7 +36,6 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons parse_object(obj); } - m_extder_data.total_extder_count = 1; SetBackgroundColour(*wxWHITE); // normal mode //Freeze(); @@ -100,7 +102,7 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons m_panel_down_road->SetBackgroundColour(AMS_CONTROL_DEF_BLOCK_BK_COLOUR); m_down_road = new AMSRoadDownPart(m_panel_down_road, wxID_ANY, wxDefaultPosition, AMS_DOWN_ROAD_SIZE); - m_sizer_down_road->Add(m_panel_down_road, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 0); + m_sizer_down_road->Add(m_panel_down_road, 0, wxTOP, 0); // ams mode // @@ -174,7 +176,7 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons /*option mid*/ - m_extruder = new AMSextruder(m_amswin, wxID_ANY, m_extder_data.total_extder_count, wxDefaultPosition, AMS_EXTRUDER_SIZE); + m_extruder = new AMSextruder(m_amswin, wxID_ANY, m_total_ext_count, wxDefaultPosition, AMS_EXTRUDER_SIZE); m_sizer_option_mid->Add( m_extruder, 0, wxALIGN_CENTER, 0 ); @@ -228,11 +230,11 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons m_panel_option_left->Layout(); m_panel_option_right->Layout(); - m_sizer_ams_option->Add(m_panel_option_left, 0, wxALIGN_LEFT, 0); + m_sizer_ams_option->Add(m_panel_option_left, 0, wxALIGN_TOP, 0); m_sizer_ams_option->Add( 0, 0, 1, wxEXPAND, 0); - m_sizer_ams_option->Add(m_sizer_option_mid, 0, wxALIGN_RIGHT, 0); + m_sizer_ams_option->Add(m_sizer_option_mid, 0, wxALIGN_TOP, 0); m_sizer_ams_option->Add( 0, 0, 1, wxEXPAND, 0); - m_sizer_ams_option->Add(m_panel_option_right, 0, wxALIGN_RIGHT, 0); + m_sizer_ams_option->Add(m_panel_option_right, 0, wxALIGN_TOP, 0); m_sizer_ams_body->Add(m_sizer_ams_area_left, wxALIGN_CENTER, 0); @@ -280,7 +282,17 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons uiAmsHumidityInfo *info = (uiAmsHumidityInfo *) evt.GetClientData(); if (info) { - if (info->humidity_percent >= 0) + if (info->ams_type == AMSModel::GENERIC_AMS) + { + wxPoint img_pos = ClientToScreen(wxPoint(0, 0)); + wxPoint popup_pos(img_pos.x - m_Humidity_tip_popup.GetSize().GetWidth() + FromDIP(150), img_pos.y - FromDIP(80)); + m_Humidity_tip_popup.Position(popup_pos, wxSize(0, 0)); + + int humidity_value = info->humidity_display_idx; + if (humidity_value > 0 && humidity_value <= 5) { m_Humidity_tip_popup.set_humidity_level(humidity_value); } + m_Humidity_tip_popup.Popup(); + } + else { m_percent_humidity_dry_popup->Update(info); @@ -289,16 +301,6 @@ AMSControl::AMSControl(wxWindow *parent, wxWindowID id, const wxPoint &pos, cons m_percent_humidity_dry_popup->Move(popup_pos); m_percent_humidity_dry_popup->ShowModal(); } - else - { - wxPoint img_pos = ClientToScreen(wxPoint(0, 0)); - wxPoint popup_pos(img_pos.x - m_Humidity_tip_popup.GetSize().GetWidth() + FromDIP(150), img_pos.y - FromDIP(80)); - m_Humidity_tip_popup.Position(popup_pos, wxSize(0, 0)); - - int humidity_value = info->humidity_level; - if (humidity_value > 0 && humidity_value <= 5) { m_Humidity_tip_popup.set_humidity_level(humidity_value); } - m_Humidity_tip_popup.Popup(); - } } delete info; @@ -342,8 +344,8 @@ std::string AMSControl::GetCurrentCan(std::string amsid) } bool AMSControl::IsAmsInRightPanel(std::string ams_id) { - if (m_extder_data.total_extder_count == 2){ - if (m_ams_item_list.find(ams_id) != m_ams_item_list.end() && m_ams_item_list[ams_id]->get_nozzle_id() == MAIN_NOZZLE_ID) { + if (m_total_ext_count == 2){ + if (m_ams_item_list.find(ams_id) != m_ams_item_list.end() && m_ams_item_list[ams_id]->get_nozzle_id() == MAIN_EXTRUDER_ID) { return true; } else{ @@ -351,7 +353,7 @@ bool AMSControl::IsAmsInRightPanel(std::string ams_id) { } } else{ - for (auto id : m_item_ids[MAIN_NOZZLE_ID]){ + for (auto id : m_item_ids[MAIN_EXTRUDER_ID]){ if (id == ams_id){ return true; } @@ -532,6 +534,8 @@ void AMSControl::msw_rescale() m_percent_humidity_dry_popup->msw_rescale(); } + m_Humidity_tip_popup.msw_rescale(); + Layout(); Refresh(); } @@ -612,17 +616,17 @@ void AMSControl::CreateAmsDoubleNozzle(const std::string &series_name, const std //Freeze(); for (auto ams_info = m_ams_info.begin(); ams_info != m_ams_info.end(); ams_info++){ if (ams_info->cans.size() == GENERIC_AMS_SLOT_NUM){ - ams_info->nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(ams_info->ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(ams_info->ams_id); + ams_info->nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(ams_info->ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(ams_info->ams_id); AddAmsPreview(*ams_info, ams_info->ams_type); AddAms(*ams_info); } else if (ams_info->cans.size() == 1){ - if (ams_info->nozzle_id == MAIN_NOZZLE_ID){ + if (ams_info->nozzle_id == MAIN_EXTRUDER_ID){ single_info_right.push_back(*ams_info); if (single_info_right.size() == 2){ - single_info_right[0].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_right[0].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_right[0].ams_id); - single_info_right[1].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_right[1].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_right[1].ams_id); + single_info_right[0].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_right[0].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_right[0].ams_id); + single_info_right[1].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_right[1].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_right[1].ams_id); AddAms(single_info_right, series_name, printer_type); AddAmsPreview(single_info_right, AMSPanelPos::RIGHT_PANEL); pair_id.push_back(std::make_pair(single_info_right[0].ams_id, single_info_right[1].ams_id)); @@ -632,8 +636,8 @@ void AMSControl::CreateAmsDoubleNozzle(const std::string &series_name, const std else if (ams_info->nozzle_id == 1){ single_info_left.push_back(*ams_info); if (single_info_left.size() == 2){ - single_info_left[0].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_left[0].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_left[0].ams_id); - single_info_left[1].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_left[1].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_left[1].ams_id); + single_info_left[0].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_left[0].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_left[0].ams_id); + single_info_left[1].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_left[1].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_left[1].ams_id); AddAms(single_info_left, series_name, printer_type); AddAmsPreview(single_info_left, AMSPanelPos::LEFT_PANEL); pair_id.push_back(std::make_pair(single_info_left[0].ams_id, single_info_left[1].ams_id)); @@ -658,9 +662,9 @@ void AMSControl::CreateAmsDoubleNozzle(const std::string &series_name, const std //wait add - single_info_right[0].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_right[0].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_right[0].ams_id); + single_info_right[0].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_right[0].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_right[0].ams_id); if (single_info_right.size() == 2){ - single_info_right[1].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_right[1].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_right[1].ams_id); + single_info_right[1].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_right[1].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_right[1].ams_id); pair_id.push_back(std::make_pair(single_info_right[0].ams_id, single_info_right[1].ams_id)); } AddAms(single_info_right, series_name, printer_type); @@ -675,9 +679,9 @@ void AMSControl::CreateAmsDoubleNozzle(const std::string &series_name, const std } } //wait add - single_info_left[0].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_left[0].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_left[0].ams_id); + single_info_left[0].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_left[0].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_left[0].ams_id); if (single_info_left.size() == 2){ - single_info_left[1].nozzle_id == MAIN_NOZZLE_ID ? m_item_ids[MAIN_NOZZLE_ID].push_back(single_info_left[1].ams_id) : m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info_left[1].ams_id); + single_info_left[1].nozzle_id == MAIN_EXTRUDER_ID ? m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info_left[1].ams_id) : m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info_left[1].ams_id); pair_id.push_back(std::make_pair(single_info_left[0].ams_id, single_info_left[1].ams_id)); } AddAmsPreview(single_info_left, AMSPanelPos::LEFT_PANEL); @@ -703,19 +707,19 @@ void AMSControl::CreateAmsDoubleNozzle(const std::string &series_name, const std auto right_init_mode = findFirstMode(AMSPanelPos::RIGHT_PANEL); - m_down_road->UpdateLeft(m_extder_data.total_extder_count, left_init_mode); - m_down_road->UpdateRight(m_extder_data.total_extder_count, right_init_mode); + m_down_road->UpdateLeft(2, left_init_mode); + m_down_road->UpdateRight(2, right_init_mode); - m_extruder->updateNozzleNum(m_extder_data.total_extder_count); + m_extruder->updateNozzleNum(2); - m_current_show_ams_left = m_item_ids[DEPUTY_NOZZLE_ID].size() > 0 ? m_item_ids[DEPUTY_NOZZLE_ID][0] : ""; - m_current_show_ams_right = m_item_ids[MAIN_NOZZLE_ID].size() > 0 ? m_item_ids[MAIN_NOZZLE_ID][0] : ""; + m_current_show_ams_left = m_item_ids[DEPUTY_EXTRUDER_ID].size() > 0 ? m_item_ids[DEPUTY_EXTRUDER_ID][0] : ""; + m_current_show_ams_right = m_item_ids[MAIN_EXTRUDER_ID].size() > 0 ? m_item_ids[MAIN_EXTRUDER_ID][0] : ""; m_current_ams = ""; m_down_road->UpdatePassRoad(AMSPanelPos::LEFT_PANEL, -1, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); - m_extruder->OnAmsLoading(false, DEPUTY_NOZZLE_ID); + m_extruder->OnAmsLoading(false, DEPUTY_EXTRUDER_ID); m_down_road->UpdatePassRoad(AMSPanelPos::RIGHT_PANEL, -1, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); - m_extruder->OnAmsLoading(false, MAIN_NOZZLE_ID); + m_extruder->OnAmsLoading(false, MAIN_EXTRUDER_ID); m_amswin->Layout(); m_amswin->Fit(); @@ -733,13 +737,13 @@ void AMSControl::CreateAmsSingleNozzle(const std::string &series_name, const std //add ams data for (auto ams_info = m_ams_info.begin(); ams_info != m_ams_info.end(); ams_info++) { if (ams_info->cans.size() == GENERIC_AMS_SLOT_NUM) { - m_item_ids[DEPUTY_NOZZLE_ID].push_back(ams_info->ams_id); + m_item_ids[DEPUTY_EXTRUDER_ID].push_back(ams_info->ams_id); AddAmsPreview(*ams_info, ams_info->ams_type); AddAms(*ams_info, AMSPanelPos::LEFT_PANEL); //AddExtraAms(*ams_info); } else if (ams_info->cans.size() == 1) { - m_item_ids[DEPUTY_NOZZLE_ID].push_back(ams_info->ams_id); + m_item_ids[DEPUTY_EXTRUDER_ID].push_back(ams_info->ams_id); AddAmsPreview(*ams_info, ams_info->ams_type); AddAms(*ams_info, AMSPanelPos::LEFT_PANEL); @@ -756,8 +760,8 @@ void AMSControl::CreateAmsSingleNozzle(const std::string &series_name, const std } } if (single_info.size() > 0){ - m_item_ids[DEPUTY_NOZZLE_ID].push_back(single_info[0].ams_id); - m_item_nums[DEPUTY_NOZZLE_ID]++; + m_item_ids[DEPUTY_EXTRUDER_ID].push_back(single_info[0].ams_id); + m_item_nums[DEPUTY_EXTRUDER_ID]++; AddAms(single_info, series_name, printer_type, AMSPanelPos::LEFT_PANEL); AddAmsPreview(single_info, AMSPanelPos::LEFT_PANEL); single_info.clear(); @@ -770,7 +774,7 @@ void AMSControl::CreateAmsSingleNozzle(const std::string &series_name, const std } single_info.push_back(m_ext_info[0]); - m_item_ids[MAIN_NOZZLE_ID].push_back(single_info[0].ams_id); + m_item_ids[MAIN_EXTRUDER_ID].push_back(single_info[0].ams_id); AddAms(single_info, series_name, printer_type, AMSPanelPos::RIGHT_PANEL); auto left_init_mode = findFirstMode(AMSPanelPos::LEFT_PANEL); auto right_init_mode = findFirstMode(AMSPanelPos::RIGHT_PANEL); @@ -800,14 +804,14 @@ void AMSControl::CreateAmsSingleNozzle(const std::string &series_name, const std m_down_road->UpdateLeft(1, left_init_mode); m_down_road->UpdateRight(1, right_init_mode); } - m_current_show_ams_left = m_item_ids[DEPUTY_NOZZLE_ID].size() > 0 ? m_item_ids[DEPUTY_NOZZLE_ID][0] : ""; - m_current_show_ams_right = m_item_ids[MAIN_NOZZLE_ID].size() > 0 ? m_item_ids[MAIN_NOZZLE_ID][0] : ""; + m_current_show_ams_left = m_item_ids[DEPUTY_EXTRUDER_ID].size() > 0 ? m_item_ids[DEPUTY_EXTRUDER_ID][0] : ""; + m_current_show_ams_right = m_item_ids[MAIN_EXTRUDER_ID].size() > 0 ? m_item_ids[MAIN_EXTRUDER_ID][0] : ""; m_current_ams = ""; m_down_road->UpdatePassRoad(AMSPanelPos::LEFT_PANEL, -1, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); m_down_road->UpdatePassRoad(AMSPanelPos::RIGHT_PANEL, -1, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); m_extruder->updateNozzleNum(1); - m_extruder->OnAmsLoading(false, MAIN_NOZZLE_ID); + m_extruder->OnAmsLoading(false, MAIN_EXTRUDER_ID); m_amswin->Layout(); m_amswin->Fit(); @@ -909,7 +913,7 @@ void AMSControl::UpdateAms(const std::string &series_name, const std::string &printer_type, std::vector ams_info, std::vector ext_info, - ExtderData data, + DevExtderSystem data, std::string dev_id, bool is_reset, bool test) @@ -919,7 +923,8 @@ void AMSControl::UpdateAms(const std::string &series_name, bool fresh = false; // basic check - if (m_ams_info.size() == ams_info.size() && m_extder_data.total_extder_count == data.total_extder_count && m_dev_id == dev_id && m_ext_info.size() == ext_info.size()) { + if (m_ams_info.size() == ams_info.size() && m_total_ext_count == data.GetTotalExtderCount() && m_dev_id == dev_id && m_ext_info.size() == ext_info.size()) + { for (int i = 0; i < m_ams_info.size(); i++){ if (m_ams_info[i].ams_id != ams_info[i].ams_id){ fresh = true; @@ -936,13 +941,13 @@ void AMSControl::UpdateAms(const std::string &series_name, m_ams_info.clear(); m_ams_info = ams_info; + m_total_ext_count = data.GetTotalExtderCount(); m_ext_info.clear(); m_ext_info = ext_info; - m_extder_data = data; m_dev_id = dev_id; if (fresh){ ClearAms(); - if (m_extder_data.total_extder_count >= 2){ + if (m_total_ext_count >= 2){ CreateAmsDoubleNozzle(series_name, printer_type); }else{ CreateAmsSingleNozzle(series_name, printer_type); @@ -984,77 +989,7 @@ void AMSControl::UpdateAms(const std::string &series_name, { ams_prv.second->Update(item->second->get_ams_info()); } } - - /*if (m_current_show_ams.empty() && !is_reset) { - if (ext_info.size() > 0) { - SwitchAms(ext_info[0].ams_id); - } - }*/ - - //m_simplebook_ams_left->SetSelection(m_simplebook_ams_left->m_first); } - //else - //{ - // static bool first_time = true; - // bool fresh = false; - // static std::vectorams_info; - // int nozzle_num = 2; - // if (first_time){ - // ams_info = GenerateSimulateData(); - // fresh = true; - // first_time = false; - // } - - // //Freeze(); - - // // update item - // m_ams_info.clear(); - // m_ams_info = ams_info; - // m_ext_info.clear(); - // m_ext_info.push_back(ext_info[0]); - // m_ext_info.push_back(ext_info[0]); - // m_ext_info[0].ams_id = std::to_string(VIRTUAL_TRAY_MAIN_ID); - // m_ext_info[0].nozzle_id = MAIN_NOZZLE_ID; - // m_ext_info[1].ams_id = std::to_string(VIRTUAL_TRAY_DEPUTY_ID); - // m_ext_info[1].nozzle_id = DEPUTY_NOZZLE_ID; - // m_extder_data = data; - // if (fresh){ - // ClearAms(); - // if (m_extder_data.total_extder_count >= 2) { - // CreateAmsDoubleNozzle(); - // } - // else { - // CreateAmsSingleNozzle(); - // } - // SetSize(wxSize(FromDIP(578), -1)); - // SetMinSize(wxSize(FromDIP(578), -1)); - // Layout(); - // } - // //Thaw(); - - // // update cans - - // for (auto ams_item : m_ams_item_list) { - // std::string ams_id = ams_item.first; - // AmsItem* cans = ams_item.second; - // if (atoi(cans->get_ams_id().c_str()) >= VIRTUAL_TRAY_DEPUTY_ID) { - // for (auto ifo : m_ext_info) { - // if (ifo.ams_id == ams_id) { - // cans->Update(ifo); - // cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true); - // } - // } - // } - // else { - // for (auto ifo : m_ams_info) { - // if (ifo.ams_id == ams_id) { - // cans->Update(ifo); - // cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true); - // } - // } - // } - // } - //} /*update humidity popup*/ if (m_percent_humidity_dry_popup->IsShown()) @@ -1066,7 +1001,7 @@ void AMSControl::UpdateAms(const std::string &series_name, { uiAmsHumidityInfo humidity_info; humidity_info.ams_id = the_info.ams_id; - humidity_info.humidity_level = the_info.ams_humidity; + humidity_info.humidity_display_idx = the_info.get_humidity_display_idx(); humidity_info.humidity_percent = the_info.humidity_raw; humidity_info.left_dry_time = the_info.left_dray_time; humidity_info.current_temperature = the_info.current_temperature; @@ -1077,7 +1012,7 @@ void AMSControl::UpdateAms(const std::string &series_name, } /*update ams extruder*/ - if (m_extruder->updateNozzleNum(m_extder_data.total_extder_count, series_name)) + if (m_extruder->updateNozzleNum(m_total_ext_count, series_name)) { m_amswin->Layout(); } @@ -1087,12 +1022,12 @@ void AMSControl::AddAmsPreview(AMSinfo info, AMSModel type) { AMSPreview *ams_prv = nullptr; - if (info.nozzle_id == MAIN_NOZZLE_ID) + if (info.nozzle_id == MAIN_EXTRUDER_ID) { ams_prv = new AMSPreview(m_panel_prv_right, wxID_ANY, info, type); m_sizer_prv_right->Add(ams_prv, 0, wxALIGN_CENTER | wxLEFT, FromDIP(6)); } - else if (info.nozzle_id == DEPUTY_NOZZLE_ID) + else if (info.nozzle_id == DEPUTY_EXTRUDER_ID) { ams_prv = new AMSPreview(m_panel_prv_left, wxID_ANY, info, type); m_sizer_prv_left->Add(ams_prv, 0, wxALIGN_CENTER | wxLEFT, FromDIP(6)); @@ -1119,11 +1054,11 @@ void AMSControl::createAms(wxSimplebook* parent, int& idx, AMSinfo info, AMSPane AMSRoadShowMode AMSControl::findFirstMode(AMSPanelPos pos) { auto init_mode = AMSRoadShowMode::AMS_ROAD_MODE_NONE; std::string ams_id = ""; - if (pos == AMSPanelPos::LEFT_PANEL && m_item_ids[DEPUTY_NOZZLE_ID].size() > 0){ - ams_id = m_item_ids[DEPUTY_NOZZLE_ID][0]; + if (pos == AMSPanelPos::LEFT_PANEL && m_item_ids[DEPUTY_EXTRUDER_ID].size() > 0){ + ams_id = m_item_ids[DEPUTY_EXTRUDER_ID][0]; } - else if (pos == AMSPanelPos::RIGHT_PANEL && m_item_ids[MAIN_NOZZLE_ID].size() > 0){ - ams_id = m_item_ids[MAIN_NOZZLE_ID][0]; + else if (pos == AMSPanelPos::RIGHT_PANEL && m_item_ids[MAIN_EXTRUDER_ID].size() > 0){ + ams_id = m_item_ids[MAIN_EXTRUDER_ID][0]; } auto item = m_ams_item_list.find(ams_id); @@ -1182,7 +1117,7 @@ void AMSControl::createAmsPanel(wxSimplebook *parent, int &idx, std::vectorAdd(ams1, 0, wxLEFT, (book_panel->GetSize().x - ams1->GetSize().x) / 2); } else{ - auto ext_image = new AMSExtImage(book_panel, pos, &m_extder_data); + auto ext_image = new AMSExtImage(book_panel, pos, m_total_ext_count, false); book_sizer->Add(ams1, 0, wxLEFT, FromDIP(30)); book_sizer->Add(ext_image, 0, wxEXPAND | wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(30)); ext_image->setTotalExtNum(series_name, printer_type, total_ext_num); @@ -1209,15 +1144,15 @@ void AMSControl::createAmsPanel(wxSimplebook *parent, int &idx, std::vector 1){ - if (info.nozzle_id == MAIN_NOZZLE_ID){ + if (m_total_ext_count > 1){ + if (info.nozzle_id == MAIN_EXTRUDER_ID){ createAms(m_simplebook_ams_right, m_right_page_index, info, AMSPanelPos::RIGHT_PANEL); } - else if (info.nozzle_id == DEPUTY_NOZZLE_ID){ + else if (info.nozzle_id == DEPUTY_EXTRUDER_ID){ createAms(m_simplebook_ams_left, m_left_page_index, info, AMSPanelPos::LEFT_PANEL); } } - else if (m_extder_data.total_extder_count == 1){ + else if (m_total_ext_count == 1){ createAms(m_simplebook_ams_left, m_left_page_index, info, AMSPanelPos::LEFT_PANEL); } m_simplebook_ams_left->Layout(); @@ -1250,20 +1185,20 @@ void AMSControl::AddAms(std::vector single_info, const std::string &ser if (single_info.size() <= 0){ return; } - if (m_extder_data.total_extder_count == 2) { - if (single_info[0].nozzle_id == MAIN_NOZZLE_ID) { - createAmsPanel(m_simplebook_ams_right, m_right_page_index, single_info, series_name, printer_type, AMSPanelPos::RIGHT_PANEL, m_extder_data.total_extder_count); + if (m_total_ext_count == 2) { + if (single_info[0].nozzle_id == MAIN_EXTRUDER_ID) { + createAmsPanel(m_simplebook_ams_right, m_right_page_index, single_info, series_name, printer_type, AMSPanelPos::RIGHT_PANEL, m_total_ext_count); } - else if (single_info[0].nozzle_id == DEPUTY_NOZZLE_ID) { - createAmsPanel(m_simplebook_ams_left, m_left_page_index, single_info, series_name, printer_type, AMSPanelPos::LEFT_PANEL, m_extder_data.total_extder_count); + else if (single_info[0].nozzle_id == DEPUTY_EXTRUDER_ID) { + createAmsPanel(m_simplebook_ams_left, m_left_page_index, single_info, series_name, printer_type, AMSPanelPos::LEFT_PANEL, m_total_ext_count); } } - else if (m_extder_data.total_extder_count == 1) { + else if (m_total_ext_count == 1) { if (pos == AMSPanelPos::RIGHT_PANEL) { - createAmsPanel(m_simplebook_ams_right, m_right_page_index, single_info, series_name, printer_type, AMSPanelPos::RIGHT_PANEL, m_extder_data.total_extder_count); + createAmsPanel(m_simplebook_ams_right, m_right_page_index, single_info, series_name, printer_type, AMSPanelPos::RIGHT_PANEL, m_total_ext_count); } else { - createAmsPanel(m_simplebook_ams_left, m_left_page_index, single_info, series_name, printer_type, AMSPanelPos::LEFT_PANEL, m_extder_data.total_extder_count); + createAmsPanel(m_simplebook_ams_left, m_left_page_index, single_info, series_name, printer_type, AMSPanelPos::LEFT_PANEL, m_total_ext_count); } } @@ -1389,7 +1324,7 @@ void AMSControl::SwitchAms(std::string ams_id) for (auto ams_item : m_ams_item_list) { AmsItem* item = ams_item.second; if (item->get_ams_id() == ams_id) { - auto ids = item->get_panel_pos() == AMSPanelPos::LEFT_PANEL ? m_item_ids[DEPUTY_NOZZLE_ID] : m_item_ids[MAIN_NOZZLE_ID]; + auto ids = item->get_panel_pos() == AMSPanelPos::LEFT_PANEL ? m_item_ids[DEPUTY_EXTRUDER_ID] : m_item_ids[MAIN_EXTRUDER_ID]; auto pos = item->get_panel_pos(); for (auto id : ids) { if (id == item->get_ams_id()) { @@ -1397,16 +1332,16 @@ void AMSControl::SwitchAms(std::string ams_id) if (item->get_can_count() == GENERIC_AMS_SLOT_NUM) { if (item->get_ams_model() == AMSModel::AMS_LITE) { if (pos == AMSPanelPos::LEFT_PANEL) { - m_down_road->UpdateLeft(m_extder_data.total_extder_count, AMSRoadShowMode::AMS_ROAD_MODE_AMS_LITE); + m_down_road->UpdateLeft(m_total_ext_count, AMSRoadShowMode::AMS_ROAD_MODE_AMS_LITE); } else { - m_down_road->UpdateRight(m_extder_data.total_extder_count, AMSRoadShowMode::AMS_ROAD_MODE_AMS_LITE); + m_down_road->UpdateRight(m_total_ext_count, AMSRoadShowMode::AMS_ROAD_MODE_AMS_LITE); } } else { if (pos == AMSPanelPos::LEFT_PANEL) { - m_down_road->UpdateLeft(m_extder_data.total_extder_count, AMSRoadShowMode::AMS_ROAD_MODE_FOUR); + m_down_road->UpdateLeft(m_total_ext_count, AMSRoadShowMode::AMS_ROAD_MODE_FOUR); } else { - m_down_road->UpdateRight(m_extder_data.total_extder_count, AMSRoadShowMode::AMS_ROAD_MODE_FOUR); + m_down_road->UpdateRight(m_total_ext_count, AMSRoadShowMode::AMS_ROAD_MODE_FOUR); } } } @@ -1422,8 +1357,8 @@ void AMSControl::SwitchAms(std::string ams_id) break; } } - pos == AMSPanelPos::LEFT_PANEL ? m_down_road->UpdateLeft(m_extder_data.total_extder_count, mode) - : m_down_road->UpdateRight(m_extder_data.total_extder_count, mode); + pos == AMSPanelPos::LEFT_PANEL ? m_down_road->UpdateLeft(m_total_ext_count, mode) + : m_down_road->UpdateRight(m_total_ext_count, mode); if (pos == AMSPanelPos::LEFT_PANEL) { m_down_road->UpdatePassRoad(AMSPanelPos::LEFT_PANEL, -1, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); } else { @@ -1708,12 +1643,12 @@ void AMSControl::on_ams_setting_click(wxMouseEvent &event) } void AMSControl::parse_object(MachineObject* obj) { - if (!obj || obj->amsList.size() == 0) + if (!obj || obj->GetFilaSystem()->GetAmsList().size() == 0) { return; } m_ams_info.clear(); - for (auto ams : obj->amsList) + for (auto ams : obj->GetFilaSystem()->GetAmsList()) { AMSinfo info; info.parse_ams_info(obj, ams.second); diff --git a/src/slic3r/GUI/Widgets/AMSControl.hpp b/src/slic3r/GUI/Widgets/AMSControl.hpp index 891018f..8116514 100644 --- a/src/slic3r/GUI/Widgets/AMSControl.hpp +++ b/src/slic3r/GUI/Widgets/AMSControl.hpp @@ -14,6 +14,7 @@ #include #include +#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h" namespace Slic3r { namespace GUI { @@ -43,11 +44,11 @@ protected: std::map m_ams_item_list; std::map m_ext_image_list; - ExtderData m_extder_data; std::string m_dev_id; std::vector> m_item_ids{ {}, {} }; std::vector> pair_id; + int m_total_ext_count = 1; AMSextruder *m_extruder{nullptr}; AMSRoadDownPart* m_down_road{ nullptr }; @@ -158,7 +159,7 @@ public: const std::string &printer_type, std::vector ams_info, std::vector ext_info, - ExtderData data, + DevExtderSystem data, std::string dev_id, bool is_reset = true, bool test = false); diff --git a/src/slic3r/GUI/Widgets/AMSItem.cpp b/src/slic3r/GUI/Widgets/AMSItem.cpp index 41243c1..434f779 100644 --- a/src/slic3r/GUI/Widgets/AMSItem.cpp +++ b/src/slic3r/GUI/Widgets/AMSItem.cpp @@ -7,6 +7,10 @@ #include "slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h" +#include "slic3r/GUI/DeviceCore/DevFilaSystem.h" +#include "slic3r/GUI/DeviceCore/DevConfig.h" +#include "slic3r/GUI/DeviceCore/DevManager.h" + #include #include @@ -42,30 +46,30 @@ namespace Slic3r { namespace GUI { //#define AMS_SINGLE_CAN_SIZE wxSize(FromDIP(78), 144) #define AMS_CANS_WINDOW_SIZE wxSize(FromDIP(264), FromDIP(174)) #define AMS_SINGLE_CAN_SIZE wxSize(FromDIP(78), FromDIP(174)) -bool AMSinfo::parse_ams_info(MachineObject *obj, Ams *ams, bool remain_flag, bool humidity_flag) +bool AMSinfo::parse_ams_info(MachineObject *obj, DevAms *ams, bool remain_flag, bool humidity_flag) { if (!ams) return false; - this->ams_id = ams->id; + this->ams_id = ams->GetAmsId(); - if (ams->type == 1 || ams->type == 3 || ams->type == N3S_AMS){ - this->ams_humidity = ams->humidity; + if (ams->SupportHumidity()){ + this->ams_humidity = ams->GetHumidityLevel(); } else{ this->ams_humidity = -1; } - this->humidity_raw = ams->humidity_raw; - this->left_dray_time = ams->left_dry_time; - this->current_temperature = ams->current_temperature; - this->ams_type = AMSModel(ams->type); + this->humidity_raw = ams->GetHumidityPercent(); + this->left_dray_time = ams->GetLeftDryTime(); + this->current_temperature = ams->GetCurrentTemperature(); + this->ams_type = AMSModel(ams->GetAmsType()); - nozzle_id = ams->nozzle; + nozzle_id = ams->GetExtruderId(); cans.clear(); - for (int i = 0; i < ams->trayList.size(); i++) { - auto it = ams->trayList.find(std::to_string(i)); + for (int i = 0; i < ams->GetTrays().size(); i++) { + auto it = ams->GetTrays().find(std::to_string(i)); Caninfo info; // tray is exists - if (it != ams->trayList.end() && it->second->is_exists) { + if (it != ams->GetTrays().end() && it->second->is_exists) { if (it->second->is_tray_info_ready()) { info.can_id = it->second->id; info.ctype = it->second->ctype; @@ -73,23 +77,23 @@ bool AMSinfo::parse_ams_info(MachineObject *obj, Ams *ams, bool remain_flag, boo info.cali_idx = it->second->cali_idx; info.filament_id = it->second->setting_id; if (!it->second->color.empty()) { - info.material_colour = AmsTray::decode_color(it->second->color); + info.material_colour = DevAmsTray::decode_color(it->second->color); } else { // set to white by default info.material_colour = AMS_TRAY_DEFAULT_COL; } for (std::string cols:it->second->cols) { - info.material_cols.push_back(AmsTray::decode_color(cols)); + info.material_cols.push_back(DevAmsTray::decode_color(cols)); } - if (MachineObject::is_qdt_filament(it->second->tag_uid)) { + if (DevFilaSystem::IsQDT_Filament(it->second->tag_uid)) { info.material_state = AMSCanType::AMS_CAN_TYPE_BRAND; } else { info.material_state = AMSCanType::AMS_CAN_TYPE_THIRDBRAND; } - if (!MachineObject::is_qdt_filament(it->second->tag_uid) || !remain_flag) { + if (!DevFilaSystem::IsQDT_Filament(it->second->tag_uid) || !remain_flag) { info.material_remain = 100; } else { if(it->second->remain < 0 || it->second->remain > 100) { @@ -128,7 +132,7 @@ bool AMSinfo::parse_ams_info(MachineObject *obj, Ams *ams, bool remain_flag, boo return true; } -void AMSinfo::parse_ext_info(MachineObject* obj, AmsTray tray) { +void AMSinfo::parse_ext_info(MachineObject* obj, DevAmsTray tray) { this->ams_id = tray.id; this->ams_type = AMSModel::EXT_AMS; @@ -147,7 +151,7 @@ void AMSinfo::parse_ext_info(MachineObject* obj, AmsTray tray) { info.cali_idx = tray.cali_idx; info.filament_id = tray.setting_id; if (!tray.color.empty()) { - info.material_colour = AmsTray::decode_color(tray.color); + info.material_colour = DevAmsTray::decode_color(tray.color); } else { // set to white by default @@ -155,7 +159,7 @@ void AMSinfo::parse_ext_info(MachineObject* obj, AmsTray tray) { } for (std::string cols : tray.cols) { - info.material_cols.push_back(AmsTray::decode_color(cols)); + info.material_cols.push_back(DevAmsTray::decode_color(cols)); } info.material_remain = 100; } @@ -193,6 +197,43 @@ Caninfo AMSinfo::get_caninfo(const std::string& can_id, bool& found) const return Caninfo(); }; +int AMSinfo::get_humidity_display_idx() const +{ + if (ams_type == AMSModel::GENERIC_AMS) + { + if (ams_humidity > 0 && ams_humidity < 6) + { + return ams_humidity; + } + } + else if (ams_type == AMSModel::N3F_AMS || ams_type == AMSModel::N3S_AMS) + { + if (humidity_raw < 20) + { + return 5; + } + else if (humidity_raw < 40) + { + return 4; + } + else if (humidity_raw < 60) + { + return 3; + } + else if (humidity_raw < 80) + { + return 2; + } + else + { + return 1; + } + } + + assert(false && "Invalid AMS type for humidity display"); + return 1; +} + /************************************************* Description:AMSExtText **************************************************/ @@ -575,9 +616,9 @@ AMSextruderImage::~AMSextruderImage() {} Description:AMSExtImage upon ext lib **************************************************/ -AMSExtImage::AMSExtImage(wxWindow* parent, AMSPanelPos ext_pos, ExtderData *data, wxWindowID id, const wxPoint& pos) +AMSExtImage::AMSExtImage(wxWindow* parent, AMSPanelPos ext_pos, int total_ext_num, bool over_ext, wxWindowID id, const wxPoint& pos) { - if (data == nullptr) + if (over_ext) { wxWindow::Create(parent, id, pos); SetMinSize(AMS_HUMIDITY_SIZE); @@ -591,9 +632,9 @@ AMSExtImage::AMSExtImage(wxWindow* parent, AMSPanelPos ext_pos, ExtderData *data SetMaxSize(wxSize(FromDIP(98), FromDIP(99))); m_show_ext = true; - total_ext_num = data->total_extder_count; } + m_ext_num = total_ext_num; m_ext_pos = ext_pos; SetBackgroundColour(StateColor::darkModeColorFor(AMS_CONTROL_DEF_LIB_BK_COLOUR)); @@ -606,7 +647,7 @@ const wxBitmap &AMSExtImage::get_bmp(const std::string &printer_type, bool is_am { int pos_id = 0; if (pos == AMSPanelPos::LEFT_PANEL) { pos_id = 1;} - const std::string &image_name = DeviceManager::get_printer_ext_img(printer_type, pos_id); + const std::string &image_name = DevPrinterConfigUtil::get_printer_ext_img(printer_type, pos_id); if (image_name.empty()) { return wxNullBitmap; } int image_size = is_ams_ext ? 25 : 98; @@ -639,9 +680,9 @@ void AMSExtImage::setShowAmsExt(bool show) void AMSExtImage::setTotalExtNum(const std::string &series_name, const std::string &printer_type, int num) { - if ((total_ext_num != num) || (m_series_name != series_name) || (m_printer_type_name != printer_type)) + if ((m_ext_num != num) || (m_series_name != series_name) || (m_printer_type_name != printer_type)) { - total_ext_num = num; + m_ext_num = num; m_series_name = series_name; m_printer_type_name = printer_type; Refresh(); @@ -701,7 +742,7 @@ void AMSExtImage::doRender(wxDC& dc) } -//Ams Extruder +//DevAms Extruder AMSextruder::AMSextruder(wxWindow *parent, wxWindowID id, int nozzle_num, const wxPoint &pos, const wxSize &size) { create(parent, id, pos, size, nozzle_num); @@ -743,13 +784,13 @@ void AMSextruder::OnAmsLoading(bool load, int nozzle_id, wxColour col /*= AMS_CO if (load) m_current_colur_deputy = col; } else if (m_nozzle_num > 1){ - if (nozzle_id == MAIN_NOZZLE_ID) { + if (nozzle_id == MAIN_EXTRUDER_ID) { m_right_extruder->OnAmsLoading(load, col); if (m_current_colur != col){ if (load) m_current_colur = col; } } - else if(nozzle_id == DEPUTY_NOZZLE_ID) { + else if(nozzle_id == DEPUTY_EXTRUDER_ID) { m_left_extruder->OnAmsLoading(load, col); if (m_current_colur_deputy != col) { if (load) m_current_colur_deputy = col; @@ -1054,7 +1095,7 @@ void AMSLib::render_generic_text(wxDC &dc) show_k_value = false; } else if (m_info.cali_idx == -1 || (m_obj && (CalibUtils::get_selected_calib_idx(m_obj->pa_calib_tab, m_info.cali_idx) == -1))) { - if (m_obj && m_obj->is_support_auto_flow_calibration) + if (m_obj && m_obj->GetConfig()->SupportCalibrationPA_FlowAuto()) show_k_value = false; else get_default_k_n_value(m_info.filament_id, m_info.k, m_info.n); @@ -1885,7 +1926,7 @@ void AMSRoad::doRender(wxDC &dc) dc.DrawRoundedRectangle(size.x * 0.37 / 2, size.y * 0.6 - size.y / 6, size.x * 0.63, size.y / 3, m_radius); } - if (m_canindex == 3) { + if (m_canindex == 3) /*To check, tao.wang*/{ if (m_amsinfo.ams_humidity >= 1 && m_amsinfo.ams_humidity <= 5) {m_show_humidity = true;} else {m_show_humidity = false;} @@ -2224,19 +2265,19 @@ void AMSRoadDownPart::SetPassRoadColour(bool left, wxColour col) { if (left) { - if (m_road_color[DEPUTY_NOZZLE_ID] == col) + if (m_road_color[DEPUTY_EXTRUDER_ID] == col) { return; } - m_road_color[DEPUTY_NOZZLE_ID] = col; + m_road_color[DEPUTY_EXTRUDER_ID] = col; } else { - if (m_road_color[MAIN_NOZZLE_ID] == col) + if (m_road_color[MAIN_EXTRUDER_ID] == col) { return; } - m_road_color[MAIN_NOZZLE_ID] = col; + m_road_color[MAIN_EXTRUDER_ID] = col; } Refresh(); @@ -2795,8 +2836,8 @@ AMSHumidity::AMSHumidity(wxWindow* parent, wxWindowID id, AMSinfo info, const wx { create(parent, id, pos, wxDefaultSize); - for (int i = 1; i <= 5; i++) { ams_humidity_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_light", 16));} - for (int i = 1; i <= 5; i++) { ams_humidity_dark_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_dark", 16));} + for (int i = 1; i <= 5; i++) { ams_humidity_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_light", 20));} + for (int i = 1; i <= 5; i++) { ams_humidity_dark_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_dark", 20));} for (int i = 1; i <= 5; i++) { ams_humidity_no_num_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_no_num_light", 16)); } for (int i = 1; i <= 5; i++) { ams_humidity_no_num_dark_imgs.push_back(ScalableBitmap(this, "hum_level" + std::to_string(i) + "_no_num_dark", 16)); } @@ -2807,11 +2848,9 @@ AMSHumidity::AMSHumidity(wxWindow* parent, wxWindowID id, AMSinfo info, const wx //wxWindow::SetBackgroundColour(AMS_CONTROL_DEF_HUMIDITY_BK_COLOUR); Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) { - if (m_show_humidity) { - if (m_amsinfo.ams_type == AMSModel::GENERIC_AMS) { - return;/*STUDIO-12083*/ - } + int humidity_display_idx = m_amsinfo.get_humidity_display_idx(); + if (1 <= humidity_display_idx && humidity_display_idx <= 5) { auto mouse_pos = ClientToScreen(e.GetPosition()); auto rect = ClientToScreen(wxPoint(0, 0)); @@ -2821,7 +2860,8 @@ AMSHumidity::AMSHumidity(wxWindow* parent, wxWindowID id, AMSinfo info, const wx uiAmsHumidityInfo *info = new uiAmsHumidityInfo; info->ams_id = m_amsinfo.ams_id; - info->humidity_level = m_amsinfo.ams_humidity; + info->ams_type = m_amsinfo.ams_type; + info->humidity_display_idx = m_amsinfo.get_humidity_display_idx(); info->humidity_percent = m_amsinfo.humidity_raw; info->left_dry_time = m_amsinfo.left_dray_time; info->current_temperature = m_amsinfo.current_temperature; @@ -2853,10 +2893,10 @@ void AMSHumidity::Update(AMSinfo amsinfo) void AMSHumidity::update_size() { wxSize size; - if (m_amsinfo.humidity_raw != -1) { - size = AMS_HUMIDITY_SIZE; - } else { + if (m_amsinfo.ams_type == AMSModel::GENERIC_AMS) { size = AMS_HUMIDITY_NO_PERCENT_SIZE; + } else { + size = AMS_HUMIDITY_SIZE; } if (!m_amsinfo.support_drying()) { size.x -= AMS_HUMIDITY_DRY_WIDTH; } @@ -2900,25 +2940,37 @@ void AMSHumidity::doRender(wxDC& dc) dc.SetPen(wxPen(*wxTRANSPARENT_PEN)); dc.SetBrush(wxBrush(StateColor::darkModeColorFor(AMS_CONTROL_DEF_BLOCK_BK_COLOUR))); + // left mode - if (m_amsinfo.ams_humidity >= 1 && m_amsinfo.ams_humidity <= 5) { m_show_humidity = true; } - else { m_show_humidity = false; } - - if (m_show_humidity) { + int humidity_display_idx = m_amsinfo.get_humidity_display_idx(); + if (1 <= humidity_display_idx && humidity_display_idx <= 5) { //background dc.SetPen(wxPen(*wxTRANSPARENT_PEN)); dc.SetBrush(wxBrush(StateColor::darkModeColorFor(AMS_CONTROL_DEF_BLOCK_BK_COLOUR))); dc.DrawRoundedRectangle(0, 0, (size.x), (size.y), (size.y / 2)); wxPoint pot; - if (m_amsinfo.humidity_raw != -1) /*image with no number + percentage*/ + if (m_amsinfo.ams_type == AMSModel::GENERIC_AMS) /*image with stage*/ + { + ScalableBitmap hum_img; + if (!wxGetApp().dark_mode()) { + hum_img = ams_humidity_imgs[humidity_display_idx - 1]; + } else { + hum_img = ams_humidity_dark_imgs[humidity_display_idx - 1]; + } + + pot = wxPoint((size.x - hum_img.GetBmpWidth()) / 2, ((size.y - hum_img.GetBmpSize().y) / 2)); + dc.DrawBitmap(hum_img.bmp(), pot); + pot.x = pot.x + hum_img.GetBmpSize().x; + } + else if (m_amsinfo.humidity_raw != -1) /*image with no number + percentage*/ { // hum image ScalableBitmap hum_img; if (!wxGetApp().dark_mode()) { - hum_img = ams_humidity_no_num_imgs[m_amsinfo.ams_humidity - 1]; + hum_img = ams_humidity_no_num_imgs[humidity_display_idx - 1]; } else { - hum_img = ams_humidity_no_num_dark_imgs[m_amsinfo.ams_humidity - 1]; + hum_img = ams_humidity_no_num_dark_imgs[humidity_display_idx - 1]; } pot = wxPoint(FromDIP(5), ((size.y - hum_img.GetBmpSize().y) / 2)); @@ -2946,20 +2998,6 @@ void AMSHumidity::doRender(wxDC& dc) pot.x += tsize2.x; } - else /*image with number*/ - { - // hum image - ScalableBitmap hum_img; - if (!wxGetApp().dark_mode()) { - hum_img = ams_humidity_imgs[m_amsinfo.ams_humidity - 1]; - } else { - hum_img = ams_humidity_dark_imgs[m_amsinfo.ams_humidity - 1]; - } - - pot = wxPoint(FromDIP(5), ((size.y - hum_img.GetBmpSize().y) / 2)); - dc.DrawBitmap(hum_img.bmp(), pot); - pot.x = pot.x + hum_img.GetBmpSize().x; - } if (m_amsinfo.support_drying()) { @@ -3061,7 +3099,7 @@ void AmsItem::create(wxWindow *parent) } else{ if (m_ams_model == EXT_AMS){ - m_ext_image = new AMSExtImage(this, m_panel_pos); + m_ext_image = new AMSExtImage(this, m_panel_pos, 1, true); sizer_item->Add(m_ext_image, 0, wxALIGN_CENTER, 0); } } diff --git a/src/slic3r/GUI/Widgets/AMSItem.hpp b/src/slic3r/GUI/Widgets/AMSItem.hpp index 4f1c637..da2d817 100644 --- a/src/slic3r/GUI/Widgets/AMSItem.hpp +++ b/src/slic3r/GUI/Widgets/AMSItem.hpp @@ -257,11 +257,14 @@ public: return true; }; - bool parse_ams_info(MachineObject* obj, Ams *ams, bool remain_flag = false, bool humidity_flag = false); - void parse_ext_info(MachineObject* obj, AmsTray tray); + bool parse_ams_info(MachineObject* obj, DevAms *ams, bool remain_flag = false, bool humidity_flag = false); + void parse_ext_info(MachineObject* obj, DevAmsTray tray); bool support_drying() const { return (ams_type == AMSModel::N3S_AMS) || (ams_type == AMSModel::N3F_AMS); }; + bool support_humidity() const { return 1 <= get_humidity_display_idx() && get_humidity_display_idx() <= 5; } Caninfo get_caninfo(const std::string& can_id, bool& found) const; + + int get_humidity_display_idx() const; }; /************************************************* @@ -376,12 +379,12 @@ private: bool m_show_ext = false; AMSPanelPos m_ext_pos; - int total_ext_num = 1; + int m_ext_num = 1; ScalableBitmap m_ext_image; public: - AMSExtImage(wxWindow *parent, AMSPanelPos ext_pos = AMSPanelPos::RIGHT_PANEL, ExtderData *data = nullptr, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition); + AMSExtImage(wxWindow *parent, AMSPanelPos ext_pos, int total_ext_num, bool over_ext, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition); ~AMSExtImage(); void msw_rescale(); @@ -737,9 +740,6 @@ public: ScalableBitmap ams_sun_img; ScalableBitmap ams_drying_img; - - int m_humidity = { 0 }; - bool m_show_humidity = { false }; bool m_vams_loading{ false }; AMSModel m_ams_model; diff --git a/src/slic3r/GUI/Widgets/DropDown.cpp b/src/slic3r/GUI/Widgets/DropDown.cpp index b3d662c..d14dde1 100644 --- a/src/slic3r/GUI/Widgets/DropDown.cpp +++ b/src/slic3r/GUI/Widgets/DropDown.cpp @@ -191,6 +191,8 @@ void DropDown::paintNow() static wxSize GetBmpSize(wxBitmap & bmp) { + if (!bmp.IsOk()) + return wxSize(0, 0); #ifdef __APPLE__ return bmp.GetScaledSize(); #else diff --git a/src/slic3r/GUI/Widgets/FanControl.cpp b/src/slic3r/GUI/Widgets/FanControl.cpp index d51c97e..17935d9 100644 --- a/src/slic3r/GUI/Widgets/FanControl.cpp +++ b/src/slic3r/GUI/Widgets/FanControl.cpp @@ -357,7 +357,7 @@ FanControlNew::FanControlNew(wxWindow *parent, const AirDuctData &fan_data, int m_static_name = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END | wxALIGN_CENTER_HORIZONTAL); m_static_name->SetBackgroundColour(wxColour(248, 248, 248)); - m_static_name->SetFont(Label::Head_18); + m_static_name->SetFont(Label::Head_16); m_static_name->SetMinSize(wxSize(FromDIP(100), -1)); m_static_name->SetMaxSize(wxSize(FromDIP(100), -1)); @@ -458,9 +458,9 @@ void FanControlNew::command_control_fan() if (m_obj) { if (!m_obj->is_enable_np){ int speed = floor(m_current_speed * float(25.5)); - m_obj->command_control_fan(m_part_id, speed); + m_obj->GetFan()->command_control_fan(m_part_id, speed); } else { - m_obj->command_control_fan_new(m_part_id, m_current_speed * 10, nullptr); + m_obj->GetFan()->command_control_fan_new(m_part_id, m_current_speed * 10); } post_event(); } @@ -692,8 +692,6 @@ void FanControlPopupNew::CreateDuct() for (const auto& part : m_data.parts) { auto part_id = part.id; - auto part_func = part.func; - auto part_name = fan_func_name[AIR_FUN(part_id)]; auto part_state = part.state; auto it = m_fan_control_list.find(part_id); @@ -708,9 +706,9 @@ void FanControlPopupNew::CreateDuct() { if (m_obj) { - int cooling_fan_speed = round(m_obj->cooling_fan_speed / float(25.5)); - int big_fan1_speed = round(m_obj->big_fan1_speed / float(25.5)); - int big_fan2_speed = round(m_obj->big_fan2_speed / float(25.5)); + int cooling_fan_speed = round(m_obj->GetFan()->GetCoolingFanSpeed() / float(25.5)); + int big_fan1_speed = round(m_obj->GetFan()->GetBigFan1Speed() / float(25.5)); + int big_fan2_speed = round(m_obj->GetFan()->GetBigFan2Speed() / float(25.5)); update_fan_data(AIR_FUN::FAN_COOLING_0_AIRDOOR, cooling_fan_speed); update_fan_data(AIR_FUN::FAN_REMOTE_COOLING_0_IDX, big_fan1_speed); update_fan_data(AIR_FUN::FAN_CHAMBER_0_IDX, big_fan2_speed); @@ -731,7 +729,7 @@ void FanControlPopupNew::UpdateParts() for (const auto& part : m_data.parts) { auto part_id = part.id; - auto part_name = fan_func_name[AIR_FUN(part_id)]; + auto part_name = get_fan_func_name(m_data.curren_mode, m_data.m_sub_mode, AIR_FUN(part_id)); auto fan_control = m_fan_control_list[part_id]; if (!fan_control) @@ -774,7 +772,7 @@ void FanControlPopupNew::UpdatePartSubMode() if (msg_wingow.ShowModal() != wxID_OK) { return; } } - int submode = m_cooling_filter_switch_panel->IsSwitchOn() ? 0 : 1; + int submode = m_cooling_filter_switch_panel->IsSwitchOn() ? 1 : 0; command_control_air_duct(m_data.curren_mode, submode); }); @@ -808,12 +806,12 @@ void FanControlPopupNew::update_fan_data(MachineObject *obj) return; } - if (!obj->m_air_duct_data.modes.empty()) { - update_fan_data(obj->m_air_duct_data); + if (!obj->GetFan()->GetAirDuctData().modes.empty()) { + update_fan_data(obj->GetFan()->GetAirDuctData()); } else { - int cooling_fan_speed = round(obj->cooling_fan_speed / float(25.5)); - int big_fan1_speed = round(obj->big_fan1_speed / float(25.5)); - int big_fan2_speed = round(obj->big_fan2_speed / float(25.5)); + int cooling_fan_speed = round(obj->GetFan()->GetCoolingFanSpeed() / float(25.5)); + int big_fan1_speed = round(obj->GetFan()->GetBigFan1Speed() / float(25.5)); + int big_fan2_speed = round(obj->GetFan()->GetBigFan2Speed() / float(25.5)); update_fan_data(AIR_FUN::FAN_COOLING_0_AIRDOOR, cooling_fan_speed); update_fan_data(AIR_FUN::FAN_REMOTE_COOLING_0_IDX, big_fan1_speed); update_fan_data(AIR_FUN::FAN_CHAMBER_0_IDX, big_fan2_speed); @@ -827,8 +825,6 @@ void FanControlPopupNew::update_fan_data(const AirDuctData &data) m_data = data; for (const auto& part : m_data.parts) { auto part_id = part.id; - auto part_func = part.func; - auto part_name = fan_func_name[AIR_FUN(part_id)]; auto part_state = part.state; auto it = m_fan_control_list.find(part_id); @@ -845,8 +841,6 @@ void FanControlPopupNew::update_fan_data(AIR_FUN id, int speed) { for (auto& part : m_data.parts) { auto part_id = part.id; - auto part_func = part.func; - auto part_name = fan_func_name[AIR_FUN(part_id)]; if (id == part_id) { part.state = speed; @@ -910,7 +904,7 @@ void FanControlPopupNew::command_control_air_duct(int mode_id, int submode) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", control air duct, id = " << mode_id; if (m_obj) { - m_obj->command_control_air_duct(mode_id, submode, [](const json& reply) {}); + m_obj->GetFan()->command_control_air_duct(mode_id, submode, [](const json& reply) {}); m_air_duct_time_out = time_out; m_data.curren_mode = mode_id; @@ -979,14 +973,6 @@ void FanControlPopupNew::init_names(MachineObject* obj) { radio_btn_name[AIR_DUCT::AIR_DUCT_FULL_COOLING] = _L("Full Cooling"); radio_btn_name[AIR_DUCT::AIR_DUCT_INIT] = L("Init"); - fan_func_name[AIR_FUN::FAN_HEAT_BREAK_0_IDX] = _L("Hotend"); - fan_func_name[AIR_FUN::FAN_COOLING_0_AIRDOOR] = _L("Parts"); - fan_func_name[AIR_FUN::FAN_REMOTE_COOLING_0_IDX] = _L("Aux"); - fan_func_name[AIR_FUN::FAN_CHAMBER_0_IDX] = _L("Exhaust"); - fan_func_name[AIR_FUN::FAN_HEAT_BREAK_1_IDX] = _L("Nozzle1"); - fan_func_name[AIR_FUN::FAN_MC_BOARD_0_IDX] = _L("MC Board"); - fan_func_name[AIR_FUN::FAN_INNNER_LOOP_FAN_0_IDX] = _L("Heat"); - air_door_func_name[AIR_DOOR::AIR_DOOR_FUNC_CHAMBER] = _L("Chamber"); air_door_func_name[AIR_DOOR::AIR_DOOR_FUNC_INNERLOOP] = _L("Innerloop"); air_door_func_name[AIR_DOOR::AIR_DOOR_FUNC_TOP] = L("Top");/*UNUSED*/ @@ -1002,20 +988,41 @@ void FanControlPopupNew::init_names(MachineObject* obj) { // special texts if (obj) { - const std::string& special_cooling_text = DeviceManager::get_fan_text(obj->printer_type, "special_cooling_text"); + const std::string& special_cooling_text = DevPrinterConfigUtil::get_fan_text(obj->printer_type, "special_cooling_text"); if (!special_cooling_text.empty()) { L("Cooling mode is suitable for printing PLA/PETG/TPU materials."); //some potential text, add i18n flags label_text[AIR_DUCT::AIR_DUCT_COOLING_FILT] = special_cooling_text; } - - const std::string& special_func_aux_text = DeviceManager::get_fan_text(obj->printer_type, "special_func_aux_text"); - if (!special_func_aux_text.empty()) { - L_CONTEXT("Right", "air_duct"); - fan_func_name[AIR_FUN::FAN_REMOTE_COOLING_0_IDX] = _CTX(special_func_aux_text, "air_duct"); - } } } +wxString FanControlPopupNew::get_fan_func_name(int mode, int submode, AIR_FUN func) const +{ + if (m_obj) + { + const std::string& func_text = DevPrinterConfigUtil::get_fan_text(m_obj->printer_type, mode, (int)func, submode); + if (!func_text.empty()) + { + L_CONTEXT("Right(Aux)", "air_duct"); + L_CONTEXT("Right(Filter)", "air_duct"); + return _CTX(func_text, "air_duct"); + } + } + + static std::map s_fan_func_name + { + { AIR_FUN::FAN_HEAT_BREAK_0_IDX, _L("Hotend") }, + { AIR_FUN::FAN_COOLING_0_AIRDOOR, _L("Parts") }, + { AIR_FUN::FAN_REMOTE_COOLING_0_IDX, _L("Aux") }, + { AIR_FUN::FAN_CHAMBER_0_IDX, _L("Exhaust") }, + { AIR_FUN::FAN_HEAT_BREAK_1_IDX, _L("Nozzle1") }, + { AIR_FUN::FAN_MC_BOARD_0_IDX, _L("MC Board") }, + { AIR_FUN::FAN_INNNER_LOOP_FAN_0_IDX, _L("Heat") }, + }; + + auto iter = s_fan_func_name.find(func); + return (iter != s_fan_func_name.end()) ? iter->second : wxString::Format(_L("Fan")); +} wxDEFINE_EVENT(EVT_FANCTRL_SWITCH, wxCommandEvent); FanControlNewSwitchPanel::FanControlNewSwitchPanel(wxWindow* parent, const wxString& title, const wxString& tips, bool on) diff --git a/src/slic3r/GUI/Widgets/FanControl.hpp b/src/slic3r/GUI/Widgets/FanControl.hpp index b757cad..fc29d22 100644 --- a/src/slic3r/GUI/Widgets/FanControl.hpp +++ b/src/slic3r/GUI/Widgets/FanControl.hpp @@ -13,7 +13,7 @@ #include #include #include - +#include "../DeviceCore/DevFan.h" namespace Slic3r { namespace GUI { @@ -237,12 +237,12 @@ private: int m_fan_set_time_out{ 0 }; std::map radio_btn_name; - std::map fan_func_name; std::map air_door_func_name; std::map label_text; private: void init_names(MachineObject* obj); + wxString get_fan_func_name(int mode, int submode, AIR_FUN func) const; void CreateDuct(); diff --git a/src/slic3r/GUI/Widgets/LinkLabel.cpp b/src/slic3r/GUI/Widgets/LinkLabel.cpp new file mode 100644 index 0000000..b83b0a8 --- /dev/null +++ b/src/slic3r/GUI/Widgets/LinkLabel.cpp @@ -0,0 +1,53 @@ +#include +#include "LinkLabel.hpp" + +LinkLabel::LinkLabel(wxWindow *parent, wxString const &text, std::string url, long style, wxSize size) + : wxWindow(parent, wxID_ANY, wxDefaultPosition, size, style) +{ + m_url = wxString(url); + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + m_txt = new Label(this, text); + m_underline = new wxPanel(this); + + Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); }); + m_txt->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); }); + m_underline->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_ARROW); }); + + Bind(wxEVT_LEFT_DOWN, &LinkLabel::link, this); + m_txt->Bind(wxEVT_LEFT_DOWN, &LinkLabel::link, this); + m_underline->Bind(wxEVT_LEFT_DOWN, &LinkLabel::link, this); + + m_underline->SetMinSize(wxSize(-1, FromDIP(1))); + m_underline->SetMaxSize(wxSize(-1, FromDIP(1))); + + SeLinkLabelBColour(*wxWHITE); + + sizer->Add(m_txt, 0, wxEXPAND, 0); + sizer->Add(m_underline, 0, wxEXPAND, 0); + SetSizer(sizer); + Layout(); + Fit(); +} + + +void LinkLabel::link(wxMouseEvent &evt) +{ + if (!m_url.IsEmpty()) { + wxLaunchDefaultBrowser(m_url); + } +} + +bool LinkLabel::SeLinkLabelFColour(const wxColour &colour) +{ + SetForegroundColour(colour); + m_txt->SetForegroundColour(colour); + m_underline->SetBackgroundColour(colour); + return true; +} + +bool LinkLabel::SeLinkLabelBColour(const wxColour &colour) +{ + SetBackgroundColour(colour); + m_txt->SetBackgroundColour(colour); + return true; +} diff --git a/src/slic3r/GUI/Widgets/LinkLabel.hpp b/src/slic3r/GUI/Widgets/LinkLabel.hpp new file mode 100644 index 0000000..8392d1b --- /dev/null +++ b/src/slic3r/GUI/Widgets/LinkLabel.hpp @@ -0,0 +1,24 @@ +#ifndef slic3r_GUI_LinkLabel_hpp_ +#define slic3r_GUI_LinkLabel_hpp_ + +#include +#include "Label.hpp" + +class LinkLabel : public wxWindow +{ +private: + wxString m_url; + Label * m_txt{nullptr}; + wxPanel* m_underline{nullptr}; + +public: + LinkLabel(wxWindow *parent, wxString const &text, std::string url, long style = 0, wxSize size = wxDefaultSize); + ~LinkLabel(){}; + + void link(wxMouseEvent &evt); + Label *getLabel(){return m_txt;}; + bool SeLinkLabelFColour(const wxColour &colour); + bool SeLinkLabelBColour(const wxColour &colour); +}; + +#endif // !slic3r_GUI_LinkLabel_hpp_ diff --git a/src/slic3r/GUI/Widgets/SideTools.cpp b/src/slic3r/GUI/Widgets/SideTools.cpp index 83d069e..072eb13 100644 --- a/src/slic3r/GUI/Widgets/SideTools.cpp +++ b/src/slic3r/GUI/Widgets/SideTools.cpp @@ -335,7 +335,7 @@ SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* sizer_extra_info = new wxBoxSizer(wxHORIZONTAL); - m_link_network_state = new wxHyperlinkCtrl(m_side_error_panel, wxID_ANY,_L("Check the status of current system services"),"",wxDefaultPosition,wxDefaultSize,wxALIGN_CENTER_HORIZONTAL | wxST_ELLIPSIZE_END); + m_link_network_state = new wxHyperlinkCtrl(m_side_error_panel, wxID_ANY,_L("Check the status of current system services"),"",wxDefaultPosition,wxDefaultSize, wxHL_ALIGN_CENTRE |wxST_ELLIPSIZE_END); m_link_network_state->SetMinSize(wxSize(FromDIP(220), -1)); m_link_network_state->SetMaxSize(wxSize(FromDIP(220), -1)); m_link_network_state->SetFont(::Label::Body_12); @@ -466,7 +466,7 @@ void SideTools::update_status(MachineObject* obj) if (!obj) return; /* Update Device Info */ - m_side_tools->set_current_printer_name(obj->dev_name); + m_side_tools->set_current_printer_name(obj->get_dev_name()); // update wifi signal image int wifi_signal_val = 0; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index fd58e8b..925b6c0 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -4,7 +4,6 @@ #include #include - #include /* mac need the macro while including */ @@ -28,6 +27,7 @@ #include "Widgets/Label.hpp" #include "../Utils/WxFontUtils.hpp" #include "FilamentBitmapUtils.hpp" +#include "../Utils/ColorSpaceConvert.hpp" #ifndef __linux__ // msw_menuitem_bitmaps is used for MSW and OSX static std::map msw_menuitem_bitmaps; @@ -652,14 +652,38 @@ std::vector> read_color_pack(std::vector c wxColourData show_sys_picker_dialog(wxWindow *parent, const wxColourData &clr_data) { - wxColourData data; + wxColourData data = clr_data; data.SetChooseFull(true); - data.SetColour(clr_data.GetColour()); + + // Load custom colors from config (support both "r,g,b,a" and "#RRGGBB" formats) + std::vector colors = Slic3r::GUI::wxGetApp().app_config->get_custom_color_from_config(); + for (int i = 0; i < (int)colors.size(); i++) { + wxColour c; + if (colors[i].find(',') != std::string::npos) + c = string_to_wxColor(colors[i]); + else + c = wxColour(colors[i]); + if (c.IsOk()) + data.SetCustomColour(i, c); + } + wxColourDialog dialog(parent, &data); dialog.SetTitle(_L("Please choose the filament colour")); + if (dialog.ShowModal() == wxID_OK) { data = dialog.GetColourData(); + + // Save custom colors to config (use RGBA string format for consistency) + std::vector colors; + colors.resize(CUSTOM_COLOR_COUNT); + for (int i = 0; i < CUSTOM_COLOR_COUNT; i++) { + wxColour custom_clr = data.GetCustomColour(i); + if (custom_clr.IsOk()) + colors[i] = color_to_string(custom_clr); + } + Slic3r::GUI::wxGetApp().app_config->save_custom_color_to_config(colors); } + return data; } @@ -752,15 +776,19 @@ wxBitmap *get_extruder_color_icon(std::string color, std::string label, int icon // there is no neede to scale created solid bitmap wxColor clr(color); bitmap = bmp_cache.insert(bitmap_key, wxBitmap(icon_width, icon_height)); -#ifndef __WXMSW__ - wxMemoryDC dc; -#else +#ifdef __WXOSX__ + bitmap->UseAlpha(); + wxMemoryDC dc(*bitmap); +#elif defined(__WXMSW__) wxClientDC cdc((wxWindow *) Slic3r::GUI::wxGetApp().mainframe); wxMemoryDC dc(&cdc); + dc.SelectObject(*bitmap); +#else + wxMemoryDC dc; + dc.SelectObject(*bitmap); #endif dc.SetFont(::Label::Body_12); Slic3r::GUI::WxFontUtils::get_suitable_font_size(icon_height - 2, dc); - dc.SelectObject(*bitmap); if (clr.Alpha() == 0) { int size = icon_height * 2; static wxBitmap transparent = *Slic3r::GUI::BitmapCache().load_svg("transparent", size, size); @@ -1105,6 +1133,8 @@ wxSize ScalableBitmap::GetBmpSize(const wxBitmap &bmp) int ScalableBitmap::GetBmpWidth() const { + if (!m_bmp.IsOk()) + return 0; #ifdef __APPLE__ return m_bmp.GetScaledWidth(); #else @@ -1114,6 +1144,8 @@ int ScalableBitmap::GetBmpWidth() const int ScalableBitmap::GetBmpHeight() const { + if (!m_bmp.IsOk()) + return 0; #ifdef __APPLE__ return m_bmp.GetScaledHeight(); #else diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index 0a1a589..a42ecfd 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -9,13 +9,21 @@ #include "libslic3r/Model.hpp" #include "../GUI/MsgDialog.hpp" #include "QDTUtil.hpp" +#include "libslic3r/FlushVolCalc.hpp" +#include "../GUI/DeviceCore/DevConfig.h" +#include "../GUI/DeviceCore/DevExtruderSystem.h" +#include "../GUI/DeviceCore/DevManager.h" +#include "../GUI/DeviceCore/DevStorage.h" +#include "libslic3r/FlushVolCalc.hpp" +#include "QDTUtil.hpp" +#include "../GUI/Plater.hpp" namespace Slic3r { namespace GUI { -const float MIN_PA_K_VALUE = 0.0; -const float MAX_PA_K_VALUE = 2.0; -static const float MIN_PA_K_VALUE_STEP = 0.001; +const double MIN_PA_K_VALUE = 0.0; +const double MAX_PA_K_VALUE = 2.0; +static const double MIN_PA_K_VALUE_STEP = 0.001; std::shared_ptr CalibUtils::print_job; wxString wxstr_temp_dir = fs::path(fs::temp_directory_path() / "calib").wstring(); @@ -76,6 +84,16 @@ wxString get_nozzle_volume_type_name(NozzleVolumeType type) return wxString(); } +static int get_physical_extruder_idx(std::vector physical_extruder_maps, int extruder_id) +{ + for (size_t index = 0; index < physical_extruder_maps.size(); ++index) { + if (physical_extruder_maps[index] == extruder_id) { + return index; + } + } + return extruder_id; +} + bool is_pa_params_valid(const Calib_Params ¶ms) { if (params.start < MIN_PA_K_VALUE || params.end > MAX_PA_K_VALUE || params.step < MIN_PA_K_VALUE_STEP || params.end < params.start + params.step) { @@ -113,6 +131,8 @@ std::string get_calib_mode_name(CalibMode cali_mode, int stage) switch(cali_mode) { case CalibMode::Calib_PA_Line: return "pa_line_calib_mode"; + case CalibMode::Calib_Auto_PA_Line: + return "auto_pa_line_calib_mode"; case CalibMode::Calib_PA_Pattern: return "pa_pattern_calib_mode"; case CalibMode::Calib_Flow_Rate: @@ -168,9 +188,9 @@ static bool is_same_nozzle_diameters(const DynamicPrintConfig &full_config, cons for (size_t idx = 0; idx < opt_nozzle_diameters->size(); ++idx) config_nozzle_diameters[idx] = opt_nozzle_diameters->values[idx]; - std::vector machine_nozzle_diameters(obj->m_extder_data.extders.size()); - for (size_t idx = 0; idx < obj->m_extder_data.extders.size(); ++idx) - machine_nozzle_diameters[idx] = obj->m_extder_data.extders[idx].current_nozzle_diameter; + std::vector machine_nozzle_diameters(obj->GetExtderSystem()->GetTotalExtderCount()); + for (size_t idx = 0; idx < obj->GetExtderSystem()->GetTotalExtderCount(); ++idx) + machine_nozzle_diameters[idx] = obj->GetExtderSystem()->GetNozzleDiameter(idx); if (config_nozzle_diameters.size() != machine_nozzle_diameters.size()) { wxString nozzle_in_preset = wxString::Format(_L("nozzle size in preset: %d"), config_nozzle_diameters.size()); @@ -200,7 +220,7 @@ static bool is_same_nozzle_type(const DynamicPrintConfig &full_config, const Mac if (obj == nullptr) return true; - NozzleType nozzle_type = obj->m_extder_data.extders[0].current_nozzle_type; + NozzleType nozzle_type = obj->GetExtderSystem()->GetNozzleType(0); int printer_nozzle_hrc = Print::get_hrc_by_nozzle_type(nozzle_type); if (full_config.has("required_nozzle_HRC")) { @@ -208,7 +228,7 @@ static bool is_same_nozzle_type(const DynamicPrintConfig &full_config, const Mac if (abs(filament_nozzle_hrc) > abs(printer_nozzle_hrc)) { BOOST_LOG_TRIVIAL(info) << "filaments hardness mismatch: printer_nozzle_hrc = " << printer_nozzle_hrc << ", filament_nozzle_hrc = " << filament_nozzle_hrc; std::string filament_type = full_config.opt_string("filament_type", 0); - error_msg = wxString::Format(_L("Printing %1s material with %2s nozzle may cause nozzle damage."), filament_type, to_wstring_name(NozzleTypeEumnToStr[obj->m_extder_data.extders[0].current_nozzle_type])); + error_msg = wxString::Format(_L("Printing %1s material with %2s nozzle may cause nozzle damage."), filament_type, to_wstring_name(NozzleTypeEumnToStr[obj->GetExtderSystem()->GetNozzleType(0)])); error_msg += "\n"; MessageDialog msg_dlg(nullptr, error_msg, wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL); @@ -244,7 +264,7 @@ static bool check_nozzle_diameter_and_type(const DynamicPrintConfig &full_config return false; // P1P/S - if (obj->m_extder_data.extders[0].current_nozzle_type == NozzleType::ntUndefine) + if (obj->GetExtderSystem()->GetNozzleType(0) == NozzleType::ntUndefine) return true; // if (!is_same_nozzle_diameters(full_config, obj, error_msg)) @@ -272,6 +292,7 @@ static void init_multi_extruder_params_for_cali(DynamicPrintConfig& config, cons for (size_t index = 0; index < extruder_count; ++index) { if (physical_extruder_maps[index] == extruder_id) { + nozzle_volume_types[index] = (int) calib_info.nozzle_volume_type; extruder_id = index + 1; } } @@ -300,6 +321,10 @@ CalibMode CalibUtils::get_calib_mode_by_name(const std::string name, int& cali_s cali_stage = 1; return CalibMode::Calib_PA_Line; } + else if (name == "auto_pa_line_calib_mode") { + cali_stage = 2; + return CalibMode::Calib_PA_Line; + } else if (name == "flow_rate_coarse_calib_mode") { cali_stage = 1; return CalibMode::Calib_Flow_Rate; @@ -722,6 +747,7 @@ bool CalibUtils::calib_flowrate(int pass, const CalibInfo &calib_info, wxString full_config.apply(printer_config); full_config.set_key_value("filament_ids", new ConfigOptionStrings({calib_info.filament_prest->filament_id})); + full_config.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); init_multi_extruder_params_for_cali(full_config, calib_info); @@ -805,6 +831,215 @@ void CalibUtils::calib_pa_pattern(const CalibInfo &calib_info, Model& model) model.calib_pa_pattern = std::make_unique(pa_pattern); } +void CalibUtils::set_for_auto_pa_model_and_config(const std::vector &calib_infos, DynamicPrintConfig &full_config, Model &model) +{ + DynamicPrintConfig print_config = calib_infos[0].print_prest->config; + + float nozzle_diameter = full_config.option("nozzle_diameter")->get_at(0); + int extruder_count = full_config.option("nozzle_diameter")->values.size(); + + for (const auto opt : SuggestedConfigCalibPAPattern().float_pairs) { print_config.set_key_value(opt.first, new ConfigOptionFloat(opt.second)); } + for (const auto opt : SuggestedConfigCalibPAPattern().floats_pairs) { print_config.set_key_value(opt.first, new ConfigOptionFloatsNullable(opt.second)); } + + std::vector sorted_calib_infos = calib_infos; + std::sort(sorted_calib_infos.begin(), sorted_calib_infos.end(), [](const CalibInfo &left_item, const CalibInfo &right_item) { + return left_item.index < right_item.index; + }); + + for (const CalibInfo &calib_info : calib_infos) { + int index = get_index_for_extruder_parameter(print_config, "outer_wall_speed", calib_info.extruder_id, calib_info.extruder_type, calib_info.nozzle_volume_type); + float wall_speed = CalibPressureAdvance::find_optimal_PA_speed(full_config, print_config.get_abs_value("line_width"), print_config.get_abs_value("layer_height"), + calib_info.extruder_id, 0); + + ConfigOptionFloatsNullable *wall_speed_speed_opt = print_config.option("outer_wall_speed"); + std::vector new_speeds = wall_speed_speed_opt->values; + new_speeds[index] = wall_speed; + ModelObject* object = model.objects[calib_info.index]; + object->config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable(new_speeds)); + } + + for (const auto opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) { + print_config.set_key_value(opt.first, new ConfigOptionFloat(nozzle_diameter * opt.second / 100)); + } + + for (const auto opt : SuggestedConfigCalibPAPattern().int_pairs) { print_config.set_key_value(opt.first, new ConfigOptionInt(opt.second)); } + + print_config.set_key_value(SuggestedConfigCalibPAPattern().brim_pair.first, new ConfigOptionEnum(SuggestedConfigCalibPAPattern().brim_pair.second)); + + auto* _wall_generator = print_config.option>("wall_generator"); + _wall_generator->value = PerimeterGeneratorType::Arachne; + + print_config.option("enable_prime_tower")->value = false; + + auto get_new_filament_id = [&sorted_calib_infos](int index) -> int { + for (size_t i = 0; i < sorted_calib_infos.size(); ++i) { + if (index == sorted_calib_infos[i].index) { + return (int) (i + 1); // 1 base filament_id + } + } + return 0; + }; + + // set printable and reset filament_id + for (size_t i = 0; i < model.objects.size(); ++i) { + auto iter = std::find_if(calib_infos.begin(), calib_infos.end(), [i](const CalibInfo &item) { return item.index == i; }); + + if (iter == calib_infos.end()) { + model.objects[i]->printable = false; + } else { + ModelObject *object = model.objects[i]; + object->config.set_key_value("extruder", new ConfigOptionInt(get_new_filament_id(iter->index))); + for (auto *volume : object->volumes) { + if (volume->config.has("extruder")) volume->config.erase("extruder"); + } + } + } + + // DynamicPrintConfig full_config; + full_config.apply(print_config); + full_config.option>("filament_map_mode", true)->value = FilamentMapMode::fmmManual; + + // nozzle volume type + std::vector& nozzle_volume_types = full_config.option("nozzle_volume_type", true)->values; + nozzle_volume_types.resize(extruder_count, NozzleVolumeType::nvtStandard); + auto nozzle_flush_dataset = full_config.option("nozzle_flush_dataset", true)->values; + nozzle_flush_dataset.resize(extruder_count, 0); + + int filament_nums = calib_infos.size(); + std::vector physical_extruder_maps = dynamic_cast(full_config.option("physical_extruder_map", true))->values; + for (size_t filament_index = 0; filament_index < calib_infos.size(); ++filament_index) { + CalibInfo calib_info = calib_infos[filament_index]; + int extruder_id = calib_info.extruder_id; + for (size_t index = 0; index < extruder_count; ++index) { + if (physical_extruder_maps[index] == extruder_id) { + extruder_id = index; + } + } + nozzle_volume_types[extruder_id] = (int)calib_info.nozzle_volume_type; + } + + // filament map transform to 1 base + std::vector &filament_maps = full_config.option("filament_map", true)->values; + std::transform(filament_maps.begin(), filament_maps.end(), filament_maps.begin(), [](int value) { return value + 1; }); + + std::vector &filament_colors = full_config.option("filament_colour")->values; + filament_colors.resize(sorted_calib_infos.size(), "#000000"); + for (size_t i = 0; i < sorted_calib_infos.size(); ++i) { + filament_colors[i] = sorted_calib_infos[i].filament_color; + } + + // Add flush volume matrix + std::vector flush_matrix_vec; + for (int e_idx = 0; e_idx < extruder_count; ++e_idx) { + const std::vector &min_flush_volumes = get_min_flush_volumes(full_config, e_idx); + for (size_t from_idx = 0; from_idx < filament_nums; ++from_idx) { + for (size_t to_idx = 0; to_idx < filament_nums; ++to_idx) { + if (from_idx == to_idx) { + flush_matrix_vec.emplace_back(0); + } + else { + Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], Slic3r::g_max_flush_volume, nozzle_flush_dataset[e_idx]); + wxColour from = wxColour(filament_colors[from_idx]); + wxColour to = wxColour(filament_colors[to_idx]); + int volume = calculator.calc_flush_vol(from.Alpha(), from.Red(), from.Green(), from.Blue(), to.Alpha(), to.Red(), to.Green(), to.Blue()); + flush_matrix_vec.emplace_back(double(volume)); + } + } + } + + } + std::vector &config_matrix = full_config.option("flush_volumes_matrix")->values; + set_flush_volumes_matrix(config_matrix, flush_matrix_vec, -1, extruder_count); +} + +bool CalibUtils::calib_generic_auto_pa_cali(const std::vector &calib_infos, wxString &error_message) +{ + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { + error_message = _L("Need select printer"); + return false; + } + + MachineObject *obj_ = dev->get_selected_machine(); + if (obj_ == nullptr) { + error_message = _L("Need select printer"); + return false; + } + + if (!check_printable_status_before_cali(obj_, calib_infos, error_message)) + return false; + + const Calib_Params ¶ms = calib_infos[0].params; + if (params.mode != CalibMode::Calib_Auto_PA_Line) + return false; + + Model model; + std::string input_file; + if (obj_->is_multi_extruders()) + input_file = Slic3r::resources_dir() + "/calib/pressure_advance/auto_pa_line_dual.3mf"; + else + input_file = Slic3r::resources_dir() + "/calib/pressure_advance/auto_pa_line_single.3mf"; + + read_model_from_file(input_file, model); + + DynamicPrintConfig print_config = calib_infos[0].print_prest->config; + DynamicPrintConfig filament_config = calib_infos[0].filament_prest->config; + DynamicPrintConfig printer_config = calib_infos[0].printer_prest->config; + + Preset printer_preset = *calib_infos[0].printer_prest; + Preset print_preset = *calib_infos[0].print_prest; + std::vector filament_presets; + std::vector filament_map; + filament_map.resize(calib_infos.size()); + std::vector physical_extruder_maps = dynamic_cast(printer_config.option("physical_extruder_map", true))->values; + for (size_t i = 0; i < calib_infos.size(); ++i) { + CalibInfo calib_info = calib_infos[i]; + calib_info.filament_prest->config.set_key_value("curr_bed_type", new ConfigOptionEnum(calib_info.bed_type)); + filament_presets.emplace_back(*calib_info.filament_prest); + for (size_t index = 0; index < physical_extruder_maps.size(); ++index) { + if (physical_extruder_maps[index] == calib_info.extruder_id) { + filament_map[i] = index; + } + } + } + + PresetBundle *preset_bundle = wxGetApp().preset_bundle; + DynamicPrintConfig full_config = PresetBundle::construct_full_config(printer_preset, print_preset, preset_bundle->project_config, filament_presets, false, filament_map); + + set_for_auto_pa_model_and_config(calib_infos, full_config, model); + if (!process_and_store_3mf(&model, full_config, params, error_message)) + return false; + + try { + json js; + if (params.mode == CalibMode::Calib_PA_Line) + js["cali_type"] = "cali_pa_line"; + else if (params.mode == CalibMode::Calib_PA_Pattern) + js["cali_type"] = "cali_pa_pattern"; + else if (params.mode == CalibMode::Calib_Auto_PA_Line) + js["cali_type"] = "cali_auto_pa_line"; + + const ConfigOptionFloatsNullable *nozzle_diameter_config = printer_config.option("nozzle_diameter"); + assert(nozzle_diameter_config->values.size() > 0); + float nozzle_diameter = nozzle_diameter_config->values[0]; + + js["nozzle_diameter"] = nozzle_diameter; + std::string filament_ids; + for (const auto calib_info : calib_infos) { + filament_ids += calib_info.filament_prest->filament_id; + filament_ids += " "; + } + js["filament_id"] = filament_ids; + js["printer_type"] = obj_->printer_type; + NetworkAgent *agent = GUI::wxGetApp().getAgent(); + if (agent) + agent->track_event("cali", js.dump()); + } catch (...) {} + + send_to_print(calib_infos, error_message); + return true; +} + bool CalibUtils::calib_generic_PA(const CalibInfo &calib_info, wxString &error_message) { DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); @@ -850,6 +1085,9 @@ bool CalibUtils::calib_generic_PA(const CalibInfo &calib_info, wxString &error_m full_config.apply(filament_config); full_config.apply(printer_config); + full_config.set_key_value("filament_ids", new ConfigOptionStrings({calib_info.filament_prest->filament_id})); + full_config.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); + init_multi_extruder_params_for_cali(full_config, calib_info); if (!process_and_store_3mf(&model, full_config, params, error_message)) @@ -1184,40 +1422,37 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co return false; } - float cali_diameter = cali_infos.calib_datas[0].nozzle_diameter; - int extruder_id = cali_infos.calib_datas[0].extruder_id; for (const auto& cali_info : cali_infos.calib_datas) { if (cali_infos.cali_mode == CalibMode::Calib_PA_Line && !is_support_auto_pa_cali(cali_info.filament_id)) { error_message = _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration."); return false; } - - if (!is_approx(cali_diameter, cali_info.nozzle_diameter)) { - error_message = _L("Automatic calibration only supports cases where the left and right nozzle diameters are identical."); - return false; - } } - if (extruder_id >= obj->m_extder_data.extders.size()) { - error_message = _L("The number of printer extruders and the printer selected for calibration does not match."); - return false; - } - - float diameter = obj->m_extder_data.extders[extruder_id].current_nozzle_diameter; bool is_multi_extruder = obj->is_multi_extruders(); std::vector nozzle_volume_types; if (is_multi_extruder) { - for (const Extder& extruder : obj->m_extder_data.extders) { - nozzle_volume_types.emplace_back(extruder.current_nozzle_flow_type); + for (const DevExtder& extruder : obj->GetExtderSystem()->GetExtruders()) { + nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType()); } } + Preset *printer_preset = get_printer_preset(obj); + for (const auto &cali_info : cali_infos.calib_datas) { wxString name = _L("left"); if (cali_info.extruder_id == 0) { name = _L("right"); } + float cali_diameter = cali_info.nozzle_diameter; + int extruder_id = cali_info.extruder_id; + if (extruder_id >= obj->GetExtderSystem()->GetTotalExtderSize()) { + error_message = _L("The number of printer extruders and the printer selected for calibration does not match."); + return false; + } + + float diameter = obj->GetExtderSystem()->GetNozzleDiameter(extruder_id); if (!is_approx(cali_info.nozzle_diameter, diameter)) { if (is_multi_extruder) error_message = wxString::Format(_L("The currently selected nozzle diameter of %s extruder does not match the actual nozzle diameter.\n" @@ -1245,6 +1480,74 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co return true; } +bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, const std::vector &cali_infos, wxString &error_message) +{ + if (!obj) { + error_message = _L("Need select printer"); + return false; + } + + if (cali_infos.empty()) + return true; + + float cali_diameter = cali_infos[0].nozzle_diameter; + int extruder_id = cali_infos[0].extruder_id; + for (const auto &cali_info : cali_infos) { + if (cali_infos[0].params.mode == CalibMode::Calib_Auto_PA_Line && !is_support_auto_pa_cali(cali_info.filament_prest->filament_id)) { + error_message = _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration."); + return false; + } + + if (!is_approx(cali_diameter, cali_info.nozzle_diameter)) { + error_message = _L("Automatic calibration only supports cases where the left and right nozzle diameters are identical."); + return false; + } + } + + if (extruder_id >= obj->GetExtderSystem()->GetExtruders().size()) { + error_message = _L("The number of printer extruders and the printer selected for calibration does not match."); + return false; + } + + float diameter = obj->GetExtderSystem()->GetNozzleDiameter(extruder_id); + bool is_multi_extruder = obj->is_multi_extruders(); + std::vector nozzle_volume_types; + if (is_multi_extruder) { + for (auto &extruder : obj->GetExtderSystem()->GetExtruders()) { nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType()); } + } + + for (const auto &cali_info : cali_infos) { + wxString name = _L("left"); + if (cali_info.extruder_id == 0) { name = _L("right"); } + + if (!is_approx(cali_info.nozzle_diameter, diameter)) { + if (is_multi_extruder) + error_message = wxString::Format(_L("The currently selected nozzle diameter of %s extruder does not match the actual nozzle diameter.\n" + "Please click the Sync button above and restart the calibration."), + name); + else + error_message = _L("The nozzle diameter does not match the actual printer nozzle diameter.\n" + "Please click the Sync button above and restart the calibration."); + return false; + } + + if (is_multi_extruder) { + if (nozzle_volume_types[cali_info.extruder_id] == NozzleFlowType::NONE_FLOWTYPE) { + error_message = wxString::Format(_L("Printer %s nozzle information has not been set. Please configure it before proceeding with the calibration."), name); + return false; + } + + if (NozzleVolumeType(nozzle_volume_types[cali_info.extruder_id] - 1) != cali_info.nozzle_volume_type) { + error_message = wxString::Format(_L("The currently selected nozzle type of %s extruder does not match the actual printer nozzle type.\n" + "Please click the Sync button above and restart the calibration."), + name); + return false; + } + } + } + return true; +} + bool CalibUtils::check_printable_status_before_cali(const MachineObject* obj, const CalibInfo& cali_info, wxString& error_message) { if (!obj) { @@ -1255,12 +1558,12 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject* obj, co const ConfigOptionFloatsNullable *nozzle_diameter_config = cali_info.printer_prest->config.option("nozzle_diameter"); float nozzle_diameter = nozzle_diameter_config->values[0]; - float diameter = obj->m_extder_data.extders[cali_info.extruder_id].current_nozzle_diameter; + float diameter = obj->GetExtderSystem()->GetNozzleDiameter(cali_info.extruder_id); bool is_multi_extruder = obj->is_multi_extruders(); std::vector nozzle_volume_types; if (is_multi_extruder) { - for (const Extder& extruder : obj->m_extder_data.extders) { - nozzle_volume_types.emplace_back(extruder.current_nozzle_flow_type); + for (const DevExtder& extruder : obj->GetExtderSystem()->GetExtruders()) { + nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType()); } } @@ -1348,7 +1651,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f BuildVolume build_volume(bedfs, print_height, extruder_areas, extruder_heights); unsigned int count = model->update_print_volume_state(build_volume); - if (count == 0) { + if (count == 0 && params.mode != CalibMode::Calib_Auto_PA_Line) { error_message = _L("Unable to calibrate: maybe because the set calibration value range is too large, or the step is too small"); return false; } @@ -1511,19 +1814,19 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess return; } - else if (!obj_->is_support_print_without_sd && (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD)) { + else if (!obj_->GetConfig()->SupportPrintWithoutSD() && (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD)) { error_message = _L("Storage needs to be inserted before printing."); return; } if (obj_->is_lan_mode_printer()) { - if (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { error_message = _L("Storage needs to be inserted before printing via LAN."); return; } } print_job = std::make_shared(std::move(process_bar), wxGetApp().plater(), dev_id); - print_job->m_dev_ip = obj_->dev_ip; + print_job->m_dev_ip = obj_->get_dev_ip(); print_job->m_ftp_folder = obj_->get_ftp_folder(); print_job->m_access_code = obj_->get_access_code(); @@ -1556,9 +1859,9 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess print_job->plate_data = plate_data; print_job->m_print_type = "from_normal"; - print_job->task_ams_mapping = select_ams; + print_job->task_ams_mapping = "[" + select_ams + "]"; print_job->task_ams_mapping_info = ""; - print_job->task_use_ams = select_ams == "[254]" ? false : true; + print_job->task_use_ams = !devPrinterUtil::IsVirtualSlot(select_ams); std::string new_ams_mapping = "[{\"ams_id\":" + std::to_string(calib_info.ams_id) + ", \"slot_id\":" + std::to_string(calib_info.slot_id) + "}]"; print_job->task_ams_mapping2 = new_ams_mapping; @@ -1567,8 +1870,8 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess print_job->m_project_name = get_calib_mode_name(cali_mode, flow_ratio_mode); print_job->set_calibration_task(true); - print_job->has_sdcard = obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL; - print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, false, 0, 0, 0); + print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL; + print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, false, 0, 0, 0, 0); print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name); { // after send: record the print job @@ -1581,6 +1884,123 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess print_job->start(); } +void CalibUtils::send_to_print(const std::vector &calib_infos, wxString &error_message, int flow_ratio_mode) +{ + std::string dev_id = calib_infos[0].dev_id; + std::shared_ptr process_bar = calib_infos[0].process_bar; + BedType bed_type = calib_infos[0].bed_type; + + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { + error_message = _L("Need select printer"); + return; + } + + MachineObject *obj_ = dev->get_selected_machine(); + if (obj_ == nullptr) { + error_message = _L("Need select printer"); + return; + } + + if (obj_->is_in_upgrading()) { + error_message = _L("Cannot send the print job when the printer is updating firmware"); + return; + } else if (obj_->is_system_printing()) { + error_message = _L("The printer is executing instructions. Please restart printing after it ends"); + return; + } else if (obj_->is_in_printing()) { + error_message = _L("The printer is busy on other print job"); + return; + } + + else if (!obj_->GetConfig()->SupportPrintWithoutSD() && (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD)) { + error_message = _L("Storage needs to be inserted before printing."); + return; + } + if (obj_->is_lan_mode_printer()) { + if (obj_->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) { + error_message = _L("Storage needs to be inserted before printing via LAN."); + return; + } + } + + print_job = std::make_shared(std::move(process_bar), wxGetApp().plater(), dev_id); + print_job->m_dev_ip = obj_->get_dev_ip(); + print_job->m_ftp_folder = obj_->get_ftp_folder(); + print_job->m_access_code = obj_->get_access_code(); + +#if !QDT_RELEASE_TO_PUBLIC + print_job->m_local_use_ssl_for_ftp = wxGetApp().app_config->get("enable_ssl_for_ftp") == "true" ? true : false; + print_job->m_local_use_ssl_for_mqtt = wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false; +#else + print_job->m_local_use_ssl_for_ftp = obj_->local_use_ssl_for_ftp; + print_job->m_local_use_ssl_for_mqtt = obj_->local_use_ssl_for_mqtt; +#endif + + print_job->connection_type = obj_->connection_type(); + print_job->cloud_print_only = obj_->is_support_cloud_print_only; + + PrintPrepareData job_data; + job_data.is_from_plater = false; + job_data.plate_idx = 0; + job_data._3mf_config_path = config_3mf_path; + job_data._3mf_path = path; + job_data._temp_path = temp_dir; + + PlateListData plate_data; + plate_data.is_valid = true; + plate_data.plate_count = 1; + plate_data.cur_plate_index = 0; + plate_data.bed_type = bed_type; + + print_job->job_data = job_data; + print_job->plate_data = plate_data; + print_job->m_print_type = "from_normal"; + + // set AMS mapping + std::string select_ams = "["; + std::string new_select_ams = "["; + for (size_t i = 0; i < calib_infos.size(); ++i) { + select_ams += calib_infos[i].select_ams; + new_select_ams += "{\"ams_id\":" + std::to_string(calib_infos[i].ams_id) + ", \"slot_id\":" + std::to_string(calib_infos[i].slot_id) + "}"; + if (i != calib_infos.size() - 1) { + select_ams += ","; + new_select_ams += ","; + } + } + select_ams += "]"; + new_select_ams += "]"; + print_job->task_ams_mapping = select_ams; + print_job->task_ams_mapping_info = ""; + print_job->task_ams_mapping2 = new_select_ams; + + print_job->task_use_ams = false; + for (const CalibInfo& calib_info : calib_infos) { + if (calib_info.select_ams != VIRTUAL_AMS_MAIN_ID_STR && calib_info.select_ams != VIRTUAL_AMS_DEPUTY_ID_STR) { + print_job->task_use_ams = true; + break; + } + } + + CalibMode cali_mode = calib_infos[0].params.mode; + print_job->m_project_name = get_calib_mode_name(cali_mode, flow_ratio_mode); + print_job->set_calibration_task(true); + + print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL; + print_job->set_print_config(MachineBedTypeString[bed_type], true, true, false, false, true, false, 0, 1, 0, 0); + print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name); + + { // after send: record the print job + json j; + j["print"]["ams_mapping"] = print_job->task_ams_mapping; + j["print"]["ams_mapping_2"] = print_job->task_ams_mapping2; + j["print"]["project_name"] = print_job->m_project_name; + j["print"]["is_cali_task"] = print_job->m_is_calibration_task; + BOOST_LOG_TRIVIAL(info) << "send_cali_job - after send: " << j.dump(); + } + + print_job->start(); +} } } diff --git a/src/slic3r/Utils/CalibUtils.hpp b/src/slic3r/Utils/CalibUtils.hpp index 367dedf..34c7aed 100644 --- a/src/slic3r/Utils/CalibUtils.hpp +++ b/src/slic3r/Utils/CalibUtils.hpp @@ -9,15 +9,17 @@ class ProgressIndicator; class Preset; namespace GUI { -extern const float MIN_PA_K_VALUE; -extern const float MAX_PA_K_VALUE; +extern const double MIN_PA_K_VALUE; +extern const double MAX_PA_K_VALUE; class CalibInfo { public: + int index = -1; int extruder_id = 0; int ams_id = 0; int slot_id = 0; + float nozzle_diameter; ExtruderType extruder_type{ExtruderType::etDirectDrive}; NozzleVolumeType nozzle_volume_type; Calib_Params params; @@ -25,6 +27,7 @@ public: Preset* filament_prest; Preset* print_prest; BedType bed_type; + std::string filament_color; std::string dev_id; std::string select_ams; std::shared_ptr process_bar; @@ -60,6 +63,9 @@ public: static void calib_pa_pattern(const CalibInfo &calib_info, Model &model); + static void set_for_auto_pa_model_and_config(const std::vector &calib_info, DynamicPrintConfig &full_config, Model &model); + + static bool calib_generic_auto_pa_cali(const std::vector &calib_info, wxString & error_message); static bool calib_generic_PA(const CalibInfo &calib_info, wxString &error_message); static void calib_temptue(const CalibInfo &calib_info, wxString &error_message); static void calib_max_vol_speed(const CalibInfo &calib_info, wxString &error_message); @@ -78,10 +84,12 @@ public: static bool check_printable_status_before_cali(const MachineObject *obj, const X1CCalibInfos &cali_infos, wxString &error_message); static bool check_printable_status_before_cali(const MachineObject *obj, const CalibInfo &cali_info, wxString &error_message); + static bool check_printable_status_before_cali(const MachineObject *obj, const std::vector &cali_infos, wxString &error_message); private: static bool process_and_store_3mf(Model* model, const DynamicPrintConfig& full_config, const Calib_Params& params, wxString& error_message); static void send_to_print(const CalibInfo &calib_info, wxString& error_message, int flow_ratio_mode = 0); // 0: none 1: coarse 2: fine + static void send_to_print(const std::vector &calib_infos, wxString &error_message, int flow_ratio_mode = 0); // 0: none 1: coarse 2: fine }; extern void get_tray_ams_and_slot_id(MachineObject* obj, int in_tray_id, int &ams_id, int &slot_id, int &tray_id); diff --git a/src/slic3r/Utils/HelioDragon.cpp b/src/slic3r/Utils/HelioDragon.cpp new file mode 100644 index 0000000..57bdb9a --- /dev/null +++ b/src/slic3r/Utils/HelioDragon.cpp @@ -0,0 +1,821 @@ +#include "HelioDragon.hpp" + +#include +#include +#include +#include + +#include "PrintHost.hpp" +#include "libslic3r/PrintConfig.hpp" +#include "libslic3r/PrintBase.hpp" +#include "libslic3r/Print.hpp" +#include +#include "../GUI/PartPlate.hpp" +#include "../GUI/GUI_App.hpp" +#include "../GUI/Event.hpp" +#include "../GUI/Plater.hpp" +#include "../GUI/NotificationManager.hpp" +#include "wx/app.h" +#include "cstdio" + + +namespace Slic3r { + +std::vector HelioQuery::global_supported_printers; +std::vector HelioQuery::global_supported_materials; + +void HelioQuery::request_support_machine(const std::string helio_api_url, const std::string helio_api_key, int page) +{ + std::string query_body = R"( { + "query": "query GetPrinters($page: Int) { printers(page: $page, pageSize: 20) { pages pageInfo { hasNextPage } objects { ... on Printer { id name alternativeNames { qidistudio } } } } }", + "variables": {"page": %1%} + } )"; + + query_body = boost::str(boost::format(query_body) % page); + + std::string url_copy = helio_api_url; + std::string key_copy = helio_api_key; + int page_copy = page; + + auto http = Http::post(url_copy); + + http.header("Content-Type", "application/json").header("Authorization", "Bearer " + helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([url_copy, key_copy, page_copy](std::string body, unsigned status) { + BOOST_LOG_TRIVIAL(info) << "request_support_machine" << body; + try { + nlohmann::json parsed_obj = nlohmann::json::parse(body); + std::vector supported_printers; + if (parsed_obj.contains("data") && parsed_obj["data"].contains("printers")) { + auto materials = parsed_obj["data"]["printers"]; + if (materials.contains("objects") && materials["objects"].is_array()) { + for (const auto &pobj : materials["objects"]) { + HelioQuery::SupportedData sp; + if (pobj.contains("id") && !pobj["id"].is_null()) { sp.id = pobj["id"].get(); } + if (pobj.contains("name") && !pobj["id"].is_null()) { sp.name = pobj["name"].get(); } + + if (pobj.contains("alternativeNames") && pobj["alternativeNames"].is_object()) { + auto alternativeNames = pobj["alternativeNames"]; + + if (alternativeNames.contains("qidistudio") && !alternativeNames["qidistudio"].is_null()) { + sp.native_name = alternativeNames["qidistudio"].get(); + } + } + + supported_printers.push_back(sp); + } + } + + HelioQuery::global_supported_printers.insert(HelioQuery::global_supported_printers.end(), supported_printers.begin(), supported_printers.end()); + + if (materials.contains("pageInfo") && materials["pageInfo"].contains("hasNextPage") && materials["pageInfo"]["hasNextPage"].get()) { + HelioQuery::request_support_machine(url_copy, key_copy, page_copy + 1); + } + } + } catch (...) {} + }) + .on_error([](std::string body, std::string error, unsigned status) { + // BOOST_LOG_TRIVIAL(info) << (boost::format("error: %1%, message: %2%") % error % body).str() + }) + .perform(); +} + +void HelioQuery::request_support_material(const std::string helio_api_url, const std::string helio_api_key, int page) +{ + std::string query_body = R"( { + "query": "query GetMaterias($page: Int) { materials(page: $page, pageSize: 20) { pages pageInfo { hasNextPage } objects { ... on Material { id name alternativeNames { qidistudio } } } } }", + "variables": {"page": %1%} + } )"; + + query_body = boost::str(boost::format(query_body) % page); + + std::string url_copy = helio_api_url; + std::string key_copy = helio_api_key; + int page_copy = page; + + auto http = Http::post(url_copy); + + http.header("Content-Type", "application/json").header("Authorization", "Bearer " + helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([url_copy, key_copy, page_copy](std::string body, unsigned status) { + BOOST_LOG_TRIVIAL(info) << "request_support_material" << body; + try { + nlohmann::json parsed_obj = nlohmann::json::parse(body); + std::vector supported_materials; + + if (parsed_obj.contains("data") && parsed_obj["data"].contains("materials")) { + auto materials = parsed_obj["data"]["materials"]; + if (materials.contains("objects") && materials["objects"].is_array()) { + for (const auto &pobj : materials["objects"]) { + HelioQuery::SupportedData sp; + if (pobj.contains("id") && !pobj["id"].is_null()) { sp.id = pobj["id"].get(); } + if (pobj.contains("name") && !pobj["id"].is_null()) { sp.name = pobj["name"].get(); } + if (pobj.contains("alternativeNames") && pobj["alternativeNames"].is_object()) { + auto alternativeNames = pobj["alternativeNames"]; + + //qidi materials + if (alternativeNames.contains("qidistudio") && !alternativeNames["qidistudio"].is_null()) { + sp.native_name = alternativeNames["qidistudio"].get(); + } + //third party materials + else { + if (pobj.contains("name") && !pobj["id"].is_null()) { sp.native_name = pobj["name"].get(); } + } + } + supported_materials.push_back(sp); + } + } + + HelioQuery::global_supported_materials.insert(HelioQuery::global_supported_materials.end(), supported_materials.begin(), supported_materials.end()); + + if (materials.contains("pageInfo") && materials["pageInfo"].contains("hasNextPage") && materials["pageInfo"]["hasNextPage"].get()) { + HelioQuery::request_support_material(url_copy, key_copy, page_copy + 1); + } + } + } catch (...) {} + }) + .on_error([](std::string body, std::string error, unsigned status) { + // BOOST_LOG_TRIVIAL(info) << (boost::format("error: %1%, message: %2%") % error % body).str() + }) + .perform(); +} + +std::string HelioQuery::get_helio_api_url() +{ + std::string helio_api_url; + if (GUI::wxGetApp().app_config->get("region") == "China") { + helio_api_url = "https://api.helioam.cn/graphql"; + } else { + helio_api_url = "https://api.helioadditive.com/graphql"; + } + return helio_api_url; +} + +std::string HelioQuery::get_helio_pat() +{ + std::string helio_pat; + if (GUI::wxGetApp().app_config->get("region") == "China") { + helio_pat = GUI::wxGetApp().app_config->get("helio_pat_china"); + } else { + helio_pat = GUI::wxGetApp().app_config->get("helio_pat_other"); + } + return helio_pat; +} + +void HelioQuery::set_helio_pat(std::string pat) +{ + if (GUI::wxGetApp().app_config->get("region") == "China") { + GUI::wxGetApp().app_config->set("helio_pat_china", pat); + } else { + GUI::wxGetApp().app_config->set("helio_pat_other", pat); + } +} + +void HelioQuery::request_pat_token(std::function func) +{ + std::string url_copy = ""; + + if (GUI::wxGetApp().app_config->get("region") == "China") { + url_copy = "https://api.helioam.cn/rest/auth/anonymous_token/qidistudio"; + } + else { + url_copy = "https://api.helioadditive.com/rest/auth/anonymous_token/qidistudio"; + } + + auto http = Http::get(url_copy); + http.timeout_connect(20) + .timeout_max(100) + .on_complete([url_copy, func](std::string body, unsigned status) { + //success + if (status == 200) { + try { + nlohmann::json parsed_obj = nlohmann::json::parse(body); + if (parsed_obj.contains("pat") && parsed_obj["pat"].is_string()) { + func(parsed_obj["pat"].get()); + } + else { + func("error"); + } + + } + catch (...) {} + } + else if (status == 429) { + func("not_enough"); + } + }) + .on_error([func](std::string body, std::string error, unsigned status) { + if (status == 429) { + func("not_enough"); + } + else { + func("error"); + } + //BOOST_LOG_TRIVIAL(info) << (boost::format("request pat token error: %1%, message: %2%") % error % body).str()); + }) + .perform(); +} + + +HelioQuery::PresignedURLResult HelioQuery::create_presigned_url(const std::string helio_api_url, const std::string helio_api_key) +{ + HelioQuery::PresignedURLResult res; + std::string query_body = R"( { + "query": "query getPresignedUrl($fileName: String!) { getPresignedUrl(fileName: $fileName) { mimeType url key } }", + "variables": { + "fileName": "test.gcode" + } + } )"; + + auto http = Http::post(helio_api_url); + + http.header("Content-Type", "application/json").header("Authorization", helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([&res](std::string body, unsigned status) { + try{ + nlohmann::json parsed_obj = nlohmann::json::parse(body); + res.status = status; + if (parsed_obj.contains("error")) { + res.error = parsed_obj["error"]; + } + else { + res.key = parsed_obj["data"]["getPresignedUrl"]["key"]; + res.mimeType = parsed_obj["data"]["getPresignedUrl"]["mimeType"]; + res.url = parsed_obj["data"]["getPresignedUrl"]["url"]; + } + } + catch (...){} + }) + .on_error([&res](std::string body, std::string error, unsigned status) { + res.error = (boost::format("error: %1%, message: %2%") % error % body).str(); + res.status = status; + }) + .perform_sync(); + + return res; +}; + +HelioQuery::UploadFileResult HelioQuery::upload_file_to_presigned_url(const std::string file_path_string, const std::string upload_url) +{ + UploadFileResult res; + + Http http = Http::put(upload_url); + boost::filesystem::path file_path(file_path_string); + http.header("Content-Type", "application/octet-stream"); + + http.set_put_body(file_path) + .on_complete([&res](std::string body, unsigned status) { + if (status == 200) + res.success = true; + else + res.success = false; + }) + .on_error([&res](std::string body, std::string error, unsigned status) { + res.success = false; + res.error = (boost::format("status: %1%, error: %2%, %3%") % status % body % error).str(); + }) + .perform_sync(); + + return res; +} + +HelioQuery::CreateGCodeResult HelioQuery::create_gcode(const std::string key, + const std::string helio_api_url, + const std::string helio_api_key, + const std::string printer_id, + const std::string filament_id) +{ + HelioQuery::CreateGCodeResult res; + std::string query_body_template = R"( { + "query": "mutation CreateGcode($input: CreateGcodeInput!) { createGcode(input: $input) { errors gcode { id name sizeKb } } }", + "variables": { + "input": { + "name": "%1%", + "printerId": "%2%", + "materialId": "%3%", + "gcodeKey": "%4%", + "isSingleShell": true + } + } + } )"; + + std::vector key_split; + boost::split(key_split, key, boost::is_any_of("/")); + + std::string gcode_name = key_split.back(); + + std::string query_body = (boost::format(query_body_template) % gcode_name % printer_id % filament_id % key).str(); + + auto http = Http::post(helio_api_url); + + http.header("Content-Type", "application/json").header("Authorization", helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([&res](std::string body, unsigned status) { + + try{ + nlohmann::json parsed_obj = nlohmann::json::parse(body); + res.status = status; + if (parsed_obj.contains("errors")) { + res.error = parsed_obj["errors"].dump(); + res.success = false; + } + else { + + if (!parsed_obj["data"]["createGcode"]["gcode"].is_null()) { + res.success = true; + res.id = parsed_obj["data"]["createGcode"]["gcode"]["id"]; + res.name = parsed_obj["data"]["createGcode"]["gcode"]["name"]; + } + else { + res.success = false; + res.error = ""; + for (const auto& err : parsed_obj["data"]["createGcode"]["criticalErrors"]) { + std::string error_msg = err.get(); + res.error_flags.push_back(error_msg); + + res.error += " "; + res.error += error_msg; + } + + for (const auto& err : parsed_obj["data"]["createGcode"]["criticalErrors"]) { + std::string error_msg = err.get(); + res.error_flags.push_back(error_msg); + + res.error += " "; + res.error += error_msg; + } + } + + for (const auto& err : parsed_obj["data"]["createGcode"]["warnings"]) { + std::string error_msg = err.get(); + res.warning_flags.push_back(error_msg); + } + } + } + catch (...){} + }) + .on_error([&res](std::string body, std::string error, unsigned status) { + res.success = false; + res.error = error; + res.status = status; + }) + .perform_sync(); + + return res; +} + +#include +#include +#include + +std::string HelioQuery::generate_graphql_query(const std::string &gcode_id, float temperatureStabilizationHeight, float airTemperatureAboveBuildPlate, float stabilizedAirTemperature) +{ + std::string name = generateTimestampedString(); + + std::string base_query = R"( { + "query": "mutation CreateSimulation($input: CreateSimulationInput!) { createSimulation(input: $input) { id name progress status gcode { id name } printer { id name } material { id name } reportJsonUrl thermalIndexGcodeUrl estimatedSimulationDurationSeconds insertedAt updatedAt } }", + "variables": { + "input": { + "name": "%1%", + "gcodeId": "%2%", + "simulationSettings": { + )"; + + std::vector settings_fields; + + if (temperatureStabilizationHeight != -1) { + settings_fields.push_back(boost::str(boost::format(R"( "temperatureStabilizationHeight": %1%)") % temperatureStabilizationHeight)); + } + + if (airTemperatureAboveBuildPlate != -1) { + settings_fields.push_back(boost::str(boost::format(R"( "airTemperatureAboveBuildPlate": %1%)") % airTemperatureAboveBuildPlate)); + } + + if (stabilizedAirTemperature != -1) { + settings_fields.push_back(boost::str(boost::format(R"( "stabilizedAirTemperature": %1%)") % stabilizedAirTemperature)); + } + + std::string settings_block; + if (!settings_fields.empty()) { settings_block = boost::join(settings_fields, ",\n"); } + + std::string full_query = base_query + settings_block + R"( + } + } + } + } )"; + + boost::format formatter(full_query); + formatter % name % gcode_id; + + return formatter.str(); +} + +HelioQuery::CreateSimulationResult HelioQuery::create_simulation(const std::string helio_api_url, + const std::string helio_api_key, + const std::string gcode_id, + const float initial_room_airtemp, + const float layer_threshold, + const float object_proximity_airtemp) +{ + HelioQuery::CreateSimulationResult res; + + const float initial_room_temp_kelvin = initial_room_airtemp == -1 ? -1 : initial_room_airtemp + 273.15; + const float object_proximity_airtemp_kelvin = object_proximity_airtemp == -1 ? -1 : object_proximity_airtemp + 273.15; + const float layer_threshold_meters = layer_threshold / 1000; + + + + std::string query_body = generate_graphql_query(gcode_id, + layer_threshold_meters, + initial_room_temp_kelvin, + object_proximity_airtemp_kelvin + ); + + auto http = Http::post(helio_api_url); + + http.header("Content-Type", "application/json").header("Authorization", helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([&res](std::string body, unsigned status) { + + try{ + nlohmann::json parsed_obj = nlohmann::json::parse(body); + res.status = status; + if (parsed_obj.contains("errors")) { + res.error = parsed_obj["errors"].dump(); + res.success = false; + } + else { + res.success = true; + res.id = parsed_obj["data"]["createSimulation"]["id"]; + res.name = parsed_obj["data"]["createSimulation"]["name"]; + } + } + catch (...){} + }) + .on_error([&res](std::string body, std::string error, unsigned status) { + res.success = false; + res.error = error; + res.status = status; + }) + .perform_sync(); + + return res; +} + +HelioQuery::CheckSimulationProgressResult HelioQuery::check_simulation_progress(const std::string helio_api_url, + const std::string helio_api_key, + const std::string simulation_id) +{ + HelioQuery::CheckSimulationProgressResult res; + std::string query_body_template = R"( { + "query": "query Simulation($id: ID!) { simulation(id: $id) { id name progress status thermalIndexGcodeUrl } }", + "variables": { + "id": "%1%" + } + } )"; + + std::string query_body = (boost::format(query_body_template) % simulation_id).str(); + + auto http = Http::post(helio_api_url); + + http.header("Content-Type", "application/json").header("Authorization", helio_api_key).set_post_body(query_body); + + http.timeout_connect(20) + .timeout_max(100) + .on_complete([&res](std::string body, unsigned status) { + try{ + nlohmann::json parsed_obj = nlohmann::json::parse(body); + res.status = status; + if (parsed_obj.contains("errors")) { + res.error = parsed_obj["errors"].dump(); + } + else { + res.id = parsed_obj["data"]["simulation"]["id"]; + res.name = parsed_obj["data"]["simulation"]["name"]; + res.progress = parsed_obj["data"]["simulation"]["progress"]; + res.is_finished = parsed_obj["data"]["simulation"]["status"] == "FINISHED"; + if (res.is_finished) + res.url = parsed_obj["data"]["simulation"]["thermalIndexGcodeUrl"]; + } + } + catch (...){} + }) + .on_error([&res](std::string body, std::string error, unsigned status) { + res.error = error; + res.status = status; + }) + .perform_sync(); + + return res; +} + +void HelioBackgroundProcess::helio_thread_start(std::mutex& slicing_mutex, + std::condition_variable& slicing_condition, + BackgroundSlicingProcess::State& slicing_state, + std::unique_ptr& notification_manager) +{ + m_thread = create_thread([this, &slicing_mutex, &slicing_condition, &slicing_state, ¬ification_manager] { + this->helio_threaded_process_start(slicing_mutex, slicing_condition, slicing_state, notification_manager); + }); +} + +void HelioBackgroundProcess::helio_threaded_process_start(std::mutex& slicing_mutex, + std::condition_variable& slicing_condition, + BackgroundSlicingProcess::State& slicing_state, + std::unique_ptr& notification_manager) +{ + set_state(STATE_RUNNING); + + std::unique_lock slicing_lck(slicing_mutex); + slicing_condition.wait(slicing_lck, [this, &slicing_state]() { + return slicing_state == BackgroundSlicingProcess::STATE_FINISHED || slicing_state == BackgroundSlicingProcess::STATE_CANCELED || + slicing_state == BackgroundSlicingProcess::STATE_IDLE; + }); + slicing_lck.unlock(); + + if ((slicing_state == BackgroundSlicingProcess::STATE_FINISHED || slicing_state == BackgroundSlicingProcess::STATE_IDLE) && + !was_canceled()) { + wxPostEvent(GUI::wxGetApp().plater(), GUI::SimpleEvent(GUI::EVT_HELIO_PROCESSING_STARTED)); + + Slic3r::PrintBase::SlicingStatus status = Slic3r::PrintBase::SlicingStatus(0.0, _u8L("Helio: Process Started")); + Slic3r::SlicingStatusEvent* evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + BOOST_LOG_TRIVIAL(debug) << boost::format("url: %1%, key: %2%") % helio_api_url % helio_api_key; + + /*check api url*/ + if (helio_api_url.empty()) { + set_state(STATE_CANCELED); + Slic3r::HelioCompletionEvent *evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + _u8L("Helio API endpoint is empty, please check the configuration.")); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + return; + } + + /*check Personal assecc token */ + if (helio_origin_key.empty()) { + set_state(STATE_CANCELED); + Slic3r::HelioCompletionEvent *evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + _u8L("Personal assecc token is empty, please fill in the correct token.")); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + return; + } + + HelioQuery::PresignedURLResult create_presigned_url_res = HelioQuery::create_presigned_url(helio_api_url, helio_api_key); + + if (create_presigned_url_res.error.empty() && create_presigned_url_res.status == 200 && !was_canceled()) { + status = Slic3r::PrintBase::SlicingStatus(5, _u8L("Helio: Presigned URL Created")); + evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + HelioQuery::UploadFileResult upload_file_res = HelioQuery::upload_file_to_presigned_url(m_gcode_result->filename, + create_presigned_url_res.url); + + if (upload_file_res.success && !was_canceled()) { + status = Slic3r::PrintBase::SlicingStatus(10, _u8L("Helio: file succesfully uploaded")); + evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + HelioQuery::CreateGCodeResult create_gcode_res = HelioQuery::create_gcode(create_presigned_url_res.key, helio_api_url, + helio_api_key, printer_id, filament_id); + + create_simulation_step(create_gcode_res, notification_manager); + + } else { + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + _u8L("Helio: file upload failed")); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } + } else { + std::string presigned_url_message = (boost::format("error: %1%") % create_presigned_url_res.error).str(); + + if (create_presigned_url_res.status == 401) { + presigned_url_message += "\n "; + presigned_url_message += _u8L("Please make sure you have the corrent API key set in preferences."); + } + + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + presigned_url_message); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } + } else { + set_state(STATE_CANCELED); + } +} + +void HelioBackgroundProcess::create_simulation_step(HelioQuery::CreateGCodeResult create_gcode_res, + std::unique_ptr& notification_manager) +{ + if (create_gcode_res.success && !was_canceled()) { + Slic3r::PrintBase::SlicingStatus status = Slic3r::PrintBase::SlicingStatus(15, _u8L("Helio: GCode created successfully")); + Slic3r::SlicingStatusEvent* evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + auto print_config = GUI::wxGetApp().preset_bundle->full_config(); + const std::string gcode_id = create_gcode_res.id; + + const float chamber_temp = simulation_input_data.chamber_temp; //User input1 + const float layer_threshold = 20; //Default values from Helio + + std::string bed_temp_key = Slic3r::get_bed_temp_1st_layer_key((Slic3r::BedType)(print_config.option("curr_bed_type")->getInt())); + + const float bed_temp = print_config.option(bed_temp_key)->get_at(0); + float initial_room_airtemp = -1; + if (chamber_temp > 0.0f) { + initial_room_airtemp = (chamber_temp + bed_temp) / 2; + } + + HelioQuery::CreateSimulationResult create_simulation_res = HelioQuery::create_simulation(helio_api_url, helio_api_key, gcode_id, + initial_room_airtemp, layer_threshold, + chamber_temp); + + if (create_simulation_res.success && !was_canceled()) { + status = Slic3r::PrintBase::SlicingStatus(20, _u8L("Helio: simulation successfully created")); + evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + int times_tried = 0; + int max_unsuccessful_tries = 5; + int times_queried = 0; + + while (!was_canceled()) { + HelioQuery::CheckSimulationProgressResult check_simulation_progress_res = + HelioQuery::check_simulation_progress(helio_api_url, helio_api_key, create_simulation_res.id); + + if (check_simulation_progress_res.status == 200) { + times_tried = 0; + if (check_simulation_progress_res.error.empty()) { + std::string trailing_dots = ""; + + for (int i = 0; i < (times_queried % 3); i++) { + trailing_dots += "...."; + } + + status = Slic3r::PrintBase::SlicingStatus(35 + (80 - 35) * check_simulation_progress_res.progress, + _u8L("Helio: simulation working") + trailing_dots); + evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + if (check_simulation_progress_res.is_finished) { + // notification_manager->push_notification((boost::format("Helio: Simulation finished.")).str()); + std::string simulated_gcode_path = HelioBackgroundProcess::create_path_for_simulated_gcode( + m_gcode_result->filename); + + HelioBackgroundProcess::save_downloaded_gcode_and_load_preview(check_simulation_progress_res.url, + simulated_gcode_path, m_gcode_result->filename, + notification_manager); + break; + } + } else { + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", + false, _u8L("Helio: simulation failed")); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + break; + } + } else { + times_tried++; + + status = Slic3r::PrintBase::SlicingStatus(35, (boost::format("Helio: Simulation check failed, %1% tries left") % + (max_unsuccessful_tries - times_tried)) + .str()); + evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + + if (times_tried >= max_unsuccessful_tries) + break; + } + + times_queried++; + boost::this_thread ::sleep_for(boost::chrono::seconds(3)); + } + + } else { + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + (boost::format("Helio: Failed to create Simulation\n%1%") % create_simulation_res.error).str()); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } + + } else { + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + (boost::format("Helio: Failed to create GCode\n%1%") % create_gcode_res.error).str()); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } +} + +void HelioBackgroundProcess::save_downloaded_gcode_and_load_preview(std::string file_download_url, + std::string simulated_gcode_path, + std::string tmp_path, + std::unique_ptr& notification_manager) +{ + auto http = Http::get(file_download_url); + unsigned response_status = 0; + std::string downloaded_gcode; + std::string response_error; + + int number_of_attempts = 0; + int max_attempts = 7; + int number_of_seconds_till_next_attempt = 0; + + while (response_status != 200 && !was_canceled()) { + if (number_of_seconds_till_next_attempt <= 0) { + http.on_complete([&downloaded_gcode, &response_error, &response_status](std::string body, unsigned status) { + response_status = status; + if (status == 200) { + downloaded_gcode = body; + } else { + response_error = (boost::format("status: %1%, error: %2%") % status % body).str(); + } + }) + .on_error([&response_error, &response_status](std::string body, std::string error, unsigned status) { + response_status = status; + response_error = (boost::format("status: %1%, error: %2%") % status % body).str(); + }) + .perform_sync(); + + if (response_status != 200) { + number_of_attempts++; + Slic3r::PrintBase::SlicingStatus status = Slic3r::PrintBase::SlicingStatus( + 80, (boost::format("Helio: Could not download file. Attempts left %1%") % (max_attempts - number_of_attempts)).str()); + Slic3r::SlicingStatusEvent* evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + number_of_seconds_till_next_attempt = number_of_attempts * 5; + } + + if (response_status == 200) { + response_error = ""; + break; + } + + else if (number_of_attempts >= max_attempts) { + response_error = "Max attempts reached but file was not found"; + break; + } + + } else { + Slic3r::PrintBase::SlicingStatus status = Slic3r::PrintBase::SlicingStatus(80, + (boost::format("Helio: Next attemp in %1% seconds") % + number_of_seconds_till_next_attempt) + .str()); + Slic3r::SlicingStatusEvent* evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + number_of_seconds_till_next_attempt--; + } + + if (response_error.empty() && !was_canceled()) { + FILE* file = fopen(simulated_gcode_path.c_str(), "wb"); + fwrite(downloaded_gcode.c_str(), 1, downloaded_gcode.size(), file); + fclose(file); + + Slic3r::PrintBase::SlicingStatus status = Slic3r::PrintBase::SlicingStatus(100, _u8L("Helio: GCode downloaded successfully")); + Slic3r::SlicingStatusEvent* evt = new Slic3r::SlicingStatusEvent(GUI::EVT_SLICING_UPDATE, 0, status); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + HelioBackgroundProcess::load_simulation_to_viwer(simulated_gcode_path, tmp_path); + } else { + set_state(STATE_CANCELED); + + Slic3r::HelioCompletionEvent* evt = + new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, "", "", false, + (boost::format("Helio: GCode download failed: %1%") % response_error).str()); + wxQueueEvent(GUI::wxGetApp().plater(), evt); + } +} + +void HelioBackgroundProcess::load_simulation_to_viwer(std::string simulated_file_path, std::string tmp_path) +{ + const Vec3d origin = GUI::wxGetApp().plater()->get_partplate_list().get_current_plate_origin(); + m_gcode_processor.set_xy_offset(origin(0), origin(1)); + m_gcode_processor.process_file(simulated_file_path); + auto res = &m_gcode_processor.result(); + m_gcode_result = res; + + set_state(STATE_FINISHED); + Slic3r::HelioCompletionEvent* evt = new Slic3r::HelioCompletionEvent(GUI::EVT_HELIO_PROCESSING_COMPLETED, 0, simulated_file_path, + tmp_path, true); + wxQueueEvent(GUI::wxGetApp().plater(), evt); +} + +void HelioBackgroundProcess::set_helio_api_key(std::string api_key) { helio_api_key = api_key; } +void HelioBackgroundProcess::set_gcode_result(Slic3r::GCodeProcessorResult* gcode_result) { m_gcode_result = gcode_result; } + +} // namespace Slic3r diff --git a/src/slic3r/Utils/HelioDragon.hpp b/src/slic3r/Utils/HelioDragon.hpp new file mode 100644 index 0000000..ff506bc --- /dev/null +++ b/src/slic3r/Utils/HelioDragon.hpp @@ -0,0 +1,298 @@ +#ifndef slic3r_HelioDragon_hpp_ +#define slic3r_HelioDragon_hpp_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "PrintHost.hpp" +#include "libslic3r/PrintConfig.hpp" +#include "nlohmann/json.hpp" +#include "../GUI/BackgroundSlicingProcess.hpp" +#include "../GUI/NotificationManager.hpp" +#include "libslic3r/GCode/GCodeProcessor.hpp" +#include "../GUI/GUI_Preview.hpp" +#include "../GUI/Plater.hpp" +#include + +namespace Slic3r { + +class DynamicPrintConfig; +class Http; +class AppConfig; + +class HelioQuery +{ +public: + struct PresignedURLResult + { + std::string key; + std::string mimeType; + std::string url; + unsigned status; + std::string error; + }; + + struct UploadFileResult + { + bool success; + std::string error; + }; + + struct SupportedData + { + std::string id; + std::string name; + std::string native_name; + }; + + struct CreateGCodeResult + { + unsigned status; + bool success; + std::string name; + std::string id; + std::string error; + vector warning_flags; + vector error_flags; + }; + + struct CreateSimulationResult + { + unsigned status; + bool success; + std::string name; + std::string id; + std::string error; + }; + + struct CheckSimulationProgressResult + { + unsigned status; + bool is_finished; + float progress; + std::string id; + std::string name; + std::string url; + std::string error; + }; + + static std::string get_helio_api_url(); + static std::string get_helio_pat(); + static void set_helio_pat(std::string pat); + static void request_support_machine(const std::string helio_api_url, const std::string helio_api_key, int page); + static void request_support_material(const std::string helio_api_url, const std::string helio_api_key, int page); + static void request_pat_token(std::function func); + static PresignedURLResult create_presigned_url(const std::string helio_api_url, const std::string helio_api_key); + static UploadFileResult upload_file_to_presigned_url(const std::string file_path_string, const std::string upload_url); + static CreateGCodeResult create_gcode(const std::string key, + const std::string helio_api_url, + const std::string helio_api_key, + const std::string printer_id, + const std::string filament_id); + + static void request_all_support_machine(const std::string helio_api_url, const std::string helio_api_key) + { + global_supported_printers.clear(); + request_support_machine(helio_api_url, helio_api_key, 1); + } + + static void request_all_support_materials(const std::string helio_api_url, const std::string helio_api_key) + { + global_supported_materials.clear(); + request_support_material(helio_api_url, helio_api_key, 1); + } + + static CreateSimulationResult create_simulation(const std::string helio_api_url, + const std::string helio_api_key, + const std::string gcode_id, + const float initial_room_airtemp, + const float layer_threshold, + const float object_proximity_airtemp); + + static CheckSimulationProgressResult check_simulation_progress(const std::string helio_api_url, + const std::string helio_api_key, + const std::string simulation_id); + + static std::string generate_graphql_query(const std::string &gcode_id, float temperatureStabilizationHeight = -1, float airTemperatureAboveBuildPlate = -1, float stabilizedAirTemperature = -1); + static std::string generateTimestampedString() + { + // Get the current UTC time + boost::posix_time::ptime now = boost::posix_time::second_clock::universal_time(); + + // Format as ISO 8601 (e.g., "2025-03-12T14:23:45") + std::string iso_datetime = boost::posix_time::to_iso_extended_string(now); + + // Combine with your desired prefix + return "QIDISlicer " + iso_datetime; + } + + static std::vector global_supported_printers; + static std::vector global_supported_materials; +}; + +class HelioBackgroundProcess +{ +public: + struct SimulationInput + { + float chamber_temp{-1}; + }; + +public: + enum State { + // m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet). + STATE_INITIAL = 0, + STATE_STARTED, + STATE_RUNNING, + STATE_FINISHED, + STATE_CANCELED, + }; + +private: + State m_state; + +public: + std::mutex m_mutex; + std::condition_variable m_condition; + boost::thread m_thread; + std::string helio_origin_key; + std::string helio_api_key; + std::string helio_api_url; + std::string printer_id; + std::string filament_id; + + //for user input + SimulationInput simulation_input_data; + + Slic3r::GCodeProcessorResult* m_gcode_result; + Slic3r::GCodeProcessor m_gcode_processor; + Slic3r::GUI::Preview* m_preview; + std::function m_update_function; + + void set_simulation_input_data(SimulationInput data) + { + simulation_input_data = data; + } + + void stop() + { + m_mutex.lock(); + m_state = STATE_CANCELED; + m_mutex.unlock(); + } + + bool is_running() + { + m_mutex.lock(); + bool running_state = (m_state == STATE_STARTED || m_state == STATE_RUNNING); + m_mutex.unlock(); + + return running_state; + } + + bool was_canceled() + { + m_mutex.lock(); + bool canceled_state = (m_state == STATE_CANCELED); + m_mutex.unlock(); + return canceled_state; + } + + void set_state(State state) + { + m_mutex.lock(); + m_state = state; + m_mutex.unlock(); + } + + State get_state() + { + m_mutex.lock(); + auto state = m_state; + m_mutex.unlock(); + + return state; + } + + void helio_threaded_process_start(std::mutex& slicing_mutex, + std::condition_variable& slicing_condition, + BackgroundSlicingProcess::State& slicing_state, + std::unique_ptr& notification_manager); + + void helio_thread_start(std::mutex& slicing_mutex, + std::condition_variable& slicing_condition, + BackgroundSlicingProcess::State& slicing_state, + std::unique_ptr& notification_manager); + + HelioBackgroundProcess() {} + + ~HelioBackgroundProcess() + { + m_gcode_result = nullptr; + if (m_thread.joinable()) { + m_thread.join(); + } + } + + void init(std::string api_key, + std::string api_url, + std::string printer_id, + std::string filament_id, + Slic3r::GCodeProcessorResult* gcode_result, + Slic3r::GUI::Preview* preview, + std::function function) + { + m_state = STATE_STARTED; + m_gcode_processor.reset(); + helio_origin_key = api_key; + helio_api_key = "Bearer " + api_key; + helio_api_url = api_url; + this->printer_id = printer_id; + this->filament_id = filament_id; + m_gcode_result = gcode_result; + m_preview = preview; + m_update_function = function; + } + + void reset() + { + m_state = STATE_INITIAL; + m_gcode_processor.reset(); + m_gcode_result = nullptr; + } + + void set_helio_api_key(std::string api_key); + void set_gcode_result(Slic3r::GCodeProcessorResult* gcode_result); + void create_simulation_step(HelioQuery::CreateGCodeResult create_gcode_res, + std::unique_ptr& notification_manager); + void save_downloaded_gcode_and_load_preview(std::string file_download_url, + std::string simulated_gcode_path, + std::string tmp_path, + std::unique_ptr& notification_manager); + + std::string create_path_for_simulated_gcode(std::string unsimulated_gcode_path) + { + boost::filesystem::path p(unsimulated_gcode_path); + + if (!p.has_filename()) { + throw std::runtime_error("Invalid path: No filename present."); + } + + boost::filesystem::path parent = p.parent_path(); + std::string new_filename = "simulated_" + p.filename().string(); + + return (parent / new_filename).string(); + } + + void load_simulation_to_viwer(std::string file_path, std::string tmp_path); +}; +} // namespace Slic3r +#endif diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index 508c56c..9b5dc3a 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -112,7 +112,6 @@ struct Http::priv std::string headers; size_t limit; bool cancel; - std::unique_ptr putFile; std::thread io_thread; Http::CompleteFn completefn; @@ -260,10 +259,8 @@ size_t Http::priv::form_file_read_cb(char *buffer, size_t size, size_t nitems, v { //y65 // try { - // auto putFile = reinterpret_cast*>(userp); - // if (!putFile) { throw std::runtime_error(std::string("The unique_ptr is nullptr! please check")); return CURL_READFUNC_ABORT; } + // auto fstream = static_cast(userp) - // fs::ifstream* fstream = putFile->get(); // if (!fstream) { throw std::runtime_error(std::string("The fstream is nullptr! please check")); return CURL_READFUNC_ABORT; } @@ -380,9 +377,10 @@ void Http::priv::set_put_body(const fs::path &path) boost::system::error_code ec; boost::uintmax_t filesize = file_size(path, ec); if (!ec) { - putFile = std::make_unique(path, std::ios_base::binary |std::ios_base::in); + form_files.emplace_back(path, std::ios_base::binary |std::ios_base::in); + auto &putFile = form_files.back(); ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - ::curl_easy_setopt(curl, CURLOPT_READDATA, (void *) &putFile); + ::curl_easy_setopt(curl, CURLOPT_READDATA, static_cast(&putFile)); ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, filesize); } } @@ -502,11 +500,6 @@ Http::Http(Http &&other) : p(std::move(other.p)) {} Http::~Http() { - if (p && p->putFile) - { - p->putFile.reset(); - } - if (p && p->io_thread.joinable()) { p->io_thread.detach(); } diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 4606357..db976bc 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -747,10 +747,11 @@ void PresetUpdater::priv::parse_ota_files(std::string ota_json, std::string& ver if (j.contains("description")) description = j["description"]; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": ota_json %1%, version %2%, force %3%, description %4%")%ota_json %version %force_upgrade %description; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ + << boost::format(": ota_json %1%, version %2%, force %3%, description %4%") % PathSanitizer::sanitize(ota_json) % version % force_upgrade % description; } catch(nlohmann::detail::parse_error &err) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<