mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 10:21:00 +00:00
Merge some features from BS1.9 beta4 (#5181)
* FIX: linux: fix the building issue on Linux Mint 21.3 Virginia
github: https://github.com/bambulab/BambuStudio/issues/3874
author: https://github.com/lucianoloder
Change-Id: Ia3db6923d5dd68dba532d7bdba6f93f73cc51d59
* FIX: auto-arranging incorrect with rotation enabled
auto-arranging incorrect with rotation enabled and the objects already have been rotated.
jira: STUDIO-6022
Change-Id: I349d663efb1fc71367c8a77aa8ed5047a0bf2017
(cherry picked from commit 75fe40257a274ed83886e1ee20ce8dedd0de48f6)
* ENH: update X1C & X1E start gcode
1.Fix fan problem
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I68ee5be78e142e8a2a210a1a70f5663893390610
* ENH: update A series gcode
1. Update A1 series start gcode and change filament gcode
2. Add G2814 command
3. Add multi-filament extrusion compensation and vibration suppression
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I57d2bc8e98d3e547881dc1369c1fb31413c6205d
* FIX: fix some cali problem of P series
jira: none
Change-Id: Id57ea8d65da22ab653cca49509cb923ff065e43f
* FIX: fix can't enter ',' in multiplicator
github: #3805
Change-Id: I6dd70822d1c2e79d66c70514d6dd580ab029c7ea
* calib wizard
* NEW: FlipLines infill
jira:6701
New infill pattern that combine block lines infill and switching layers for smooth transition.
Change-Id: I2608a2d39b14efcdfe9d39a9437280da350b94c0
(cherry picked from commit 8d0a09c8b763dfc924cbba9913c241e6afadbc7f)
* ENH: add nozzle blob detection and air printing detection
jira: new
Change-Id: Ie4a19a7ad7d0b10a021c516cbc3a84b4ae734302
* FIX: Top surface bridging fail on 3DHC & FL infill
Add 45 degree angle offset when processing the bridge.
Need to raise infill_direction to invalidate posPrepareInfill
jira: 6774
Change-Id: I5e6bef3aa814b01c5f30398ac745937a67e3ef4c
(cherry picked from commit 7b12cab10b88f432a11414f8caa1c6427777a1ba)
* FIX: the error display when reset virtual slot
jira: none
Change-Id: I5ae5899baf1bfc2aaadb832083b277855a669fd5
* FIX: Error "Voronoi cell doesn't contain a sourcepoint"
github: 3859
Change-Id: Idca84992bcba5380bfe05e63ac9a5e40419dcfdf
* fix build error
* FIX: CLI: fix the crash issue caused by get_min_flush_volumes
JIRA: no jira
Change-Id: I0d5bfd605e51ebddac8fddc4d83dab5055b0fbf2
* FIX: can't use support filament in gcode.3mf
1. Add total_filament_volumes, directly access it to get used filaments
github:#3865
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I4fae4f1947b4ebd16e394e0f3cf5fb0e9f979717
* ENH: p series support long retraction
1. P series support long retraction in filament
2. Add long retraction params in common.json
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ib94184fa1f0b5ab151360f1f053d8c8ff92e7e18
* ENH::modify some logs level
jira:[for log]
Change-Id: I6a46b8fcd3a030b4b630e800fe9a9ac5c387f117
* NEW: support multi device
JIRA: STUDIO-6072
Change-Id: Ic514c4097767b0a728368c9ea48ee103c031fbb0
Signed-off-by: Stone Li <stone.li@bambulab.com>
* ENH: update A1 series gcode
1.Update filament change gcode and machine start gcode for
A1 and A1 mini
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I2f3be3fd89fef21e717a32f2b89985fc046f7f6e
* FIX: always have 0th filament in ams mapping
1. Only set the filament id in map when flush length is not 0
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I6e0aeaf010f6e6dcbdc3bca5c0034aa60750bb67
* ENH: add filament id in slice info
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ic5fe4632bca8acacc9ffd072ee2ed207c1da37aa
* ENH: refine ui for multi machine
JIRA: STUDIO-6819 STUDIO-6824
1. Shrink the Send Print dialog box
2. add input box for flipping panel
Change-Id: I4174c79ecd239c374ee11478951e12be399c57ce
* FIX: fix Issues with sending multiple devices
JIRA: STUDIO-6876
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: I33c6a932863fc715c3f0eb5dfd4b299f980a4918
* NEW: support hms error code
Change-Id: Ic256a83cf501fb05bb9d3203f3d24cb1d1290fa4
* FIX:fixed some multi job issue
Change-Id: I338078ad8fcf809888db9d8daeb470a9bf4eab46
* NEW:support pin code binding
Change-Id: Ida5d47881fbd83f3ffedc80369cfe377114d7f13
* ENH:add printable check for devices
Change-Id: I672988fa9cfa986d924bfc64331752f4aef68067
(cherry picked from commit 69de9e5b8334ec94eec7fcee31038b8ff42d1d3b)
* FIX: add more fonts
jira: none
Change-Id: I6bafed3563083858f29e92a3d84906a2e53dcb5c
(cherry picked from commit afbea693e807dcc1c406a59aa5376b9ea2a5d606)
* ENH: load more fonts
this feature is according to Prusa by Filip Sykala<filip.sykala@prusa3d.cz>, thanks to Filip Sykala
jira: none
Change-Id: I55e92f184f750c0b93b679d4382aaa5b164ec5c3
(cherry picked from commit d05522c4cc5d7ee4cac42de398b88d347a55f74b)
* ENH: add ProfileDescription for translate
1.Add ProfileDescription.hpp simply for translating
jira:NEW
Signed-off-by: XunZhangBambu <xun.zhang@bambulab.com>
Change-Id: Iaa3ced1edccf67eaeebde35c1e8b36442d2e9a6f
* ENH: Improve CrossHatch transation layers
jira: 6701
Change name from Flippingline to CrossHatch.
Reduce noise, improve speed by 6.5%. Improve transation layers by
gradually increasing rotation angle and overshoot the transation
layer while direction changed.
Change-Id: I17fcc45b409074d121bf5bb5702e15553d925b51
* UP
* ENH: modify the default config for multi-device
JIRA: STUDIO-6072
Change-Id: If6e7582a8274eb5e685b8b8545f6eab5d17de3f5
Signed-off-by: Stone Li <stone.li@bambulab.com>
* ENH: add long retraction for P series
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I6890695b67e674fc5cdc2a208e89bd9e41404213
* FIX: all plates stats data missing issue
jira: new
Change-Id: I137a2b6d69ad08791f5a9a9788653621960dc63f
* ENH:update pre print options
jira:[for multi]
Change-Id: I2e9bb8a09436a71749af98a0bad94e9922f95c81
* FIX:fixed can't popup pinbind win on macos
jira:[STUDIO-6895]
Change-Id: I664bba78cf27420d736b586df19e3c09c6f8ed21
* FIX:fixed the task of padding cannot be cancelled
Change-Id: I401a22118c14ca7601be7a925cfd8e4796dfc1e9
* ENH:Play video after redirecting to device page
jira:[STUDIO-6884]
Change-Id: Ia5e2ac84e3d71baacfcf941b782dab2325f35d54
* FIX: fix ui bug in send multi machine page for mac
JIRA: STUDIO-6882
Incorrect background color when renaming during multi machine printing
Change-Id: I6c551f5023ffe747e7a7e2f5703b0707c9505922
* FIX: Fix some bugs in maintaining the selected status of local tasks
JIRA: STUDIO-6824
Change-Id: I12c4da3fc56ac5077b3ccd7e89a4b57c3675eaf5
* ENH: local task sort by send time by default
JIRA: STUDIO-6885
Change-Id: I03b5881a39ab2e90c5b9cf46052ba465ee707ccc
* FIX: Clicking to continue printing does not take effect in error code
JIRA: STUDIO-6830
Detected an incomplete printing task error pop-up when power outage occurred. Clicking to continue printing did not take effect
Change-Id: Ie85a1602093dabac861cd1f41ea21e1c312c83e9
* ENH: use designTitle when designId > 0
JIRA: STUDIO-6072
Change-Id: I8342df053edeab16f930522e099e2eef91e5c5a4
Signed-off-by: Stone Li <stone.li@bambulab.com>
* NEW:import vertex and mtl color from obj file
Jira: STUDIO-6805
Change-Id: Iaacb13ee2451effdb83e5aba4b7fe1637b7fc95f
* FIX:change the strategy of merge_ka_kd
Upgrade ui, users can directly ok to proceed to the next step
jira: STUDIO-6805
Change-Id: Ia81019c2eacb503666680c0b8583d026baa0134c
(cherry picked from commit 38a2434753c8e3b422267283b16c75f6ad195b14)
* FIX:use default_strategy after modifed cluster number
jira: STUDIO-6915
Change-Id: I4e0c3d62f5a766f73d48d1e06c4364fc6babe1ac
* FIX: the bug of incorrect button without restarting
JIRA: STUDIO-6824
The bug can cause the user to not restart when opening the multi-device option, but the button of send multi-devices appears
Change-Id: I0837fa79ecc1d8ab5ce98273ad134fa2f830421e
* FIX: wrong default value for long retraction
jira:NEW
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ifc2ec57a320fdb14e7ca746e5795501ed146ff32
* FIX: error code pop-up window without retry button in some code
JIRA: STUDIO-6922
Change-Id: I67464bebaba4558618301592c455db8824bbfe30
* FIX: air printing and nozzle blob detection issue
jira: STUDIO-6897
Change-Id: I008ddb24b74119d7e4124ae26310b4b86c42a799
* FIX:fix bugs of algo and read quad in obj file
Jira: STUDIO-6805
Change-Id: I6c33e8197225f27dccdfa0681e64d76d1df14f61
* dd
* ENH:Set the default nozzle diameter to 0.4
jira:[for nozzle]
Change-Id: I74a5c9b0460046496b897eae3d9f917ac1b99052
* FIX:fixed backspace error on macos
Change-Id: I76066391783c04857c1a60a6f8438111501b6d7c
* ENH:Subscription list deduplication
jira:[for mulit]
Change-Id: I10e9d849986c9661b587c7b1a509180c2451816e
* ENH:update wiki url for Pin Code
jira:[pin code]
Change-Id: I95faaa396a839b5b159119ef235b650c76706a84
* NEW:add OpenCV.cmake in deps
jira: none
Change-Id: I1ae4a2bd5618e9e620b08a937904d6af5d00bc41
* FIX:cancel obj import restrictions
jira: none
Change-Id: Iaf3e799ca982ad6aeb3ec76e9a416c4c8e4d100c
* NEW:add multiple printer restrictions
jira:[for multiple]
Change-Id: I0bb5a0c1062a543c42f8d67a9347efa358b0864a
* ENH:Added two entrances for adding devices
jira:[multi device]
Change-Id: Ieb6197e067d422979606f93b22b337a2399aec74
* slic3r: Fix wxFont being undefined
[427/494] Building CXX object src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o
FAILED: src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o
/usr/bin/c++ -DBOOST_ATOMIC_NO_LIB -DBOOST_CHRONO_NO_LIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_FILESYSTEM_NO_LIB -DBOOST_IOSTREAMS_NO_LIB -DBOOST_LOCALE_NO_LIB -DBOOST_LOG_NO_LIB -DBOOST_REGEX_NO_LIB -DBOOST_SYSTEM_NO_LIB -DBOOST_THREAD_NO_LIB -DCURL_STATICLIB -DGLEW_STATIC -DLIBNEST2D_GEOMETRIES_libslic3r -DLIBNEST2D_OPTIMIZER_nlopt -DLIBNEST2D_STATIC -DLIBNEST2D_THREADING_tbb -DOPENSSL_CERT_OVERRIDE -DOPENVDB_OPENEXR_STATICLIB -DOPENVDB_STATICLIB -DSLIC3R_CURRENTLY_COMPILING_GUI_MODULE -DSLIC3R_GUI -DTBB_USE_CAPTURED_EXCEPTION=0 -DUNICODE -DUSE_TBB -DWXINTL_NO_GETTEXT_MACRO -D_UNICODE -D__WXGTK3__ -D__WXGTK__ -DwxDEBUG_LEVEL=0 -DwxNO_UNSAFE_WXSTRING_CONV -DwxUSE_UNICODE -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/run/build/BambuStudio/src -I/run/build/BambuStudio/build/src/platform -I/run/build/BambuStudio/src/hidapi/include -I/run/build/BambuStudio/src/slic3r/Utils -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/webp -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/atk-1.0 -I/usr/include/fribidi -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/sysprof-6 -I/usr/include/gstreamer-1.0 -I/run/build/BambuStudio/build/src/libslic3r -I/run/build/BambuStudio/deps/build/destdir/usr/local/include/opencascade -I/run/build/BambuStudio/src/libnest2d/include -I/run/build/BambuStudio/src/miniz -I/run/build/BambuStudio/src/glu-libtess/include -I/run/build/BambuStudio/src/clipper2/Clipper2Lib/include -I/run/build/BambuStudio/src/minilzo -isystem /run/build/BambuStudio/src/eigen -isystem /run/build/BambuStudio/src/libigl -isystem /app/lib/wx/include/gtk3-unicode-static-3.1 -isystem /app/include/wx-3.1 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/opencv4 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/OpenEXR -std=gnu++20 -fext-numeric-literals -Wall -Wno-reorder -pthread -O3 -DNDEBUG -std=gnu++17 -fPIC -fsigned-char -Werror=return-type -Wno-ignored-attributes -Wno-unknown-pragmas -DOPENVDB_ABI_VERSION_NUMBER=8 -MD -MT src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o -MF src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o.d -o src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o -c /run/build/BambuStudio/src/slic3r/Utils/FontUtils.cpp
In file included from /run/build/BambuStudio/src/slic3r/Utils/FontUtils.cpp:1:
/run/build/BambuStudio/src/slic3r/Utils/FontUtils.hpp:51:21: error: ‘wxFont’ does not name a type
51 | bool can_load(const wxFont &font);
| ^~~~~~
* slic3r: Fix missing BOOST_LOG_TRIVIAL declaration
[427/494] Building CXX object src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o
FAILED: src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o
/usr/bin/c++ -DBOOST_ATOMIC_NO_LIB -DBOOST_CHRONO_NO_LIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_FILESYSTEM_NO_LIB -DBOOST_IOSTREAMS_NO_LIB -DBOOST_LOCALE_NO_LIB -DBOOST_LOG_NO_LIB -DBOOST_REGEX_NO_LIB -DBOOST_SYSTEM_NO_LIB -DBOOST_THREAD_NO_LIB -DCURL_STATICLIB -DGLEW_STATIC -DLIBNEST2D_GEOMETRIES_libslic3r -DLIBNEST2D_OPTIMIZER_nlopt -DLIBNEST2D_STATIC -DLIBNEST2D_THREADING_tbb -DOPENSSL_CERT_OVERRIDE -DOPENVDB_OPENEXR_STATICLIB -DOPENVDB_STATICLIB -DSLIC3R_CURRENTLY_COMPILING_GUI_MODULE -DSLIC3R_GUI -DTBB_USE_CAPTURED_EXCEPTION=0 -DUNICODE -DUSE_TBB -DWXINTL_NO_GETTEXT_MACRO -D_UNICODE -D__WXGTK3__ -D__WXGTK__ -DwxDEBUG_LEVEL=0 -DwxNO_UNSAFE_WXSTRING_CONV -DwxUSE_UNICODE -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/run/build/BambuStudio/src -I/run/build/BambuStudio/build/src/platform -I/run/build/BambuStudio/src/hidapi/include -I/run/build/BambuStudio/src/slic3r/Utils -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/webp -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/atk-1.0 -I/usr/include/fribidi -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/sysprof-6 -I/usr/include/gstreamer-1.0 -I/run/build/BambuStudio/build/src/libslic3r -I/run/build/BambuStudio/deps/build/destdir/usr/local/include/opencascade -I/run/build/BambuStudio/src/libnest2d/include -I/run/build/BambuStudio/src/miniz -I/run/build/BambuStudio/src/glu-libtess/include -I/run/build/BambuStudio/src/clipper2/Clipper2Lib/include -I/run/build/BambuStudio/src/minilzo -isystem /run/build/BambuStudio/src/eigen -isystem /run/build/BambuStudio/src/libigl -isystem /app/lib/wx/include/gtk3-unicode-static-3.1 -isystem /app/include/wx-3.1 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/opencv4 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/OpenEXR -std=gnu++20 -fext-numeric-literals -Wall -Wno-reorder -pthread -O3 -DNDEBUG -std=gnu++17 -fPIC -fsigned-char -Werror=return-type -Wno-ignored-attributes -Wno-unknown-pragmas -DOPENVDB_ABI_VERSION_NUMBER=8 -MD -MT src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o -MF src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o.d -o src/slic3r/CMakeFiles/libslic3r_gui.dir/Utils/FontUtils.cpp.o -c /run/build/BambuStudio/src/slic3r/Utils/FontUtils.cpp
/run/build/BambuStudio/src/slic3r/Utils/FontUtils.cpp: In function ‘std::unique_ptr<Slic3r::FontFile> Slic3r::create_font_file(const char*)’:
/run/build/BambuStudio/src/slic3r/Utils/FontUtils.cpp:127:27: error: ‘error’ was not declared in this scope; did you mean ‘perror’?
127 | BOOST_LOG_TRIVIAL(error) << "Couldn't open " << file_path << " for reading.";
| ^~~~~
| perror
[447/494] Building CXX object src/slic3r/CMakeFiles/libslic3r_gui.dir/GUI/TaskManager.cpp.o
FAILED: src/slic3r/CMakeFiles/libslic3r_gui.dir/GUI/TaskManager.cpp.o
/usr/bin/c++ -DBOOST_ATOMIC_NO_LIB -DBOOST_CHRONO_NO_LIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_FILESYSTEM_NO_LIB -DBOOST_IOSTREAMS_NO_LIB -DBOOST_LOCALE_NO_LIB -DBOOST_LOG_NO_LIB -DBOOST_REGEX_NO_LIB -DBOOST_SYSTEM_NO_LIB -DBOOST_THREAD_NO_LIB -DCURL_STATICLIB -DGLEW_STATIC -DLIBNEST2D_GEOMETRIES_libslic3r -DLIBNEST2D_OPTIMIZER_nlopt -DLIBNEST2D_STATIC -DLIBNEST2D_THREADING_tbb -DOPENSSL_CERT_OVERRIDE -DOPENVDB_OPENEXR_STATICLIB -DOPENVDB_STATICLIB -DSLIC3R_CURRENTLY_COMPILING_GUI_MODULE -DSLIC3R_GUI -DTBB_USE_CAPTURED_EXCEPTION=0 -DUNICODE -DUSE_TBB -DWXINTL_NO_GETTEXT_MACRO -D_UNICODE -D__WXGTK3__ -D__WXGTK__ -DwxDEBUG_LEVEL=0 -DwxNO_UNSAFE_WXSTRING_CONV -DwxUSE_UNICODE -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/run/build/BambuStudio/src -I/run/build/BambuStudio/build/src/platform -I/run/build/BambuStudio/src/hidapi/include -I/run/build/BambuStudio/src/slic3r/Utils -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/webp -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/atk-1.0 -I/usr/include/fribidi -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/gio-unix-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/sysprof-6 -I/usr/include/gstreamer-1.0 -I/run/build/BambuStudio/build/src/libslic3r -I/run/build/BambuStudio/deps/build/destdir/usr/local/include/opencascade -I/run/build/BambuStudio/src/libnest2d/include -I/run/build/BambuStudio/src/miniz -I/run/build/BambuStudio/src/glu-libtess/include -I/run/build/BambuStudio/src/clipper2/Clipper2Lib/include -I/run/build/BambuStudio/src/minilzo -isystem /run/build/BambuStudio/src/eigen -isystem /run/build/BambuStudio/src/libigl -isystem /app/lib/wx/include/gtk3-unicode-static-3.1 -isystem /app/include/wx-3.1 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/opencv4 -isystem /run/build/BambuStudio/deps/build/destdir/usr/local/include/OpenEXR -std=gnu++20 -fext-numeric-literals -Wall -Wno-reorder -pthread -O3 -DNDEBUG -std=gnu++17 -fPIC -fsigned-char -Werror=return-type -Wno-ignored-attributes -Wno-unknown-pragmas -DOPENVDB_ABI_VERSION_NUMBER=8 -MD -MT src/slic3r/CMakeFiles/libslic3r_gui.dir/GUI/TaskManager.cpp.o -MF src/slic3r/CMakeFiles/libslic3r_gui.dir/GUI/TaskManager.cpp.o.d -o src/slic3r/CMakeFiles/libslic3r_gui.dir/GUI/TaskManager.cpp.o -c /run/build/BambuStudio/src/slic3r/GUI/TaskManager.cpp
In file included from /run/build/BambuStudio/src/slic3r/GUI/TaskManager.cpp:1:
/run/build/BambuStudio/src/slic3r/GUI/TaskManager.hpp: In member function ‘void Slic3r::TaskStateInfo::set_state(Slic3r::TaskState)’:
/run/build/BambuStudio/src/slic3r/GUI/TaskManager.hpp:40:9: error: ‘BOOST_LOG_TRIVIAL’ was not declared in this scope
40 | BOOST_LOG_TRIVIAL(trace) << "TaskStateInfo set state = " << get_task_state_enum_str(ts);
| ^~~~~~~~~~~~~~~~~
* fix OpenCV
* wip - build break
* fix build error wip
* ENH: support preset description(tooltip)
Change-Id: Iff005baac4974c538d1109fb0ba1df20b04a8f69
Jira: STUDIO-5754
* fix more build errors
* Revert "ENH: load more fonts"
This reverts commit 32b6fd199a.
* change colors
* misc fixes
* restore export gcode btn
---------
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Signed-off-by: Stone Li <stone.li@bambulab.com>
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Signed-off-by: XunZhangBambu <xun.zhang@bambulab.com>
Co-authored-by: lane.wei <lane.wei@bambulab.com>
Co-authored-by: Arthur <arthur.tang@bambulab.com>
Co-authored-by: xun.zhang <xun.zhang@bambulab.com>
Co-authored-by: zhimin.zeng <zhimin.zeng@bambulab.com>
Co-authored-by: Kunlong Ma <kunlong.ma@bambulab.com>
Co-authored-by: jianjia.ma <jianjia.ma@bambulab.com>
Co-authored-by: liz.li <liz.li@bambulab.com>
Co-authored-by: tao wang <tao.wang@bambulab.com>
Co-authored-by: Stone Li <stone.li@bambulab.com>
Co-authored-by: zhou.xu <zhou.xu@bambulab.com>
Co-authored-by: Bastien Nocera <hadess@hadess.net>
Co-authored-by: chunmao.guo <chunmao.guo@bambulab.com>
This commit is contained in:
co-authored by
lane.wei
Arthur
xun.zhang
zhimin.zeng
Kunlong Ma
jianjia.ma
liz.li
tao wang
Stone Li
zhou.xu
Bastien Nocera
chunmao.guo
parent
78af750ed9
commit
226450ea6a
+82
-36
@@ -791,7 +791,8 @@ static int construct_assemble_list(std::vector<assemble_plate_info_t> &assemble_
|
||||
else if (boost::algorithm::iends_with(assemble_object.path, ".obj"))
|
||||
{
|
||||
std::string message;
|
||||
bool result = load_obj(path_str, &mesh, message);
|
||||
ObjInfo obj_info;
|
||||
bool result = load_obj(path_str, &mesh, obj_info, message);
|
||||
if (!result) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": failed to read a valid mesh from obj file %1%, plate index %2%, object index %3%, error %4%") % assemble_object.path % (index + 1) % (obj_index + 1) % message;
|
||||
return CLI_DATA_FILE_ERROR;
|
||||
@@ -1456,6 +1457,12 @@ int CLI::run(int argc, char **argv)
|
||||
m_models.push_back(std::move(model));
|
||||
}
|
||||
|
||||
if (!is_bbl_3mf && plate_to_slice > 0)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("%1%: not support to slice plate %2%, reset to 0")%__LINE__ %plate_to_slice;
|
||||
plate_to_slice = 0;
|
||||
}
|
||||
|
||||
//load custom gcode file
|
||||
std::map<int, CustomGCode::Info> custom_gcodes_map;
|
||||
if (!custom_gcode_file.empty()) {
|
||||
@@ -2624,7 +2631,7 @@ int CLI::run(int argc, char **argv)
|
||||
//set multiplier to 1?
|
||||
m_print_config.option<ConfigOptionFloat>("flush_multiplier", true)->set(new ConfigOptionFloat(1.f));
|
||||
|
||||
const std::vector<int>& min_flush_volumes = Slic3r::GUI::get_min_flush_volumes();
|
||||
const std::vector<int>& min_flush_volumes = Slic3r::GUI::get_min_flush_volumes(m_print_config);
|
||||
|
||||
if (filament_is_support->size() != project_filament_count)
|
||||
{
|
||||
@@ -3525,7 +3532,8 @@ int CLI::run(int argc, char **argv)
|
||||
|
||||
ap.apply();
|
||||
}
|
||||
partplate_list.rebuild_plates_after_arrangement(false, true, i);
|
||||
//lock here
|
||||
cur_plate->lock(true);
|
||||
}
|
||||
else {
|
||||
size_t plate_obj_count = assemble_plate.loaded_obj_list.size();
|
||||
@@ -3548,6 +3556,8 @@ int CLI::run(int argc, char **argv)
|
||||
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate*)partplate_list.get_plate(i);
|
||||
cur_plate->lock(false);
|
||||
}
|
||||
|
||||
partplate_list.reload_all_objects(false, -1);
|
||||
}
|
||||
else if (need_arrange)
|
||||
{
|
||||
@@ -4175,7 +4185,8 @@ int CLI::run(int argc, char **argv)
|
||||
bool no_check = false;
|
||||
std::string export_3mf_file, load_slice_data_dir, export_slice_data_dir;
|
||||
std::vector<ThumbnailData*> calibration_thumbnails;
|
||||
int max_slicing_time_per_plate = 0, max_triangle_count_per_plate = 0;
|
||||
std::vector<int> plate_object_count(partplate_list.get_plate_count(), 0);
|
||||
int max_slicing_time_per_plate = 0, max_triangle_count_per_plate = 0, sliced_plate = -1;
|
||||
std::vector<bool> plate_has_skips(partplate_list.get_plate_count(), false);
|
||||
std::vector<std::vector<size_t>> plate_skipped_objects(partplate_list.get_plate_count());
|
||||
|
||||
@@ -4269,6 +4280,7 @@ int CLI::run(int argc, char **argv)
|
||||
} else if (opt_key == "slice") {
|
||||
//BBS: slice 0 means all plates, i means plate i;
|
||||
plate_to_slice = m_config.option<ConfigOptionInt>("slice")->value;
|
||||
sliced_plate = plate_to_slice;
|
||||
bool pre_check = (plate_to_slice == 0)?true:false;
|
||||
bool finished = false;
|
||||
|
||||
@@ -4427,6 +4439,7 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
|
||||
plate_triangle_counts[index] = triangle_count;
|
||||
plate_object_count[index] = printable_instances;
|
||||
BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ": load cached data success, go on.";
|
||||
}
|
||||
// BBS: TODO
|
||||
@@ -4734,6 +4747,28 @@ int CLI::run(int argc, char **argv)
|
||||
PlateDataPtrs plate_data_list;
|
||||
partplate_list.store_to_3mf_structure(plate_data_list);
|
||||
|
||||
if (sliced_plate == -1) {
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i);
|
||||
plate_object_count[i] = part_plate->printable_instance_size();
|
||||
}
|
||||
}
|
||||
else if (sliced_plate == 0){
|
||||
//slicing all
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
if (skip_useless_pick && (plate_object_count[i] == 1)) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("only has 1 object, set plate %1%'s is_label_object_enabled from %2% to false")%(i+1) % (plate_data_list[i]->is_label_object_enabled);
|
||||
plate_data_list[i]->is_label_object_enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (skip_useless_pick && (plate_object_count[sliced_plate - 1] == 1)) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("only has 1 object, set plate %1%'s is_label_object_enabled from %2% to false")%sliced_plate % (plate_data_list[sliced_plate - 1]->is_label_object_enabled);
|
||||
plate_data_list[sliced_plate - 1]->is_label_object_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!outfile_dir.empty()) {
|
||||
export_3mf_file = outfile_dir + "/"+export_3mf_file;
|
||||
}
|
||||
@@ -4752,7 +4787,7 @@ int CLI::run(int argc, char **argv)
|
||||
// get type and color for platedata
|
||||
auto* filament_types = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_type"));
|
||||
const ConfigOptionStrings* filament_color = dynamic_cast<const ConfigOptionStrings *>(m_print_config.option("filament_colour"));
|
||||
//auto* filament_id = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_ids"));
|
||||
auto* filament_id = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_ids"));
|
||||
const ConfigOptionFloats* nozzle_diameter_option = dynamic_cast<const ConfigOptionFloats *>(m_print_config.option("nozzle_diameter"));
|
||||
std::string nozzle_diameter_str;
|
||||
if (nozzle_diameter_option)
|
||||
@@ -4769,10 +4804,10 @@ int CLI::run(int argc, char **argv)
|
||||
plate_data->nozzle_diameters = nozzle_diameter_str;
|
||||
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++) {
|
||||
//it->filament_id = filament_id?filament_id->get_at(it->id):"unknown";
|
||||
std::string display_filament_type;
|
||||
it->type = m_print_config.get_filament_type(display_filament_type, it->id);
|
||||
it->color = filament_color ? filament_color->get_at(it->id) : "#FFFFFF";
|
||||
it->filament_id = filament_id?filament_id->get_at(it->id):"";
|
||||
}
|
||||
|
||||
if (!plate_data->plate_thumbnail.is_valid()) {
|
||||
@@ -4940,6 +4975,7 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
ThumbnailsParams thumbnail_params;
|
||||
GLShaderProgram* shader = opengl_mgr.get_shader("thumbnail");
|
||||
if (!shader) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("can not get shader for rendering thumbnail");
|
||||
@@ -5057,39 +5093,49 @@ int CLI::run(int argc, char **argv)
|
||||
unsigned int thumbnail_width = 512, thumbnail_height = 512;
|
||||
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top/pick thumbnail missed, need to regenerate")%(i+1);
|
||||
|
||||
switch (Slic3r::GUI::OpenGLManager::get_framebuffers_type())
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top/pick thumbnail missed, need to regenerate, objects count %2%, skip_useless_pick %3%")%(i+1) %plate_object_count[i] %skip_useless_pick;
|
||||
if (skip_useless_pick && ((plate_object_count[i] <= 1) || (plate_object_count[i] > 64)))
|
||||
{
|
||||
case Slic3r::GUI::OpenGLManager::EFramebufferType::Arb:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: ARB");
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*top_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*picking_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
|
||||
//don't render pick and top
|
||||
part_plate->top_thumbnail_data.reset();
|
||||
part_plate->pick_thumbnail_data.reset();
|
||||
plate_data->top_file.clear();
|
||||
plate_data->pick_file.clear();
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("skip rendering for top&&pick");
|
||||
}
|
||||
else {
|
||||
switch (Slic3r::GUI::OpenGLManager::get_framebuffers_type())
|
||||
{
|
||||
case Slic3r::GUI::OpenGLManager::EFramebufferType::Arb:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: ARB");
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*top_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*picking_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
|
||||
break;
|
||||
}
|
||||
case Slic3r::GUI::OpenGLManager::EFramebufferType::Ext:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: EXT");
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*top_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*picking_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: unknown");
|
||||
break;
|
||||
}
|
||||
case Slic3r::GUI::OpenGLManager::EFramebufferType::Ext:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: EXT");
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*top_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
|
||||
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*picking_thumbnail,
|
||||
thumbnail_width, thumbnail_height, thumbnail_params,
|
||||
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: unknown");
|
||||
break;
|
||||
}
|
||||
plate_data->top_file = "valid_top";
|
||||
plate_data->pick_file = "valid_pick";
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top_thumbnail,finished rendering")%(i+1);
|
||||
}
|
||||
plate_data->top_file = "valid_top";
|
||||
plate_data->pick_file = "valid_pick";
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top_thumbnail,finished rendering")%(i+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,6 +186,8 @@ void AppConfig::set_defaults()
|
||||
if (get("show_hints").empty())
|
||||
set_bool("show_hints", true);
|
||||
//#endif
|
||||
if (get("enable_multi_machine").empty())
|
||||
set_bool("enable_multi_machine", false);
|
||||
|
||||
if (get("show_gcode_window").empty())
|
||||
set_bool("show_gcode_window", true);
|
||||
@@ -359,6 +361,14 @@ void AppConfig::set_defaults()
|
||||
set("curr_bed_type", "1");
|
||||
}
|
||||
|
||||
if (get("sending_interval").empty()) {
|
||||
set("sending_interval", "5");
|
||||
}
|
||||
|
||||
if (get("max_send").empty()) {
|
||||
set("max_send", "3");
|
||||
}
|
||||
|
||||
// #if BBL_RELEASE_TO_PUBLIC
|
||||
if (get("iot_environment").empty()) {
|
||||
set("iot_environment", "3");
|
||||
@@ -1246,6 +1256,38 @@ bool AppConfig::is_engineering_region(){
|
||||
return false;
|
||||
}
|
||||
|
||||
void AppConfig::save_custom_color_to_config(const std::vector<std::string> &colors)
|
||||
{
|
||||
auto set_colors = [](std::map<std::string, std::string> &data, const std::vector<std::string> &colors) {
|
||||
for (size_t i = 0; i < colors.size(); i++) {
|
||||
data[std::to_string(10 + i)] = colors[i]; // for map sort:10 begin
|
||||
}
|
||||
};
|
||||
if (colors.size() > 0) {
|
||||
if (!has_section("custom_color_list")) {
|
||||
std::map<std::string, std::string> data;
|
||||
set_colors(data, colors);
|
||||
set_section("custom_color_list", data);
|
||||
} else {
|
||||
auto data = get_section("custom_color_list");
|
||||
auto data_modify = const_cast<std::map<std::string, std::string> *>(&data);
|
||||
set_colors(*data_modify, colors);
|
||||
set_section("custom_color_list", *data_modify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> AppConfig::get_custom_color_from_config()
|
||||
{
|
||||
std::vector<std::string> colors;
|
||||
if (has_section("custom_color_list")) {
|
||||
auto data = get_section("custom_color_list");
|
||||
for (auto iter : data) {
|
||||
colors.push_back(iter.second);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
void AppConfig::reset_selections()
|
||||
{
|
||||
|
||||
@@ -233,7 +233,9 @@ public:
|
||||
std::string get_country_code();
|
||||
bool is_engineering_region();
|
||||
|
||||
// reset the current print / filament / printer selections, so that
|
||||
void save_custom_color_to_config(const std::vector<std::string> &colors);
|
||||
std::vector<std::string> get_custom_color_from_config();
|
||||
// reset the current print / filament / printer selections, so that
|
||||
// the PresetBundle::load_selections(const AppConfig &config) call will select
|
||||
// the first non-default preset when called.
|
||||
void reset_selections();
|
||||
|
||||
@@ -987,7 +987,7 @@ void _arrange(
|
||||
// polygon nesting, a convex hull needs to be calculated.
|
||||
if (params.allow_rotations) {
|
||||
for (auto &itm : shapes) {
|
||||
itm.rotation(min_area_boundingbox_rotation(itm.rawShape()));
|
||||
itm.rotation(min_area_boundingbox_rotation(itm.transformedShape()));
|
||||
|
||||
// If the item is too big, try to find a rotation that makes it fit
|
||||
if constexpr (std::is_same_v<BinT, Box>) {
|
||||
|
||||
@@ -100,6 +100,8 @@ set(lisbslic3r_sources
|
||||
Fill/FillConcentric.hpp
|
||||
Fill/FillConcentricInternal.cpp
|
||||
Fill/FillConcentricInternal.hpp
|
||||
Fill/FillCrossHatch.cpp
|
||||
Fill/FillCrossHatch.hpp
|
||||
Fill/FillHoneycomb.cpp
|
||||
Fill/FillHoneycomb.hpp
|
||||
Fill/FillGyroid.cpp
|
||||
@@ -232,6 +234,7 @@ set(lisbslic3r_sources
|
||||
Arrange.cpp
|
||||
NormalUtils.cpp
|
||||
NormalUtils.hpp
|
||||
ObjColorUtils.hpp
|
||||
Orient.hpp
|
||||
Orient.cpp
|
||||
MultiPoint.cpp
|
||||
@@ -473,6 +476,7 @@ set(CGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE ON CACHE BOOL "" FORCE)
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0011 NEW)
|
||||
find_package(CGAL REQUIRED)
|
||||
find_package(OpenCV REQUIRED core)
|
||||
cmake_policy(POP)
|
||||
|
||||
add_library(libslic3r_cgal STATIC
|
||||
@@ -573,6 +577,7 @@ target_link_libraries(libslic3r
|
||||
mcut
|
||||
JPEG::JPEG
|
||||
qoi
|
||||
opencv_world
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
|
||||
@@ -6,7 +6,15 @@
|
||||
static const float INV_255 = 1.0f / 255.0f;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool color_is_equal(const RGBA a, const RGBA& b)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (abs(a[i] - b[i]) > 0.01) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Conversion from RGB to HSV color space
|
||||
// The input RGB values are in the range [0, 1]
|
||||
// The output HSV values are in the ranges h = [0, 360], and s, v = [0, 1]
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using RGB = std::array<float, 3>;
|
||||
using RGBA = std::array<float, 4>;
|
||||
const RGBA UNDEFINE_COLOR = {0,0,0,0};
|
||||
bool color_is_equal(const RGBA a, const RGBA &b);
|
||||
class ColorRGB
|
||||
{
|
||||
std::array<float, 3> m_data{1.0f, 1.0f, 1.0f};
|
||||
@@ -82,7 +85,9 @@ public:
|
||||
|
||||
ColorRGBA& operator = (const ColorRGBA& other) { m_data = other.m_data; return *this; }
|
||||
|
||||
bool operator == (const ColorRGBA& other) const { return m_data == other.m_data; }
|
||||
bool operator==(const ColorRGBA &other) const{
|
||||
return color_is_equal(m_data, other.m_data);
|
||||
}
|
||||
bool operator != (const ColorRGBA& other) const { return !operator==(other); }
|
||||
bool operator < (const ColorRGBA& other) const;
|
||||
bool operator > (const ColorRGBA& other) const;
|
||||
|
||||
@@ -831,6 +831,9 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
||||
else if (boost::iequals(it.key(), BBL_JSON_KEY_FROM)) {
|
||||
key_values.emplace(BBL_JSON_KEY_FROM, it.value());
|
||||
}
|
||||
else if (boost::iequals(it.key(), BBL_JSON_KEY_DESCRIPTION)) {
|
||||
key_values.emplace(BBL_JSON_KEY_DESCRIPTION, it.value());
|
||||
}
|
||||
else if (boost::iequals(it.key(), BBL_JSON_KEY_INSTANTIATION)) {
|
||||
key_values.emplace(BBL_JSON_KEY_INSTANTIATION, it.value());
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "FillLightning.hpp"
|
||||
// BBS: new infill pattern header
|
||||
#include "FillConcentricInternal.hpp"
|
||||
#include "FillCrossHatch.hpp"
|
||||
|
||||
// #define INFILL_DEBUG_OUTPUT
|
||||
|
||||
@@ -51,6 +52,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
||||
case ipGyroid: return new FillGyroid();
|
||||
case ipRectilinear: return new FillRectilinear();
|
||||
case ipAlignedRectilinear: return new FillAlignedRectilinear();
|
||||
case ipCrossHatch: return new FillCrossHatch();
|
||||
case ipMonotonic: return new FillMonotonic();
|
||||
case ipLine: return new FillLine();
|
||||
case ipGrid: return new FillGrid();
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#include "../ClipperUtils.hpp"
|
||||
#include "../ShortestPath.hpp"
|
||||
#include "../Surface.hpp"
|
||||
|
||||
#include "FillCrossHatch.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// CrossHatch Infill: Enhances 3D Printing Speed & Reduces Noise
|
||||
// CrossHatch, as its name hints, alternates line direction by 90 degrees every few layers to improve adhesion.
|
||||
// It introduces transform layers between direction shifts for better line cohesion, which fixes the weakness of line infill.
|
||||
// The transform technique is inspired by David Eccles, improved 3D honeycomb but we made a more flexible implementation.
|
||||
// This method notably increases printing speed, meeting the demands of modern high-speed 3D printers, and reduces noise for most layers.
|
||||
// By Bambu Lab
|
||||
|
||||
// graph credits: David Eccles (gringer).
|
||||
// But we made a different definition for points.
|
||||
/* o---o
|
||||
* / \
|
||||
* / \
|
||||
* \ /
|
||||
* \ /
|
||||
* o---o
|
||||
* p1 p2 p3 p4
|
||||
*/
|
||||
|
||||
static Pointfs generate_one_cycle(double progress, coordf_t period)
|
||||
{
|
||||
Pointfs out;
|
||||
double offset = progress * 1. / 8. * period;
|
||||
out.reserve(4);
|
||||
out.push_back(Vec2d(0.25 * period - offset, offset));
|
||||
out.push_back(Vec2d(0.25 * period + offset, offset));
|
||||
out.push_back(Vec2d(0.75 * period - offset, -offset));
|
||||
out.push_back(Vec2d(0.75 * period + offset, -offset));
|
||||
return out;
|
||||
}
|
||||
|
||||
static Polylines generate_transform_pattern(double inprogress, int direction, coordf_t ingrid_size, coordf_t inwidth, coordf_t inheight)
|
||||
{
|
||||
coordf_t width = inwidth;
|
||||
coordf_t height = inheight;
|
||||
coordf_t grid_size = ingrid_size * 2; // we due with odd and even saparately.
|
||||
double progress = inprogress;
|
||||
Polylines out_polylines;
|
||||
|
||||
// generate template patterns;
|
||||
Pointfs one_cycle_points = generate_one_cycle(progress, grid_size);
|
||||
|
||||
Polyline one_cycle;
|
||||
one_cycle.points.reserve(one_cycle_points.size());
|
||||
for (size_t i = 0; i < one_cycle_points.size(); i++) one_cycle.points.push_back(Point(one_cycle_points[i]));
|
||||
|
||||
// swap if vertical
|
||||
if (direction < 0) {
|
||||
width = height;
|
||||
height = inwidth;
|
||||
}
|
||||
|
||||
// replicate polylines;
|
||||
Polylines odd_polylines;
|
||||
Polyline odd_poly;
|
||||
int num_of_cycle = width / grid_size + 2;
|
||||
odd_poly.points.reserve(num_of_cycle * one_cycle.size());
|
||||
|
||||
// replicate to odd line
|
||||
Point translate = Point(0, 0);
|
||||
for (size_t i = 0; i < num_of_cycle; i++) {
|
||||
Polyline odd_points;
|
||||
odd_points = Polyline(one_cycle);
|
||||
odd_points.translate(Point(i * grid_size, 0.0));
|
||||
odd_poly.points.insert(odd_poly.points.end(), odd_points.begin(), odd_points.end());
|
||||
}
|
||||
|
||||
// fill the height
|
||||
int num_of_lines = height / grid_size + 2;
|
||||
odd_polylines.reserve(num_of_lines * odd_poly.size());
|
||||
for (size_t i = 0; i < num_of_lines; i++) {
|
||||
Polyline poly = odd_poly;
|
||||
poly.translate(Point(0.0, grid_size * i));
|
||||
odd_polylines.push_back(poly);
|
||||
}
|
||||
// save to output
|
||||
out_polylines.insert(out_polylines.end(), odd_polylines.begin(), odd_polylines.end());
|
||||
|
||||
// replicate to even lines
|
||||
Polylines even_polylines;
|
||||
even_polylines.reserve(odd_polylines.size());
|
||||
for (size_t i = 0; i < odd_polylines.size(); i++) {
|
||||
Polyline even = odd_poly;
|
||||
even.translate(Point(-0.5 * grid_size, (i + 0.5) * grid_size));
|
||||
even_polylines.push_back(even);
|
||||
}
|
||||
|
||||
// save for output
|
||||
out_polylines.insert(out_polylines.end(), even_polylines.begin(), even_polylines.end());
|
||||
|
||||
// change to vertical if need
|
||||
if (direction < 0) {
|
||||
// swap xy, see if we need better performance method
|
||||
for (Polyline &poly : out_polylines) {
|
||||
for (Point &p : poly) { std::swap(p.x(), p.y()); }
|
||||
}
|
||||
}
|
||||
|
||||
return out_polylines;
|
||||
}
|
||||
|
||||
static Polylines generate_repeat_pattern(int direction, coordf_t grid_size, coordf_t inwidth, coordf_t inheight)
|
||||
{
|
||||
coordf_t width = inwidth;
|
||||
coordf_t height = inheight;
|
||||
Polylines out_polylines;
|
||||
|
||||
// swap if vertical
|
||||
if (direction < 0) {
|
||||
width = height;
|
||||
height = inwidth;
|
||||
}
|
||||
|
||||
int num_of_lines = height / grid_size + 1;
|
||||
out_polylines.reserve(num_of_lines);
|
||||
|
||||
for (int i = 0; i < num_of_lines; i++) {
|
||||
Polyline poly;
|
||||
poly.points.reserve(2);
|
||||
poly.append(Point(coordf_t(0), coordf_t(grid_size * i)));
|
||||
poly.append(Point(width, coordf_t(grid_size * i)));
|
||||
out_polylines.push_back(poly);
|
||||
}
|
||||
|
||||
// change to vertical if needed
|
||||
if (direction < 0) {
|
||||
// swap xy
|
||||
for (Polyline &poly : out_polylines) {
|
||||
for (Point &p : poly) { std::swap(p.x(), p.y()); }
|
||||
}
|
||||
}
|
||||
|
||||
return out_polylines;
|
||||
}
|
||||
|
||||
// it makes the real patterns that overlap the bounding box
|
||||
// repeat_ratio define the ratio between the height of repeat pattern and grid
|
||||
static Polylines generate_infill_layers(coordf_t z_height, double repeat_ratio, coordf_t grid_size, coordf_t width, coordf_t height)
|
||||
{
|
||||
Polylines result;
|
||||
coordf_t trans_layer_size = grid_size * 0.4; // upper.
|
||||
coordf_t repeat_layer_size = grid_size * repeat_ratio; // lower.
|
||||
z_height += repeat_layer_size / 2; // offset to improve first few layer strength
|
||||
coordf_t period = trans_layer_size + repeat_layer_size;
|
||||
coordf_t remains = z_height - std::floor(z_height / period) * period;
|
||||
coordf_t trans_z = remains - repeat_layer_size; // put repeat layer first.
|
||||
coordf_t repeat_z = remains;
|
||||
|
||||
int phase = fmod(z_height, period * 2) - (period - 1); // add epsilon
|
||||
int direction = phase <= 0 ? -1 : 1;
|
||||
|
||||
// this is a repeat layer
|
||||
if (trans_z < 0) {
|
||||
result = generate_repeat_pattern(direction, grid_size, width, height);
|
||||
}
|
||||
// this is a transform layer
|
||||
else {
|
||||
double progress = fmod(trans_z, trans_layer_size) / trans_layer_size;
|
||||
|
||||
// split the progress to forward and backward, with a opposite direction.
|
||||
if (progress < 0.5)
|
||||
result = generate_transform_pattern((progress + 0.1) * 2, direction, grid_size, width, height); // increase overlapping.
|
||||
else
|
||||
result = generate_transform_pattern((1.1 - progress) * 2, -1 * direction, grid_size, width, height);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FillCrossHatch ::_fill_surface_single(
|
||||
const FillParams ¶ms, unsigned int thickness_layers, const std::pair<float, Point> &direction, ExPolygon expolygon, Polylines &polylines_out)
|
||||
{
|
||||
// rotate angle
|
||||
auto infill_angle = float(this->angle);
|
||||
if (std::abs(infill_angle) >= EPSILON) expolygon.rotate(-infill_angle);
|
||||
|
||||
// get the rotated bounding box
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
|
||||
// linespace modifier
|
||||
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
|
||||
|
||||
// reduce density
|
||||
if (params.density < 0.999) line_spacing *= 1.08;
|
||||
|
||||
bb.merge(align_to_grid(bb.min, Point(line_spacing * 4, line_spacing * 4)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = generate_infill_layers(scale_(this->z), 1, line_spacing, bb.size()(0), bb.size()(1));
|
||||
|
||||
// shift the pattern to the actual space
|
||||
for (Polyline &pl : polylines) { pl.translate(bb.min); }
|
||||
|
||||
polylines = intersection_pl(polylines, to_polygons(expolygon));
|
||||
|
||||
// --- remove small remains from gyroid infill
|
||||
if (!polylines.empty()) {
|
||||
// Remove very small bits, but be careful to not remove infill lines connecting thin walls!
|
||||
// The infill perimeter lines should be separated by around a single infill line width.
|
||||
const double minlength = scale_(0.8 * this->spacing);
|
||||
polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline &pl)
|
||||
{ return pl.length() < minlength; }), polylines.end());
|
||||
}
|
||||
|
||||
if (!polylines.empty()) {
|
||||
int infill_start_idx = polylines_out.size(); // only rotate what belongs to us.
|
||||
// connect lines
|
||||
if (params.dont_connect() || polylines.size() <= 1)
|
||||
append(polylines_out, chain_polylines(std::move(polylines)));
|
||||
else
|
||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
|
||||
// rotate back
|
||||
if (std::abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it) it->rotate(infill_angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef slic3r_FillCrossHatch_hpp_
|
||||
#define slic3r_FillCrossHatch_hpp_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../libslic3r.h"
|
||||
|
||||
#include "FillBase.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class FillCrossHatch : public Fill
|
||||
{
|
||||
public:
|
||||
Fill *clone() const override { return new FillCrossHatch(*this); };
|
||||
~FillCrossHatch() override {}
|
||||
|
||||
protected:
|
||||
void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon expolygon,
|
||||
Polylines &polylines_out) override;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_FillCrossHatch_hpp_
|
||||
+106
-18
@@ -21,19 +21,39 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool load_obj(const char *path, TriangleMesh *meshptr, std::string &message)
|
||||
bool load_obj(const char *path, TriangleMesh *meshptr, ObjInfo& obj_info, std::string &message)
|
||||
{
|
||||
if (meshptr == nullptr)
|
||||
return false;
|
||||
|
||||
// Parse the OBJ file.
|
||||
ObjParser::ObjData data;
|
||||
ObjParser::MtlData mtl_data;
|
||||
if (! ObjParser::objparse(path, data)) {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_obj: failed to parse " << path;
|
||||
message = _L("load_obj: failed to parse");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exist_mtl = false;
|
||||
if (data.mtllibs.size() > 0) { // read mtl
|
||||
for (auto mtl_name : data.mtllibs) {
|
||||
boost::filesystem::path full_path(path);
|
||||
std::string dir = full_path.parent_path().string();
|
||||
auto mtl_file = dir + "/" + mtl_name;
|
||||
boost::filesystem::path mtl_path(mtl_file);
|
||||
auto _mtl_path = mtl_path.string().c_str();
|
||||
if (boost::filesystem::exists(mtl_path)) {
|
||||
if (!ObjParser::mtlparse(_mtl_path, mtl_data)) {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_obj:load_mtl: failed to parse " << _mtl_path;
|
||||
message = _L("load mtl in obj: failed to parse");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_obj: failed to load mtl_path:" << _mtl_path;
|
||||
}
|
||||
}
|
||||
exist_mtl = true;
|
||||
}
|
||||
// Count the faces and verify, that all faces are triangular.
|
||||
size_t num_faces = 0;
|
||||
size_t num_quads = 0;
|
||||
@@ -59,17 +79,27 @@ bool load_obj(const char *path, TriangleMesh *meshptr, std::string &message)
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert ObjData into indexed triangle set.
|
||||
indexed_triangle_set its;
|
||||
size_t num_vertices = data.coordinates.size() / 4;
|
||||
size_t num_vertices = data.coordinates.size() / OBJ_VERTEX_LENGTH;
|
||||
its.vertices.reserve(num_vertices);
|
||||
its.indices.reserve(num_faces + num_quads);
|
||||
for (size_t i = 0; i < num_vertices; ++ i) {
|
||||
size_t j = i << 2;
|
||||
its.vertices.emplace_back(data.coordinates[j], data.coordinates[j + 1], data.coordinates[j + 2]);
|
||||
if (exist_mtl) {
|
||||
obj_info.is_single_mtl = data.usemtls.size() == 1 && mtl_data.new_mtl_unmap.size() == 1;
|
||||
obj_info.face_colors.reserve(num_faces + num_quads);
|
||||
}
|
||||
int indices[4];
|
||||
bool has_color = data.has_vertex_color;
|
||||
for (size_t i = 0; i < num_vertices; ++ i) {
|
||||
size_t j = i * OBJ_VERTEX_LENGTH;
|
||||
its.vertices.emplace_back(data.coordinates[j], data.coordinates[j + 1], data.coordinates[j + 2]);
|
||||
if (data.has_vertex_color) {
|
||||
RGBA color{std::clamp(data.coordinates[j + 3], 0.f, 1.f), std::clamp(data.coordinates[j + 4], 0.f, 1.f), std::clamp(data.coordinates[j + 5], 0.f, 1.f),
|
||||
std::clamp(data.coordinates[j + 6], 0.f, 1.f)};
|
||||
obj_info.vertex_colors.emplace_back(color);
|
||||
}
|
||||
}
|
||||
int indices[ONE_FACE_SIZE];
|
||||
int uvs[ONE_FACE_SIZE];
|
||||
for (size_t i = 0; i < data.vertices.size();)
|
||||
if (data.vertices[i].coordIdx == -1)
|
||||
++ i;
|
||||
@@ -79,20 +109,79 @@ bool load_obj(const char *path, TriangleMesh *meshptr, std::string &message)
|
||||
if (const ObjParser::ObjVertex &vertex = data.vertices[i ++]; vertex.coordIdx == -1) {
|
||||
break;
|
||||
} else {
|
||||
assert(cnt < 4);
|
||||
assert(cnt < OBJ_VERTEX_LENGTH);
|
||||
if (vertex.coordIdx < 0 || vertex.coordIdx >= int(its.vertices.size())) {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_obj: failed to parse " << path << ". The file contains invalid vertex index.";
|
||||
message = _L("The file contains invalid vertex index.");
|
||||
return false;
|
||||
}
|
||||
indices[cnt ++] = vertex.coordIdx;
|
||||
indices[cnt] = vertex.coordIdx;
|
||||
uvs[cnt] = vertex.textureCoordIdx;
|
||||
cnt++;
|
||||
}
|
||||
if (cnt) {
|
||||
assert(cnt == 3 || cnt == 4);
|
||||
// Insert one or two faces (triangulate a quad).
|
||||
its.indices.emplace_back(indices[0], indices[1], indices[2]);
|
||||
if (cnt == 4)
|
||||
int face_index =its.indices.size() - 1;
|
||||
RGBA face_color;
|
||||
auto set_face_color = [&uvs, &data, &mtl_data, &obj_info, &face_color](int face_index, const std::string mtl_name) {
|
||||
if (mtl_data.new_mtl_unmap.find(mtl_name) != mtl_data.new_mtl_unmap.end()) {
|
||||
bool is_merge_ka_kd = true;
|
||||
for (size_t n = 0; n < 3; n++) {
|
||||
if (float(mtl_data.new_mtl_unmap[mtl_name]->Ka[n] + mtl_data.new_mtl_unmap[mtl_name]->Kd[n]) > 1.0) {
|
||||
is_merge_ka_kd=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (size_t n = 0; n < 3; n++) {
|
||||
if (is_merge_ka_kd) {
|
||||
face_color[n] = std::clamp(float(mtl_data.new_mtl_unmap[mtl_name]->Ka[n] + mtl_data.new_mtl_unmap[mtl_name]->Kd[n]), 0.f, 1.f);
|
||||
}
|
||||
else {
|
||||
face_color[n] = std::clamp(float(mtl_data.new_mtl_unmap[mtl_name]->Kd[n]), 0.f, 1.f);
|
||||
}
|
||||
}
|
||||
face_color[3] = mtl_data.new_mtl_unmap[mtl_name]->Tr; // alpha
|
||||
if (mtl_data.new_mtl_unmap[mtl_name]->map_Kd.size() > 0) {
|
||||
auto png_name = mtl_data.new_mtl_unmap[mtl_name]->map_Kd;
|
||||
obj_info.has_uv_png = true;
|
||||
if (obj_info.pngs.find(png_name) == obj_info.pngs.end()) { obj_info.pngs[png_name] = false; }
|
||||
obj_info.uv_map_pngs[face_index] = png_name;
|
||||
}
|
||||
if (data.textureCoordinates.size() > 0) {
|
||||
Vec2f uv0(data.textureCoordinates[uvs[0] * 2], data.textureCoordinates[uvs[0] * 2 + 1]);
|
||||
Vec2f uv1(data.textureCoordinates[uvs[1] * 2], data.textureCoordinates[uvs[1] * 2 + 1]);
|
||||
Vec2f uv2(data.textureCoordinates[uvs[2] * 2], data.textureCoordinates[uvs[2] * 2 + 1]);
|
||||
std::array<Vec2f, 3> uv_array{uv0, uv1, uv2};
|
||||
obj_info.uvs.emplace_back(uv_array);
|
||||
}
|
||||
obj_info.face_colors.emplace_back(face_color);
|
||||
}
|
||||
};
|
||||
auto set_face_color_by_mtl = [&data, &set_face_color](int face_index) {
|
||||
if (data.usemtls.size() == 1) {
|
||||
set_face_color(face_index, data.usemtls[0].name);
|
||||
} else {
|
||||
for (size_t k = 0; k < data.usemtls.size(); k++) {
|
||||
auto mtl = data.usemtls[k];
|
||||
if (face_index >= mtl.face_start && face_index <= mtl.face_end) {
|
||||
set_face_color(face_index, data.usemtls[k].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (exist_mtl) {
|
||||
set_face_color_by_mtl(face_index);
|
||||
}
|
||||
if (cnt == 4) {
|
||||
its.indices.emplace_back(indices[0], indices[2], indices[3]);
|
||||
int face_index = its.indices.size() - 1;
|
||||
if (exist_mtl) {
|
||||
set_face_color_by_mtl(face_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,12 +196,12 @@ bool load_obj(const char *path, TriangleMesh *meshptr, std::string &message)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_obj(const char *path, Model *model, std::string &message, const char *object_name_in)
|
||||
bool load_obj(const char *path, Model *model, ObjInfo& obj_info, std::string &message, const char *object_name_in)
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
|
||||
bool ret = load_obj(path, &mesh, message);
|
||||
|
||||
|
||||
bool ret = load_obj(path, &mesh, obj_info, message);
|
||||
|
||||
if (ret) {
|
||||
std::string object_name;
|
||||
if (object_name_in == nullptr) {
|
||||
@@ -120,10 +209,9 @@ bool load_obj(const char *path, Model *model, std::string &message, const char *
|
||||
object_name.assign((last_slash == nullptr) ? path : last_slash + 1);
|
||||
} else
|
||||
object_name.assign(object_name_in);
|
||||
|
||||
model->add_object(object_name.c_str(), path, std::move(mesh));
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
#ifndef slic3r_Format_OBJ_hpp_
|
||||
#define slic3r_Format_OBJ_hpp_
|
||||
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include <unordered_map>
|
||||
namespace Slic3r {
|
||||
|
||||
class TriangleMesh;
|
||||
class Model;
|
||||
class ModelObject;
|
||||
|
||||
typedef std::function<void(std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids, unsigned char &first_extruder_id)> ObjImportColorFn;
|
||||
// Load an OBJ file into a provided model.
|
||||
extern bool load_obj(const char *path, TriangleMesh *mesh, std::string &message);
|
||||
extern bool load_obj(const char *path, Model *model, std::string &message, const char *object_name = nullptr);
|
||||
struct ObjInfo {
|
||||
std::vector<RGBA> vertex_colors;
|
||||
std::vector<RGBA> face_colors;
|
||||
bool is_single_mtl{false};
|
||||
std::vector<std::array<Vec2f,3>> uvs;
|
||||
std::string obj_dircetory;
|
||||
std::map<std::string,bool> pngs;
|
||||
std::unordered_map<int, std::string> uv_map_pngs;
|
||||
bool has_uv_png{false};
|
||||
|
||||
};
|
||||
extern bool load_obj(const char *path, TriangleMesh *mesh, ObjInfo &vertex_colors, std::string &message);
|
||||
extern bool load_obj(const char *path, Model *model, ObjInfo &vertex_colors, std::string &message, const char *object_name = nullptr);
|
||||
|
||||
extern bool store_obj(const char *path, TriangleMesh *mesh);
|
||||
extern bool store_obj(const char *path, ModelObject *model);
|
||||
|
||||
@@ -213,6 +213,7 @@ static constexpr const char* FILAMENT_TYPE_TAG = "type";
|
||||
static constexpr const char *FILAMENT_COLOR_TAG = "color";
|
||||
static constexpr const char *FILAMENT_USED_M_TAG = "used_m";
|
||||
static constexpr const char *FILAMENT_USED_G_TAG = "used_g";
|
||||
static constexpr const char *FILAMENT_TRAY_INFO_ID_TAG = "tray_info_idx";
|
||||
|
||||
|
||||
static constexpr const char* CONFIG_TAG = "config";
|
||||
@@ -586,21 +587,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return ret;
|
||||
};
|
||||
|
||||
for (auto it = ps.volumes_per_extruder.begin(); it != ps.volumes_per_extruder.end(); it++) {
|
||||
for (auto it = ps.total_volumes_per_extruder.begin(); it != ps.total_volumes_per_extruder.end(); it++) {
|
||||
double volume = it->second;
|
||||
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, it->first);
|
||||
|
||||
FilamentInfo info;
|
||||
info.id = it->first;
|
||||
if (ps.flush_per_filament.find(it->first) != ps.flush_per_filament.end()) {
|
||||
volume = ps.flush_per_filament.at(it->first);
|
||||
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, it->first);
|
||||
info.used_m = used_filament_m + flushed_filament_m;
|
||||
info.used_g = used_filament_g + flushed_filament_g;
|
||||
} else {
|
||||
info.used_m = used_filament_m;
|
||||
info.used_g = used_filament_g;
|
||||
}
|
||||
info.used_g = used_filament_g;
|
||||
info.used_m = used_filament_m;
|
||||
slice_filaments_info.push_back(info);
|
||||
}
|
||||
|
||||
@@ -4231,13 +4225,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
std::string color = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_COLOR_TAG);
|
||||
std::string used_m = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_M_TAG);
|
||||
std::string used_g = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_G_TAG);
|
||||
|
||||
std::string filament_id = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_TRAY_INFO_ID_TAG);
|
||||
FilamentInfo filament_info;
|
||||
filament_info.id = atoi(id.c_str()) - 1;
|
||||
filament_info.type = type;
|
||||
filament_info.color = color;
|
||||
filament_info.used_m = atof(used_m.c_str());
|
||||
filament_info.used_g = atof(used_g.c_str());
|
||||
filament_info.filament_id = filament_id;
|
||||
m_curr_plater->slice_filaments_info.push_back(filament_info);
|
||||
}
|
||||
return true;
|
||||
@@ -7659,6 +7654,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++)
|
||||
{
|
||||
stream << " <" << FILAMENT_TAG << " " << FILAMENT_ID_TAG << "=\"" << std::to_string(it->id + 1) << "\" "
|
||||
<< FILAMENT_TRAY_INFO_ID_TAG <<"=\""<< it->filament_id <<"\" "
|
||||
<< FILAMENT_TYPE_TAG << "=\"" << it->type << "\" "
|
||||
<< FILAMENT_COLOR_TAG << "=\"" << it->color << "\" "
|
||||
<< FILAMENT_USED_M_TAG << "=\"" << it->used_m << "\" "
|
||||
|
||||
@@ -9,16 +9,12 @@
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
|
||||
namespace ObjParser {
|
||||
|
||||
#define EATWS() while (*line == ' ' || *line == '\t') ++line
|
||||
static bool obj_parseline(const char *line, ObjData &data)
|
||||
{
|
||||
#define EATWS() while (*line == ' ' || *line == '\t') ++ line
|
||||
|
||||
if (*line == 0)
|
||||
return true;
|
||||
|
||||
assert(Slic3r::is_decimal_separator_point());
|
||||
|
||||
// Ignore whitespaces at the beginning of the line.
|
||||
//FIXME is this a good idea?
|
||||
EATWS();
|
||||
@@ -55,19 +51,19 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
line = endptr;
|
||||
EATWS();
|
||||
}
|
||||
double w = 0;
|
||||
/*double w = 0;
|
||||
if (*line != 0) {
|
||||
w = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
}
|
||||
}*/
|
||||
if (*line != 0)
|
||||
return false;
|
||||
data.textureCoordinates.push_back((float)u);
|
||||
data.textureCoordinates.push_back((float)v);
|
||||
data.textureCoordinates.push_back((float)w);
|
||||
//data.textureCoordinates.push_back((float)w);
|
||||
break;
|
||||
}
|
||||
case 'n':
|
||||
@@ -156,23 +152,46 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double w = 1.0;
|
||||
if (*line != 0) {
|
||||
w = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double color_x = 0.0, color_y = 0.0, color_z = 0.0, color_w = 0.0;//undefine color
|
||||
if (*line != 0) {
|
||||
if (!data.has_vertex_color) {
|
||||
data.has_vertex_color = true;
|
||||
}
|
||||
color_x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
color_y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
color_z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
|
||||
return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
color_w = 1.0;//default define alpha = 1.0
|
||||
if (*line != 0) {
|
||||
color_w = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
}
|
||||
}
|
||||
// the following check is commented out because there may be obj files containing extra data, as those generated by Meshlab,
|
||||
// see https://dev.prusa3d.com/browse/SPE-1019 for an example,
|
||||
// and this would lead to a crash because no vertex would be stored
|
||||
// and this would lead to a crash because no vertex would be stored
|
||||
// if (*line != 0)
|
||||
// return false;
|
||||
data.coordinates.push_back((float)x);
|
||||
data.coordinates.push_back((float)y);
|
||||
data.coordinates.push_back((float)z);
|
||||
data.coordinates.push_back((float)w);
|
||||
data.coordinates.push_back((float) color_x);
|
||||
data.coordinates.push_back((float) color_y);
|
||||
data.coordinates.push_back((float) color_z);
|
||||
data.coordinates.push_back((float) color_w);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -232,6 +251,24 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
data.vertices.push_back(vertex);
|
||||
EATWS();
|
||||
}
|
||||
if (data.usemtls.size() > 0) {
|
||||
data.usemtls.back().vertexIdxEnd = (int) data.vertices.size();
|
||||
}
|
||||
if (data.usemtls.size() > 0) {
|
||||
int face_index_count = 0;
|
||||
for (int i = data.vertices.size() - 1; i >= 0; i--) {
|
||||
if (data.vertices[i].coordIdx == -1) {
|
||||
break;
|
||||
}
|
||||
face_index_count++;
|
||||
}
|
||||
if (face_index_count == 3) {//tri
|
||||
data.usemtls.back().face_end++;
|
||||
} else if (face_index_count == 4) {//quad
|
||||
data.usemtls.back().face_end++;
|
||||
data.usemtls.back().face_end++;
|
||||
}
|
||||
}
|
||||
vertex.coordIdx = -1;
|
||||
vertex.normalIdx = -1;
|
||||
vertex.textureCoordIdx = -1;
|
||||
@@ -263,10 +300,23 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
// usemtl [material name]
|
||||
// printf("usemtl %s\r\n", line);
|
||||
EATWS();
|
||||
if (data.usemtls.size()>0) {
|
||||
data.usemtls.back().vertexIdxEnd = (int) data.vertices.size();
|
||||
}
|
||||
ObjUseMtl usemtl;
|
||||
usemtl.vertexIdxFirst = (int)data.vertices.size();
|
||||
usemtl.name = line;
|
||||
data.usemtls.push_back(usemtl);
|
||||
if (data.usemtls.size() == 1) {
|
||||
data.usemtls.back().face_start = 0;
|
||||
}
|
||||
else {//>=2
|
||||
auto count = data.usemtls.size();
|
||||
auto& last_usemtl = data.usemtls[count-1];
|
||||
auto& last_last_usemtl = data.usemtls[count - 2];
|
||||
last_usemtl.face_start = last_last_usemtl.face_end + 1;
|
||||
}
|
||||
data.usemtls.back().face_end = data.usemtls.back().face_start - 1;
|
||||
break;
|
||||
}
|
||||
case 'o':
|
||||
@@ -323,6 +373,197 @@ static bool obj_parseline(const char *line, ObjData &data)
|
||||
|
||||
return true;
|
||||
}
|
||||
static std::string cur_mtl_name = "";
|
||||
static bool mtl_parseline(const char *line, MtlData &data)
|
||||
{
|
||||
if (*line == 0) return true;
|
||||
assert(Slic3r::is_decimal_separator_point());
|
||||
// Ignore whitespaces at the beginning of the line.
|
||||
// FIXME is this a good idea?
|
||||
EATWS();
|
||||
|
||||
char c1 = *line++;
|
||||
switch (c1) {
|
||||
case '#': {// Comment, ignore the rest of the line.
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
if (*(line++) != 'e' || *(line++) != 'w' || *(line++) != 'm' || *(line++) != 't' || *(line++) != 'l')
|
||||
return false;
|
||||
EATWS();
|
||||
ObjNewMtl new_mtl;
|
||||
cur_mtl_name = line;
|
||||
data.new_mtl_unmap[cur_mtl_name] = std::make_shared<ObjNewMtl>();
|
||||
break;
|
||||
}
|
||||
case 'm': {
|
||||
if (*(line++) != 'a' || *(line++) != 'p' || *(line++) != '_' || *(line++) != 'K' || *(line++) != 'd') return false;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->map_Kd = line;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'N': {
|
||||
char cur_char = *(line++);
|
||||
if (cur_char == 's') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double ns = strtod(line, &endptr);
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ns = (float) ns;
|
||||
}
|
||||
} else if (cur_char == 'i') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double ni = strtod(line, &endptr);
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ni = (float) ni;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'K': {
|
||||
char cur_char = *(line++);
|
||||
if (cur_char == 'a') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ka[0] = x;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ka[1] = y;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ka[2] = z;
|
||||
}
|
||||
} else if (cur_char == 'd') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Kd[0] = x;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Kd[1] = y;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Kd[2] = z;
|
||||
}
|
||||
} else if (cur_char == 's') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ks[0] = x;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ks[1] = y;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ks[2] = z;
|
||||
}
|
||||
} else if (cur_char == 'e') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ke[0] = x;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ke[1] = y;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Ke[2] = z;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
if (*(line++) != 'l' || *(line++) != 'l' || *(line++) != 'u' || *(line++) != 'm')
|
||||
return false;
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double illum = strtod(line, &endptr);
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->illum = (float) illum;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double d = strtod(line, &endptr);
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->d = (float) d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'T': {
|
||||
char cur_char = *(line++);
|
||||
if (cur_char == 'r') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double tr = strtod(line, &endptr);
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Tr = (float) tr;
|
||||
}
|
||||
break;
|
||||
} else if (cur_char == 'f') {
|
||||
EATWS();
|
||||
char * endptr = 0;
|
||||
double x = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double y = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t')) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
double z = strtod(line, &endptr);
|
||||
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0)) return false;
|
||||
line = endptr;
|
||||
EATWS();
|
||||
if (data.new_mtl_unmap.find(cur_mtl_name) != data.new_mtl_unmap.end()) {
|
||||
data.new_mtl_unmap[cur_mtl_name]->Tf[0] = x;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Tf[1] = y;
|
||||
data.new_mtl_unmap[cur_mtl_name]->Tf[2] = z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objparse(const char *path, ObjData &data)
|
||||
{
|
||||
@@ -369,10 +610,52 @@ bool objparse(const char *path, ObjData &data)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mtlparse(const char *path, MtlData &data)
|
||||
{
|
||||
Slic3r::CNumericLocalesSetter locales_setter;
|
||||
|
||||
FILE *pFile = boost::nowide::fopen(path, "rt");
|
||||
if (pFile == 0) return false;
|
||||
cur_mtl_name = "";
|
||||
try {
|
||||
char buf[65536 * 2];
|
||||
size_t len = 0;
|
||||
size_t lenPrev = 0;
|
||||
while ((len = ::fread(buf + lenPrev, 1, 65536, pFile)) != 0) {
|
||||
len += lenPrev;
|
||||
size_t lastLine = 0;
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
if (buf[i] == '\r' || buf[i] == '\n') {
|
||||
buf[i] = 0;
|
||||
char *c = buf + lastLine;
|
||||
while (*c == ' ' || *c == '\t') ++c;
|
||||
// FIXME check the return value and exit on error?
|
||||
// Will it break parsing of some obj files?
|
||||
mtl_parseline(c, data);
|
||||
lastLine = i + 1;
|
||||
}
|
||||
lenPrev = len - lastLine;
|
||||
if (lenPrev > 65536) {
|
||||
BOOST_LOG_TRIVIAL(error) << "MtlParser: Excessive line length";
|
||||
::fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
memmove(buf, buf + lastLine, lenPrev);
|
||||
}
|
||||
} catch (std::bad_alloc &) {
|
||||
BOOST_LOG_TRIVIAL(error) << "MtlParser: Out of memory";
|
||||
}
|
||||
::fclose(pFile);
|
||||
|
||||
// printf("vertices: %d\r\n", data.vertices.size() / 4);
|
||||
// printf("coords: %d\r\n", data.coordinates.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objparse(std::istream &stream, ObjData &data)
|
||||
{
|
||||
Slic3r::CNumericLocalesSetter locales_setter;
|
||||
|
||||
|
||||
try {
|
||||
char buf[65536 * 2];
|
||||
size_t len = 0;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <istream>
|
||||
|
||||
namespace ObjParser {
|
||||
@@ -16,22 +18,39 @@ struct ObjVertex
|
||||
|
||||
inline bool operator==(const ObjVertex &v1, const ObjVertex &v2)
|
||||
{
|
||||
return
|
||||
v1.coordIdx == v2.coordIdx &&
|
||||
v1.textureCoordIdx == v2.textureCoordIdx &&
|
||||
return v1.coordIdx == v2.coordIdx &&
|
||||
v1.textureCoordIdx == v2.textureCoordIdx &&
|
||||
v1.normalIdx == v2.normalIdx;
|
||||
}
|
||||
|
||||
struct ObjUseMtl
|
||||
{
|
||||
int vertexIdxFirst;
|
||||
int vertexIdxEnd{-1};
|
||||
int face_start;
|
||||
int face_end{-1};
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct ObjNewMtl
|
||||
{
|
||||
std::string name;
|
||||
float Ns;
|
||||
float Ni;
|
||||
float d;
|
||||
float illum;
|
||||
float Tr{1.0f}; // Transmission
|
||||
std::array<float, 3> Tf;
|
||||
std::array<float, 3> Ka;
|
||||
std::array<float, 3> Kd;
|
||||
std::array<float, 3> Ks;
|
||||
std::array<float, 3> Ke;
|
||||
std::string map_Kd;//defalut png
|
||||
};
|
||||
|
||||
inline bool operator==(const ObjUseMtl &v1, const ObjUseMtl &v2)
|
||||
{
|
||||
return
|
||||
v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
return v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
v1.name.compare(v2.name) == 0;
|
||||
}
|
||||
|
||||
@@ -56,8 +75,7 @@ struct ObjGroup
|
||||
|
||||
inline bool operator==(const ObjGroup &v1, const ObjGroup &v2)
|
||||
{
|
||||
return
|
||||
v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
return v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
v1.name.compare(v2.name) == 0;
|
||||
}
|
||||
|
||||
@@ -69,17 +87,19 @@ struct ObjSmoothingGroup
|
||||
|
||||
inline bool operator==(const ObjSmoothingGroup &v1, const ObjSmoothingGroup &v2)
|
||||
{
|
||||
return
|
||||
v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
return v1.vertexIdxFirst == v2.vertexIdxFirst &&
|
||||
v1.smoothingGroupID == v2.smoothingGroupID;
|
||||
}
|
||||
|
||||
#define OBJ_VERTEX_COLOR_ALPHA 6
|
||||
#define OBJ_VERTEX_LENGTH 7 // x, y, z, color_x,color_y,color_z,color_w
|
||||
#define ONE_FACE_SIZE 4//ONE_FACE format: f 8/4/6 7/3/6 6/2/6 -1/-1/-1
|
||||
struct ObjData {
|
||||
// Version of the data structure for load / store in the private binary format.
|
||||
int version;
|
||||
|
||||
// x, y, z, w
|
||||
// x, y, z, color_x,color_y,color_z,color_w
|
||||
std::vector<float> coordinates;
|
||||
bool has_vertex_color{false};
|
||||
// u, v, w
|
||||
std::vector<float> textureCoordinates;
|
||||
// x, y, z
|
||||
@@ -97,7 +117,14 @@ struct ObjData {
|
||||
std::vector<ObjVertex> vertices;
|
||||
};
|
||||
|
||||
struct MtlData
|
||||
{
|
||||
// Version of the data structure for load / store in the private binary format.
|
||||
int version;
|
||||
std::unordered_map<std::string, std::shared_ptr<ObjNewMtl>> new_mtl_unmap;
|
||||
};
|
||||
extern bool objparse(const char *path, ObjData &data);
|
||||
extern bool mtlparse(const char *path, MtlData &data);
|
||||
extern bool objparse(std::istream &stream, ObjData &data);
|
||||
|
||||
extern bool objbinsave(const char *path, const ObjData &data);
|
||||
|
||||
+2
-46
@@ -1382,52 +1382,8 @@ namespace DoExport {
|
||||
double total_used_filament = 0.0;
|
||||
double total_weight = 0.0;
|
||||
double total_cost = 0.0;
|
||||
for (auto volume : result.print_statistics.volumes_per_extruder) {
|
||||
total_extruded_volume += volume.second;
|
||||
|
||||
size_t extruder_id = volume.first;
|
||||
auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) { return extr.id() == extruder_id; });
|
||||
if (extruder == extruders.end())
|
||||
continue;
|
||||
|
||||
double s = PI * sqr(0.5* extruder->filament_diameter());
|
||||
double weight = volume.second * extruder->filament_density() * 0.001;
|
||||
total_used_filament += volume.second/s;
|
||||
total_weight += weight;
|
||||
total_cost += weight * extruder->filament_cost() * 0.001;
|
||||
}
|
||||
//BBS: add flush volume
|
||||
for (auto volume : result.print_statistics.flush_per_filament) {
|
||||
total_extruded_volume += volume.second;
|
||||
|
||||
size_t extruder_id = volume.first;
|
||||
auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) { return extr.id() == extruder_id; });
|
||||
if (extruder == extruders.end())
|
||||
continue;
|
||||
|
||||
double s = PI * sqr(0.5* extruder->filament_diameter());
|
||||
double weight = volume.second * extruder->filament_density() * 0.001;
|
||||
total_used_filament += volume.second/s;
|
||||
total_weight += weight;
|
||||
total_cost += weight * extruder->filament_cost() * 0.001;
|
||||
}
|
||||
|
||||
for (auto volume : result.print_statistics.wipe_tower_volumes_per_extruder) {
|
||||
total_extruded_volume += volume.second;
|
||||
|
||||
size_t extruder_id = volume.first;
|
||||
auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) {return extr.id() == extruder_id; });
|
||||
if (extruder == extruders.end())
|
||||
continue;
|
||||
|
||||
double s = PI * sqr(0.5* extruder->filament_diameter());
|
||||
double weight = volume.second * extruder->filament_density() * 0.001;
|
||||
total_used_filament += volume.second/s;
|
||||
total_weight += weight;
|
||||
total_cost += weight * extruder->filament_cost() * 0.001;
|
||||
}
|
||||
|
||||
for (auto volume : result.print_statistics.support_volumes_per_extruder) {
|
||||
for (auto volume : result.print_statistics.total_volumes_per_extruder) {
|
||||
total_extruded_volume += volume.second;
|
||||
|
||||
size_t extruder_id = volume.first;
|
||||
@@ -1447,7 +1403,7 @@ namespace DoExport {
|
||||
print_statistics.total_weight = total_weight;
|
||||
print_statistics.total_cost = total_cost;
|
||||
|
||||
print_statistics.filament_stats = result.print_statistics.volumes_per_extruder;
|
||||
print_statistics.filament_stats = result.print_statistics.model_volumes_per_extruder;
|
||||
}
|
||||
|
||||
// if any reserved keyword is found, returns a std::vector containing the first MAX_COUNT keywords found
|
||||
|
||||
@@ -753,7 +753,7 @@ void GCodeProcessor::UsedFilaments::reset()
|
||||
volumes_per_color_change = std::vector<double>();
|
||||
|
||||
model_extrude_cache = 0.0f;
|
||||
volumes_per_extruder.clear();
|
||||
model_volumes_per_extruder.clear();
|
||||
|
||||
flush_per_filament.clear();
|
||||
|
||||
@@ -761,16 +761,20 @@ void GCodeProcessor::UsedFilaments::reset()
|
||||
filaments_per_role.clear();
|
||||
|
||||
wipe_tower_cache = 0.0f;
|
||||
wipe_tower_volume_per_extruder.clear();
|
||||
wipe_tower_volumes_per_extruder.clear();
|
||||
|
||||
support_volume_cache = 0.0f;
|
||||
support_volume_per_extruder.clear();
|
||||
support_volumes_per_extruder.clear();
|
||||
|
||||
total_volume_cache = 0.0f;
|
||||
total_volumes_per_extruder.clear();
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::increase_support_caches(double extruded_volume)
|
||||
{
|
||||
support_volume_cache += extruded_volume;
|
||||
role_cache += extruded_volume;
|
||||
total_volume_cache += extruded_volume;
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::increase_model_caches(double extruded_volume)
|
||||
@@ -778,12 +782,14 @@ void GCodeProcessor::UsedFilaments::increase_model_caches(double extruded_volume
|
||||
color_change_cache += extruded_volume;
|
||||
model_extrude_cache += extruded_volume;
|
||||
role_cache += extruded_volume;
|
||||
total_volume_cache += extruded_volume;
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::increase_wipe_tower_caches(double extruded_volume)
|
||||
{
|
||||
wipe_tower_cache += extruded_volume;
|
||||
role_cache += extruded_volume;
|
||||
total_volume_cache += extruded_volume;
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_color_change_cache()
|
||||
@@ -794,14 +800,27 @@ void GCodeProcessor::UsedFilaments::process_color_change_cache()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_total_volume_cache(GCodeProcessor* processor)
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (total_volume_cache!= 0.0f) {
|
||||
if (total_volumes_per_extruder.find(active_extruder_id) != total_volumes_per_extruder.end())
|
||||
total_volumes_per_extruder[active_extruder_id] += total_volume_cache;
|
||||
else
|
||||
total_volumes_per_extruder[active_extruder_id] = total_volume_cache;
|
||||
total_volume_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_model_cache(GCodeProcessor* processor)
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (model_extrude_cache != 0.0f) {
|
||||
if (volumes_per_extruder.find(active_extruder_id) != volumes_per_extruder.end())
|
||||
volumes_per_extruder[active_extruder_id] += model_extrude_cache;
|
||||
if (model_volumes_per_extruder.find(active_extruder_id) != model_volumes_per_extruder.end())
|
||||
model_volumes_per_extruder[active_extruder_id] += model_extrude_cache;
|
||||
else
|
||||
volumes_per_extruder[active_extruder_id] = model_extrude_cache;
|
||||
model_volumes_per_extruder[active_extruder_id] = model_extrude_cache;
|
||||
model_extrude_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -810,10 +829,10 @@ void GCodeProcessor::UsedFilaments::process_wipe_tower_cache(GCodeProcessor* pro
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (wipe_tower_cache != 0.0f) {
|
||||
if (wipe_tower_volume_per_extruder.find(active_extruder_id) != wipe_tower_volume_per_extruder.end())
|
||||
wipe_tower_volume_per_extruder[active_extruder_id] += wipe_tower_cache;
|
||||
if (wipe_tower_volumes_per_extruder.find(active_extruder_id) != wipe_tower_volumes_per_extruder.end())
|
||||
wipe_tower_volumes_per_extruder[active_extruder_id] += wipe_tower_cache;
|
||||
else
|
||||
wipe_tower_volume_per_extruder[active_extruder_id] = wipe_tower_cache;
|
||||
wipe_tower_volumes_per_extruder[active_extruder_id] = wipe_tower_cache;
|
||||
wipe_tower_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -822,20 +841,27 @@ void GCodeProcessor::UsedFilaments::process_support_cache(GCodeProcessor* proces
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (support_volume_cache != 0.0f){
|
||||
if (support_volume_per_extruder.find(active_extruder_id) != support_volume_per_extruder.end())
|
||||
support_volume_per_extruder[active_extruder_id] += support_volume_cache;
|
||||
if (support_volumes_per_extruder.find(active_extruder_id) != support_volumes_per_extruder.end())
|
||||
support_volumes_per_extruder[active_extruder_id] += support_volume_cache;
|
||||
else
|
||||
support_volume_per_extruder[active_extruder_id] = support_volume_cache;
|
||||
support_volumes_per_extruder[active_extruder_id] = support_volume_cache;
|
||||
support_volume_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::update_flush_per_filament(size_t extrude_id, float flush_volume)
|
||||
{
|
||||
if (flush_per_filament.find(extrude_id) != flush_per_filament.end())
|
||||
flush_per_filament[extrude_id] += flush_volume;
|
||||
else
|
||||
flush_per_filament[extrude_id] = flush_volume;
|
||||
if (flush_volume != 0.f) {
|
||||
if (flush_per_filament.find(extrude_id) != flush_per_filament.end())
|
||||
flush_per_filament[extrude_id] += flush_volume;
|
||||
else
|
||||
flush_per_filament[extrude_id] = flush_volume;
|
||||
|
||||
if (total_volumes_per_extruder.find(extrude_id) != total_volumes_per_extruder.end())
|
||||
total_volumes_per_extruder[extrude_id] += flush_volume;
|
||||
else
|
||||
total_volumes_per_extruder[extrude_id] = flush_volume;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_role_cache(GCodeProcessor* processor)
|
||||
@@ -865,6 +891,7 @@ void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor)
|
||||
process_role_cache(processor);
|
||||
process_wipe_tower_cache(processor);
|
||||
process_support_cache(processor);
|
||||
process_total_volume_cache(processor);
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
@@ -4542,6 +4569,7 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code)
|
||||
if (code == CustomGCode::ToolChange) {
|
||||
m_used_filaments.process_model_cache(this);
|
||||
m_used_filaments.process_support_cache(this);
|
||||
m_used_filaments.process_total_volume_cache(this);
|
||||
//BBS: reset remaining filament
|
||||
m_remaining_volume = m_nozzle_volume;
|
||||
}
|
||||
@@ -4573,11 +4601,12 @@ void GCodeProcessor::update_estimated_times_stats()
|
||||
m_result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].reset();
|
||||
|
||||
m_result.print_statistics.volumes_per_color_change = m_used_filaments.volumes_per_color_change;
|
||||
m_result.print_statistics.volumes_per_extruder = m_used_filaments.volumes_per_extruder;
|
||||
m_result.print_statistics.wipe_tower_volumes_per_extruder = m_used_filaments.wipe_tower_volume_per_extruder;
|
||||
m_result.print_statistics.support_volumes_per_extruder = m_used_filaments.support_volume_per_extruder;
|
||||
m_result.print_statistics.model_volumes_per_extruder = m_used_filaments.model_volumes_per_extruder;
|
||||
m_result.print_statistics.wipe_tower_volumes_per_extruder = m_used_filaments.wipe_tower_volumes_per_extruder;
|
||||
m_result.print_statistics.support_volumes_per_extruder = m_used_filaments.support_volumes_per_extruder;
|
||||
m_result.print_statistics.flush_per_filament = m_used_filaments.flush_per_filament;
|
||||
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
|
||||
m_result.print_statistics.total_volumes_per_extruder = m_used_filaments.total_volumes_per_extruder;
|
||||
}
|
||||
|
||||
//BBS: ugly code...
|
||||
@@ -4587,8 +4616,8 @@ void GCodeProcessor::update_slice_warnings()
|
||||
|
||||
auto get_used_extruders = [this]() {
|
||||
std::vector<size_t> used_extruders;
|
||||
used_extruders.reserve(m_used_filaments.volumes_per_extruder.size());
|
||||
for (auto item : m_used_filaments.volumes_per_extruder) {
|
||||
used_extruders.reserve(m_used_filaments.total_volumes_per_extruder.size());
|
||||
for (auto item : m_used_filaments.total_volumes_per_extruder) {
|
||||
used_extruders.push_back(item.first);
|
||||
}
|
||||
return used_extruders;
|
||||
|
||||
@@ -73,9 +73,10 @@ namespace Slic3r {
|
||||
};
|
||||
|
||||
std::vector<double> volumes_per_color_change;
|
||||
std::map<size_t, double> volumes_per_extruder;
|
||||
std::map<size_t, double> model_volumes_per_extruder;
|
||||
std::map<size_t, double> wipe_tower_volumes_per_extruder;
|
||||
std::map<size_t, double> support_volumes_per_extruder;
|
||||
std::map<size_t, double> total_volumes_per_extruder;
|
||||
//BBS: the flush amount of every filament
|
||||
std::map<size_t, double> flush_per_filament;
|
||||
std::map<ExtrusionRole, std::pair<double, double>> used_filaments_per_role;
|
||||
@@ -92,7 +93,9 @@ namespace Slic3r {
|
||||
volumes_per_color_change.clear();
|
||||
volumes_per_color_change.shrink_to_fit();
|
||||
wipe_tower_volumes_per_extruder.clear();
|
||||
volumes_per_extruder.clear();
|
||||
model_volumes_per_extruder.clear();
|
||||
support_volumes_per_extruder.clear();
|
||||
total_volumes_per_extruder.clear();
|
||||
flush_per_filament.clear();
|
||||
used_filaments_per_role.clear();
|
||||
total_filamentchanges = 0;
|
||||
@@ -500,17 +503,20 @@ namespace Slic3r {
|
||||
std::vector<double> volumes_per_color_change;
|
||||
|
||||
double model_extrude_cache;
|
||||
std::map<size_t, double> volumes_per_extruder;
|
||||
std::map<size_t, double> model_volumes_per_extruder;
|
||||
|
||||
double wipe_tower_cache;
|
||||
std::map<size_t, double>wipe_tower_volume_per_extruder;
|
||||
std::map<size_t, double>wipe_tower_volumes_per_extruder;
|
||||
|
||||
double support_volume_cache;
|
||||
std::map<size_t, double>support_volume_per_extruder;
|
||||
std::map<size_t, double>support_volumes_per_extruder;
|
||||
|
||||
//BBS: the flush amount of every filament
|
||||
std::map<size_t, double> flush_per_filament;
|
||||
|
||||
double total_volume_cache;
|
||||
std::map<size_t, double>total_volumes_per_extruder;
|
||||
|
||||
double role_cache;
|
||||
std::map<ExtrusionRole, std::pair<double, double>> filaments_per_role;
|
||||
|
||||
@@ -524,6 +530,7 @@ namespace Slic3r {
|
||||
void process_model_cache(GCodeProcessor* processor);
|
||||
void process_wipe_tower_cache(GCodeProcessor* processor);
|
||||
void process_support_cache(GCodeProcessor* processor);
|
||||
void process_total_volume_cache(GCodeProcessor* processor);
|
||||
|
||||
void update_flush_per_filament(size_t extrude_id, float flush_length);
|
||||
void process_role_cache(GCodeProcessor* processor);
|
||||
|
||||
@@ -160,10 +160,12 @@ VoronoiDiagram::detect_known_issues(const VoronoiDiagram &voronoi_diagram, Segme
|
||||
return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX;
|
||||
} else if (const IssueType cell_issue_type = detect_known_voronoi_cell_issues(voronoi_diagram, segment_begin, segment_end); cell_issue_type != IssueType::NO_ISSUE_DETECTED) {
|
||||
return cell_issue_type;
|
||||
} else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) {
|
||||
// Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446.
|
||||
return IssueType::NON_PLANAR_VORONOI_DIAGRAM;
|
||||
}
|
||||
// BBS: test no problem in BBS
|
||||
//} else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) {
|
||||
// // Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446.
|
||||
// return IssueType::NON_PLANAR_VORONOI_DIAGRAM;
|
||||
//}
|
||||
|
||||
return IssueType::NO_ISSUE_DETECTED;
|
||||
}
|
||||
|
||||
+206
-6
@@ -24,9 +24,6 @@
|
||||
#include "TriangleSelector.hpp"
|
||||
|
||||
#include "Format/AMF.hpp"
|
||||
#include "Format/OBJ.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
#include "Format/STEP.hpp"
|
||||
#include "Format/svg.hpp"
|
||||
// BBS
|
||||
#include "FaceDetector.hpp"
|
||||
@@ -60,6 +57,9 @@
|
||||
#define _L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
namespace Slic3r {
|
||||
const std::vector<std::string> CONST_FILAMENTS = {
|
||||
"", "4", "8", "0C", "1C", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "AC", "BC", "CC", "DC",
|
||||
}; // 5 10 15 16
|
||||
// BBS initialization of static variables
|
||||
std::map<size_t, ExtruderParams> Model::extruderParamsMap = { {0,{"",0,0}}};
|
||||
GlobalSpeedMap Model::printSpeedMap{};
|
||||
@@ -190,7 +190,12 @@ Model::~Model()
|
||||
// Loading model from a file, it may be a simple geometry file as STL or OBJ, however it may be a project file as well.
|
||||
Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions,
|
||||
LoadStrategy options, PlateDataPtrs* plate_data, std::vector<Preset*>* project_presets, bool *is_xxx, Semver* file_version, Import3mfProgressFn proFn,
|
||||
ImportstlProgressFn stlFn, ImportStepProgressFn stepFn, StepIsUtf8Fn stepIsUtf8Fn, BBLProject* project, int plate_id)
|
||||
ImportstlProgressFn stlFn,
|
||||
ImportStepProgressFn stepFn,
|
||||
StepIsUtf8Fn stepIsUtf8Fn,
|
||||
BBLProject * project,
|
||||
int plate_id,
|
||||
ObjImportColorFn objFn)
|
||||
{
|
||||
Model model;
|
||||
|
||||
@@ -221,8 +226,46 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
||||
result = load_stl(input_file.c_str(), &model, nullptr, stlFn);
|
||||
else if (boost::algorithm::iends_with(input_file, ".oltp"))
|
||||
result = load_stl(input_file.c_str(), &model, nullptr, stlFn,256);
|
||||
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
||||
result = load_obj(input_file.c_str(), &model, message);
|
||||
else if (boost::algorithm::iends_with(input_file, ".obj")) {
|
||||
ObjInfo obj_info;
|
||||
result = load_obj(input_file.c_str(), &model, obj_info, message);
|
||||
if (result){
|
||||
unsigned char first_extruder_id;
|
||||
if (obj_info.vertex_colors.size() > 0) {
|
||||
std::vector<unsigned char> vertex_filament_ids;
|
||||
if (objFn) { // 1.result is ok and pop up a dialog
|
||||
objFn(obj_info.vertex_colors, false, vertex_filament_ids, first_extruder_id);
|
||||
if (vertex_filament_ids.size() > 0) {
|
||||
result = obj_import_vertex_color_deal(vertex_filament_ids, first_extruder_id, & model);
|
||||
}
|
||||
} else { // test //todo delete
|
||||
vertex_filament_ids.push_back(2);
|
||||
vertex_filament_ids.push_back(3);
|
||||
vertex_filament_ids.push_back(4);
|
||||
vertex_filament_ids.push_back(1); // 4
|
||||
vertex_filament_ids.push_back(1);
|
||||
vertex_filament_ids.push_back(1);
|
||||
vertex_filament_ids.push_back(1);
|
||||
vertex_filament_ids.push_back(1); // 8
|
||||
result = obj_import_vertex_color_deal(vertex_filament_ids, first_extruder_id, &model);
|
||||
}
|
||||
} else if (obj_info.face_colors.size() > 0 && obj_info.has_uv_png == false) { // mtl file
|
||||
std::vector<unsigned char> face_filament_ids;
|
||||
if (objFn) { // 1.result is ok and pop up a dialog
|
||||
objFn(obj_info.face_colors, obj_info.is_single_mtl, face_filament_ids, first_extruder_id);
|
||||
if (face_filament_ids.size() > 0) {
|
||||
result = obj_import_face_color_deal(face_filament_ids, first_extruder_id, &model);
|
||||
}
|
||||
}
|
||||
} /*else if (obj_info.has_uv_png && obj_info.uvs.size() > 0) {
|
||||
boost::filesystem::path full_path(input_file);
|
||||
std::string obj_directory = full_path.parent_path().string();
|
||||
obj_info.obj_dircetory = obj_directory;
|
||||
result = false;
|
||||
message = _L("Importing obj with png function is developing.");
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else if (boost::algorithm::iends_with(input_file, ".svg"))
|
||||
result = load_svg(input_file.c_str(), &model, message);
|
||||
//BBS: remove the old .amf.xml files
|
||||
@@ -2866,6 +2909,163 @@ void Model::setExtruderParams(const DynamicPrintConfig& config, int extruders_co
|
||||
}
|
||||
}
|
||||
|
||||
static void get_real_filament_id(const unsigned char &id, std::string &result) {
|
||||
if (id < CONST_FILAMENTS.size()) {
|
||||
result = CONST_FILAMENTS[id];
|
||||
} else {
|
||||
result = "";//error
|
||||
}
|
||||
};
|
||||
|
||||
bool Model::obj_import_vertex_color_deal(const std::vector<unsigned char> &vertex_filament_ids, const unsigned char &first_extruder_id, Model *model)
|
||||
{
|
||||
if (vertex_filament_ids.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
// 2.generate mmu_segmentation_facets
|
||||
if (model->objects.size() == 1 ) {
|
||||
auto obj = model->objects[0];
|
||||
obj->config.set("extruder", first_extruder_id);
|
||||
if (obj->volumes.size() == 1) {
|
||||
enum VertexColorCase {
|
||||
_3_SAME_COLOR,
|
||||
_3_DIFF_COLOR,
|
||||
_2_SAME_1_DIFF_COLOR,
|
||||
};
|
||||
auto calc_vertex_color_case = [](const unsigned char &c0, const unsigned char &c1, const unsigned char &c2, VertexColorCase &vertex_color_case,
|
||||
unsigned char &iso_index) {
|
||||
if (c0 == c1 && c1 == c2) {
|
||||
vertex_color_case = VertexColorCase::_3_SAME_COLOR;
|
||||
} else if (c0 != c1 && c1 != c2 && c0 != c2) {
|
||||
vertex_color_case = VertexColorCase::_3_DIFF_COLOR;
|
||||
} else if (c0 == c1) {
|
||||
vertex_color_case = _2_SAME_1_DIFF_COLOR;
|
||||
iso_index = 2;
|
||||
} else if (c1 == c2) {
|
||||
vertex_color_case = _2_SAME_1_DIFF_COLOR;
|
||||
iso_index = 0;
|
||||
} else if (c0 == c2) {
|
||||
vertex_color_case = _2_SAME_1_DIFF_COLOR;
|
||||
iso_index = 1;
|
||||
} else {
|
||||
std::cout << "error";
|
||||
}
|
||||
};
|
||||
auto calc_tri_area = [](const Vec3f &v0, const Vec3f &v1, const Vec3f &v2) {
|
||||
return std::abs((v0 - v1).cross(v0 - v2).norm()) / 2;
|
||||
};
|
||||
auto volume = obj->volumes[0];
|
||||
volume->config.set("extruder", first_extruder_id);
|
||||
auto face_count = volume->mesh().its.indices.size();
|
||||
volume->mmu_segmentation_facets.reserve(face_count);
|
||||
if (volume->mesh().its.vertices.size() != vertex_filament_ids.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < volume->mesh().its.indices.size(); i++) {
|
||||
auto face = volume->mesh().its.indices[i];
|
||||
auto filament_id0 = vertex_filament_ids[face[0]];
|
||||
auto filament_id1 = vertex_filament_ids[face[1]];
|
||||
auto filament_id2 = vertex_filament_ids[face[2]];
|
||||
if (filament_id0 <= 1 && filament_id1 <= 1 && filament_id2 <= 2) {
|
||||
continue;
|
||||
}
|
||||
if (i == 0) {
|
||||
std::cout << "";
|
||||
}
|
||||
VertexColorCase vertex_color_case;
|
||||
unsigned char iso_index;
|
||||
calc_vertex_color_case(filament_id0, filament_id1, filament_id2, vertex_color_case, iso_index);
|
||||
switch (vertex_color_case) {
|
||||
case _3_SAME_COLOR: {
|
||||
std::string result;
|
||||
get_real_filament_id(filament_id0, result);
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result);
|
||||
break;
|
||||
}
|
||||
case _3_DIFF_COLOR: {
|
||||
std::string result0, result1, result2;
|
||||
get_real_filament_id(filament_id0, result0);
|
||||
get_real_filament_id(filament_id1, result1);
|
||||
get_real_filament_id(filament_id2, result2);
|
||||
|
||||
auto v0 = volume->mesh().its.vertices[face[0]];
|
||||
auto v1 = volume->mesh().its.vertices[face[1]];
|
||||
auto v2 = volume->mesh().its.vertices[face[2]];
|
||||
auto dir_0_1 = (v1 - v0).normalized();
|
||||
auto dir_0_2 = (v2 - v0).normalized();
|
||||
float sita0 = acos(dir_0_1.dot(dir_0_2));
|
||||
auto dir_1_0 = -dir_0_1;
|
||||
auto dir_1_2 = (v2 - v1).normalized();
|
||||
float sita1 = acos(dir_1_0.dot(dir_1_2));
|
||||
float sita2 = PI - sita0 - sita1;
|
||||
std::array<float, 3> sitas = {sita0, sita1, sita2};
|
||||
float max_sita = sitas[0];
|
||||
int max_sita_vertex_index = 0;
|
||||
for (size_t j = 1; j < sitas.size(); j++) {
|
||||
if (sitas[j] > max_sita) {
|
||||
max_sita_vertex_index = j;
|
||||
max_sita = sitas[j];
|
||||
}
|
||||
}
|
||||
if (max_sita_vertex_index == 0) {
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result0 + result1 + result2 + (result1 + result2 + "5" )+ "3"); //"1C0C2C0C1C13"
|
||||
} else if (max_sita_vertex_index == 1) {
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result0 + result1 + result2 + (result0 + result2 + "9") + "3");
|
||||
} else{// if (max_sita_vertex_index == 2)
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result0 + result1 + result2 + (result1 + result0 + "1") + "3");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _2_SAME_1_DIFF_COLOR: {
|
||||
std::string result0, result1, result2;
|
||||
get_real_filament_id(filament_id0, result0);
|
||||
get_real_filament_id(filament_id1, result1);
|
||||
get_real_filament_id(filament_id2, result2);
|
||||
if (iso_index == 0) {
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result0 + result1 + result1 + "2");
|
||||
} else if (iso_index == 1) {
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result1 + result0 + result0 + "6");
|
||||
} else if (iso_index == 2) {
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result2 + result0 + result0 + "A");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Model::obj_import_face_color_deal(const std::vector<unsigned char> &face_filament_ids, const unsigned char &first_extruder_id, Model *model)
|
||||
{
|
||||
if (face_filament_ids.size() == 0) { return false; }
|
||||
// 2.generate mmu_segmentation_facets
|
||||
if (model->objects.size() == 1) {
|
||||
auto obj = model->objects[0];
|
||||
obj->config.set("extruder", first_extruder_id);
|
||||
if (obj->volumes.size() == 1) {
|
||||
auto volume = obj->volumes[0];
|
||||
volume->config.set("extruder", first_extruder_id);
|
||||
auto face_count = volume->mesh().its.indices.size();
|
||||
volume->mmu_segmentation_facets.reserve(face_count);
|
||||
if (volume->mesh().its.indices.size() != face_filament_ids.size()) { return false; }
|
||||
for (size_t i = 0; i < volume->mesh().its.indices.size(); i++) {
|
||||
auto face = volume->mesh().its.indices[i];
|
||||
auto filament_id = face_filament_ids[i];
|
||||
if (filament_id <= 1) { continue; }
|
||||
std::string result;
|
||||
get_real_filament_id(filament_id, result);
|
||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// update the maxSpeed of an object if it is different from the global configuration
|
||||
double Model::findMaxSpeed(const ModelObject* object) {
|
||||
auto objectKeys = object->config.keys();
|
||||
|
||||
+10
-1
@@ -35,6 +35,7 @@
|
||||
#include "Format/STEP.hpp"
|
||||
//BBS: add stl
|
||||
#include "Format/STL.hpp"
|
||||
#include "Format/OBJ.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -1564,8 +1565,16 @@ public:
|
||||
DynamicPrintConfig* config = nullptr, ConfigSubstitutionContext* config_substitutions = nullptr,
|
||||
LoadStrategy options = LoadStrategy::AddDefaultInstances, PlateDataPtrs* plate_data = nullptr,
|
||||
std::vector<Preset*>* project_presets = nullptr, bool* is_xxx = nullptr, Semver* file_version = nullptr, Import3mfProgressFn proFn = nullptr,
|
||||
ImportstlProgressFn stlFn = nullptr, ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn stepIsUtf8Fn = nullptr, BBLProject* project = nullptr, int plate_id = 0);
|
||||
ImportstlProgressFn stlFn = nullptr,
|
||||
ImportStepProgressFn stepFn = nullptr,
|
||||
StepIsUtf8Fn stepIsUtf8Fn = nullptr,
|
||||
BBLProject * project = nullptr,
|
||||
int plate_id = 0,
|
||||
ObjImportColorFn objFn = nullptr
|
||||
);
|
||||
// BBS
|
||||
static bool obj_import_vertex_color_deal(const std::vector<unsigned char> &vertex_filament_ids, const unsigned char &first_extruder_id, Model *model);
|
||||
static bool obj_import_face_color_deal(const std::vector<unsigned char> &face_filament_ids, const unsigned char &first_extruder_id, Model *model);
|
||||
static double findMaxSpeed(const ModelObject* object);
|
||||
static double getThermalLength(const ModelVolume* modelVolumePtr);
|
||||
static double getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs);
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
class QuantKMeans
|
||||
{
|
||||
public:
|
||||
int m_alpha_thres;
|
||||
cv::Mat m_flatten_labels;
|
||||
cv::Mat m_centers8UC3;
|
||||
QuantKMeans(int alpha_thres = 10) : m_alpha_thres(alpha_thres) {}
|
||||
void apply(cv::Mat &ori_image, cv::Mat &new_image, int num_cluster, int color_space)
|
||||
{
|
||||
cv::Mat image;
|
||||
convert_color_space(ori_image, image, color_space);
|
||||
cv::Mat flatten_image = flatten(image);
|
||||
|
||||
apply(flatten_image, num_cluster, color_space);
|
||||
replace_centers(ori_image, new_image);
|
||||
}
|
||||
void apply_aplha(cv::Mat &ori_image, cv::Mat &new_image, int num_cluster, int color_space)
|
||||
{
|
||||
// cout << " *** DoAlpha *** " << endl;
|
||||
cv::Mat flatten_image8UC3 = flatten_alpha(ori_image);
|
||||
cv::Mat image8UC3;
|
||||
convert_color_space(flatten_image8UC3, image8UC3, color_space);
|
||||
cv::Mat image32FC3(image8UC3.rows, 1, CV_32FC3);
|
||||
for (int i = 0; i < image8UC3.rows; i++) image32FC3.at<cv::Vec3f>(i, 0) = image8UC3.at<cv::Vec3b>(i, 0);
|
||||
|
||||
apply(image32FC3, num_cluster, color_space);
|
||||
repalce_centers_aplha(ori_image, new_image);
|
||||
}
|
||||
void apply(cv::Mat &flatten_image, int num_cluster, int color_space)
|
||||
{
|
||||
cv::Mat centers32FC3;
|
||||
num_cluster = fmin(flatten_image.rows, num_cluster);
|
||||
kmeans(flatten_image, num_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS,
|
||||
centers32FC3);
|
||||
this->m_centers8UC3 = cv::Mat(num_cluster, 1, CV_8UC3);
|
||||
for (int i = 0; i < num_cluster; i++) this->m_centers8UC3.at<cv::Vec3b>(i) = centers32FC3.at<cv::Vec3f>(i);
|
||||
|
||||
convert_color_space(this->m_centers8UC3, this->m_centers8UC3, color_space, true);
|
||||
}
|
||||
|
||||
void apply(const std::vector<std::array<float, 4>> &ori_colors,
|
||||
std::vector<std::array<float, 4>> & cluster_results,
|
||||
std::vector<int> & labels,
|
||||
int num_cluster = -1,
|
||||
int color_space = 2)
|
||||
{
|
||||
// 0~255
|
||||
cv::Mat flatten_image8UC3 = flatten_vector(ori_colors);
|
||||
|
||||
cv::Mat image8UC3;
|
||||
convert_color_space(flatten_image8UC3, image8UC3, color_space);
|
||||
|
||||
cv::Mat image32FC3(image8UC3.rows, 1, CV_32FC3);
|
||||
for (int i = 0; i < image8UC3.rows; i++)
|
||||
image32FC3.at<cv::Vec3f>(i, 0) = image8UC3.at<cv::Vec3b>(i, 0);
|
||||
|
||||
int best_cluster = 1;
|
||||
double cur_score, best_score = 100;
|
||||
int max_cluster = ori_colors.size();
|
||||
num_cluster = fmin(num_cluster, max_cluster);
|
||||
if (num_cluster < 1) {
|
||||
cur_score = kmeans(image32FC3, 1, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS);
|
||||
best_score = cur_score;
|
||||
for (int cur_cluster = 2; cur_cluster < 16; cur_cluster++) {
|
||||
if (cur_cluster > max_cluster)
|
||||
break;
|
||||
cur_score = kmeans(image32FC3, cur_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3,
|
||||
cv::KMEANS_PP_CENTERS);
|
||||
best_cluster = cur_score < best_score ? cur_cluster : best_cluster;
|
||||
best_score = cur_score < best_score ? cur_score : best_score;
|
||||
}
|
||||
} else
|
||||
best_cluster = num_cluster;
|
||||
|
||||
cv::Mat centers32FC3;
|
||||
kmeans(image32FC3, best_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS,
|
||||
centers32FC3);
|
||||
this->m_centers8UC3 = cv::Mat(best_cluster, 1, CV_8UC3);
|
||||
for (int i = 0; i < best_cluster; i++)
|
||||
this->m_centers8UC3.at<cv::Vec3b>(i) = centers32FC3.at<cv::Vec3f>(i);
|
||||
|
||||
convert_color_space(this->m_centers8UC3, this->m_centers8UC3, color_space, true);
|
||||
|
||||
cluster_results.clear();
|
||||
labels.clear();
|
||||
for (int i = 0; i < ori_colors.size(); i++)
|
||||
labels.emplace_back(this->m_flatten_labels.at<int>(i, 0));
|
||||
for (int i = 0; i < best_cluster; i++) {
|
||||
cv::Vec3f center = this->m_centers8UC3.at<cv::Vec3b>(i, 0);
|
||||
cluster_results.emplace_back(std::array<float, 4>{center[0] / 255.f, center[1] / 255.f, center[2] / 255.f, 1.f});
|
||||
}
|
||||
}
|
||||
|
||||
void replace_centers(cv::Mat &ori_image, cv::Mat &new_image)
|
||||
{
|
||||
for (int i = 0; i < ori_image.rows; i++) {
|
||||
for (int j = 0; j < ori_image.cols; j++) {
|
||||
int idx = this->m_flatten_labels.at<int>(i * ori_image.cols + j, 0);
|
||||
cv::Vec3b pixel = this->m_centers8UC3.at<cv::Vec3b>(idx);
|
||||
new_image.at<cv::Vec3b>(i, j) = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
void repalce_centers_aplha(cv::Mat &ori_image, cv::Mat &new_image)
|
||||
{
|
||||
int cnt = 0;
|
||||
int idx;
|
||||
cv::Vec3b center;
|
||||
for (int i = 0; i < ori_image.rows; i++) {
|
||||
for (int j = 0; j < ori_image.cols; j++) {
|
||||
cv::Vec4b pixel = ori_image.at<cv::Vec4b>(i, j);
|
||||
if ((int) pixel[3] < this->m_alpha_thres)
|
||||
new_image.at<cv::Vec4b>(i, j) = pixel;
|
||||
else {
|
||||
idx = this->m_flatten_labels.at<int>(cnt++, 0);
|
||||
center = this->m_centers8UC3.at<cv::Vec3b>(idx);
|
||||
new_image.at<cv::Vec4b>(i, j) = cv::Vec4b(center[0], center[1], center[2], pixel[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void convert_color_space(cv::Mat &ori_image, cv::Mat &image, int color_space, bool reverse = false)
|
||||
{
|
||||
switch (color_space) {
|
||||
case 0: image = ori_image; break;
|
||||
case 1:
|
||||
if (reverse)
|
||||
cvtColor(ori_image, image, cv::COLOR_HSV2BGR);
|
||||
else
|
||||
cvtColor(ori_image, image, cv::COLOR_BGR2HSV);
|
||||
break;
|
||||
case 2:
|
||||
if (reverse)
|
||||
cvtColor(ori_image, image, cv::COLOR_Lab2BGR);
|
||||
else
|
||||
cvtColor(ori_image, image, cv::COLOR_BGR2Lab);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat flatten(cv::Mat &image)
|
||||
{
|
||||
int num_pixels = image.rows * image.cols;
|
||||
cv::Mat img(num_pixels, 1, CV_32FC3);
|
||||
for (int i = 0; i < image.rows; i++) {
|
||||
for (int j = 0; j < image.cols; j++) {
|
||||
cv::Vec3f pixel = image.at<cv::Vec3b>(i, j);
|
||||
img.at<cv::Vec3f>(i * image.cols + j, 0) = pixel;
|
||||
}
|
||||
}
|
||||
return img;
|
||||
}
|
||||
cv::Mat flatten_alpha(cv::Mat &image)
|
||||
{
|
||||
int num_pixels = image.rows * image.cols;
|
||||
for (int i = 0; i < image.rows; i++)
|
||||
for (int j = 0; j < image.cols; j++) {
|
||||
cv::Vec4b pixel = image.at<cv::Vec4b>(i, j);
|
||||
if ((int) pixel[3] < this->m_alpha_thres) num_pixels--;
|
||||
}
|
||||
|
||||
cv::Mat img(num_pixels, 1, CV_8UC3);
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < image.rows; i++) {
|
||||
for (int j = 0; j < image.cols; j++) {
|
||||
cv::Vec4b pixel = image.at<cv::Vec4b>(i, j);
|
||||
if ((int) pixel[3] >= this->m_alpha_thres) img.at<cv::Vec3b>(cnt++, 0) = cv::Vec3b(pixel[0], pixel[1], pixel[2]);
|
||||
}
|
||||
}
|
||||
return img;
|
||||
}
|
||||
cv::Mat flatten_vector(const std::vector<std::array<float, 4>> &ori_colors)
|
||||
{
|
||||
int num_pixels = ori_colors.size();
|
||||
|
||||
cv::Mat image8UC3(num_pixels, 1, CV_8UC3);
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
std::array<float, 4> pixel = ori_colors[i];
|
||||
image8UC3.at<cv::Vec3b>(i, 0) = cv::Vec3b((int) (pixel[0] * 255.f), (int) (pixel[1] * 255.f), (int) (pixel[2] * 255.f));
|
||||
}
|
||||
return image8UC3;
|
||||
}
|
||||
};
|
||||
@@ -1138,6 +1138,8 @@ void PresetCollection::load_presets(
|
||||
preset.filament_id = key_values[BBL_JSON_KEY_FILAMENT_ID];
|
||||
if (key_values.find(BBL_JSON_KEY_IS_CUSTOM) != key_values.end())
|
||||
preset.custom_defined = key_values[BBL_JSON_KEY_IS_CUSTOM];
|
||||
if (key_values.find(BBL_JSON_KEY_DESCRIPTION) != key_values.end())
|
||||
preset.description = key_values[BBL_JSON_KEY_DESCRIPTION];
|
||||
if (key_values.find("instantiation") != key_values.end())
|
||||
preset.is_visible = key_values["instantiation"] != "false";
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ public:
|
||||
std::string base_id; // base id of preset
|
||||
std::string sync_info; // enum: "delete", "create", "update", ""
|
||||
std::string custom_defined; // enum: "1", "0", ""
|
||||
std::string description; //
|
||||
long long updated_time{0}; //last updated time
|
||||
std::map<std::string, std::string> key_values;
|
||||
|
||||
|
||||
@@ -1964,7 +1964,8 @@ std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle
|
||||
|
||||
if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) printer_names.insert(printer_it->name);
|
||||
}
|
||||
assert(printer_names.size() == 1);
|
||||
|
||||
//assert(printer_names.size() == 1);
|
||||
|
||||
for (auto& printer_name : printer_names) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " printer name: " << printer_name;
|
||||
@@ -3463,7 +3464,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
||||
// Load the print, filament or printer preset.
|
||||
std::string preset_name;
|
||||
DynamicPrintConfig config;
|
||||
std::string alias_name, inherits, instantiation, setting_id, filament_id;
|
||||
std::string alias_name, inherits, description, instantiation, setting_id, filament_id;
|
||||
std::vector<std::string> renamed_from;
|
||||
const DynamicPrintConfig* default_config = nullptr;
|
||||
std::string reason;
|
||||
@@ -3480,7 +3481,8 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
||||
return reason;
|
||||
}
|
||||
preset_name = key_values[BBL_JSON_KEY_NAME];
|
||||
instantiation = key_values[BBL_JSON_KEY_INSTANTIATION];
|
||||
description = key_values[BBL_JSON_KEY_DESCRIPTION];
|
||||
instantiation = key_values[BBL_JSON_KEY_INSTANTIATION];
|
||||
auto setting_it = key_values.find(BBL_JSON_KEY_SETTING_ID);
|
||||
if (setting_it != key_values.end())
|
||||
setting_id = setting_it->second;
|
||||
@@ -3603,6 +3605,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
||||
loaded.is_system = true;
|
||||
loaded.vendor = current_vendor_profile;
|
||||
loaded.version = current_vendor_profile->config_version;
|
||||
loaded.description = description;
|
||||
loaded.setting_id = setting_id;
|
||||
loaded.filament_id = filament_id;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << loaded.name << " load filament_id: " << filament_id;
|
||||
|
||||
@@ -160,7 +160,8 @@ static t_config_enum_values s_keys_map_InfillPattern {
|
||||
{ "archimedeanchords", ipArchimedeanChords },
|
||||
{ "octagramspiral", ipOctagramSpiral },
|
||||
{ "supportcubic", ipSupportCubic },
|
||||
{ "lightning", ipLightning }
|
||||
{ "lightning", ipLightning },
|
||||
{ "crosshatch", ipCrossHatch}
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern)
|
||||
|
||||
@@ -2049,6 +2050,7 @@ def = this->add("filament_loading_speed", coFloats);
|
||||
def->enum_values.push_back("octagramspiral");
|
||||
def->enum_values.push_back("supportcubic");
|
||||
def->enum_values.push_back("lightning");
|
||||
def->enum_values.push_back("crosshatch");
|
||||
def->enum_labels.push_back(L("Concentric"));
|
||||
def->enum_labels.push_back(L("Rectilinear"));
|
||||
def->enum_labels.push_back(L("Grid"));
|
||||
@@ -2066,6 +2068,7 @@ def = this->add("filament_loading_speed", coFloats);
|
||||
def->enum_labels.push_back(L("Octagram Spiral"));
|
||||
def->enum_labels.push_back(L("Support Cubic"));
|
||||
def->enum_labels.push_back(L("Lightning"));
|
||||
def->enum_labels.push_back(L("Cross Hatch"));
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCubic));
|
||||
|
||||
auto def_infill_anchor_min = def = this->add("infill_anchor", coFloatOrPercent);
|
||||
|
||||
@@ -69,7 +69,7 @@ enum AuthorizationType {
|
||||
enum InfillPattern : int {
|
||||
ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
|
||||
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
|
||||
ipLightning,
|
||||
ipLightning, ipCrossHatch,
|
||||
ipCount,
|
||||
};
|
||||
|
||||
|
||||
@@ -2333,9 +2333,17 @@ void PrintObject::bridge_over_infill()
|
||||
};
|
||||
|
||||
// LAMBDA do determine optimal bridging angle
|
||||
auto determine_bridging_angle = [](const Polygons &bridged_area, const Lines &anchors, InfillPattern dominant_pattern) {
|
||||
auto determine_bridging_angle = [](const Polygons &bridged_area, const Lines &anchors, InfillPattern dominant_pattern, double infill_direction) {
|
||||
AABBTreeLines::LinesDistancer<Line> lines_tree(anchors);
|
||||
|
||||
// Check it the infill that require a fixed infill angle.
|
||||
switch (dominant_pattern) {
|
||||
case ip3DHoneycomb:
|
||||
case ipCrossHatch:
|
||||
return (infill_direction + 45.0) * 2.0 * M_PI / 360.;
|
||||
default: break;
|
||||
}
|
||||
|
||||
std::map<double, int> counted_directions;
|
||||
for (const Polygon &p : bridged_area) {
|
||||
double acc_distance = 0;
|
||||
@@ -2715,11 +2723,12 @@ void PrintObject::bridge_over_infill()
|
||||
double bridging_angle = 0;
|
||||
if (!anchors.empty()) {
|
||||
bridging_angle = determine_bridging_angle(area_to_be_bridge, to_lines(anchors),
|
||||
candidate.region->region().config().sparse_infill_pattern.value);
|
||||
candidate.region->region().config().sparse_infill_pattern.value,
|
||||
candidate.region->region().config().infill_direction.value);
|
||||
} else {
|
||||
// use expansion boundaries as anchors.
|
||||
// Also, use Infill pattern that is neutral for angle determination, since there are no infill lines.
|
||||
bridging_angle = determine_bridging_angle(area_to_be_bridge, to_lines(boundary_plines), InfillPattern::ipLine);
|
||||
bridging_angle = determine_bridging_angle(area_to_be_bridge, to_lines(boundary_plines), InfillPattern::ipLine, 0);
|
||||
}
|
||||
|
||||
boundary_plines.insert(boundary_plines.end(), anchors.begin(), anchors.end());
|
||||
|
||||
@@ -208,6 +208,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Plater.hpp
|
||||
GUI/PartPlate.cpp
|
||||
GUI/PartPlate.hpp
|
||||
GUI/UserNotification.cpp
|
||||
GUI/UserNotification.hpp
|
||||
GUI/PresetComboBoxes.hpp
|
||||
GUI/PresetComboBoxes.cpp
|
||||
GUI/BitmapComboBox.hpp
|
||||
@@ -304,6 +306,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/CameraUtils.hpp
|
||||
GUI/wxExtensions.cpp
|
||||
GUI/wxExtensions.hpp
|
||||
GUI/ObjColorDialog.cpp
|
||||
GUI/ObjColorDialog.hpp
|
||||
GUI/WipeTowerDialog.cpp
|
||||
GUI/RammingChart.cpp
|
||||
GUI/RammingChart.hpp
|
||||
@@ -321,6 +325,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/ImGuiWrapper.cpp
|
||||
GUI/DeviceManager.hpp
|
||||
GUI/DeviceManager.cpp
|
||||
GUI/UserManager.hpp
|
||||
GUI/UserManager.cpp
|
||||
GUI/HttpServer.hpp
|
||||
GUI/HttpServer.cpp
|
||||
Config/Snapshot.cpp
|
||||
@@ -467,6 +473,24 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/json_diff.cpp
|
||||
GUI/KBShortcutsDialog.hpp
|
||||
GUI/KBShortcutsDialog.cpp
|
||||
GUI/MultiMachine.hpp
|
||||
GUI/MultiMachine.cpp
|
||||
GUI/MultiMachinePage.hpp
|
||||
GUI/MultiMachinePage.cpp
|
||||
GUI/MultiMachineManagerPage.cpp
|
||||
GUI/MultiMachineManagerPage.hpp
|
||||
GUI/MultiPrintJob.cpp
|
||||
GUI/MultiPrintJob.hpp
|
||||
GUI/MultiSendMachineModel.hpp
|
||||
GUI/MultiSendMachineModel.cpp
|
||||
GUI/MultiTaskManagerPage.hpp
|
||||
GUI/MultiTaskManagerPage.cpp
|
||||
GUI/MultiTaskModel.hpp
|
||||
GUI/MultiTaskModel.cpp
|
||||
GUI/SendMultiMachinePage.hpp
|
||||
GUI/SendMultiMachinePage.cpp
|
||||
GUI/TaskManager.cpp
|
||||
GUI/TaskManager.hpp
|
||||
Utils/Http.cpp
|
||||
Utils/Http.hpp
|
||||
Utils/FixModelByWin10.cpp
|
||||
@@ -526,6 +550,7 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/calib_dlg.cpp
|
||||
Utils/CalibUtils.cpp
|
||||
Utils/CalibUtils.hpp
|
||||
Utils/ProfileDescription.hpp
|
||||
GUI/PrinterCloudAuthDialog.cpp
|
||||
GUI/PrinterCloudAuthDialog.hpp
|
||||
Utils/Obico.cpp
|
||||
|
||||
@@ -8,12 +8,19 @@
|
||||
#include <wx/colordlg.h>
|
||||
#include <wx/dcgraph.h>
|
||||
#include "CalibUtils.hpp"
|
||||
|
||||
#include "../Utils/ColorSpaceConvert.hpp"
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
wxDEFINE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent);
|
||||
|
||||
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id)
|
||||
static std::string float_to_string_with_precision(float value, int precision = 3)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(precision) << value;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id)
|
||||
: DPIDialog(parent, id, _L("AMS Materials Setting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
||||
, m_color_picker_popup(ColorPickerPopup(this))
|
||||
{
|
||||
@@ -281,6 +288,14 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent)
|
||||
m_ratio_text->SetForegroundColour(wxColour(50, 58, 61));
|
||||
m_ratio_text->SetFont(Label::Head_14);
|
||||
|
||||
m_ratio_text->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
|
||||
m_ratio_text->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
|
||||
|
||||
m_ratio_text->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
|
||||
wxLaunchDefaultBrowser(wxT("https://wiki.bambulab.com/en/software/bambu-studio/calibration_pa"));
|
||||
});
|
||||
|
||||
|
||||
wxBoxSizer *m_sizer_cali_resutl = new wxBoxSizer(wxHORIZONTAL);
|
||||
// pa profile
|
||||
m_title_pa_profile = new wxStaticText(parent, wxID_ANY, _L("PA Profile"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
|
||||
@@ -750,6 +765,16 @@ bool AMSMaterialsSetting::Show(bool show)
|
||||
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
//m_clr_picker->set_color(m_clr_picker->GetParent()->GetBackgroundColour());
|
||||
|
||||
/*if (obj && (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI) || obj->is_high_printer_type())) {
|
||||
m_ratio_text->Show();
|
||||
m_k_param->Show();
|
||||
m_input_k_val->Show();
|
||||
}
|
||||
else {
|
||||
m_ratio_text->Hide();
|
||||
m_k_param->Hide();
|
||||
m_input_k_val->Hide();
|
||||
}*/
|
||||
m_ratio_text->Show();
|
||||
m_k_param->Show();
|
||||
m_input_k_val->Show();
|
||||
@@ -922,8 +947,8 @@ void AMSMaterialsSetting::on_select_cali_result(wxCommandEvent &evt)
|
||||
{
|
||||
m_pa_cali_select_id = evt.GetSelection();
|
||||
if (m_pa_cali_select_id >= 0) {
|
||||
m_input_k_val->GetTextCtrl()->SetValue(std::to_string(m_pa_profile_items[m_pa_cali_select_id].k_value));
|
||||
m_input_n_val->GetTextCtrl()->SetValue(std::to_string(m_pa_profile_items[m_pa_cali_select_id].n_coef));
|
||||
m_input_k_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[m_pa_cali_select_id].k_value));
|
||||
m_input_n_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[m_pa_cali_select_id].n_coef));
|
||||
}
|
||||
else{
|
||||
m_input_k_val->GetTextCtrl()->SetValue(std::to_string(0.00));
|
||||
@@ -1012,6 +1037,8 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
m_button_confirm->SetBorderColor(wxColour(0x90, 0x90, 0x90));
|
||||
m_comboBox_cali_result->Clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -1076,8 +1103,8 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
|
||||
if (cali_select_idx >= 0) {
|
||||
m_input_k_val->GetTextCtrl()->SetValue(std::to_string(m_pa_profile_items[cali_select_idx].k_value));
|
||||
m_input_n_val->GetTextCtrl()->SetValue(std::to_string(m_pa_profile_items[cali_select_idx].n_coef));
|
||||
m_input_k_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[cali_select_idx].k_value));
|
||||
m_input_n_val->GetTextCtrl()->SetValue(float_to_string_with_precision(m_pa_profile_items[cali_select_idx].n_coef));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1121,7 +1148,6 @@ ColorPicker::ColorPicker(wxWindow* parent, wxWindowID id, const wxPoint& pos /*=
|
||||
|
||||
m_bitmap_border = create_scaled_bitmap("color_picker_border", nullptr, 25);
|
||||
m_bitmap_border_dark = create_scaled_bitmap("color_picker_border_dark", nullptr, 25);
|
||||
m_bitmap_transparent_def = create_scaled_bitmap("transparent_color_picker", nullptr, 25);
|
||||
m_bitmap_transparent = create_scaled_bitmap("transparent_color_picker", nullptr, 25);
|
||||
}
|
||||
|
||||
@@ -1185,12 +1211,12 @@ void ColorPicker::doRender(wxDC& dc)
|
||||
if (m_selected) radius -= FromDIP(1);
|
||||
|
||||
if (alpha == 0) {
|
||||
dc.DrawBitmap(m_bitmap_transparent_def, 0, 0);
|
||||
dc.DrawBitmap(m_bitmap_transparent, 0, 0);
|
||||
}
|
||||
else if (alpha != 254 && alpha != 255) {
|
||||
if (transparent_changed) {
|
||||
std::string rgb = (m_colour.GetAsString(wxC2S_HTML_SYNTAX)).ToStdString();
|
||||
if (rgb.size() == 9) {
|
||||
if (rgb.size() == 8) {
|
||||
//delete alpha value
|
||||
rgb = rgb.substr(0, rgb.size() - 2);
|
||||
}
|
||||
@@ -1201,8 +1227,8 @@ void ColorPicker::doRender(wxDC& dc)
|
||||
replace.push_back(fill_replace);
|
||||
m_bitmap_transparent = ScalableBitmap(this, "transparent_color_picker", 25, false, false, true, replace).bmp();
|
||||
transparent_changed = false;
|
||||
dc.DrawBitmap(m_bitmap_transparent, 0, 0);
|
||||
}
|
||||
dc.DrawBitmap(m_bitmap_transparent, 0, 0);
|
||||
}
|
||||
else {
|
||||
dc.SetPen(wxPen(m_colour));
|
||||
@@ -1439,11 +1465,22 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
|
||||
|
||||
void ColorPickerPopup::on_custom_clr_picker(wxMouseEvent& event)
|
||||
{
|
||||
std::vector<std::string> 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]));
|
||||
}
|
||||
auto clr_dialog = new wxColourDialog(nullptr, m_clrData);
|
||||
wxColour picker_color;
|
||||
|
||||
if (clr_dialog->ShowModal() == wxID_OK) {
|
||||
m_clrData = &(clr_dialog->GetColourData());
|
||||
if (colors.size() != CUSTOM_COLOR_COUNT) {
|
||||
colors.resize(CUSTOM_COLOR_COUNT);
|
||||
}
|
||||
for (int i = 0; i < CUSTOM_COLOR_COUNT; i++) {
|
||||
colors[i] = color_to_string(m_clrData->GetCustomColour(i));
|
||||
}
|
||||
wxGetApp().app_config->save_custom_color_to_config(colors);
|
||||
|
||||
picker_color = wxColour(
|
||||
m_clrData->GetColour().Red(),
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "wxExtensions.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
#include "wx/colourdata.h"
|
||||
#include "wx/clrpicker.h"
|
||||
#include "wx/colourdata.h"
|
||||
#include "Widgets/RadioBox.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/RoundedRectangle.hpp"
|
||||
@@ -36,7 +36,6 @@ public:
|
||||
wxBitmap m_bitmap_border;
|
||||
wxBitmap m_bitmap_border_dark;
|
||||
wxBitmap m_bitmap_transparent;
|
||||
wxBitmap m_bitmap_transparent_def; //default transparent material
|
||||
|
||||
wxColour m_colour;
|
||||
std::vector<wxColour> m_cols;
|
||||
|
||||
@@ -193,6 +193,40 @@ void AMSSetting::create()
|
||||
m_sizer_switch_filament_tip->Add(m_sizer_switch_filament_inline, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
|
||||
// checkbox area 5
|
||||
wxBoxSizer* m_sizer_air_print = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_checkbox_air_print = new ::CheckBox(m_panel_body);
|
||||
m_checkbox_air_print->Bind(wxEVT_TOGGLEBUTTON, &AMSSetting::on_air_print_detect, this);
|
||||
m_sizer_air_print->Add(m_checkbox_air_print, 0, wxTOP, 1);
|
||||
m_sizer_air_print->Add(0, 0, 0, wxLEFT, 12);
|
||||
m_title_air_print = new wxStaticText(m_panel_body, wxID_ANY, _L("Air Printing Detection"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_air_print->SetFont(::Label::Head_13);
|
||||
m_title_air_print->SetForegroundColour(AMS_SETTING_GREY800);
|
||||
m_title_air_print->Wrap(AMS_SETTING_BODY_WIDTH);
|
||||
m_sizer_air_print->Add(m_title_air_print, 1, wxEXPAND, 0);
|
||||
|
||||
wxBoxSizer* m_sizer_air_print_tip = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_sizer_air_print_tip->Add(0, 0, 0, wxLEFT, 10);
|
||||
|
||||
// tip line
|
||||
auto m_sizer_air_print_inline = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_tip_air_print_line = new Label(m_panel_body,
|
||||
_L("Detects clogging and filament grinding, halting printing immediately to conserve time and filament.")
|
||||
);
|
||||
m_tip_air_print_line->SetFont(::Label::Body_13);
|
||||
m_tip_air_print_line->SetForegroundColour(AMS_SETTING_GREY700);
|
||||
m_tip_air_print_line->SetSize(wxSize(AMS_SETTING_BODY_WIDTH, -1));
|
||||
m_tip_air_print_line->Wrap(AMS_SETTING_BODY_WIDTH);
|
||||
m_sizer_air_print_inline->Add(m_tip_air_print_line, 0, wxEXPAND, 0);
|
||||
m_sizer_air_print_tip->Add(m_sizer_air_print_inline, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
m_checkbox_air_print->Hide();
|
||||
m_title_air_print->Hide();
|
||||
m_tip_air_print_line->Hide();
|
||||
|
||||
|
||||
// panel img
|
||||
wxPanel* m_panel_img = new wxPanel(m_panel_body, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_panel_img->SetBackgroundColour(AMS_SETTING_GREY200);
|
||||
@@ -221,6 +255,11 @@ void AMSSetting::create()
|
||||
m_sizerl_body->Add(m_sizer_switch_filament_tip, 0, wxLEFT, 18);
|
||||
m_sizerl_body->Add(0, 0, 0, wxTOP, 6);
|
||||
m_sizerl_body->Add(0, 0, 0, wxTOP, FromDIP(5));
|
||||
m_sizerl_body->Add(m_sizer_air_print, 0, wxEXPAND | wxTOP, FromDIP(8));
|
||||
m_sizerl_body->Add(0, 0, 0, wxTOP, 8);
|
||||
m_sizerl_body->Add(m_sizer_air_print_tip, 0, wxLEFT, 18);
|
||||
m_sizerl_body->Add(0, 0, 0, wxTOP, 6);
|
||||
m_sizerl_body->Add(0, 0, 0, wxTOP, FromDIP(5));
|
||||
m_sizerl_body->Add(m_panel_img, 1, wxEXPAND | wxALL, FromDIP(5));
|
||||
|
||||
m_panel_body->SetSizer(m_sizerl_body);
|
||||
@@ -285,6 +324,9 @@ void AMSSetting::update_insert_material_read_mode(bool selected, std::string ver
|
||||
|
||||
void AMSSetting::update_ams_img(std::string ams_icon_str)
|
||||
{
|
||||
if (wxGetApp().dark_mode()&& ams_icon_str=="extra_icon") {
|
||||
ams_icon_str += "_dark";
|
||||
}
|
||||
m_am_img->SetBitmap(create_scaled_bitmap(ams_icon_str, nullptr, 126));
|
||||
}
|
||||
|
||||
@@ -336,6 +378,22 @@ void AMSSetting::update_switch_filament(bool selected)
|
||||
m_checkbox_switch_filament->SetValue(selected);
|
||||
}
|
||||
|
||||
void AMSSetting::update_air_printing_detection(bool selected)
|
||||
{
|
||||
if (false/*obj->is_support_air_print_detection*/) {
|
||||
m_checkbox_air_print->Show();
|
||||
m_title_air_print->Show();
|
||||
m_tip_air_print_line->Show();
|
||||
}
|
||||
else {
|
||||
m_checkbox_air_print->Hide();
|
||||
m_title_air_print->Hide();
|
||||
m_tip_air_print_line->Hide();
|
||||
}
|
||||
Layout();
|
||||
m_checkbox_air_print->SetValue(selected);
|
||||
}
|
||||
|
||||
|
||||
void AMSSetting::on_select_ok(wxMouseEvent &event)
|
||||
{
|
||||
@@ -415,6 +473,13 @@ void AMSSetting::on_switch_filament(wxCommandEvent& event)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void AMSSetting::on_air_print_detect(wxCommandEvent& event)
|
||||
{
|
||||
bool air_print_detect = m_checkbox_air_print->GetValue();
|
||||
obj->command_ams_air_print_detect(air_print_detect);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
wxString AMSSetting::append_title(wxString text)
|
||||
{
|
||||
wxString lab;
|
||||
|
||||
@@ -33,11 +33,13 @@ public:
|
||||
void update_starting_read_mode(bool selected);
|
||||
void update_remain_mode(bool selected);
|
||||
void update_switch_filament(bool selected);
|
||||
void update_air_printing_detection(bool selected);
|
||||
void on_select_ok(wxMouseEvent& event);
|
||||
void on_insert_material_read(wxCommandEvent &event);
|
||||
void on_starting_read(wxCommandEvent &event);
|
||||
void on_remain(wxCommandEvent& event);
|
||||
void on_switch_filament(wxCommandEvent& event);
|
||||
void on_air_print_detect(wxCommandEvent& event);
|
||||
wxString append_title(wxString text);
|
||||
wxStaticText *append_text(wxString text);
|
||||
MachineObject *obj{nullptr};
|
||||
@@ -70,6 +72,10 @@ protected:
|
||||
wxStaticText* m_title_switch_filament;
|
||||
Label* m_tip_switch_filament_line1;
|
||||
|
||||
CheckBox* m_checkbox_air_print;
|
||||
wxStaticText* m_title_air_print;
|
||||
Label* m_tip_air_print_line;
|
||||
|
||||
wxStaticText *m_tip_ams_img;
|
||||
Button * m_button_auto_demarcate;
|
||||
|
||||
|
||||
@@ -412,6 +412,48 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
void AmsMapingPopup::update_ams_data_multi_machines()
|
||||
{
|
||||
m_has_unmatch_filament = false;
|
||||
for (auto& ams_container : m_amsmapping_container_list) {
|
||||
ams_container->Hide();
|
||||
}
|
||||
|
||||
for (wxWindow* mitem : m_mapping_item_list) {
|
||||
mitem->Destroy();
|
||||
mitem = nullptr;
|
||||
}
|
||||
m_mapping_item_list.clear();
|
||||
|
||||
if (m_amsmapping_container_sizer_list.size() > 0) {
|
||||
for (wxBoxSizer* siz : m_amsmapping_container_sizer_list) {
|
||||
siz->Clear(true);
|
||||
}
|
||||
}
|
||||
|
||||
int m_amsmapping_container_list_index = 0;
|
||||
std::vector<TrayData> tray_datas;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TrayData td;
|
||||
td.id = i;
|
||||
td.type = EMPTY;
|
||||
td.colour = wxColour(166, 169, 170);
|
||||
td.name = "";
|
||||
td.filament_type = "";
|
||||
td.ctype = 0;
|
||||
tray_datas.push_back(td);
|
||||
}
|
||||
|
||||
m_amsmapping_container_list[m_amsmapping_container_list_index]->Show();
|
||||
add_ams_mapping(tray_datas, m_amsmapping_container_list[m_amsmapping_container_list_index], m_amsmapping_container_sizer_list[m_amsmapping_container_list_index]);
|
||||
|
||||
m_warning_text->Show(m_has_unmatch_filament);
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
|
||||
{
|
||||
m_has_unmatch_filament = false;
|
||||
|
||||
@@ -157,6 +157,7 @@ public:
|
||||
void update_materials_list(std::vector<std::string> list);
|
||||
void set_tag_texture(std::string texture);
|
||||
void update_ams_data(std::map<std::string, Ams *> amsList);
|
||||
void update_ams_data_multi_machines();
|
||||
void add_ams_mapping(std::vector<TrayData> tray_data, wxWindow* container, wxBoxSizer* sizer);
|
||||
void set_current_filament_id(int id){m_current_filament_id = id;};
|
||||
int get_current_filament_id(){return m_current_filament_id;};
|
||||
|
||||
@@ -54,6 +54,300 @@ wxString get_fail_reason(int code)
|
||||
return _L("Unknown Failure");
|
||||
}
|
||||
|
||||
PingCodeBindDialog::PingCodeBindDialog(Plater* plater /*= nullptr*/)
|
||||
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _L("Bind with Pin Code"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
wxBoxSizer* sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
|
||||
m_simplebook = new wxSimplebook(this);
|
||||
m_simplebook->SetSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
m_simplebook->SetMinSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
m_simplebook->SetMaxSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
|
||||
|
||||
request_bind_panel = new wxPanel(m_simplebook);
|
||||
binding_panel = new wxPanel(m_simplebook);
|
||||
|
||||
request_bind_panel->SetSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
request_bind_panel->SetMinSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
request_bind_panel->SetMaxSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
|
||||
binding_panel->SetSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
binding_panel->SetMinSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
binding_panel->SetMaxSize(wxSize(FromDIP(460), FromDIP(240)));
|
||||
|
||||
|
||||
request_bind_panel->SetBackgroundColour(*wxWHITE);
|
||||
binding_panel->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
m_status_text = new Label(request_bind_panel, _L("Please Find the Pin Code in Account page on printer screen,\n and type in the Pin Code below."));
|
||||
m_status_text->SetBackgroundColour(*wxWHITE);
|
||||
m_status_text->SetFont(Label::Body_14);
|
||||
m_status_text->SetMaxSize(wxSize(FromDIP(440), -1));
|
||||
m_status_text->Wrap(FromDIP(440));
|
||||
m_status_text->SetForegroundColour(wxColour(38, 46, 48));
|
||||
|
||||
m_link_show_ping_code_wiki = new wxStaticText(request_bind_panel, wxID_ANY, _L("Can't find Pin Code?"));
|
||||
m_link_show_ping_code_wiki->SetFont(Label::Body_14);
|
||||
m_link_show_ping_code_wiki->SetBackgroundColour(*wxWHITE);
|
||||
m_link_show_ping_code_wiki->SetForegroundColour(wxColour(31, 142, 234));
|
||||
|
||||
m_link_show_ping_code_wiki->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); });
|
||||
m_link_show_ping_code_wiki->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); });
|
||||
|
||||
m_link_show_ping_code_wiki->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
|
||||
m_ping_code_wiki = "https://wiki.bambulab.com/en/bambu-studio/manual/pin-code";
|
||||
wxLaunchDefaultBrowser(m_ping_code_wiki);
|
||||
});
|
||||
|
||||
m_text_input_title = new wxStaticText(request_bind_panel, wxID_ANY, _L("Pin Code"));
|
||||
m_text_input_title->SetFont(Label::Body_14);
|
||||
m_text_input_title->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
wxBoxSizer* ping_code_input = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
|
||||
for (int i = 0; i < PING_CODE_LENGTH; i++) {
|
||||
m_text_input_single_code[i] = new TextInput(request_bind_panel, wxEmptyString, "", "", wxDefaultPosition, wxSize(FromDIP(38), FromDIP(38)), wxTE_PROCESS_ENTER | wxTE_CENTER);
|
||||
wxTextAttr textAttr;
|
||||
textAttr.SetAlignment(wxTEXT_ALIGNMENT_CENTER);
|
||||
textAttr.SetTextColour(wxColour(34, 139, 34));
|
||||
m_text_input_single_code[i]->GetTextCtrl()->SetDefaultStyle(textAttr);
|
||||
m_text_input_single_code[i]->SetFont(Label::Body_16);
|
||||
m_text_input_single_code[i]->GetTextCtrl()->SetMaxLength(1);
|
||||
m_text_input_single_code[i]->GetTextCtrl()->Bind(wxEVT_TEXT, &PingCodeBindDialog::on_text_changed, this);
|
||||
m_text_input_single_code[i]->GetTextCtrl()->Bind(wxEVT_KEY_DOWN, &PingCodeBindDialog::on_key_backspace, this);
|
||||
m_text_input_single_code[i]->GetTextCtrl()->Bind(wxEVT_CHAR, &PingCodeBindDialog::on_key_input, this);
|
||||
ping_code_input->Add(m_text_input_single_code[i], 0, wxALL, FromDIP(5));
|
||||
}
|
||||
|
||||
wxBoxSizer* m_sizer_button = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_sizer_button->Add(0, 0, 1, wxEXPAND, 5);
|
||||
m_button_bind = new Button(request_bind_panel, _L("Confirm"));
|
||||
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
|
||||
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
m_button_bind->SetBackgroundColor(btn_bg_green);
|
||||
m_button_bind->SetBorderColor(*wxWHITE);
|
||||
m_button_bind->SetTextColor(wxColour("#FFFFFE"));
|
||||
m_button_bind->SetSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_bind->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_bind->SetCornerRadius(FromDIP(12));
|
||||
m_button_bind->Enable(false);
|
||||
|
||||
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
|
||||
m_button_cancel = new Button(request_bind_panel, _L("Cancel"));
|
||||
m_button_cancel->SetBackgroundColor(btn_bg_white);
|
||||
m_button_cancel->SetBorderColor(BIND_DIALOG_GREY900);
|
||||
m_button_cancel->SetSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_cancel->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_cancel->SetTextColor(BIND_DIALOG_GREY900);
|
||||
m_button_cancel->SetCornerRadius(FromDIP(12));
|
||||
|
||||
m_sizer_button->Add(m_button_bind, 0, wxALIGN_CENTER, 0);
|
||||
m_sizer_button->Add(0, 0, 0, wxLEFT, FromDIP(13));
|
||||
m_sizer_button->Add(m_button_cancel, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
|
||||
m_simplebook->AddPage(request_bind_panel, wxEmptyString, true);
|
||||
m_simplebook->AddPage(binding_panel, wxEmptyString, false);
|
||||
|
||||
|
||||
auto sizer_request = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_request->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer_request->Add(m_status_text, 0, wxLEFT, FromDIP(13));
|
||||
sizer_request->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer_request->Add(m_link_show_ping_code_wiki, 0, wxLEFT, FromDIP(13));
|
||||
sizer_request->Add(0, 0, 0, wxTOP, FromDIP(15));
|
||||
sizer_request->Add(m_text_input_title, 0, wxLEFT, FromDIP(13));
|
||||
sizer_request->Add(0, 0, 0, wxTOP, FromDIP(5));
|
||||
sizer_request->Add(ping_code_input, 0, wxLEFT, FromDIP(10));
|
||||
sizer_request->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer_request->Add(m_sizer_button, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, FromDIP(15));
|
||||
request_bind_panel->SetSizer(sizer_request);
|
||||
request_bind_panel->Layout();
|
||||
request_bind_panel->Fit();
|
||||
|
||||
|
||||
|
||||
auto m_loading_txt = new Label(binding_panel, _L("Binding..."));
|
||||
m_loading_txt->SetBackgroundColour(*wxWHITE);
|
||||
m_loading_txt->SetFont(Label::Head_16);
|
||||
auto m_loading_tip_txt = new Label(binding_panel, _L("Please confirm on the printer screen"));
|
||||
m_loading_tip_txt->SetBackgroundColour(*wxWHITE);
|
||||
m_loading_tip_txt->SetFont(Label::Body_15);
|
||||
|
||||
wxBoxSizer* m_sizer_binding_button = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_sizer_binding_button->Add(0, 0, 1, wxEXPAND, 5);
|
||||
|
||||
m_button_close = new Button(binding_panel, _L("Close"));
|
||||
m_button_close->SetBackgroundColor(btn_bg_white);
|
||||
m_button_close->SetBorderColor(BIND_DIALOG_GREY900);
|
||||
m_button_close->SetSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_close->SetMinSize(BIND_DIALOG_BUTTON_SIZE);
|
||||
m_button_close->SetTextColor(BIND_DIALOG_GREY900);
|
||||
m_button_close->SetCornerRadius(FromDIP(12));
|
||||
m_sizer_binding_button->Add(m_button_close, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
auto sizer_binding = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_binding->Add(0, 0, 0, wxTOP, FromDIP(80));
|
||||
sizer_binding->Add(m_loading_txt, 0, wxALIGN_CENTER, 0);
|
||||
sizer_binding->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer_binding->Add(m_loading_tip_txt, 0, wxALIGN_CENTER, 0);
|
||||
sizer_binding->Add(0, 0, 0, wxTOP, FromDIP(30));
|
||||
sizer_binding->Add(m_sizer_binding_button, 0, wxALIGN_RIGHT | wxRIGHT, FromDIP(20));
|
||||
binding_panel->SetSizer(sizer_binding);
|
||||
binding_panel->Layout();
|
||||
binding_panel->Fit();
|
||||
|
||||
|
||||
|
||||
sizer_main->Add(m_line_top, 0, wxEXPAND, 0);
|
||||
sizer_main->Add(m_simplebook, 0, wxEXPAND, 0);
|
||||
|
||||
|
||||
|
||||
SetSizer(sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
m_button_bind->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_bind_printer), NULL, this);
|
||||
m_button_cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_cancel), NULL, this);
|
||||
m_button_close->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_cancel), NULL, this);
|
||||
|
||||
m_simplebook->SetSelection(0);
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_key_input(wxKeyEvent& evt)
|
||||
{
|
||||
int keyCode = evt.GetKeyCode();
|
||||
|
||||
if (keyCode == WXK_BACK || (keyCode >= '0' && keyCode <= '9') || (keyCode >= 'a' && keyCode <= 'z') || (keyCode >= 'A' && keyCode <= 'Z'))
|
||||
{
|
||||
evt.Skip();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_text_changed(wxCommandEvent& event) {
|
||||
//switch focus to the text text input
|
||||
wxTextCtrl* text_input = static_cast<wxTextCtrl*>(event.GetEventObject());
|
||||
int idx = -1;
|
||||
for (int i = 0; i < PING_CODE_LENGTH; i++) {
|
||||
if (text_input == m_text_input_single_code[i]->GetTextCtrl()) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx != -1 && text_input->GetValue().Length() == 1) {
|
||||
if (idx < PING_CODE_LENGTH-1) {
|
||||
m_text_input_single_code[idx + 1]->SetFocus();
|
||||
}
|
||||
|
||||
auto has_empty = false;
|
||||
for (int i = 0; i < PING_CODE_LENGTH; i++) {
|
||||
if (m_text_input_single_code[i]->GetTextCtrl()->GetValue().ToStdString().empty()) {
|
||||
has_empty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_empty) {
|
||||
m_button_bind->Enable(false);
|
||||
}
|
||||
else {
|
||||
m_button_bind->Enable(true);
|
||||
}
|
||||
|
||||
/*if (idx == PING_CODE_LENGTH - 1) {
|
||||
m_button_bind->Enable(true);
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_key_backspace(wxKeyEvent& event)
|
||||
{
|
||||
wxTextCtrl* text_input = static_cast<wxTextCtrl*>(event.GetEventObject());
|
||||
int idx = -1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (text_input == m_text_input_single_code[i]->GetTextCtrl()) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.GetKeyCode() == WXK_BACK && idx >= 0) {
|
||||
CallAfter([this, idx]() {
|
||||
m_text_input_single_code[idx - 1]->SetFocus();
|
||||
m_button_bind->Enable(false);
|
||||
});
|
||||
}
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_bind_printer(wxCommandEvent& event)
|
||||
{
|
||||
wxString ping_code;
|
||||
|
||||
for (int i = 0; i < PING_CODE_LENGTH; i++) {
|
||||
ping_code += m_text_input_single_code[i]->GetTextCtrl()->GetValue().ToStdString();
|
||||
}
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent && agent->is_user_login() && ping_code.length() == PING_CODE_LENGTH) {
|
||||
auto result = agent->ping_bind(ping_code.ToStdString());
|
||||
|
||||
if(result < 0){
|
||||
MessageDialog msg_wingow(nullptr, _L("Log in failed. Please check the Pin Code."), "", wxAPPLY | wxOK);
|
||||
msg_wingow.ShowModal();
|
||||
return;
|
||||
}
|
||||
m_simplebook->SetSelection(1);
|
||||
}
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_cancel(wxCommandEvent& event)
|
||||
{
|
||||
EndModal(wxCLOSE);
|
||||
}
|
||||
|
||||
void PingCodeBindDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
PingCodeBindDialog::~PingCodeBindDialog() {
|
||||
m_button_bind->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_bind_printer), NULL, this);
|
||||
m_button_cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_cancel), NULL, this);
|
||||
m_button_close->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PingCodeBindDialog::on_cancel), NULL, this);
|
||||
}
|
||||
|
||||
BindMachineDialog::BindMachineDialog(Plater *plater /*= nullptr*/)
|
||||
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Log in printer"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <wx/webrequest.h>
|
||||
#include <wx/hyperlink.h>
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "Widgets/StepCtrl.hpp"
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
@@ -29,15 +28,21 @@
|
||||
#include "BBLStatusBar.hpp"
|
||||
#include "BBLStatusBarBind.hpp"
|
||||
#include "Jobs/Worker.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
#include "Jobs/PrintJob.hpp"
|
||||
#include "Jobs/SendJob.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
|
||||
#define BIND_DIALOG_GREY200 wxColour(248, 248, 248)
|
||||
#define BIND_DIALOG_GREY800 wxColour(50, 58, 61)
|
||||
#define BIND_DIALOG_GREY900 wxColour(38, 46, 48)
|
||||
#define BIND_DIALOG_BUTTON_SIZE wxSize(FromDIP(68), FromDIP(24))
|
||||
#define BIND_DIALOG_BUTTON_PANEL_SIZE wxSize(FromDIP(450), FromDIP(30))
|
||||
#define PING_CODE_LENGTH 6
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class Plater;
|
||||
struct MemoryStruct
|
||||
{
|
||||
char * memory;
|
||||
@@ -45,6 +50,47 @@ struct MemoryStruct
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class PingCodeBindDialog : public DPIDialog
|
||||
{
|
||||
private:
|
||||
|
||||
Label* m_status_text;
|
||||
wxStaticText* m_text_input_title;
|
||||
wxStaticText* m_link_show_ping_code_wiki;
|
||||
TextInput* m_text_input_single_code[PING_CODE_LENGTH];
|
||||
Button* m_button_bind;
|
||||
Button* m_button_cancel;
|
||||
Button* m_button_close;
|
||||
wxSimplebook* m_simplebook;
|
||||
wxPanel* request_bind_panel;
|
||||
wxPanel* binding_panel;
|
||||
|
||||
wxScrolledWindow* m_sw_bind_failed_info;
|
||||
Label* m_bind_failed_info;
|
||||
Label* m_st_txt_error_code{ nullptr };
|
||||
Label* m_st_txt_error_desc{ nullptr };
|
||||
Label* m_st_txt_extra_info{ nullptr };
|
||||
wxHyperlinkCtrl* m_link_network_state{ nullptr };
|
||||
wxString m_result_info;
|
||||
wxString m_result_extra;
|
||||
wxString m_ping_code_wiki;
|
||||
bool m_show_error_info_state = true;
|
||||
|
||||
int m_result_code;
|
||||
std::shared_ptr<BBLStatusBarBind> m_status_bar;
|
||||
|
||||
public:
|
||||
PingCodeBindDialog(Plater* plater = nullptr);
|
||||
~PingCodeBindDialog();
|
||||
|
||||
void on_key_input(wxKeyEvent& evt);
|
||||
void on_text_changed(wxCommandEvent& event);
|
||||
void on_key_backspace(wxKeyEvent& event);
|
||||
void on_cancel(wxCommandEvent& event);
|
||||
void on_bind_printer(wxCommandEvent& event);
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
};
|
||||
|
||||
class BindMachineDialog : public DPIDialog
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -323,7 +323,7 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
|
||||
|
||||
// map of color replaces
|
||||
std::map<std::string, std::string> replaces;
|
||||
replaces["\"#0x00AE42\""] = "\"#009688\"";
|
||||
replaces["\"#0x00AE42\""] = "\"#009688\"";
|
||||
replaces["\"#00FF00\""] = "\"#52c7b8\"";
|
||||
if (dark_mode) {
|
||||
replaces["\"#262E30\""] = "\"#EFEFF0\"";
|
||||
@@ -334,7 +334,7 @@ replaces["\"#0x00AE42\""] = "\"#009688\"";
|
||||
replaces["\"#6B6B6B\""] = "\"#818182\"";
|
||||
replaces["\"#909090\""] = "\"#FFFFFF\"";
|
||||
replaces["\"#00FF00\""] = "\"#FF0000\"";
|
||||
replaces["\"#009688\""] = "\"#00675b\"";
|
||||
replaces["\"#009688\""] = "\"#00675b\"";
|
||||
}
|
||||
//if (!new_color.empty())
|
||||
// replaces["\"#ED6B21\""] = "\"" + new_color + "\"";
|
||||
|
||||
@@ -55,9 +55,10 @@ static wxString get_preset_name_by_filament_id(std::string filament_id)
|
||||
return preset_name;
|
||||
}
|
||||
|
||||
HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history)
|
||||
HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history, bool& show)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Flow Dynamics Calibration Result"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
, m_calib_results_history(calib_results_history)
|
||||
, m_show_history_dialog(show)
|
||||
{
|
||||
this->SetBackgroundColour(*wxWHITE);
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
@@ -73,11 +74,11 @@ HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>&
|
||||
scroll_window->SetSizer(scroll_sizer);
|
||||
|
||||
Button * mew_btn = new Button(scroll_window, _L("New"));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
mew_btn->SetBackgroundColour(*wxWHITE);
|
||||
mew_btn->SetBackgroundColor(btn_bg_green);
|
||||
mew_btn->SetBorderColor(wxColour(0, 174, 66));
|
||||
mew_btn->SetBorderColor(wxColour(0, 150, 136));
|
||||
mew_btn->SetTextColor(wxColour("#FFFFFE"));
|
||||
mew_btn->SetMinSize(wxSize(FromDIP(100), FromDIP(24)));
|
||||
mew_btn->SetMaxSize(wxSize(FromDIP(100), FromDIP(24)));
|
||||
@@ -138,11 +139,14 @@ HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>&
|
||||
m_refresh_timer->SetOwner(this);
|
||||
m_refresh_timer->Start(200);
|
||||
Bind(wxEVT_TIMER, &HistoryWindow::on_timer, this);
|
||||
|
||||
m_show_history_dialog = true;
|
||||
}
|
||||
|
||||
HistoryWindow::~HistoryWindow()
|
||||
{
|
||||
m_refresh_timer->Stop();
|
||||
m_show_history_dialog = false;
|
||||
}
|
||||
|
||||
void HistoryWindow::sync_history_result(MachineObject* obj)
|
||||
@@ -364,6 +368,12 @@ float HistoryWindow::get_nozzle_value()
|
||||
|
||||
void HistoryWindow::on_click_new_button(wxCommandEvent& event)
|
||||
{
|
||||
if (curr_obj && curr_obj->get_printer_series() == PrinterSeries::SERIES_P1P && m_calib_results_history.size() >= 16) {
|
||||
MessageDialog msg_dlg(nullptr, wxString::Format(_L("This machine type can only hold %d history results per nozzle."), 16), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
NewCalibrationHistoryDialog dlg(this, m_calib_results_history);
|
||||
dlg.ShowModal();
|
||||
}
|
||||
@@ -560,7 +570,7 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject
|
||||
}
|
||||
|
||||
NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const std::vector<PACalibResult> history_results)
|
||||
: DPIDialog(parent, wxID_ANY, _L("New Flow Dynamics Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
: DPIDialog(parent, wxID_ANY, _L("New Flow Dynamic Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
, m_history_results(history_results)
|
||||
{
|
||||
Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
@@ -570,6 +580,8 @@ NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
curr_obj = obj;
|
||||
|
||||
this->SetBackgroundColour(*wxWHITE);
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
@@ -628,11 +640,11 @@ NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const
|
||||
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
Button * ok_btn = new Button(top_panel, _L("Ok"));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
ok_btn->SetBackgroundColour(*wxWHITE);
|
||||
ok_btn->SetBackgroundColor(btn_bg_green);
|
||||
ok_btn->SetBorderColor(wxColour(0, 174, 66));
|
||||
ok_btn->SetBorderColor(wxColour(0, 150, 136));
|
||||
ok_btn->SetTextColor(wxColour("#FFFFFE"));
|
||||
ok_btn->SetMinSize(wxSize(-1, FromDIP(24)));
|
||||
ok_btn->SetCornerRadius(FromDIP(12));
|
||||
@@ -699,26 +711,18 @@ void NewCalibrationHistoryDialog::on_ok(wxCommandEvent &event)
|
||||
|
||||
// Check for duplicate names from history
|
||||
{
|
||||
struct PACalibResult
|
||||
{
|
||||
size_t operator()(const std::pair<std::string, std::string> &item) const
|
||||
{
|
||||
return std::hash<string>()(item.first) * std::hash<string>()(item.second);
|
||||
}
|
||||
};
|
||||
std::unordered_set<std::pair<std::string, std::string>, PACalibResult> set;
|
||||
set.insert({m_new_result.name, m_new_result.filament_id});
|
||||
auto iter = std::find_if(m_history_results.begin(), m_history_results.end(), [this](const PACalibResult &item) {
|
||||
return item.name == m_new_result.name && item.filament_id == m_new_result.filament_id;
|
||||
});
|
||||
|
||||
for (auto &result : m_history_results) {
|
||||
if (!set.insert({result.name, result.filament_id}).second) {
|
||||
MessageDialog msg_dlg(nullptr,
|
||||
wxString::Format(_L("There is already a historical calibration result with the same name: %s. Only one of the results with the same name "
|
||||
"is saved. Are you sure you want to override the historical result?"),
|
||||
result.name),
|
||||
wxEmptyString, wxICON_WARNING | wxYES_NO);
|
||||
if (msg_dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
}
|
||||
if (iter != m_history_results.end()) {
|
||||
MessageDialog msg_dlg(nullptr,
|
||||
wxString::Format(_L("There is already a historical calibration result with the same name: %s. Only one of the results with the same name "
|
||||
"is saved. Are you sure you want to override the historical result?"),
|
||||
m_new_result.name),
|
||||
wxEmptyString, wxICON_WARNING | wxYES_NO);
|
||||
if (msg_dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace GUI {
|
||||
|
||||
class HistoryWindow : public DPIDialog {
|
||||
public:
|
||||
HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history);
|
||||
HistoryWindow(wxWindow* parent, const std::vector<PACalibResult>& calib_results_history, bool& show);
|
||||
~HistoryWindow();
|
||||
void on_dpi_changed(const wxRect& suggested_rect) {}
|
||||
void on_select_nozzle(wxCommandEvent& evt);
|
||||
@@ -33,6 +33,7 @@ protected:
|
||||
|
||||
wxTimer* m_refresh_timer { nullptr };
|
||||
|
||||
bool& m_show_history_dialog;
|
||||
std::vector<PACalibResult> m_calib_results_history;
|
||||
MachineObject* curr_obj { nullptr };
|
||||
int history_version = -1;
|
||||
@@ -74,6 +75,7 @@ protected:
|
||||
protected:
|
||||
PACalibResult m_new_result;
|
||||
std::vector<PACalibResult> m_history_results;
|
||||
MachineObject * curr_obj;
|
||||
|
||||
TextInput *m_name_value{nullptr};
|
||||
TextInput *m_k_value{nullptr};
|
||||
|
||||
@@ -18,6 +18,7 @@ static const wxString NA_STR = _L("N/A");
|
||||
static const float MIN_PA_K_VALUE = 0.0;
|
||||
static const float MAX_PA_K_VALUE = 0.3;
|
||||
static const float MIN_PA_K_VALUE_STEP = 0.001;
|
||||
static const int MAX_PA_HISTORY_RESULTS_NUMS = 16;
|
||||
|
||||
std::map<int, Preset*> get_cached_selected_filament(MachineObject* obj) {
|
||||
std::map<int, Preset*> selected_filament_map;
|
||||
@@ -429,7 +430,7 @@ void PressureAdvanceWizard::on_cali_action(wxCommandEvent& evt)
|
||||
{
|
||||
CaliPageActionType action = static_cast<CaliPageActionType>(evt.GetInt());
|
||||
if (action == CaliPageActionType::CALI_ACTION_MANAGE_RESULT) {
|
||||
HistoryWindow history_dialog(this, m_calib_results_history);
|
||||
HistoryWindow history_dialog(this, m_calib_results_history, m_show_result_dialog);
|
||||
history_dialog.on_device_connected(curr_obj);
|
||||
history_dialog.ShowModal();
|
||||
}
|
||||
@@ -467,7 +468,17 @@ void PressureAdvanceWizard::on_cali_action(wxCommandEvent& evt)
|
||||
|
||||
void PressureAdvanceWizard::update(MachineObject* obj)
|
||||
{
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
CalibrationWizard::update(obj);
|
||||
|
||||
if (!m_show_result_dialog) {
|
||||
if (obj->cali_version != -1 && obj->cali_version != cali_version) {
|
||||
cali_version = obj->cali_version;
|
||||
CalibUtils::emit_get_PA_calib_info(obj->nozzle_diameter, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PressureAdvanceWizard::on_device_connected(MachineObject* obj)
|
||||
@@ -648,11 +659,21 @@ void PressureAdvanceWizard::on_cali_start()
|
||||
cali_page->set_pa_cali_image(int(pa_cali_method));
|
||||
curr_obj->manual_pa_cali_method = pa_cali_method;
|
||||
|
||||
CalibUtils::calib_generic_PA(calib_info, wx_err_string);
|
||||
if (curr_obj->pa_calib_tab.size() >= MAX_PA_HISTORY_RESULTS_NUMS) {
|
||||
MessageDialog msg_dlg(nullptr, wxString::Format(_L("This machine type can only hold 16 history results per nozzle. "
|
||||
"You can delete the existing historical results and then start calibration. "
|
||||
"Or you can continue the calibration, but you cannot create new calibration historical results. \n"
|
||||
"Do you still want to continue the calibration?"), MAX_PA_HISTORY_RESULTS_NUMS), wxEmptyString, wxICON_WARNING | wxYES | wxCANCEL);
|
||||
if (msg_dlg.ShowModal() != wxID_YES) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wx_err_string.empty()) {
|
||||
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
if (!CalibUtils::calib_generic_PA(calib_info, wx_err_string)) {
|
||||
if (!wx_err_string.empty()) {
|
||||
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -713,6 +734,30 @@ void PressureAdvanceWizard::on_cali_save()
|
||||
if (!save_page->get_manual_result(new_pa_cali_result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto iter = std::find_if(curr_obj->pa_calib_tab.begin(), curr_obj->pa_calib_tab.end(), [&new_pa_cali_result](const PACalibResult &item) {
|
||||
return item.name == new_pa_cali_result.name && item.filament_id == item.filament_id;
|
||||
});
|
||||
|
||||
if (iter != curr_obj->pa_calib_tab.end()) {
|
||||
MessageDialog
|
||||
msg_dlg(nullptr,
|
||||
wxString::Format(_L("There is already a historical calibration result with the same name: %s. Only one of the results with the same name "
|
||||
"is saved. Are you sure you want to override the historical result?"),
|
||||
new_pa_cali_result.name),
|
||||
wxEmptyString, wxICON_WARNING | wxYES_NO);
|
||||
if (msg_dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
}
|
||||
else if (curr_obj->pa_calib_tab.size() >= MAX_PA_HISTORY_RESULTS_NUMS) {
|
||||
MessageDialog msg_dlg(nullptr,
|
||||
wxString::Format(_L("This machine type can only hold %d history results per nozzle. This result will not be saved."), MAX_PA_HISTORY_RESULTS_NUMS),
|
||||
wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
CalibUtils::set_PA_calib_result({new_pa_cali_result}, false);
|
||||
} else {
|
||||
auto save_page = static_cast<CalibrationPASavePage *>(save_step->page);
|
||||
@@ -1020,7 +1065,13 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
|
||||
calib_info.filament_prest = temp_filament_preset;
|
||||
|
||||
if (cali_stage > 0) {
|
||||
CalibUtils::calib_flowrate(cali_stage, calib_info, wx_err_string);
|
||||
if (!CalibUtils::calib_flowrate(cali_stage, calib_info, wx_err_string)) {
|
||||
if (!wx_err_string.empty()) {
|
||||
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wx_err_string = _L("Internal Error") + wxString(": Invalid calibration stage");
|
||||
|
||||
@@ -121,7 +121,9 @@ protected:
|
||||
|
||||
void on_device_connected(MachineObject* obj) override;
|
||||
|
||||
bool m_show_result_dialog = false;
|
||||
std::vector<PACalibResult> m_calib_results_history;
|
||||
int cali_version = -1;
|
||||
};
|
||||
|
||||
class FlowRateWizard : public CalibrationWizard {
|
||||
|
||||
@@ -382,7 +382,7 @@ void CalibrationCaliPage::update_subtask(MachineObject* obj)
|
||||
m_printing_panel->update_subtask_name(wxString::Format("%s", GUI::from_u8(obj->subtask_name)));
|
||||
|
||||
if (obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
|
||||
m_printing_panel->show_profile_info(true, wxString::FromUTF8(obj->get_modeltask()->profile_name));
|
||||
m_printing_panel->show_profile_info(wxString::FromUTF8(obj->get_modeltask()->profile_name));
|
||||
}
|
||||
else {
|
||||
m_printing_panel->show_profile_info(false);
|
||||
@@ -502,4 +502,4 @@ float CalibrationCaliPage::get_selected_calibration_nozzle_dia(MachineObject* ob
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
}}
|
||||
}}
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <regex>
|
||||
#include "CalibrationWizardPresetPage.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
@@ -312,7 +313,7 @@ void CaliPresetCustomRangePanel::create_panel(wxWindow* parent)
|
||||
m_title_texts[i]->Wrap(-1);
|
||||
m_title_texts[i]->SetFont(::Label::Body_14);
|
||||
item_sizer->Add(m_title_texts[i], 0, wxALL, 0);
|
||||
m_value_inputs[i] = new TextInput(parent, wxEmptyString, _L("\u2103"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, 0);
|
||||
m_value_inputs[i] = new TextInput(parent, wxEmptyString, wxString::FromUTF8("°C"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, 0);
|
||||
m_value_inputs[i]->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
m_value_inputs[i]->GetTextCtrl()->Bind(wxEVT_TEXT, [this, i](wxCommandEvent& event) {
|
||||
std::string number = m_value_inputs[i]->GetTextCtrl()->GetValue().ToStdString();
|
||||
@@ -391,7 +392,7 @@ void CaliPresetTipsPanel::create_panel(wxWindow* parent)
|
||||
auto nozzle_temp_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto nozzle_temp_text = new Label(parent, _L("Nozzle temperature"));
|
||||
nozzle_temp_text->SetFont(Label::Body_12);
|
||||
m_nozzle_temp = new TextInput(parent, wxEmptyString, _L("\u2103"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, wxTE_READONLY);
|
||||
m_nozzle_temp = new TextInput(parent, wxEmptyString, wxString::FromUTF8("°C"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, wxTE_READONLY);
|
||||
m_nozzle_temp->SetBorderWidth(0);
|
||||
nozzle_temp_sizer->Add(nozzle_temp_text, 0, wxALIGN_LEFT);
|
||||
nozzle_temp_sizer->Add(m_nozzle_temp, 0, wxEXPAND);
|
||||
@@ -406,7 +407,7 @@ void CaliPresetTipsPanel::create_panel(wxWindow* parent)
|
||||
auto bed_temp_text = new Label(parent, _L("Bed temperature"));
|
||||
bed_temp_text->SetFont(Label::Body_12);
|
||||
|
||||
m_bed_temp = new Label(parent, _L("- \u2103"));
|
||||
m_bed_temp = new Label(parent, wxString::FromUTF8("- °C"));
|
||||
m_bed_temp->SetFont(Label::Body_12);
|
||||
bed_temp_sizer->Add(bed_temp_text, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(10));
|
||||
bed_temp_sizer->Add(m_bed_temp, 0, wxALIGN_CENTER);
|
||||
@@ -414,7 +415,7 @@ void CaliPresetTipsPanel::create_panel(wxWindow* parent)
|
||||
auto max_flow_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto max_flow_text = new Label(parent, _L("Max volumetric speed"));
|
||||
max_flow_text->SetFont(Label::Body_12);
|
||||
m_max_volumetric_speed = new TextInput(parent, wxEmptyString, _L("mm\u00B3"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, wxTE_READONLY);
|
||||
m_max_volumetric_speed = new TextInput(parent, wxEmptyString, wxString::FromUTF8("mm³"), "", wxDefaultPosition, CALIBRATION_FROM_TO_INPUT_SIZE, wxTE_READONLY);
|
||||
m_max_volumetric_speed->SetBorderWidth(0);
|
||||
max_flow_sizer->Add(max_flow_text, 0, wxALIGN_LEFT);
|
||||
max_flow_sizer->Add(m_max_volumetric_speed, 0, wxEXPAND);
|
||||
@@ -1204,7 +1205,7 @@ void CalibrationPresetPage::update_show_status()
|
||||
show_status(CaliPresetPageStatus::CaliPresetStatusInPrinting);
|
||||
return;
|
||||
}
|
||||
else if (need_check_sdcard(obj_) && obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD) {
|
||||
else if (!obj_->is_support_print_without_sd && (obj_->get_sdcard_state() == MachineObject::SdcardState::NO_SDCARD)) {
|
||||
show_status(CaliPresetPageStatus::CaliPresetStatusNoSdcard);
|
||||
return;
|
||||
}
|
||||
@@ -1424,10 +1425,10 @@ void CalibrationPresetPage::set_cali_method(CalibrationMethod method)
|
||||
m_custom_range_panel->set_titles(titles);
|
||||
|
||||
wxArrayString values;
|
||||
values.push_back(_L("0"));
|
||||
values.push_back(_L("0.5"));
|
||||
values.push_back(_L("0.005"));
|
||||
m_custom_range_panel->set_values(values);
|
||||
values.push_back(wxString::Format(wxT("%.0f"), 0));
|
||||
values.push_back(wxString::Format(wxT("%.2f"), 0.05));
|
||||
values.push_back(wxString::Format(wxT("%.3f"), 0.005));
|
||||
m_custom_range_panel->set_values(values);
|
||||
|
||||
m_custom_range_panel->set_unit("");
|
||||
m_custom_range_panel->Show();
|
||||
@@ -1479,7 +1480,7 @@ void CalibrationPresetPage::on_cali_cancel_job()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "CalibrationWizard::print_job: enter canceled";
|
||||
if (CalibUtils::print_worker) {
|
||||
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
|
||||
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
|
||||
CalibUtils::print_worker->cancel_all();
|
||||
CalibUtils::print_worker->wait_for_idle();
|
||||
}
|
||||
@@ -1913,7 +1914,7 @@ MaxVolumetricSpeedPresetPage::MaxVolumetricSpeedPresetPage(
|
||||
titles.push_back(_L("Step"));
|
||||
m_custom_range_panel->set_titles(titles);
|
||||
|
||||
m_custom_range_panel->set_unit(_L("mm\u00B3/s"));
|
||||
m_custom_range_panel->set_unit("mm³/s");
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
|
||||
// returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis
|
||||
bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; }
|
||||
|
||||
bool is_looking_front() const { return abs(get_dir_up().dot(Vec3d::UnitZ())-1) < 0.001; }
|
||||
// forces camera right vector to be parallel to XY plane
|
||||
void recover_from_free_camera() {
|
||||
if (std::abs(get_dir_right()(2)) > EPSILON)
|
||||
|
||||
+1230
-1024
File diff suppressed because it is too large
Load Diff
@@ -325,6 +325,9 @@ private:
|
||||
std::string access_code;
|
||||
std::string user_access_code;
|
||||
|
||||
// type, time stamp, delay
|
||||
std::vector<std::tuple<std::string, uint64_t, uint64_t>> message_delay;
|
||||
|
||||
public:
|
||||
|
||||
enum LIGHT_EFFECT {
|
||||
@@ -488,6 +491,7 @@ public:
|
||||
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_use_ams { false };
|
||||
bool ams_support_virtual_tray { true };
|
||||
int ams_humidity;
|
||||
@@ -569,7 +573,7 @@ public:
|
||||
int upgrade_display_state = 0; // 0 : upgrade unavailable, 1: upgrade idle, 2: upgrading, 3: upgrade_finished
|
||||
int upgrade_display_hold_count = 0;
|
||||
PrinterFirmwareType firmware_type; // engineer|production
|
||||
PrinterFirmwareType lifecycle { PrinterFirmwareType::FIRMEARE_TYPE_UKNOWN };
|
||||
PrinterFirmwareType lifecycle { PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION };
|
||||
std::string upgrade_progress;
|
||||
std::string upgrade_message;
|
||||
std::string upgrade_status;
|
||||
@@ -615,6 +619,7 @@ public:
|
||||
int curr_layer = 0;
|
||||
int total_layers = 0;
|
||||
bool is_support_layer_num { false };
|
||||
bool nozzle_blob_detection_enabled{ false };
|
||||
|
||||
int cali_version = -1;
|
||||
float cali_selected_nozzle_dia { 0.0 };
|
||||
@@ -754,6 +759,8 @@ public:
|
||||
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};
|
||||
|
||||
int nozzle_max_temperature = -1;
|
||||
int bed_temperature_limit = -1;
|
||||
@@ -844,6 +851,7 @@ public:
|
||||
int command_ams_user_settings(int ams_id, bool start_read_opt, bool tray_read_opt, bool remain_flag = false);
|
||||
int command_ams_user_settings(int ams_id, AmsOptionType op, bool value);
|
||||
int command_ams_switch_filament(bool switch_filament);
|
||||
int command_ams_air_print_detect(bool air_print_detect);
|
||||
int command_ams_calibrate(int ams_id);
|
||||
int command_ams_filament_settings(int ams_id, int tray_id, std::string filament_id, std::string setting_id, std::string tray_color, std::string tray_type, int nozzle_temp_min, int nozzle_temp_max);
|
||||
int command_ams_select_tray(std::string tray_id);
|
||||
@@ -868,6 +876,8 @@ public:
|
||||
// set print option
|
||||
int command_set_printing_option(bool auto_recovery);
|
||||
|
||||
int command_nozzle_blob_detect(bool nozzle_blob_detect);
|
||||
|
||||
// axis string is X, Y, Z, E
|
||||
int command_axis_control(std::string axis, double unit = 1.0f, double input_val = 1.0f, int speed = 3000);
|
||||
|
||||
@@ -932,7 +942,7 @@ public:
|
||||
int publish_json(std::string json_str, int qos = 0);
|
||||
int cloud_publish_json(std::string json_str, int qos = 0);
|
||||
int local_publish_json(std::string json_str, int qos = 0);
|
||||
int parse_json(std::string payload);
|
||||
int parse_json(std::string payload, bool key_filed_only = false);
|
||||
int publish_gcode(std::string gcode_str);
|
||||
|
||||
std::string setting_id_to_type(std::string setting_id, std::string tray_type);
|
||||
@@ -946,14 +956,16 @@ public:
|
||||
bool m_firmware_thread_started { false };
|
||||
void get_firmware_info();
|
||||
bool is_firmware_info_valid();
|
||||
std::string get_string_from_fantype(FanType type);
|
||||
};
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
private:
|
||||
NetworkAgent* m_agent { nullptr };
|
||||
|
||||
public:
|
||||
static bool EnableMultiMachine;
|
||||
|
||||
DeviceManager(NetworkAgent* agent = nullptr);
|
||||
~DeviceManager();
|
||||
void set_agent(NetworkAgent* agent);
|
||||
@@ -978,9 +990,14 @@ public:
|
||||
|
||||
bool set_selected_machine(std::string dev_id, bool need_disconnect = false);
|
||||
MachineObject* get_selected_machine();
|
||||
void add_user_subscribe();
|
||||
void del_user_subscribe();
|
||||
|
||||
void subscribe_device_list(std::vector<std::string> dev_list);
|
||||
|
||||
/* return machine has access code and user machine if login*/
|
||||
std::map<std::string, MachineObject*> get_my_machine_list();
|
||||
std::map<std::string, MachineObject*> 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();
|
||||
@@ -997,6 +1014,11 @@ public:
|
||||
std::map<std::string, MachineObject*> get_local_machine_list();
|
||||
void load_last_machine();
|
||||
|
||||
std::vector<std::string> 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;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
#include "Widgets/TextCtrl.h"
|
||||
|
||||
#include "../Utils/ColorSpaceConvert.hpp"
|
||||
#ifdef __WXOSX__
|
||||
#define wxOSX true
|
||||
#else
|
||||
@@ -1704,6 +1705,7 @@ void ColourPicker::BUILD()
|
||||
if (parent_is_custom_ctrl && m_opt.height < 0)
|
||||
opt_height = (double)temp->GetSize().GetHeight() / m_em_unit;
|
||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
convert_to_picker_widget(temp);
|
||||
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
|
||||
wxGetApp().UpdateDarkUI(temp->GetPickerCtrl());
|
||||
@@ -1760,6 +1762,7 @@ void ColourPicker::set_value(const boost::any& value, bool change_event)
|
||||
|
||||
boost::any& ColourPicker::get_value()
|
||||
{
|
||||
save_colors_to_config();
|
||||
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
|
||||
if (colour == wxTransparentColour)
|
||||
m_value = std::string("");
|
||||
@@ -1798,6 +1801,44 @@ void ColourPicker::sys_color_changed()
|
||||
#endif
|
||||
}
|
||||
|
||||
void ColourPicker::on_button_click(wxCommandEvent &event) {
|
||||
#if !defined(__linux__) && !defined(__LINUX__)
|
||||
if (m_clrData) {
|
||||
std::vector<std::string> 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]));
|
||||
}
|
||||
}
|
||||
m_picker_widget->OnButtonClick(event);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ColourPicker::convert_to_picker_widget(wxColourPickerCtrl *widget)
|
||||
{
|
||||
#if !defined(__linux__) && !defined(__LINUX__)
|
||||
m_picker_widget = dynamic_cast<wxColourPickerWidget*>(widget->GetPickerCtrl());
|
||||
if (m_picker_widget) {
|
||||
m_picker_widget->Bind(wxEVT_BUTTON, &ColourPicker::on_button_click, this);
|
||||
m_clrData = m_picker_widget->GetColourData();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ColourPicker::save_colors_to_config() {
|
||||
#if !defined(__linux__) && !defined(__LINUX__)
|
||||
if (m_clrData) {
|
||||
std::vector<std::string> colors;
|
||||
if (colors.size() != CUSTOM_COLOR_COUNT) {
|
||||
colors.resize(CUSTOM_COLOR_COUNT);
|
||||
}
|
||||
for (int i = 0; i < CUSTOM_COLOR_COUNT; i++) {
|
||||
colors[i] = color_to_string(m_clrData->GetCustomColour(i));
|
||||
}
|
||||
wxGetApp().app_config->save_custom_color_to_config(colors);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PointCtrl::BUILD()
|
||||
{
|
||||
auto temp = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
@@ -481,6 +481,14 @@ public:
|
||||
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); }
|
||||
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); }
|
||||
wxWindow* getWindow() override { return window; }
|
||||
|
||||
private:
|
||||
void convert_to_picker_widget(wxColourPickerCtrl *widget);
|
||||
void on_button_click(wxCommandEvent &WXUNUSED(ev));
|
||||
void save_colors_to_config();
|
||||
private:
|
||||
wxColourData* m_clrData{nullptr};
|
||||
wxColourPickerWidget* m_picker_widget{nullptr};
|
||||
};
|
||||
|
||||
class PointCtrl : public Field {
|
||||
|
||||
@@ -4183,10 +4183,10 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
|
||||
auto plate_extruders = plate->get_extruders(true);
|
||||
for (size_t extruder_id : plate_extruders) {
|
||||
extruder_id -= 1;
|
||||
if (plate_print_statistics.volumes_per_extruder.find(extruder_id) == plate_print_statistics.volumes_per_extruder.end())
|
||||
flushed_volume_of_extruders_all_plates[extruder_id] += 0;
|
||||
if (plate_print_statistics.model_volumes_per_extruder.find(extruder_id) == plate_print_statistics.model_volumes_per_extruder.end())
|
||||
model_volume_of_extruders_all_plates[extruder_id] += 0;
|
||||
else {
|
||||
double model_volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
|
||||
double model_volume = plate_print_statistics.model_volumes_per_extruder.at(extruder_id);
|
||||
model_volume_of_extruders_all_plates[extruder_id] += model_volume;
|
||||
}
|
||||
if (plate_print_statistics.flush_per_filament.find(extruder_id) == plate_print_statistics.flush_per_filament.end())
|
||||
@@ -4736,12 +4736,12 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
|
||||
// used filament statistics
|
||||
for (size_t extruder_id : m_extruder_ids) {
|
||||
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end()) {
|
||||
if (m_print_statistics.model_volumes_per_extruder.find(extruder_id) == m_print_statistics.model_volumes_per_extruder.end()) {
|
||||
model_used_filaments_m.push_back(0.0);
|
||||
model_used_filaments_g.push_back(0.0);
|
||||
}
|
||||
else {
|
||||
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
||||
double volume = m_print_statistics.model_volumes_per_extruder.at(extruder_id);
|
||||
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
||||
model_used_filaments_m.push_back(model_used_filament_m);
|
||||
model_used_filaments_g.push_back(model_used_filament_g);
|
||||
@@ -4862,9 +4862,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
{
|
||||
// calculate used filaments data
|
||||
for (size_t extruder_id : m_extruder_ids) {
|
||||
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
||||
if (m_print_statistics.model_volumes_per_extruder.find(extruder_id) == m_print_statistics.model_volumes_per_extruder.end())
|
||||
continue;
|
||||
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
||||
double volume = m_print_statistics.model_volumes_per_extruder.at(extruder_id);
|
||||
|
||||
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
||||
model_used_filaments_m.push_back(model_used_filament_m);
|
||||
|
||||
@@ -35,6 +35,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent);
|
||||
|
||||
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
|
||||
|
||||
@@ -35,6 +35,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent);
|
||||
|
||||
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
|
||||
|
||||
+166
-7
@@ -3,6 +3,8 @@
|
||||
#include "GUI_Init.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "GUI_Factories.hpp"
|
||||
#include "slic3r/GUI/UserManager.hpp"
|
||||
#include "slic3r/GUI/TaskManager.hpp"
|
||||
#include "format.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
@@ -151,6 +153,7 @@ class MainFrame;
|
||||
|
||||
void start_ping_test()
|
||||
{
|
||||
return;
|
||||
wxArrayString output;
|
||||
wxExecute("ping www.amazon.com", output, wxEXEC_NODISABLE);
|
||||
|
||||
@@ -1599,6 +1602,22 @@ void GUI_App::init_networking_callbacks()
|
||||
return;
|
||||
BOOST_LOG_TRIVIAL(trace) << "static: server connected";
|
||||
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
|
||||
if (this->is_enable_multi_machine()) {
|
||||
auto evt = new wxCommandEvent(EVT_UPDATE_MACHINE_LIST);
|
||||
wxQueueEvent(this, evt);
|
||||
}
|
||||
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
|
||||
//subscribe device
|
||||
if (m_agent->is_user_login()) {
|
||||
m_agent->start_device_subscribe();
|
||||
/* resubscribe the cache dev list */
|
||||
if (this->is_enable_multi_machine()) {
|
||||
DeviceManager* dev = this->getDeviceManager();
|
||||
if (dev && !dev->subscribe_list_cache.empty()) {
|
||||
dev->subscribe_device_list(dev->subscribe_list_cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1618,7 +1637,9 @@ void GUI_App::init_networking_callbacks()
|
||||
obj->command_get_version();
|
||||
obj->erase_user_access_code();
|
||||
obj->command_get_access_code();
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
|
||||
if (!is_enable_multi_machine()) {
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1714,11 +1735,21 @@ void GUI_App::init_networking_callbacks()
|
||||
MachineObject* obj = this->m_device_manager->get_user_machine(dev_id);
|
||||
if (obj) {
|
||||
obj->is_ams_need_update = false;
|
||||
obj->parse_json(msg);
|
||||
|
||||
auto sel = this->m_device_manager->get_selected_machine();
|
||||
if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) {
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
|
||||
|
||||
if (sel && sel->dev_id == dev_id) {
|
||||
obj->parse_json(msg);
|
||||
}
|
||||
else {
|
||||
obj->parse_json(msg, true);
|
||||
}
|
||||
|
||||
|
||||
if (!this->is_enable_multi_machine()) {
|
||||
if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) {
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1726,6 +1757,25 @@ void GUI_App::init_networking_callbacks()
|
||||
|
||||
m_agent->set_on_message_fn(message_arrive_fn);
|
||||
|
||||
auto user_message_arrive_fn = [this](std::string user_id, std::string msg) {
|
||||
if (m_is_closing) {
|
||||
return;
|
||||
}
|
||||
CallAfter([this, user_id, msg] {
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
//check user
|
||||
if (user_id == m_agent->get_user_id()) {
|
||||
this->m_user_manager->parse_json(msg);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
m_agent->set_on_user_message_fn(user_message_arrive_fn);
|
||||
|
||||
|
||||
auto lan_message_arrive_fn = [this](std::string dev_id, std::string msg) {
|
||||
if (m_is_closing) {
|
||||
return;
|
||||
@@ -1740,11 +1790,15 @@ void GUI_App::init_networking_callbacks()
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
obj->parse_json(msg);
|
||||
obj->parse_json(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 = m_device_manager->get_local_machine(dev_id);
|
||||
if (obj) {
|
||||
obj->parse_json(msg, DeviceManager::key_field_only);
|
||||
}
|
||||
});
|
||||
};
|
||||
m_agent->set_on_local_message_fn(lan_message_arrive_fn);
|
||||
@@ -2054,6 +2108,11 @@ int GUI_App::OnExit()
|
||||
m_device_manager = nullptr;
|
||||
}
|
||||
|
||||
if (m_user_manager) {
|
||||
delete m_user_manager;
|
||||
m_user_manager = nullptr;
|
||||
}
|
||||
|
||||
if (m_agent) {
|
||||
// BBS avoid a crash on mac platform
|
||||
#ifdef __WINDOWS__
|
||||
@@ -2402,6 +2461,7 @@ bool GUI_App::on_init_inner()
|
||||
preset_bundle->set_default_suppressed(true);
|
||||
|
||||
Bind(EVT_SET_SELECTED_MACHINE, &GUI_App::on_set_selected_machine, this);
|
||||
Bind(EVT_UPDATE_MACHINE_LIST, &GUI_App::on_update_machine_list, this);
|
||||
Bind(EVT_USER_LOGIN, &GUI_App::on_user_login, this);
|
||||
Bind(EVT_USER_LOGIN_HANDLE, &GUI_App::on_user_login_handle, this);
|
||||
Bind(EVT_CHECK_PRIVACY_VER, &GUI_App::on_check_privacy_update, this);
|
||||
@@ -2724,6 +2784,22 @@ __retry:
|
||||
else
|
||||
m_device_manager->set_agent(m_agent);
|
||||
|
||||
if (!m_user_manager)
|
||||
m_user_manager = new Slic3r::UserManager(m_agent);
|
||||
else
|
||||
m_user_manager->set_agent(m_agent);
|
||||
|
||||
if (this->is_enable_multi_machine()) {
|
||||
if (!m_task_manager) {
|
||||
m_task_manager = new Slic3r::TaskManager(m_agent);
|
||||
m_task_manager->start();
|
||||
}
|
||||
m_agent->enable_multi_machine(true);
|
||||
DeviceManager::EnableMultiMachine = true;
|
||||
} else {
|
||||
m_agent->enable_multi_machine(false);
|
||||
DeviceManager::EnableMultiMachine = false;
|
||||
}
|
||||
|
||||
//BBS set config dir
|
||||
if (m_agent) {
|
||||
@@ -2753,6 +2829,9 @@ __retry:
|
||||
|
||||
if (!m_device_manager)
|
||||
m_device_manager = new Slic3r::DeviceManager();
|
||||
|
||||
if (!m_user_manager)
|
||||
m_user_manager = new Slic3r::UserManager();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -3794,6 +3873,21 @@ std::string GUI_App::handle_web_request(std::string cmd)
|
||||
if (path.has_value()) {
|
||||
wxLaunchDefaultBrowser(path.value());
|
||||
}
|
||||
}
|
||||
else if (command_str.compare("homepage_makerlab_get") == 0) {
|
||||
//if (mainframe->m_webview) { mainframe->m_webview->SendMakerlabList(); }
|
||||
}
|
||||
else if (command_str.compare("makerworld_model_open") == 0)
|
||||
{
|
||||
if (root.get_child_optional("model") != boost::none) {
|
||||
pt::ptree data_node = root.get_child("model");
|
||||
boost::optional<std::string> path = data_node.get_optional<std::string>("url");
|
||||
if (path.has_value())
|
||||
{
|
||||
wxString realurl = from_u8(url_decode(path.value()));
|
||||
wxGetApp().request_model_download(realurl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3947,9 +4041,17 @@ void GUI_App::enable_user_preset_folder(bool enable)
|
||||
void GUI_App::on_set_selected_machine(wxCommandEvent &evt)
|
||||
{
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev || m_agent) return;
|
||||
if (dev) {
|
||||
dev->set_selected_machine(m_agent->get_user_selected_machine());
|
||||
}
|
||||
}
|
||||
|
||||
dev->set_selected_machine(m_agent->get_user_selected_machine());
|
||||
void GUI_App::on_update_machine_list(wxCommandEvent &evt)
|
||||
{
|
||||
/* DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (dev) {
|
||||
dev->add_user_subscribe();
|
||||
}*/
|
||||
}
|
||||
|
||||
void GUI_App::on_user_login_handle(wxCommandEvent &evt)
|
||||
@@ -4383,6 +4485,24 @@ std::string GUI_App::format_display_version()
|
||||
return version_display;
|
||||
}
|
||||
|
||||
std::string GUI_App::format_IP(const std::string& ip)
|
||||
{
|
||||
std::string format_ip = ip;
|
||||
size_t pos_st = 0;
|
||||
size_t pos_en = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
pos_en = format_ip.find('.', pos_st + 1);
|
||||
if (pos_en == std::string::npos) {
|
||||
return ip;
|
||||
}
|
||||
format_ip.replace(pos_st, pos_en - pos_st, "***");
|
||||
pos_st = pos_en + 1;
|
||||
}
|
||||
|
||||
return format_ip;
|
||||
}
|
||||
|
||||
void GUI_App::show_dialog(wxString msg)
|
||||
{
|
||||
if (m_info_dialog_content.empty()) {
|
||||
@@ -4393,6 +4513,26 @@ void GUI_App::show_dialog(wxString msg)
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::push_notification(wxString msg, wxString title, UserNotificationStyle style)
|
||||
{
|
||||
if (!this->is_enable_multi_machine()) {
|
||||
if (style == UserNotificationStyle::UNS_NORMAL) {
|
||||
if (m_info_dialog_content.empty()) {
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_DIALOG);
|
||||
evt->SetString(msg);
|
||||
GUI::wxGetApp().QueueEvent(evt);
|
||||
m_info_dialog_content = msg;
|
||||
}
|
||||
}
|
||||
else if (style == UserNotificationStyle::UNS_WARNING_CONFIRM) {
|
||||
GUI::wxGetApp().CallAfter([msg, title] {
|
||||
GUI::MessageDialog msg_dlg(nullptr, msg, title, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::reload_settings()
|
||||
{
|
||||
if (preset_bundle && m_agent) {
|
||||
@@ -5964,6 +6104,25 @@ std::string GUI_App::url_encode(std::string value) {
|
||||
return Http::url_encode(value);
|
||||
}
|
||||
|
||||
void GUI_App::popup_ping_bind_dialog()
|
||||
{
|
||||
if (m_ping_code_binding_dialog == nullptr) {
|
||||
m_ping_code_binding_dialog = new PingCodeBindDialog();
|
||||
m_ping_code_binding_dialog->ShowModal();
|
||||
remove_ping_bind_dialog();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI_App::remove_ping_bind_dialog()
|
||||
{
|
||||
if (m_ping_code_binding_dialog != nullptr) {
|
||||
m_ping_code_binding_dialog->Destroy();
|
||||
delete m_mall_publish_dialog;
|
||||
m_ping_code_binding_dialog = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GUI_App::remove_mall_system_dialog()
|
||||
{
|
||||
if (m_mall_publish_dialog != nullptr) {
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
#include "slic3r/GUI/UserNotification.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/GUI/WebViewDialog.hpp"
|
||||
#include "slic3r/GUI/WebUserLoginDialog.hpp"
|
||||
#include "slic3r/GUI/BindDialog.hpp"
|
||||
#include "slic3r/GUI/HMS.hpp"
|
||||
#include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp"
|
||||
#include "slic3r/GUI/HttpServer.hpp"
|
||||
@@ -55,8 +57,10 @@ class PresetBundle;
|
||||
class PresetUpdater;
|
||||
class ModelObject;
|
||||
class Model;
|
||||
class UserManager;
|
||||
class DeviceManager;
|
||||
class NetworkAgent;
|
||||
class TaskManager;
|
||||
|
||||
namespace GUI{
|
||||
|
||||
@@ -74,6 +78,7 @@ struct GUI_InitParams;
|
||||
class ParamsDialog;
|
||||
class HMSQuery;
|
||||
class ModelMallDialog;
|
||||
class PingCodeBindDialog;
|
||||
|
||||
|
||||
enum FileType
|
||||
@@ -273,6 +278,8 @@ private:
|
||||
//BBS
|
||||
bool m_is_closing {false};
|
||||
Slic3r::DeviceManager* m_device_manager { nullptr };
|
||||
Slic3r::UserManager* m_user_manager { nullptr };
|
||||
Slic3r::TaskManager* m_task_manager { nullptr };
|
||||
NetworkAgent* m_agent { nullptr };
|
||||
std::vector<std::string> need_delete_presets; // store setting ids of preset
|
||||
std::vector<bool> m_create_preset_blocked { false, false, false, false, false, false }; // excceed limit
|
||||
@@ -307,6 +314,7 @@ private:
|
||||
bool OnInit() override;
|
||||
int OnExit() override;
|
||||
bool initialized() const { return m_initialized; }
|
||||
inline bool is_enable_multi_machine() { return this->app_config&& this->app_config->get("enable_multi_machine") == "true"; }
|
||||
|
||||
std::map<std::string, bool> test_url_state;
|
||||
|
||||
@@ -318,6 +326,7 @@ private:
|
||||
void show_message_box(std::string msg) { wxMessageBox(msg); }
|
||||
EAppMode get_app_mode() const { return m_app_mode; }
|
||||
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
|
||||
Slic3r::TaskManager* getTaskManager() { return m_task_manager; }
|
||||
HMSQuery* get_hms_query() { return hms_query; }
|
||||
NetworkAgent* getAgent() { return m_agent; }
|
||||
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
|
||||
@@ -442,6 +451,7 @@ private:
|
||||
void handle_http_error(unsigned int status, std::string body);
|
||||
void on_http_error(wxCommandEvent &evt);
|
||||
void on_set_selected_machine(wxCommandEvent& evt);
|
||||
void on_update_machine_list(wxCommandEvent& evt);
|
||||
void on_user_login(wxCommandEvent &evt);
|
||||
void on_user_login_handle(wxCommandEvent& evt);
|
||||
void enable_user_preset_folder(bool enable);
|
||||
@@ -460,7 +470,9 @@ private:
|
||||
void set_skip_version(bool skip = true);
|
||||
void no_new_version();
|
||||
static std::string format_display_version();
|
||||
std::string format_IP(const std::string& ip);
|
||||
void show_dialog(wxString msg);
|
||||
void push_notification(wxString msg, wxString title = wxEmptyString, UserNotificationStyle style = UserNotificationStyle::UNS_NORMAL);
|
||||
void reload_settings();
|
||||
void remove_user_presets();
|
||||
void sync_preset(Preset* preset);
|
||||
@@ -552,6 +564,7 @@ private:
|
||||
std::string m_mall_model_download_url;
|
||||
std::string m_mall_model_download_name;
|
||||
ModelMallDialog* m_mall_publish_dialog{ nullptr };
|
||||
PingCodeBindDialog* m_ping_code_binding_dialog{ nullptr };
|
||||
|
||||
void set_download_model_url(std::string url) {m_mall_model_download_url = url;}
|
||||
void set_download_model_name(std::string name) {m_mall_model_download_name = name;}
|
||||
@@ -570,6 +583,9 @@ private:
|
||||
std::string url_encode(std::string value);
|
||||
std::string url_decode(std::string value);
|
||||
|
||||
void popup_ping_bind_dialog();
|
||||
void remove_ping_bind_dialog();
|
||||
|
||||
// Parameters extracted from the command line to be passed to GUI after initialization.
|
||||
GUI_InitParams* init_params { nullptr };
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#include <codecvt>
|
||||
#include "wx/fontenum.h"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@@ -34,6 +35,119 @@ static const wxColour FONT_TEXTURE_FG = *wxWHITE;
|
||||
static const int FONT_SIZE = 12;
|
||||
static const float SELECTABLE_INNER_OFFSET = 8.0f;
|
||||
|
||||
static std::vector<std::string> font_black_list = {
|
||||
#ifdef _WIN32
|
||||
"MT Extra",
|
||||
"Marlett",
|
||||
"Symbol",
|
||||
"Webdings",
|
||||
"Wingdings",
|
||||
"Wingdings 2",
|
||||
"Wingdings 3",
|
||||
#endif
|
||||
};
|
||||
|
||||
static const wxFontEncoding font_encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
||||
|
||||
#ifdef _WIN32
|
||||
static bool load_hfont(void *hfont, DWORD &dwTable, DWORD &dwOffset, size_t &size, HDC hdc = nullptr)
|
||||
{
|
||||
bool del_hdc = false;
|
||||
if (hdc == nullptr) {
|
||||
del_hdc = true;
|
||||
hdc = ::CreateCompatibleDC(NULL);
|
||||
if (hdc == NULL) return false;
|
||||
}
|
||||
|
||||
// To retrieve the data from the beginning of the file for TrueType
|
||||
// Collection files specify 'ttcf' (0x66637474).
|
||||
dwTable = 0x66637474;
|
||||
dwOffset = 0;
|
||||
|
||||
::SelectObject(hdc, hfont);
|
||||
size = ::GetFontData(hdc, dwTable, dwOffset, NULL, 0);
|
||||
if (size == GDI_ERROR) {
|
||||
// HFONT is NOT TTC(collection)
|
||||
dwTable = 0;
|
||||
size = ::GetFontData(hdc, dwTable, dwOffset, NULL, 0);
|
||||
}
|
||||
|
||||
if (size == 0 || size == GDI_ERROR) {
|
||||
if (del_hdc) ::DeleteDC(hdc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
bool can_load(const wxFont &font)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD dwTable = 0, dwOffset = 0;
|
||||
size_t size = 0;
|
||||
void* hfont = font.GetHFONT();
|
||||
if (!load_hfont(hfont, dwTable, dwOffset, size))
|
||||
return false;
|
||||
return hfont != nullptr;
|
||||
#elif defined(__APPLE__)
|
||||
return true;
|
||||
#elif defined(__linux__)
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> init_face_names()
|
||||
{
|
||||
std::vector<std::string> valid_font_names;
|
||||
wxArrayString facenames = wxFontEnumerator::GetFacenames(font_encoding);
|
||||
std::vector<wxString> bad_fonts;
|
||||
|
||||
// validation lambda
|
||||
auto is_valid_font = [coding = font_encoding, bad = bad_fonts](const wxString &name) {
|
||||
if (name.empty())
|
||||
return false;
|
||||
|
||||
// vertical font start with @, we will filter it out
|
||||
// Not sure if it is only in Windows so filtering is on all platforms
|
||||
if (name[0] == '@')
|
||||
return false;
|
||||
|
||||
// previously detected bad font
|
||||
auto it = std::lower_bound(bad.begin(), bad.end(), name);
|
||||
if (it != bad.end() && *it == name)
|
||||
return false;
|
||||
|
||||
wxFont wx_font(wxFontInfo().FaceName(name).Encoding(coding));
|
||||
// Faster chech if wx_font is loadable but not 100%
|
||||
// names could contain not loadable font
|
||||
if (!wx_font.IsOk())
|
||||
return false;
|
||||
|
||||
if (!can_load(wx_font))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
std::sort(facenames.begin(), facenames.end());
|
||||
for (const wxString &name : facenames) {
|
||||
if (is_valid_font(name)) {
|
||||
valid_font_names.push_back(name.ToStdString());
|
||||
}
|
||||
else {
|
||||
bad_fonts.emplace_back(name);
|
||||
}
|
||||
}
|
||||
assert(std::is_sorted(bad_fonts.begin(), bad_fonts.end()));
|
||||
|
||||
for (auto iter = font_black_list.begin(); iter != font_black_list.end(); ++iter) {
|
||||
valid_font_names.erase(std::remove(valid_font_names.begin(), valid_font_names.end(), *iter), valid_font_names.end());
|
||||
}
|
||||
|
||||
return valid_font_names;
|
||||
}
|
||||
|
||||
class Line_3D
|
||||
{
|
||||
public:
|
||||
@@ -142,7 +256,9 @@ GLGizmoText::~GLGizmoText()
|
||||
|
||||
bool GLGizmoText::on_init()
|
||||
{
|
||||
m_avail_font_names = init_occt_fonts();
|
||||
m_avail_font_names = init_face_names();
|
||||
|
||||
//m_avail_font_names = init_occt_fonts();
|
||||
update_font_texture();
|
||||
m_scale = m_imgui->get_font_size();
|
||||
m_shortcut_key = WXK_CONTROL_T;
|
||||
|
||||
+94
-53
@@ -41,30 +41,45 @@ int get_hms_info_version(std::string& version)
|
||||
return result;
|
||||
}
|
||||
|
||||
int HMSQuery::download_hms_info()
|
||||
int HMSQuery::download_hms_related(std::string hms_type, json* receive_json)
|
||||
{
|
||||
std::string local_version = "0";
|
||||
load_from_local(local_version, hms_type, receive_json);
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
if (!config) return -1;
|
||||
|
||||
std::string hms_host = wxGetApp().app_config->get_hms_host();
|
||||
std::string lang;
|
||||
std::string query_params = HMSQuery::build_query_params(lang);
|
||||
std::string url = (boost::format("https://%1%/query.php?%2%") % hms_host % query_params).str();
|
||||
std::string url;
|
||||
if (hms_type.compare(QUERY_HMS_INFO) == 0) {
|
||||
url = (boost::format("https://%1%/query.php?%2%&v=%3%") % hms_host % query_params % local_version).str();
|
||||
}
|
||||
else if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
|
||||
url = (boost::format("https://%1%/hms/GetActionImage.php?v=%2%") % hms_host % local_version).str();
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "hms: download url = " << url;
|
||||
|
||||
Slic3r::Http http = Slic3r::Http::get(url);
|
||||
m_hms_json.clear();
|
||||
http.on_complete([this](std::string body, unsigned status) {
|
||||
http.on_complete([this, receive_json, hms_type](std::string body, unsigned status) {
|
||||
try {
|
||||
json j = json::parse(body);
|
||||
if (j.contains("result")) {
|
||||
if (j["result"] == 0 && j.contains("data")) {
|
||||
this->m_hms_json = j["data"];
|
||||
if (hms_type.compare(QUERY_HMS_INFO) == 0) {
|
||||
(*receive_json) = j["data"];
|
||||
this->save_local = true;
|
||||
}
|
||||
else if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
|
||||
(*receive_json)["data"] = j["data"];
|
||||
this->save_local = true;
|
||||
}
|
||||
if (j.contains("ver"))
|
||||
m_hms_json["version"] = std::to_string(j["ver"].get<long long>());
|
||||
} else {
|
||||
this->m_hms_json.clear();
|
||||
(*receive_json)["version"] = std::to_string(j["ver"].get<long long>());
|
||||
} else if (j["result"] == 201){
|
||||
BOOST_LOG_TRIVIAL(info) << "HMSQuery: HMS info is the latest version";
|
||||
}else{
|
||||
receive_json->clear();
|
||||
BOOST_LOG_TRIVIAL(info) << "HMSQuery: update hms info error = " << j["result"].get<int>();
|
||||
}
|
||||
}
|
||||
@@ -77,19 +92,21 @@ int HMSQuery::download_hms_info()
|
||||
BOOST_LOG_TRIVIAL(error) << "HMSQuery: update hms info error = " << error << ", body = " << body << ", status = " << status;
|
||||
}).perform_sync();
|
||||
|
||||
if (!m_hms_json.empty())
|
||||
save_to_local(lang);
|
||||
if (!receive_json->empty() && save_local == true) {
|
||||
save_to_local(lang, hms_type, *receive_json);
|
||||
save_local = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HMSQuery::load_from_local(std::string &version_info)
|
||||
int HMSQuery::load_from_local(std::string& version_info, std::string hms_type, json* load_json)
|
||||
{
|
||||
if (data_dir().empty()) {
|
||||
version_info = "";
|
||||
version_info = "0";
|
||||
BOOST_LOG_TRIVIAL(error) << "HMS: load_from_local, data_dir() is empty";
|
||||
return -1;
|
||||
}
|
||||
std::string filename = get_hms_file(HMSQuery::hms_language_code());
|
||||
std::string filename = get_hms_file(hms_type, HMSQuery::hms_language_code());
|
||||
auto hms_folder = (boost::filesystem::path(data_dir()) / "hms");
|
||||
if (!fs::exists(hms_folder))
|
||||
fs::create_directory(hms_folder);
|
||||
@@ -98,9 +115,9 @@ int HMSQuery::load_from_local(std::string &version_info)
|
||||
std::ifstream json_file(encode_path(dir_str.c_str()));
|
||||
try {
|
||||
if (json_file.is_open()) {
|
||||
json_file >> m_hms_json;
|
||||
if (m_hms_json.contains("version")) {
|
||||
version_info = m_hms_json["version"].get<std::string>();
|
||||
json_file >> (*load_json);
|
||||
if ((*load_json).contains("version")) {
|
||||
version_info = (*load_json)["version"].get<std::string>();
|
||||
return 0;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "HMS: load_from_local, no version info";
|
||||
@@ -108,28 +125,28 @@ int HMSQuery::load_from_local(std::string &version_info)
|
||||
}
|
||||
}
|
||||
} catch(...) {
|
||||
version_info = "";
|
||||
version_info = "0";
|
||||
BOOST_LOG_TRIVIAL(error) << "HMS: load_from_local failed";
|
||||
return -1;
|
||||
}
|
||||
version_info = "";
|
||||
version_info = "0";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HMSQuery::save_to_local(std::string lang)
|
||||
int HMSQuery::save_to_local(std::string lang, std::string hms_type, json save_json)
|
||||
{
|
||||
if (data_dir().empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "HMS: save_to_local, data_dir() is empty";
|
||||
return -1;
|
||||
}
|
||||
std::string filename = get_hms_file(lang);
|
||||
std::string filename = get_hms_file(hms_type,lang);
|
||||
auto hms_folder = (boost::filesystem::path(data_dir()) / "hms");
|
||||
if (!fs::exists(hms_folder))
|
||||
fs::create_directory(hms_folder);
|
||||
std::string dir_str = (hms_folder / filename).make_preferred().string();
|
||||
std::ofstream json_file(encode_path(dir_str.c_str()));
|
||||
if (json_file.is_open()) {
|
||||
json_file << std::setw(4) << m_hms_json << std::endl;
|
||||
json_file << std::setw(4) << save_json << std::endl;
|
||||
json_file.close();
|
||||
return 0;
|
||||
}
|
||||
@@ -166,9 +183,13 @@ std::string HMSQuery::build_query_params(std::string& lang)
|
||||
return query_params;
|
||||
}
|
||||
|
||||
std::string HMSQuery::get_hms_file(std::string lang)
|
||||
std::string HMSQuery::get_hms_file(std::string hms_type, std::string lang)
|
||||
{
|
||||
//std::string lang_code = HMSQuery::hms_language_code();
|
||||
//return hms action filename
|
||||
if (hms_type.compare(QUERY_HMS_ACTION) == 0) {
|
||||
return (boost::format("hms_action.json")).str();
|
||||
}
|
||||
//return hms filename
|
||||
return (boost::format("hms_%1%.json") % lang).str();
|
||||
}
|
||||
|
||||
@@ -185,9 +206,9 @@ wxString HMSQuery::_query_hms_msg(std::string long_error_code, std::string lang_
|
||||
if (long_error_code.empty())
|
||||
return wxEmptyString;
|
||||
|
||||
if (m_hms_json.contains("device_hms")) {
|
||||
if (m_hms_json["device_hms"].contains(lang_code)) {
|
||||
for (auto item = m_hms_json["device_hms"][lang_code].begin(); item != m_hms_json["device_hms"][lang_code].end(); item++) {
|
||||
if (m_hms_info_json.contains("device_hms")) {
|
||||
if (m_hms_info_json["device_hms"].contains(lang_code)) {
|
||||
for (auto item = m_hms_info_json["device_hms"][lang_code].begin(); item != m_hms_info_json["device_hms"][lang_code].end(); item++) {
|
||||
if (item->contains("ecode")) {
|
||||
std::string temp_string = (*item)["ecode"].get<std::string>();
|
||||
if (boost::to_upper_copy(temp_string) == long_error_code) {
|
||||
@@ -201,8 +222,8 @@ wxString HMSQuery::_query_hms_msg(std::string long_error_code, std::string lang_
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "hms: query_hms_msg, do not contains lang_code = " << lang_code;
|
||||
// return first language
|
||||
if (!m_hms_json["device_hms"].empty()) {
|
||||
for (auto lang : m_hms_json["device_hms"]) {
|
||||
if (!m_hms_info_json["device_hms"].empty()) {
|
||||
for (auto lang : m_hms_info_json["device_hms"]) {
|
||||
for (auto item = lang.begin(); item != lang.end(); item++) {
|
||||
if (item->contains("ecode")) {
|
||||
std::string temp_string = (*item)["ecode"].get<std::string>();
|
||||
@@ -225,9 +246,9 @@ wxString HMSQuery::_query_hms_msg(std::string long_error_code, std::string lang_
|
||||
|
||||
wxString HMSQuery::_query_error_msg(std::string error_code, std::string lang_code)
|
||||
{
|
||||
if (m_hms_json.contains("device_error")) {
|
||||
if (m_hms_json["device_error"].contains(lang_code)) {
|
||||
for (auto item = m_hms_json["device_error"][lang_code].begin(); item != m_hms_json["device_error"][lang_code].end(); item++) {
|
||||
if (m_hms_info_json.contains("device_error")) {
|
||||
if (m_hms_info_json["device_error"].contains(lang_code)) {
|
||||
for (auto item = m_hms_info_json["device_error"][lang_code].begin(); item != m_hms_info_json["device_error"][lang_code].end(); item++) {
|
||||
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
|
||||
if (item->contains("intro")) {
|
||||
return wxString::FromUTF8((*item)["intro"].get<std::string>());
|
||||
@@ -238,8 +259,8 @@ wxString HMSQuery::_query_error_msg(std::string error_code, std::string lang_cod
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "hms: query_error_msg, do not contains lang_code = " << lang_code;
|
||||
// return first language
|
||||
if (!m_hms_json["device_error"].empty()) {
|
||||
for (auto lang : m_hms_json["device_error"]) {
|
||||
if (!m_hms_info_json["device_error"].empty()) {
|
||||
for (auto lang : m_hms_info_json["device_error"]) {
|
||||
for (auto item = lang.begin(); item != lang.end(); item++) {
|
||||
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == error_code) {
|
||||
if (item->contains("intro")) {
|
||||
@@ -258,6 +279,33 @@ wxString HMSQuery::_query_error_msg(std::string error_code, std::string lang_cod
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString HMSQuery::_query_error_url_action(std::string long_error_code, std::string dev_id, std::vector<int>& button_action)
|
||||
{
|
||||
if (m_hms_action_json.contains("data")) {
|
||||
for (auto item = m_hms_action_json["data"].begin(); item != m_hms_action_json["data"].end(); item++) {
|
||||
if (item->contains("ecode") && boost::to_upper_copy((*item)["ecode"].get<std::string>()) == long_error_code) {
|
||||
if (item->contains("device") && (boost::to_upper_copy((*item)["device"].get<std::string>()) == dev_id ||
|
||||
(*item)["device"].get<std::string>() == "default")) {
|
||||
if (item->contains("actions")) {
|
||||
for (auto item_actions = (*item)["actions"].begin(); item_actions != (*item)["actions"].end(); item_actions++) {
|
||||
button_action.emplace_back(item_actions->get<int>());
|
||||
}
|
||||
}
|
||||
if (item->contains("image")) {
|
||||
return wxString::FromUTF8((*item)["image"].get<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << "data is not exists";
|
||||
return wxEmptyString;
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
wxString HMSQuery::query_print_error_msg(int print_error)
|
||||
{
|
||||
char buf[32];
|
||||
@@ -266,29 +314,22 @@ wxString HMSQuery::query_print_error_msg(int print_error)
|
||||
return _query_error_msg(std::string(buf), lang_code);
|
||||
}
|
||||
|
||||
wxString HMSQuery::query_print_error_url_action(int print_error, std::string dev_id, std::vector<int>& button_action)
|
||||
{
|
||||
char buf[32];
|
||||
::sprintf(buf, "%08X", print_error);
|
||||
//The first three digits of SN number
|
||||
dev_id = dev_id.substr(0, 3);
|
||||
return _query_error_url_action(std::string(buf), dev_id, button_action);
|
||||
}
|
||||
|
||||
|
||||
int HMSQuery::check_hms_info()
|
||||
{
|
||||
boost::thread check_thread = boost::thread([this] {
|
||||
bool download_new_hms_info = true;
|
||||
// load local hms json file
|
||||
std::string version = "";
|
||||
if (load_from_local(version) == 0) {
|
||||
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info current version = " << version;
|
||||
std::string new_version;
|
||||
get_hms_info_version(new_version);
|
||||
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info latest version = " << new_version;
|
||||
|
||||
if (new_version.empty()) {return 0;}
|
||||
|
||||
if (!version.empty() && version == new_version) {
|
||||
download_new_hms_info = false;
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "HMS: check_hms_info need download new hms info = " << download_new_hms_info;
|
||||
// download if version is update
|
||||
if (download_new_hms_info) {
|
||||
download_hms_info();
|
||||
}
|
||||
download_hms_related(QUERY_HMS_INFO, &m_hms_info_json);
|
||||
download_hms_related(QUERY_HMS_ACTION, &m_hms_action_json);
|
||||
return 0;
|
||||
});
|
||||
return 0;
|
||||
|
||||
+14
-7
@@ -16,23 +16,30 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define HMS_INFO_FILE "hms.json"
|
||||
#define QUERY_HMS_INFO "query_hms_info"
|
||||
#define QUERY_HMS_ACTION "query_hms_action"
|
||||
|
||||
class HMSQuery {
|
||||
protected:
|
||||
json m_hms_json;
|
||||
int download_hms_info();
|
||||
int load_from_local(std::string& version_info);
|
||||
int save_to_local(std::string lang);
|
||||
std::string get_hms_file(std::string lang);
|
||||
wxString _query_hms_msg(std::string long_error_code, std::string lang_code = "en");
|
||||
wxString _query_error_msg(std::string long_error_code, std::string lang_code = "en");
|
||||
json m_hms_info_json;
|
||||
json m_hms_action_json;
|
||||
int download_hms_related(std::string hms_type,json* receive_json);
|
||||
int load_from_local(std::string& version_info, std::string hms_type, json* load_json);
|
||||
int save_to_local(std::string lang, std::string hms_type,json save_json);
|
||||
std::string get_hms_file(std::string hms_type, std::string lang = std::string("en"));
|
||||
wxString _query_hms_msg(std::string long_error_code, std::string lang_code = std::string("en"));
|
||||
wxString _query_error_msg(std::string long_error_code, std::string lang_code = std::string("en"));
|
||||
wxString _query_error_url_action(std::string long_error_code, std::string dev_id, std::vector<int>& button_action);
|
||||
public:
|
||||
HMSQuery() {}
|
||||
int check_hms_info();
|
||||
wxString query_hms_msg(std::string long_error_code);
|
||||
wxString query_print_error_msg(int print_error);
|
||||
wxString query_print_error_url_action(int print_error, std::string dev_id, std::vector<int>& button_action);
|
||||
static std::string hms_language_code();
|
||||
static std::string build_query_params(std::string& lang);
|
||||
|
||||
bool save_local = false;
|
||||
};
|
||||
|
||||
int get_hms_info_version(std::string &version);
|
||||
|
||||
@@ -124,9 +124,9 @@ void BindJob::process(Ctl &ctl)
|
||||
}
|
||||
dev->update_user_machine_list_info();
|
||||
|
||||
wxCommandEvent event(EVT_BIND_MACHINE_SUCCESS);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
wxCommandEvent event(EVT_BIND_MACHINE_SUCCESS);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -979,7 +979,8 @@ TriangleMesh create_default_mesh()
|
||||
std::string path = Slic3r::resources_dir() + "/data/embossed_text.obj";
|
||||
TriangleMesh triangle_mesh;
|
||||
std::string message;
|
||||
if (!load_obj(path.c_str(), &triangle_mesh, message)) {
|
||||
ObjInfo obj_info;
|
||||
if (!load_obj(path.c_str(), &triangle_mesh, obj_info, message)) {
|
||||
// when can't load mesh use cube
|
||||
return TriangleMesh(its_make_cube(36., 4., 2.5));
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ wxDEFINE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
|
||||
|
||||
|
||||
@@ -1078,14 +1079,21 @@ void MainFrame::init_tabpanel() {
|
||||
m_printer_view->load_url(url, key);
|
||||
});
|
||||
m_printer_view->Hide();
|
||||
|
||||
|
||||
if (wxGetApp().is_enable_multi_machine()) {
|
||||
m_multi_machine = new MultiMachinePage(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_multi_machine->SetBackgroundColour(*wxWHITE);
|
||||
// TODO: change the bitmap
|
||||
m_tabpanel->AddPage(m_multi_machine, _L("Multi-device"), std::string("tab_multi_active"), std::string("tab_multi_active"), false);
|
||||
}
|
||||
|
||||
m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_project->SetBackgroundColour(*wxWHITE);
|
||||
m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_active"), std::string("tab_auxiliary_active"), false);
|
||||
|
||||
m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_calibration->SetBackgroundColour(*wxWHITE);
|
||||
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"), false);
|
||||
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_calibration_active"), std::string("tab_calibration_active"), false);
|
||||
|
||||
if (m_plater) {
|
||||
// load initial config
|
||||
@@ -1479,6 +1487,7 @@ bool MainFrame::can_reslice() const
|
||||
|
||||
wxBoxSizer* MainFrame::create_side_tools()
|
||||
{
|
||||
enable_multi_machine = wxGetApp().is_enable_multi_machine();
|
||||
int em = em_unit();
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
@@ -1536,7 +1545,7 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
m_print_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
|
||||
{
|
||||
//this->m_plater->select_view_3D("Preview");
|
||||
if (m_print_select == ePrintAll || m_print_select == ePrintPlate)
|
||||
if (m_print_select == ePrintAll || m_print_select == ePrintPlate || m_print_select == ePrintMultiMachine)
|
||||
{
|
||||
m_plater->apply_background_progress();
|
||||
// check valid of print
|
||||
@@ -1547,6 +1556,8 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_ALL));
|
||||
if (m_print_select == ePrintPlate)
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE));
|
||||
if(m_print_select == ePrintMultiMachine)
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE));
|
||||
}
|
||||
}
|
||||
else if (m_print_select == eExportGcode)
|
||||
@@ -1563,6 +1574,8 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER));
|
||||
else if (m_print_select == eSendToPrinterAll)
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL));
|
||||
/* else if (m_print_select == ePrintMultiMachine)
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE));*/
|
||||
});
|
||||
|
||||
m_slice_option_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
|
||||
@@ -1701,6 +1714,25 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
p->Dismiss();
|
||||
});
|
||||
|
||||
p->append_button(print_plate_btn);
|
||||
p->append_button(print_all_btn);
|
||||
p->append_button(send_to_printer_btn);
|
||||
p->append_button(send_to_printer_all_btn);
|
||||
if (enable_multi_machine) {
|
||||
SideButton* print_multi_machine_btn = new SideButton(p, _L("Send to Multi-device"), "");
|
||||
print_multi_machine_btn->SetCornerRadius(0);
|
||||
print_multi_machine_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
|
||||
m_print_btn->SetLabel(_L("Send to Multi-device"));
|
||||
m_print_select = ePrintMultiMachine;
|
||||
m_print_enable = get_enable_print_status();
|
||||
m_print_btn->Enable(m_print_enable);
|
||||
this->Layout();
|
||||
p->Dismiss();
|
||||
});
|
||||
p->append_button(print_multi_machine_btn);
|
||||
}
|
||||
p->append_button(export_sliced_file_btn);
|
||||
p->append_button(export_all_sliced_file_btn);
|
||||
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
|
||||
export_gcode_btn->SetCornerRadius(0);
|
||||
export_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
|
||||
@@ -1710,13 +1742,7 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
m_print_btn->Enable(m_print_enable);
|
||||
this->Layout();
|
||||
p->Dismiss();
|
||||
});
|
||||
p->append_button(print_plate_btn);
|
||||
p->append_button(print_all_btn);
|
||||
p->append_button(send_to_printer_btn);
|
||||
p->append_button(send_to_printer_all_btn);
|
||||
p->append_button(export_sliced_file_btn);
|
||||
p->append_button(export_all_sliced_file_btn);
|
||||
});
|
||||
p->append_button(export_gcode_btn);
|
||||
}
|
||||
|
||||
@@ -1859,6 +1885,14 @@ bool MainFrame::get_enable_print_status()
|
||||
enable = false;
|
||||
}
|
||||
}
|
||||
else if (m_print_select == ePrintMultiMachine)
|
||||
{
|
||||
if (!current_plate->is_slice_result_ready_for_print())
|
||||
{
|
||||
enable = false;
|
||||
}
|
||||
enable = enable && !is_all_plates;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": m_print_select %1%, enable= %2% ")%m_print_select %enable;
|
||||
|
||||
@@ -1979,6 +2013,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
|
||||
m_param_panel->msw_rescale();
|
||||
m_project->msw_rescale();
|
||||
m_monitor->msw_rescale();
|
||||
m_multi_machine->msw_rescale();
|
||||
m_calibration->msw_rescale();
|
||||
|
||||
// BBS
|
||||
@@ -3290,6 +3325,13 @@ void MainFrame::jump_to_monitor(std::string dev_id)
|
||||
((MonitorPanel*)m_monitor)->select_machine(dev_id);
|
||||
}
|
||||
|
||||
void MainFrame::jump_to_multipage()
|
||||
{
|
||||
m_tabpanel->SetSelection(tpMultiDevice);
|
||||
((MultiMachinePage*)m_multi_machine)->jump_to_send_page();
|
||||
}
|
||||
|
||||
|
||||
//BBS GUI refactor: remove unused layout new/dlg
|
||||
void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
|
||||
{
|
||||
@@ -3655,6 +3697,10 @@ void MainFrame::update_side_preset_ui()
|
||||
//BBS: update the preset
|
||||
m_plater->sidebar().update_presets(Preset::TYPE_PRINTER);
|
||||
m_plater->sidebar().update_presets(Preset::TYPE_FILAMENT);
|
||||
|
||||
|
||||
//take off multi machine
|
||||
if(m_multi_machine){m_multi_machine->clear_page();}
|
||||
}
|
||||
|
||||
void MainFrame::on_select_default_preset(SimpleEvent& evt)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "BBLTopbar.hpp"
|
||||
#include "PrinterWebView.hpp"
|
||||
#include "calib_dlg.hpp"
|
||||
#include "MultiMachinePage.hpp"
|
||||
|
||||
#define ENABEL_PRINT_ALL 0
|
||||
|
||||
@@ -98,6 +99,7 @@ class MainFrame : public DPIFrame
|
||||
wxMenuBar* m_menubar{ nullptr };
|
||||
//wxMenu* publishMenu{ nullptr };
|
||||
wxMenu * m_calib_menu{nullptr};
|
||||
bool enable_multi_machine{ false };
|
||||
|
||||
#if 0
|
||||
wxMenuItem* m_menu_item_repeat { nullptr }; // doesn't used now
|
||||
@@ -199,21 +201,6 @@ protected:
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
//BBS GUI refactor
|
||||
enum PrintSelectType
|
||||
{
|
||||
ePrintAll = 0,
|
||||
ePrintPlate = 1,
|
||||
eExportSlicedFile = 2,
|
||||
eExportGcode = 3,
|
||||
eSendGcode = 4,
|
||||
eSendToPrinter = 5,
|
||||
eSendToPrinterAll = 6,
|
||||
eUploadGcode = 7,
|
||||
eExportAllSlicedFile = 8
|
||||
};
|
||||
|
||||
MainFrame();
|
||||
~MainFrame() = default;
|
||||
|
||||
@@ -224,10 +211,11 @@ public:
|
||||
tp3DEditor = 1,
|
||||
tpPreview = 2,
|
||||
tpMonitor = 3,
|
||||
tpProject = 4,
|
||||
tpCalibration = 5,
|
||||
tpAuxiliary = 6,
|
||||
toDebugTool = 7,
|
||||
tpMultiDevice = 4,
|
||||
tpProject = 5,
|
||||
tpCalibration = 6,
|
||||
tpAuxiliary = 7,
|
||||
toDebugTool = 8,
|
||||
};
|
||||
|
||||
//BBS: add slice&&print status update logic
|
||||
@@ -240,6 +228,20 @@ public:
|
||||
eEventPrintUpdate = 4
|
||||
};
|
||||
|
||||
// BBS GUI refactor
|
||||
enum PrintSelectType {
|
||||
ePrintAll = 0,
|
||||
ePrintPlate = 1,
|
||||
eExportSlicedFile = 2,
|
||||
eExportGcode = 3,
|
||||
eSendGcode = 4,
|
||||
eSendToPrinter = 5,
|
||||
eSendToPrinterAll = 6,
|
||||
eUploadGcode = 7,
|
||||
eExportAllSlicedFile = 8,
|
||||
ePrintMultiMachine = 9
|
||||
};
|
||||
|
||||
void update_layout();
|
||||
|
||||
// Called when closing the application and when switching the application language.
|
||||
@@ -308,6 +310,7 @@ public:
|
||||
void load_config(const DynamicPrintConfig& config);
|
||||
//BBS: jump to monitor
|
||||
void jump_to_monitor(std::string dev_id = "");
|
||||
void jump_to_multipage();
|
||||
//BBS: hint when jump to 3Deditor under preview only mode
|
||||
bool preview_only_hint();
|
||||
// Select tab in m_tabpanel
|
||||
@@ -361,6 +364,7 @@ public:
|
||||
MonitorPanel* m_monitor{ nullptr };
|
||||
|
||||
//AuxiliaryPanel* m_auxiliary{ nullptr };
|
||||
MultiMachinePage* m_multi_machine{ nullptr };
|
||||
ProjectPanel* m_project{ nullptr };
|
||||
|
||||
CalibrationPanel* m_calibration{ nullptr };
|
||||
@@ -413,6 +417,7 @@ wxDECLARE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
|
||||
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
|
||||
m_button_management->SetTextColorNormal(*wxWHITE);
|
||||
m_button_management->Enable(false);
|
||||
m_button_refresh->SetBorderWidth(0);
|
||||
m_button_refresh->SetBackgroundColorNormal(wxColor("#00AE42"));
|
||||
m_button_refresh->SetBackgroundColorNormal(wxColor("#009688"));
|
||||
m_button_refresh->SetTextColorNormal(*wxWHITE);
|
||||
m_button_refresh->Enable(false);
|
||||
|
||||
|
||||
@@ -546,6 +546,13 @@ void MediaPlayCtrl::msw_rescale() {
|
||||
m_button_play->Rescale();
|
||||
}
|
||||
|
||||
void MediaPlayCtrl::jump_to_play()
|
||||
{
|
||||
if (m_last_state != MEDIASTATE_IDLE)
|
||||
return;
|
||||
TogglePlay();
|
||||
}
|
||||
|
||||
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
||||
{
|
||||
auto last_state = m_last_state;
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
void jump_to_play();
|
||||
|
||||
protected:
|
||||
void onStateChanged(wxMediaEvent & event);
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@ AddMachinePanel::~AddMachinePanel() {
|
||||
update_hms_tag();
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
Bind(EVT_JUMP_TO_HMS, &MonitorPanel::jump_to_HMS, this);
|
||||
}
|
||||
|
||||
MonitorPanel::~MonitorPanel()
|
||||
@@ -196,7 +198,7 @@ MonitorPanel::~MonitorPanel()
|
||||
m_tabpanel->AddPage(m_upgrade_panel, _L("Update"), "", false);
|
||||
|
||||
m_hms_panel = new HMSPanel(m_tabpanel);
|
||||
m_tabpanel->AddPage(m_hms_panel, _L("HMS"),"", false);
|
||||
m_tabpanel->AddPage(m_hms_panel, "HMS","", false);
|
||||
|
||||
m_initialized = true;
|
||||
show_status((int)MonitorStatus::MONITOR_NO_PRINTER);
|
||||
@@ -530,5 +532,34 @@ Freeze();
|
||||
Thaw();
|
||||
}
|
||||
|
||||
std::string MonitorPanel::get_string_from_tab(PrinterTab tab)
|
||||
{
|
||||
switch (tab) {
|
||||
case PT_STATUS :
|
||||
return "status";
|
||||
case PT_MEDIA:
|
||||
return "sd_card";
|
||||
case PT_UPDATE:
|
||||
return "update";
|
||||
case PT_HMS:
|
||||
return "HMS";
|
||||
case PT_DEBUG:
|
||||
return "debug";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void MonitorPanel::jump_to_HMS(wxCommandEvent& e)
|
||||
{
|
||||
if (!this->IsShown())
|
||||
return;
|
||||
auto page = m_tabpanel->GetCurrentPage();
|
||||
if (page && page != m_hms_panel)
|
||||
m_tabpanel->SetSelection(PT_HMS);
|
||||
}
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
||||
@@ -148,11 +148,15 @@ public:
|
||||
void update_side_panel();
|
||||
void show_status(int status);
|
||||
|
||||
std::string get_string_from_tab(PrinterTab tab);
|
||||
|
||||
MachineObject *obj { nullptr };
|
||||
std::string last_conn_type = "undedefined";
|
||||
|
||||
void stop_update() {update_flag = false;};
|
||||
void start_update() {update_flag = true;};
|
||||
|
||||
void jump_to_HMS(wxCommandEvent& e);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ Newer3mfVersionDialog::Newer3mfVersionDialog(wxWindow *parent, const Semver *fil
|
||||
, m_new_keys(new_keys)
|
||||
{
|
||||
this->SetBackgroundColour(*wxWHITE);
|
||||
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
@@ -614,8 +614,8 @@ wxBoxSizer *Newer3mfVersionDialog::get_btn_sizer()
|
||||
{
|
||||
wxBoxSizer *horizontal_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
horizontal_sizer->Add(0, 0, 1, wxEXPAND, 0);
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
bool file_version_newer = (*m_file_version) > (*m_cloud_version);
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
#include "MultiMachine.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
wxDEFINE_EVENT(EVT_MULTI_CLOUD_TASK_SELECTED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MULTI_LOCAL_TASK_SELECTED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MULTI_DEVICE_SELECTED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MULTI_DEVICE_SELECTED_FINHSH, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MULTI_DEVICE_VIEW, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_MULTI_REFRESH, wxCommandEvent);
|
||||
|
||||
DeviceItem::DeviceItem(wxWindow* parent, MachineObject* obj)
|
||||
: wxWindow(parent, wxID_ANY)
|
||||
, obj_(obj)
|
||||
{
|
||||
sync_state();
|
||||
Bind(EVT_MULTI_REFRESH, &DeviceItem::on_refresh, this);
|
||||
}
|
||||
|
||||
void DeviceItem::on_refresh(wxCommandEvent& evt)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void DeviceItem::sync_state()
|
||||
{
|
||||
if (obj_) {
|
||||
state_online = obj_->is_online();
|
||||
state_dev_name = obj_->dev_name;
|
||||
|
||||
//printable
|
||||
if (obj_->print_status == "IDLE") {
|
||||
state_printable = 0;
|
||||
}
|
||||
else if (obj_->print_status == "FINISH") {
|
||||
state_printable = 1;
|
||||
}
|
||||
else if (obj_->print_status == "FAILED") {
|
||||
state_printable = 2;
|
||||
}
|
||||
else if (obj_->is_in_printing()) {
|
||||
state_printable = 3;
|
||||
}
|
||||
else {
|
||||
state_printable = 6;
|
||||
}
|
||||
|
||||
if (is_blocking_printing(obj_)) {
|
||||
state_printable = 5;
|
||||
}
|
||||
|
||||
if (obj_->is_in_upgrading()) {
|
||||
state_printable = 4;
|
||||
}
|
||||
|
||||
state_enable_ams = obj_->ams_exist_bits;
|
||||
|
||||
|
||||
//device
|
||||
if (obj_->print_status == "IDLE") {
|
||||
state_device = 0;
|
||||
}
|
||||
else if (obj_->print_status == "FINISH") {
|
||||
state_device = 1;
|
||||
}
|
||||
else if (obj_->print_status == "FAILED") {
|
||||
state_device = 2;
|
||||
}
|
||||
else if (obj_->print_status == "RUNNING") {
|
||||
state_device = 3;
|
||||
}
|
||||
else if (obj_->print_status == "PAUSE") {
|
||||
state_device = 4;
|
||||
}
|
||||
else if (obj_->print_status == "PREPARE") {
|
||||
state_device = 5;
|
||||
}
|
||||
else if (obj_->print_status == "SLICING") {
|
||||
state_device = 6;
|
||||
}
|
||||
else {
|
||||
state_device = 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceItem::selected()
|
||||
{
|
||||
if (state_selected != 2) {
|
||||
state_selected = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceItem::unselected()
|
||||
{
|
||||
if (state_selected != 2) {
|
||||
state_selected = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceItem::is_blocking_printing(MachineObject* obj_)
|
||||
{
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev) return true;
|
||||
auto target_model = obj_->printer_type;
|
||||
std::string source_model = "";
|
||||
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
|
||||
if (source_model != target_model) {
|
||||
std::vector<std::string> compatible_machine = dev->get_compatible_machine(target_model);
|
||||
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
|
||||
if (it == compatible_machine.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceItem::update_item(const DeviceItem* item)
|
||||
{
|
||||
// Except for the selected status, everything else is updated
|
||||
if (this == item)
|
||||
return;
|
||||
this->state_online = item->state_online;
|
||||
this->state_printable = item->state_printable;
|
||||
this->state_enable_ams = item->state_enable_ams;
|
||||
this->state_device = item->state_device;
|
||||
this->state_local_task = item->state_local_task;
|
||||
}
|
||||
|
||||
wxString DeviceItem::get_state_printable()
|
||||
{
|
||||
//0-idle 1-finish 2-printing 3-upgrading 4-preset incompatible 5-unknown
|
||||
std::vector<wxString> str_state_printable;
|
||||
str_state_printable.push_back(_L("Idle"));
|
||||
str_state_printable.push_back(_L("Idle"));
|
||||
str_state_printable.push_back(_L("Idle"));
|
||||
str_state_printable.push_back(_L("Printing"));
|
||||
str_state_printable.push_back(_L("Upgrading"));
|
||||
str_state_printable.push_back(_L("Incompatible"));
|
||||
str_state_printable.push_back(_L("syncing"));
|
||||
|
||||
return str_state_printable[state_printable];
|
||||
}
|
||||
|
||||
wxString DeviceItem::get_state_device()
|
||||
{
|
||||
//0-idle 1-finish 2-running 3-pause 4-failed 5-prepare
|
||||
std::vector<wxString> str_state_device;
|
||||
str_state_device.push_back(_L("Idle"));
|
||||
str_state_device.push_back(_L("Printing Finish"));
|
||||
str_state_device.push_back(_L("Printing Failed"));
|
||||
str_state_device.push_back(_L("Printing"));
|
||||
str_state_device.push_back(_L("PrintingPause"));
|
||||
str_state_device.push_back(_L("Prepare"));
|
||||
str_state_device.push_back(_L("Slicing"));
|
||||
str_state_device.push_back(_L("syncing"));
|
||||
|
||||
return str_state_device[state_device];
|
||||
}
|
||||
|
||||
wxString DeviceItem::get_local_state_task()
|
||||
{
|
||||
//0-padding 1-sending 2-sending finish 3-sending cancel 4-sending failed 5-Removed
|
||||
std::vector<wxString> str_state_task;
|
||||
str_state_task.push_back(_L("Pending"));
|
||||
str_state_task.push_back(_L("Sending"));
|
||||
str_state_task.push_back(_L("Sending Finish"));
|
||||
str_state_task.push_back(_L("Sending Cancel"));
|
||||
str_state_task.push_back(_L("Sending Failed"));
|
||||
str_state_task.push_back(_L("Printing"));
|
||||
str_state_task.push_back(_L("Print Success"));
|
||||
str_state_task.push_back(_L("Print Failed"));
|
||||
str_state_task.push_back(_L("Removed"));
|
||||
str_state_task.push_back(_L("Idle"));
|
||||
return str_state_task[state_local_task];
|
||||
}
|
||||
|
||||
wxString DeviceItem::get_cloud_state_task()
|
||||
{
|
||||
//0-printing 1-printing finish 2-printing failed
|
||||
std::vector<wxString> str_state_task;
|
||||
str_state_task.push_back(_L("Printing"));
|
||||
str_state_task.push_back(_L("Printing Finish"));
|
||||
str_state_task.push_back(_L("Printing Failed"));
|
||||
|
||||
return str_state_task[state_cloud_task];
|
||||
}
|
||||
|
||||
|
||||
std::vector<DeviceItem*> selected_machines(const std::vector<DeviceItem*>& dev_item_list, std::string search_text)
|
||||
{
|
||||
std::vector<DeviceItem*> 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;
|
||||
|
||||
auto name_it = dev_name.find(search_text);
|
||||
auto ip_it = dev_ip.find(search_text);
|
||||
|
||||
if (name_it != std::string::npos || ip_it != std::string::npos)
|
||||
res.emplace_back(item);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
SortItem::SortItem()
|
||||
{
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_None, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return d1->state_dev_name > d2->state_dev_name;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_DEV_NAME, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_dev_name > d2->state_dev_name : d1->state_dev_name < d2->state_dev_name;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_ONLINE, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_online > d2->state_online : d1->state_online < d2->state_online;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_PRINTABLE, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_printable > d2->state_printable : d1->state_printable < d2->state_printable;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_EN_AMS, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_enable_ams > d2->state_enable_ams : d1->state_enable_ams < d2->state_enable_ams;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_DEV_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_device > d2->state_device : d1->state_device < d2->state_device;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_LOCAL_TASK_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_local_task > d2->state_local_task : d1->state_local_task < d2->state_local_task;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_CLOUD_TASK_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->state_cloud_task > d2->state_cloud_task : d1->state_cloud_task < d2->state_cloud_task;
|
||||
}));
|
||||
sort_map.emplace(std::make_pair(SortRule::SR_SEND_TIME, [this](const DeviceItem* d1, const DeviceItem* d2) {
|
||||
return this->big ? d1->m_send_time > d2->m_send_time : d1->m_send_time < d2->m_send_time;
|
||||
}));
|
||||
}
|
||||
|
||||
SortItem::SortCallBack SortItem::get_call_back()
|
||||
{
|
||||
return sort_map[rule];
|
||||
}
|
||||
|
||||
void SortItem::set_role(SortRule rule, bool big)
|
||||
{
|
||||
this->rule = rule;
|
||||
this->big = big;
|
||||
}
|
||||
|
||||
void SortItem::set_role(SortMultiMachineCB cb, SortRule rl, bool big)
|
||||
{
|
||||
this->cb = cb;
|
||||
this->rule = rl;
|
||||
this->big = big;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifndef slic3r_MultiMachine_hpp_
|
||||
#define slic3r_MultiMachine_hpp_
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
#define DEVICE_ITEM_MAX_WIDTH 900
|
||||
#define SEND_ITEM_MAX_HEIGHT 30
|
||||
#define DEVICE_ITEM_MAX_HEIGHT 50
|
||||
|
||||
#define TABLE_HEAR_NORMAL_COLOUR wxColour(238, 238, 238)
|
||||
#define TABLE_HEAD_PRESSED_COLOUR wxColour(150, 150, 150)
|
||||
#define CTRL_BUTTON_NORMAL_COLOUR wxColour(255, 255, 255)
|
||||
#define CTRL_BUTTON_PRESSEN_COLOUR wxColour(150, 150, 150)
|
||||
#define TABLE_HEAD_FONT Label::Body_13
|
||||
#define ICON_SIZE FromDIP(16)
|
||||
|
||||
class DeviceItem : public wxWindow
|
||||
{
|
||||
public:
|
||||
MachineObject* obj_{nullptr};
|
||||
int state_online = { 0 }; //0-Offline 1-Online
|
||||
std::string state_dev_name; //device name
|
||||
int state_printable{ 0 }; //0-idle 1-finish 2-failed 3-printing 4-upgrading 5-preset incompatible 6-unknown
|
||||
int state_selected{ 0 }; //0-selected 1-unselected 2-un selectable
|
||||
int state_enable_ams{ 0 };//0-no ams 1-enabled ams 2-not enabled ams
|
||||
int state_device{ 0 }; //0-idle 1-finish 2-failed 3-running 4-pause 5-prepare 6-slicing 7-removed
|
||||
int state_local_task{ 0 }; //0-padding 1-sending 2-sending finish 3-sending cancel 4-sending failed 5-TS_PRINT_SUCCESS 6- TS_PRINT_FAILED 7-TS_REMOVED 8-TS_IDLE
|
||||
int state_cloud_task{ 0 }; //0-printing 1-printing finish 2-printing failed
|
||||
int state_optional{0}; //0-Not optional 1-Optional
|
||||
std::string m_send_time;
|
||||
|
||||
public:
|
||||
|
||||
DeviceItem(wxWindow* parent, MachineObject* obj);
|
||||
~DeviceItem() {};
|
||||
|
||||
void on_refresh(wxCommandEvent& evt);
|
||||
void sync_state();
|
||||
wxString get_state_printable();
|
||||
wxString get_state_device();
|
||||
wxString get_local_state_task();
|
||||
wxString get_cloud_state_task();
|
||||
MachineObject* get_obj() const { return obj_; }
|
||||
|
||||
int get_state_online() const { return state_online; }
|
||||
int get_state_printable() const { return state_printable; }
|
||||
int get_state_selected() const { return state_selected; }
|
||||
int get_state_enable_ams() const { return state_enable_ams; }
|
||||
int get_state_device() const { return state_device; }
|
||||
int get_state_local_task() const { return state_local_task; }
|
||||
int get_state_cloud_task() const { return state_cloud_task; }
|
||||
std::string get_state_dev_name() const { return state_dev_name; }
|
||||
|
||||
void selected();
|
||||
void unselected();
|
||||
bool is_blocking_printing(MachineObject* obj_);
|
||||
void update_item(const DeviceItem* item);
|
||||
};
|
||||
|
||||
std::vector<DeviceItem*> selected_machines(const std::vector<DeviceItem*>& dev_item_list, std::string search_text);
|
||||
|
||||
struct ObjState
|
||||
{
|
||||
std::string dev_id;
|
||||
std::string state_dev_name;
|
||||
int state_device{ 0 };
|
||||
};
|
||||
|
||||
struct SortItem
|
||||
{
|
||||
typedef std::function<bool(DeviceItem*, DeviceItem*)> SortCallBack;
|
||||
typedef std::function<bool(ObjState s1, ObjState s2) > SortMultiMachineCB;
|
||||
|
||||
enum SortRule : uint8_t
|
||||
{
|
||||
SR_None = 0,
|
||||
SR_DEV_NAME = 1,
|
||||
SR_ONLINE,
|
||||
SR_PRINTABLE,
|
||||
SR_EN_AMS,
|
||||
SR_DEV_STATE,
|
||||
SR_LOCAL_TASK_STATE,
|
||||
SR_CLOUD_TASK_STATE,
|
||||
SR_SEND_TIME,
|
||||
SR_MACHINE_NAME,
|
||||
SR_MACHINE_STATE,
|
||||
SR_COUNT
|
||||
};
|
||||
|
||||
SortRule rule{ SortRule::SR_None };
|
||||
bool big{ true };
|
||||
std::unordered_map<SortRule, SortCallBack> sort_map;
|
||||
SortMultiMachineCB cb;
|
||||
|
||||
SortItem();
|
||||
SortItem(SortRule sr) { rule = sr; }
|
||||
|
||||
SortCallBack get_call_back();
|
||||
void set_role(SortRule rule, bool big);
|
||||
void set_role(SortMultiMachineCB cb, SortRule rl, bool big);
|
||||
SortMultiMachineCB get_machine_call_back() const { return cb; }
|
||||
};
|
||||
|
||||
|
||||
wxDECLARE_EVENT(EVT_MULTI_DEVICE_SELECTED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MULTI_DEVICE_SELECTED_FINHSH, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MULTI_DEVICE_VIEW, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MULTI_CLOUD_TASK_SELECTED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MULTI_LOCAL_TASK_SELECTED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_MULTI_REFRESH, wxCommandEvent);
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,725 @@
|
||||
#include "MultiMachineManagerPage.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
MultiMachineItem::MultiMachineItem(wxWindow* parent, MachineObject* obj)
|
||||
: DeviceItem(parent, obj)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
|
||||
Bind(wxEVT_PAINT, &MultiMachineItem::paintEvent, this);
|
||||
Bind(wxEVT_ENTER_WINDOW, &MultiMachineItem::OnEnterWindow, this);
|
||||
Bind(wxEVT_LEAVE_WINDOW, &MultiMachineItem::OnLeaveWindow, this);
|
||||
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);
|
||||
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();
|
||||
}
|
||||
});
|
||||
wxGetApp().UpdateDarkUIWin(this);
|
||||
}
|
||||
|
||||
void MultiMachineItem::OnEnterWindow(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MultiMachineItem::OnLeaveWindow(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = false;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MultiMachineItem::OnLeftDown(wxMouseEvent& evt)
|
||||
{
|
||||
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT +
|
||||
DEVICE_LEFT_DEV_NAME +
|
||||
DEVICE_LEFT_PRO_NAME +
|
||||
DEVICE_LEFT_PRO_INFO);
|
||||
auto mouse_pos = ClientToScreen(evt.GetPosition());
|
||||
auto item = this->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
if (mouse_pos.x > (item.x + left) &&
|
||||
mouse_pos.x < (item.x + left + FromDIP(90)) &&
|
||||
mouse_pos.y > item.y &&
|
||||
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
|
||||
post_event(wxCommandEvent(EVT_MULTI_DEVICE_VIEW));
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMachineItem::OnMove(wxMouseEvent& evt)
|
||||
{
|
||||
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT +
|
||||
DEVICE_LEFT_DEV_NAME +
|
||||
DEVICE_LEFT_PRO_NAME +
|
||||
DEVICE_LEFT_PRO_INFO);
|
||||
|
||||
auto mouse_pos = ClientToScreen(evt.GetPosition());
|
||||
auto item = this->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
if (mouse_pos.x > (item.x + left) &&
|
||||
mouse_pos.x < (item.x + left + FromDIP(90)) &&
|
||||
mouse_pos.y > item.y &&
|
||||
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
}
|
||||
else {
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMachineItem::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void MultiMachineItem::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MultiMachineItem::DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top) {
|
||||
wxSize size = GetSize();
|
||||
wxFont font = dc.GetFont();
|
||||
|
||||
wxSize textSize = dc.GetTextExtent(text);
|
||||
dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(50, 58, 61)));
|
||||
int textWidth = textSize.GetWidth();
|
||||
|
||||
if (textWidth > maxWidth) {
|
||||
wxString truncatedText = text;
|
||||
int ellipsisWidth = dc.GetTextExtent("...").GetWidth();
|
||||
int numChars = text.length();
|
||||
|
||||
for (int i = numChars - 1; i >= 0; --i) {
|
||||
truncatedText = text.substr(0, i) + "...";
|
||||
int truncatedWidth = dc.GetTextExtent(truncatedText).GetWidth();
|
||||
|
||||
if (truncatedWidth <= maxWidth - ellipsisWidth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (top == 0) {
|
||||
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2);
|
||||
}
|
||||
else {
|
||||
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2 - top);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (top == 0) {
|
||||
dc.DrawText(text, left, (size.y - textSize.y) / 2);
|
||||
}
|
||||
else {
|
||||
dc.DrawText(text, left, (size.y - textSize.y) / 2 - top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMachineItem::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
dc.SetPen(wxPen(*wxBLACK));
|
||||
|
||||
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT);
|
||||
|
||||
if (obj_) {
|
||||
//dev name
|
||||
wxString dev_name = wxString::FromUTF8(obj_->dev_name);
|
||||
if (!obj_->is_online()) {
|
||||
dev_name = dev_name + "(" + _L("Offline") + ")";
|
||||
}
|
||||
dc.SetFont(Label::Body_13);
|
||||
DrawTextWithEllipsis(dc, dev_name, FromDIP(DEVICE_LEFT_DEV_NAME), left);
|
||||
left += FromDIP(DEVICE_LEFT_DEV_NAME);
|
||||
|
||||
//project name
|
||||
wxString project_name = _L("No task");
|
||||
if (obj_->is_in_printing()) {
|
||||
project_name = wxString::Format("%s", GUI::from_u8(obj_->subtask_name));
|
||||
}
|
||||
dc.SetFont(Label::Body_13);
|
||||
DrawTextWithEllipsis(dc, project_name, FromDIP(DEVICE_LEFT_PRO_NAME), left);
|
||||
left += FromDIP(DEVICE_LEFT_PRO_NAME);
|
||||
|
||||
//state
|
||||
dc.SetFont(Label::Body_13);
|
||||
if (state_device == 0) {
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
|
||||
}
|
||||
else if (state_device == 1) {
|
||||
dc.SetTextForeground(wxColour(0,174,66));
|
||||
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
|
||||
}
|
||||
else if (state_device == 2)
|
||||
{
|
||||
dc.SetTextForeground(wxColour(208,27,27));
|
||||
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
|
||||
}
|
||||
else if (state_device > 2 && state_device < 7) {
|
||||
dc.SetFont(Label::Body_12);
|
||||
dc.SetTextForeground(wxColour(0, 150, 136));
|
||||
if (obj_->get_curr_stage().IsEmpty() && obj_->subtask_) {
|
||||
//wxString layer_info = wxString::Format(_L("Layer: %d/%d"), obj_->curr_layer, obj_->total_layers);
|
||||
wxString progress_info = wxString::Format("%d", obj_->subtask_->task_progress);
|
||||
wxString left_time = wxString::Format("%s", get_left_time(obj_->mc_left_time));
|
||||
|
||||
DrawTextWithEllipsis(dc, progress_info + "% | " + left_time, FromDIP(DEVICE_LEFT_PRO_INFO), left, FromDIP(10));
|
||||
|
||||
|
||||
dc.SetPen(wxPen(wxColour(233,233,233)));
|
||||
dc.SetBrush(wxBrush(wxColour(233,233,233)));
|
||||
dc.DrawRoundedRectangle(left, FromDIP(30), FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(10), 2);
|
||||
|
||||
dc.SetPen(wxPen(wxColour(0, 150, 136)));
|
||||
dc.SetBrush(wxBrush(wxColour(0, 150, 136)));
|
||||
dc.DrawRoundedRectangle(left, FromDIP(30), FromDIP(DEVICE_LEFT_PRO_INFO) * (static_cast<float>(obj_->subtask_->task_progress) / 100.0f), FromDIP(10), 2);
|
||||
}
|
||||
else {
|
||||
DrawTextWithEllipsis(dc, obj_->get_curr_stage(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
|
||||
}
|
||||
|
||||
left += FromDIP(DEVICE_LEFT_PRO_INFO);
|
||||
|
||||
//button
|
||||
dc.SetPen(wxPen(wxColour(38, 46, 48)));
|
||||
dc.SetBrush(wxBrush(wxColour(*wxWHITE)));
|
||||
dc.DrawRoundedRectangle(left, (size.y - FromDIP(38)) / 2, FromDIP(90), FromDIP(38), 6);
|
||||
dc.SetFont(Label::Body_14);
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
dc.DrawText(_L("View"),left + FromDIP(90) / 2 - dc.GetTextExtent(_L("View")).x / 2, (size.y -dc.GetTextExtent(_L("View")).y) / 2);
|
||||
|
||||
}
|
||||
|
||||
if (m_hover) {
|
||||
dc.SetPen(wxPen(wxColour(0, 150, 136)));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMachineItem::post_event(wxCommandEvent&& event)
|
||||
{
|
||||
event.SetEventObject(this);
|
||||
event.SetString(obj_->dev_id);
|
||||
event.SetInt(state_selected);
|
||||
wxPostEvent(this, event);
|
||||
}
|
||||
|
||||
void MultiMachineItem::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
}
|
||||
|
||||
wxString MultiMachineItem::get_left_time(int mc_left_time)
|
||||
{
|
||||
// update gcode progress
|
||||
std::string left_time;
|
||||
wxString left_time_text = _L("N/A");
|
||||
|
||||
try {
|
||||
left_time = get_bbl_monitor_time_dhm(mc_left_time);
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
|
||||
if (!left_time.empty()) left_time_text = wxString::Format("-%s", left_time);
|
||||
return left_time_text;
|
||||
}
|
||||
|
||||
|
||||
MultiMachineManagerPage::MultiMachineManagerPage(wxWindow* parent)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
SetBackgroundColour(wxColour(0xEEEEEE));
|
||||
m_main_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
m_main_panel->SetBackgroundColour(*wxWHITE);
|
||||
m_main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
StateColor head_bg(
|
||||
std::pair<wxColour, int>(TABLE_HEAD_PRESSED_COLOUR, StateColor::Pressed),
|
||||
std::pair<wxColour, int>(TABLE_HEAR_NORMAL_COLOUR, StateColor::Normal)
|
||||
);
|
||||
|
||||
//edit prints
|
||||
auto m_btn_bg_enable = StateColor(
|
||||
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
|
||||
|
||||
StateColor clean_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
|
||||
StateColor clean_bd(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
StateColor clean_text(std::pair<wxColour, int>(wxColour(144, 144, 144), StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
|
||||
auto sizer_button_printer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_button_printer->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_button_edit = new Button(m_main_panel, _L("Edit Printers"));
|
||||
m_button_edit->SetBackgroundColor(clean_bg);
|
||||
m_button_edit->SetBorderColor(clean_bd);
|
||||
m_button_edit->SetTextColor(clean_text);
|
||||
m_button_edit->SetFont(Label::Body_12);
|
||||
m_button_edit->SetCornerRadius(6);
|
||||
m_button_edit->SetMinSize(wxSize(FromDIP(90), FromDIP(36)));
|
||||
m_button_edit->SetMaxSize(wxSize(FromDIP(90), FromDIP(36)));
|
||||
|
||||
m_button_edit->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) {
|
||||
MultiMachinePickPage dlg;
|
||||
dlg.ShowModal();
|
||||
refresh_user_device();
|
||||
evt.Skip();
|
||||
});
|
||||
|
||||
sizer_button_printer->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
sizer_button_printer->Add(m_button_edit, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
m_table_head_panel = new wxPanel(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_table_head_panel->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_table_head_panel->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_table_head_panel->SetBackgroundColour(TABLE_HEAR_NORMAL_COLOUR);
|
||||
m_table_head_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_printer_name = new Button(m_table_head_panel, _L("Device Name"), "toolbar_double_directional_arrow", wxNO_BORDER, ICON_SIZE);
|
||||
m_printer_name->SetBackgroundColor(head_bg);
|
||||
m_printer_name->SetFont(TABLE_HEAD_FONT);
|
||||
m_printer_name->SetCornerRadius(0);
|
||||
m_printer_name->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_printer_name->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_printer_name->SetCenter(false);
|
||||
m_printer_name->Bind(wxEVT_ENTER_WINDOW, [&](wxMouseEvent& evt) {
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
});
|
||||
m_printer_name->Bind(wxEVT_LEAVE_WINDOW, [&](wxMouseEvent& evt) {
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
});
|
||||
m_printer_name->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& evt) {
|
||||
device_dev_name_big = !device_dev_name_big;
|
||||
auto sortcb = [this](ObjState s1, ObjState s2) {
|
||||
return device_dev_name_big ? s1.state_dev_name > s2.state_dev_name : s1.state_dev_name < s2.state_dev_name;
|
||||
};
|
||||
this->m_sort.set_role(sortcb, SortItem::SR_MACHINE_NAME, device_dev_name_big);
|
||||
this->refresh_user_device();
|
||||
});
|
||||
|
||||
|
||||
m_task_name = new Button(m_table_head_panel, _L("Task Name"), "", wxNO_BORDER, ICON_SIZE);
|
||||
m_task_name->SetBackgroundColor(TABLE_HEAR_NORMAL_COLOUR);
|
||||
m_task_name->SetFont(TABLE_HEAD_FONT);
|
||||
m_task_name->SetCornerRadius(0);
|
||||
m_task_name->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_task_name->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_task_name->SetCenter(false);
|
||||
|
||||
|
||||
|
||||
m_status = new Button(m_table_head_panel, _L("Device Status"), "toolbar_double_directional_arrow", wxNO_BORDER, ICON_SIZE);
|
||||
m_status->SetBackgroundColor(head_bg);
|
||||
m_status->SetFont(TABLE_HEAD_FONT);
|
||||
m_status->SetCornerRadius(0);
|
||||
m_status->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_status->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_status->SetCenter(false);
|
||||
m_status->Bind(wxEVT_ENTER_WINDOW, [&](wxMouseEvent& evt) {
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
});
|
||||
m_status->Bind(wxEVT_LEAVE_WINDOW, [&](wxMouseEvent& evt) {
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
});
|
||||
m_status->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& evt) {
|
||||
device_state_big = !device_state_big;
|
||||
auto sortcb = [this](ObjState s1, ObjState s2) {
|
||||
return device_state_big ? s1.state_device > s2.state_device : s1.state_device < s2.state_device;
|
||||
};
|
||||
this->m_sort.set_role(sortcb, SortItem::SortRule::SR_MACHINE_STATE, device_state_big);
|
||||
this->refresh_user_device();
|
||||
});
|
||||
|
||||
|
||||
m_action = new Button(m_table_head_panel, _L("Actions"), "", wxNO_BORDER, ICON_SIZE, false);
|
||||
m_action->SetBackgroundColor(TABLE_HEAR_NORMAL_COLOUR);
|
||||
m_action->SetFont(TABLE_HEAD_FONT);
|
||||
m_action->SetCornerRadius(0);
|
||||
m_action->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_PRO_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_action->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_PRO_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_action->SetCenter(false);
|
||||
|
||||
|
||||
m_table_head_sizer->AddSpacer(FromDIP(DEVICE_LEFT_PADDING_LEFT));
|
||||
m_table_head_sizer->Add(m_printer_name, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_table_head_sizer->Add(m_task_name, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_table_head_sizer->Add(m_status, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_table_head_sizer->Add(m_action, 0, wxLEFT, 0);
|
||||
|
||||
m_table_head_panel->SetSizer(m_table_head_sizer);
|
||||
m_table_head_panel->Layout();
|
||||
|
||||
m_tip_text = new wxStaticText(m_main_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
||||
m_tip_text->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_tip_text->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_tip_text->SetLabel(_L("Please select the devices you would like to manage here (up to 6 devices)"));
|
||||
m_tip_text->SetForegroundColour(wxColour(50, 58, 61));
|
||||
m_tip_text->SetFont(::Label::Head_20);
|
||||
m_tip_text->Wrap(-1);
|
||||
|
||||
m_button_add = new Button(m_main_panel, _L("Add"));
|
||||
m_button_add->SetBackgroundColor(m_btn_bg_enable);
|
||||
m_button_add->SetBorderColor(m_btn_bg_enable);
|
||||
m_button_add->SetTextColor(*wxWHITE);
|
||||
m_button_add->SetFont(Label::Body_12);
|
||||
m_button_add->SetCornerRadius(6);
|
||||
m_button_add->SetMinSize(wxSize(FromDIP(90), FromDIP(36)));
|
||||
m_button_add->SetMaxSize(wxSize(FromDIP(90), FromDIP(36)));
|
||||
|
||||
m_button_add->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) {
|
||||
MultiMachinePickPage dlg;
|
||||
dlg.ShowModal();
|
||||
refresh_user_device();
|
||||
evt.Skip();
|
||||
});
|
||||
|
||||
m_machine_list = new wxScrolledWindow(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_machine_list->SetBackgroundColour(*wxWHITE);
|
||||
m_machine_list->SetScrollRate(0, 5);
|
||||
m_machine_list->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), 10 * FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
m_machine_list->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), 10 * FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
|
||||
|
||||
m_sizer_machine_list = new wxBoxSizer(wxVERTICAL);
|
||||
m_machine_list->SetSizer(m_sizer_machine_list);
|
||||
m_machine_list->Layout();
|
||||
|
||||
// add flipping page
|
||||
StateColor ctrl_bg(
|
||||
std::pair<wxColour, int>(CTRL_BUTTON_PRESSEN_COLOUR, StateColor::Pressed),
|
||||
std::pair<wxColour, int>(CTRL_BUTTON_NORMAL_COLOUR, StateColor::Normal)
|
||||
);
|
||||
|
||||
m_flipping_panel = new wxPanel(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_flipping_panel->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_flipping_panel->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
|
||||
m_flipping_panel->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
m_flipping_page_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_page_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
btn_last_page = new Button(m_flipping_panel, "", "go_last_plate", 0, FromDIP(20));
|
||||
btn_last_page->SetMinSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
btn_last_page->SetMaxSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
btn_last_page->SetBackgroundColor(head_bg);
|
||||
btn_last_page->Bind(wxEVT_LEFT_DOWN, [&](wxMouseEvent& evt) {
|
||||
evt.Skip();
|
||||
if (m_current_page == 0)
|
||||
return;
|
||||
btn_last_page->Enable(false);
|
||||
btn_next_page->Enable(false);
|
||||
start_timer();
|
||||
m_current_page--;
|
||||
if (m_current_page < 0)
|
||||
m_current_page = 0;
|
||||
refresh_user_device();
|
||||
update_page_number();
|
||||
});
|
||||
st_page_number = new wxStaticText(m_flipping_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize);
|
||||
btn_next_page = new Button(m_flipping_panel, "", "go_next_plate", 0, FromDIP(20));
|
||||
btn_next_page->SetMinSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
btn_next_page->SetMaxSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
btn_next_page->SetBackgroundColor(head_bg);
|
||||
btn_next_page->Bind(wxEVT_LEFT_DOWN, [&](wxMouseEvent& evt) {
|
||||
evt.Skip();
|
||||
if (m_current_page == m_total_page - 1)
|
||||
return;
|
||||
btn_last_page->Enable(false);
|
||||
btn_next_page->Enable(false);
|
||||
start_timer();
|
||||
m_current_page++;
|
||||
if (m_current_page > m_total_page - 1)
|
||||
m_current_page = m_total_page - 1;
|
||||
refresh_user_device();
|
||||
update_page_number();
|
||||
});
|
||||
|
||||
m_page_num_input = new ::TextInput(m_flipping_panel, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(50), -1), wxTE_PROCESS_ENTER);
|
||||
StateColor input_bg(std::pair<wxColour, int>(wxColour("#F0F0F1"), StateColor::Disabled), std::pair<wxColour, int>(*wxWHITE, StateColor::Enabled));
|
||||
m_page_num_input->SetBackgroundColor(input_bg);
|
||||
m_page_num_input->GetTextCtrl()->SetValue("1");
|
||||
wxTextValidator validator(wxFILTER_DIGITS);
|
||||
m_page_num_input->GetTextCtrl()->SetValidator(validator);
|
||||
m_page_num_input->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [&](wxCommandEvent& e) {
|
||||
page_num_enter_evt();
|
||||
});
|
||||
|
||||
m_page_num_enter = new Button(m_flipping_panel, _("Go"));
|
||||
m_page_num_enter->SetMinSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetMaxSize(wxSize(FromDIP(25), FromDIP(25)));
|
||||
m_page_num_enter->SetBackgroundColor(ctrl_bg);
|
||||
m_page_num_enter->SetCornerRadius(FromDIP(5));
|
||||
m_page_num_enter->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](auto& evt) {
|
||||
page_num_enter_evt();
|
||||
});
|
||||
|
||||
m_flipping_page_sizer->Add(0, 0, 1, wxEXPAND, 0);
|
||||
m_flipping_page_sizer->Add(btn_last_page, 0, wxALIGN_CENTER, 0);
|
||||
m_flipping_page_sizer->Add(st_page_number, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||
m_flipping_page_sizer->Add(btn_next_page, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||
m_flipping_page_sizer->Add(m_page_num_input, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(20));
|
||||
m_flipping_page_sizer->Add(m_page_num_enter, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||
m_page_sizer->Add(m_flipping_page_sizer, 0, wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
|
||||
m_flipping_panel->SetSizer(m_page_sizer);
|
||||
m_flipping_panel->Layout();
|
||||
|
||||
m_main_sizer->AddSpacer(FromDIP(16));
|
||||
m_main_sizer->Add(sizer_button_printer, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
m_main_sizer->AddSpacer(FromDIP(5));
|
||||
m_main_sizer->Add(m_table_head_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
m_main_sizer->Add(m_tip_text, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(50));
|
||||
m_main_sizer->Add(m_button_add, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(16));
|
||||
m_main_sizer->Add(m_machine_list, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
m_main_sizer->Add(m_flipping_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
m_main_panel->SetSizer(m_main_sizer);
|
||||
m_main_panel->Layout();
|
||||
page_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
page_sizer->Add(m_main_panel, 1, wxALL | wxEXPAND, FromDIP(25));
|
||||
|
||||
SetSizer(page_sizer);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
Bind(wxEVT_TIMER, &MultiMachineManagerPage::on_timer, this);
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::update_page()
|
||||
{
|
||||
for (int i = 0; i < m_device_items.size(); i++) {
|
||||
m_device_items[i]->sync_state();
|
||||
m_device_items[i]->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::refresh_user_device(bool clear)
|
||||
{
|
||||
m_sizer_machine_list->Clear(true);
|
||||
m_device_items.clear();
|
||||
|
||||
if(clear) return;
|
||||
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev) return;
|
||||
|
||||
auto all_machine = dev->get_my_cloud_machine_list();
|
||||
auto user_machine = std::map<std::string, MachineObject*>();
|
||||
|
||||
//selected machine
|
||||
for (int i = 0; i < PICK_DEVICE_MAX; i++) {
|
||||
auto dev_id = wxGetApp().app_config->get("multi_devices", std::to_string(i));
|
||||
|
||||
if (all_machine.count(dev_id) > 0) {
|
||||
user_machine[dev_id] = all_machine[dev_id];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_total_count = user_machine.size();
|
||||
|
||||
m_state_objs.clear();
|
||||
for (auto it = user_machine.begin(); it != user_machine.end(); ++it) {
|
||||
sync_state(it->second);
|
||||
}
|
||||
|
||||
//sort
|
||||
if (m_sort.rule != SortItem::SortRule::SR_None) {
|
||||
std::sort(m_state_objs.begin(), m_state_objs.end(), m_sort.get_machine_call_back());
|
||||
}
|
||||
|
||||
double result = static_cast<double>(user_machine.size()) / m_count_page_item;
|
||||
m_total_page = std::ceil(result);
|
||||
|
||||
std::vector<ObjState> sort_devices = extractRange(m_state_objs, m_current_page * m_count_page_item, (m_current_page + 1) * m_count_page_item - 1 );
|
||||
std::vector<std::string> subscribe_list;
|
||||
|
||||
for (auto i = 0; i < sort_devices.size(); ++i) {
|
||||
auto dev_id = sort_devices[i].dev_id;
|
||||
|
||||
auto machine = user_machine[dev_id];
|
||||
|
||||
MultiMachineItem* di = new MultiMachineItem(m_machine_list, machine);
|
||||
m_device_items.push_back(di);
|
||||
m_sizer_machine_list->Add(m_device_items[i], 0, wxALL | wxEXPAND, 0);
|
||||
|
||||
subscribe_list.push_back(dev_id);
|
||||
}
|
||||
|
||||
dev->subscribe_device_list(subscribe_list);
|
||||
|
||||
m_tip_text->Show(m_device_items.empty());
|
||||
m_button_add->Show(m_device_items.empty());
|
||||
|
||||
update_page_number();
|
||||
m_flipping_panel->Show(m_total_page > 1);
|
||||
m_sizer_machine_list->Layout();
|
||||
Layout();
|
||||
}
|
||||
|
||||
std::vector<ObjState> MultiMachineManagerPage::extractRange(const std::vector<ObjState>& source, int start, int end) {
|
||||
std::vector<ObjState> result;
|
||||
|
||||
if (start < 0 || start > end || source.size() <= 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( end >= source.size() ) {
|
||||
end = source.size();
|
||||
}
|
||||
|
||||
auto startIter = source.begin() + start;
|
||||
auto endIter = source.begin() + end;
|
||||
result.assign(startIter, endIter);
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (obj_->print_status == "IDLE") {
|
||||
state_obj.state_device = 0;
|
||||
}
|
||||
else if (obj_->print_status == "FINISH") {
|
||||
state_obj.state_device = 1;
|
||||
}
|
||||
else if (obj_->print_status == "FAILED") {
|
||||
state_obj.state_device = 2;
|
||||
}
|
||||
else if (obj_->print_status == "RUNNING") {
|
||||
state_obj.state_device = 3;
|
||||
}
|
||||
else if (obj_->print_status == "PAUSE") {
|
||||
state_obj.state_device = 4;
|
||||
}
|
||||
else if (obj_->print_status == "PREPARE") {
|
||||
state_obj.state_device = 5;
|
||||
}
|
||||
else if (obj_->print_status == "SLICING") {
|
||||
state_obj.state_device = 6;
|
||||
}
|
||||
else {
|
||||
state_obj.state_device = 7;
|
||||
}
|
||||
}
|
||||
m_state_objs.push_back(state_obj);
|
||||
}
|
||||
|
||||
bool MultiMachineManagerPage::Show(bool show)
|
||||
{
|
||||
if (show) {
|
||||
refresh_user_device();
|
||||
}
|
||||
else {
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (dev) {
|
||||
dev->subscribe_device_list(std::vector<std::string>());
|
||||
}
|
||||
}
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::start_timer()
|
||||
{
|
||||
if (m_flipping_timer) {
|
||||
m_flipping_timer->Stop();
|
||||
}
|
||||
else {
|
||||
m_flipping_timer = new wxTimer();
|
||||
}
|
||||
|
||||
m_flipping_timer->SetOwner(this);
|
||||
m_flipping_timer->Start(1000);
|
||||
wxPostEvent(this, wxTimerEvent());
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::update_page_number()
|
||||
{
|
||||
double result = static_cast<double>(m_total_count) / m_count_page_item;
|
||||
m_total_page = std::ceil(result);
|
||||
|
||||
wxString number = wxString(std::to_string(m_current_page + 1)) + " / " + wxString(std::to_string(m_total_page));
|
||||
st_page_number->SetLabel(number);
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::on_timer(wxTimerEvent& event)
|
||||
{
|
||||
m_flipping_timer->Stop();
|
||||
if (btn_last_page)
|
||||
btn_last_page->Enable(true);
|
||||
if (btn_next_page)
|
||||
btn_next_page->Enable(true);
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::clear_page()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MultiMachineManagerPage::page_num_enter_evt()
|
||||
{
|
||||
btn_last_page->Enable(false);
|
||||
btn_next_page->Enable(false);
|
||||
start_timer();
|
||||
auto value = m_page_num_input->GetTextCtrl()->GetValue();
|
||||
long page_num = 0;
|
||||
if (value.ToLong(&page_num)) {
|
||||
if (page_num > m_total_page)
|
||||
m_current_page = m_total_page - 1;
|
||||
else if (page_num < 1)
|
||||
m_current_page = 0;
|
||||
else
|
||||
m_current_page = page_num - 1;
|
||||
}
|
||||
refresh_user_device();
|
||||
update_page_number();
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef slic3r_MultiMachineMangerPage_hpp_
|
||||
#define slic3r_MultiMachineMangerPage_hpp_
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MultiMachine.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define DEVICE_LEFT_PADDING_LEFT 15
|
||||
#define DEVICE_LEFT_DEV_NAME 180
|
||||
#define DEVICE_LEFT_PRO_NAME 180
|
||||
#define DEVICE_LEFT_PRO_INFO 320
|
||||
|
||||
class MultiMachineItem : public DeviceItem
|
||||
{
|
||||
|
||||
public:
|
||||
MultiMachineItem(wxWindow* parent, MachineObject* obj);
|
||||
~MultiMachineItem() {};
|
||||
|
||||
void OnEnterWindow(wxMouseEvent& evt);
|
||||
void OnLeaveWindow(wxMouseEvent& evt);
|
||||
void OnLeftDown(wxMouseEvent& evt);
|
||||
void OnMove(wxMouseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
|
||||
void doRender(wxDC& dc);
|
||||
void post_event(wxCommandEvent&& event);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
public:
|
||||
bool m_hover{ false };
|
||||
ScalableBitmap m_bitmap_check_disable;
|
||||
ScalableBitmap m_bitmap_check_off;
|
||||
ScalableBitmap m_bitmap_check_on;
|
||||
wxString get_left_time(int mc_left_time);
|
||||
};
|
||||
|
||||
class MultiMachineManagerPage : public wxPanel
|
||||
{
|
||||
public:
|
||||
MultiMachineManagerPage(wxWindow* parent);
|
||||
~MultiMachineManagerPage() {};
|
||||
|
||||
void update_page();
|
||||
void refresh_user_device(bool clear = false);
|
||||
|
||||
void sync_state(MachineObject* obj_);
|
||||
bool Show(bool show);
|
||||
|
||||
std::vector<ObjState> extractRange(const std::vector<ObjState>& source, int start, int end);
|
||||
|
||||
void start_timer();
|
||||
void update_page_number();
|
||||
void on_timer(wxTimerEvent& event);
|
||||
void clear_page();
|
||||
|
||||
void page_num_enter_evt();
|
||||
|
||||
private:
|
||||
std::vector<ObjState> m_state_objs;
|
||||
std::vector<MultiMachineItem*> m_device_items;
|
||||
SortItem m_sort;
|
||||
bool device_dev_name_big{ true };
|
||||
bool device_state_big{ true };
|
||||
|
||||
|
||||
Button* m_button_edit{nullptr};
|
||||
wxBoxSizer* page_sizer{ nullptr };
|
||||
wxPanel* m_main_panel{ nullptr };
|
||||
wxBoxSizer* m_main_sizer{nullptr};
|
||||
wxBoxSizer* m_sizer_machine_list{nullptr};
|
||||
wxScrolledWindow* m_machine_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
wxBoxSizer* m_table_head_sizer{ nullptr };
|
||||
Button* m_printer_name{ nullptr };
|
||||
Button* m_task_name{ nullptr };
|
||||
Button* m_status{ nullptr };
|
||||
Button* m_action{ nullptr };
|
||||
Button* m_stop_all_botton{nullptr};
|
||||
|
||||
// tip when no device
|
||||
wxStaticText* m_tip_text{ nullptr };
|
||||
Button* m_button_add{ nullptr };
|
||||
|
||||
// Flipping pages
|
||||
int m_current_page{ 0 };
|
||||
int m_total_page{ 0 };
|
||||
int m_total_count{ 0 };
|
||||
int m_count_page_item{ 10 };
|
||||
|
||||
bool prev{ false };
|
||||
bool next{ false };
|
||||
Button* btn_last_page{ nullptr };
|
||||
Button* btn_next_page{ nullptr };
|
||||
wxStaticText* st_page_number{ nullptr };
|
||||
wxBoxSizer* m_flipping_page_sizer{ nullptr };
|
||||
wxBoxSizer* m_page_sizer{ nullptr };
|
||||
wxPanel* m_flipping_panel{ nullptr };
|
||||
wxTimer* m_flipping_timer{ nullptr };
|
||||
TextInput* m_page_num_input{ nullptr };
|
||||
Button* m_page_num_enter{ nullptr };
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,485 @@
|
||||
#include "MultiMachinePage.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
MultiMachinePage::MultiMachinePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxPanel(parent, id, pos, size, style)
|
||||
{
|
||||
init_tabpanel();
|
||||
m_main_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxLEFT, 0);
|
||||
SetSizerAndFit(m_main_sizer);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
wxGetApp().UpdateDarkUIWin(this);
|
||||
|
||||
init_timer();
|
||||
Bind(wxEVT_TIMER, &MultiMachinePage::on_timer, this);
|
||||
}
|
||||
|
||||
MultiMachinePage::~MultiMachinePage()
|
||||
{
|
||||
if (m_refresh_timer)
|
||||
m_refresh_timer->Stop();
|
||||
delete m_refresh_timer;
|
||||
}
|
||||
|
||||
void MultiMachinePage::jump_to_send_page()
|
||||
{
|
||||
m_tabpanel->SetSelection(1);
|
||||
}
|
||||
|
||||
void MultiMachinePage::on_sys_color_changed()
|
||||
{
|
||||
}
|
||||
|
||||
void MultiMachinePage::msw_rescale()
|
||||
{
|
||||
}
|
||||
|
||||
bool MultiMachinePage::Show(bool show)
|
||||
{
|
||||
if (show) {
|
||||
m_refresh_timer->Stop();
|
||||
m_refresh_timer->SetOwner(this);
|
||||
m_refresh_timer->Start(2000);
|
||||
wxPostEvent(this, wxTimerEvent());
|
||||
}
|
||||
else {
|
||||
m_refresh_timer->Stop();
|
||||
}
|
||||
|
||||
auto page = m_tabpanel->GetCurrentPage();
|
||||
if (page)
|
||||
page->Show(show);
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void MultiMachinePage::init_tabpanel()
|
||||
{
|
||||
auto m_side_tools = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), FromDIP(18)));
|
||||
wxBoxSizer* sizer_side_tools = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0);
|
||||
m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
|
||||
m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF"));
|
||||
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {; });
|
||||
|
||||
m_local_task_manager = new LocalTaskManagerPage(m_tabpanel);
|
||||
m_cloud_task_manager = new CloudTaskManagerPage(m_tabpanel);
|
||||
m_machine_manager = new MultiMachineManagerPage(m_tabpanel);
|
||||
|
||||
m_tabpanel->AddPage(m_machine_manager, _L("Device"), "", true);
|
||||
m_tabpanel->AddPage(m_local_task_manager, _L("Task Sending"), "", false);
|
||||
m_tabpanel->AddPage(m_cloud_task_manager, _L("Task Sent"), "", false);
|
||||
}
|
||||
|
||||
void MultiMachinePage::init_timer()
|
||||
{
|
||||
m_refresh_timer = new wxTimer();
|
||||
//m_refresh_timer->SetOwner(this);
|
||||
//m_refresh_timer->Start(8000);
|
||||
//wxPostEvent(this, wxTimerEvent());
|
||||
}
|
||||
|
||||
void MultiMachinePage::on_timer(wxTimerEvent& event)
|
||||
{
|
||||
m_local_task_manager->update_page();
|
||||
m_cloud_task_manager->update_page();
|
||||
m_machine_manager->update_page();
|
||||
}
|
||||
|
||||
void MultiMachinePage::clear_page()
|
||||
{
|
||||
m_local_task_manager->refresh_user_device(true);
|
||||
m_cloud_task_manager->refresh_user_device(true);
|
||||
m_machine_manager->refresh_user_device(true);
|
||||
}
|
||||
|
||||
DevicePickItem::DevicePickItem(wxWindow* parent, MachineObject* obj)
|
||||
: DeviceItem(parent, obj)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
m_bitmap_check_disable = ScalableBitmap(this, "check_off_disabled", 18);
|
||||
m_bitmap_check_off = ScalableBitmap(this, "check_off_focused", 18);
|
||||
m_bitmap_check_on = ScalableBitmap(this, "check_on", 18);
|
||||
|
||||
|
||||
SetMinSize(wxSize(FromDIP(400), FromDIP(30)));
|
||||
SetMaxSize(wxSize(FromDIP(400), FromDIP(30)));
|
||||
|
||||
Bind(wxEVT_PAINT, &DevicePickItem::paintEvent, this);
|
||||
Bind(wxEVT_ENTER_WINDOW, &DevicePickItem::OnEnterWindow, this);
|
||||
Bind(wxEVT_LEAVE_WINDOW, &DevicePickItem::OnLeaveWindow, this);
|
||||
Bind(wxEVT_LEFT_DOWN, &DevicePickItem::OnLeftDown, this);
|
||||
Bind(wxEVT_MOTION, &DevicePickItem::OnMove, this);
|
||||
Bind(EVT_MULTI_DEVICE_SELECTED, &DevicePickItem::OnSelectedDevice, this);
|
||||
wxGetApp().UpdateDarkUIWin(this);
|
||||
}
|
||||
|
||||
void DevicePickItem::DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top /*= 0*/)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxFont font = dc.GetFont();
|
||||
|
||||
wxSize textSize = dc.GetTextExtent(text);
|
||||
dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(50, 58, 61)));
|
||||
int textWidth = textSize.GetWidth();
|
||||
|
||||
if (textWidth > maxWidth) {
|
||||
wxString truncatedText = text;
|
||||
int ellipsisWidth = dc.GetTextExtent("...").GetWidth();
|
||||
int numChars = text.length();
|
||||
|
||||
for (int i = numChars - 1; i >= 0; --i) {
|
||||
truncatedText = text.substr(0, i) + "...";
|
||||
int truncatedWidth = dc.GetTextExtent(truncatedText).GetWidth();
|
||||
|
||||
if (truncatedWidth <= maxWidth - ellipsisWidth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (top == 0) {
|
||||
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2);
|
||||
}
|
||||
else {
|
||||
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2 - top);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (top == 0) {
|
||||
dc.DrawText(text, left, (size.y - textSize.y) / 2);
|
||||
}
|
||||
else {
|
||||
dc.DrawText(text, left, (size.y - textSize.y) / 2 - top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePickItem::OnEnterWindow(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = true;
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
void DevicePickItem::OnLeaveWindow(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = false;
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
void DevicePickItem::OnSelectedDevice(wxCommandEvent& evt)
|
||||
{
|
||||
auto dev_id = evt.GetString();
|
||||
auto state = evt.GetInt();
|
||||
if (state == 0) {
|
||||
state_selected = 1;
|
||||
}
|
||||
else if (state == 1) {
|
||||
state_selected = 0;
|
||||
}
|
||||
Refresh(false);
|
||||
evt.Skip();
|
||||
|
||||
post_event(wxCommandEvent(EVT_MULTI_DEVICE_SELECTED_FINHSH));
|
||||
}
|
||||
|
||||
void DevicePickItem::OnLeftDown(wxMouseEvent& evt)
|
||||
{
|
||||
int left = FromDIP(15);
|
||||
auto mouse_pos = ClientToScreen(evt.GetPosition());
|
||||
auto item = this->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
if (mouse_pos.x > (item.x + left) &&
|
||||
mouse_pos.x < (item.x + left + m_bitmap_check_disable.GetBmpWidth()) &&
|
||||
mouse_pos.y > item.y &&
|
||||
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
|
||||
|
||||
post_event(wxCommandEvent(EVT_MULTI_DEVICE_SELECTED));
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePickItem::OnMove(wxMouseEvent& evt)
|
||||
{
|
||||
int left = FromDIP(15);
|
||||
auto mouse_pos = ClientToScreen(evt.GetPosition());
|
||||
auto item = this->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
if (mouse_pos.x > (item.x + left) &&
|
||||
mouse_pos.x < (item.x + left + m_bitmap_check_disable.GetBmpWidth()) &&
|
||||
mouse_pos.y > item.y &&
|
||||
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
}
|
||||
else {
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePickItem::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void DevicePickItem::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DevicePickItem::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
dc.SetPen(wxPen(*wxBLACK));
|
||||
|
||||
int left = FromDIP(PICK_LEFT_PADDING_LEFT);
|
||||
|
||||
|
||||
//checkbox
|
||||
if (state_selected == 0) {
|
||||
dc.DrawBitmap(m_bitmap_check_off.bmp(), wxPoint(left, (size.y - m_bitmap_check_disable.GetBmpSize().y) / 2));
|
||||
}
|
||||
else if (state_selected == 1) {
|
||||
dc.DrawBitmap(m_bitmap_check_on.bmp(), wxPoint(left, (size.y - m_bitmap_check_disable.GetBmpSize().y) / 2));
|
||||
}
|
||||
|
||||
left += FromDIP(PICK_LEFT_PRINTABLE);
|
||||
|
||||
//dev names
|
||||
DrawTextWithEllipsis(dc, wxString::FromUTF8(get_obj()->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.SetInt(state_selected);
|
||||
wxPostEvent(this, event);
|
||||
}
|
||||
|
||||
void DevicePickItem::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
}
|
||||
|
||||
MultiMachinePickPage::MultiMachinePickPage(Plater* plater /*= nullptr*/)
|
||||
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY,
|
||||
_L("Edit multiple printers"),
|
||||
wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
|
||||
app_config = get_app_config();
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
// icon
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
auto line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
m_label = new Label(this, _L("Select connected printetrs (0/6)"));
|
||||
|
||||
scroll_macine_list = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
|
||||
scroll_macine_list->SetSize(wxSize(FromDIP(400), FromDIP(10 * 30)));
|
||||
scroll_macine_list->SetMinSize(wxSize(FromDIP(400), FromDIP(10 * 30)));
|
||||
scroll_macine_list->SetMaxSize(wxSize(FromDIP(400), FromDIP(10 * 30)));
|
||||
scroll_macine_list->SetBackgroundColour(*wxWHITE);
|
||||
scroll_macine_list->SetScrollRate(0, 5);
|
||||
|
||||
sizer_machine_list = new wxBoxSizer(wxVERTICAL);
|
||||
scroll_macine_list->SetSizer(sizer_machine_list);
|
||||
scroll_macine_list->Layout();
|
||||
|
||||
main_sizer->Add(line_top, 0, wxEXPAND, 0);
|
||||
main_sizer->AddSpacer(FromDIP(10));
|
||||
main_sizer->Add(m_label, 0, wxLEFT, FromDIP(20));
|
||||
main_sizer->Add(scroll_macine_list, 0, wxLEFT|wxRIGHT, FromDIP(20));
|
||||
main_sizer->AddSpacer(FromDIP(10));
|
||||
|
||||
SetSizer(main_sizer);
|
||||
Layout();
|
||||
Fit();
|
||||
Centre(wxBOTH);
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
MultiMachinePickPage::~MultiMachinePickPage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int MultiMachinePickPage::get_selected_count()
|
||||
{
|
||||
int count = 0;
|
||||
for (auto it = m_device_items.begin(); it != m_device_items.end(); it++) {
|
||||
if (it->second->state_selected == 1) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void MultiMachinePickPage::update_selected_count()
|
||||
{
|
||||
std::vector<std::string> selected_multi_devices;
|
||||
|
||||
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);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
m_selected_count = count;
|
||||
m_label->SetLabel(wxString::Format(_L("Select Connected Printetrs (%d/6)"), m_selected_count));
|
||||
|
||||
if (m_selected_count > PICK_DEVICE_MAX) {
|
||||
MessageDialog msg_wingow(nullptr, wxString::Format(_L("The maximum number of printers that can be selected is %d"), PICK_DEVICE_MAX), "", wxAPPLY | wxOK);
|
||||
if (msg_wingow.ShowModal() == wxOK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < PICK_DEVICE_MAX; i++) {
|
||||
app_config->erase("multi_devices",std::to_string(i));
|
||||
}
|
||||
|
||||
for (int j = 0; j < selected_multi_devices.size(); j++) {
|
||||
app_config->set_str("multi_devices", std::to_string(j), selected_multi_devices[j]);
|
||||
}
|
||||
app_config->save();
|
||||
}
|
||||
|
||||
void MultiMachinePickPage::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MultiMachinePickPage::on_sys_color_changed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MultiMachinePickPage::refresh_user_device()
|
||||
{
|
||||
std::vector<std::string> selected_multi_devices;
|
||||
|
||||
for(int i = 0; i < PICK_DEVICE_MAX; i++){
|
||||
auto dev_id = app_config->get("multi_devices", std::to_string(i));
|
||||
selected_multi_devices.push_back(dev_id);
|
||||
}
|
||||
|
||||
sizer_machine_list->Clear(false);
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev) {
|
||||
for (auto it = m_device_items.begin(); it != m_device_items.end(); it++) {
|
||||
wxWindow* child = it->second;
|
||||
child->Destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto user_machine = dev->get_my_cloud_machine_list();
|
||||
auto task_manager = wxGetApp().getTaskManager();
|
||||
|
||||
std::vector<std::string> subscribe_list;
|
||||
|
||||
for (auto it = user_machine.begin(); it != user_machine.end(); ++it) {
|
||||
DevicePickItem* di = new DevicePickItem(scroll_macine_list, it->second);
|
||||
|
||||
di->Bind(EVT_MULTI_DEVICE_SELECTED_FINHSH, [this, di](auto& e) {
|
||||
int count = get_selected_count();
|
||||
if (count > PICK_DEVICE_MAX) {
|
||||
di->unselected();
|
||||
return;
|
||||
}
|
||||
update_selected_count();
|
||||
});
|
||||
|
||||
/* if (m_device_items.find(it->first) != m_device_items.end()) {
|
||||
auto item = m_device_items[it->first];
|
||||
if (item->state_selected == 1 && di->state_printable <= 2)
|
||||
di->state_selected = item->state_selected;
|
||||
item->Destroy();
|
||||
}*/
|
||||
m_device_items[it->first] = di;
|
||||
|
||||
//update state
|
||||
if (task_manager) {
|
||||
m_device_items[it->first]->state_local_task = task_manager->query_task_state(it->first);
|
||||
}
|
||||
|
||||
//update selected
|
||||
auto dev_it = std::find(selected_multi_devices.begin(), selected_multi_devices.end(), it->second->dev_id );
|
||||
if (dev_it != selected_multi_devices.end()) {
|
||||
di->state_selected = 1;
|
||||
}
|
||||
|
||||
sizer_machine_list->Add(di, 0, wxALL | wxEXPAND, 0);
|
||||
subscribe_list.push_back(it->first);
|
||||
}
|
||||
|
||||
dev->subscribe_device_list(subscribe_list);
|
||||
|
||||
sizer_machine_list->Layout();
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void MultiMachinePickPage::on_confirm(wxCommandEvent& event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool MultiMachinePickPage::Show(bool show)
|
||||
{
|
||||
if (show) {
|
||||
refresh_user_device();
|
||||
update_selected_count();
|
||||
//m_refresh_timer->Stop();
|
||||
//m_refresh_timer->SetOwner(this);
|
||||
//m_refresh_timer->Start(4000);
|
||||
//wxPostEvent(this, wxTimerEvent());
|
||||
}
|
||||
else {
|
||||
//m_refresh_timer->Stop();
|
||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (dev) {
|
||||
dev->subscribe_device_list(std::vector<std::string>());
|
||||
}
|
||||
}
|
||||
return wxDialog::Show(show);
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef slic3r_MultiMachinePage_hpp_
|
||||
#define slic3r_MultiMachinePage_hpp_
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MultiTaskManagerPage.hpp"
|
||||
#include "MultiMachineManagerPage.hpp"
|
||||
#include "Tabbook.hpp"
|
||||
|
||||
#include "wx/button.h"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define PICK_LEFT_PADDING_LEFT 15
|
||||
#define PICK_LEFT_PRINTABLE 40
|
||||
#define PICK_LEFT_DEV_NAME 250
|
||||
#define PICK_LEFT_DEV_STATUS 250
|
||||
#define PICK_DEVICE_MAX 6
|
||||
|
||||
class MultiMachinePage : public wxPanel
|
||||
{
|
||||
private:
|
||||
wxTimer* m_refresh_timer = nullptr;
|
||||
wxSizer* m_main_sizer{ nullptr };
|
||||
LocalTaskManagerPage* m_local_task_manager{ nullptr };
|
||||
CloudTaskManagerPage* m_cloud_task_manager{ nullptr };
|
||||
MultiMachineManagerPage* m_machine_manager{ nullptr };
|
||||
Tabbook* m_tabpanel{ nullptr };
|
||||
|
||||
public:
|
||||
MultiMachinePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
|
||||
~MultiMachinePage();
|
||||
|
||||
void jump_to_send_page();
|
||||
|
||||
void on_sys_color_changed();
|
||||
void msw_rescale();
|
||||
bool Show(bool show);
|
||||
|
||||
void init_tabpanel();
|
||||
void init_timer();
|
||||
void on_timer(wxTimerEvent& event);
|
||||
|
||||
void clear_page();
|
||||
};
|
||||
|
||||
|
||||
class DevicePickItem : public DeviceItem
|
||||
{
|
||||
|
||||
public:
|
||||
DevicePickItem(wxWindow* parent, MachineObject* obj);
|
||||
~DevicePickItem() {};
|
||||
|
||||
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
|
||||
void OnEnterWindow(wxMouseEvent& evt);
|
||||
void OnLeaveWindow(wxMouseEvent& evt);
|
||||
void OnSelectedDevice(wxCommandEvent& evt);
|
||||
void OnLeftDown(wxMouseEvent& evt);
|
||||
void OnMove(wxMouseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
void post_event(wxCommandEvent&& event);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
public:
|
||||
bool m_hover{ false };
|
||||
ScalableBitmap m_bitmap_check_disable;
|
||||
ScalableBitmap m_bitmap_check_off;
|
||||
ScalableBitmap m_bitmap_check_on;
|
||||
};
|
||||
|
||||
|
||||
class MultiMachinePickPage : public DPIDialog
|
||||
{
|
||||
private:
|
||||
AppConfig* app_config;
|
||||
Label* m_label{ nullptr };
|
||||
wxScrolledWindow* scroll_macine_list{ nullptr };
|
||||
wxBoxSizer* m_sizer_body{ nullptr };
|
||||
wxBoxSizer* sizer_machine_list{ nullptr };
|
||||
std::map<std::string, DevicePickItem*> m_device_items;
|
||||
int m_selected_count{0};
|
||||
public:
|
||||
MultiMachinePickPage(Plater* plater = nullptr);
|
||||
~MultiMachinePickPage();
|
||||
|
||||
int get_selected_count();
|
||||
void update_selected_count();
|
||||
void on_dpi_changed(const wxRect& suggested_rect);
|
||||
void on_sys_color_changed();
|
||||
void refresh_user_device();
|
||||
void on_confirm(wxCommandEvent& event);
|
||||
bool Show(bool show);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "MultiPrintJob.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef slic3r_MultiPrintJob_hpp_
|
||||
#define slic3r_MultiPrintJob_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "MultiSendMachineModel.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
MultiSendMachineModel::MultiSendMachineModel()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
MultiSendMachineModel::~MultiSendMachineModel()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void MultiSendMachineModel::Init()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
wxDataViewItem MultiSendMachineModel::AddMachine(MachineObject* obj)
|
||||
{
|
||||
wxString name = from_u8(obj->dev_name);
|
||||
|
||||
wxDataViewItem new_item;
|
||||
|
||||
// TODO
|
||||
return new_item;
|
||||
}
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef slic3r_MultiSendMachineModel_hpp_
|
||||
#define slic3r_MultiSendMachineModel_hpp_
|
||||
|
||||
#include "DeviceManager.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class MultiSendMachineModel : public wxDataViewModel
|
||||
{
|
||||
public:
|
||||
MultiSendMachineModel();
|
||||
~MultiSendMachineModel();
|
||||
|
||||
void Init();
|
||||
|
||||
wxDataViewItem AddMachine(MachineObject* obj);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,208 @@
|
||||
#ifndef slic3r_MultiTaskManagerPage_hpp_
|
||||
#define slic3r_MultiTaskManagerPage_hpp_
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MultiMachine.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
#include "TaskManager.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
#include "Widgets/ScrolledWindow.hpp"
|
||||
#include "Widgets/PopupWindow.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define CLOUD_TASK_ITEM_MAX_WIDTH 1100
|
||||
#define TASK_ITEM_MAX_WIDTH 900
|
||||
#define TASK_LEFT_PADDING_LEFT 15
|
||||
#define TASK_LEFT_PRINTABLE 40
|
||||
#define TASK_LEFT_PRO_NAME 180
|
||||
#define TASK_LEFT_DEV_NAME 150
|
||||
#define TASK_LEFT_PRO_STATE 170
|
||||
#define TASK_LEFT_PRO_INFO 230
|
||||
#define TASK_LEFT_SEND_TIME 180
|
||||
|
||||
class MultiTaskItem : public DeviceItem
|
||||
{
|
||||
public:
|
||||
MultiTaskItem(wxWindow* parent, MachineObject* obj, int type);
|
||||
~MultiTaskItem() {};
|
||||
|
||||
|
||||
void OnEnterWindow(wxMouseEvent& evt);
|
||||
void OnLeaveWindow(wxMouseEvent& evt);
|
||||
void OnSelectedDevice(wxCommandEvent& evt);
|
||||
void OnLeftDown(wxMouseEvent& evt);
|
||||
void OnMove(wxMouseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
|
||||
void post_event(wxCommandEvent&& event);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
bool m_hover{ false };
|
||||
wxString get_left_time(int mc_left_time);
|
||||
|
||||
ScalableBitmap m_bitmap_check_disable;
|
||||
ScalableBitmap m_bitmap_check_off;
|
||||
ScalableBitmap m_bitmap_check_on;
|
||||
|
||||
int m_sending_percent{0};
|
||||
int m_task_type{0}; //0-local 1-cloud
|
||||
wxString m_project_name;
|
||||
wxString m_dev_name;
|
||||
std::string m_dev_id;
|
||||
TaskStateInfo* task_obj { nullptr };
|
||||
std::string m_job_id;
|
||||
//std::string m_sent_time;
|
||||
|
||||
Button* m_button_resume{ nullptr };
|
||||
Button* m_button_cancel{ nullptr };
|
||||
Button* m_button_pause{ nullptr };
|
||||
Button* m_button_stop{ nullptr };
|
||||
|
||||
void update_info();
|
||||
void onPause();
|
||||
void onResume();
|
||||
void onStop();
|
||||
void onCancel();
|
||||
};
|
||||
|
||||
class LocalTaskManagerPage : public wxPanel
|
||||
{
|
||||
public:
|
||||
LocalTaskManagerPage(wxWindow* parent);
|
||||
~LocalTaskManagerPage() {};
|
||||
|
||||
void update_page();
|
||||
void refresh_user_device(bool clear = false);
|
||||
bool Show(bool show);
|
||||
void cancel_all(wxCommandEvent& evt);
|
||||
|
||||
private:
|
||||
SortItem m_sort;
|
||||
std::map<int, MultiTaskItem*> m_task_items;
|
||||
bool device_name_big{ true };
|
||||
bool device_state_big{ true };
|
||||
bool device_send_time{ true };
|
||||
|
||||
wxPanel* m_main_panel{ nullptr };
|
||||
wxBoxSizer* m_main_sizer{ nullptr };
|
||||
wxBoxSizer* page_sizer{ nullptr };
|
||||
wxBoxSizer* m_sizer_task_list{ nullptr };
|
||||
wxScrolledWindow* m_task_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
wxBoxSizer* m_table_head_sizer{ nullptr };
|
||||
CheckBox* m_select_checkbox{ nullptr };
|
||||
Button* m_task_name{ nullptr };
|
||||
Button* m_printer_name{ nullptr };
|
||||
Button* m_status{ nullptr };
|
||||
Button* m_info{ nullptr };
|
||||
Button* m_send_time{ nullptr };
|
||||
Button* m_action{ nullptr };
|
||||
|
||||
// ctrl button for all
|
||||
int m_sel_number{0};
|
||||
wxPanel* m_ctrl_btn_panel{ nullptr };
|
||||
wxBoxSizer* m_btn_sizer{ nullptr };
|
||||
Button* btn_stop_all{ nullptr };
|
||||
wxStaticText* m_sel_text{ nullptr };
|
||||
|
||||
// tip when no device
|
||||
wxStaticText* m_tip_text{ nullptr };
|
||||
};
|
||||
|
||||
class CloudTaskManagerPage : public wxPanel
|
||||
{
|
||||
public:
|
||||
CloudTaskManagerPage(wxWindow* parent);
|
||||
~CloudTaskManagerPage();
|
||||
|
||||
void update_page();
|
||||
void refresh_user_device(bool clear = false);
|
||||
std::string utc_time_to_date(std::string utc_time);
|
||||
bool Show(bool show);
|
||||
void update_page_number();
|
||||
void start_timer();
|
||||
void on_timer(wxTimerEvent& event);
|
||||
|
||||
void pause_all(wxCommandEvent& evt);
|
||||
void resume_all(wxCommandEvent& evt);
|
||||
void stop_all(wxCommandEvent& evt);
|
||||
|
||||
void enable_buttons(bool enable);
|
||||
void page_num_enter_evt();
|
||||
|
||||
private:
|
||||
SortItem m_sort;
|
||||
bool device_name_big{ true };
|
||||
bool device_state_big{ true };
|
||||
bool device_send_time{ true };
|
||||
|
||||
/* job_id -> sel */
|
||||
std::map <std::string, MultiTaskItem*> m_task_items;
|
||||
|
||||
wxPanel* m_main_panel{ nullptr };
|
||||
wxBoxSizer* page_sizer{ nullptr };
|
||||
wxBoxSizer* m_sizer_task_list{ nullptr };
|
||||
wxBoxSizer* m_main_sizer{ nullptr };
|
||||
wxScrolledWindow* m_task_list{ nullptr };
|
||||
wxStaticText* m_selected_num{ nullptr };
|
||||
|
||||
// Flipping pages
|
||||
int m_current_page{ 0 };
|
||||
int m_total_page{0};
|
||||
int m_total_count{ 0 };
|
||||
int m_count_page_item{ 10 };
|
||||
bool prev{ false };
|
||||
bool next{ false };
|
||||
Button* btn_last_page{ nullptr };
|
||||
Button* btn_next_page{ nullptr };
|
||||
wxStaticText* st_page_number{ nullptr };
|
||||
wxBoxSizer* m_flipping_page_sizer{ nullptr };
|
||||
wxBoxSizer* m_page_sizer{ nullptr };
|
||||
wxPanel* m_flipping_panel{ nullptr };
|
||||
wxTimer* m_flipping_timer{ nullptr };
|
||||
TextInput* m_page_num_input{ nullptr };
|
||||
Button* m_page_num_enter{ nullptr };
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
wxBoxSizer* m_table_head_sizer{ nullptr };
|
||||
CheckBox* m_select_checkbox{ nullptr };
|
||||
Button* m_task_name{ nullptr };
|
||||
Button* m_printer_name{ nullptr };
|
||||
Button* m_status{ nullptr };
|
||||
Button* m_info{ nullptr };
|
||||
Button* m_send_time{ nullptr };
|
||||
Button* m_action{ nullptr };
|
||||
|
||||
// ctrl button for all
|
||||
int m_sel_number;
|
||||
wxPanel* m_ctrl_btn_panel{ nullptr };
|
||||
wxBoxSizer* m_btn_sizer{ nullptr };
|
||||
Button* btn_pause_all{ nullptr };
|
||||
Button* btn_continue_all{ nullptr };
|
||||
Button* btn_stop_all{ nullptr };
|
||||
wxStaticText* m_sel_text{ nullptr };
|
||||
|
||||
// tip when no device
|
||||
wxStaticText* m_tip_text{ nullptr };
|
||||
wxStaticText* m_loading_text{ nullptr };
|
||||
};
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef slic3r_MultiTaskModel_hpp_
|
||||
#define slic3r_MultiTaskModel_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,817 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
//#include "libslic3r/FlushVolCalc.hpp"
|
||||
#include "ObjColorDialog.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "slic3r/Utils/ColorSpaceConvert.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "BitmapComboBox.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
#include <wx/sizer.h>
|
||||
|
||||
#include "libslic3r/ObjColorUtils.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
int objcolor_scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit() / 10; }
|
||||
int OBJCOLOR_ITEM_WIDTH() { return objcolor_scale(30); }
|
||||
static const wxColour g_text_color = wxColour(107, 107, 107, 255);
|
||||
const int HEADER_BORDER = 5;
|
||||
const int CONTENT_BORDER = 3;
|
||||
const int PANEL_WIDTH = 370;
|
||||
const int COLOR_LABEL_WIDTH = 180;
|
||||
#define ICON_SIZE wxSize(FromDIP(16), FromDIP(16))
|
||||
#define MIN_OBJCOLOR_DIALOG_WIDTH FromDIP(400)
|
||||
#define FIX_SCROLL_HEIGTH FromDIP(400)
|
||||
#define BTN_SIZE wxSize(FromDIP(58), FromDIP(24))
|
||||
#define BTN_GAP FromDIP(20)
|
||||
|
||||
static void update_ui(wxWindow* window)
|
||||
{
|
||||
Slic3r::GUI::wxGetApp().UpdateDarkUI(window);
|
||||
}
|
||||
|
||||
static const char g_min_cluster_color = 1;
|
||||
//static const char g_max_cluster_color = 15;
|
||||
static const char g_max_color = 16;
|
||||
const StateColor ok_btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
const StateColor ok_btn_disable_bg(std::pair<wxColour, int>(wxColour(205, 201, 201), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(205, 201, 201), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(205, 201, 201), StateColor::Normal));
|
||||
wxBoxSizer* ObjColorDialog::create_btn_sizer(long flags)
|
||||
{
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_sizer->AddStretchSpacer();
|
||||
|
||||
StateColor ok_btn_bd(
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
StateColor ok_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal)
|
||||
);
|
||||
StateColor cancel_btn_bg(
|
||||
std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal)
|
||||
);
|
||||
StateColor cancel_btn_bd_(
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Normal)
|
||||
);
|
||||
StateColor cancel_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Normal)
|
||||
);
|
||||
StateColor calc_btn_bg(
|
||||
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
StateColor calc_btn_bd(
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
StateColor calc_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal)
|
||||
);
|
||||
if (flags & wxOK) {
|
||||
Button* ok_btn = new Button(this, _L("OK"));
|
||||
ok_btn->SetMinSize(BTN_SIZE);
|
||||
ok_btn->SetCornerRadius(FromDIP(12));
|
||||
ok_btn->Enable(false);
|
||||
ok_btn->SetBackgroundColor(ok_btn_disable_bg);
|
||||
ok_btn->SetBorderColor(ok_btn_bd);
|
||||
ok_btn->SetTextColor(ok_btn_text);
|
||||
ok_btn->SetFocus();
|
||||
ok_btn->SetId(wxID_OK);
|
||||
btn_sizer->Add(ok_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, BTN_GAP);
|
||||
m_button_list[wxOK] = ok_btn;
|
||||
}
|
||||
if (flags & wxCANCEL) {
|
||||
Button* cancel_btn = new Button(this, _L("Cancel"));
|
||||
cancel_btn->SetMinSize(BTN_SIZE);
|
||||
cancel_btn->SetCornerRadius(FromDIP(12));
|
||||
cancel_btn->SetBackgroundColor(cancel_btn_bg);
|
||||
cancel_btn->SetBorderColor(cancel_btn_bd_);
|
||||
cancel_btn->SetTextColor(cancel_btn_text);
|
||||
cancel_btn->SetId(wxID_CANCEL);
|
||||
btn_sizer->Add(cancel_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, BTN_GAP);
|
||||
m_button_list[wxCANCEL] = cancel_btn;
|
||||
}
|
||||
return btn_sizer;
|
||||
}
|
||||
|
||||
void ObjColorDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
{
|
||||
for (auto button_item : m_button_list)
|
||||
{
|
||||
if (button_item.first == wxRESET)
|
||||
{
|
||||
button_item.second->SetMinSize(wxSize(FromDIP(75), FromDIP(24)));
|
||||
button_item.second->SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
if (button_item.first == wxOK) {
|
||||
button_item.second->SetMinSize(BTN_SIZE);
|
||||
button_item.second->SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
if (button_item.first == wxCANCEL) {
|
||||
button_item.second->SetMinSize(BTN_SIZE);
|
||||
button_item.second->SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
}
|
||||
m_panel_ObjColor->msw_rescale();
|
||||
this->Refresh();
|
||||
};
|
||||
|
||||
ObjColorDialog::ObjColorDialog(wxWindow * parent,
|
||||
std::vector<Slic3r::RGBA> & input_colors,
|
||||
bool is_single_color,
|
||||
const std::vector<std::string> &extruder_colours,
|
||||
std::vector<unsigned char> & filament_ids,
|
||||
unsigned char & first_extruder_id)
|
||||
: DPIDialog(parent ? parent : static_cast<wxWindow *>(wxGetApp().mainframe),
|
||||
wxID_ANY,
|
||||
_(L("Obj file Import color")),
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE /* | wxRESIZE_BORDER*/)
|
||||
, m_filament_ids(filament_ids)
|
||||
, m_first_extruder_id(first_extruder_id)
|
||||
{
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % Slic3r::resources_dir()).str();
|
||||
SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
this->SetBackgroundColour(*wxWHITE);
|
||||
this->SetMinSize(wxSize(MIN_OBJCOLOR_DIALOG_WIDTH, -1));
|
||||
|
||||
m_panel_ObjColor = new ObjColorPanel(this, input_colors, is_single_color, extruder_colours, filament_ids, first_extruder_id);
|
||||
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
|
||||
// set min sizer width according to extruders count
|
||||
auto sizer_width = (int) (2.8 * OBJCOLOR_ITEM_WIDTH());
|
||||
sizer_width = sizer_width > MIN_OBJCOLOR_DIALOG_WIDTH ? sizer_width : MIN_OBJCOLOR_DIALOG_WIDTH;
|
||||
main_sizer->SetMinSize(wxSize(sizer_width, -1));
|
||||
main_sizer->Add(m_panel_ObjColor, 1, wxEXPAND | wxALL, 0);
|
||||
|
||||
auto btn_sizer = create_btn_sizer(wxOK | wxCANCEL);
|
||||
{
|
||||
m_button_list[wxOK]->Bind(wxEVT_UPDATE_UI, ([this](wxUpdateUIEvent &e) {
|
||||
if (m_panel_ObjColor->is_ok() == m_button_list[wxOK]->IsEnabled()) { return; }
|
||||
m_button_list[wxOK]->Enable(m_panel_ObjColor->is_ok());
|
||||
m_button_list[wxOK]->SetBackgroundColor(m_panel_ObjColor->is_ok() ? ok_btn_bg : ok_btn_disable_bg);
|
||||
}));
|
||||
}
|
||||
main_sizer->Add(btn_sizer, 0, wxBOTTOM | wxRIGHT | wxEXPAND, BTN_GAP);
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
|
||||
if (this->FindWindowById(wxID_OK, this)) {
|
||||
this->FindWindowById(wxID_OK, this)->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {// if OK button is clicked..
|
||||
m_panel_ObjColor->update_filament_ids();
|
||||
EndModal(wxID_OK);
|
||||
}, wxID_OK);
|
||||
}
|
||||
if (this->FindWindowById(wxID_CANCEL, this)) {
|
||||
update_ui(static_cast<wxButton*>(this->FindWindowById(wxID_CANCEL, this)));
|
||||
this->FindWindowById(wxID_CANCEL, this)->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { EndModal(wxCANCEL); });
|
||||
}
|
||||
this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { EndModal(wxCANCEL); });
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
RGBA convert_to_rgba(const wxColour &color)
|
||||
{
|
||||
RGBA rgba;
|
||||
rgba[0] = std::clamp(color.Red() / 255.f, 0.f, 1.f);
|
||||
rgba[1] = std::clamp(color.Green() / 255.f, 0.f, 1.f);
|
||||
rgba[2] = std::clamp(color.Blue() / 255.f, 0.f, 1.f);
|
||||
rgba[3] = std::clamp(color.Alpha() / 255.f, 0.f, 1.f);
|
||||
return rgba;
|
||||
}
|
||||
wxColour convert_to_wxColour(const RGBA &color)
|
||||
{
|
||||
auto r = std::clamp((int) (color[0] * 255.f), 0, 255);
|
||||
auto g = std::clamp((int) (color[1] * 255.f), 0, 255);
|
||||
auto b = std::clamp((int) (color[2] * 255.f), 0, 255);
|
||||
auto a = std::clamp((int) (color[3] * 255.f), 0, 255);
|
||||
wxColour wx_color(r,g,b,a);
|
||||
return wx_color;
|
||||
}
|
||||
// This panel contains all control widgets for both simple and advanced mode (these reside in separate sizers)
|
||||
ObjColorPanel::ObjColorPanel(wxWindow * parent,
|
||||
std::vector<Slic3r::RGBA>& input_colors,
|
||||
bool is_single_color,
|
||||
const std::vector<std::string>& extruder_colours,
|
||||
std::vector<unsigned char> & filament_ids,
|
||||
unsigned char & first_extruder_id)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize /*,wxBORDER_RAISED*/)
|
||||
, m_input_colors(input_colors)
|
||||
, m_filament_ids(filament_ids)
|
||||
, m_first_extruder_id(first_extruder_id)
|
||||
{
|
||||
if (input_colors.size() == 0) { return; }
|
||||
for (const std::string& color : extruder_colours) {
|
||||
m_colours.push_back(wxColor(color));
|
||||
}
|
||||
//deal input_colors
|
||||
m_input_colors_size = input_colors.size();
|
||||
for (size_t i = 0; i < input_colors.size(); i++) {
|
||||
if (color_is_equal(input_colors[i] , UNDEFINE_COLOR)) { // not define color range:0~1
|
||||
input_colors[i]=convert_to_rgba( m_colours[0]);
|
||||
}
|
||||
}
|
||||
if (is_single_color && input_colors.size() >=1) {
|
||||
m_cluster_colors_from_algo.emplace_back(input_colors[0]);
|
||||
m_cluster_colours.emplace_back(convert_to_wxColour(input_colors[0]));
|
||||
m_cluster_labels_from_algo.reserve(m_input_colors_size);
|
||||
for (size_t i = 0; i < m_input_colors_size; i++) {
|
||||
m_cluster_labels_from_algo.emplace_back(0);
|
||||
}
|
||||
m_cluster_map_filaments.resize(m_cluster_colors_from_algo.size());
|
||||
m_color_num_recommend = m_color_cluster_num_by_algo = m_cluster_colors_from_algo.size();
|
||||
} else {//cluster deal
|
||||
deal_algo(-1);
|
||||
}
|
||||
//end first cluster
|
||||
//draw ui
|
||||
auto sizer_width = FromDIP(300);
|
||||
// Create two switched panels with their own sizers
|
||||
m_sizer_simple = new wxBoxSizer(wxVERTICAL);
|
||||
m_page_simple = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
m_page_simple->SetSizer(m_sizer_simple);
|
||||
m_page_simple->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
update_ui(m_page_simple);
|
||||
// BBS
|
||||
m_sizer_simple->AddSpacer(FromDIP(10));
|
||||
// BBS: for tunning flush volumes
|
||||
{
|
||||
//color cluster results
|
||||
wxBoxSizer * specify_cluster_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticText *specify_color_cluster_title = new wxStaticText(m_page_simple, wxID_ANY, _L("Specify number of colors:"));
|
||||
specify_color_cluster_title->SetFont(Label::Head_14);
|
||||
specify_cluster_sizer->Add(specify_color_cluster_title, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
|
||||
|
||||
m_color_cluster_num_by_user_ebox = new wxTextCtrl(m_page_simple, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(25), -1), wxTE_PROCESS_ENTER);
|
||||
m_color_cluster_num_by_user_ebox->SetValue(std::to_string(m_color_cluster_num_by_algo).c_str());
|
||||
{//event
|
||||
auto on_apply_color_cluster_text_modify = [this](wxEvent &e) {
|
||||
wxString str = m_color_cluster_num_by_user_ebox->GetValue();
|
||||
int number = wxAtoi(str);
|
||||
if (number > m_color_num_recommend || number < g_min_cluster_color) {
|
||||
number = number < g_min_cluster_color ? g_min_cluster_color : m_color_num_recommend;
|
||||
str = wxString::Format(("%d"), number);
|
||||
m_color_cluster_num_by_user_ebox->SetValue(str);
|
||||
MessageDialog dlg(nullptr, wxString::Format(_L("The color count should be in range [%d, %d]."), g_min_cluster_color, m_color_num_recommend),
|
||||
_L("Warning"), wxICON_WARNING | wxOK);
|
||||
dlg.ShowModal();
|
||||
}
|
||||
e.Skip();
|
||||
};
|
||||
m_color_cluster_num_by_user_ebox->Bind(wxEVT_TEXT_ENTER, on_apply_color_cluster_text_modify);
|
||||
m_color_cluster_num_by_user_ebox->Bind(wxEVT_KILL_FOCUS, on_apply_color_cluster_text_modify);
|
||||
m_color_cluster_num_by_user_ebox->Bind(wxEVT_COMMAND_TEXT_UPDATED, [this](wxCommandEvent &) {
|
||||
wxString str = m_color_cluster_num_by_user_ebox->GetValue();
|
||||
int number = wxAtof(str);
|
||||
if (number > m_color_num_recommend || number < g_min_cluster_color) {
|
||||
number = number < g_min_cluster_color ? g_min_cluster_color : m_color_num_recommend;
|
||||
str = wxString::Format(("%d"), number);
|
||||
m_color_cluster_num_by_user_ebox->SetValue(str);
|
||||
m_color_cluster_num_by_user_ebox->SetInsertionPointEnd();
|
||||
}
|
||||
if (m_last_cluster_num != number) {
|
||||
deal_algo(number, true);
|
||||
Layout();
|
||||
//Fit();
|
||||
Refresh();
|
||||
Update();
|
||||
m_last_cluster_num = number;
|
||||
}
|
||||
});
|
||||
m_color_cluster_num_by_user_ebox->Bind(wxEVT_CHAR, [this](wxKeyEvent &e) {
|
||||
int keycode = e.GetKeyCode();
|
||||
wxString input_char = wxString::Format("%c", keycode);
|
||||
long value;
|
||||
if (!input_char.ToLong(&value))
|
||||
return;
|
||||
e.Skip();
|
||||
});
|
||||
}
|
||||
specify_cluster_sizer->AddSpacer(FromDIP(2));
|
||||
specify_cluster_sizer->Add(m_color_cluster_num_by_user_ebox, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
specify_cluster_sizer->AddSpacer(FromDIP(15));
|
||||
wxStaticText *recommend_color_cluster_title = new wxStaticText(m_page_simple, wxID_ANY, "(" + std::to_string(m_color_num_recommend) + " " + _L("Recommended ") + ")");
|
||||
specify_cluster_sizer->Add(recommend_color_cluster_title, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
|
||||
m_sizer_simple->Add(specify_cluster_sizer, 0, wxEXPAND | wxLEFT, FromDIP(20));
|
||||
|
||||
wxBoxSizer * current_filaments_title_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticText *current_filaments_title = new wxStaticText(m_page_simple, wxID_ANY, _L("Current filament colors:"));
|
||||
current_filaments_title->SetFont(Label::Head_14);
|
||||
current_filaments_title_sizer->Add(current_filaments_title, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
|
||||
m_sizer_simple->Add(current_filaments_title_sizer, 0, wxEXPAND | wxLEFT, FromDIP(20));
|
||||
|
||||
wxBoxSizer * current_filaments_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
current_filaments_sizer->AddSpacer(FromDIP(10));
|
||||
for (size_t i = 0; i < m_colours.size(); i++) {
|
||||
auto extruder_icon_sizer = create_extruder_icon_and_rgba_sizer(m_page_simple, i, m_colours[i]);
|
||||
current_filaments_sizer->Add(extruder_icon_sizer, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(10));
|
||||
}
|
||||
m_sizer_simple->Add(current_filaments_sizer, 0, wxEXPAND | wxLEFT, FromDIP(20));
|
||||
//colors table
|
||||
m_scrolledWindow = new wxScrolledWindow(m_page_simple,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxSB_VERTICAL);
|
||||
m_sizer_simple->Add(m_scrolledWindow, 0, wxEXPAND | wxALL, FromDIP(5));
|
||||
draw_table();
|
||||
//buttons
|
||||
wxBoxSizer *quick_set_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticText *quick_set_title = new wxStaticText(m_page_simple, wxID_ANY, _L("Quick set:"));
|
||||
quick_set_title->SetFont(Label::Head_12);
|
||||
quick_set_sizer->Add(quick_set_title, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
quick_set_sizer->AddSpacer(FromDIP(10));
|
||||
|
||||
auto calc_approximate_match_btn_sizer = create_approximate_match_btn_sizer(m_page_simple);
|
||||
auto calc_add_btn_sizer = create_add_btn_sizer(m_page_simple);
|
||||
auto calc_reset_btn_sizer = create_reset_btn_sizer(m_page_simple);
|
||||
quick_set_sizer->Add(calc_add_btn_sizer, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
quick_set_sizer->AddSpacer(FromDIP(10));
|
||||
quick_set_sizer->Add(calc_approximate_match_btn_sizer, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
quick_set_sizer->AddSpacer(FromDIP(10));
|
||||
quick_set_sizer->Add(calc_reset_btn_sizer, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
quick_set_sizer->AddSpacer(FromDIP(10));
|
||||
m_sizer_simple->Add(quick_set_sizer, 0, wxEXPAND | wxLEFT, FromDIP(30));
|
||||
|
||||
wxBoxSizer *warning_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_warning_text = new wxStaticText(m_page_simple, wxID_ANY, "");
|
||||
warning_sizer->Add(m_warning_text, 0, wxALIGN_CENTER | wxALL, 0);
|
||||
m_sizer_simple->Add(warning_sizer, 0, wxEXPAND | wxLEFT, FromDIP(30));
|
||||
|
||||
m_sizer_simple->AddSpacer(10);
|
||||
}
|
||||
deal_default_strategy();
|
||||
//page_simple//page_advanced
|
||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_sizer->Add(m_page_simple, 0, wxEXPAND, 0);
|
||||
|
||||
m_sizer->SetSizeHints(this);
|
||||
SetSizer(m_sizer);
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
void ObjColorPanel::msw_rescale()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_extruder_icon_list.size(); ++i) {
|
||||
auto bitmap = *get_extruder_color_icon(m_colours[i].GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(i + 1), FromDIP(16), FromDIP(16));
|
||||
m_extruder_icon_list[i]->SetBitmap(bitmap);
|
||||
}
|
||||
/* for (unsigned int i = 0; i < m_color_cluster_icon_list.size(); ++i) {
|
||||
auto bitmap = *get_extruder_color_icon(m_cluster_colours[i].GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(i + 1), FromDIP(16), FromDIP(16));
|
||||
m_color_cluster_icon_list[i]->SetBitmap(bitmap);
|
||||
}*/
|
||||
}
|
||||
|
||||
bool ObjColorPanel::is_ok() {
|
||||
for (auto item : m_result_icon_list) {
|
||||
if (item->bitmap_combox->IsShown()) {
|
||||
auto selection = item->bitmap_combox->GetSelection();
|
||||
if (selection < 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjColorPanel::update_filament_ids()
|
||||
{
|
||||
if (m_is_add_filament) {
|
||||
for (auto c:m_new_add_colors) {
|
||||
/*auto evt = new ColorEvent(EVT_ADD_CUSTOM_FILAMENT, c);
|
||||
wxQueueEvent(wxGetApp().plater(), evt);*/
|
||||
wxGetApp().sidebar().add_custom_filament(c);
|
||||
}
|
||||
}
|
||||
//deal m_filament_ids
|
||||
m_filament_ids.clear();
|
||||
m_filament_ids.reserve(m_input_colors_size);
|
||||
for (size_t i = 0; i < m_input_colors_size; i++) {
|
||||
auto label = m_cluster_labels_from_algo[i];
|
||||
m_filament_ids.emplace_back(m_cluster_map_filaments[label]);
|
||||
}
|
||||
m_first_extruder_id = m_cluster_map_filaments[0];
|
||||
}
|
||||
|
||||
wxBoxSizer *ObjColorPanel::create_approximate_match_btn_sizer(wxWindow *parent)
|
||||
{
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
StateColor calc_btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_bd(std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_text(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal));
|
||||
//create btn
|
||||
m_quick_approximate_match_btn = new Button(parent, _L("Color match"));
|
||||
m_quick_approximate_match_btn->SetToolTip(_L("Approximate color matching."));
|
||||
auto cur_btn = m_quick_approximate_match_btn;
|
||||
cur_btn->SetFont(Label::Body_13);
|
||||
cur_btn->SetMinSize(wxSize(FromDIP(60), FromDIP(20)));
|
||||
cur_btn->SetCornerRadius(FromDIP(10));
|
||||
cur_btn->SetBackgroundColor(calc_btn_bg);
|
||||
cur_btn->SetBorderColor(calc_btn_bd);
|
||||
cur_btn->SetTextColor(calc_btn_text);
|
||||
cur_btn->SetFocus();
|
||||
btn_sizer->Add(cur_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 0);
|
||||
cur_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) {
|
||||
deal_approximate_match_btn();
|
||||
});
|
||||
return btn_sizer;
|
||||
}
|
||||
|
||||
wxBoxSizer *ObjColorPanel::create_add_btn_sizer(wxWindow *parent)
|
||||
{
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
StateColor calc_btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_bd(std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_text(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal));
|
||||
// create btn
|
||||
m_quick_add_btn = new Button(parent, _L("Append"));
|
||||
m_quick_add_btn->SetToolTip(_L("Add consumable extruder after existing extruders."));
|
||||
auto cur_btn = m_quick_add_btn;
|
||||
cur_btn->SetFont(Label::Body_13);
|
||||
cur_btn->SetMinSize(wxSize(FromDIP(60), FromDIP(20)));
|
||||
cur_btn->SetCornerRadius(FromDIP(10));
|
||||
cur_btn->SetBackgroundColor(calc_btn_bg);
|
||||
cur_btn->SetBorderColor(calc_btn_bd);
|
||||
cur_btn->SetTextColor(calc_btn_text);
|
||||
cur_btn->SetFocus();
|
||||
btn_sizer->Add(cur_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 0);
|
||||
cur_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) {
|
||||
deal_add_btn();
|
||||
});
|
||||
return btn_sizer;
|
||||
}
|
||||
|
||||
wxBoxSizer *ObjColorPanel::create_reset_btn_sizer(wxWindow *parent)
|
||||
{
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
StateColor calc_btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_bd(std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
|
||||
StateColor calc_btn_text(std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal));
|
||||
// create btn
|
||||
m_quick_reset_btn = new Button(parent, _L("Reset"));
|
||||
m_quick_add_btn->SetToolTip(_L("Reset mapped extruders."));
|
||||
auto cur_btn = m_quick_reset_btn;
|
||||
cur_btn->SetFont(Label::Body_13);
|
||||
cur_btn->SetMinSize(wxSize(FromDIP(60), FromDIP(20)));
|
||||
cur_btn->SetCornerRadius(FromDIP(10));
|
||||
cur_btn->SetBackgroundColor(calc_btn_bg);
|
||||
cur_btn->SetBorderColor(calc_btn_bd);
|
||||
cur_btn->SetTextColor(calc_btn_text);
|
||||
cur_btn->SetFocus();
|
||||
btn_sizer->Add(cur_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 0);
|
||||
cur_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) {
|
||||
deal_reset_btn();
|
||||
});
|
||||
return btn_sizer;
|
||||
}
|
||||
|
||||
wxBoxSizer *ObjColorPanel::create_extruder_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour &color)
|
||||
{
|
||||
auto icon_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxButton *icon = new wxButton(parent, wxID_ANY, {}, wxDefaultPosition, ICON_SIZE, wxBORDER_NONE | wxBU_AUTODRAW);
|
||||
icon->SetBitmap(*get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(id + 1), FromDIP(16), FromDIP(16)));
|
||||
icon->SetCanFocus(false);
|
||||
m_extruder_icon_list.emplace_back(icon);
|
||||
icon_sizer->Add(icon, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(10)); // wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM
|
||||
|
||||
icon_sizer->AddSpacer(FromDIP(5));
|
||||
return icon_sizer;
|
||||
}
|
||||
|
||||
std::string ObjColorPanel::get_color_str(const wxColour &color) {
|
||||
std::string str = ("R:" + std::to_string(color.Red()) +
|
||||
std::string(" G:") + std::to_string(color.Green()) +
|
||||
std::string(" B:") + std::to_string(color.Blue()) +
|
||||
std::string(" A:") + std::to_string(color.Alpha()));
|
||||
return str;
|
||||
}
|
||||
|
||||
ComboBox *ObjColorPanel::CreateEditorCtrl(wxWindow *parent, int id) // wxRect labelRect,, const wxVariant &value
|
||||
{
|
||||
std::vector<wxBitmap *> icons = get_extruder_color_icons();
|
||||
const double em = Slic3r::GUI::wxGetApp().em_unit();
|
||||
bool thin_icon = false;
|
||||
const int icon_width = lround((thin_icon ? 2 : 4.4) * em);
|
||||
const int icon_height = lround(2 * em);
|
||||
m_combox_icon_width = icon_width;
|
||||
m_combox_icon_height = icon_height;
|
||||
wxColour undefined_color(0,255,0,255);
|
||||
icons.insert(icons.begin(), get_extruder_color_icon(undefined_color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(-1), icon_width, icon_height));
|
||||
if (icons.empty())
|
||||
return nullptr;
|
||||
|
||||
::ComboBox *c_editor = new ::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(m_combox_width), -1), 0, nullptr,
|
||||
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);
|
||||
for (size_t i = 0; i < icons.size(); i++) {
|
||||
c_editor->Append(wxString::Format("%d", i), *icons[i]);
|
||||
if (i == 0) {
|
||||
c_editor->SetItemTooltip(i,undefined_color.GetAsString(wxC2S_HTML_SYNTAX));
|
||||
} else {
|
||||
c_editor->SetItemTooltip(i, m_colours[i-1].GetAsString(wxC2S_HTML_SYNTAX));
|
||||
}
|
||||
}
|
||||
c_editor->SetSelection(0);
|
||||
c_editor->SetName(wxString::Format("%d", id));
|
||||
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) {
|
||||
auto *com_box = static_cast<ComboBox *>(evt.GetEventObject());
|
||||
int i = atoi(com_box->GetName().c_str());
|
||||
if (i < m_cluster_map_filaments.size()) { m_cluster_map_filaments[i] = com_box->GetSelection(); }
|
||||
evt.StopPropagation();
|
||||
});
|
||||
return c_editor;
|
||||
}
|
||||
|
||||
void ObjColorPanel::deal_approximate_match_btn()
|
||||
{
|
||||
auto calc_color_distance = [](wxColour c1, wxColour c2) {
|
||||
float lab[2][3];
|
||||
RGB2Lab(c1.Red(), c1.Green(), c1.Blue(), &lab[0][0], &lab[0][1], &lab[0][2]);
|
||||
RGB2Lab(c2.Red(), c2.Green(), c2.Blue(), &lab[1][0], &lab[1][1], &lab[1][2]);
|
||||
|
||||
return DeltaE76(lab[0][0], lab[0][1], lab[0][2], lab[1][0], lab[1][1], lab[1][2]);
|
||||
};
|
||||
m_warning_text->SetLabelText("");
|
||||
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; }
|
||||
for (size_t i = 0; i < m_cluster_colours.size(); i++) {
|
||||
auto c = m_cluster_colours[i];
|
||||
std::vector<ColorDistValue> color_dists;
|
||||
color_dists.resize(map_count);
|
||||
for (size_t j = 0; j < map_count; j++) {
|
||||
auto tip_color = m_result_icon_list[0]->bitmap_combox->GetItemTooltip(j+1);
|
||||
wxColour candidate_c(tip_color);
|
||||
color_dists[j].distance = calc_color_distance(c, candidate_c);
|
||||
color_dists[j].id = j + 1;
|
||||
}
|
||||
std::sort(color_dists.begin(), color_dists.end(), [](ColorDistValue &a, ColorDistValue& b) {
|
||||
return a.distance < b.distance;
|
||||
});
|
||||
auto new_index= color_dists[0].id;
|
||||
m_result_icon_list[i]->bitmap_combox->SetSelection(new_index);
|
||||
m_cluster_map_filaments[i] = new_index;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjColorPanel::show_sizer(wxSizer *sizer, bool show)
|
||||
{
|
||||
wxSizerItemList items = sizer->GetChildren();
|
||||
for (wxSizerItemList::iterator it = items.begin(); it != items.end(); ++it) {
|
||||
wxSizerItem *item = *it;
|
||||
if (wxWindow *window = item->GetWindow()) {
|
||||
window->Show(show);
|
||||
}
|
||||
if (wxSizer *son_sizer = item->GetSizer()) {
|
||||
show_sizer(son_sizer, show);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjColorPanel::redraw_part_table() {
|
||||
//show all and set -1
|
||||
deal_reset_btn();
|
||||
for (size_t i = 0; i < m_row_sizer_list.size(); i++) {
|
||||
show_sizer(m_row_sizer_list[i], true);
|
||||
}
|
||||
if (m_cluster_colours.size() < m_row_sizer_list.size()) { // show part
|
||||
for (size_t i = m_cluster_colours.size(); i < m_row_sizer_list.size(); i++) {
|
||||
show_sizer(m_row_sizer_list[i], false);
|
||||
//m_row_panel_list[i]->Show(false); // show_sizer(m_left_color_cluster_boxsizer_list[i],false);
|
||||
// m_result_icon_list[i]->bitmap_combox->Show(false);
|
||||
}
|
||||
} else if (m_cluster_colours.size() > m_row_sizer_list.size()) {
|
||||
for (size_t i = m_row_sizer_list.size(); i < m_cluster_colours.size(); i++) {
|
||||
int id = i;
|
||||
wxPanel *row_panel = new wxPanel(m_scrolledWindow);
|
||||
row_panel->SetBackgroundColour((i+1) % 2 == 0 ? *wxWHITE : wxColour(238, 238, 238));
|
||||
auto row_sizer = new wxGridSizer(1, 2, 1, 3);
|
||||
row_panel->SetSizer(row_sizer);
|
||||
|
||||
row_panel->SetMinSize(wxSize(FromDIP(PANEL_WIDTH), -1));
|
||||
row_panel->SetMaxSize(wxSize(FromDIP(PANEL_WIDTH), -1));
|
||||
|
||||
auto cluster_color_icon_sizer = create_color_icon_and_rgba_sizer(row_panel, id, m_cluster_colours[id]);
|
||||
row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER));
|
||||
// result_combox
|
||||
create_result_button_sizer(row_panel, id);
|
||||
row_sizer->Add(m_result_icon_list[id]->bitmap_combox, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
m_row_sizer_list.emplace_back(row_sizer);
|
||||
m_gridsizer->Add(row_panel, 0, wxALIGN_LEFT | wxALL, FromDIP(HEADER_BORDER));
|
||||
}
|
||||
m_gridsizer->Layout();
|
||||
}
|
||||
for (size_t i = 0; i < m_cluster_colours.size(); i++) { // update data
|
||||
// m_color_cluster_icon_list//m_color_cluster_text_list
|
||||
update_color_icon_and_rgba_sizer(i, m_cluster_colours[i]);
|
||||
}
|
||||
m_scrolledWindow->Refresh();
|
||||
}
|
||||
|
||||
void ObjColorPanel::draw_table()
|
||||
{
|
||||
auto row = std::max(m_cluster_colours.size(), m_colours.size()) + 1;
|
||||
m_gridsizer = new wxGridSizer(row, 1, 1, 3); //(int rows, int cols, int vgap, int hgap );
|
||||
|
||||
m_color_cluster_icon_list.clear();
|
||||
m_extruder_icon_list.clear();
|
||||
float row_height ;
|
||||
for (size_t ii = 0; ii < row; ii++) {
|
||||
wxPanel *row_panel = new wxPanel(m_scrolledWindow);
|
||||
row_panel->SetBackgroundColour(ii % 2 == 0 ? *wxWHITE : wxColour(238, 238, 238));
|
||||
auto row_sizer = new wxGridSizer(1, 2, 1, 5);
|
||||
row_panel->SetSizer(row_sizer);
|
||||
|
||||
row_panel->SetMinSize(wxSize(FromDIP(PANEL_WIDTH), -1));
|
||||
row_panel->SetMaxSize(wxSize(FromDIP(PANEL_WIDTH), -1));
|
||||
if (ii == 0) {
|
||||
wxStaticText *colors_left_title = new wxStaticText(row_panel, wxID_ANY, _L("Cluster colors"));
|
||||
colors_left_title->SetFont(Label::Head_14);
|
||||
row_sizer->Add(colors_left_title, 0, wxALIGN_CENTER | wxALL, FromDIP(HEADER_BORDER));
|
||||
|
||||
wxStaticText *colors_middle_title = new wxStaticText(row_panel, wxID_ANY, _L("Map Filament"));
|
||||
colors_middle_title->SetFont(Label::Head_14);
|
||||
row_sizer->Add(colors_middle_title, 0, wxALIGN_CENTER | wxALL, FromDIP(HEADER_BORDER));
|
||||
} else {
|
||||
int id = ii - 1;
|
||||
if (id < m_cluster_colours.size()) {
|
||||
auto cluster_color_icon_sizer = create_color_icon_and_rgba_sizer(row_panel, id, m_cluster_colours[id]);
|
||||
row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER));
|
||||
// result_combox
|
||||
create_result_button_sizer(row_panel, id);
|
||||
row_sizer->Add(m_result_icon_list[id]->bitmap_combox, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER));
|
||||
}
|
||||
}
|
||||
row_height = row_panel->GetSize().GetHeight();
|
||||
if (ii>=1) {
|
||||
m_row_sizer_list.emplace_back(row_sizer);
|
||||
}
|
||||
m_gridsizer->Add(row_panel, 0, wxALIGN_LEFT | wxALL, FromDIP(HEADER_BORDER));
|
||||
}
|
||||
m_scrolledWindow->SetSizer(m_gridsizer);
|
||||
int totalHeight = row_height *(row+1) * 2;
|
||||
m_scrolledWindow->SetVirtualSize(MIN_OBJCOLOR_DIALOG_WIDTH, totalHeight);
|
||||
auto look = FIX_SCROLL_HEIGTH;
|
||||
if (totalHeight > FIX_SCROLL_HEIGTH) {
|
||||
m_scrolledWindow->SetMinSize(wxSize(MIN_OBJCOLOR_DIALOG_WIDTH, FIX_SCROLL_HEIGTH));
|
||||
m_scrolledWindow->SetMaxSize(wxSize(MIN_OBJCOLOR_DIALOG_WIDTH, FIX_SCROLL_HEIGTH));
|
||||
}
|
||||
else {
|
||||
m_scrolledWindow->SetMinSize(wxSize(MIN_OBJCOLOR_DIALOG_WIDTH, totalHeight));
|
||||
}
|
||||
m_scrolledWindow->EnableScrolling(false, true);
|
||||
m_scrolledWindow->ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT);//wxSHOW_SB_ALWAYS
|
||||
m_scrolledWindow->SetScrollRate(20, 20);
|
||||
}
|
||||
|
||||
void ObjColorPanel::deal_algo(char cluster_number, bool redraw_ui)
|
||||
{
|
||||
if (m_last_cluster_number == cluster_number) {
|
||||
return;
|
||||
}
|
||||
m_last_cluster_number = cluster_number;
|
||||
QuantKMeans quant(10);
|
||||
quant.apply(m_input_colors, m_cluster_colors_from_algo, m_cluster_labels_from_algo, (int)cluster_number);
|
||||
m_cluster_colours.clear();
|
||||
m_cluster_colours.reserve(m_cluster_colors_from_algo.size());
|
||||
for (size_t i = 0; i < m_cluster_colors_from_algo.size(); i++) {
|
||||
m_cluster_colours.emplace_back(convert_to_wxColour(m_cluster_colors_from_algo[i]));
|
||||
}
|
||||
if (m_cluster_colours.size() == 0) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ",m_cluster_colours.size() = 0\n";
|
||||
return;
|
||||
}
|
||||
m_cluster_map_filaments.resize(m_cluster_colors_from_algo.size());
|
||||
m_color_cluster_num_by_algo = m_cluster_colors_from_algo.size();
|
||||
if (cluster_number == -1) {
|
||||
m_color_num_recommend = m_color_cluster_num_by_algo;
|
||||
}
|
||||
//redraw ui
|
||||
if (redraw_ui) {
|
||||
redraw_part_table();
|
||||
deal_default_strategy();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjColorPanel::deal_default_strategy()
|
||||
{
|
||||
deal_add_btn();
|
||||
deal_approximate_match_btn();
|
||||
m_warning_text->SetLabelText(_L("Note:The color has been selected, you can choose OK \n to continue or manually adjust it."));
|
||||
}
|
||||
|
||||
void ObjColorPanel::deal_add_btn()
|
||||
{
|
||||
if (m_colours.size() > g_max_color) { return; }
|
||||
deal_reset_btn();
|
||||
std::vector<wxBitmap *> new_icons;
|
||||
auto new_color_size = m_cluster_colors_from_algo.size();
|
||||
new_icons.reserve(new_color_size);
|
||||
m_new_add_colors.clear();
|
||||
m_new_add_colors.reserve(new_color_size);
|
||||
int new_index = m_colours.size() + 1;
|
||||
bool is_exceed = false;
|
||||
for (size_t i = 0; i < new_color_size; i++) {
|
||||
if (m_colours.size() + new_icons.size() >= g_max_color) {
|
||||
is_exceed = true;
|
||||
break;
|
||||
}
|
||||
wxColour cur_color = convert_to_wxColour(m_cluster_colors_from_algo[i]);
|
||||
m_new_add_colors.emplace_back(cur_color);
|
||||
new_icons.emplace_back(get_extruder_color_icon(cur_color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(),
|
||||
std::to_string(new_index), m_combox_icon_width, m_combox_icon_height));
|
||||
new_index++;
|
||||
}
|
||||
new_index = m_colours.size() + 1;
|
||||
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++) {
|
||||
item->bitmap_combox->Append(wxString::Format("%d", item->bitmap_combox->GetCount()), *new_icons[k]);
|
||||
item->bitmap_combox->SetItemTooltip(item->bitmap_combox->GetCount() -1,m_new_add_colors[k].GetAsString(wxC2S_HTML_SYNTAX));
|
||||
}
|
||||
item->bitmap_combox->SetSelection(new_index);
|
||||
m_cluster_map_filaments[i] = new_index;
|
||||
new_index++;
|
||||
}
|
||||
if (is_exceed) {
|
||||
deal_approximate_match_btn();
|
||||
m_warning_text->SetLabelText(_L("Waring:The count of newly added and \n current extruders exceeds 16."));
|
||||
}
|
||||
m_is_add_filament = true;
|
||||
}
|
||||
|
||||
void ObjColorPanel::deal_reset_btn()
|
||||
{
|
||||
for (auto item : m_result_icon_list) {
|
||||
// delete redundant bitmap
|
||||
while (item->bitmap_combox->GetCount() > m_colours.size()+ 1) {
|
||||
item->bitmap_combox->DeleteOneItem(item->bitmap_combox->GetCount() - 1);
|
||||
}
|
||||
item->bitmap_combox->SetSelection(0);
|
||||
}
|
||||
m_is_add_filament = false;
|
||||
m_new_add_colors.clear();
|
||||
m_warning_text->SetLabelText("");
|
||||
}
|
||||
|
||||
void ObjColorPanel::create_result_button_sizer(wxWindow *parent, int id)
|
||||
{
|
||||
for (size_t i = m_result_icon_list.size(); i < id + 1; i++) {
|
||||
m_result_icon_list.emplace_back(new ButtonState());
|
||||
}
|
||||
m_result_icon_list[id]->bitmap_combox = CreateEditorCtrl(parent,id);
|
||||
}
|
||||
|
||||
wxBoxSizer *ObjColorPanel::create_color_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color)
|
||||
{
|
||||
auto icon_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
icon_sizer->AddSpacer(FromDIP(40));
|
||||
wxButton *icon = new wxButton(parent, wxID_ANY, {}, wxDefaultPosition, ICON_SIZE, wxBORDER_NONE | wxBU_AUTODRAW);
|
||||
icon->SetBitmap(*get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(id + 1), FromDIP(16), FromDIP(16)));
|
||||
icon->SetCanFocus(false);
|
||||
m_color_cluster_icon_list.emplace_back(icon);
|
||||
icon_sizer->Add(icon, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0); // wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM
|
||||
icon_sizer->AddSpacer(FromDIP(10));
|
||||
|
||||
std::string message = get_color_str(color);
|
||||
wxStaticText *rgba_title = new wxStaticText(parent, wxID_ANY, message.c_str());
|
||||
m_color_cluster_text_list.emplace_back(rgba_title);
|
||||
rgba_title->SetMinSize(wxSize(FromDIP(COLOR_LABEL_WIDTH), -1));
|
||||
rgba_title->SetMaxSize(wxSize(FromDIP(COLOR_LABEL_WIDTH), -1));
|
||||
//rgba_title->SetFont(Label::Head_12);
|
||||
icon_sizer->Add(rgba_title, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
|
||||
return icon_sizer;
|
||||
}
|
||||
|
||||
void ObjColorPanel::update_color_icon_and_rgba_sizer(int id, const wxColour &color)
|
||||
{
|
||||
if (id < m_color_cluster_text_list.size()) {
|
||||
auto icon = m_color_cluster_icon_list[id];
|
||||
icon->SetBitmap(*get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(id + 1), FromDIP(16), FromDIP(16)));
|
||||
std::string message = get_color_str(color);
|
||||
m_color_cluster_text_list[id]->SetLabelText(message.c_str());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef _OBJ_COLOR_DIALOG_H_
|
||||
#define _OBJ_COLOR_DIALOG_H_
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/msgdlg.h>
|
||||
class Button;
|
||||
class Label;
|
||||
class ComboBox;
|
||||
struct ColorDistValue
|
||||
{
|
||||
int id;
|
||||
float distance;
|
||||
};
|
||||
class ObjColorPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
// BBS
|
||||
ObjColorPanel(wxWindow * parent,
|
||||
std::vector<Slic3r::RGBA> & input_colors,bool is_single_color,
|
||||
const std::vector<std::string> & extruder_colours,
|
||||
std::vector<unsigned char> & filament_ids,
|
||||
unsigned char & first_extruder_id);
|
||||
void msw_rescale();
|
||||
bool is_ok();
|
||||
void update_filament_ids();
|
||||
struct ButtonState
|
||||
{
|
||||
ComboBox* bitmap_combox{nullptr};
|
||||
bool is_map{false};//int id{0};
|
||||
};
|
||||
private:
|
||||
wxBoxSizer *create_approximate_match_btn_sizer(wxWindow *parent);
|
||||
wxBoxSizer *create_add_btn_sizer(wxWindow *parent);
|
||||
wxBoxSizer *create_reset_btn_sizer(wxWindow *parent);
|
||||
wxBoxSizer *create_extruder_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color);
|
||||
std::string get_color_str(const wxColour &color);
|
||||
void create_result_button_sizer(wxWindow *parent, int id);
|
||||
wxBoxSizer *create_color_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color);
|
||||
void update_color_icon_and_rgba_sizer(int id, const wxColour &color);
|
||||
ComboBox* CreateEditorCtrl(wxWindow *parent,int id);
|
||||
void draw_table();
|
||||
void show_sizer(wxSizer *sizer, bool show);
|
||||
void redraw_part_table();
|
||||
void deal_approximate_match_btn();
|
||||
void deal_add_btn();
|
||||
void deal_reset_btn();
|
||||
void deal_algo(char cluster_number,bool redraw_ui =false);
|
||||
void deal_default_strategy();
|
||||
private:
|
||||
//view ui
|
||||
wxScrolledWindow * m_scrolledWindow = nullptr;
|
||||
wxPanel * m_page_simple = nullptr;
|
||||
wxBoxSizer * m_sizer = nullptr;
|
||||
wxBoxSizer * m_sizer_simple = nullptr;
|
||||
wxTextCtrl *m_color_cluster_num_by_user_ebox{nullptr};
|
||||
wxStaticText * m_warning_text{nullptr};
|
||||
Button * m_quick_approximate_match_btn{nullptr};
|
||||
Button * m_quick_add_btn{nullptr};
|
||||
Button * m_quick_reset_btn{nullptr};
|
||||
std::vector<wxButton*> m_extruder_icon_list;
|
||||
std::vector<wxButton*> m_color_cluster_icon_list;//need modeify
|
||||
std::vector<wxStaticText*> m_color_cluster_text_list;//need modeify
|
||||
std::vector<wxGridSizer*> m_row_sizer_list; // control show or not
|
||||
std::vector<ButtonState*> m_result_icon_list;
|
||||
int m_last_cluster_num{-1};
|
||||
const int m_combox_width{50};
|
||||
int m_combox_icon_width;
|
||||
int m_combox_icon_height;
|
||||
wxGridSizer* m_gridsizer = nullptr;
|
||||
wxStaticText * m_test = nullptr;
|
||||
//data
|
||||
char m_last_cluster_number{-2};
|
||||
std::vector<Slic3r::RGBA>& m_input_colors;
|
||||
int m_color_num_recommend{0};
|
||||
int m_color_cluster_num_by_algo{0};
|
||||
int m_input_colors_size{0};
|
||||
std::vector<wxColour> m_colours;//from project and show right
|
||||
std::vector<int> m_cluster_map_filaments;//show middle
|
||||
std::vector<wxColour> m_cluster_colours;//from_algo and show left
|
||||
bool m_can_add_filament{true};
|
||||
std::vector<wxColour> m_new_add_colors;
|
||||
//algo result
|
||||
std::vector<Slic3r::RGBA> m_cluster_colors_from_algo;
|
||||
std::vector<int> m_cluster_labels_from_algo;
|
||||
//result
|
||||
bool m_is_add_filament{false};
|
||||
unsigned char& m_first_extruder_id;
|
||||
std::vector<unsigned char> &m_filament_ids;
|
||||
};
|
||||
|
||||
class ObjColorDialog : public Slic3r::GUI::DPIDialog
|
||||
{
|
||||
public:
|
||||
ObjColorDialog(wxWindow * parent,
|
||||
std::vector<Slic3r::RGBA>& input_colors, bool is_single_color,
|
||||
const std::vector<std::string> & extruder_colours,
|
||||
std::vector<unsigned char>& filament_ids,
|
||||
unsigned char & first_extruder_id);
|
||||
wxBoxSizer* create_btn_sizer(long flags);
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
private:
|
||||
ObjColorPanel* m_panel_ObjColor = nullptr;
|
||||
std::unordered_map<int, Button *> m_button_list;
|
||||
std::vector<unsigned char>& m_filament_ids;
|
||||
unsigned char & m_first_extruder_id;
|
||||
};
|
||||
|
||||
#endif // _WIPE_TOWER_DIALOG_H_
|
||||
@@ -1580,14 +1580,7 @@ std::vector<int> PartPlate::get_used_extruders()
|
||||
|
||||
std::set<int> used_extruders_set;
|
||||
PrintEstimatedStatistics& ps = result->print_statistics;
|
||||
// model usage
|
||||
for (const auto&item:ps.volumes_per_extruder)
|
||||
used_extruders_set.emplace(item.first + 1);
|
||||
// support usage
|
||||
for (const auto&item:ps.support_volumes_per_extruder)
|
||||
used_extruders_set.emplace(item.first + 1);
|
||||
// wipe tower usage
|
||||
for (const auto&item:ps.wipe_tower_volumes_per_extruder)
|
||||
for (const auto& item : ps.total_volumes_per_extruder)
|
||||
used_extruders_set.emplace(item.first + 1);
|
||||
|
||||
return std::vector(used_extruders_set.begin(), used_extruders_set.end());
|
||||
|
||||
+174
-43
@@ -116,6 +116,7 @@
|
||||
#include "Jobs/BoostThreadWorker.hpp"
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "SelectMachine.hpp"
|
||||
#include "SendMultiMachinePage.hpp"
|
||||
#include "SendToPrinter.hpp"
|
||||
#include "PublishDialog.hpp"
|
||||
#include "ModelMall.hpp"
|
||||
@@ -156,6 +157,7 @@
|
||||
#include <libslic3r/CutUtils.hpp>
|
||||
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
||||
#include "WipeTowerDialog.hpp"
|
||||
#include "ObjColorDialog.hpp"
|
||||
|
||||
#include "libslic3r/CustomGCode.hpp"
|
||||
#include "libslic3r/Platform.hpp"
|
||||
@@ -209,7 +211,9 @@ wxDEFINE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent);
|
||||
|
||||
wxDEFINE_EVENT(EVT_CREATE_FILAMENT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_MODIFY_FILAMENT, SimpleEvent);
|
||||
|
||||
wxDEFINE_EVENT(EVT_ADD_FILAMENT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_DEL_FILAMENT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
||||
bool Plater::has_illegal_filename_characters(const wxString& wxs_name)
|
||||
{
|
||||
std::string name = into_u8(wxs_name);
|
||||
@@ -431,7 +435,7 @@ void Sidebar::priv::show_preset_comboboxes()
|
||||
void Sidebar::priv::on_search_update()
|
||||
{
|
||||
m_object_list->assembly_plate_object_name();
|
||||
|
||||
|
||||
wxString search_text = m_search_bar->GetValue();
|
||||
m_object_list->GetModel()->search_object(search_text);
|
||||
dia->update_list();
|
||||
@@ -491,37 +495,63 @@ void Sidebar::priv::hide_rich_tip(wxButton* btn)
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<int> get_min_flush_volumes()
|
||||
std::vector<int> get_min_flush_volumes(const DynamicPrintConfig& full_config)
|
||||
{
|
||||
std::vector<int>extra_flush_volumes;
|
||||
const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
auto& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
//const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
//auto& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
|
||||
ConfigOption* nozzle_volume_opt = printer_config.option("nozzle_volume");
|
||||
const ConfigOption* nozzle_volume_opt = full_config.option("nozzle_volume");
|
||||
int nozzle_volume_val = nozzle_volume_opt ? (int)nozzle_volume_opt->getFloat() : 0;
|
||||
|
||||
int machine_enabled_level = printer_config.option<ConfigOptionInt>("enable_long_retraction_when_cut")->value;
|
||||
bool machine_activated = printer_config.option<ConfigOptionBools>("long_retractions_when_cut")->values[0] == 1;
|
||||
const ConfigOptionInt* enable_long_retraction_when_cut_opt = full_config.option<ConfigOptionInt>("enable_long_retraction_when_cut");
|
||||
int machine_enabled_level = 0;
|
||||
if (enable_long_retraction_when_cut_opt) {
|
||||
machine_enabled_level = enable_long_retraction_when_cut_opt->value;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": get enable_long_retraction_when_cut from config, value=%1%")%machine_enabled_level;
|
||||
}
|
||||
const ConfigOptionBools* long_retractions_when_cut_opt = full_config.option<ConfigOptionBools>("long_retractions_when_cut");
|
||||
bool machine_activated = false;
|
||||
if (long_retractions_when_cut_opt) {
|
||||
machine_activated = long_retractions_when_cut_opt->values[0] == 1;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": get long_retractions_when_cut from config, value=%1%, activated=%2%")%long_retractions_when_cut_opt->values[0] %machine_activated;
|
||||
}
|
||||
|
||||
auto filament_retraction_distance_when_cut = full_config.option<ConfigOptionFloats>("filament_retraction_distances_when_cut");
|
||||
auto printer_retraction_distance_when_cut = full_config.option<ConfigOptionFloats>("retraction_distances_when_cut");
|
||||
auto filament_long_retractions_when_cut = full_config.option<ConfigOptionBools>("filament_long_retractions_when_cut");
|
||||
size_t filament_size = full_config.option<ConfigOptionFloats>("filament_diameter")->values.size();
|
||||
std::vector<double> filament_retraction_distance_when_cut(filament_size, 18.0f), printer_retraction_distance_when_cut(filament_size, 18.0f);
|
||||
std::vector<unsigned char> filament_long_retractions_when_cut(filament_size, 0);
|
||||
const ConfigOptionFloats* filament_retraction_distances_when_cut_opt = full_config.option<ConfigOptionFloats>("filament_retraction_distances_when_cut");
|
||||
if (filament_retraction_distances_when_cut_opt) {
|
||||
filament_retraction_distance_when_cut = filament_retraction_distances_when_cut_opt->values;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": get filament_retraction_distance_when_cut from config, size=%1%, values=%2%")%filament_retraction_distance_when_cut.size() %filament_retraction_distances_when_cut_opt->serialize();
|
||||
}
|
||||
|
||||
const ConfigOptionFloats* printer_retraction_distance_when_cut_opt = full_config.option<ConfigOptionFloats>("retraction_distances_when_cut");
|
||||
if (printer_retraction_distance_when_cut_opt) {
|
||||
printer_retraction_distance_when_cut = printer_retraction_distance_when_cut_opt->values;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": get retraction_distances_when_cut from config, size=%1%, values=%2%")%printer_retraction_distance_when_cut.size() %printer_retraction_distance_when_cut_opt->serialize();
|
||||
}
|
||||
|
||||
const ConfigOptionBools* filament_long_retractions_when_cut_opt = full_config.option<ConfigOptionBools>("filament_long_retractions_when_cut");
|
||||
if (filament_long_retractions_when_cut_opt) {
|
||||
filament_long_retractions_when_cut = filament_long_retractions_when_cut_opt->values;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": get filament_long_retractions_when_cut from config, size=%1%, values=%2%")%filament_long_retractions_when_cut.size() %filament_long_retractions_when_cut_opt->serialize();
|
||||
}
|
||||
|
||||
size_t filament_size = filament_retraction_distance_when_cut->values.size();
|
||||
for (size_t idx = 0; idx < filament_size; ++idx) {
|
||||
int extra_flush_volume = nozzle_volume_val;
|
||||
int retract_length = machine_enabled_level && machine_activated ? printer_retraction_distance_when_cut->values[0] : 0;
|
||||
int retract_length = machine_enabled_level && machine_activated ? printer_retraction_distance_when_cut[0] : 0;
|
||||
|
||||
char filament_activated = filament_long_retractions_when_cut->values[idx];
|
||||
double filament_retract_length = filament_retraction_distance_when_cut->values[idx];
|
||||
unsigned char filament_activated = filament_long_retractions_when_cut[idx];
|
||||
double filament_retract_length = filament_retraction_distance_when_cut[idx];
|
||||
|
||||
if (filament_activated == 0)
|
||||
retract_length = 0;
|
||||
else if (filament_activated == 1 && machine_enabled_level == LongRectrationLevel::EnableFilament) {
|
||||
if (!std::isnan(filament_retract_length))
|
||||
retract_length = (int)filament_retraction_distance_when_cut->values[idx];
|
||||
retract_length = (int)filament_retraction_distance_when_cut[idx];
|
||||
else
|
||||
retract_length = printer_retraction_distance_when_cut->values[0];
|
||||
retract_length = printer_retraction_distance_when_cut[0];
|
||||
}
|
||||
|
||||
extra_flush_volume -= PI * 1.75 * 1.75 / 4 * retract_length;
|
||||
@@ -849,7 +879,8 @@ Sidebar::Sidebar(Plater *parent)
|
||||
float flush_multiplier = flush_multi_opt ? flush_multi_opt->getFloat() : 1.f;
|
||||
|
||||
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
const auto& extra_flush_volumes = get_min_flush_volumes();
|
||||
const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
const auto& extra_flush_volumes = get_min_flush_volumes(full_config);
|
||||
WipingDialog dlg(parent, cast<float>(init_matrix), cast<float>(init_extruders), extruder_colours, extra_flush_volumes, flush_multiplier);
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
std::vector<float> matrix = dlg.get_matrix();
|
||||
@@ -1266,7 +1297,7 @@ void Sidebar::update_presets(Preset::Type preset_type)
|
||||
if (preset) {
|
||||
if (preset->is_compatible) preset_bundle.set_filament_preset(0, name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < filament_cnt; i++)
|
||||
@@ -1559,6 +1590,43 @@ void Sidebar::on_filaments_change(size_t num_filaments)
|
||||
dynamic_filament_list.update();
|
||||
}
|
||||
|
||||
void Sidebar::add_filament() {
|
||||
// BBS: limit filament choices to 16
|
||||
if (p->combos_filament.size() >= 16) return;
|
||||
wxColour new_col = Plater::get_next_color_for_filament();
|
||||
add_custom_filament(new_col);
|
||||
}
|
||||
|
||||
void Sidebar::delete_filament() {
|
||||
if (p->combos_filament.size() <= 1) return;
|
||||
|
||||
size_t filament_count = p->combos_filament.size() - 1;
|
||||
if (wxGetApp().preset_bundle->is_the_only_edited_filament(filament_count) || (filament_count == 1)) {
|
||||
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0], false, "", true);
|
||||
}
|
||||
|
||||
if (p->editing_filament >= filament_count) {
|
||||
p->editing_filament = -1;
|
||||
}
|
||||
|
||||
wxGetApp().preset_bundle->set_num_filaments(filament_count);
|
||||
wxGetApp().plater()->on_filaments_change(filament_count);
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
}
|
||||
|
||||
void Sidebar::add_custom_filament(wxColour new_col) {
|
||||
if (p->combos_filament.size() >= 16) return;
|
||||
|
||||
int filament_count = p->combos_filament.size() + 1;
|
||||
std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
||||
wxGetApp().preset_bundle->set_num_filaments(filament_count, new_color);
|
||||
wxGetApp().plater()->on_filaments_change(filament_count);
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
|
||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
||||
auto_calc_flushing_volumes(filament_count - 1);
|
||||
}
|
||||
|
||||
void Sidebar::on_bed_type_change(BedType bed_type)
|
||||
{
|
||||
// btDefault option is not included in global bed type setting
|
||||
@@ -1894,13 +1962,14 @@ void Sidebar::auto_calc_flushing_volumes(const int modify_id)
|
||||
auto& preset_bundle = wxGetApp().preset_bundle;
|
||||
auto& project_config = preset_bundle->project_config;
|
||||
auto& printer_config = preset_bundle->printers.get_edited_preset().config;
|
||||
const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment;
|
||||
auto& ams_filament_list = preset_bundle->filament_ams_list;
|
||||
|
||||
const std::vector<double>& init_matrix = (project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values;
|
||||
const std::vector<double>& init_extruders = (project_config.option<ConfigOptionFloats>("flush_volumes_vector"))->values;
|
||||
|
||||
const std::vector<int>& min_flush_volumes= get_min_flush_volumes();
|
||||
const std::vector<int>& min_flush_volumes= get_min_flush_volumes(full_config);
|
||||
|
||||
ConfigOptionFloat* flush_multi_opt = project_config.option<ConfigOptionFloat>("flush_multiplier");
|
||||
float flush_multiplier = flush_multi_opt ? flush_multi_opt->getFloat() : 1.f;
|
||||
@@ -2077,6 +2146,7 @@ struct Plater::priv
|
||||
MenuFactory menus;
|
||||
|
||||
SelectMachineDialog* m_select_machine_dlg = nullptr;
|
||||
SendMultiMachinePage* m_send_multi_dlg = nullptr;
|
||||
SendToPrinterDialog* m_send_to_sdcard_dlg = nullptr;
|
||||
PublishDialog *m_publish_dlg = nullptr;
|
||||
|
||||
@@ -2424,6 +2494,9 @@ struct Plater::priv
|
||||
void on_action_layersediting(SimpleEvent&);
|
||||
void on_create_filament(SimpleEvent &);
|
||||
void on_modify_filament(SimpleEvent &);
|
||||
void on_add_filament(SimpleEvent &);
|
||||
void on_delete_filament(SimpleEvent &);
|
||||
void on_add_custom_filament(ColorEvent &);
|
||||
|
||||
void on_object_select(SimpleEvent&);
|
||||
void show_right_click_menu(Vec2d mouse_position, wxMenu *menu);
|
||||
@@ -2540,6 +2613,7 @@ struct Plater::priv
|
||||
//BBS: add popup object table logic
|
||||
bool PopupObjectTable(int object_id, int volume_id, const wxPoint& position);
|
||||
void on_action_send_to_printer(bool isall = false);
|
||||
void on_action_send_to_multi_machine(SimpleEvent&);
|
||||
int update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path);
|
||||
private:
|
||||
bool layers_height_allowed() const;
|
||||
@@ -2580,7 +2654,6 @@ private:
|
||||
|
||||
//record print preset
|
||||
void record_start_print_preset(std::string action);
|
||||
|
||||
};
|
||||
|
||||
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf)", std::regex::icase);
|
||||
@@ -2698,7 +2771,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
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);
|
||||
|
||||
this->q->Bind(EVT_ADD_CUSTOM_FILAMENT, &priv::on_add_custom_filament, this);
|
||||
main_frame->m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this);
|
||||
|
||||
auto* panel_3d = new wxPanel(q);
|
||||
@@ -2969,6 +3042,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
q->Bind(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, &priv::on_action_export_all_sliced_file, this);
|
||||
q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER, &priv::on_action_export_to_sdcard, this);
|
||||
q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, &priv::on_action_export_to_sdcard_all, this);
|
||||
q->Bind(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, &priv::on_action_send_to_multi_machine, this);
|
||||
q->Bind(EVT_GLCANVAS_PLATE_SELECT, &priv::on_plate_selected, this);
|
||||
q->Bind(EVT_DOWNLOAD_PROJECT, &priv::on_action_download_project, this);
|
||||
q->Bind(EVT_IMPORT_MODEL_ID, &priv::on_action_request_model_id, this);
|
||||
@@ -3941,7 +4015,17 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
std::vector<Preset *> project_presets;
|
||||
bool is_xxx;
|
||||
Semver file_version;
|
||||
|
||||
|
||||
//ObjImportColorFn obj_color_fun=nullptr;
|
||||
auto obj_color_fun = [this, &path](std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids,
|
||||
unsigned char &first_extruder_id) {
|
||||
if (!boost::iends_with(path.string(), ".obj")) { return; }
|
||||
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
ObjColorDialog color_dlg(nullptr, input_colors, is_single_color, extruder_colours, filament_ids, first_extruder_id);
|
||||
if (color_dlg.ShowModal() != wxID_OK) {
|
||||
filament_ids.clear();
|
||||
}
|
||||
};
|
||||
model = Slic3r::Model::read_from_file(
|
||||
path.string(), nullptr, nullptr, strategy, &plate_data, &project_presets, &is_xxx, &file_version, nullptr,
|
||||
[this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id, &designer_country_code](int current, int total, bool &cancel, std::string &mode_id, std::string &code)
|
||||
@@ -3971,7 +4055,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
if (!isUtf8StepFile)
|
||||
Slic3r::GUI::show_info(nullptr, _L("Name of components inside step file is not UTF8 format!") + "\n\n" + _L("The name may show garbage characters!"),
|
||||
_L("Attention!"));
|
||||
});
|
||||
},
|
||||
nullptr, 0, obj_color_fun);
|
||||
|
||||
|
||||
if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) {
|
||||
@@ -6959,6 +7044,14 @@ void Plater::priv::on_action_print_plate(SimpleEvent&)
|
||||
record_start_print_preset("print_plate");
|
||||
}
|
||||
|
||||
void Plater::priv::on_action_send_to_multi_machine(SimpleEvent&)
|
||||
{
|
||||
if (!m_send_multi_dlg)
|
||||
m_send_multi_dlg = new SendMultiMachinePage(q);
|
||||
m_send_multi_dlg->prepare(partplate_list.get_curr_plate_index());
|
||||
m_send_multi_dlg->ShowModal();
|
||||
}
|
||||
|
||||
void Plater::priv::on_action_print_plate_from_sdcard(SimpleEvent&)
|
||||
{
|
||||
if (q != nullptr) {
|
||||
@@ -7018,6 +7111,7 @@ void Plater::priv::on_action_send_to_printer(bool isall)
|
||||
m_send_to_sdcard_dlg->ShowModal();
|
||||
}
|
||||
|
||||
|
||||
void Plater::priv::on_action_select_sliced_plate(wxCommandEvent &evt)
|
||||
{
|
||||
if (q != nullptr) {
|
||||
@@ -7088,7 +7182,6 @@ void Plater::priv::on_action_export_to_sdcard_all(SimpleEvent&)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//BBS: add plate select logic
|
||||
void Plater::priv::on_plate_selected(SimpleEvent&)
|
||||
{
|
||||
@@ -8071,6 +8164,19 @@ void Plater::priv::on_modify_filament(SimpleEvent &evt)
|
||||
|
||||
}
|
||||
|
||||
void Plater::priv::on_add_filament(SimpleEvent &evt) {
|
||||
sidebar->add_filament();
|
||||
}
|
||||
|
||||
void Plater::priv::on_delete_filament(SimpleEvent &evt) {
|
||||
sidebar->delete_filament();
|
||||
}
|
||||
|
||||
void Plater::priv::on_add_custom_filament(ColorEvent &evt)
|
||||
{
|
||||
sidebar->add_custom_filament(evt.data);
|
||||
}
|
||||
|
||||
void Plater::priv::enter_gizmos_stack()
|
||||
{
|
||||
assert(m_undo_redo_stack_active == &m_undo_redo_stack_main);
|
||||
@@ -8628,7 +8734,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
|
||||
void Plater::load_project(wxString const& filename2,
|
||||
wxString const& originfile)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "filename is: " << filename2 << "and originfile is: " << originfile;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "filename is: " << filename2 << "and originfile is: " << originfile;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__;
|
||||
auto filename = filename2;
|
||||
auto check = [&filename, this] (bool yes_or_no) {
|
||||
@@ -8702,13 +8808,13 @@ void Plater::load_project(wxString const& filename2,
|
||||
if (load_restore && originfile.IsEmpty()) {
|
||||
p->set_project_name(_L("Untitled"));
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if (using_exported_file()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " using ecported set project filename: " << filename;
|
||||
p->set_project_filename(filename);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// BBS set default 3D view and direction after loading project
|
||||
@@ -8869,6 +8975,14 @@ void Plater::import_model_id(wxString download_info)
|
||||
{
|
||||
vecFiles.clear();
|
||||
wxString extension = fs::path(filename.wx_str()).extension().c_str();
|
||||
|
||||
|
||||
//check file suffix
|
||||
if (!extension.Contains(".3mf")) {
|
||||
msg = _L("Download failed, unknown file format.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto name = filename.substr(0, filename.length() - extension.length() - 1);
|
||||
|
||||
for (const auto& iter : boost::filesystem::directory_iterator(target_path))
|
||||
@@ -8916,17 +9030,35 @@ void Plater::import_model_id(wxString download_info)
|
||||
fs::path tmp_path = target_path;
|
||||
tmp_path += format(".%1%", ".download");
|
||||
|
||||
|
||||
auto filesize = 0;
|
||||
bool size_limit = false;
|
||||
auto http = Http::get(download_url.ToStdString());
|
||||
|
||||
while (cont && retry_count < max_retries) {
|
||||
retry_count++;
|
||||
http.on_progress([&percent, &cont, &msg](Http::Progress progress, bool& cancel) {
|
||||
http.on_progress([&percent, &cont, &msg, &filesize, &size_limit](Http::Progress progress, bool& cancel) {
|
||||
|
||||
if (!cont) cancel = true;
|
||||
if (progress.dltotal != 0) {
|
||||
|
||||
if (filesize == 0) {
|
||||
filesize = progress.dltotal;
|
||||
double megabytes = static_cast<double>(progress.dltotal) / (1024 * 1024);
|
||||
//The maximum size of a 3mf file is 500mb
|
||||
if (megabytes > 500) {
|
||||
cont = false;
|
||||
size_limit = true;
|
||||
}
|
||||
}
|
||||
percent = progress.dlnow * 100 / progress.dltotal;
|
||||
}
|
||||
msg = wxString::Format(_L("Project downloaded %d%%"), percent);
|
||||
|
||||
if (size_limit) {
|
||||
msg = _L("Download failed, File size exception.");
|
||||
}
|
||||
else {
|
||||
msg = wxString::Format(_L("Project downloaded %d%%"), percent);
|
||||
}
|
||||
})
|
||||
.on_error([&msg, &cont, &retry_count, max_retries](std::string body, std::string error, unsigned http_status) {
|
||||
(void)body;
|
||||
@@ -8936,7 +9068,7 @@ void Plater::import_model_id(wxString download_info)
|
||||
error);
|
||||
|
||||
if (retry_count == max_retries) {
|
||||
msg = _L("Importing to Orca Slicer failed. Please download the file and manually import it.");
|
||||
msg = _L("Importing to Bambu Studio failed. Please download the file and manually import it.");
|
||||
cont = false;
|
||||
}
|
||||
})
|
||||
@@ -8985,7 +9117,7 @@ void Plater::import_model_id(wxString download_info)
|
||||
}
|
||||
|
||||
// show save new project
|
||||
p->set_project_filename(filename);
|
||||
p->set_project_filename(target_path.wstring());
|
||||
p->notification_manager->push_import_finished_notification(target_path.string(), target_path.parent_path().string(), false);
|
||||
}
|
||||
else {
|
||||
@@ -8997,7 +9129,6 @@ void Plater::import_model_id(wxString download_info)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//BBS download project by project id
|
||||
void Plater::download_project(const wxString& project_id)
|
||||
{
|
||||
@@ -9731,14 +9862,12 @@ void Plater::load_gcode(const wxString& filename)
|
||||
//BBS: add cost info when drag in gcode
|
||||
auto& ps = current_result->print_statistics;
|
||||
double total_cost = 0.0;
|
||||
for (auto& volumes_map : { ps.volumes_per_extruder,ps.flush_per_filament ,ps.wipe_tower_volumes_per_extruder }) {
|
||||
for (auto volume : volumes_map) {
|
||||
size_t extruder_id = volume.first;
|
||||
double density = current_result->filament_densities.at(extruder_id);
|
||||
double cost = current_result->filament_costs.at(extruder_id);
|
||||
double weight = volume.second * density * 0.001;
|
||||
total_cost += weight * cost * 0.001;
|
||||
}
|
||||
for (auto volume : ps.total_volumes_per_extruder) {
|
||||
size_t extruder_id = volume.first;
|
||||
double density = current_result->filament_densities.at(extruder_id);
|
||||
double cost = current_result->filament_costs.at(extruder_id);
|
||||
double weight = volume.second * density * 0.001;
|
||||
total_cost += weight * cost * 0.001;
|
||||
}
|
||||
current_print.print_statistics().total_cost = total_cost;
|
||||
|
||||
@@ -9757,7 +9886,7 @@ void Plater::load_gcode(const wxString& filename)
|
||||
} else {
|
||||
set_project_filename(filename);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Plater::reload_gcode_from_disk()
|
||||
@@ -11519,6 +11648,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
// get type and color for platedata
|
||||
auto* filament_color = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_colour"));
|
||||
auto* nozzle_diameter_option = dynamic_cast<const ConfigOptionFloats*>(cfg.option("nozzle_diameter"));
|
||||
auto* filament_id_opt = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_ids"));
|
||||
std::string nozzle_diameter_str;
|
||||
if (nozzle_diameter_option)
|
||||
nozzle_diameter_str = nozzle_diameter_option->serialize();
|
||||
@@ -11532,6 +11662,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++) {
|
||||
std::string display_filament_type;
|
||||
it->type = cfg.get_filament_type(display_filament_type, it->id);
|
||||
it->filament_id = filament_id_opt ? filament_id_opt->get_at(it->id) : "";
|
||||
it->color = filament_color ? filament_color->get_at(it->id) : "#FFFFFF";
|
||||
// save filament info used in curr plate
|
||||
int index = p->partplate_list.get_curr_plate_index();
|
||||
|
||||
@@ -117,7 +117,10 @@ wxDECLARE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_CREATE_FILAMENT, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_MODIFY_FILAMENT, SimpleEvent);
|
||||
|
||||
wxDECLARE_EVENT(EVT_ADD_FILAMENT, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_DEL_FILAMENT, SimpleEvent);
|
||||
using ColorEvent = Event<wxColour>;
|
||||
wxDECLARE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
||||
const wxString DEFAULT_PROJECT_NAME = "Untitled";
|
||||
|
||||
class Sidebar : public wxPanel
|
||||
@@ -153,6 +156,9 @@ public:
|
||||
void jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category);
|
||||
// BBS. Add on_filaments_change() method.
|
||||
void on_filaments_change(size_t num_filaments);
|
||||
void add_filament();
|
||||
void delete_filament();
|
||||
void add_custom_filament(wxColour new_col);
|
||||
// BBS
|
||||
void on_bed_type_change(BedType bed_type);
|
||||
void load_ams_list(std::string const & device, MachineObject* obj);
|
||||
@@ -827,7 +833,7 @@ private:
|
||||
bool m_was_scheduled;
|
||||
};
|
||||
|
||||
std::vector<int> get_min_flush_volumes();
|
||||
std::vector<int> get_min_flush_volumes(const DynamicPrintConfig& full_config);
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
@@ -1046,6 +1046,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||
auto item_calc_mode = create_item_checkbox(_L("Flushing volumes: Auto-calculate everytime the color changed."), page, _L("If enabled, auto-calculate everytime the color changed."), 50, "auto_calculate");
|
||||
auto item_calc_in_long_retract = create_item_checkbox(_L("Flushing volumes: Auto-calculate every time when the filament is changed."), page, _L("If enabled, auto-calculate every time when filament is changed"), 50, "auto_calculate_when_filament_change");
|
||||
auto item_remember_printer_config = create_item_checkbox(_L("Remember printer configuration"), page, _L("If enabled, Orca will remember and switch filament/process configuration for each printer automatically."), 50, "remember_printer_config");
|
||||
auto item_multi_machine = create_item_checkbox(_L("Multi-device Management(Take effect after restarting Studio)."), page, _L("With this option enabled, you can send a task to multiple devices at the same time and manage multiple devices."), 50, "enable_multi_machine");
|
||||
auto title_presets = create_item_title(_L("Presets"), page, _L("Presets"));
|
||||
auto title_network = create_item_title(_L("Network"), page, _L("Network"));
|
||||
auto item_user_sync = create_item_checkbox(_L("Auto sync user presets(Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset");
|
||||
@@ -1111,6 +1112,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
||||
sizer_page->Add(item_show_splash_screen, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_calc_in_long_retract, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_multi_machine, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||
sizer_page->Add(item_calc_mode, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#include "../Utils/ASCIIFolding.hpp"
|
||||
#include "../Utils/FixModelByWin10.hpp"
|
||||
#include "../Utils/UndoRedo.hpp"
|
||||
#include "../Utils/ColorSpaceConvert.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "SavePresetDialog.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "ParamsDialog.hpp"
|
||||
|
||||
@@ -625,37 +627,6 @@ bool PresetComboBox::selection_is_changed_according_to_physical_printers()
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlaterPresetComboBox::save_custom_color_to_config(const std::vector<std::string>& colors)
|
||||
{
|
||||
auto set_colors = [](std::map<std::string, std::string> &data, const std::vector<std::string> &colors) {
|
||||
for (size_t i = 0; i < colors.size(); i++) {
|
||||
data[std::to_string(10 + i)] = colors[i]; //for map sort:10 begin
|
||||
}
|
||||
};
|
||||
if (colors.size() > 0) {
|
||||
if (!wxGetApp().app_config->has_section("custom_color_list")) {
|
||||
std::map<std::string, std::string> data;
|
||||
set_colors(data,colors);
|
||||
wxGetApp().app_config->set_section("custom_color_list", data);
|
||||
} else {
|
||||
auto data = wxGetApp().app_config->get_section("custom_color_list");
|
||||
auto data_modify = const_cast<std::map<std::string, std::string> *>(&data);
|
||||
set_colors(*data_modify, colors);
|
||||
wxGetApp().app_config->set_section("custom_color_list", *data_modify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> PlaterPresetComboBox::get_custom_color_from_config() {
|
||||
std::vector<std::string> colors;
|
||||
if (wxGetApp().app_config->has_section("custom_color_list")) {
|
||||
auto data = wxGetApp().app_config->get_section("custom_color_list");
|
||||
for (auto iter : data) {
|
||||
colors.push_back(iter.second);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
// ---------------------------------
|
||||
// *** PlaterPresetComboBox ***
|
||||
// ---------------------------------
|
||||
@@ -704,21 +675,9 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset
|
||||
m_clrData.SetColour(clr_picker->GetBackgroundColour());
|
||||
m_clrData.SetChooseFull(true);
|
||||
m_clrData.SetChooseAlpha(false);
|
||||
auto color_to_string = [](const wxColour& color) {
|
||||
std::string str = std::to_string(color.Red()) + "," + std::to_string(color.Green()) + "," + std::to_string(color.Blue()) + "," + std::to_string(color.Alpha());
|
||||
return str;
|
||||
};
|
||||
auto string_to_wxColor = [](const std::string& str) {
|
||||
wxColour color;
|
||||
std::vector<std::string> result;
|
||||
boost::split(result, str, boost::is_any_of(","));
|
||||
if (result.size() == 4) {
|
||||
color = wxColour(std::stoi(result[0]), std::stoi(result[1]), std::stoi(result[2]), std::stoi(result[3]));
|
||||
}
|
||||
return color;
|
||||
};
|
||||
std::vector<std::string> colors=get_custom_color_from_config();
|
||||
for (int i = 0; i < colors.size(); i++) {
|
||||
|
||||
std::vector<std::string> 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]));
|
||||
}
|
||||
wxColourDialog dialog(this, &m_clrData);
|
||||
@@ -726,13 +685,13 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset
|
||||
if ( dialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
m_clrData = dialog.GetColourData();
|
||||
const int custom_color_count = 15;
|
||||
if (colors.size() != custom_color_count) {
|
||||
colors.resize(custom_color_count); }
|
||||
for (int i = 0; i < custom_color_count; i++) {
|
||||
if (colors.size() != CUSTOM_COLOR_COUNT) {
|
||||
colors.resize(CUSTOM_COLOR_COUNT);
|
||||
}
|
||||
for (int i = 0; i < CUSTOM_COLOR_COUNT; i++) {
|
||||
colors[i] = color_to_string(m_clrData.GetCustomColour(i));
|
||||
}
|
||||
save_custom_color_to_config(colors);
|
||||
wxGetApp().app_config->save_custom_color_to_config(colors);
|
||||
// get current color
|
||||
DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config;
|
||||
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
|
||||
@@ -999,7 +958,8 @@ void PlaterPresetComboBox::update()
|
||||
std::map<wxString, wxBitmap*> nonsys_presets;
|
||||
//BBS: add project embedded presets logic
|
||||
std::map<wxString, wxBitmap*> project_embedded_presets;
|
||||
std::map<wxString, wxBitmap*> system_presets;
|
||||
std::map<wxString, wxBitmap *> system_presets;
|
||||
std::map<wxString, wxString> preset_descriptions;
|
||||
|
||||
//BBS: move system to the end
|
||||
wxString selected_system_preset;
|
||||
@@ -1040,13 +1000,15 @@ void PlaterPresetComboBox::update()
|
||||
wxBitmap* bmp = get_bmp(preset);
|
||||
assert(bmp);
|
||||
|
||||
const std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
||||
const wxString name = get_preset_name(preset);
|
||||
preset_descriptions.emplace(name, from_u8(preset.description));
|
||||
|
||||
if (preset.is_default || preset.is_system) {
|
||||
//BBS: move system to the end
|
||||
system_presets.emplace(get_preset_name(preset), bmp);
|
||||
system_presets.emplace(name, bmp);
|
||||
if (is_selected) {
|
||||
tooltip = get_tooltip(preset);
|
||||
selected_system_preset = get_preset_name(preset);
|
||||
selected_system_preset = name;
|
||||
}
|
||||
//Append(get_preset_name(preset), *bmp);
|
||||
//validate_selection(is_selected);
|
||||
@@ -1057,17 +1019,17 @@ void PlaterPresetComboBox::update()
|
||||
//BBS: add project embedded preset logic
|
||||
else if (preset.is_project_embedded)
|
||||
{
|
||||
project_embedded_presets.emplace(get_preset_name(preset), bmp);
|
||||
project_embedded_presets.emplace(name, bmp);
|
||||
if (is_selected) {
|
||||
selected_user_preset = get_preset_name(preset);
|
||||
selected_user_preset = name;
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nonsys_presets.emplace(get_preset_name(preset), bmp);
|
||||
nonsys_presets.emplace(name, bmp);
|
||||
if (is_selected) {
|
||||
selected_user_preset = get_preset_name(preset);
|
||||
selected_user_preset = name;
|
||||
//BBS set tooltip
|
||||
tooltip = get_tooltip(preset);
|
||||
}
|
||||
@@ -1084,7 +1046,7 @@ void PlaterPresetComboBox::update()
|
||||
{
|
||||
set_label_marker(Append(separator(L("Project-inside presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = project_embedded_presets.begin(); it != project_embedded_presets.end(); ++it) {
|
||||
Append(it->first, *it->second);
|
||||
SetItemTooltip(Append(it->first, *it->second), preset_descriptions[it->first]);
|
||||
validate_selection(it->first == selected_user_preset);
|
||||
}
|
||||
}
|
||||
@@ -1092,7 +1054,7 @@ void PlaterPresetComboBox::update()
|
||||
{
|
||||
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
Append(it->first, *it->second);
|
||||
SetItemTooltip(Append(it->first, *it->second), preset_descriptions[it->first]);
|
||||
validate_selection(it->first == selected_user_preset);
|
||||
}
|
||||
}
|
||||
@@ -1101,7 +1063,7 @@ void PlaterPresetComboBox::update()
|
||||
{
|
||||
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = system_presets.begin(); it != system_presets.end(); ++it) {
|
||||
Append(it->first, *it->second);
|
||||
SetItemTooltip(Append(it->first, *it->second), preset_descriptions[it->first]);
|
||||
validate_selection(it->first == selected_system_preset);
|
||||
}
|
||||
}
|
||||
@@ -1250,6 +1212,7 @@ void TabPresetComboBox::update()
|
||||
std::map<wxString, std::pair<wxBitmap*, bool>> project_embedded_presets;
|
||||
//BBS: move system to the end
|
||||
std::map<wxString, std::pair<wxBitmap*, bool>> system_presets;
|
||||
std::map<wxString, wxString> preset_descriptions;
|
||||
|
||||
wxString selected = "";
|
||||
//BBS: move system to the end
|
||||
@@ -1276,11 +1239,14 @@ void TabPresetComboBox::update()
|
||||
wxBitmap* bmp = get_bmp(preset);
|
||||
assert(bmp);
|
||||
|
||||
const wxString name = get_preset_name(preset);
|
||||
preset_descriptions.emplace(name, from_u8(preset.description));
|
||||
|
||||
if (preset.is_default || preset.is_system) {
|
||||
//BBS: move system to the end
|
||||
system_presets.emplace(get_preset_name(preset), std::pair<wxBitmap *, bool>(bmp, is_enabled));
|
||||
system_presets.emplace(name, std::pair<wxBitmap *, bool>(bmp, is_enabled));
|
||||
if (i == idx_selected)
|
||||
selected = get_preset_name(preset);
|
||||
selected = name;
|
||||
//int item_id = Append(get_preset_name(preset), *bmp);
|
||||
//if (!is_enabled)
|
||||
// set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
||||
@@ -1290,16 +1256,16 @@ void TabPresetComboBox::update()
|
||||
else if (preset.is_project_embedded)
|
||||
{
|
||||
//std::pair<wxBitmap*, bool> pair(bmp, is_enabled);
|
||||
project_embedded_presets.emplace(get_preset_name(preset), std::pair<wxBitmap *, bool>(bmp, is_enabled));
|
||||
project_embedded_presets.emplace(name, std::pair<wxBitmap *, bool>(bmp, is_enabled));
|
||||
if (i == idx_selected)
|
||||
selected = get_preset_name(preset);
|
||||
selected = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<wxBitmap*, bool> pair(bmp, is_enabled);
|
||||
nonsys_presets.emplace(get_preset_name(preset), std::pair<wxBitmap*, bool>(bmp, is_enabled));
|
||||
nonsys_presets.emplace(name, std::pair<wxBitmap *, bool>(bmp, is_enabled));
|
||||
if (i == idx_selected)
|
||||
selected = get_preset_name(preset);
|
||||
selected = name;
|
||||
}
|
||||
//BBS: move system to the end
|
||||
//if (i + 1 == m_collection->num_default_presets())
|
||||
@@ -1315,6 +1281,7 @@ void TabPresetComboBox::update()
|
||||
set_label_marker(Append(separator(L("Project-inside presets")), wxNullBitmap));
|
||||
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = project_embedded_presets.begin(); it != project_embedded_presets.end(); ++it) {
|
||||
int item_id = Append(it->first, *it->second.first);
|
||||
SetItemTooltip(item_id, preset_descriptions[it->first]);
|
||||
bool is_enabled = it->second.second;
|
||||
if (!is_enabled)
|
||||
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
||||
@@ -1326,6 +1293,7 @@ void TabPresetComboBox::update()
|
||||
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
||||
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
int item_id = Append(it->first, *it->second.first);
|
||||
SetItemTooltip(item_id, preset_descriptions[it->first]);
|
||||
bool is_enabled = it->second.second;
|
||||
if (!is_enabled)
|
||||
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
||||
@@ -1338,6 +1306,7 @@ void TabPresetComboBox::update()
|
||||
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
||||
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = system_presets.begin(); it != system_presets.end(); ++it) {
|
||||
int item_id = Append(it->first, *it->second.first);
|
||||
SetItemTooltip(item_id, preset_descriptions[it->first]);
|
||||
bool is_enabled = it->second.second;
|
||||
if (!is_enabled)
|
||||
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#define slic3r_PresetComboBoxes_hpp_
|
||||
|
||||
//#include <wx/bmpcbox.h>
|
||||
#include <wx/colourdata.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/clrpicker.h>
|
||||
#include <wx/colourdata.h>
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@@ -164,8 +164,6 @@ public:
|
||||
PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type);
|
||||
~PlaterPresetComboBox();
|
||||
|
||||
void save_custom_color_to_config(const std::vector<std::string> &colors);
|
||||
std::vector<std::string> get_custom_color_from_config();
|
||||
ScalableButton* edit_btn { nullptr };
|
||||
|
||||
// BBS
|
||||
|
||||
@@ -67,6 +67,12 @@ PrintOptionsDialog::PrintOptionsDialog(wxWindow* parent)
|
||||
}
|
||||
evt.Skip();
|
||||
});
|
||||
m_cb_nozzle_blob->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& evt) {
|
||||
if (obj) {
|
||||
obj->command_nozzle_blob_detect(m_cb_nozzle_blob->GetValue());
|
||||
}
|
||||
evt.Skip();
|
||||
});
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
@@ -163,6 +169,18 @@ void PrintOptionsDialog::update_options(MachineObject* obj_)
|
||||
m_cb_filament_tangle->Hide();
|
||||
line6->Hide();
|
||||
}
|
||||
if (false/*obj_->is_support_nozzle_blob_detection*/) {
|
||||
text_nozzle_blob->Show();
|
||||
m_cb_nozzle_blob->Show();
|
||||
text_nozzle_blob_caption->Show();
|
||||
line7->Show();
|
||||
}
|
||||
else {
|
||||
text_nozzle_blob->Hide();
|
||||
m_cb_nozzle_blob->Hide();
|
||||
text_nozzle_blob_caption->Hide();
|
||||
line7->Hide();
|
||||
}
|
||||
|
||||
this->Freeze();
|
||||
|
||||
@@ -171,6 +189,7 @@ void PrintOptionsDialog::update_options(MachineObject* obj_)
|
||||
m_cb_auto_recovery->SetValue(obj_->xcam_auto_recovery_step_loss);
|
||||
m_cb_sup_sound->SetValue(obj_->xcam_allow_prompt_sound);
|
||||
m_cb_filament_tangle->SetValue(obj_->xcam_filament_tangle_detect);
|
||||
m_cb_nozzle_blob->SetValue(obj_->nozzle_blob_detection_enabled);
|
||||
|
||||
m_cb_ai_monitoring->SetValue(obj_->xcam_ai_monitoring);
|
||||
for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) {
|
||||
@@ -325,6 +344,38 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent)
|
||||
line6 = new StaticLine(parent, false);
|
||||
line6->SetLineColour(STATIC_BOX_LINE_COL);
|
||||
sizer->Add(line6, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(20));
|
||||
|
||||
//nozzle blob detect
|
||||
line_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_cb_nozzle_blob = new CheckBox(parent);
|
||||
text_nozzle_blob = new wxStaticText(parent, wxID_ANY, _L("Nozzle Clumping Detection"));
|
||||
text_nozzle_blob->SetFont(Label::Body_14);
|
||||
line_sizer->Add(FromDIP(5), 0, 0, 0);
|
||||
line_sizer->Add(m_cb_nozzle_blob, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||
line_sizer->Add(text_nozzle_blob, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(15));
|
||||
sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18));
|
||||
line_sizer->Add(FromDIP(5), 0, 0, 0);
|
||||
|
||||
line_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxString nozzle_blob_caption_text = _L("Check if the nozzle is clumping by filament or other foreign objects.");
|
||||
text_nozzle_blob_caption = new Label(parent, nozzle_blob_caption_text);
|
||||
text_nozzle_blob_caption->SetFont(Label::Body_14);
|
||||
text_nozzle_blob_caption->Wrap(-1);
|
||||
text_nozzle_blob_caption->SetForegroundColour(STATIC_TEXT_CAPTION_COL);
|
||||
line_sizer->Add(FromDIP(30), 0, 0, 0);
|
||||
line_sizer->Add(text_nozzle_blob_caption, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));
|
||||
sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18));
|
||||
|
||||
line7 = new StaticLine(parent, false);
|
||||
line7->SetLineColour(STATIC_BOX_LINE_COL);
|
||||
sizer->Add(line7, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
|
||||
|
||||
text_nozzle_blob->Hide();
|
||||
m_cb_nozzle_blob->Hide();
|
||||
text_nozzle_blob_caption->Hide();
|
||||
line7->Hide();
|
||||
|
||||
ai_monitoring_level_list->Connect( wxEVT_COMBOBOX, wxCommandEventHandler(PrintOptionsDialog::set_ai_monitor_sensitivity), NULL, this );
|
||||
|
||||
@@ -487,6 +538,8 @@ void PrinterPartsDialog::set_nozzle_type(wxCommandEvent& evt)
|
||||
nozzle_diameter_checkbox->Append(wxString::Format(_L("%.1f"), diameter_list[i]));
|
||||
}
|
||||
nozzle_diameter_checkbox->SetSelection(0);
|
||||
|
||||
|
||||
last_nozzle_type = type;
|
||||
set_nozzle_diameter(evt);
|
||||
}
|
||||
@@ -526,7 +579,11 @@ bool PrinterPartsDialog::Show(bool show)
|
||||
CentreOnParent();
|
||||
|
||||
auto type = obj->nozzle_type;
|
||||
auto diameter = round(obj->nozzle_diameter * 10) / 10;
|
||||
auto diameter = 0.4f;
|
||||
|
||||
if (obj->nozzle_diameter > 0) {
|
||||
diameter = round(obj->nozzle_diameter * 10) / 10;
|
||||
}
|
||||
|
||||
nozzle_type_checkbox->Clear();
|
||||
nozzle_diameter_checkbox->Clear();
|
||||
|
||||
@@ -49,6 +49,7 @@ protected:
|
||||
CheckBox* m_cb_auto_recovery;
|
||||
CheckBox* m_cb_sup_sound;
|
||||
CheckBox* m_cb_filament_tangle;
|
||||
CheckBox* m_cb_nozzle_blob;
|
||||
wxStaticText* text_first_layer;
|
||||
wxStaticText* text_ai_monitoring;
|
||||
wxStaticText* text_ai_monitoring_caption;
|
||||
@@ -58,12 +59,15 @@ protected:
|
||||
wxStaticText* text_auto_recovery;
|
||||
wxStaticText* text_sup_sound;
|
||||
wxStaticText* text_filament_tangle;
|
||||
wxStaticText* text_nozzle_blob;
|
||||
wxStaticText* text_nozzle_blob_caption;
|
||||
StaticLine* line1;
|
||||
StaticLine* line2;
|
||||
StaticLine* line3;
|
||||
StaticLine* line4;
|
||||
StaticLine* line5;
|
||||
StaticLine* line6;
|
||||
StaticLine* line7;
|
||||
wxBoxSizer* create_settings_group(wxWindow* parent);
|
||||
|
||||
bool print_halt = false;
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#include "../../Utils/NetworkAgent.hpp"
|
||||
#include "../BitmapCache.hpp"
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/uuid/detail/md5.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
@@ -1139,8 +1139,7 @@ void PrinterFileSystem::RecvMessageThread()
|
||||
if (n == 0) {
|
||||
HandleResponse(l, sample);
|
||||
} else if (n == Bambu_stream_end) {
|
||||
if (m_status == ListSyncing)
|
||||
m_stopped = true;
|
||||
m_stopped = true;
|
||||
Reconnect(l, m_status == ListSyncing ? ERROR_RES_BUSY : ERROR_PIPE);
|
||||
} else if (n == Bambu_would_block) {
|
||||
m_cond.timed_wait(l, boost::posix_time::milliseconds(m_messages.empty() && m_callbacks.empty() ? 1000 : 20));
|
||||
@@ -1219,10 +1218,6 @@ void PrinterFileSystem::HandleResponse(boost::unique_lock<boost::mutex> &l, Bamb
|
||||
}
|
||||
}
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
extern wxString hide_passwd(wxString url, std::vector<wxString> const &passwords);
|
||||
}}
|
||||
|
||||
void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int result)
|
||||
{
|
||||
if (m_session.tunnel) {
|
||||
@@ -1266,7 +1261,7 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
|
||||
if (m_last_error == 0)
|
||||
m_stopped = true;
|
||||
} else {
|
||||
wxLogMessage("PrinterFileSystem::Reconnect Initialized: %s", Slic3r::GUI::hide_passwd(wxString::FromUTF8(url), {"authkey=", "passwd="}));
|
||||
wxLogInfo("PrinterFileSystem::Reconnect Initialized: %s", wxString::FromUTF8(url));
|
||||
l.unlock();
|
||||
m_status = Status::Connecting;
|
||||
wxLogMessage("PrinterFileSystem::Reconnect Connecting");
|
||||
@@ -1288,6 +1283,9 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
|
||||
m_session.tunnel = tunnel;
|
||||
wxLogMessage("PrinterFileSystem::Reconnect Connected");
|
||||
break;
|
||||
} else if (ret == 1) {
|
||||
m_stopped = true;
|
||||
ret = ERROR_RES_BUSY;
|
||||
}
|
||||
if (tunnel) {
|
||||
Bambu_Close(tunnel);
|
||||
|
||||
@@ -31,12 +31,16 @@ wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CONFIRM, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SECONDARY_CHECK_CANCEL, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SECONDARY_CHECK_DONE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SECONDARY_CHECK_RESUME, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_LOAD_VAMS_TRAY, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_CHECKBOX_CHANGE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_ENTER_IP_ADDRESS, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_CLOSE_IPADDRESS_DLG, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_CHECK_IP_ADDRESS_FAILED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_SECONDARY_CHECK_RETRY, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_PRINT_ERROR_STOP, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPDATE_NOZZLE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_JUMP_TO_HMS, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_JUMP_TO_LIVEVIEW, wxCommandEvent);
|
||||
|
||||
ReleaseNoteDialog::ReleaseNoteDialog(Plater *plater /*= nullptr*/)
|
||||
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Release Note"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
@@ -860,6 +864,306 @@ void SecondaryCheckDialog::rescale()
|
||||
m_button_cancel->Rescale();
|
||||
}
|
||||
|
||||
PrintErrorDialog::PrintErrorDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
|
||||
:DPIFrame(parent, id, title, pos, size, style)
|
||||
{
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
btn_bg_white = StateColor(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
|
||||
m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(350), 1));
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0);
|
||||
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5));
|
||||
|
||||
wxBoxSizer* m_sizer_right = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_sizer_right->Add(0, 0, 1, wxTOP, FromDIP(5));
|
||||
|
||||
m_vebview_release_note = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
|
||||
m_vebview_release_note->SetScrollRate(0, 5);
|
||||
m_vebview_release_note->SetBackgroundColour(*wxWHITE);
|
||||
m_vebview_release_note->SetMinSize(wxSize(FromDIP(320), FromDIP(250)));
|
||||
m_sizer_right->Add(m_vebview_release_note, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15));
|
||||
|
||||
m_error_prompt_pic_static = new wxStaticBitmap(m_vebview_release_note, wxID_ANY, wxBitmap(), wxDefaultPosition, wxSize(FromDIP(300), FromDIP(180)));
|
||||
|
||||
auto bottom_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_sizer_button = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
bottom_sizer->Add(m_sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, 0);
|
||||
|
||||
m_sizer_right->Add(bottom_sizer, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15));
|
||||
m_sizer_right->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
|
||||
m_sizer_main->Add(m_sizer_right, 0, wxBOTTOM | wxEXPAND, FromDIP(5));
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, [this](auto& e) {this->on_hide(); });
|
||||
Bind(wxEVT_ACTIVATE, [this](auto& e) { if (!e.GetActive()) this->RequestUserAttention(wxUSER_ATTENTION_ERROR); });
|
||||
Bind(wxEVT_WEBREQUEST_STATE, &PrintErrorDialog::on_webrequest_state, this);
|
||||
|
||||
|
||||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
m_sizer_main->Fit(this);
|
||||
|
||||
init_button_list();
|
||||
|
||||
CenterOnParent();
|
||||
wxGetApp().UpdateFrameDarkUI(this);
|
||||
}
|
||||
|
||||
void PrintErrorDialog::post_event(wxCommandEvent&& event)
|
||||
{
|
||||
if (event_parent) {
|
||||
event.SetString("");
|
||||
event.SetEventObject(event_parent);
|
||||
wxPostEvent(event_parent, event);
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
void PrintErrorDialog::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_prompt_pic_static->SetBitmap(error_prompt_pic);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
break;
|
||||
}
|
||||
case wxWebRequest::State_Failed:
|
||||
case wxWebRequest::State_Cancelled:
|
||||
case wxWebRequest::State_Unauthorized: {
|
||||
m_error_prompt_pic_static->SetBitmap(wxBitmap());
|
||||
break;
|
||||
}
|
||||
case wxWebRequest::State_Active:
|
||||
case wxWebRequest::State_Idle: break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintErrorDialog::update_text_image(wxString text, wxString image_url)
|
||||
{
|
||||
//if (!m_sizer_text_release_note) {
|
||||
// m_sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
|
||||
//}
|
||||
wxBoxSizer* sizer_text_release_note = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
||||
if (!m_staticText_release_note) {
|
||||
m_staticText_release_note = new Label(m_vebview_release_note, text, LB_AUTO_WRAP);
|
||||
sizer_text_release_note->Add(m_error_prompt_pic_static, 0, wxALIGN_CENTER, FromDIP(5));
|
||||
sizer_text_release_note->Add(m_staticText_release_note, 0, wxALIGN_CENTER , FromDIP(5));
|
||||
m_vebview_release_note->SetSizer(sizer_text_release_note);
|
||||
}
|
||||
if (!image_url.empty()) {
|
||||
web_request = wxWebSession::GetDefault().CreateRequest(this, image_url);
|
||||
BOOST_LOG_TRIVIAL(trace) << "monitor: create new webrequest, state = " << web_request.GetState() << ", url = " << image_url;
|
||||
if (web_request.GetState() == wxWebRequest::State_Idle)
|
||||
web_request.Start();
|
||||
BOOST_LOG_TRIVIAL(trace) << "monitor: start new webrequest, state = " << web_request.GetState() << ", url = " << image_url;
|
||||
m_error_prompt_pic_static->Show();
|
||||
|
||||
}
|
||||
else {
|
||||
m_error_prompt_pic_static->Hide();
|
||||
}
|
||||
sizer_text_release_note->Layout();
|
||||
m_staticText_release_note->SetMaxSize(wxSize(FromDIP(300), -1));
|
||||
m_staticText_release_note->SetMinSize(wxSize(FromDIP(300), -1));
|
||||
m_staticText_release_note->SetLabelText(text);
|
||||
m_vebview_release_note->Layout();
|
||||
|
||||
auto text_size = m_staticText_release_note->GetBestSize();
|
||||
if (text_size.y < FromDIP(360))
|
||||
if (!image_url.empty()) {
|
||||
m_vebview_release_note->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(220)));
|
||||
}
|
||||
else {
|
||||
m_vebview_release_note->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(25)));
|
||||
}
|
||||
else {
|
||||
m_vebview_release_note->SetMinSize(wxSize(FromDIP(320), FromDIP(340)));
|
||||
}
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void PrintErrorDialog::on_show()
|
||||
{
|
||||
wxGetApp().UpdateFrameDarkUI(this);
|
||||
|
||||
this->Show();
|
||||
this->Raise();
|
||||
}
|
||||
|
||||
void PrintErrorDialog::on_hide()
|
||||
{
|
||||
//m_sizer_button->Clear();
|
||||
//m_sizer_button->Layout();
|
||||
//m_used_button.clear();
|
||||
this->Hide();
|
||||
if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active) {
|
||||
BOOST_LOG_TRIVIAL(info) << "web_request: cancelled";
|
||||
web_request.Cancel();
|
||||
}
|
||||
m_error_prompt_pic_static->SetBitmap(wxBitmap());
|
||||
|
||||
if (wxGetApp().mainframe != nullptr) {
|
||||
wxGetApp().mainframe->Show();
|
||||
wxGetApp().mainframe->Raise();
|
||||
}
|
||||
}
|
||||
|
||||
void PrintErrorDialog::update_title_style(wxString title, std::vector<int> button_style, wxWindow* parent)
|
||||
{
|
||||
SetTitle(title);
|
||||
event_parent = parent;
|
||||
for (int used_button_id : m_used_button) {
|
||||
if (m_button_list.find(used_button_id) != m_button_list.end()) {
|
||||
m_button_list[used_button_id]->Hide();
|
||||
}
|
||||
}
|
||||
m_sizer_button->Clear();
|
||||
m_used_button = button_style;
|
||||
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();
|
||||
}
|
||||
}
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
}
|
||||
|
||||
void PrintErrorDialog::init_button(PrintErrorButton style,wxString buton_text) {
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
void PrintErrorDialog::init_button_list() {
|
||||
|
||||
init_button(RESUME_PRINTING, _L("Resume Printing"));
|
||||
m_button_list[RESUME_PRINTING]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_RESUME));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(RESUME_PRINTING_DEFECTS, _L("Resume Printing(defects acceptable)"));
|
||||
m_button_list[RESUME_PRINTING_DEFECTS]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_RESUME));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
|
||||
init_button(RESUME_PRINTING_PROBELM_SOLVED, _L("Resume Printing(problem solved)"));
|
||||
m_button_list[RESUME_PRINTING_PROBELM_SOLVED]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_RESUME));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(STOP_PRINTING, _L("Stop Printing"));
|
||||
m_button_list[STOP_PRINTING]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_PRINT_ERROR_STOP));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(CHECK_ASSISTANT, _L("Check Assistant"));
|
||||
m_button_list[CHECK_ASSISTANT]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_JUMP_TO_HMS));
|
||||
this->on_hide();
|
||||
});
|
||||
|
||||
init_button(FILAMENT_EXTRUDED, _L("Filament Extruded, Continue"));
|
||||
m_button_list[FILAMENT_EXTRUDED]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_DONE));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(RETRY_FILAMENT_EXTRUDED, _L("Not Extruded Yet, Retry"));
|
||||
m_button_list[RETRY_FILAMENT_EXTRUDED]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
wxCommandEvent evt(EVT_SECONDARY_CHECK_RETRY, GetId());
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(evt);
|
||||
this->on_hide();
|
||||
});
|
||||
|
||||
init_button(CONTINUE, _L("Finished, Continue"));
|
||||
m_button_list[CONTINUE]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_DONE));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(LOAD_VIRTUAL_TRAY, _L("Load Filament"));
|
||||
m_button_list[LOAD_VIRTUAL_TRAY]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_LOAD_VAMS_TRAY));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(OK_BUTTON, _L("OK"));
|
||||
m_button_list[OK_BUTTON]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
wxCommandEvent evt(EVT_SECONDARY_CHECK_CONFIRM, GetId());
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(evt);
|
||||
this->on_hide();
|
||||
});
|
||||
|
||||
init_button(FILAMENT_LOAD_RESUME, _L("Filament Loaded, Resume"));
|
||||
m_button_list[FILAMENT_LOAD_RESUME]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_SECONDARY_CHECK_RESUME));
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
init_button(JUMP_TO_LIVEVIEW, _L("View Liveview"));
|
||||
m_button_list[JUMP_TO_LIVEVIEW]->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
post_event(wxCommandEvent(EVT_JUMP_TO_LIVEVIEW));
|
||||
e.Skip();
|
||||
});
|
||||
}
|
||||
|
||||
PrintErrorDialog::~PrintErrorDialog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PrintErrorDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
rescale();
|
||||
}
|
||||
|
||||
void PrintErrorDialog::msw_rescale() {
|
||||
wxGetApp().UpdateFrameDarkUI(this);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void PrintErrorDialog::rescale()
|
||||
{
|
||||
for(auto used_button:m_used_button)
|
||||
m_button_list[used_button]->Rescale();
|
||||
}
|
||||
|
||||
ConfirmBeforeSendDialog::ConfirmBeforeSendDialog(wxWindow* parent, wxWindowID id, const wxString& title, enum ButtonStyle btn_style, const wxPoint& pos, const wxSize& size, long style, bool not_show_again_check)
|
||||
:DPIDialog(parent, id, title, pos, size, style)
|
||||
{
|
||||
@@ -1121,7 +1425,7 @@ void ConfirmBeforeSendDialog::disable_button_ok()
|
||||
void ConfirmBeforeSendDialog::enable_button_ok()
|
||||
{
|
||||
m_button_ok->Enable();
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
|
||||
m_button_ok->SetBackgroundColor(btn_bg_green);
|
||||
m_button_ok->SetBorderColor(btn_bg_green);
|
||||
|
||||
@@ -47,7 +47,11 @@ wxDECLARE_EVENT(EVT_SECONDARY_CHECK_CANCEL, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SECONDARY_CHECK_RETRY, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SECONDARY_CHECK_DONE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_SECONDARY_CHECK_RESUME, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_PRINT_ERROR_STOP, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPDATE_NOZZLE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_LOAD_VAMS_TRAY, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_JUMP_TO_HMS, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_JUMP_TO_LIVEVIEW, wxCommandEvent);
|
||||
|
||||
class ReleaseNoteDialog : public DPIDialog
|
||||
{
|
||||
@@ -159,6 +163,57 @@ public:
|
||||
std::string show_again_config_text = "";
|
||||
};
|
||||
|
||||
class PrintErrorDialog : public DPIFrame
|
||||
{
|
||||
private:
|
||||
wxWindow* event_parent{ nullptr };
|
||||
public:
|
||||
enum PrintErrorButton {
|
||||
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,
|
||||
JUMP_TO_LIVEVIEW,
|
||||
ERROR_BUTTON_COUNT
|
||||
};
|
||||
PrintErrorDialog(
|
||||
wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxString& title = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxCLOSE_BOX | wxCAPTION
|
||||
);
|
||||
void update_text_image(wxString text, wxString image_url);
|
||||
void on_show();
|
||||
void on_hide();
|
||||
void update_title_style(wxString title, std::vector<int> style, wxWindow* parent = nullptr);
|
||||
void post_event(wxCommandEvent&& event);
|
||||
void rescale();
|
||||
~PrintErrorDialog();
|
||||
void on_dpi_changed(const wxRect& suggested_rect);
|
||||
void msw_rescale();
|
||||
void init_button(PrintErrorButton style, wxString buton_text);
|
||||
void init_button_list();
|
||||
void on_webrequest_state(wxWebRequestEvent& evt);
|
||||
|
||||
StateColor btn_bg_white;
|
||||
wxWebRequest web_request;
|
||||
wxStaticBitmap* m_error_prompt_pic_static;
|
||||
Label* m_staticText_release_note{ nullptr };
|
||||
wxBoxSizer* m_sizer_main;
|
||||
wxBoxSizer* m_sizer_button;
|
||||
wxScrolledWindow* m_vebview_release_note{ nullptr };
|
||||
std::map<int, Button*> m_button_list;
|
||||
std::vector<int> m_used_button;
|
||||
};
|
||||
|
||||
struct ConfirmBeforeSendInfo
|
||||
{
|
||||
|
||||
@@ -398,12 +398,15 @@ SelectMachinePopup::SelectMachinePopup(wxWindow *parent)
|
||||
auto other_title = create_title_panel(_L("Other Device"));
|
||||
m_sizer_other_devices = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
||||
m_panel_ping_code = new PinCodePanel(m_scrolledWindow, wxID_ANY, wxDefaultPosition, SELECT_MACHINE_ITEM_SIZE);
|
||||
|
||||
m_sizxer_scrolledWindow->Add(own_title, 0, wxEXPAND | wxLEFT, FromDIP(15));
|
||||
m_sizxer_scrolledWindow->Add(m_sizer_my_devices, 0, wxEXPAND, 0);
|
||||
m_sizxer_scrolledWindow->Add(m_panel_ping_code, 0, wxEXPAND, 0);
|
||||
m_sizxer_scrolledWindow->Add(other_title, 0, wxEXPAND | wxLEFT, FromDIP(15));
|
||||
m_sizxer_scrolledWindow->Add(m_sizer_other_devices, 0, wxEXPAND, 0);
|
||||
|
||||
|
||||
m_sizer_main->Add(m_scrolledWindow, 0, wxALL | wxEXPAND, FromDIP(2));
|
||||
|
||||
SetSizer(m_sizer_main);
|
||||
@@ -872,6 +875,17 @@ void SelectMachinePopup::OnLeftUp(wxMouseEvent &event)
|
||||
}
|
||||
}
|
||||
|
||||
//pin code
|
||||
auto pc_rect = m_panel_ping_code->ClientToScreen(wxPoint(0, 0));
|
||||
if (mouse_pos.x > pc_rect.x && mouse_pos.y > pc_rect.y && mouse_pos.x < (pc_rect.x + m_panel_ping_code->GetSize().x) && mouse_pos.y < (pc_rect.y + m_panel_ping_code->GetSize().y)) {
|
||||
/*wxMouseEvent event(wxEVT_LEFT_UP);
|
||||
auto tag_pos = m_panel_ping_code->ScreenToClient(mouse_pos);
|
||||
event.SetPosition(tag_pos);
|
||||
event.SetEventObject(m_panel_ping_code);
|
||||
wxPostEvent(m_panel_ping_code, event);*/
|
||||
wxGetApp().popup_ping_bind_dialog();
|
||||
}
|
||||
|
||||
//hyper link
|
||||
auto h_rect = m_hyperlink->ClientToScreen(wxPoint(0, 0));
|
||||
if (mouse_pos.x > h_rect.x && mouse_pos.y > h_rect.y && mouse_pos.x < (h_rect.x + m_hyperlink->GetSize().x) && mouse_pos.y < (h_rect.y + m_hyperlink->GetSize().y)) {
|
||||
@@ -4581,4 +4595,80 @@ void EditDevNameDialog::on_edit_name(wxCommandEvent &e)
|
||||
|
||||
ThumbnailPanel::~ThumbnailPanel() {}
|
||||
|
||||
PinCodePanel::PinCodePanel(wxWindow* parent, wxWindowID winid /*= wxID_ANY*/, const wxPoint& pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/)
|
||||
{
|
||||
wxPanel::Create(parent, winid, pos, SELECT_MACHINE_ITEM_SIZE);
|
||||
Bind(wxEVT_PAINT, &PinCodePanel::OnPaint, this);
|
||||
SetSize(SELECT_MACHINE_ITEM_SIZE);
|
||||
SetMaxSize(SELECT_MACHINE_ITEM_SIZE);
|
||||
SetMinSize(SELECT_MACHINE_ITEM_SIZE);
|
||||
|
||||
m_bitmap = ScalableBitmap(this, "bind_device_ping_code",10);
|
||||
|
||||
this->Bind(wxEVT_ENTER_WINDOW, &PinCodePanel::on_mouse_enter, this);
|
||||
this->Bind(wxEVT_LEAVE_WINDOW, &PinCodePanel::on_mouse_leave, this);
|
||||
this->Bind(wxEVT_LEFT_UP, &PinCodePanel::on_mouse_left_up, this);
|
||||
}
|
||||
|
||||
void PinCodePanel::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void PinCodePanel::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PinCodePanel::doRender(wxDC& dc)
|
||||
{
|
||||
auto size = GetSize();
|
||||
dc.DrawBitmap(m_bitmap.bmp(), wxPoint(FromDIP(20), (size.y - m_bitmap.GetBmpSize().y) / 2));
|
||||
dc.SetFont(::Label::Head_13);
|
||||
dc.SetTextForeground(wxColour(38, 46, 48));
|
||||
wxString txt = _L("Bind with Pin Code");
|
||||
auto txt_size = dc.GetTextExtent(txt);
|
||||
dc.DrawText(txt, wxPoint(FromDIP(40), (size.y - txt_size.y) / 2));
|
||||
|
||||
if (m_hover) {
|
||||
dc.SetPen(SELECT_MACHINE_BRAND);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
void PinCodePanel::on_mouse_enter(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void PinCodePanel::on_mouse_leave(wxMouseEvent& evt)
|
||||
{
|
||||
m_hover = false;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void PinCodePanel::on_mouse_left_up(wxMouseEvent& evt)
|
||||
{
|
||||
wxGetApp().popup_ping_bind_dialog();
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -210,6 +210,27 @@ public:
|
||||
MachineObjectPanel *mPanel;
|
||||
};
|
||||
|
||||
class PinCodePanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
PinCodePanel(wxWindow* parent,
|
||||
wxWindowID winid = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize);
|
||||
~PinCodePanel() {};
|
||||
|
||||
ScalableBitmap m_bitmap;
|
||||
bool m_hover{false};
|
||||
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
|
||||
void on_mouse_enter(wxMouseEvent& evt);
|
||||
void on_mouse_leave(wxMouseEvent& evt);
|
||||
void on_mouse_left_up(wxMouseEvent& evt);
|
||||
};
|
||||
|
||||
|
||||
class ThumbnailPanel;
|
||||
|
||||
@@ -232,8 +253,11 @@ public:
|
||||
private:
|
||||
int m_my_devices_count{0};
|
||||
int m_other_devices_count{0};
|
||||
PinCodePanel* m_panel_ping_code{nullptr};
|
||||
wxWindow* m_placeholder_panel{nullptr};
|
||||
wxHyperlinkCtrl* m_hyperlink{nullptr};
|
||||
Label* m_ping_code_text{nullptr};
|
||||
wxStaticBitmap* m_img_ping_code{nullptr};
|
||||
wxBoxSizer * m_sizer_body{nullptr};
|
||||
wxBoxSizer * m_sizer_my_devices{nullptr};
|
||||
wxBoxSizer * m_sizer_other_devices{nullptr};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,210 @@
|
||||
#ifndef slic3r_SendMultiMachinePage_hpp_
|
||||
#define slic3r_SendMultiMachinePage_hpp_
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MultiMachine.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
#include "Widgets/ScrolledWindow.hpp"
|
||||
#include "Widgets/PopupWindow.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
#include "AmsMappingPopup.hpp"
|
||||
#include "SelectMachine.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
#define SEND_LEFT_PADDING_LEFT 15
|
||||
#define SEND_LEFT_PRINTABLE 40
|
||||
#define SEND_LEFT_DEV_NAME 250
|
||||
#define SEND_LEFT_DEV_STATUS 250
|
||||
#define SEND_LEFT_TAKS_STATUS 180
|
||||
|
||||
#define DESIGN_SELECTOR_NOMORE_COLOR wxColour(248, 248, 248)
|
||||
#define DESIGN_GRAY900_COLOR wxColour(38, 46, 48)
|
||||
#define DESIGN_GRAY800_COLOR wxColour(50, 58, 61)
|
||||
#define DESIGN_GRAY600_COLOR wxColour(144, 144, 144)
|
||||
#define DESIGN_GRAY400_COLOR wxColour(166, 169, 170)
|
||||
#define DESIGN_RESOUTION_PREFERENCES wxSize(FromDIP(540), -1)
|
||||
#define DESIGN_COMBOBOX_SIZE wxSize(FromDIP(140), -1)
|
||||
#define DESIGN_LARGE_COMBOBOX_SIZE wxSize(FromDIP(160), -1)
|
||||
#define DESIGN_INPUT_SIZE wxSize(FromDIP(50), -1)
|
||||
|
||||
#define MATERIAL_ITEM_SIZE wxSize(FromDIP(64), FromDIP(34))
|
||||
#define MATERIAL_ITEM_REAL_SIZE wxSize(FromDIP(62), FromDIP(32))
|
||||
#define MAPPING_ITEM_REAL_SIZE wxSize(FromDIP(48), FromDIP(45))
|
||||
|
||||
#define THUMBNAIL_SIZE FromDIP(128)
|
||||
|
||||
class RadioBox;
|
||||
class AmsRadioSelector
|
||||
{
|
||||
public:
|
||||
wxString m_param_name;
|
||||
int m_groupid;
|
||||
RadioBox* m_radiobox;
|
||||
bool m_selected = false;
|
||||
};
|
||||
|
||||
WX_DECLARE_LIST(AmsRadioSelector, AmsRadioSelectorList);
|
||||
|
||||
class SendDeviceItem : public DeviceItem
|
||||
{
|
||||
|
||||
public:
|
||||
SendDeviceItem(wxWindow* parent, MachineObject* obj);
|
||||
~SendDeviceItem() {};
|
||||
|
||||
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
|
||||
void OnEnterWindow(wxMouseEvent& evt);
|
||||
void OnLeaveWindow(wxMouseEvent& evt);
|
||||
void OnSelectedDevice(wxCommandEvent& evt);
|
||||
void OnLeftDown(wxMouseEvent& evt);
|
||||
void OnMove(wxMouseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void render(wxDC& dc);
|
||||
void doRender(wxDC& dc);
|
||||
void post_event(wxCommandEvent&& event);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
public:
|
||||
bool m_hover{false};
|
||||
ScalableBitmap m_bitmap_check_disable;
|
||||
ScalableBitmap m_bitmap_check_off;
|
||||
ScalableBitmap m_bitmap_check_on;
|
||||
};
|
||||
|
||||
class Plater;
|
||||
class SendMultiMachinePage : public DPIDialog
|
||||
{
|
||||
private:
|
||||
/* dev_id -> device_item */
|
||||
std::map<std::string, SendDeviceItem*> m_device_items;
|
||||
|
||||
wxTimer* m_refresh_timer = nullptr;
|
||||
|
||||
// sort
|
||||
SortItem m_sort;
|
||||
bool device_name_big{ true };
|
||||
bool device_printable_big{ true };
|
||||
bool device_en_ams_big{ true };
|
||||
|
||||
Button* m_button_send{ nullptr };
|
||||
wxScrolledWindow* scroll_macine_list{ nullptr };
|
||||
wxBoxSizer* sizer_machine_list{ nullptr };
|
||||
Plater* m_plater{ nullptr };
|
||||
|
||||
int m_print_plate_idx;
|
||||
bool m_is_canceled{ false };
|
||||
bool m_export_3mf_cancel{ false };
|
||||
AppConfig* app_config;
|
||||
|
||||
wxPanel* m_main_page{ nullptr };
|
||||
wxScrolledWindow* m_main_scroll{ nullptr };
|
||||
wxBoxSizer* m_sizer_body{ nullptr };
|
||||
wxGridSizer* m_ams_list_sizer{ nullptr };
|
||||
AmsMapingPopup* m_mapping_popup{ nullptr };
|
||||
|
||||
AmsRadioSelectorList m_radio_group;
|
||||
MaterialHash m_material_list;
|
||||
std::map<std::string, CheckBox*> m_checkbox_map;
|
||||
std::map<std::string, TextInput*> m_input_map;
|
||||
std::vector<FilamentInfo> m_filaments;
|
||||
std::vector<FilamentInfo> m_ams_mapping_result;
|
||||
int m_current_filament_id{ 0 };
|
||||
|
||||
StateColor btn_bg_enable;
|
||||
|
||||
// table head
|
||||
wxPanel* m_table_head_panel{ nullptr };
|
||||
wxBoxSizer* m_table_head_sizer{ nullptr };
|
||||
CheckBox* m_select_checkbox{ nullptr };
|
||||
Button* m_printer_name{ nullptr };
|
||||
Button* m_device_status{ nullptr };
|
||||
//Button* m_task_status{ nullptr };
|
||||
Button* m_ams{ nullptr };
|
||||
Button* m_refresh_button{ nullptr };
|
||||
|
||||
// rename
|
||||
wxSimplebook* m_rename_switch_panel{ nullptr };
|
||||
wxPanel* m_rename_normal_panel{ nullptr };
|
||||
wxPanel* m_rename_edit_panel{ nullptr };
|
||||
TextInput* m_rename_input{ nullptr };
|
||||
ScalableButton* m_rename_button{ nullptr };
|
||||
wxBoxSizer* rename_sizer_v{ nullptr };
|
||||
wxBoxSizer* rename_sizer_h{ nullptr };
|
||||
wxStaticText* m_task_name{ nullptr };
|
||||
wxString m_current_project_name;
|
||||
bool m_is_rename_mode{ false };
|
||||
|
||||
// title and thumbnail
|
||||
wxPanel* m_title_panel{ nullptr };
|
||||
wxBoxSizer* m_title_sizer{ nullptr };
|
||||
wxBoxSizer* m_text_sizer{ nullptr };
|
||||
ScalableBitmap* m_print_time{ nullptr };
|
||||
wxStaticBitmap* m_time_img{ nullptr };
|
||||
wxStaticText* m_stext_time{ nullptr };
|
||||
wxStaticText* m_stext_weight{ nullptr };
|
||||
wxStaticBitmap* timeimg{ nullptr };
|
||||
ScalableBitmap* print_time{ nullptr };
|
||||
wxStaticBitmap* weightimg{ nullptr };
|
||||
ScalableBitmap* print_weight{ nullptr };
|
||||
wxBoxSizer* m_thumbnail_sizer{ nullptr };
|
||||
ThumbnailPanel* m_thumbnail_panel{nullptr};
|
||||
wxPanel* m_panel_image{ nullptr };
|
||||
wxBoxSizer* m_image_sizer{ nullptr };
|
||||
|
||||
// tip when no device
|
||||
wxStaticText* m_tip_text{ nullptr };
|
||||
Button* m_button_add{ nullptr };
|
||||
|
||||
public:
|
||||
SendMultiMachinePage(Plater* plater = nullptr);
|
||||
~SendMultiMachinePage();
|
||||
|
||||
void prepare(int plate_idx);
|
||||
|
||||
void on_dpi_changed(const wxRect& suggested_rect);
|
||||
void on_sys_color_changed();
|
||||
void refresh_user_device();
|
||||
void on_send(wxCommandEvent& event);
|
||||
bool Show(bool show);
|
||||
|
||||
BBL::PrintParams request_params(MachineObject* obj);
|
||||
|
||||
bool get_ams_mapping_result(std::string& mapping_array_str, std::string& ams_mapping_info);
|
||||
wxBoxSizer* create_item_title(wxString title, wxWindow* parent, wxString tooltip);
|
||||
wxBoxSizer* create_item_checkbox(wxString title, wxWindow* parent, wxString tooltip, int padding_left, std::string param);
|
||||
wxBoxSizer* create_item_input(wxString str_before, wxString str_after, wxWindow* parent, wxString tooltip, std::string param);
|
||||
wxBoxSizer* create_item_radiobox(wxString title, wxWindow* parent, wxString tooltip, int groupid, std::string param);
|
||||
|
||||
wxPanel* create_page();
|
||||
void sync_ams_list();
|
||||
void set_default_normal(const ThumbnailData& data);
|
||||
void set_default();
|
||||
void on_rename_enter();
|
||||
void check_fcous_state(wxWindow* window);
|
||||
void check_focus(wxWindow* window);
|
||||
|
||||
protected:
|
||||
void OnSelectRadio(wxMouseEvent& event);
|
||||
void on_select_radio(std::string param);
|
||||
bool get_value_radio(std::string param);
|
||||
void on_set_finish_mapping(wxCommandEvent& evt);
|
||||
void on_rename_click(wxCommandEvent& event);
|
||||
|
||||
void on_timer(wxTimerEvent& event);
|
||||
void init_timer();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -84,7 +84,8 @@ static std::vector<std::string> message_containing_retry{
|
||||
"07FF 8011",
|
||||
"07FF 8012",
|
||||
"07FF 8013",
|
||||
"12FF 8007"
|
||||
"12FF 8007",
|
||||
"1200 8006"
|
||||
};
|
||||
|
||||
static std::vector<std::string> message_containing_done{
|
||||
@@ -1779,6 +1780,14 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
|
||||
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_PRINT_ERROR_STOP, &StatusPanel::on_subtask_abort, this);
|
||||
Bind(EVT_LOAD_VAMS_TRAY, &StatusPanel::on_ams_load_vams, this);
|
||||
Bind(EVT_JUMP_TO_LIVEVIEW, [this](wxCommandEvent& e) {
|
||||
m_media_play_ctrl->jump_to_play();
|
||||
if (m_print_error_dlg)
|
||||
m_print_error_dlg->on_hide();
|
||||
});
|
||||
|
||||
|
||||
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);
|
||||
@@ -1933,6 +1942,8 @@ void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event)
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2156,52 +2167,76 @@ void StatusPanel::show_recenter_dialog() {
|
||||
obj->command_go_home();
|
||||
}
|
||||
|
||||
void StatusPanel::show_error_message(MachineObject* obj, wxString msg, std::string print_error_str)
|
||||
void StatusPanel::show_error_message(MachineObject* obj, wxString msg, std::string print_error_str, wxString image_url, std::vector<int> used_button)
|
||||
{
|
||||
if (msg.IsEmpty()) {
|
||||
error_info_reset();
|
||||
} else {
|
||||
m_project_task_panel->show_error_msg(msg);
|
||||
|
||||
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);
|
||||
if (!used_button.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "show print error! error_msg = " << msg;
|
||||
if (m_print_error_dlg == nullptr) {
|
||||
m_print_error_dlg = new PrintErrorDialog(this->GetParent(), wxID_ANY, _L("Error"));
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "show print error! error_msg = " << msg;
|
||||
if (m_print_error_dlg == nullptr) {
|
||||
m_print_error_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Warning"), SecondaryCheckDialog::ButtonStyle::ONLY_CONFIRM);
|
||||
}
|
||||
m_print_error_dlg->update_title_style(_L("Error"), used_button, this);
|
||||
m_print_error_dlg->update_text_image(msg, image_url);
|
||||
m_print_error_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, obj](wxCommandEvent& e) {
|
||||
if (obj) {
|
||||
obj->command_clean_print_error(obj->subtask_id_, obj->print_error);
|
||||
}
|
||||
});
|
||||
|
||||
if (it_done != message_containing_done.end() && it_retry != message_containing_retry.end()) {
|
||||
m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::DONE_AND_RETRY, this);
|
||||
}
|
||||
else if (it_done != message_containing_done.end()) {
|
||||
m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_DONE, this);
|
||||
}
|
||||
else if (it_retry != message_containing_retry.end()) {
|
||||
m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RETRY, this);
|
||||
}
|
||||
else if (it_resume!= message_containing_resume.end()) {
|
||||
m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::CONFIRM_AND_RESUME, this);
|
||||
m_print_error_dlg->Bind(EVT_SECONDARY_CHECK_RETRY, [this, obj](wxCommandEvent& e) {
|
||||
if (m_ams_control) {
|
||||
m_ams_control->on_retry();
|
||||
}
|
||||
});
|
||||
|
||||
m_print_error_dlg->on_show();
|
||||
}
|
||||
else {
|
||||
m_print_error_dlg->update_title_style(_L("Warning"), SecondaryCheckDialog::ButtonStyle::ONLY_CONFIRM, this);
|
||||
//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;
|
||||
if (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(msg);
|
||||
m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, obj](wxCommandEvent& e) {
|
||||
if (obj) {
|
||||
obj->command_clean_print_error(obj->subtask_id_, obj->print_error);
|
||||
}
|
||||
});
|
||||
|
||||
m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_RETRY, [this, obj](wxCommandEvent& e) {
|
||||
if (m_ams_control) {
|
||||
m_ams_control->on_retry();
|
||||
}
|
||||
});
|
||||
|
||||
m_print_error_dlg_no_action->on_show();
|
||||
}
|
||||
m_print_error_dlg->update_text(msg);
|
||||
|
||||
m_print_error_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, obj](wxCommandEvent& e) {
|
||||
if (obj) {
|
||||
obj->command_clean_print_error(obj->subtask_id_, obj->print_error);
|
||||
}
|
||||
});
|
||||
|
||||
m_print_error_dlg->Bind(EVT_SECONDARY_CHECK_RETRY, [this, obj](wxCommandEvent& e) {
|
||||
if (m_ams_control) {
|
||||
m_ams_control->on_retry();
|
||||
}
|
||||
});
|
||||
|
||||
m_print_error_dlg->on_show();
|
||||
wxGetApp().mainframe->RequestUserAttention(wxUSER_ATTENTION_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -2224,13 +2259,19 @@ void StatusPanel::update_error_message()
|
||||
}
|
||||
|
||||
wxString error_msg = wxGetApp().get_hms_query()->query_print_error_msg(obj->print_error);
|
||||
std::vector<int> used_button;
|
||||
wxString error_image_url = wxGetApp().get_hms_query()->query_print_error_url_action(obj->print_error,obj->dev_id, 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);
|
||||
if (!error_msg.IsEmpty()) {
|
||||
wxDateTime now = wxDateTime::Now();
|
||||
wxString show_time = now.Format("%H:%M:%S");
|
||||
error_msg = wxString::Format("%s[%s %s]",
|
||||
wxString show_time = now.Format("%Y-%m-%d %H:%M:%S");
|
||||
|
||||
error_msg = wxString::Format("%s\n[%s %s]",
|
||||
error_msg,
|
||||
print_error_str, show_time);
|
||||
show_error_message(obj, error_msg, print_error_str);
|
||||
show_error_message(obj, error_msg, print_error_str,error_image_url,used_button);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "show print error! error_msg is empty, print error = " << obj->print_error;
|
||||
}
|
||||
@@ -2531,6 +2572,7 @@ void StatusPanel::update_ams(MachineObject *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_air_printing_detection(obj->ams_air_print_status);
|
||||
}
|
||||
}
|
||||
if (m_filament_setting_dlg) { m_filament_setting_dlg->obj = obj; }
|
||||
@@ -3515,6 +3557,16 @@ void StatusPanel::on_ams_load_curr()
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel::on_ams_load_vams(wxCommandEvent& event) {
|
||||
BOOST_LOG_TRIVIAL(info) << "on_ams_load_vams_tray";
|
||||
|
||||
m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_ID));
|
||||
on_ams_load_curr();
|
||||
if (m_print_error_dlg) {
|
||||
m_print_error_dlg->on_hide();
|
||||
}
|
||||
}
|
||||
|
||||
void StatusPanel::on_ams_unload(SimpleEvent &event)
|
||||
{
|
||||
if (obj) { obj->command_ams_switch(255); }
|
||||
@@ -3839,6 +3891,8 @@ void StatusPanel::on_print_error_done(wxCommandEvent& event)
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user