mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-23 00:42:33 +00:00
Compare commits
190
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cda25c3715 | ||
|
|
9e34ca536b | ||
|
|
201617a6c0 | ||
|
|
2dcbee3d76 | ||
|
|
6183007c28 | ||
|
|
b23953d7cf | ||
|
|
cfc6be5001 | ||
|
|
19e094a1d1 | ||
|
|
a2c631753b | ||
|
|
29b9076440 | ||
|
|
323cd3afe1 | ||
|
|
57b3a040e2 | ||
|
|
fd9c1218a4 | ||
|
|
f27b0a1f9d | ||
|
|
cf1c164546 | ||
|
|
bca8dd00dd | ||
|
|
8b7f8cac82 | ||
|
|
aae03257ed | ||
|
|
3fba237c9a | ||
|
|
cfb6349695 | ||
|
|
f53ad6993a | ||
|
|
e168d900f2 | ||
|
|
bc03e3be2f | ||
|
|
f224b8e4a6 | ||
|
|
8b479c9af3 | ||
|
|
d8299c388e | ||
|
|
4d85b6627e | ||
|
|
ee2b4ccf70 | ||
|
|
753c793ea0 | ||
|
|
9c5494b19f | ||
|
|
93a119427a | ||
|
|
d264fcaef4 | ||
|
|
b4ab6dedfd | ||
|
|
ed59f93456 | ||
|
|
cf52c81dcd | ||
|
|
803a2a3239 | ||
|
|
985092bb46 | ||
|
|
cb16a2e547 | ||
|
|
2c2e91b629 | ||
|
|
c3faf903ca | ||
|
|
5f3c957597 | ||
|
|
8557285389 | ||
|
|
a9edab78a8 | ||
|
|
79dede7d59 | ||
|
|
2ac45b2f78 | ||
|
|
b4f33e71e9 | ||
|
|
8c91cab971 | ||
|
|
79077518e9 | ||
|
|
56aa348c89 | ||
|
|
ae1752fbf2 | ||
|
|
cf3f36a1c6 | ||
|
|
cca7d8adb1 | ||
|
|
396d9ff51a | ||
|
|
81540c81e0 | ||
|
|
e7ace6cc99 | ||
|
|
79c20a1fad | ||
|
|
e48f9f47d2 | ||
|
|
2f566e3779 | ||
|
|
37d1edf69a | ||
|
|
f1cf9c69b1 | ||
|
|
1df362888e | ||
|
|
4b2466b179 | ||
|
|
3adcb3e953 | ||
|
|
104dbb2140 | ||
|
|
e482cbbdd7 | ||
|
|
2a5ddd9edb | ||
|
|
c10f83cf61 | ||
|
|
8eeec6935e | ||
|
|
131a2abf99 | ||
|
|
9daecc59b4 | ||
|
|
58e000d842 | ||
|
|
af6be5858e | ||
|
|
3fc7fd99d6 | ||
|
|
3fe043651b | ||
|
|
b0b78c296c | ||
|
|
62791fabfa | ||
|
|
b0ada2dee5 | ||
|
|
8f4df1aa8c | ||
|
|
5fec9b8d19 | ||
|
|
75ed5afbac | ||
|
|
01c553bad9 | ||
|
|
a4376c77c3 | ||
|
|
c459994290 | ||
|
|
3a0fda7d18 | ||
|
|
eb8733f0f4 | ||
|
|
55acb940a8 | ||
|
|
0d691403de | ||
|
|
9b2b75a51d | ||
|
|
25da273ea0 | ||
|
|
dbcb82075f | ||
|
|
2f82cfe40f | ||
|
|
972031cf06 | ||
|
|
2a4792e762 | ||
|
|
dd15ac6146 | ||
|
|
b0469254bc | ||
|
|
2228589e16 | ||
|
|
4d8480e1a1 | ||
|
|
4320cc78d9 | ||
|
|
d9d9678a7e | ||
|
|
d55a0bfec6 | ||
|
|
3b1017df51 | ||
|
|
f5b81d2ffc | ||
|
|
eb9cfe0ecb | ||
|
|
1e8805d43d | ||
|
|
e8f089dfa4 | ||
|
|
84e929ea24 | ||
|
|
abec603e73 | ||
|
|
0ed19d4826 | ||
|
|
b747c13ef4 | ||
|
|
6a12aca495 | ||
|
|
d486db6459 | ||
|
|
fe777b8801 | ||
|
|
1b3e206f34 | ||
|
|
4df1607ec4 | ||
|
|
a0ec8bec8a | ||
|
|
36c362cbd2 | ||
|
|
84fde32616 | ||
|
|
34e349e323 | ||
|
|
44941e571f | ||
|
|
876d6e2499 | ||
|
|
858b3024ff | ||
|
|
6595557c34 | ||
|
|
c729849843 | ||
|
|
c0563be36e | ||
|
|
462f8dce30 | ||
|
|
b2a0485139 | ||
|
|
f16071f083 | ||
|
|
a1505e9bed | ||
|
|
8e48312b1f | ||
|
|
ba7fdb8ceb | ||
|
|
8be9800567 | ||
|
|
c4eabc3c52 | ||
|
|
0d0d281d0c | ||
|
|
c4bbcd322b | ||
|
|
7aea1b1235 | ||
|
|
41c16436bf | ||
|
|
2bbb229c91 | ||
|
|
c2a43157d2 | ||
|
|
738b30a743 | ||
|
|
6e6ffe13f8 | ||
|
|
eb96d127b0 | ||
|
|
60421c33f4 | ||
|
|
300c4b8afb | ||
|
|
96092ef2d3 | ||
|
|
d9002ad87d | ||
|
|
4c1ea0a602 | ||
|
|
9415812d85 | ||
|
|
d3c728557e | ||
|
|
6558c52849 | ||
|
|
a34d056de2 | ||
|
|
7ba5718be6 | ||
|
|
c1163ce7e5 | ||
|
|
da187eaaf9 | ||
|
|
de0268ce86 | ||
|
|
108923bdaa | ||
|
|
44793f7a21 | ||
|
|
7cb1805272 | ||
|
|
d5c528b7c7 | ||
|
|
742cb712d8 | ||
|
|
fd1c5d826c | ||
|
|
58be7f4861 | ||
|
|
4031b00915 | ||
|
|
07c62112b8 | ||
|
|
f23e4963bf | ||
|
|
95279f7084 | ||
|
|
1014558c91 | ||
|
|
6515062a3a | ||
|
|
8153e26b6d | ||
|
|
79fd33d49a | ||
|
|
cdb662d4b2 | ||
|
|
a27fa7b5df | ||
|
|
cdeed107c5 | ||
|
|
be92f7e78c | ||
|
|
76f9de4cfb | ||
|
|
cd6d2cbf5e | ||
|
|
deaca0189f | ||
|
|
7d54ee286d | ||
|
|
dddfc7a8ad | ||
|
|
673bfb0dee | ||
|
|
b9e8c5a38c | ||
|
|
a2a4ca20e4 | ||
|
|
12075459d2 | ||
|
|
f3770f3106 | ||
|
|
90fbf1770f | ||
|
|
bde94ab37f | ||
|
|
6d25e1777e | ||
|
|
7ce26ca8e5 | ||
|
|
367fcce634 | ||
|
|
9b3a44b339 | ||
|
|
6384191102 |
+42
-2
@@ -826,6 +826,37 @@ find_package(OpenSSL REQUIRED)
|
|||||||
find_package(CURL REQUIRED)
|
find_package(CURL REQUIRED)
|
||||||
find_package(Freetype REQUIRED)
|
find_package(Freetype REQUIRED)
|
||||||
|
|
||||||
|
if (SLIC3R_GUI)
|
||||||
|
# LibDataChannel's installed export references its bundled dependencies,
|
||||||
|
# but does not install their CMake targets. Recreate those targets from
|
||||||
|
# the same dependency prefix before loading the LibDataChannel config.
|
||||||
|
if (NOT TARGET Usrsctp::usrsctp)
|
||||||
|
find_library(_ORCA_USRSCTP_LIBRARY NAMES usrsctp
|
||||||
|
PATHS "${CMAKE_PREFIX_PATH}/lib" NO_DEFAULT_PATH)
|
||||||
|
if (_ORCA_USRSCTP_LIBRARY)
|
||||||
|
add_library(Usrsctp::usrsctp UNKNOWN IMPORTED GLOBAL)
|
||||||
|
set_target_properties(Usrsctp::usrsctp PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${_ORCA_USRSCTP_LIBRARY}"
|
||||||
|
IMPORTED_LINK_INTERFACE_LANGUAGES C
|
||||||
|
INTERFACE_LINK_LIBRARIES "Threads::Threads")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT TARGET LibJuice::LibJuice)
|
||||||
|
find_library(_ORCA_LIBJUICE_LIBRARY NAMES juice
|
||||||
|
PATHS "${CMAKE_PREFIX_PATH}/lib" NO_DEFAULT_PATH)
|
||||||
|
if (_ORCA_LIBJUICE_LIBRARY)
|
||||||
|
add_library(LibJuice::LibJuice UNKNOWN IMPORTED GLOBAL)
|
||||||
|
set_target_properties(LibJuice::LibJuice PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${_ORCA_LIBJUICE_LIBRARY}"
|
||||||
|
IMPORTED_LINK_INTERFACE_LANGUAGES C
|
||||||
|
INTERFACE_LINK_LIBRARIES "Threads::Threads")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(LibDataChannel CONFIG REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_library(libcurl INTERFACE)
|
add_library(libcurl INTERFACE)
|
||||||
target_link_libraries(libcurl INTERFACE CURL::libcurl)
|
target_link_libraries(libcurl INTERFACE CURL::libcurl)
|
||||||
@@ -1106,6 +1137,7 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
endif ()
|
endif ()
|
||||||
file(COPY ${_occt_dlls}
|
file(COPY ${_occt_dlls}
|
||||||
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
||||||
|
${CMAKE_PREFIX_PATH}/bin/avformat-61.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
|
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
|
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
|
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
|
||||||
@@ -1118,11 +1150,11 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
${_out_dir}/WebView2Loader.dll
|
${_out_dir}/WebView2Loader.dll
|
||||||
|
|
||||||
${_out_dir}/freetype.dll
|
${_out_dir}/freetype.dll
|
||||||
|
${_out_dir}/avformat-61.dll
|
||||||
${_out_dir}/avcodec-61.dll
|
${_out_dir}/avcodec-61.dll
|
||||||
${_out_dir}/swresample-5.dll
|
${_out_dir}/swresample-5.dll
|
||||||
${_out_dir}/swscale-8.dll
|
${_out_dir}/swscale-8.dll
|
||||||
${_out_dir}/avutil-59.dll
|
${_out_dir}/avutil-59.dll
|
||||||
PARENT_SCOPE
|
|
||||||
)
|
)
|
||||||
list(APPEND _dll_list ${_occt_staged})
|
list(APPEND _dll_list ${_occt_staged})
|
||||||
set(${output_dlls} ${_dll_list} PARENT_SCOPE)
|
set(${output_dlls} ${_dll_list} PARENT_SCOPE)
|
||||||
@@ -1142,7 +1174,10 @@ function(orcaslicer_copy_sos target config postfix output_sos)
|
|||||||
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
file(COPY ${CMAKE_PREFIX_PATH}/lib/libavcodec.so
|
file(COPY ${CMAKE_PREFIX_PATH}/lib/libavformat.so
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavformat.so.61
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavformat.so.61.1.100
|
||||||
|
${CMAKE_PREFIX_PATH}/lib/libavcodec.so
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61
|
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100
|
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavutil.so
|
${CMAKE_PREFIX_PATH}/lib/libavutil.so
|
||||||
@@ -1157,6 +1192,9 @@ function(orcaslicer_copy_sos target config postfix output_sos)
|
|||||||
DESTINATION ${_out_dir})
|
DESTINATION ${_out_dir})
|
||||||
|
|
||||||
set(${output_sos}
|
set(${output_sos}
|
||||||
|
${_out_dir}/libavformat.so
|
||||||
|
${_out_dir}/libavformat.so.61
|
||||||
|
${_out_dir}/libavformat.so.61.1.100
|
||||||
${_out_dir}/libavcodec.so
|
${_out_dir}/libavcodec.so
|
||||||
${_out_dir}/libavcodec.so.61
|
${_out_dir}/libavcodec.so.61
|
||||||
${_out_dir}/libavcodec.so.61.3.100
|
${_out_dir}/libavcodec.so.61.3.100
|
||||||
@@ -1286,6 +1324,8 @@ endif ()
|
|||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
set(LIBRARY_FILES
|
set(LIBRARY_FILES
|
||||||
|
${LIBDIR_BIN}/libavformat.so.61
|
||||||
|
${LIBDIR_BIN}/libavformat.so.61.1.100
|
||||||
${LIBDIR_BIN}/libavcodec.so.61
|
${LIBDIR_BIN}/libavcodec.so.61
|
||||||
${LIBDIR_BIN}/libavcodec.so.61.3.100
|
${LIBDIR_BIN}/libavcodec.so.61.3.100
|
||||||
${LIBDIR_BIN}/libavutil.so.59
|
${LIBDIR_BIN}/libavutil.so.59
|
||||||
|
|||||||
Vendored
+23
-11
@@ -156,7 +156,7 @@ if (NOT _is_multi AND NOT CMAKE_BUILD_TYPE)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
function(orcaslicer_add_cmake_project projectname)
|
function(orcaslicer_add_cmake_project projectname)
|
||||||
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
|
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND;SOURCE_DIR" "CMAKE_ARGS" ${ARGN})
|
||||||
|
|
||||||
# MSVC is true for clang-cl as well, so the sub-build toolchain has to key on the
|
# MSVC is true for clang-cl as well, so the sub-build toolchain has to key on the
|
||||||
# generator. A non-Visual-Studio superbuild passes its own generator down, and with
|
# generator. A non-Visual-Studio superbuild passes its own generator down, and with
|
||||||
@@ -202,12 +202,18 @@ function(orcaslicer_add_cmake_project projectname)
|
|||||||
set(_build_j "-j${NPROC}")
|
set(_build_j "-j${NPROC}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
set(_source_dir_arg "")
|
||||||
|
if (P_ARGS_SOURCE_DIR)
|
||||||
|
set(_source_dir_arg SOURCE_DIR ${P_ARGS_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (NOT IS_CROSS_COMPILE OR NOT APPLE)
|
if (NOT IS_CROSS_COMPILE OR NOT APPLE)
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
dep_${projectname}
|
dep_${projectname}
|
||||||
EXCLUDE_FROM_ALL ON
|
EXCLUDE_FROM_ALL ON
|
||||||
INSTALL_DIR ${DESTDIR}
|
INSTALL_DIR ${DESTDIR}
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
|
||||||
|
${_source_dir_arg}
|
||||||
${_gen}
|
${_gen}
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
@@ -240,12 +246,14 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE)
|
|||||||
# note for future devs: shared libs may actually create a size reduction
|
# note for future devs: shared libs may actually create a size reduction
|
||||||
# but orcaslicer_deps tends to get really funny regarding linking after that (notably boost)
|
# but orcaslicer_deps tends to get really funny regarding linking after that (notably boost)
|
||||||
# so, as much as I would like to use that, it's not happening
|
# so, as much as I would like to use that, it's not happening
|
||||||
ExternalProject_Add_Step(dep_${projectname} free_download_space
|
if (NOT P_ARGS_SOURCE_DIR)
|
||||||
DEPENDEES download # do after download
|
ExternalProject_Add_Step(dep_${projectname} free_download_space
|
||||||
COMMENT "Freeing Space: Removing source archive"
|
DEPENDEES download # do after download
|
||||||
WORKING_DIRECTORY ${DEP_DOWNLOAD_DIR}
|
COMMENT "Freeing Space: Removing source archive"
|
||||||
COMMAND ${CMAKE_COMMAND} -E rm -r ${projectname}
|
WORKING_DIRECTORY ${DEP_DOWNLOAD_DIR}
|
||||||
)
|
COMMAND ${CMAKE_COMMAND} -E rm -rf ${projectname}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
ExternalProject_Add_Step(dep_${projectname} free_build_space
|
ExternalProject_Add_Step(dep_${projectname} free_build_space
|
||||||
DEPENDEES install # do after install
|
DEPENDEES install # do after install
|
||||||
COMMENT "Freeing Space: Removing source and build files"
|
COMMENT "Freeing Space: Removing source and build files"
|
||||||
@@ -259,6 +267,7 @@ else()
|
|||||||
EXCLUDE_FROM_ALL ON
|
EXCLUDE_FROM_ALL ON
|
||||||
INSTALL_DIR ${DESTDIR}
|
INSTALL_DIR ${DESTDIR}
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
|
||||||
|
${_source_dir_arg}
|
||||||
${_gen}
|
${_gen}
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
@@ -386,10 +395,6 @@ include(libnoise/libnoise.cmake)
|
|||||||
|
|
||||||
include(Draco/Draco.cmake)
|
include(Draco/Draco.cmake)
|
||||||
|
|
||||||
include(FFMPEG/FFMPEG.cmake)
|
|
||||||
include(Assimp/Assimp.cmake)
|
|
||||||
|
|
||||||
|
|
||||||
# I *think* 1.1 is used for *just* md5 hashing?
|
# I *think* 1.1 is used for *just* md5 hashing?
|
||||||
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
||||||
# a grep across the repo shows it is used for other things
|
# a grep across the repo shows it is used for other things
|
||||||
@@ -400,6 +405,12 @@ if(NOT OPENSSL_FOUND)
|
|||||||
set(OPENSSL_PKG dep_OpenSSL)
|
set(OPENSSL_PKG dep_OpenSSL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(FFMPEG/FFMPEG.cmake)
|
||||||
|
include(Assimp/Assimp.cmake)
|
||||||
|
|
||||||
|
include(DataChannel/DataChannel.cmake)
|
||||||
|
set(DATACHANNEL_PKG dep_DataChannel)
|
||||||
|
|
||||||
# we don't want to load a "wrong" openssl when loading curl
|
# we don't want to load a "wrong" openssl when loading curl
|
||||||
# so, just don't even bother
|
# so, just don't even bother
|
||||||
# ...i think this is how it works? change if wrong
|
# ...i think this is how it works? change if wrong
|
||||||
@@ -473,6 +484,7 @@ set(_dep_list
|
|||||||
dep_wxInspector
|
dep_wxInspector
|
||||||
dep_FFMPEG
|
dep_FFMPEG
|
||||||
dep_Assimp
|
dep_Assimp
|
||||||
|
${DATACHANNEL_PKG}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
Vendored
+37
@@ -0,0 +1,37 @@
|
|||||||
|
# libdatachannel is the native ICE/DTLS/SCTP implementation used by the
|
||||||
|
# GUI WebRTC camera controller. Keep the source revision fixed: the signaling
|
||||||
|
# protocol is evolving independently of this transport dependency.
|
||||||
|
#
|
||||||
|
# It vendors plog, usrsctp and libjuice as git submodules, which a plain
|
||||||
|
# GitHub tag tarball does not include. The flatpak sandbox has no network
|
||||||
|
# access during the build, so there the manifest itself clones the repo
|
||||||
|
# (submodules and all) into the dependency download directory before the
|
||||||
|
# sandbox closes. ExternalProject_Add is pointed at that existing checkout
|
||||||
|
# instead of being given its own network-dependent download method.
|
||||||
|
if (FLATPAK)
|
||||||
|
set(_datachannel_source
|
||||||
|
SOURCE_DIR ${DEP_DOWNLOAD_DIR}/DataChannel
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(_datachannel_source
|
||||||
|
GIT_REPOSITORY https://github.com/paullouisageneau/libdatachannel.git
|
||||||
|
GIT_TAG v0.24.5
|
||||||
|
GIT_SHALLOW ON
|
||||||
|
GIT_SUBMODULES_RECURSE ON
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
orcaslicer_add_cmake_project(DataChannel
|
||||||
|
DEPENDS ${OPENSSL_PKG}
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DNO_EXAMPLES=ON
|
||||||
|
-DNO_TESTS=ON
|
||||||
|
-DNO_WEBSOCKET=ON
|
||||||
|
-DNO_MEDIA=ON
|
||||||
|
-DUSE_NICE=OFF
|
||||||
|
-DUSE_SYSTEM_JUICE=OFF
|
||||||
|
-DUSE_SYSTEM_USRSCTP=OFF
|
||||||
|
-DOPENSSL_ROOT_DIR:PATH=${DESTDIR}
|
||||||
|
-DOPENSSL_USE_STATIC_LIBS=ON
|
||||||
|
${_datachannel_source}
|
||||||
|
)
|
||||||
Vendored
+23
-7
@@ -1,14 +1,26 @@
|
|||||||
set(_conf_cmd ./configure)
|
set(_conf_cmd ./configure)
|
||||||
|
|
||||||
|
set(_ffmpeg_depends)
|
||||||
|
set(_ffmpeg_configure_command ${_conf_cmd})
|
||||||
|
if (TARGET dep_OpenSSL)
|
||||||
|
set(_ffmpeg_depends DEPENDS dep_OpenSSL)
|
||||||
|
set(_ffmpeg_configure_command
|
||||||
|
${CMAKE_COMMAND} -E env
|
||||||
|
"PKG_CONFIG_PATH=${DESTDIR}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}"
|
||||||
|
${_conf_cmd}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
|
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
|
||||||
|
|
||||||
set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-winarm64-orca-shared-7.0.zip")
|
set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-09-18-16-50/ffmpeg-n7.0.3-33-g887d4b4919-winarm64-orca-shared-7.0.zip")
|
||||||
set(PREBUILD_HASH_arm64 "12f4140279f2f8469885e1b5b2e8be9d788882914c21523cacd56989f3548054")
|
set(PREBUILD_HASH_arm64 "da480cbb39680056de824c57ec4dc3bd577b479ebbc310ff1f9dc55cf014b4c1")
|
||||||
set(PREBUILD_URL_x64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-win64-orca-shared-7.0.zip")
|
set(PREBUILD_URL_x64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-09-18-16-50/ffmpeg-n7.0.3-33-g887d4b4919-win64-orca-shared-7.0.zip")
|
||||||
set(PREBUILD_HASH_x64 "e65916020ddb9ef84b2666dfbcbfc9b1d67f69d15b4a66db53754637bf2d498c")
|
set(PREBUILD_HASH_x64 "85da19daf198f5548259d8aabb349db84997a3f6e6886d8d7764114add9c6dae")
|
||||||
|
|
||||||
ExternalProject_Add(dep_FFMPEG
|
ExternalProject_Add(dep_FFMPEG
|
||||||
|
${_ffmpeg_depends}
|
||||||
URL ${PREBUILD_URL_${DEPS_ARCH}}
|
URL ${PREBUILD_URL_${DEPS_ARCH}}
|
||||||
URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}}
|
URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}}
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
||||||
@@ -21,6 +33,8 @@ if (MSVC)
|
|||||||
)
|
)
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
|
set(_openssl_cmd --enable-openssl)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(_minos_cmd
|
set(_minos_cmd
|
||||||
"--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
"--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
@@ -52,10 +66,11 @@ else ()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
ExternalProject_Add(dep_FFMPEG
|
ExternalProject_Add(dep_FFMPEG
|
||||||
|
${_ffmpeg_depends}
|
||||||
URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
|
URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
|
||||||
URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC
|
URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
||||||
CONFIGURE_COMMAND ${_conf_cmd}
|
CONFIGURE_COMMAND ${_ffmpeg_configure_command}
|
||||||
${_cross_cmd}
|
${_cross_cmd}
|
||||||
${_pic_cmd}
|
${_pic_cmd}
|
||||||
${_arch_cmd}
|
${_arch_cmd}
|
||||||
@@ -63,20 +78,21 @@ else ()
|
|||||||
"--prefix=${DESTDIR}"
|
"--prefix=${DESTDIR}"
|
||||||
${_link_cmd}
|
${_link_cmd}
|
||||||
${_minos_cmd}
|
${_minos_cmd}
|
||||||
|
${_openssl_cmd}
|
||||||
--disable-doc
|
--disable-doc
|
||||||
--enable-small
|
--enable-small
|
||||||
--disable-outdevs
|
--disable-outdevs
|
||||||
--disable-filters
|
--disable-filters
|
||||||
--enable-filter=*null*,afade,*fifo,*format,*resample,aeval,allrgb,allyuv,atempo,pan,*bars,color,*key,crop,draw*,eq*,framerate,*_qsv,*_vaapi,*v4l2*,hw*,scale,volume,test*
|
--enable-filter=*null*,afade,*fifo,*format,*resample,aeval,allrgb,allyuv,atempo,pan,*bars,color,*key,crop,draw*,eq*,framerate,*_qsv,*_vaapi,*v4l2*,hw*,scale,volume,test*
|
||||||
--disable-protocols
|
--disable-protocols
|
||||||
--enable-protocol=file,fd,pipe,rtp,udp
|
--enable-protocol=file,fd,pipe,http,https,rtp,tcp,udp
|
||||||
--disable-muxers
|
--disable-muxers
|
||||||
--enable-muxer=rtp
|
--enable-muxer=rtp
|
||||||
--disable-encoders
|
--disable-encoders
|
||||||
--disable-decoders
|
--disable-decoders
|
||||||
--enable-decoder=*aac*,h264*,mp3*,mjpeg,rv*
|
--enable-decoder=*aac*,h264*,mp3*,mjpeg,rv*
|
||||||
--disable-demuxers
|
--disable-demuxers
|
||||||
--enable-demuxer=h264,mp3,mov
|
--enable-demuxer=h264,mp3,mov,mpjpeg,rtsp,sdp
|
||||||
--disable-zlib
|
--disable-zlib
|
||||||
--disable-avdevice
|
--disable-avdevice
|
||||||
BUILD_IN_SOURCE ON
|
BUILD_IN_SOURCE ON
|
||||||
|
|||||||
@@ -0,0 +1,240 @@
|
|||||||
|
# Printer agents
|
||||||
|
|
||||||
|
Printer agents isolate printer-specific communication from the rest of OrcaSlicer. The GUI and
|
||||||
|
`DeviceManager` operate on a shared set of printer operations and device state; a selected printer
|
||||||
|
agent implements those operations for a particular printer ecosystem. The agent boundary allows
|
||||||
|
Bambu, Moonraker-based printers, built-in integrations, and Python-provided integrations to use the
|
||||||
|
same application workflow without making the GUI understand every printer protocol.
|
||||||
|
|
||||||
|
The current boundary is an adapter boundary around the existing application contract. In particular,
|
||||||
|
some request fields and message payloads still use the Bambu-shaped representation that existing
|
||||||
|
`MachineObject` and `DeviceManager` code consumes. The printer agent is responsible for translating
|
||||||
|
that representation into the protocol spoken by its printer. This is an intentional compatibility
|
||||||
|
constraint of the current design; the interface is not yet a neutral printer protocol.
|
||||||
|
|
||||||
|
The v1 dialect migration path is deliberately narrow. `DeviceManager` currently speaks the Bambu JSON
|
||||||
|
dialect because that is the payload shape already used throughout the command and state workflow. The
|
||||||
|
v1 `OrcaPrinterAgent` also accepts that Bambu dialect. Its transport path places the small translation
|
||||||
|
needed for the target printer at `deliver_to_sink`, keeping the compatibility code at the edge rather
|
||||||
|
than spreading it through `DeviceManager` or the agent interface.
|
||||||
|
|
||||||
|
The eventual direction is for `DeviceManager` to produce an Orca JSON dialect. The Bambu agent will then
|
||||||
|
own the translation from Orca JSON to Bambu's protocol, while `OrcaPrinterAgent` can forward the Orca
|
||||||
|
payload directly to its sink. The v1 translation at `deliver_to_sink` can then be removed without
|
||||||
|
changing `DeviceManager`, the command callers, or the rest of the agent workflow.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
The system has four relevant layers:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GUI / DeviceManager / MachineObject
|
||||||
|
|
|
||||||
|
NetworkAgent
|
||||||
|
/ \
|
||||||
|
IPrinterAgent ICloudServiceAgent
|
||||||
|
| |
|
||||||
|
printer protocol authentication and cloud services
|
||||||
|
```
|
||||||
|
|
||||||
|
### `DeviceManager` and `MachineObject`
|
||||||
|
|
||||||
|
`DeviceManager` owns the application-facing printer workflow. It maintains `MachineObject` instances,
|
||||||
|
updates their state, filters devices for the active printer agent, and initiates operations such as
|
||||||
|
homing, temperature changes, printing, subscriptions, and camera playback.
|
||||||
|
|
||||||
|
`MachineObject` remains the shared state model used by the GUI. It does not contain the implementation
|
||||||
|
of a printer protocol. When a device is discovered or returned by a cloud query, the device is tagged
|
||||||
|
with the active `printer_agent_id`. Device lists and selected-machine operations use that tag to avoid
|
||||||
|
sending an operation through an agent that does not own the device.
|
||||||
|
|
||||||
|
### `NetworkAgent`
|
||||||
|
|
||||||
|
`NetworkAgent` is the façade used by the GUI and `DeviceManager`. It owns:
|
||||||
|
|
||||||
|
- the currently selected `IPrinterAgent`;
|
||||||
|
- the registered cloud-service instances, indexed by provider;
|
||||||
|
- callbacks shared by the active printer agent and the application;
|
||||||
|
- the forwarding methods for printer commands and cloud operations.
|
||||||
|
|
||||||
|
There is one active printer agent for the currently selected printer preset. Switching the preset
|
||||||
|
increments the machine-list generation, disconnects the old printer agent, removes its callbacks, and
|
||||||
|
installs the newly selected agent. The façade then forwards printer operations to that agent.
|
||||||
|
|
||||||
|
Cloud operations are selected separately using a provider key. `NetworkAgent` forwards a cloud request
|
||||||
|
to the matching `ICloudServiceAgent`, and forwards cloud camera operations with a device ID. The
|
||||||
|
printer agent receives a cloud-agent pointer through `set_cloud_agent()` when it is created, allowing
|
||||||
|
printer communication to obtain cloud tokens without depending on a concrete cloud implementation.
|
||||||
|
|
||||||
|
### `IPrinterAgent`
|
||||||
|
|
||||||
|
`IPrinterAgent` is the printer-facing contract. It covers:
|
||||||
|
|
||||||
|
- cloud-relay and direct-LAN message delivery;
|
||||||
|
- LAN connection, discovery, binding, and certificates;
|
||||||
|
- printer subscriptions and callbacks;
|
||||||
|
- print operations;
|
||||||
|
- filament synchronization;
|
||||||
|
- camera capability and local camera URL reporting;
|
||||||
|
- printer command methods.
|
||||||
|
|
||||||
|
Concrete built-in implementations include the Bambu wrapper, the native Orca/Moonraker path, and
|
||||||
|
other printer-agent implementations registered by the application. A printer agent may use either
|
||||||
|
the cloud agent, a direct LAN connection, or both.
|
||||||
|
|
||||||
|
### `ICloudServiceAgent`
|
||||||
|
|
||||||
|
`ICloudServiceAgent` owns authentication and services provided by a cloud backend. It covers login
|
||||||
|
state, tokens, user and printer lists, settings synchronization, model services, cloud messages, and
|
||||||
|
cloud camera operations.
|
||||||
|
|
||||||
|
Cloud camera operations are device-scoped:
|
||||||
|
|
||||||
|
- `get_camera_url(dev_id, callback)` obtains a stream URL for one device;
|
||||||
|
- `create_camera_signaling_channel(dev_id)` creates signaling for one device where the provider
|
||||||
|
supports it.
|
||||||
|
|
||||||
|
This is separate from the local camera URL exposed by `IPrinterAgent`, which is currently scoped to
|
||||||
|
the active printer agent because a normal LAN agent represents one physical printer connection.
|
||||||
|
|
||||||
|
## Agent registration and selection
|
||||||
|
|
||||||
|
`NetworkAgentFactory` maintains the printer-agent registry. Each registry entry contains an agent ID,
|
||||||
|
a display name, and a factory function. Built-in agents register during application initialization.
|
||||||
|
Python printer-agent capabilities register dynamically and contribute an agent ID and factory entry.
|
||||||
|
|
||||||
|
The selected printer preset contains the printer-agent choice. If no explicit choice is stored, the
|
||||||
|
application preserves the existing default behavior: Bambu presets select the Bambu agent and other
|
||||||
|
presets select the native Orca agent. When a preset is changed, `GUI_App` resolves the effective agent
|
||||||
|
ID, obtains the corresponding cloud agent, creates the printer agent through the registry, and installs
|
||||||
|
it in `NetworkAgent`.
|
||||||
|
|
||||||
|
The registry rejects conflicting agent IDs. This matters for Python plugins because an agent ID is the
|
||||||
|
stable identity used by presets and device ownership; two enabled plugin capabilities must not claim
|
||||||
|
the same ID.
|
||||||
|
|
||||||
|
## Message and command flow
|
||||||
|
|
||||||
|
There are two low-level message paths:
|
||||||
|
|
||||||
|
- `send_message()` publishes a command through the printer's cloud relay;
|
||||||
|
- `send_message_to_printer()` sends a command directly to the printer over the LAN path.
|
||||||
|
|
||||||
|
Both paths accept a JSON string, quality-of-service and flag values, and return the existing network
|
||||||
|
status code domain. The agent owns the conversion from that JSON contract to its native transport.
|
||||||
|
|
||||||
|
The typed `command_*` methods are the application-facing convenience layer. The five generic defaults
|
||||||
|
currently implemented by `IPrinterAgent` construct the existing JSON dialect and route through the
|
||||||
|
same message path:
|
||||||
|
|
||||||
|
| Method | Default operation |
|
||||||
|
| --- | --- |
|
||||||
|
| `command_xyz_abs()` | Send `G90` for absolute positioning |
|
||||||
|
| `command_auto_leveling()` | Send `G29` for bed leveling |
|
||||||
|
| `command_go_home()` | Use the supported homing operation or send `G28` |
|
||||||
|
| `command_set_bed()` | Use the supported bed control or send `M140` |
|
||||||
|
| `command_set_nozzle()` | Send `M104` for nozzle temperature |
|
||||||
|
|
||||||
|
These are compatibility defaults for common printer workflows, not a guarantee that every firmware
|
||||||
|
implements every command identically. An agent can override a method when its protocol needs another
|
||||||
|
operation. For example, a Klipper configuration may use `BED_MESH_CALIBRATE` instead of `G29`.
|
||||||
|
|
||||||
|
The remaining common command methods default to `ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED` because their
|
||||||
|
existing behavior is vendor-specific or has no portable implementation:
|
||||||
|
|
||||||
|
- AMS RFID refresh;
|
||||||
|
- AMS calibration;
|
||||||
|
- AMS tray selection;
|
||||||
|
- camera start;
|
||||||
|
- axis control.
|
||||||
|
|
||||||
|
The methods remain on the common interface so an agent that supports them can override them explicitly.
|
||||||
|
`sequence_id` remains part of the command contract because `DeviceManager` creates and tracks it as
|
||||||
|
the command ID.
|
||||||
|
|
||||||
|
## Device ownership and stale responses
|
||||||
|
|
||||||
|
Printer-agent ownership is represented by `printer_agent_id` on device records and `MachineObject`
|
||||||
|
instances. The active agent ID is attached when a device is discovered, returned by a cloud list, or
|
||||||
|
reused after a preset switch. Local-machine configuration also persists the agent ID so a saved LAN
|
||||||
|
device is not silently reused by an unrelated agent.
|
||||||
|
|
||||||
|
Cloud printer-list responses carry three pieces of request context added by `NetworkAgent`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
provider cloud provider used for the request
|
||||||
|
agent_id active printer agent when the request was made
|
||||||
|
generation machine-list generation when the request was made
|
||||||
|
```
|
||||||
|
|
||||||
|
`DeviceManager` accepts the response only when those values still match the current provider, active
|
||||||
|
agent, and generation. This prevents a slow response from the previous preset or provider from
|
||||||
|
repopulating the current device list.
|
||||||
|
|
||||||
|
The provider mapping is currently selected by `GUI_App`: the Bambu agent maps to the Bambu cloud
|
||||||
|
provider and other agents map to the Orca cloud provider. The generation check protects that existing
|
||||||
|
selection from races; it does not make cloud-provider ownership intrinsic to an agent. Cloud-printer
|
||||||
|
ownership and the broader Orca cloud services are therefore still separate architectural concerns.
|
||||||
|
|
||||||
|
## Python printer agents
|
||||||
|
|
||||||
|
`PrinterAgentPluginCapability` implements `IPrinterAgent` directly. The live capability object is
|
||||||
|
registered with `NetworkAgentFactory` and handed out as the printer agent when its agent ID is selected.
|
||||||
|
The plugin receives the selected `ICloudServiceAgent` through `set_cloud_agent()` just like a built-in
|
||||||
|
printer agent.
|
||||||
|
|
||||||
|
Python plugins must implement the core communication and lifecycle methods required by the interface,
|
||||||
|
including agent metadata, printer connection, discovery callbacks, and the two message-send methods.
|
||||||
|
Methods that are meaningful only to a particular printer are optional overrides where the C++ base
|
||||||
|
class provides a default.
|
||||||
|
|
||||||
|
All ten `command_*` methods are available in the Python binding and in the trampoline. Their override
|
||||||
|
status is intentionally optional:
|
||||||
|
|
||||||
|
- the five generic commands use the C++ default when Python does not override them;
|
||||||
|
- the five vendor-specific commands return `NOT_SUPPORTED` unless Python supplies an implementation;
|
||||||
|
- a Python implementation can replace either behavior for its own protocol.
|
||||||
|
|
||||||
|
The Python camera binding exposes HTTP, HTTPS, RTSP, and HTTP-snapshot modes. WebRTC remains a
|
||||||
|
built-in C++ camera mode, but is not exposed as a Python mode because the current Python capability
|
||||||
|
does not provide the corresponding cloud signaling-channel contract.
|
||||||
|
|
||||||
|
## Camera playback boundary
|
||||||
|
|
||||||
|
The camera stream mode describes how a stream is obtained; it does not by itself define ownership of
|
||||||
|
the wxWidgets view that renders it. `MediaPlayCtrl` selects and tears down the active backend, while
|
||||||
|
the wx parent owns the child window or renderer. This is important because a web view, native media
|
||||||
|
control, and frame-based/WebRTC renderer have different wx window-lifetime requirements.
|
||||||
|
|
||||||
|
Cloud URL and signaling requests are routed through `NetworkAgent` to the cloud provider selected for
|
||||||
|
the device. Local URL requests are routed to the active printer agent. The distinction keeps cloud
|
||||||
|
account services device-scoped while preserving the current one-LAN-agent/one-printer model.
|
||||||
|
|
||||||
|
## Compatibility constraints
|
||||||
|
|
||||||
|
The printer-agent boundary intentionally preserves several existing application contracts:
|
||||||
|
|
||||||
|
- Bambu-shaped JSON is still the shared command representation;
|
||||||
|
- existing network status codes are reused, with Orca-specific unsupported/capability errors added
|
||||||
|
in the Orca-reserved range;
|
||||||
|
- `MachineObject` remains the shared device-state model;
|
||||||
|
- preset and local-machine data retain compatibility with the existing agent-selection behavior;
|
||||||
|
- Python plugins use the existing capability and pybind11 registration system.
|
||||||
|
|
||||||
|
The agent abstraction is therefore responsible for containing vendor differences, not for pretending
|
||||||
|
that all vendor protocols are identical. The planned Orca JSON dialect is the protocol-neutral command
|
||||||
|
model for the `DeviceManager`/agent boundary. Once it is introduced, Bambu-specific translation remains
|
||||||
|
inside the Bambu agent and the Orca agent's v1 sink adapter can be removed as a self-contained cleanup.
|
||||||
|
|
||||||
|
## Main implementation locations
|
||||||
|
|
||||||
|
- [`IPrinterAgent`](../../src/slic3r/Utils/IPrinterAgent.hpp) — printer-agent contract and generic command defaults
|
||||||
|
- [`ICloudServiceAgent`](../../src/slic3r/Utils/ICloudServiceAgent.hpp) — cloud service and per-device
|
||||||
|
cloud camera contract
|
||||||
|
- [`NetworkAgent`](../../src/slic3r/Utils/NetworkAgent.hpp) — façade and dispatch between active agents
|
||||||
|
- [`NetworkAgentFactory`](../../src/slic3r/Utils/NetworkAgentFactory.hpp) — built-in and Python agent registry
|
||||||
|
- [`DeviceManager`](../../src/slic3r/GUI/DeviceCore/DevManager.cpp) — device ownership, filtering, and
|
||||||
|
stale-response checks
|
||||||
|
- [`PrinterAgentPluginCapability`](../../src/slic3r/plugin/pluginTypes/printerAgent/PrinterAgentPluginCapability.cpp)
|
||||||
|
— Python bindings
|
||||||
|
- [`MediaPlayCtrl`](../../src/slic3r/GUI/MediaPlayCtrl.cpp) — camera backend selection and playback lifecycle
|
||||||
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -6161,9 +6161,6 @@ msgstr ""
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -6171,6 +6168,9 @@ msgstr ""
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2025-03-15 10:55+0100\n"
|
"PO-Revision-Date: 2025-03-15 10:55+0100\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6637,9 +6637,6 @@ msgstr "Mostrar el contorn al voltant de l'objecte seleccionat a l'escena 3D"
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Preferències"
|
msgstr "Preferències"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6648,6 +6645,9 @@ msgstr "Edita"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Vista"
|
msgstr "Vista"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Paquet de perfils"
|
msgstr "Paquet de perfils"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Jakub Hencl\n"
|
"Last-Translator: Jakub Hencl\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6602,9 +6602,6 @@ msgstr "Zobrazit obrys kolem vybraného objektu ve 3D scéně."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Předvolby"
|
msgstr "Předvolby"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6613,6 +6610,9 @@ msgstr "Upravit"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Zobrazit"
|
msgstr "Zobrazit"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Balík předvoleb"
|
msgstr "Balík předvoleb"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Heiko Liebscher <hliebschergmail.com>\n"
|
"Last-Translator: Heiko Liebscher <hliebschergmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6490,9 +6490,6 @@ msgstr "Kontur um das ausgewählte Objekt in der 3D-Szene anzeigen."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6501,6 +6498,9 @@ msgstr "Bearbeiten"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Ansicht"
|
msgstr "Ansicht"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Vorlagen-Bundle"
|
msgstr "Vorlagen-Bundle"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-06-17 15:44-0300\n"
|
"PO-Revision-Date: 2026-06-17 15:44-0300\n"
|
||||||
"Last-Translator: Alexandre Folle de Menezes\n"
|
"Last-Translator: Alexandre Folle de Menezes\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6157,9 +6157,6 @@ msgstr ""
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -6167,6 +6164,9 @@ msgstr ""
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Ian A. Bassi <>\n"
|
"Last-Translator: Ian A. Bassi <>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6346,9 +6346,6 @@ msgstr "Mostrar el contorno alrededor del objeto seleccionado en la escena 3D."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Preferencias"
|
msgstr "Preferencias"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Edición"
|
msgstr "Edición"
|
||||||
@@ -6356,6 +6353,9 @@ msgstr "Edición"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Vista"
|
msgstr "Vista"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Paquete de perfiles"
|
msgstr "Paquete de perfiles"
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-07-20 13:33+0200\n"
|
"PO-Revision-Date: 2026-07-20 13:33+0200\n"
|
||||||
"Last-Translator: Manu Goiogana <mgoiogana@gmail.com>\n"
|
"Last-Translator: Manu Goiogana <mgoiogana@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6392,9 +6392,6 @@ msgstr "Erakutsi hautatutako objektuaren inguruko ingerada 3D eszenan."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Hobespenak"
|
msgstr "Hobespenak"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6403,6 +6400,9 @@ msgstr "Editatu"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Bista"
|
msgstr "Bista"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Aurrezarpen-paketea"
|
msgstr "Aurrezarpen-paketea"
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Guislain Cyril, Thomas Lété\n"
|
"Language-Team: Guislain Cyril, Thomas Lété\n"
|
||||||
@@ -6439,9 +6439,6 @@ msgstr "Afficher le tracé contour de l’objet sélectionné dans la scène 3D.
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Préférences"
|
msgstr "Préférences"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6450,6 +6447,9 @@ msgstr "Édition"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Affichage"
|
msgstr "Affichage"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Paquet de préréglages"
|
msgstr "Paquet de préréglages"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"Language: hu\n"
|
"Language: hu\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -6541,9 +6541,6 @@ msgstr "Körvonal megjelenítése a kijelölt objektum körül a 3D nézetben."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Beállítások"
|
msgstr "Beállítások"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6552,6 +6549,9 @@ msgstr "Szerkesztés"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Nézet"
|
msgstr "Nézet"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Beállításcsomag"
|
msgstr "Beállításcsomag"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6543,9 +6543,6 @@ msgstr "Mostra il contorno attorno all'oggetto selezionato nella scena 3D."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Preferenze"
|
msgstr "Preferenze"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6554,6 +6551,9 @@ msgstr "Modifica"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Vista"
|
msgstr "Vista"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Pacchetto profili"
|
msgstr "Pacchetto profili"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6553,9 +6553,6 @@ msgstr "3Dシーンで選択したオブジェクトの周りにアウトライ
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "設定"
|
msgstr "設定"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6564,6 +6561,9 @@ msgstr "編集"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "表示"
|
msgstr "表示"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "プリセットバンドル"
|
msgstr "プリセットバンドル"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2025-06-02 17:12+0900\n"
|
"PO-Revision-Date: 2025-06-02 17:12+0900\n"
|
||||||
"Last-Translator: crwusiz <crwusiz@gmail.com>\n"
|
"Last-Translator: crwusiz <crwusiz@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6566,9 +6566,6 @@ msgstr "3D 장면에서 선택한 객체 주변에 윤곽선 표시"
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "기본 설정"
|
msgstr "기본 설정"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6577,6 +6574,9 @@ msgstr "편집"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "시점"
|
msgstr "시점"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "사전 설정 번들"
|
msgstr "사전 설정 번들"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-07-02 14:13+0300\n"
|
"PO-Revision-Date: 2026-07-02 14:13+0300\n"
|
||||||
"Last-Translator: Gintaras Kučinskas <sharanchius@gmail.com>\n"
|
"Last-Translator: Gintaras Kučinskas <sharanchius@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6528,9 +6528,6 @@ msgstr "Rodyti kontūrą aplink pasirinktą objektą 3D scenoje."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Parinktys"
|
msgstr "Parinktys"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6539,6 +6536,9 @@ msgstr "Redaguoti"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Vaizdas"
|
msgstr "Vaizdas"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Profilių rinkinys"
|
msgstr "Profilių rinkinys"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -7122,9 +7122,6 @@ msgstr "Toon een omtrek rond het geselecteerde object in de 3D-scène."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Voorkeuren"
|
msgstr "Voorkeuren"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -7133,6 +7130,9 @@ msgstr "Bewerken"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Weergave"
|
msgstr "Weergave"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Voorinstellingenbundel"
|
msgstr "Voorinstellingenbundel"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: OrcaSlicer 2.3.0-rc\n"
|
"Project-Id-Version: OrcaSlicer 2.3.0-rc\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Krzysztof Morga <<tlumaczeniebs@gmail.com>>\n"
|
"Last-Translator: Krzysztof Morga <<tlumaczeniebs@gmail.com>>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6689,9 +6689,6 @@ msgstr "Przełącza wyświetlanie konturu wokół zaznaczonego obiektu w scenie
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Preferencje"
|
msgstr "Preferencje"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6700,6 +6697,9 @@ msgstr "Edycja"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Widok"
|
msgstr "Widok"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Pakiet profili"
|
msgstr "Pakiet profili"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-07-26 11:14-0300\n"
|
"PO-Revision-Date: 2026-07-26 11:14-0300\n"
|
||||||
"Last-Translator: Alexandre Folle de Menezes\n"
|
"Last-Translator: Alexandre Folle de Menezes\n"
|
||||||
"Language-Team: Portuguese, Brazilian\n"
|
"Language-Team: Portuguese, Brazilian\n"
|
||||||
@@ -6363,9 +6363,6 @@ msgstr "Mostrar contorno ao redor do objeto selecionado na cena 3D."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Preferências"
|
msgstr "Preferências"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Editar"
|
msgstr "Editar"
|
||||||
@@ -6373,6 +6370,9 @@ msgstr "Editar"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Visualizar"
|
msgstr "Visualizar"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Pacote de Predefinições"
|
msgstr "Pacote de Predefinições"
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: OrcaSlicer V2.5.0\n"
|
"Project-Id-Version: OrcaSlicer V2.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-02-25 13:38+0300\n"
|
"PO-Revision-Date: 2026-02-25 13:38+0300\n"
|
||||||
"Last-Translator: Felix14_v2\n"
|
"Last-Translator: Felix14_v2\n"
|
||||||
"Language-Team: Felix14_v2 (ДС/ТГ: @felix14_v2, почта: aleks111001@list.ru), Andylg <andylg@yandex.ru>\n"
|
"Language-Team: Felix14_v2 (ДС/ТГ: @felix14_v2, почта: aleks111001@list.ru), Andylg <andylg@yandex.ru>\n"
|
||||||
@@ -6597,9 +6597,6 @@ msgstr "Отображение контура вокруг выбранных м
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Настройки"
|
msgstr "Настройки"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Правка"
|
msgstr "Правка"
|
||||||
@@ -6607,6 +6604,9 @@ msgstr "Правка"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Вид"
|
msgstr "Вид"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Пакет профилей"
|
msgstr "Пакет профилей"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"Language: sv\n"
|
"Language: sv\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -7205,9 +7205,6 @@ msgstr "Visa en kontur runt det markerade objektet i 3D-scenen."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Inställningar"
|
msgstr "Inställningar"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -7216,6 +7213,9 @@ msgstr "Redigera"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Vy"
|
msgstr "Vy"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Förinställningspaket"
|
msgstr "Förinställningspaket"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-06-19 13:40+0700\n"
|
"PO-Revision-Date: 2026-06-19 13:40+0700\n"
|
||||||
"Last-Translator: Icezaza\n"
|
"Last-Translator: Icezaza\n"
|
||||||
"Language-Team: Thai\n"
|
"Language-Team: Thai\n"
|
||||||
@@ -6520,9 +6520,6 @@ msgstr "แสดงเค้าร่างรอบๆ วัตถุที
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "การตั้งค่า"
|
msgstr "การตั้งค่า"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6531,6 +6528,9 @@ msgstr "แก้ไข"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "มุมมอง"
|
msgstr "มุมมอง"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "ชุดที่ตั้งไว้ล่วงหน้า"
|
msgstr "ชุดที่ตั้งไว้ล่วงหน้า"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-08-21 23:18+0300\n"
|
"PO-Revision-Date: 2026-08-21 23:18+0300\n"
|
||||||
"Last-Translator: GlauTech\n"
|
"Last-Translator: GlauTech\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6588,9 +6588,6 @@ msgstr "3D sahnede seçilen nesnenin etrafındaki ana hatları göster."
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Tercihler"
|
msgstr "Tercihler"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6599,6 +6596,9 @@ msgstr "Düzen"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Görünüm"
|
msgstr "Görünüm"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Ön ayar paketi"
|
msgstr "Ön ayar paketi"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: orcaslicerua\n"
|
"Project-Id-Version: orcaslicerua\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-07-17 16:25+0300\n"
|
"PO-Revision-Date: 2026-07-17 16:25+0300\n"
|
||||||
"Last-Translator: Andrij Mizyk <andm1zyk@proton.me>\n"
|
"Last-Translator: Andrij Mizyk <andm1zyk@proton.me>\n"
|
||||||
"Language-Team: Ukrainian\n"
|
"Language-Team: Ukrainian\n"
|
||||||
@@ -6557,9 +6557,6 @@ msgstr "Показувати контур навколо виділеного о
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Налаштування"
|
msgstr "Налаштування"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6568,6 +6565,9 @@ msgstr "Редагування"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Вигляд"
|
msgstr "Вигляд"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Набір пресетів"
|
msgstr "Набір пресетів"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2025-10-02 17:43+0700\n"
|
"PO-Revision-Date: 2025-10-02 17:43+0700\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: hainguyen.ts13@gmail.com\n"
|
"Language-Team: hainguyen.ts13@gmail.com\n"
|
||||||
@@ -6907,9 +6907,6 @@ msgstr "Hiện đường viền xung quanh vật thể đã chọn trong cảnh
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "Tùy chọn"
|
msgstr "Tùy chọn"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6918,6 +6915,9 @@ msgstr "Chỉnh sửa"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "Xem"
|
msgstr "Xem"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "Gói cài đặt sẵn"
|
msgstr "Gói cài đặt sẵn"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Slic3rPE\n"
|
"Project-Id-Version: Slic3rPE\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2026-06-11 12:37-0300\n"
|
"PO-Revision-Date: 2026-06-11 12:37-0300\n"
|
||||||
"Last-Translator: Handle <mail@bysb.net>\n"
|
"Last-Translator: Handle <mail@bysb.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6375,9 +6375,6 @@ msgstr "在3D场景中显示选中对象的轮廓"
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "偏好设置"
|
msgstr "偏好设置"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6386,6 +6383,9 @@ msgstr "编辑"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "视图"
|
msgstr "视图"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "预设包"
|
msgstr "预设包"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Orca Slicer\n"
|
"Project-Id-Version: Orca Slicer\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-09-22 12:39+0800\n"
|
"POT-Creation-Date: 2026-09-22 17:02+0800\n"
|
||||||
"PO-Revision-Date: 2025-11-28 13:48-0600\n"
|
"PO-Revision-Date: 2025-11-28 13:48-0600\n"
|
||||||
"Last-Translator: tntchn <15895303+tntchn@users.noreply.github.com>\n"
|
"Last-Translator: tntchn <15895303+tntchn@users.noreply.github.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
@@ -6505,9 +6505,6 @@ msgstr "在 3D 場景中顯示選定物件的輪廓"
|
|||||||
msgid "Preferences"
|
msgid "Preferences"
|
||||||
msgstr "偏好設定"
|
msgstr "偏好設定"
|
||||||
|
|
||||||
msgid "Open speed dial"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
# AI Translated
|
# AI Translated
|
||||||
msgctxt "Menu"
|
msgctxt "Menu"
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
@@ -6516,6 +6513,9 @@ msgstr "編輯"
|
|||||||
msgid "View"
|
msgid "View"
|
||||||
msgstr "視角"
|
msgstr "視角"
|
||||||
|
|
||||||
|
msgid "Open Speed Dial"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Preset Bundle"
|
msgid "Preset Bundle"
|
||||||
msgstr "設定檔組"
|
msgstr "設定檔組"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Eryone",
|
"name": "Eryone",
|
||||||
"version": "02.04.00.05",
|
"version": "02.04.00.06",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "Eryone configurations",
|
"description": "Eryone configurations",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
@@ -432,10 +432,18 @@
|
|||||||
"name": "Eryone ABS",
|
"name": "Eryone ABS",
|
||||||
"sub_path": "filament/Eryone ABS.json"
|
"sub_path": "filament/Eryone ABS.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone ABS+-HS @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone ABS+-HS @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone ABS-CF",
|
"name": "Eryone ABS-CF",
|
||||||
"sub_path": "filament/Eryone ABS-CF.json"
|
"sub_path": "filament/Eryone ABS-CF.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone ABS-GF @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone ABS-GF @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone ASA",
|
"name": "Eryone ASA",
|
||||||
"sub_path": "filament/Eryone ASA.json"
|
"sub_path": "filament/Eryone ASA.json"
|
||||||
@@ -444,6 +452,10 @@
|
|||||||
"name": "Eryone ASA-CF",
|
"name": "Eryone ASA-CF",
|
||||||
"sub_path": "filament/Eryone ASA-CF.json"
|
"sub_path": "filament/Eryone ASA-CF.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone ASA-HS @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone ASA-HS @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone PA",
|
"name": "Eryone PA",
|
||||||
"sub_path": "filament/Eryone PA.json"
|
"sub_path": "filament/Eryone PA.json"
|
||||||
@@ -460,18 +472,50 @@
|
|||||||
"name": "Eryone PETG",
|
"name": "Eryone PETG",
|
||||||
"sub_path": "filament/Eryone PETG.json"
|
"sub_path": "filament/Eryone PETG.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PETG HS @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PETG HS @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone PETG-CF",
|
"name": "Eryone PETG-CF",
|
||||||
"sub_path": "filament/Eryone PETG-CF.json"
|
"sub_path": "filament/Eryone PETG-CF.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PETG-GF @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PETG-GF @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PETG-Lite @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PETG-Lite @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PETG-Matte @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PETG-Matte @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PETG-Translucent @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PETG-Translucent @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone PLA",
|
"name": "Eryone PLA",
|
||||||
"sub_path": "filament/Eryone PLA.json"
|
"sub_path": "filament/Eryone PLA.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PLA+HS @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PLA+HS @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone PLA-CF",
|
"name": "Eryone PLA-CF",
|
||||||
"sub_path": "filament/Eryone PLA-CF.json"
|
"sub_path": "filament/Eryone PLA-CF.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PLA-Matte @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PLA-Matte @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone PLA-Matte HS @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone PLA-Matte HS @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Eryone PP",
|
"name": "Eryone PP",
|
||||||
"sub_path": "filament/Eryone PP.json"
|
"sub_path": "filament/Eryone PP.json"
|
||||||
@@ -488,6 +532,14 @@
|
|||||||
"name": "Eryone TPU",
|
"name": "Eryone TPU",
|
||||||
"sub_path": "filament/Eryone TPU.json"
|
"sub_path": "filament/Eryone TPU.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone petg-Galaxy @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone petg-Galaxy @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Eryone pla-Ultra Silk @Thinker X400 0.4 nozzle",
|
||||||
|
"sub_path": "filament/Eryone pla-Ultra Silk @Thinker X400 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "fdm_filament_pla",
|
"name": "fdm_filament_pla",
|
||||||
"sub_path": "filament/fdm_filament_pla.json"
|
"sub_path": "filament/fdm_filament_pla.json"
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone ABS+-HS @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "aUH1I90BFXa0C84r",
|
||||||
|
"filament_id": "OFRgjTRp",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone ABS+-HS @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"20"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.96"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"25"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"ABS"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"255"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"255"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone ABS-GF @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "WnsZC7HYi5Z1MOcn",
|
||||||
|
"filament_id": "OFenMm2Y",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone ABS-GF @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"20"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.96"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"18"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"ABS"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"265"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"265"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone ASA-HS @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "xw8zqUsFb2WVaSo1",
|
||||||
|
"filament_id": "OFIzY5sP",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone ASA-HS @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"20"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"20"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"ASA"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"90"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"260"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"260"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PETG HS @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "GtPiiNgHAnxrR9Tj",
|
||||||
|
"filament_id": "OFtqfvcE",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PETG HS @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.97"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"15"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"240"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"240"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
"14"
|
"14"
|
||||||
],
|
],
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Eryone PETG"
|
"Eryone PETG-CF"
|
||||||
],
|
],
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PETG-CF"
|
"PETG-CF"
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PETG-GF @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "S1FBfw93PzYJMhCa",
|
||||||
|
"filament_id": "OFbzOkXX",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PETG-GF @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.96"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"13"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"250"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"250"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PETG-Lite @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "CWHhUswq3j9XHAuC",
|
||||||
|
"filament_id": "OFyWb8AA",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PETG-Lite @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.9796"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"13"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"245"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"245"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PETG-Matte @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "pzceBG5k2u3X9TLO",
|
||||||
|
"filament_id": "OFSvr7Aj",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PETG-Matte @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"22"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"250"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"250"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PETG-Translucent @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "jN64L5SUnQB5dG1x",
|
||||||
|
"filament_id": "OFY2E8cd",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PETG-Translucent @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.99"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"24"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"215"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"215"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PLA+HS @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "AfUEns6VhCXsj9Ft",
|
||||||
|
"filament_id": "OFeRoHy3",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PLA+HS @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.99"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"18"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"210"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"210"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PLA-Matte @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "Ho1nQYsweqTTte0g",
|
||||||
|
"filament_id": "OFFMWFWL",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PLA-Matte @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.99"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"21"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"215"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"215"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone PLA-Matte HS @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "8W0yhuRu7OBJkSOS",
|
||||||
|
"filament_id": "OF9mNFSM",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone PLA-Matte HS @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"1.1"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"28"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"225"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"225"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone petg-Galaxy @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "R4BPYs8aAc9DFf0n",
|
||||||
|
"filament_id": "OFWDDu8u",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone petg-Galaxy @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"close_fan_the_first_x_layers": [
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"fan_max_speed": [
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.96"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"21"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"filament_type": [
|
||||||
|
"PETG"
|
||||||
|
],
|
||||||
|
"full_fan_speed_layer": [
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"70"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"245"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"245"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type": "filament",
|
||||||
|
"name": "Eryone pla-Ultra Silk @Thinker X400 0.4 nozzle",
|
||||||
|
"inherits": "Eryone Standard PLA",
|
||||||
|
"from": "system",
|
||||||
|
"setting_id": "jCbto64oaAKrDaN0",
|
||||||
|
"filament_id": "OF99Cc22",
|
||||||
|
"instantiation": "true",
|
||||||
|
"compatible_printers": [
|
||||||
|
"Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"filament_settings_id": [
|
||||||
|
"Eryone pla-Ultra Silk @Thinker X400 0.4 nozzle"
|
||||||
|
],
|
||||||
|
"fan_min_speed": [
|
||||||
|
"80"
|
||||||
|
],
|
||||||
|
"filament_end_gcode": [
|
||||||
|
"; filament end gcode \nSET_FAN_SPEED FAN=filter_fan SPEED=0"
|
||||||
|
],
|
||||||
|
"filament_flow_ratio": [
|
||||||
|
"0.97"
|
||||||
|
],
|
||||||
|
"filament_max_volumetric_speed": [
|
||||||
|
"15"
|
||||||
|
],
|
||||||
|
"filament_start_gcode": [
|
||||||
|
"; filament start gcode\nSET_FAN_SPEED FAN=filter_fan SPEED=1"
|
||||||
|
],
|
||||||
|
"hot_plate_temp": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"hot_plate_temp_initial_layer": [
|
||||||
|
"55"
|
||||||
|
],
|
||||||
|
"nozzle_temperature": [
|
||||||
|
"230"
|
||||||
|
],
|
||||||
|
"nozzle_temperature_initial_layer": [
|
||||||
|
"230"
|
||||||
|
],
|
||||||
|
"slow_down_layer_time": [
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"slow_down_min_speed": [
|
||||||
|
"15"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "WonderMaker",
|
"name": "WonderMaker",
|
||||||
"url": "",
|
"url": "",
|
||||||
"version": "02.04.00.03",
|
"version": "02.04.00.04",
|
||||||
"force_update": "0",
|
"force_update": "0",
|
||||||
"description": "WonderMaker configurations",
|
"description": "WonderMaker configurations",
|
||||||
"machine_model_list": [
|
"machine_model_list": [
|
||||||
@@ -432,12 +432,8 @@
|
|||||||
"sub_path": "machine/WonderMaker ZR 0.4 nozzle.json"
|
"sub_path": "machine/WonderMaker ZR 0.4 nozzle.json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "WonderMaker ZR Ultra 0.4 nozzle",
|
"name": "fdm_ultra_common",
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra 0.4 nozzle.json"
|
"sub_path": "machine/fdm_ultra_common.json"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "WonderMaker ZR Ultra S 0.4 nozzle",
|
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra S 0.4 nozzle.json"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "WonderMaker ZR 0.2 nozzle",
|
"name": "WonderMaker ZR 0.2 nozzle",
|
||||||
@@ -455,6 +451,10 @@
|
|||||||
"name": "WonderMaker ZR Ultra 0.2 nozzle",
|
"name": "WonderMaker ZR Ultra 0.2 nozzle",
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra 0.2 nozzle.json"
|
"sub_path": "machine/WonderMaker ZR Ultra 0.2 nozzle.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "WonderMaker ZR Ultra 0.4 nozzle",
|
||||||
|
"sub_path": "machine/WonderMaker ZR Ultra 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "WonderMaker ZR Ultra 0.6 nozzle",
|
"name": "WonderMaker ZR Ultra 0.6 nozzle",
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra 0.6 nozzle.json"
|
"sub_path": "machine/WonderMaker ZR Ultra 0.6 nozzle.json"
|
||||||
@@ -467,6 +467,10 @@
|
|||||||
"name": "WonderMaker ZR Ultra S 0.2 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.2 nozzle",
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra S 0.2 nozzle.json"
|
"sub_path": "machine/WonderMaker ZR Ultra S 0.2 nozzle.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "WonderMaker ZR Ultra S 0.4 nozzle",
|
||||||
|
"sub_path": "machine/WonderMaker ZR Ultra S 0.4 nozzle.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "WonderMaker ZR Ultra S 0.6 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.6 nozzle",
|
||||||
"sub_path": "machine/WonderMaker ZR Ultra S 0.6 nozzle.json"
|
"sub_path": "machine/WonderMaker ZR Ultra S 0.6 nozzle.json"
|
||||||
|
|||||||
Executable → Regular
+8
-7
@@ -1,22 +1,23 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra 0.2 nozzle",
|
"name": "WonderMaker ZR Ultra 0.2 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra 0.4 nozzle",
|
"inherits": "fdm_ultra_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "AX42zNj8YsJ94ilv",
|
"setting_id": "AX42zNj8YsJ94ilv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
|
"printer_model": "WonderMaker ZR Ultra",
|
||||||
|
"printer_variant": "0.2",
|
||||||
|
"default_print_profile": "0.10mm Standard @WonderMaker ZR Ultra 0.2 nozzle",
|
||||||
|
"default_bed_type": "4",
|
||||||
|
"max_layer_height": [
|
||||||
|
"0.14"
|
||||||
|
],
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2"
|
"0.2"
|
||||||
],
|
],
|
||||||
"printer_model": "WonderMaker ZR Ultra",
|
|
||||||
"printer_variant": "0.2",
|
|
||||||
"default_print_profile": "0.10mm Standard @WonderMaker ZR Ultra 0.2 nozzle",
|
|
||||||
"max_layer_height": [
|
|
||||||
"0.14"
|
|
||||||
],
|
|
||||||
"min_layer_height": [
|
"min_layer_height": [
|
||||||
"0.04"
|
"0.04"
|
||||||
],
|
],
|
||||||
|
|||||||
Executable → Regular
+1
-49
@@ -1,65 +1,17 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra 0.4 nozzle",
|
"name": "WonderMaker ZR Ultra 0.4 nozzle",
|
||||||
"inherits": "fdm_klipper_common",
|
"inherits": "fdm_ultra_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "xJBdCljSZVDINXnP",
|
"setting_id": "xJBdCljSZVDINXnP",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"printer_model": "WonderMaker ZR Ultra",
|
"printer_model": "WonderMaker ZR Ultra",
|
||||||
"default_print_profile": "0.20mm Standard @WonderMaker ZR Ultra",
|
"default_print_profile": "0.20mm Standard @WonderMaker ZR Ultra",
|
||||||
"default_bed_type": "4",
|
"default_bed_type": "4",
|
||||||
"default_filament_profile": [
|
|
||||||
"WonderMaker PLA Basic"
|
|
||||||
],
|
|
||||||
"single_extruder_multi_material": "0",
|
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4"
|
"0.4"
|
||||||
],
|
|
||||||
"printable_area": [
|
|
||||||
"0x0",
|
|
||||||
"300x0",
|
|
||||||
"300x270",
|
|
||||||
"0x270"
|
|
||||||
],
|
|
||||||
"bed_exclude_area": [],
|
|
||||||
"printable_height": "290",
|
|
||||||
"extruder_clearance_radius": "134",
|
|
||||||
"bed_mesh_min": [
|
|
||||||
"10",
|
|
||||||
"10"
|
|
||||||
],
|
|
||||||
"bed_mesh_max": [
|
|
||||||
"290",
|
|
||||||
"260"
|
|
||||||
],
|
|
||||||
"bed_mesh_probe_distance": [
|
|
||||||
"50",
|
|
||||||
"50"
|
|
||||||
],
|
|
||||||
"support_air_filtration": "0",
|
|
||||||
"support_chamber_temp_control": "0",
|
|
||||||
"machine_tool_change_time": "10",
|
|
||||||
"machine_load_filament_time": "0",
|
|
||||||
"machine_unload_filament_time": "0",
|
|
||||||
"retract_lift_below": [
|
|
||||||
"279",
|
|
||||||
"279",
|
|
||||||
"279",
|
|
||||||
"279"
|
|
||||||
],
|
|
||||||
"enable_long_retraction_when_cut": [
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0"
|
|
||||||
],
|
|
||||||
"long_retractions_when_cut": [
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
+8
-7
@@ -1,22 +1,23 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra 0.6 nozzle",
|
"name": "WonderMaker ZR Ultra 0.6 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra 0.4 nozzle",
|
"inherits": "fdm_ultra_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "6OWxZLFn3RD54QfX",
|
"setting_id": "6OWxZLFn3RD54QfX",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
|
"printer_model": "WonderMaker ZR Ultra",
|
||||||
|
"printer_variant": "0.6",
|
||||||
|
"default_print_profile": "0.30mm Standard @WonderMaker ZR Ultra 0.6 nozzle",
|
||||||
|
"default_bed_type": "4",
|
||||||
|
"max_layer_height": [
|
||||||
|
"0.42"
|
||||||
|
],
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.6",
|
"0.6",
|
||||||
"0.6",
|
"0.6",
|
||||||
"0.6",
|
"0.6",
|
||||||
"0.6"
|
"0.6"
|
||||||
],
|
],
|
||||||
"printer_model": "WonderMaker ZR Ultra",
|
|
||||||
"printer_variant": "0.6",
|
|
||||||
"default_print_profile": "0.30mm Standard @WonderMaker ZR Ultra 0.6 nozzle",
|
|
||||||
"max_layer_height": [
|
|
||||||
"0.42"
|
|
||||||
],
|
|
||||||
"min_layer_height": [
|
"min_layer_height": [
|
||||||
"0.12"
|
"0.12"
|
||||||
],
|
],
|
||||||
|
|||||||
Executable → Regular
+8
-7
@@ -1,22 +1,23 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra 0.8 nozzle",
|
"name": "WonderMaker ZR Ultra 0.8 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra 0.4 nozzle",
|
"inherits": "fdm_ultra_common",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "SY9snlsMkurhEYWP",
|
"setting_id": "SY9snlsMkurhEYWP",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
|
"printer_model": "WonderMaker ZR Ultra",
|
||||||
|
"printer_variant": "0.8",
|
||||||
|
"default_print_profile": "0.40mm Standard @WonderMaker ZR Ultra 0.8 nozzle",
|
||||||
|
"default_bed_type": "4",
|
||||||
|
"max_layer_height": [
|
||||||
|
"0.56"
|
||||||
|
],
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.8",
|
"0.8",
|
||||||
"0.8",
|
"0.8",
|
||||||
"0.8",
|
"0.8",
|
||||||
"0.8"
|
"0.8"
|
||||||
],
|
],
|
||||||
"printer_model": "WonderMaker ZR Ultra",
|
|
||||||
"printer_variant": "0.8",
|
|
||||||
"default_print_profile": "0.40mm Standard @WonderMaker ZR Ultra 0.8 nozzle",
|
|
||||||
"max_layer_height": [
|
|
||||||
"0.56"
|
|
||||||
],
|
|
||||||
"min_layer_height": [
|
"min_layer_height": [
|
||||||
"0.16"
|
"0.16"
|
||||||
],
|
],
|
||||||
|
|||||||
Executable → Regular
+5
-15
@@ -1,29 +1,19 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra S 0.2 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.2 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra S 0.4 nozzle",
|
"inherits": "WonderMaker ZR Ultra 0.2 nozzle",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "ZNAx3f7tX3DatiK1",
|
"setting_id": "ZNAx3f7tX3DatiK1",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
|
"printer_model": "WonderMaker ZR Ultra S",
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2",
|
"0.2",
|
||||||
"0.2"
|
"0.2"
|
||||||
],
|
],
|
||||||
"printer_model": "WonderMaker ZR Ultra S",
|
|
||||||
"printer_variant": "0.2",
|
|
||||||
"default_print_profile": "0.10mm Standard @WonderMaker ZR Ultra 0.2 nozzle",
|
"default_print_profile": "0.10mm Standard @WonderMaker ZR Ultra 0.2 nozzle",
|
||||||
"max_layer_height": [
|
"printer_variant": "0.2",
|
||||||
"0.14"
|
"support_air_filtration": "1",
|
||||||
],
|
"support_chamber_temp_control": "1"
|
||||||
"min_layer_height": [
|
|
||||||
"0.04"
|
|
||||||
],
|
|
||||||
"retraction_length": [
|
|
||||||
"0.4",
|
|
||||||
"0.4",
|
|
||||||
"0.4",
|
|
||||||
"0.4"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
+3
-50
@@ -1,65 +1,18 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra S 0.4 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.4 nozzle",
|
||||||
"inherits": "fdm_klipper_common",
|
"inherits": "WonderMaker ZR Ultra 0.4 nozzle",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "8xoZ6vYv9ws0J97u",
|
"setting_id": "8xoZ6vYv9ws0J97u",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"printer_model": "WonderMaker ZR Ultra S",
|
"printer_model": "WonderMaker ZR Ultra S",
|
||||||
"default_print_profile": "0.20mm Standard @WonderMaker ZR Ultra",
|
|
||||||
"default_bed_type": "4",
|
|
||||||
"default_filament_profile": [
|
|
||||||
"WonderMaker PLA Basic"
|
|
||||||
],
|
|
||||||
"single_extruder_multi_material": "0",
|
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4",
|
"0.4",
|
||||||
"0.4"
|
"0.4"
|
||||||
],
|
],
|
||||||
"printable_area": [
|
"default_print_profile": "0.20mm Standard @WonderMaker ZR Ultra",
|
||||||
"0x0",
|
|
||||||
"300x0",
|
|
||||||
"300x270",
|
|
||||||
"0x270"
|
|
||||||
],
|
|
||||||
"bed_exclude_area": [],
|
|
||||||
"printable_height": "290",
|
|
||||||
"extruder_clearance_radius": "134",
|
|
||||||
"bed_mesh_min": [
|
|
||||||
"10",
|
|
||||||
"10"
|
|
||||||
],
|
|
||||||
"bed_mesh_max": [
|
|
||||||
"290",
|
|
||||||
"260"
|
|
||||||
],
|
|
||||||
"bed_mesh_probe_distance": [
|
|
||||||
"50",
|
|
||||||
"50"
|
|
||||||
],
|
|
||||||
"support_air_filtration": "1",
|
"support_air_filtration": "1",
|
||||||
"support_chamber_temp_control": "1",
|
"support_chamber_temp_control": "1"
|
||||||
"machine_tool_change_time": "10",
|
|
||||||
"machine_load_filament_time": "0",
|
|
||||||
"machine_unload_filament_time": "0",
|
|
||||||
"retract_lift_below": [
|
|
||||||
"279",
|
|
||||||
"279",
|
|
||||||
"279",
|
|
||||||
"279"
|
|
||||||
],
|
|
||||||
"enable_long_retraction_when_cut": [
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0"
|
|
||||||
],
|
|
||||||
"long_retractions_when_cut": [
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0",
|
|
||||||
"0"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
+8
-21
@@ -1,32 +1,19 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra S 0.6 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.6 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra S 0.4 nozzle",
|
"inherits": "WonderMaker ZR Ultra 0.6 nozzle",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "xuJnOPTmSW1BMo6p",
|
"setting_id": "xuJnOPTmSW1BMo6p",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"printer_model": "WonderMaker ZR Ultra S",
|
"printer_model": "WonderMaker ZR Ultra S",
|
||||||
"default_print_profile": "0.30mm Standard @WonderMaker ZR Ultra 0.6 nozzle",
|
|
||||||
"printer_variant": "0.6",
|
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
|
"0.6",
|
||||||
|
"0.6",
|
||||||
|
"0.6",
|
||||||
"0.6"
|
"0.6"
|
||||||
],
|
],
|
||||||
"max_layer_height": [
|
"default_print_profile": "0.30mm Standard @WonderMaker ZR Ultra 0.6 nozzle",
|
||||||
"0.42"
|
"printer_variant": "0.6",
|
||||||
],
|
"support_air_filtration": "1",
|
||||||
"min_layer_height": [
|
"support_chamber_temp_control": "1"
|
||||||
"0.12"
|
|
||||||
],
|
|
||||||
"retraction_length": [
|
|
||||||
"1.4",
|
|
||||||
"1.4",
|
|
||||||
"1.4",
|
|
||||||
"1.4"
|
|
||||||
],
|
|
||||||
"retraction_minimum_travel": [
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
+8
-21
@@ -1,32 +1,19 @@
|
|||||||
{
|
{
|
||||||
"type": "machine",
|
"type": "machine",
|
||||||
"name": "WonderMaker ZR Ultra S 0.8 nozzle",
|
"name": "WonderMaker ZR Ultra S 0.8 nozzle",
|
||||||
"inherits": "WonderMaker ZR Ultra S 0.4 nozzle",
|
"inherits": "WonderMaker ZR Ultra 0.8 nozzle",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "0BPLKMspArilfkGT",
|
"setting_id": "0BPLKMspArilfkGT",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"printer_model": "WonderMaker ZR Ultra S",
|
"printer_model": "WonderMaker ZR Ultra S",
|
||||||
"default_print_profile": "0.40mm Standard @WonderMaker ZR Ultra 0.8 nozzle",
|
|
||||||
"printer_variant": "0.8",
|
|
||||||
"nozzle_diameter": [
|
"nozzle_diameter": [
|
||||||
|
"0.8",
|
||||||
|
"0.8",
|
||||||
|
"0.8",
|
||||||
"0.8"
|
"0.8"
|
||||||
],
|
],
|
||||||
"max_layer_height": [
|
"default_print_profile": "0.40mm Standard @WonderMaker ZR Ultra 0.8 nozzle",
|
||||||
"0.56"
|
"printer_variant": "0.8",
|
||||||
],
|
"support_air_filtration": "1",
|
||||||
"min_layer_height": [
|
"support_chamber_temp_control": "1"
|
||||||
"0.16"
|
|
||||||
],
|
|
||||||
"retract_length_toolchange": [
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3"
|
|
||||||
],
|
|
||||||
"retraction_length": [
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3",
|
|
||||||
"3"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"type": "machine",
|
||||||
|
"name": "fdm_ultra_common",
|
||||||
|
"inherits": "fdm_klipper_common",
|
||||||
|
"from": "system",
|
||||||
|
"instantiation": "false",
|
||||||
|
"default_bed_type": "4",
|
||||||
|
"default_filament_profile": [
|
||||||
|
"WonderMaker PLA Basic"
|
||||||
|
],
|
||||||
|
"single_extruder_multi_material": "0",
|
||||||
|
"enable_filament_mapping": "1",
|
||||||
|
"filament_swap_gcode": "M117 Swap filament for tool {next_extruder}\nPAUSE",
|
||||||
|
"nozzle_diameter": [
|
||||||
|
"0.4",
|
||||||
|
"0.4",
|
||||||
|
"0.4",
|
||||||
|
"0.4"
|
||||||
|
],
|
||||||
|
"printable_area": [
|
||||||
|
"0x0",
|
||||||
|
"300x0",
|
||||||
|
"300x270",
|
||||||
|
"0x270"
|
||||||
|
],
|
||||||
|
"bed_exclude_area": [],
|
||||||
|
"printable_height": "290",
|
||||||
|
"extruder_clearance_radius": "134",
|
||||||
|
"bed_mesh_min": [
|
||||||
|
"10",
|
||||||
|
"10"
|
||||||
|
],
|
||||||
|
"bed_mesh_max": [
|
||||||
|
"290",
|
||||||
|
"260"
|
||||||
|
],
|
||||||
|
"bed_mesh_probe_distance": [
|
||||||
|
"50",
|
||||||
|
"50"
|
||||||
|
],
|
||||||
|
"support_air_filtration": "0",
|
||||||
|
"support_chamber_temp_control": "0",
|
||||||
|
"machine_tool_change_time": "10",
|
||||||
|
"machine_load_filament_time": "0",
|
||||||
|
"machine_unload_filament_time": "0",
|
||||||
|
"retract_lift_below": [
|
||||||
|
"279",
|
||||||
|
"279",
|
||||||
|
"279",
|
||||||
|
"279"
|
||||||
|
],
|
||||||
|
"enable_long_retraction_when_cut": [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"long_retractions_when_cut": [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -575,7 +575,7 @@ function CapabilityCanRun(plugin, capability) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function IsPluginChecked(plugin) {
|
function IsPluginChecked(plugin) {
|
||||||
return GetStatus(plugin) === "Activated";
|
return plugin.is_loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
function HasMixedCapabilityState(plugin) {
|
function HasMixedCapabilityState(plugin) {
|
||||||
@@ -1347,6 +1347,8 @@ function StatusDescription(plugin) {
|
|||||||
return "This plugin is still loading.";
|
return "This plugin is still loading.";
|
||||||
case "Error":
|
case "Error":
|
||||||
return "This plugin is blocked until its error is fixed.";
|
return "This plugin is blocked until its error is fixed.";
|
||||||
|
case "RuntimeError":
|
||||||
|
return "This plugin is loaded but a capability reported an error.";
|
||||||
case "Inactive":
|
case "Inactive":
|
||||||
default:
|
default:
|
||||||
return "This plugin is inactive. Activate it to install or load it.";
|
return "This plugin is inactive. Activate it to install or load it.";
|
||||||
|
|||||||
@@ -424,6 +424,11 @@ body.pane-resizing {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-cell.status-runtimeerror {
|
||||||
|
color: var(--plugin-status-warn);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.status-cell.status-loading {
|
.status-cell.status-loading {
|
||||||
color: var(--plugin-status-warn);
|
color: var(--plugin-status-warn);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -680,6 +685,11 @@ body.pane-resizing {
|
|||||||
color: var(--plugin-status-danger);
|
color: var(--plugin-status-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-status-chip.status-runtimeerror {
|
||||||
|
background: var(--plugin-status-warn-bg);
|
||||||
|
color: var(--plugin-status-warn);
|
||||||
|
}
|
||||||
|
|
||||||
.detail-status-chip.status-loading {
|
.detail-status-chip.status-loading {
|
||||||
background: var(--plugin-status-warn-bg);
|
background: var(--plugin-status-warn-bg);
|
||||||
color: var(--plugin-status-warn);
|
color: var(--plugin-status-warn);
|
||||||
|
|||||||
@@ -331,6 +331,15 @@ modules:
|
|||||||
sha256: deedcabe339165214a3637df4c86a507aef0d793cf8774ff68735f4737e8ddbc
|
sha256: deedcabe339165214a3637df4c86a507aef0d793cf8774ff68735f4737e8ddbc
|
||||||
dest: external-packages/FFMPEG
|
dest: external-packages/FFMPEG
|
||||||
|
|
||||||
|
# libdatachannel v0.24.5
|
||||||
|
# The Git checkout includes the submodules that are missing from the
|
||||||
|
# GitHub source archive. DataChannel.cmake consumes it as SOURCE_DIR.
|
||||||
|
- type: git
|
||||||
|
url: https://github.com/paullouisageneau/libdatachannel.git
|
||||||
|
tag: v0.24.5
|
||||||
|
commit: 443f6934d9007eb7076ab7825ba330f355fcbead
|
||||||
|
dest: external-packages/DataChannel
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# Fallback archives for deps normally provided by the GNOME SDK.
|
# Fallback archives for deps normally provided by the GNOME SDK.
|
||||||
# These are only used if find_package() fails to locate them.
|
# These are only used if find_package() fails to locate them.
|
||||||
|
|||||||
@@ -7015,12 +7015,6 @@ int CLI::run(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sliced_info.sliced_plates.push_back(sliced_plate_info);
|
sliced_info.sliced_plates.push_back(sliced_plate_info);
|
||||||
} catch (const Slic3r::SlicingErrors &exs) {
|
|
||||||
const std::string message = print_fff ? print_fff->slicing_errors_message(exs) : std::string(exs.what());
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "found slicing or export error for partplate " << index+1 << ": " << message;
|
|
||||||
boost::nowide::cerr << message << std::endl;
|
|
||||||
record_exit_reson(outfile_dir, CLI_SLICING_ERROR, index+1, message, sliced_info);
|
|
||||||
flush_and_exit(CLI_SLICING_ERROR);
|
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "found slicing or export error for partplate "<<index+1 << std::endl;
|
BOOST_LOG_TRIVIAL(error) << "found slicing or export error for partplate "<<index+1 << std::endl;
|
||||||
boost::nowide::cerr << ex.what() << std::endl;
|
boost::nowide::cerr << ex.what() << std::endl;
|
||||||
|
|||||||
@@ -122,17 +122,19 @@ Vec2d printable_area_center(const DynamicPrintConfig &cfg)
|
|||||||
|
|
||||||
// Put the prime tower where the GUI and CLI would before slicing. The config default (x 15, y 220)
|
// Put the prime tower where the GUI and CLI would before slicing. The config default (x 15, y 220)
|
||||||
// lies off any bed shallower than the tower, and generation rejects an off-plate tower instead of
|
// lies off any bed shallower than the tower, and generation rejects an off-plate tower instead of
|
||||||
// exporting it. Beside the centred cube, clear of the edge exclusion strips some beds carry, then
|
// exporting it. Beside the cube at the bed centre, clear of the edge exclusion strips some beds
|
||||||
// pulled inside the printable outline by the tower's own estimated footprint, with a few mm of
|
// carry, with a few mm of clearance so the conflict checker never sees the two touch. The cube and
|
||||||
// clearance so the conflict checker never sees the two touch.
|
// the tower's estimated footprint are then pulled inside the printable outline as one rigid pair:
|
||||||
void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er)
|
// moving the tower alone would push it back onto the cube on a narrow bed. Returns that move for
|
||||||
|
// the cube.
|
||||||
|
Vec2d place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er)
|
||||||
{
|
{
|
||||||
const auto *area = cfg.option<ConfigOptionPoints>("printable_area");
|
const auto *area = cfg.option<ConfigOptionPoints>("printable_area");
|
||||||
if (area == nullptr || area->values.size() < 3)
|
if (area == nullptr || area->values.size() < 3)
|
||||||
return;
|
return Vec2d::Zero();
|
||||||
const WipeTowerFootprint footprint = estimate_wipe_tower_footprint(cfg, resolve_wipe_tower_type(cfg), {0, 1}, cfg.opt_float("layer_height"), 10.);
|
const WipeTowerFootprint footprint = estimate_wipe_tower_footprint(cfg, resolve_wipe_tower_type(cfg), {0, 1}, cfg.opt_float("layer_height"), 10.);
|
||||||
if (footprint.depth < EPSILON)
|
if (footprint.depth < EPSILON)
|
||||||
return;
|
return Vec2d::Zero();
|
||||||
const double margin = WIPE_TOWER_MARGIN + footprint.brim_width;
|
const double margin = WIPE_TOWER_MARGIN + footprint.brim_width;
|
||||||
// The position is the tower's own origin; a rotated tower extends from it in another
|
// The position is the tower's own origin; a rotated tower extends from it in another
|
||||||
// direction, so place the rotated box's extents rather than the origin.
|
// direction, so place the rotated box's extents rather than the origin.
|
||||||
@@ -143,13 +145,22 @@ void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er)
|
|||||||
const Vec2d size = unscale(local.max) - lo;
|
const Vec2d size = unscale(local.max) - lo;
|
||||||
Vec2d pos(center.x() + 5. + margin + 5. - lo.x(), center.y() - size.y() / 2. - lo.y());
|
Vec2d pos(center.x() + 5. + margin + 5. - lo.x(), center.y() - size.y() / 2. - lo.y());
|
||||||
box.translate(Point::new_scale(pos.x(), pos.y()));
|
box.translate(Point::new_scale(pos.x(), pos.y()));
|
||||||
const Vec2f move = WipeTower::move_box_inside_polygon(get_extents(box), Polygons{Polygon::new_scale(area->values)}, scaled<coord_t>(margin));
|
// A bed too small for the pair keeps the cube at its centre and places the tower alone.
|
||||||
pos += move.cast<double>();
|
const Polygons bed{Polygon::new_scale(area->values)};
|
||||||
|
const BoundingBox tower = get_extents(box);
|
||||||
|
BoundingBox pair = tower;
|
||||||
|
pair.merge(Point::new_scale(center.x() - 5., center.y() - 5.));
|
||||||
|
pair.merge(Point::new_scale(center.x() + 5., center.y() + 5.));
|
||||||
|
const Point room = get_extents(bed).size() - Point::new_scale(2. * margin, 2. * margin);
|
||||||
|
const bool rigid = pair.size().x() < room.x() && pair.size().y() < room.y();
|
||||||
|
const Vec2d move = WipeTower::move_box_inside_polygon(rigid ? pair : tower, bed, scaled<coord_t>(margin)).cast<double>();
|
||||||
|
pos += move;
|
||||||
cfg.option<ConfigOptionFloats>("wipe_tower_x", true)->values = {pos.x()};
|
cfg.option<ConfigOptionFloats>("wipe_tower_x", true)->values = {pos.x()};
|
||||||
cfg.option<ConfigOptionFloats>("wipe_tower_y", true)->values = {pos.y()};
|
cfg.option<ConfigOptionFloats>("wipe_tower_y", true)->values = {pos.y()};
|
||||||
|
return rigid ? move : Vec2d::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice one centered cube that switches from filament 1 to filament 2 partway up, so exactly one
|
// Slice one cube that switches from filament 1 to filament 2 partway up, so exactly one
|
||||||
// filament change fires, then export. The change drives the printer's own change_filament_gcode: on a
|
// filament change fires, then export. The change drives the printer's own change_filament_gcode: on a
|
||||||
// single-nozzle machine it rides the AMS prime tower (append_tcr), on a multi-nozzle machine it routes
|
// single-nozzle machine it rides the AMS prime tower (append_tcr), on a multi-nozzle machine it routes
|
||||||
// through the nozzle swap (set_extruder / append_tcr2) - the engine picks the path from the printer's
|
// through the nozzle swap (set_extruder / append_tcr2) - the engine picks the path from the printer's
|
||||||
@@ -157,10 +168,10 @@ void place_wipe_tower(DynamicPrintConfig &cfg, const Vec2d ¢er)
|
|||||||
// Slic3r::PlaceholderParserError from export.
|
// Slic3r::PlaceholderParserError from export.
|
||||||
std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl)
|
std::string slice_two_color_cube_and_export(DynamicPrintConfig cfg, bool is_bbl)
|
||||||
{
|
{
|
||||||
const Vec2d center = printable_area_center(cfg);
|
const Vec2d center = printable_area_center(cfg);
|
||||||
place_wipe_tower(cfg, center);
|
const Vec2d cube_min = center - Vec2d(5., 5.) + place_wipe_tower(cfg, center);
|
||||||
TriangleMesh m = make_cube(10, 10, 10);
|
TriangleMesh m = make_cube(10, 10, 10);
|
||||||
m.translate(float(center.x() - 5.), float(center.y() - 5.), 0.f);
|
m.translate(static_cast<float>(cube_min.x()), static_cast<float>(cube_min.y()), 0.f);
|
||||||
|
|
||||||
Model model;
|
Model model;
|
||||||
Print print;
|
Print print;
|
||||||
|
|||||||
@@ -3824,7 +3824,6 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
|||||||
ConfigOptionStrings *filament_color_type = project_config.option<ConfigOptionStrings>("filament_colour_type");
|
ConfigOptionStrings *filament_color_type = project_config.option<ConfigOptionStrings>("filament_colour_type");
|
||||||
ConfigOptionInts * filament_map = project_config.option<ConfigOptionInts>("filament_map");
|
ConfigOptionInts * filament_map = project_config.option<ConfigOptionInts>("filament_map");
|
||||||
ConfigOptionInts * filament_volume_map = project_config.option<ConfigOptionInts>("filament_volume_map");
|
ConfigOptionInts * filament_volume_map = project_config.option<ConfigOptionInts>("filament_volume_map");
|
||||||
|
|
||||||
// Snapshot and temporarily strip mixed filament slots so AMS sync operates on physical
|
// Snapshot and temporarily strip mixed filament slots so AMS sync operates on physical
|
||||||
// filaments only. A mixed slot is virtual and has no tray to sync against; leaving it in
|
// filaments only. A mixed slot is virtual and has no tray to sync against; leaving it in
|
||||||
// would let AMS mapping overwrite it and would break the physical-first slot ordering the
|
// would let AMS mapping overwrite it and would break the physical-first slot ordering the
|
||||||
|
|||||||
@@ -1704,25 +1704,6 @@ StringObjectException Print::check_multi_filament_valid(const Print& print)
|
|||||||
|
|
||||||
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
|
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
|
||||||
//BBS: refine seq-print validation logic
|
//BBS: refine seq-print validation logic
|
||||||
// The exception's own message is just "Errors"; the detail is in the per-object errors,
|
|
||||||
// whose object id is the PrintObject's.
|
|
||||||
std::string Print::slicing_errors_message(const SlicingErrors &errors) const
|
|
||||||
{
|
|
||||||
std::string message;
|
|
||||||
for (const SlicingError &error : errors.errors_) {
|
|
||||||
std::string object_name;
|
|
||||||
for (const PrintObject *object : m_objects)
|
|
||||||
if (object->id().id == error.objectId()) {
|
|
||||||
object_name = object->model_object()->name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!message.empty())
|
|
||||||
message += "\n";
|
|
||||||
message += object_name.empty() ? std::string(error.what()) : object_name + ": " + error.what();
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringObjectException Print::validate(std::vector<StringObjectException> *warnings, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
|
StringObjectException Print::validate(std::vector<StringObjectException> *warnings, Polygons* collison_polygons, std::vector<std::pair<Polygon, float>>* height_polygons) const
|
||||||
{
|
{
|
||||||
auto add_warning = [warnings](StringObjectException w) {
|
auto add_warning = [warnings](StringObjectException w) {
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class SlicingErrors;
|
|
||||||
|
|
||||||
class GCode;
|
class GCode;
|
||||||
class Layer;
|
class Layer;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
@@ -969,8 +967,6 @@ public:
|
|||||||
|
|
||||||
// Returns an empty string if valid, otherwise returns an error message.
|
// Returns an empty string if valid, otherwise returns an error message.
|
||||||
StringObjectException validate(std::vector<StringObjectException> *warnings = nullptr, Polygons* collison_polygons = nullptr, std::vector<std::pair<Polygon, float>>* height_polygons = nullptr) const override;
|
StringObjectException validate(std::vector<StringObjectException> *warnings = nullptr, Polygons* collison_polygons = nullptr, std::vector<std::pair<Polygon, float>>* height_polygons = nullptr) const override;
|
||||||
// The per-object messages of a SlicingErrors, each prefixed with its object's name.
|
|
||||||
std::string slicing_errors_message(const SlicingErrors &errors) const;
|
|
||||||
double skirt_first_layer_height() const;
|
double skirt_first_layer_height() const;
|
||||||
Flow brim_flow() const;
|
Flow brim_flow() const;
|
||||||
Flow skirt_flow() const;
|
Flow skirt_flow() const;
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/GLToolbar.hpp
|
GUI/GLToolbar.hpp
|
||||||
GUI/ImageDPIFrame.cpp
|
GUI/ImageDPIFrame.cpp
|
||||||
GUI/ImageDPIFrame.hpp
|
GUI/ImageDPIFrame.hpp
|
||||||
|
GUI/IMediaController.hpp
|
||||||
GUI/GUI_App.cpp
|
GUI/GUI_App.cpp
|
||||||
GUI/GUI_App.hpp
|
GUI/GUI_App.hpp
|
||||||
GUI/GUI_AuxiliaryList.cpp
|
GUI/GUI_AuxiliaryList.cpp
|
||||||
@@ -359,6 +360,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/MediaFilePanel.h
|
GUI/MediaFilePanel.h
|
||||||
GUI/MediaPlayCtrl.cpp
|
GUI/MediaPlayCtrl.cpp
|
||||||
GUI/MediaPlayCtrl.h
|
GUI/MediaPlayCtrl.h
|
||||||
|
GUI/WebRtcMediaController.cpp
|
||||||
|
GUI/WebRtcMediaController.hpp
|
||||||
GUI/MeshUtils.cpp
|
GUI/MeshUtils.cpp
|
||||||
GUI/MeshUtils.hpp
|
GUI/MeshUtils.hpp
|
||||||
GUI/ModelMall.cpp
|
GUI/ModelMall.cpp
|
||||||
@@ -552,6 +555,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/WebUserLoginDialog.hpp
|
GUI/WebUserLoginDialog.hpp
|
||||||
GUI/WebViewDialog.cpp
|
GUI/WebViewDialog.cpp
|
||||||
GUI/WebViewDialog.hpp
|
GUI/WebViewDialog.hpp
|
||||||
|
GUI/WebMediaController.hpp
|
||||||
|
GUI/WebMediaController.cpp
|
||||||
GUI/Widgets/AMSControl.cpp
|
GUI/Widgets/AMSControl.cpp
|
||||||
GUI/Widgets/AMSControl.hpp
|
GUI/Widgets/AMSControl.hpp
|
||||||
GUI/Widgets/AMSItem.cpp
|
GUI/Widgets/AMSItem.cpp
|
||||||
@@ -746,6 +751,7 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
Utils/NetworkAgentFactory.cpp
|
Utils/NetworkAgentFactory.cpp
|
||||||
Utils/ICloudServiceAgent.hpp
|
Utils/ICloudServiceAgent.hpp
|
||||||
Utils/IPrinterAgent.hpp
|
Utils/IPrinterAgent.hpp
|
||||||
|
Utils/ICameraSignalingChannel.hpp
|
||||||
Utils/OrcaCloudServiceAgent.cpp
|
Utils/OrcaCloudServiceAgent.cpp
|
||||||
Utils/OrcaCloudServiceAgent.hpp
|
Utils/OrcaCloudServiceAgent.hpp
|
||||||
Utils/OrcaPrinterAgent.cpp
|
Utils/OrcaPrinterAgent.cpp
|
||||||
@@ -916,7 +922,7 @@ else()
|
|||||||
set(_opengl_link_lib OpenGL::GL)
|
set(_opengl_link_lib OpenGL::GL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html glad ${_opengl_link_lib} hidapi mdns ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise pybind11::embed)
|
target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo libvgcode md4c-html glad ${_opengl_link_lib} hidapi mdns ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto LibDataChannel::LibDataChannel noise::noise pybind11::embed)
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
# Linux finds wxWidgets in module mode, whose include dirs and definitions
|
# Linux finds wxWidgets in module mode, whose include dirs and definitions
|
||||||
@@ -973,29 +979,32 @@ endif ()
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# Static FFmpeg from the deps install: nothing to bundle into the .app,
|
# Static FFmpeg from the deps install: nothing to bundle into the .app,
|
||||||
# no rpath/install_name handling. Order matters: avcodec -> swscale -> avutil.
|
# no rpath/install_name handling. Order matters: avformat -> avcodec -> swscale -> avutil.
|
||||||
|
find_library(LIBAVFORMAT_LIBRARY NAMES libavformat.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBAVCODEC_LIBRARY NAMES libavcodec.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVCODEC_LIBRARY NAMES libavcodec.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBSWSCALE_LIBRARY NAMES libswscale.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBSWSCALE_LIBRARY NAMES libswscale.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBAVUTIL_LIBRARY NAMES libavutil.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVUTIL_LIBRARY NAMES libavutil.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
if (NOT LIBAVFORMAT_LIBRARY OR NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
||||||
message(FATAL_ERROR "Static FFmpeg (libavcodec.a/libswscale.a/libavutil.a) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps — FFMPEG builds static-only on macOS.")
|
message(FATAL_ERROR "Static FFmpeg (libavformat.a/libavcodec.a/libswscale.a/libavutil.a) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps — FFMPEG builds static-only on macOS.")
|
||||||
endif ()
|
endif ()
|
||||||
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
target_link_libraries(libslic3r_gui ${LIBAVFORMAT_LIBRARY} ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
# Prebuilt shared FFmpeg from the deps install. Windows has no pkg-config,
|
# Prebuilt shared FFmpeg from the deps install. Windows has no pkg-config,
|
||||||
# so resolve the import libraries out of the deps prefix directly; the DLLs
|
# so resolve the import libraries out of the deps prefix directly; the DLLs
|
||||||
# are copied next to the executable by the top level CMakeLists.
|
# are copied next to the executable by the top level CMakeLists.
|
||||||
|
find_library(LIBAVFORMAT_LIBRARY NAMES avformat PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBAVCODEC_LIBRARY NAMES avcodec PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVCODEC_LIBRARY NAMES avcodec PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBSWSCALE_LIBRARY NAMES swscale PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBSWSCALE_LIBRARY NAMES swscale PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
find_library(LIBAVUTIL_LIBRARY NAMES avutil PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
find_library(LIBAVUTIL_LIBRARY NAMES avutil PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
||||||
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
if (NOT LIBAVCODEC_LIBRARY OR NOT LIBSWSCALE_LIBRARY OR NOT LIBAVUTIL_LIBRARY)
|
||||||
message(FATAL_ERROR "FFmpeg (avcodec/swscale/avutil) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps.")
|
message(FATAL_ERROR "FFmpeg (avcodec/swscale/avutil) not found under ${CMAKE_PREFIX_PATH}/lib. Rebuild the deps.")
|
||||||
endif ()
|
endif ()
|
||||||
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
target_link_libraries(libslic3r_gui ${LIBAVFORMAT_LIBRARY} ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
||||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
||||||
else ()
|
else ()
|
||||||
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
||||||
|
libavformat
|
||||||
libavcodec
|
libavcodec
|
||||||
libswscale
|
libswscale
|
||||||
libavutil
|
libavutil
|
||||||
|
|||||||
@@ -45,6 +45,25 @@ int AVVideoDecoder::open(Bambu_StreamInfo const &info)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AVVideoDecoder::open(AVCodecParameters const ¶meters)
|
||||||
|
{
|
||||||
|
if (avcodec_parameters_to_context(codec_ctx_, ¶meters) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
auto codec = avcodec_find_decoder(codec_ctx_->codec_id);
|
||||||
|
if (codec == nullptr) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: unsupported codec!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (avcodec_open2(codec_ctx_, codec, nullptr) < 0) {
|
||||||
|
fprintf(stderr, "AVVideoDecoder: could not open codec\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_ = av_frame_alloc();
|
||||||
|
return frame_ == nullptr ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int AVVideoDecoder::decode(const Bambu_Sample &sample)
|
int AVVideoDecoder::decode(const Bambu_Sample &sample)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -71,6 +90,14 @@ int AVVideoDecoder::decode(const Bambu_Sample &sample)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AVVideoDecoder::decode(const AVPacket &packet)
|
||||||
|
{
|
||||||
|
int ret = avcodec_send_packet(codec_ctx_, &packet);
|
||||||
|
if (ret == 0)
|
||||||
|
got_frame_ = avcodec_receive_frame(codec_ctx_, frame_) == 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int AVVideoDecoder::flush()
|
int AVVideoDecoder::flush()
|
||||||
{
|
{
|
||||||
int ret = avcodec_send_packet(codec_ctx_, nullptr);
|
int ret = avcodec_send_packet(codec_ctx_, nullptr);
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int open(Bambu_StreamInfo const &info);
|
int open(Bambu_StreamInfo const &info);
|
||||||
|
int open(AVCodecParameters const ¶meters);
|
||||||
|
|
||||||
int decode(Bambu_Sample const &sample);
|
int decode(Bambu_Sample const &sample);
|
||||||
|
int decode(AVPacket const &packet);
|
||||||
|
|
||||||
int flush();
|
int flush();
|
||||||
|
|
||||||
@@ -34,6 +36,14 @@ public:
|
|||||||
|
|
||||||
bool toWxBitmap(wxBitmap &bitmap, wxSize const & size);
|
bool toWxBitmap(wxBitmap &bitmap, wxSize const & size);
|
||||||
|
|
||||||
|
// Native size of the most recently decoded frame, or an unspecified size if
|
||||||
|
// nothing has decoded yet. Lets a caller learn the video dimensions when the
|
||||||
|
// container/probe could not report them up front.
|
||||||
|
wxSize decoded_frame_size() const
|
||||||
|
{
|
||||||
|
return got_frame_ && frame_ ? wxSize{frame_->width, frame_->height} : wxSize{};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AVCodecContext *codec_ctx_ = nullptr;
|
AVCodecContext *codec_ctx_ = nullptr;
|
||||||
AVFrame * frame_ = nullptr;
|
AVFrame * frame_ = nullptr;
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ void SelectMObjectPopup::update_user_devices()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_bind_machine_list.clear();
|
m_bind_machine_list.clear();
|
||||||
m_bind_machine_list = dev->get_my_machine_list();
|
m_bind_machine_list = dev->get_my_machine_list(dev->get_current_printer_agent_id());
|
||||||
|
|
||||||
//sort list
|
//sort list
|
||||||
std::vector<std::pair<std::string, MachineObject*>> user_machine_list;
|
std::vector<std::pair<std::string, MachineObject*>> user_machine_list;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevConfig.h"
|
#include "DeviceCore/DevConfig.h"
|
||||||
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
#include "DeviceCore/DevExtruderSystem.h"
|
#include "DeviceCore/DevExtruderSystem.h"
|
||||||
#include "DeviceCore/DevFilaBlackList.h"
|
#include "DeviceCore/DevFilaBlackList.h"
|
||||||
#include "DeviceCore/DevFilaSystem.h"
|
#include "DeviceCore/DevFilaSystem.h"
|
||||||
@@ -1647,18 +1648,8 @@ bool CalibrationPresetPage::is_blocking_printing()
|
|||||||
if (obj_ == nullptr) return true;
|
if (obj_ == nullptr) return true;
|
||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
const auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||||
auto target_model = obj_->printer_type;
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
|
|
||||||
if (source_model != target_model) {
|
|
||||||
std::vector<std::string> compatible_machine = obj_->get_compatible_machine();
|
|
||||||
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
|
|
||||||
if (it == compatible_machine.end()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CalibrationPresetPage::is_nozzle_info_synced() const
|
bool CalibrationPresetPage::is_nozzle_info_synced() const
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ wxEND_EVENT_TABLE()
|
|||||||
|
|
||||||
wxDEFINE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
|
wxDEFINE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
|
||||||
wxDEFINE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
|
wxDEFINE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
|
||||||
wxDEFINE_EVENT(EVT_CAM_SOURCE_CHANGE, wxCommandEvent);
|
|
||||||
|
|
||||||
#define CAMERAPOPUP_CLICK_INTERVAL 20
|
#define CAMERAPOPUP_CLICK_INTERVAL 20
|
||||||
|
|
||||||
@@ -102,34 +101,6 @@ CameraPopup::CameraPopup(wxWindow *parent)
|
|||||||
top_sizer->Add(0, 0, wxALL, 0);
|
top_sizer->Add(0, 0, wxALL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Orca: custom IP camera source — lets the user point Live Video at any camera URL (Orca feature; not in the reference)
|
|
||||||
m_custom_camera_input_confirm = new Button(m_panel, _L("Enable"));
|
|
||||||
m_custom_camera_input_confirm->SetBackgroundColor(wxColour(38, 166, 154));
|
|
||||||
m_custom_camera_input_confirm->SetBorderColor(wxColour(38, 166, 154));
|
|
||||||
m_custom_camera_input_confirm->SetTextColor(wxColour(0xFFFFFE));
|
|
||||||
m_custom_camera_input_confirm->SetFont(Label::Body_14);
|
|
||||||
m_custom_camera_input_confirm->SetMinSize(wxSize(FromDIP(90), FromDIP(30)));
|
|
||||||
m_custom_camera_input_confirm->SetPosition(wxDefaultPosition);
|
|
||||||
m_custom_camera_input_confirm->SetCornerRadius(FromDIP(12));
|
|
||||||
m_custom_camera_input = new TextInput(m_panel, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxDefaultSize);
|
|
||||||
m_custom_camera_input->GetTextCtrl()->SetHint(_L("Hostname or IP"));
|
|
||||||
m_custom_camera_input->GetTextCtrl()->SetFont(Label::Body_14);
|
|
||||||
m_custom_camera_hint = new wxStaticText(m_panel, wxID_ANY, _L("Custom camera source"));
|
|
||||||
m_custom_camera_hint->Wrap(-1);
|
|
||||||
m_custom_camera_hint->SetFont(Label::Head_14);
|
|
||||||
m_custom_camera_hint->SetForegroundColour(TEXT_COL);
|
|
||||||
|
|
||||||
m_custom_camera_input_confirm->Bind(wxEVT_BUTTON, &CameraPopup::on_camera_source_changed, this);
|
|
||||||
|
|
||||||
if (!wxGetApp().app_config->get("camera", "custom_source").empty()) {
|
|
||||||
m_custom_camera_input->GetTextCtrl()->SetValue(wxGetApp().app_config->get("camera", "custom_source"));
|
|
||||||
set_custom_cam_button_state(wxGetApp().app_config->get("camera", "enable_custom_source") == "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
top_sizer->Add(m_custom_camera_hint, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
|
|
||||||
top_sizer->Add(0, 0, wxALL, 0);
|
|
||||||
top_sizer->Add(m_custom_camera_input, 2, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, FromDIP(5));
|
|
||||||
top_sizer->Add(m_custom_camera_input_confirm, 1, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5));
|
|
||||||
main_sizer->Add(top_sizer, 0, wxALL, FromDIP(10));
|
main_sizer->Add(top_sizer, 0, wxALL, FromDIP(10));
|
||||||
|
|
||||||
auto url = wxString(L"https://www.orcaslicer.com/wiki/"); // Orca: neutral wiki link (vendor URL removed)
|
auto url = wxString(L"https://www.orcaslicer.com/wiki/"); // Orca: neutral wiki link (vendor URL removed)
|
||||||
@@ -184,37 +155,6 @@ void CameraPopup::sdcard_absent_hint()
|
|||||||
GetEventHandler()->ProcessEvent(evt);
|
GetEventHandler()->ProcessEvent(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraPopup::on_camera_source_changed(wxCommandEvent &event)
|
|
||||||
{
|
|
||||||
if (m_obj && !m_custom_camera_input->GetTextCtrl()->IsEmpty()) {
|
|
||||||
handle_camera_source_change();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CameraPopup::handle_camera_source_change()
|
|
||||||
{
|
|
||||||
m_custom_camera_enabled = !m_custom_camera_enabled;
|
|
||||||
|
|
||||||
set_custom_cam_button_state(m_custom_camera_enabled);
|
|
||||||
|
|
||||||
wxGetApp().app_config->set("camera", "custom_source", m_custom_camera_input->GetTextCtrl()->GetValue().ToStdString());
|
|
||||||
wxGetApp().app_config->set("camera", "enable_custom_source", m_custom_camera_enabled);
|
|
||||||
|
|
||||||
wxCommandEvent evt(EVT_CAM_SOURCE_CHANGE);
|
|
||||||
evt.SetEventObject(this);
|
|
||||||
GetEventHandler()->ProcessEvent(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CameraPopup::set_custom_cam_button_state(bool state)
|
|
||||||
{
|
|
||||||
m_custom_camera_enabled = state;
|
|
||||||
auto stateColour = state ? wxColour(170, 0, 0) : wxColour(38, 166, 154);
|
|
||||||
auto stateText = state ? "Disable" : "Enable";
|
|
||||||
m_custom_camera_input_confirm->SetBackgroundColor(stateColour);
|
|
||||||
m_custom_camera_input_confirm->SetBorderColor(stateColour);
|
|
||||||
m_custom_camera_input_confirm->SetLabel(_L(stateText));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CameraPopup::on_switch_recording(wxCommandEvent& event)
|
void CameraPopup::on_switch_recording(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
if (!m_obj) return;
|
if (!m_obj) return;
|
||||||
|
|||||||
@@ -15,14 +15,12 @@
|
|||||||
#include "Widgets/SwitchButton.hpp"
|
#include "Widgets/SwitchButton.hpp"
|
||||||
#include "Widgets/RadioBox.hpp"
|
#include "Widgets/RadioBox.hpp"
|
||||||
#include "Widgets/PopupWindow.hpp"
|
#include "Widgets/PopupWindow.hpp"
|
||||||
#include "Widgets/TextInput.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
wxDECLARE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
|
wxDECLARE_EVENT(EVT_VCAMERA_SWITCH, wxMouseEvent);
|
||||||
wxDECLARE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
|
wxDECLARE_EVENT(EVT_SDCARD_ABSENT_HINT, wxCommandEvent);
|
||||||
wxDECLARE_EVENT(EVT_CAM_SOURCE_CHANGE, wxCommandEvent);
|
|
||||||
|
|
||||||
class CameraPopup : public PopupWindow
|
class CameraPopup : public PopupWindow
|
||||||
{
|
{
|
||||||
@@ -53,9 +51,6 @@ protected:
|
|||||||
void on_switch_recording(wxCommandEvent& event);
|
void on_switch_recording(wxCommandEvent& event);
|
||||||
void on_set_resolution();
|
void on_set_resolution();
|
||||||
void sdcard_absent_hint();
|
void sdcard_absent_hint();
|
||||||
void on_camera_source_changed(wxCommandEvent& event);
|
|
||||||
void handle_camera_source_change();
|
|
||||||
void set_custom_cam_button_state(bool state);
|
|
||||||
|
|
||||||
wxWindow * create_item_radiobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left);
|
wxWindow * create_item_radiobox(wxString title, wxWindow *parent, wxString tooltip, int padding_left);
|
||||||
void select_curr_radiobox(int btn_idx);
|
void select_curr_radiobox(int btn_idx);
|
||||||
@@ -76,10 +71,10 @@ private:
|
|||||||
wxStaticText* m_text_liveview_retry;
|
wxStaticText* m_text_liveview_retry;
|
||||||
SwitchButton* m_switch_liveview_retry;
|
SwitchButton* m_switch_liveview_retry;
|
||||||
#endif //BBL_RELEASE_TO_PUBLIC
|
#endif //BBL_RELEASE_TO_PUBLIC
|
||||||
wxStaticText* m_custom_camera_hint;
|
// wxStaticText* m_custom_camera_hint;
|
||||||
TextInput* m_custom_camera_input;
|
// TextInput* m_custom_camera_input;
|
||||||
Button* m_custom_camera_input_confirm;
|
// Button* m_custom_camera_input_confirm;
|
||||||
bool m_custom_camera_enabled{ false };
|
// bool m_custom_camera_enabled{ false };
|
||||||
wxStaticText* m_text_resolution;
|
wxStaticText* m_text_resolution;
|
||||||
wxWindow* m_resolution_options[RESOLUTION_OPTIONS_NUM];
|
wxWindow* m_resolution_options[RESOLUTION_OPTIONS_NUM];
|
||||||
wxScrolledWindow *m_panel;
|
wxScrolledWindow *m_panel;
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, cons
|
|||||||
sizer_connect = new wxBoxSizer(wxHORIZONTAL);
|
sizer_connect = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
m_textCtrl_code = new TextInput(this, wxEmptyString);
|
m_textCtrl_code = new TextInput(this, wxEmptyString);
|
||||||
m_textCtrl_code->GetTextCtrl()->SetMaxLength(10);
|
// OrcaSonar uses a 12-character base32 access code. Keep this field long
|
||||||
|
// enough for it while retaining the existing validation for LAN codes.
|
||||||
|
m_textCtrl_code->GetTextCtrl()->SetMaxLength(12);
|
||||||
m_textCtrl_code->SetFont(Label::Body_14);
|
m_textCtrl_code->SetFont(Label::Body_14);
|
||||||
m_textCtrl_code->SetCornerRadius(FromDIP(5));
|
m_textCtrl_code->SetCornerRadius(FromDIP(5));
|
||||||
m_textCtrl_code->SetSize(wxSize(FromDIP(330), FromDIP(40)));
|
m_textCtrl_code->SetSize(wxSize(FromDIP(330), FromDIP(40)));
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "DevConfigUtil.h"
|
#include "DevConfigUtil.h"
|
||||||
|
|
||||||
|
#include "slic3r/GUI/DeviceManager.hpp"
|
||||||
|
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include "../I18N.hpp"
|
#include "../I18N.hpp"
|
||||||
@@ -41,6 +43,19 @@ static void _toolhead_translation_markers()
|
|||||||
|
|
||||||
std::string DevPrinterConfigUtil::m_resource_file_path = "";
|
std::string DevPrinterConfigUtil::m_resource_file_path = "";
|
||||||
|
|
||||||
|
bool DevPrinterConfigUtil::is_printer_model_compatible(const std::string& source_model, MachineObject& machine)
|
||||||
|
{
|
||||||
|
const std::string& target_model = machine.printer_type;
|
||||||
|
if (is_optional_printer_model_id(source_model) || is_optional_printer_model_id(target_model))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (source_model == target_model)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const auto compatible_machine = machine.get_compatible_machine();
|
||||||
|
return std::find(compatible_machine.begin(), compatible_machine.end(), source_model) != compatible_machine.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, std::string> DevPrinterConfigUtil::get_all_model_id_with_name()
|
std::map<std::string, std::string> DevPrinterConfigUtil::get_all_model_id_with_name()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class MachineObject;
|
||||||
|
|
||||||
/// Toolhead component type (extruder / nozzle / hotend)
|
/// Toolhead component type (extruder / nozzle / hotend)
|
||||||
enum class ToolHeadComponent {
|
enum class ToolHeadComponent {
|
||||||
Extruder,
|
Extruder,
|
||||||
@@ -59,6 +61,10 @@ public:
|
|||||||
/*printer*/
|
/*printer*/
|
||||||
// info
|
// info
|
||||||
static std::map<std::string, std::string> get_all_model_id_with_name();
|
static std::map<std::string, std::string> get_all_model_id_with_name();
|
||||||
|
// A printer agent may not know the physical model. Keep that case optional so
|
||||||
|
// model compatibility checks do not turn missing identity into a hard error.
|
||||||
|
static bool is_printer_model_compatible(const std::string& source_model, MachineObject& machine);
|
||||||
|
static bool is_optional_printer_model_id(const std::string& model_id) { return model_id.empty(); }
|
||||||
static std::string get_printer_type(const std::string& type_str) { return get_value_from_config<std::string>(type_str, "printer_type"); }
|
static std::string get_printer_type(const std::string& type_str) { return get_value_from_config<std::string>(type_str, "printer_type"); }
|
||||||
static std::string get_printer_display_name(const std::string& type_str) { return get_value_from_config<std::string>(type_str, "display_name"); }
|
static std::string get_printer_display_name(const std::string& type_str) { return get_value_from_config<std::string>(type_str, "display_name"); }
|
||||||
static std::string get_printer_series_str(std::string type_str) { return get_value_from_config<std::string>(type_str, "printer_series"); }
|
static std::string get_printer_series_str(std::string type_str) { return get_value_from_config<std::string>(type_str, "printer_series"); }
|
||||||
|
|||||||
@@ -762,9 +762,9 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
|||||||
{
|
{
|
||||||
curr_tray->remain = -1;
|
curr_tray->remain = -1;
|
||||||
}
|
}
|
||||||
if (tray_it->contains("tray_slot_placeholder")) {
|
// The tray objects are reused across status updates. Reset this
|
||||||
curr_tray->is_slot_placeholder = true;
|
// state when a previously empty slot receives a filament again.
|
||||||
}
|
curr_tray->is_slot_placeholder = tray_it->contains("tray_slot_placeholder");
|
||||||
int ams_id_int = 0;
|
int ams_id_int = 0;
|
||||||
int tray_id_int = 0;
|
int tray_id_int = 0;
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include "DevManager.h"
|
#include "DevManager.h"
|
||||||
|
#include "CloudProvider.hpp"
|
||||||
#include "DevUtil.h"
|
#include "DevUtil.h"
|
||||||
|
|
||||||
// TODO: remove this include
|
// TODO: remove this include
|
||||||
@@ -14,6 +15,8 @@
|
|||||||
|
|
||||||
#include "libslic3r/Time.hpp"
|
#include "libslic3r/Time.hpp"
|
||||||
|
|
||||||
|
#include "IPrinterAgent.hpp"
|
||||||
|
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -264,6 +267,10 @@ namespace Slic3r
|
|||||||
/* update userMachineList info */
|
/* update userMachineList info */
|
||||||
auto it = userMachineList.find(dev_id);
|
auto it = userMachineList.find(dev_id);
|
||||||
if (it != userMachineList.end()) {
|
if (it != userMachineList.end()) {
|
||||||
|
// A reused entry may have been created while another printer agent was active.
|
||||||
|
// The response was obtained through the current agent, so move ownership with
|
||||||
|
// the entry; otherwise agent-scoped lists hide it after a preset switch.
|
||||||
|
it->second->printer_agent_id = get_current_printer_agent_id();
|
||||||
if (it->second->get_dev_ip() != dev_ip ||
|
if (it->second->get_dev_ip() != dev_ip ||
|
||||||
it->second->bind_state != bind_state ||
|
it->second->bind_state != bind_state ||
|
||||||
it->second->bind_sec_link != sec_link ||
|
it->second->bind_sec_link != sec_link ||
|
||||||
@@ -294,6 +301,9 @@ namespace Slic3r
|
|||||||
// update properties
|
// update properties
|
||||||
/* ip changed */
|
/* ip changed */
|
||||||
obj = it->second;
|
obj = it->second;
|
||||||
|
// A reused LAN entry may have been discovered while another printer agent was
|
||||||
|
// active. The current discovery message establishes ownership for this agent.
|
||||||
|
obj->printer_agent_id = get_current_printer_agent_id();
|
||||||
|
|
||||||
if (obj->get_dev_ip().compare(dev_ip) != 0) {
|
if (obj->get_dev_ip().compare(dev_ip) != 0) {
|
||||||
if ( connection_name.empty() ) {
|
if ( connection_name.empty() ) {
|
||||||
@@ -405,6 +415,9 @@ namespace Slic3r
|
|||||||
auto it = localMachineList.find(machine.dev_id);
|
auto it = localMachineList.find(machine.dev_id);
|
||||||
if (it != localMachineList.end()) {
|
if (it != localMachineList.end()) {
|
||||||
obj = it->second;
|
obj = it->second;
|
||||||
|
// insert_local_device is called by the active agent, so a reused entry must follow
|
||||||
|
// that agent as well; otherwise the agent-scoped printer list hides it.
|
||||||
|
obj->printer_agent_id = get_current_printer_agent_id();
|
||||||
} else {
|
} else {
|
||||||
obj = new MachineObject(this, m_agent, machine.dev_name, machine.dev_id, machine.dev_ip);
|
obj = new MachineObject(this, m_agent, machine.dev_name, machine.dev_id, machine.dev_ip);
|
||||||
obj->printer_agent_id = get_current_printer_agent_id();
|
obj->printer_agent_id = get_current_printer_agent_id();
|
||||||
@@ -497,7 +510,7 @@ namespace Slic3r
|
|||||||
|
|
||||||
MachineObject* DeviceManager::get_my_machine(std::string dev_id)
|
MachineObject* DeviceManager::get_my_machine(std::string dev_id)
|
||||||
{
|
{
|
||||||
auto list = get_my_machine_list();
|
auto list = get_my_machine_list(get_current_printer_agent_id());
|
||||||
auto it = list.find(dev_id);
|
auto it = list.find(dev_id);
|
||||||
if (it != list.end())
|
if (it != list.end())
|
||||||
{
|
{
|
||||||
@@ -534,25 +547,15 @@ namespace Slic3r
|
|||||||
OnSelectedMachineChanged(previous_selected_machine, selected_machine);
|
OnSelectedMachineChanged(previous_selected_machine, selected_machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::clear_other_devices(const std::string& target_agent_id)
|
void DeviceManager::clear_other_devices()
|
||||||
{
|
{
|
||||||
// why: on agent swap, keep "My Devices" but drop the transient "Other Devices"
|
// Device entries are now scoped by printer_agent_id when they are presented. Keep
|
||||||
// Those belong to the previous agent's network scan; the new agent's start_discovery re-populates its own.
|
// agent-owned discoveries across a switch so agents without automatic discovery (and
|
||||||
//
|
// plugins whose devices have not received an access code yet) do not lose their list.
|
||||||
// Also drop "My Devices" stamped by a different agent than the one we're swapping to
|
// Entries without an owner are legacy/unscoped and cannot safely be shown.
|
||||||
// (target_agent_id, passed by the caller since the live agent hasn't been repointed yet
|
|
||||||
// at this point): otherwise a device first discovered under agent A survives every swap
|
|
||||||
// with a stale printer_agent_id, stays hidden from every agent's filtered list, and only
|
|
||||||
// gets re-tagged if something happens to delete and re-create it (e.g. account logout).
|
|
||||||
// Dropping it here instead lets the new agent's start_discovery re-insert and re-stamp it
|
|
||||||
// like any other fresh device.
|
|
||||||
const auto my = get_my_machine_list();
|
|
||||||
for (auto it = localMachineList.begin(); it != localMachineList.end();)
|
for (auto it = localMachineList.begin(); it != localMachineList.end();)
|
||||||
{
|
{
|
||||||
const bool is_my_device = my.find(it->first) != my.end();
|
if (!it->second || it->second->printer_agent_id.empty())
|
||||||
const bool agent_mismatch = !target_agent_id.empty() && it->second &&
|
|
||||||
it->second->printer_agent_id != target_agent_id;
|
|
||||||
if (!is_my_device || agent_mismatch)
|
|
||||||
{
|
{
|
||||||
delete it->second;
|
delete it->second;
|
||||||
it = localMachineList.erase(it);
|
it = localMachineList.erase(it);
|
||||||
@@ -568,8 +571,22 @@ namespace Slic3r
|
|||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id
|
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id
|
||||||
<< " cur_selected=" << selected_machine;
|
<< " cur_selected=" << selected_machine;
|
||||||
auto my_machine_list = get_my_machine_list();
|
auto my_machine_list = get_my_machine_list(get_current_printer_agent_id());
|
||||||
auto it = my_machine_list.find(dev_id);
|
auto it = my_machine_list.find(dev_id);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: set_selected_machine lookup dev_id=" << dev_id
|
||||||
|
<< " found=" << (it != my_machine_list.end())
|
||||||
|
<< " my_machine_count=" << my_machine_list.size()
|
||||||
|
<< " current_agent=" << get_current_printer_agent_id()
|
||||||
|
<< " provider=" << GUI::wxGetApp().get_printer_cloud_provider();
|
||||||
|
if (it != my_machine_list.end() && it->second) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: target machine dev_id=" << it->second->get_dev_id()
|
||||||
|
<< " printer_agent_id=" << it->second->printer_agent_id
|
||||||
|
<< " connection_type=" << it->second->connection_type()
|
||||||
|
<< " dev_connection_type=" << it->second->dev_connection_type;
|
||||||
|
} else if (!dev_id.empty()) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "Orca diagnostic: target machine was not found in the current agent's machine list";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// disconnect last if dev_id difference from previous one
|
// disconnect last if dev_id difference from previous one
|
||||||
auto last_selected = my_machine_list.find(selected_machine);
|
auto last_selected = my_machine_list.find(selected_machine);
|
||||||
@@ -580,7 +597,9 @@ namespace Slic3r
|
|||||||
m_agent->disconnect_printer();
|
m_agent->disconnect_printer();
|
||||||
}
|
}
|
||||||
else if (last_selected->second->connection_type() == "cloud") {
|
else if (last_selected->second->connection_type() == "cloud") {
|
||||||
m_agent->set_user_selected_machine("");
|
const int result = m_agent->set_user_selected_machine("");
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: cleared previous cloud selection dev_id="
|
||||||
|
<< selected_machine << " result=" << result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +651,9 @@ namespace Slic3r
|
|||||||
{
|
{
|
||||||
// diff dev_id, cloud => set_user_selected_machine(new)
|
// diff dev_id, cloud => set_user_selected_machine(new)
|
||||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new cloud machine, dev_id =" << dev_id;
|
BOOST_LOG_TRIVIAL(info) << "set_selected_machine: select new cloud machine, dev_id =" << dev_id;
|
||||||
m_agent->set_user_selected_machine(dev_id);
|
const int result = m_agent->set_user_selected_machine(dev_id);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: set new cloud selection dev_id="
|
||||||
|
<< dev_id << " result=" << result;
|
||||||
it->second->reset();
|
it->second->reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -660,6 +681,8 @@ namespace Slic3r
|
|||||||
|
|
||||||
selected_machine = dev_id;
|
selected_machine = dev_id;
|
||||||
record_user_last_machine(selected_machine);
|
record_user_last_machine(selected_machine);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: DeviceManager selection complete selected_machine="
|
||||||
|
<< selected_machine;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,7 +713,9 @@ namespace Slic3r
|
|||||||
dev_list.push_back(it->first);
|
dev_list.push_back(it->first);
|
||||||
BOOST_LOG_TRIVIAL(trace) << "add_user_subscribe: " << it->first;
|
BOOST_LOG_TRIVIAL(trace) << "add_user_subscribe: " << it->first;
|
||||||
}
|
}
|
||||||
m_agent->add_subscribe(dev_list);
|
const int result = m_agent->add_subscribe(dev_list);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: add_user_subscribe count=" << dev_list.size()
|
||||||
|
<< " result=" << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -703,7 +728,9 @@ namespace Slic3r
|
|||||||
dev_list.push_back(it->first);
|
dev_list.push_back(it->first);
|
||||||
BOOST_LOG_TRIVIAL(trace) << "del_user_subscribe: " << it->first;
|
BOOST_LOG_TRIVIAL(trace) << "del_user_subscribe: " << it->first;
|
||||||
}
|
}
|
||||||
m_agent->del_subscribe(dev_list);
|
const int result = m_agent->del_subscribe(dev_list);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: del_user_subscribe count=" << dev_list.size()
|
||||||
|
<< " result=" << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::subscribe_device_list(std::vector<std::string> dev_list)
|
void DeviceManager::subscribe_device_list(std::vector<std::string> dev_list)
|
||||||
@@ -822,7 +849,23 @@ namespace Slic3r
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
json j = json::parse(body);
|
json j = json::parse(body);
|
||||||
const std::string provider = GUI::wxGetApp().get_printer_cloud_provider();
|
|
||||||
|
const bool has_request_context = j.contains("provider") && j.contains("agent_id") && j.contains("generation");
|
||||||
|
const std::string provider = j.contains("provider") ? j["provider"].get<std::string>()
|
||||||
|
: GUI::wxGetApp().get_printer_cloud_provider();
|
||||||
|
const std::string agent_id = j.contains("agent_id") ? j["agent_id"].get<std::string>()
|
||||||
|
: get_current_printer_agent_id();
|
||||||
|
const std::uint64_t generation = j.value("generation", std::uint64_t(0));
|
||||||
|
|
||||||
|
if (has_request_context &&
|
||||||
|
(provider != GUI::wxGetApp().get_printer_cloud_provider() ||
|
||||||
|
agent_id != get_current_printer_agent_id() ||
|
||||||
|
generation != (m_agent ? m_agent->get_user_machine_list_generation() : 0))) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": ignoring stale response provider="
|
||||||
|
<< provider << " agent_id=" << agent_id
|
||||||
|
<< " generation=" << generation;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if !BBL_RELEASE_TO_PUBLIC
|
#if !BBL_RELEASE_TO_PUBLIC
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << j;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << j;
|
||||||
@@ -845,11 +888,14 @@ namespace Slic3r
|
|||||||
/* update field */
|
/* update field */
|
||||||
obj = iter->second;
|
obj = iter->second;
|
||||||
obj->set_dev_id(dev_id);
|
obj->set_dev_id(dev_id);
|
||||||
|
// A device can be rediscovered by a different agent after a preset
|
||||||
|
// switch while retaining the same MachineObject instance.
|
||||||
|
obj->printer_agent_id = agent_id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
obj = new MachineObject(this, m_agent, "", "", "");
|
obj = new MachineObject(this, m_agent, "", "", "");
|
||||||
obj->printer_agent_id = get_current_printer_agent_id();
|
obj->printer_agent_id = agent_id;
|
||||||
if (m_agent)
|
if (m_agent)
|
||||||
{
|
{
|
||||||
obj->set_bind_status(m_agent->get_user_name(provider));
|
obj->set_bind_status(m_agent->get_user_name(provider));
|
||||||
@@ -864,6 +910,12 @@ namespace Slic3r
|
|||||||
|
|
||||||
if (!obj) continue;
|
if (!obj) continue;
|
||||||
|
|
||||||
|
// Orca cloud printers are only ever delivered through this REST
|
||||||
|
// account list; tag them so DeviceManager's cloud/lan branches
|
||||||
|
// (subscribe + deselect in set_selected_machine) treat them right.
|
||||||
|
if (provider == ORCA_CLOUD_PROVIDER)
|
||||||
|
obj->dev_connection_type = "cloud";
|
||||||
|
|
||||||
if (!elem["dev_id"].is_null())
|
if (!elem["dev_id"].is_null())
|
||||||
obj->set_dev_id(elem["dev_id"].get<std::string>());
|
obj->set_dev_id(elem["dev_id"].get<std::string>());
|
||||||
if (!elem["dev_name"].is_null())
|
if (!elem["dev_name"].is_null())
|
||||||
@@ -895,6 +947,12 @@ namespace Slic3r
|
|||||||
acc_code.erase(std::remove(acc_code.begin(), acc_code.end(), '\n'), acc_code.end());
|
acc_code.erase(std::remove(acc_code.begin(), acc_code.end(), '\n'), acc_code.end());
|
||||||
obj->set_access_code(acc_code);
|
obj->set_access_code(acc_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: parsed cloud machine dev_id=" << dev_id
|
||||||
|
<< " name=" << obj->get_dev_name()
|
||||||
|
<< " agent_id=" << obj->printer_agent_id
|
||||||
|
<< " connection_type=" << obj->connection_type()
|
||||||
|
<< " online=" << obj->m_is_online;
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove MachineObject from userMachineList
|
//remove MachineObject from userMachineList
|
||||||
@@ -910,6 +968,9 @@ namespace Slic3r
|
|||||||
iterat++;
|
iterat++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: parse_user_print_info complete provider=" << provider
|
||||||
|
<< " parsed_count=" << new_list.size()
|
||||||
|
<< " stored_count=" << userMachineList.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
@@ -926,10 +987,14 @@ namespace Slic3r
|
|||||||
unsigned int http_code;
|
unsigned int http_code;
|
||||||
std::string body;
|
std::string body;
|
||||||
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: get_user_print_info provider=" << provider
|
||||||
|
<< " result=" << result << " http_code=" << http_code
|
||||||
|
<< " body_bytes=" << body.size();
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
// parse_user_print_info and on_machine_alive (SSDP for discovery) both mutate the same userMachineList map.
|
// parse_user_print_info and on_machine_alive (SSDP for discovery) both mutate the same userMachineList map.
|
||||||
// on_machine_alive mutates the map on the UI thread, do the same for parse_user_print_info.
|
// on_machine_alive mutates the map on the UI thread, do the same for parse_user_print_info.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: queueing parse_user_print_info on UI thread";
|
||||||
Slic3r::GUI::wxGetApp().CallAfter([this, body]() { parse_user_print_info(body); });
|
Slic3r::GUI::wxGetApp().CallAfter([this, body]() { parse_user_print_info(body); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,10 +74,9 @@ public:
|
|||||||
void erase_user_machine(std::string dev_id) { userMachineList.erase(dev_id); }
|
void erase_user_machine(std::string dev_id) { userMachineList.erase(dev_id); }
|
||||||
void clean_user_info(bool keep_local_selection = false);
|
void clean_user_info(bool keep_local_selection = false);
|
||||||
|
|
||||||
// target_agent_id: id of the agent being swapped to (empty = no agent-mismatch check,
|
// Retain agent-owned LAN discoveries across a switch; the active-agent list filter keeps
|
||||||
// just the original "drop Other Devices" behavior). Pass the incoming agent's id, not the
|
// entries from other agents hidden while allowing them to reappear when switched back.
|
||||||
// live one - this runs before the live agent is repointed.
|
void clear_other_devices();
|
||||||
void clear_other_devices(const std::string& target_agent_id = "");
|
|
||||||
|
|
||||||
void load_last_machine();
|
void load_last_machine();
|
||||||
void update_user_machine_list_info(const std::string& provider);
|
void update_user_machine_list_info(const std::string& provider);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "libslic3r/Time.hpp"
|
#include "libslic3r/Time.hpp"
|
||||||
#include "libslic3r/Thread.hpp"
|
#include "libslic3r/Thread.hpp"
|
||||||
|
#include "slic3r/Utils/Http.hpp"
|
||||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||||
#include "GuiColor.hpp"
|
#include "GuiColor.hpp"
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
#include "DeviceCore/DevStatus.h"
|
#include "DeviceCore/DevStatus.h"
|
||||||
#include "DeviceCore/DevUpgrade.h"
|
#include "DeviceCore/DevUpgrade.h"
|
||||||
|
|
||||||
|
#include "IPrinterAgent.hpp"
|
||||||
|
|
||||||
#define CALI_DEBUG
|
#define CALI_DEBUG
|
||||||
#define MINUTE_30 1800000 //ms
|
#define MINUTE_30 1800000 //ms
|
||||||
@@ -373,8 +375,22 @@ NozzleVolumeType convert_to_nozzle_type(const std::string &str)
|
|||||||
wxString MachineObject::get_printer_type_display_str() const
|
wxString MachineObject::get_printer_type_display_str() const
|
||||||
{
|
{
|
||||||
std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type);
|
std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type);
|
||||||
|
|
||||||
|
// Bambu printers use m_resource_file_path + "/printers/" + type_str + ".json", which is a semantic that only works for their profiles.
|
||||||
|
// For any other profile, we can simply consult preset bundle if the model_id exists.
|
||||||
|
if (display_name.empty()) {
|
||||||
|
for (const auto& [vendor_id, vendor] : GUI::wxGetApp().preset_bundle->vendors) {
|
||||||
|
for (const auto& model : vendor.models) {
|
||||||
|
if (printer_type == model.model_id)
|
||||||
|
display_name = model.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!display_name.empty())
|
if (!display_name.empty())
|
||||||
return display_name;
|
return display_name;
|
||||||
|
else if (printer_type == "orcasonar")
|
||||||
|
return "OrcaSonar Printer";
|
||||||
else
|
else
|
||||||
return _L("Unknown");
|
return _L("Unknown");
|
||||||
}
|
}
|
||||||
@@ -1341,7 +1357,6 @@ int MachineObject::command_get_access_code() {
|
|||||||
return this->publish_json(j);
|
return this->publish_json(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MachineObject::command_request_push_all(bool request_now)
|
int MachineObject::command_request_push_all(bool request_now)
|
||||||
{
|
{
|
||||||
auto curr_time = std::chrono::system_clock::now();
|
auto curr_time = std::chrono::system_clock::now();
|
||||||
@@ -1473,26 +1488,20 @@ int MachineObject::command_upgrade_module(std::string url, std::string module_ty
|
|||||||
|
|
||||||
int MachineObject::command_xyz_abs()
|
int MachineObject::command_xyz_abs()
|
||||||
{
|
{
|
||||||
return this->publish_gcode("G90 \n");
|
if (!m_agent) return -1;
|
||||||
|
return command_with_dialog(m_agent->command_xyz_abs(get_dev_id(), MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_auto_leveling()
|
int MachineObject::command_auto_leveling()
|
||||||
{
|
{
|
||||||
return this->publish_gcode("G29 \n");
|
if (!m_agent) return -1;
|
||||||
|
return command_with_dialog(m_agent->command_auto_leveling(get_dev_id(), MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_go_home()
|
int MachineObject::command_go_home()
|
||||||
{
|
{
|
||||||
if (m_support_mqtt_homing)
|
if (!m_agent) return -1;
|
||||||
{
|
return command_with_dialog(m_agent->command_go_home(get_dev_id(), this->is_in_printing(), m_support_mqtt_homing, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
json j;
|
|
||||||
j["print"]["command"] = "back_to_center";
|
|
||||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
|
||||||
return this->publish_json(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gcode command
|
|
||||||
return this->is_in_printing() ? this->publish_gcode("G28 X\n") : this->publish_gcode("G28 \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_task_partskip(std::vector<int> part_ids)
|
int MachineObject::command_task_partskip(std::vector<int> part_ids)
|
||||||
@@ -1614,23 +1623,14 @@ int MachineObject::command_stop_buzzer()
|
|||||||
|
|
||||||
int MachineObject::command_set_bed(int temp)
|
int MachineObject::command_set_bed(int temp)
|
||||||
{
|
{
|
||||||
if (m_support_mqtt_bet_ctrl)
|
if (!m_agent) return -1;
|
||||||
{
|
return command_with_dialog(m_agent->command_set_bed(get_dev_id(), temp, m_support_mqtt_bet_ctrl, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
json j;
|
|
||||||
j["print"]["command"] = "set_bed_temp";
|
|
||||||
j["print"]["temp"] = temp;
|
|
||||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
|
||||||
return this->publish_json(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string gcode_str = (boost::format("M140 S%1%\n") % temp).str();
|
|
||||||
return this->publish_gcode(gcode_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_set_nozzle(int temp)
|
int MachineObject::command_set_nozzle(int temp)
|
||||||
{
|
{
|
||||||
std::string gcode_str = (boost::format("M104 S%1%\n") % temp).str();
|
if (!m_agent) return -1;
|
||||||
return this->publish_gcode(gcode_str);
|
return command_with_dialog(m_agent->command_set_nozzle(get_dev_id(), temp, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_set_nozzle_new(int nozzle_id, int temp)
|
int MachineObject::command_set_nozzle_new(int nozzle_id, int temp)
|
||||||
@@ -1735,9 +1735,8 @@ int MachineObject::command_ams_user_settings(bool start_read_opt, bool tray_read
|
|||||||
|
|
||||||
int MachineObject::command_ams_calibrate(int ams_id)
|
int MachineObject::command_ams_calibrate(int ams_id)
|
||||||
{
|
{
|
||||||
std::string gcode_cmd = (boost::format("M620 C%1% \n") % ams_id).str();
|
if (!m_agent) return -1;
|
||||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
return command_with_dialog(m_agent->command_ams_calibrate(get_dev_id(), ams_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
return this->publish_gcode(gcode_cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_ams_filament_settings(int ams_id, int slot_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 MachineObject::command_ams_filament_settings(int ams_id, int slot_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)
|
||||||
@@ -1775,9 +1774,8 @@ int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::s
|
|||||||
|
|
||||||
int MachineObject::command_ams_refresh_rfid(std::string tray_id)
|
int MachineObject::command_ams_refresh_rfid(std::string tray_id)
|
||||||
{
|
{
|
||||||
std::string gcode_cmd = (boost::format("M620 R%1% \n") % tray_id).str();
|
if (!m_agent) return -1;
|
||||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
return command_with_dialog(m_agent->command_ams_refresh_rfid(get_dev_id(), tray_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
return this->publish_gcode(gcode_cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id)
|
int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id)
|
||||||
@@ -1790,12 +1788,17 @@ int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id)
|
|||||||
return this->publish_json(j);
|
return this->publish_json(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MachineObject::command_start_camera()
|
||||||
|
{
|
||||||
|
if (!m_agent) return -1;
|
||||||
|
return m_agent->command_start_camera(get_dev_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int MachineObject::command_ams_select_tray(std::string tray_id)
|
int MachineObject::command_ams_select_tray(std::string tray_id)
|
||||||
{
|
{
|
||||||
std::string gcode_cmd = (boost::format("M620 P%1% \n") % tray_id).str();
|
if (!m_agent) return -1;
|
||||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
return command_with_dialog(m_agent->command_ams_select_tray(get_dev_id(), tray_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||||
return this->publish_gcode(gcode_cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_ams_control(std::string action)
|
int MachineObject::command_ams_control(std::string action)
|
||||||
@@ -1954,47 +1957,10 @@ int MachineObject::command_ams_air_print_detect(bool air_print_detect)
|
|||||||
|
|
||||||
int MachineObject::command_axis_control(std::string axis, double unit, double input_val, int speed)
|
int MachineObject::command_axis_control(std::string axis, double unit, double input_val, int speed)
|
||||||
{
|
{
|
||||||
if (m_support_mqtt_axis_control)
|
if (!m_agent) return -1;
|
||||||
{
|
return command_with_dialog(m_agent->command_axis_control(get_dev_id(), axis, unit, input_val, speed, is_core_xy(),
|
||||||
int dir = input_val > 0 ? 1 : -1;
|
m_support_mqtt_axis_control, MachineObject::m_sequence_id++,
|
||||||
// i3-arch printers move the bed for Y/Z, so the on-screen direction is
|
is_lan_mode_printer()));
|
||||||
// reversed — same negation the g-code fallback below applies.
|
|
||||||
if (!is_core_xy() && (axis.compare("Y") == 0 || axis.compare("Z") == 0)) {
|
|
||||||
dir = -dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
json j;
|
|
||||||
j["print"]["command"] = "xyz_ctrl";
|
|
||||||
j["print"]["axis"] = axis;
|
|
||||||
j["print"]["dir"] = dir;
|
|
||||||
j["print"]["mode"] = (std::abs(input_val) >= 10) ? 1 : 0;
|
|
||||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
|
||||||
return this->publish_json(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
double value = input_val;
|
|
||||||
if (!is_core_xy()) {
|
|
||||||
if ( axis.compare("Y") == 0
|
|
||||||
|| axis.compare("Z") == 0) {
|
|
||||||
value = -1.0 * input_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char cmd[256];
|
|
||||||
if (axis.compare("X") == 0
|
|
||||||
|| axis.compare("Y") == 0
|
|
||||||
|| axis.compare("Z") == 0) {
|
|
||||||
sprintf(cmd, "M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %s%0.1f F%d\nM1002 pop_ref_mode\nM211 R\n", axis.c_str(), value * unit, speed);
|
|
||||||
}
|
|
||||||
else if (axis.compare("E") == 0) {
|
|
||||||
sprintf(cmd, "M83 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return this->publish_gcode(cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachineObject::command_extruder_control(int nozzle_id, double val)
|
int MachineObject::command_extruder_control(int nozzle_id, double val)
|
||||||
@@ -2619,7 +2585,12 @@ void MachineObject::reset()
|
|||||||
vt_slot.erase(vt_slot.begin() + 1);
|
vt_slot.erase(vt_slot.begin() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subtask_ = nullptr;
|
// why: reset reuses MachineObject, so release its lazy subtask
|
||||||
|
// before dropping the pointer to prevent reconnect leaks.
|
||||||
|
if (subtask_) {
|
||||||
|
delete subtask_;
|
||||||
|
subtask_ = nullptr;
|
||||||
|
}
|
||||||
has_extra_flow_type = false;
|
has_extra_flow_type = false;
|
||||||
m_partskip_ids.clear();
|
m_partskip_ids.clear();
|
||||||
}
|
}
|
||||||
@@ -2629,15 +2600,52 @@ void MachineObject::set_print_state(std::string status)
|
|||||||
print_status = status;
|
print_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why: printer agents can report progress without BBL cloud task identity.
|
||||||
|
void MachineObject::update_print_progress(const json& value)
|
||||||
|
{
|
||||||
|
if (value.is_string())
|
||||||
|
mc_print_percent = stoi(value.get<std::string>());
|
||||||
|
else if (value.is_number_integer())
|
||||||
|
mc_print_percent = value.get<int>();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (BBLSubTask* curr_task = get_subtask())
|
||||||
|
curr_task->task_progress = mc_print_percent;
|
||||||
|
}
|
||||||
|
|
||||||
int MachineObject::connect(bool use_openssl)
|
int MachineObject::connect(bool use_openssl)
|
||||||
{
|
{
|
||||||
if (get_dev_ip().empty()) return -1;
|
if (get_dev_ip().empty()) return -1;
|
||||||
std::string username = "bblp";
|
std::string username = m_agent ? m_agent->default_lan_username() : std::string();
|
||||||
std::string password = get_access_code();
|
std::string password = get_access_code();
|
||||||
|
|
||||||
|
std::string port;
|
||||||
|
std::string host = Http::get_host_from_url(get_dev_ip(), &port);
|
||||||
|
std::string ca_file;
|
||||||
|
|
||||||
|
if (GUI::wxGetApp().preset_bundle) {
|
||||||
|
const auto& config = GUI::wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
if (port.empty())
|
||||||
|
port = config.opt_string("printhost_port");
|
||||||
|
ca_file = config.opt_string("printhost_cafile");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host.empty())
|
||||||
|
host = get_dev_ip();
|
||||||
|
|
||||||
if (m_agent) {
|
if (m_agent) {
|
||||||
try {
|
try {
|
||||||
return m_agent->connect_printer(get_dev_id(), get_dev_ip(), username, password, use_openssl);
|
PrinterConnectionParams params{
|
||||||
|
get_dev_id(),
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
use_openssl,
|
||||||
|
ca_file
|
||||||
|
};
|
||||||
|
return m_agent->connect_printer(params);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -2742,6 +2750,14 @@ int MachineObject::publish_json(const json& json_item, int qos, int flag)
|
|||||||
BOOST_LOG_TRIVIAL(error) << "publish_json: " << json_item.dump() << " code: " << rtn;
|
BOOST_LOG_TRIVIAL(error) << "publish_json: " << json_item.dump() << " code: " << rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why: the agent is the only thing that knows what it can translate, so it reports
|
||||||
|
// not-supported in its return value and this - the single funnel every command_* builder
|
||||||
|
// passes through - is the one place that turns it into something the user sees. No list of
|
||||||
|
// unsupported commands is needed anywhere: an agent that has no case for a command says so.
|
||||||
|
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE) {
|
||||||
|
show_unsupported_dlg(rtn);
|
||||||
|
}
|
||||||
|
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3046,6 +3062,13 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
}
|
}
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (j.contains("info"))
|
||||||
|
parse_new_info2(j["info"]);
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "parse_json: failed to parse OrcaSonar capability info";
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (auto ptr = m_fila_system->GetAmsFirmwareSwitch().lock()) {
|
if (auto ptr = m_fila_system->GetAmsFirmwareSwitch().lock()) {
|
||||||
ptr->ParseFirmwareSwitch(j);
|
ptr->ParseFirmwareSwitch(j);
|
||||||
@@ -3298,10 +3321,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
print_type = jj["print_type"].get<std::string>();
|
print_type = jj["print_type"].get<std::string>();
|
||||||
}
|
}
|
||||||
if (jj.contains("mc_percent")) {
|
if (jj.contains("mc_percent")) {
|
||||||
if (jj["mc_percent"].is_string())
|
update_print_progress(jj["mc_percent"]);
|
||||||
mc_print_percent = stoi(j["print"]["mc_percent"].get<std::string>());
|
|
||||||
else if (jj["mc_percent"].is_number_integer())
|
|
||||||
mc_print_percent = j["print"]["mc_percent"].get<int>();
|
|
||||||
}
|
}
|
||||||
if (jj.contains("mc_print_sub_stage")) {
|
if (jj.contains("mc_print_sub_stage")) {
|
||||||
if (jj["mc_print_sub_stage"].is_number_integer())
|
if (jj["mc_print_sub_stage"].is_number_integer())
|
||||||
@@ -3471,6 +3491,9 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
this->task_id_ = jj["task_id"].get<std::string>();
|
this->task_id_ = jj["task_id"].get<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jj.contains("thumbnail_url") && jj["thumbnail_url"].is_string())
|
||||||
|
m_agent_thumbnail_url = jj["thumbnail_url"].get<std::string>();
|
||||||
|
|
||||||
if (jj.contains("job_attr")) {
|
if (jj.contains("job_attr")) {
|
||||||
int jobAttr = jj["job_attr"].get<int>();
|
int jobAttr = jj["job_attr"].get<int>();
|
||||||
jobState_ = get_flag_bits(jobAttr, 4, 4);
|
jobState_ = get_flag_bits(jobAttr, 4, 4);
|
||||||
@@ -3516,7 +3539,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
update_slice_info(jj["project_id"].get<std::string>(), jj["profile_id"].get<std::string>(), jj["subtask_id"].get<std::string>(), plate_index);
|
update_slice_info(jj["project_id"].get<std::string>(), jj["profile_id"].get<std::string>(), jj["subtask_id"].get<std::string>(), plate_index);
|
||||||
BBLSubTask* curr_task = get_subtask();
|
BBLSubTask* curr_task = get_subtask();
|
||||||
if (curr_task) {
|
if (curr_task) {
|
||||||
curr_task->task_progress = mc_print_percent;
|
|
||||||
curr_task->printing_status = print_status;
|
curr_task->printing_status = print_status;
|
||||||
curr_task->task_id = jj["subtask_id"].get<std::string>();
|
curr_task->task_id = jj["subtask_id"].get<std::string>();
|
||||||
}
|
}
|
||||||
@@ -3819,6 +3841,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
has_ipcam = true;
|
has_ipcam = true;
|
||||||
} else {
|
} else {
|
||||||
has_ipcam = false;
|
has_ipcam = false;
|
||||||
|
webcam_stream_url.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ipcam.contains("resolution")) {
|
if (ipcam.contains("resolution")) {
|
||||||
@@ -3853,6 +3876,9 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
|||||||
liveview_local = local_rtsp_url.empty() ? LVL_None : local_rtsp_url == "disable"
|
liveview_local = local_rtsp_url.empty() ? LVL_None : local_rtsp_url == "disable"
|
||||||
? LVL_Disable : boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? LVL_Rtsps : LVL_Rtsp;
|
? LVL_Disable : boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? LVL_Rtsps : LVL_Rtsp;
|
||||||
}
|
}
|
||||||
|
if (ipcam.contains("stream_url") && ipcam["stream_url"].is_string()) {
|
||||||
|
webcam_stream_url = ipcam["stream_url"].get<std::string>();
|
||||||
|
}
|
||||||
if (ipcam.contains("tutk_server")) {
|
if (ipcam.contains("tutk_server")) {
|
||||||
tutk_state = ipcam["tutk_server"].get<std::string>();
|
tutk_state = ipcam["tutk_server"].get<std::string>();
|
||||||
}
|
}
|
||||||
@@ -5432,6 +5458,86 @@ void MachineObject::parse_new_info(json print)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MachineObject::parse_new_info2(const json& info)
|
||||||
|
{
|
||||||
|
if (!info.is_object() || info.value("command", "") != "get_capabilities")
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto capabilities_it = info.find("capabilities");
|
||||||
|
if (capabilities_it == info.end() || !capabilities_it->is_object())
|
||||||
|
return;
|
||||||
|
const auto flags_it = capabilities_it->find("flags");
|
||||||
|
if (flags_it == capabilities_it->end() || !flags_it->is_object())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const json& flags = *flags_it;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "parse_new_info2: OrcaSonar capability flags=" << flags.dump();
|
||||||
|
|
||||||
|
auto parse_bool = [&flags](const char* name, bool& target) {
|
||||||
|
const auto it = flags.find(name);
|
||||||
|
if (it != flags.end() && it->is_boolean())
|
||||||
|
target = it->get<bool>();
|
||||||
|
};
|
||||||
|
|
||||||
|
parse_bool("support_send_to_sd", is_support_send_to_sdcard);
|
||||||
|
parse_bool("support_filament_backup", is_support_filament_backup);
|
||||||
|
parse_bool("support_update_remain", is_support_update_remain);
|
||||||
|
parse_bool("support_auto_recovery_step_loss", is_support_auto_recovery_step_loss);
|
||||||
|
parse_bool("support_ams_humidity", is_support_ams_humidity);
|
||||||
|
parse_bool("support_prompt_sound", is_support_prompt_sound);
|
||||||
|
parse_bool("support_filament_tangle_detect", is_support_filament_tangle_detect);
|
||||||
|
parse_bool("support_1080dpi", is_support_1080dpi);
|
||||||
|
parse_bool("support_cloud_print_only", is_support_cloud_print_only);
|
||||||
|
parse_bool("support_command_ams_switch", is_support_command_ams_switch);
|
||||||
|
parse_bool("support_mqtt_alive", is_support_mqtt_alive);
|
||||||
|
parse_bool("support_motor_noise_cali", is_support_motor_noise_cali);
|
||||||
|
parse_bool("support_timelapse", is_support_timelapse);
|
||||||
|
parse_bool("support_user_preset", is_support_user_preset);
|
||||||
|
parse_bool("support_refresh_nozzle", is_support_refresh_nozzle);
|
||||||
|
parse_bool("support_flow_calibration", is_support_flow_calibration);
|
||||||
|
parse_bool("support_build_plate_marker_detect", is_support_build_plate_marker_detect);
|
||||||
|
parse_bool("support_nozzle_blob_detect", is_support_nozzle_blob_detection);
|
||||||
|
|
||||||
|
if (!m_manager->IsMultiMachineEnabled() && !is_support_agora)
|
||||||
|
parse_bool("support_tunnel_mqtt", is_support_tunnel_mqtt);
|
||||||
|
|
||||||
|
const auto bed_leveling_it = flags.find("support_bed_leveling");
|
||||||
|
if (bed_leveling_it != flags.end() && bed_leveling_it->is_number_integer())
|
||||||
|
is_support_bed_leveling = bed_leveling_it->get<int>();
|
||||||
|
|
||||||
|
auto copy_bool = [&flags](json& target, const char* name) {
|
||||||
|
const auto it = flags.find(name);
|
||||||
|
if (it != flags.end() && it->is_boolean())
|
||||||
|
target[name] = *it;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The capability manifest uses an object for this range, while the legacy
|
||||||
|
// DeviceCore parser consumes a boolean plus a two-element range array.
|
||||||
|
json device_config;
|
||||||
|
copy_bool(device_config, "support_chamber");
|
||||||
|
copy_bool(device_config, "support_first_layer_inspect");
|
||||||
|
copy_bool(device_config, "support_ai_monitoring");
|
||||||
|
copy_bool(device_config, "support_lidar_calibration");
|
||||||
|
const auto chamber_edit_it = flags.find("support_chamber_temp_edit");
|
||||||
|
if (chamber_edit_it != flags.end() && chamber_edit_it->is_boolean()) {
|
||||||
|
device_config["support_chamber_temp_edit"] = *chamber_edit_it;
|
||||||
|
} else if (chamber_edit_it != flags.end() && chamber_edit_it->is_object()) {
|
||||||
|
const auto min_it = chamber_edit_it->find("min");
|
||||||
|
const auto max_it = chamber_edit_it->find("max");
|
||||||
|
if (min_it != chamber_edit_it->end() && max_it != chamber_edit_it->end() && min_it->is_number() && max_it->is_number()) {
|
||||||
|
device_config["support_chamber_temp_edit"] = true;
|
||||||
|
device_config["support_chamber_temp_edit_range"] = {*min_it, *max_it};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json fan_config;
|
||||||
|
copy_bool(fan_config, "support_aux_fan");
|
||||||
|
copy_bool(fan_config, "support_chamber_fan");
|
||||||
|
|
||||||
|
m_config->ParseConfig(device_config);
|
||||||
|
m_fan->ParseV2_0(fan_config);
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_hex_digit(char c) {
|
static bool is_hex_digit(char c) {
|
||||||
return std::isxdigit(static_cast<unsigned char>(c)) != 0;
|
return std::isxdigit(static_cast<unsigned char>(c)) != 0;
|
||||||
}
|
}
|
||||||
@@ -5937,6 +6043,15 @@ bool MachineObject::HasAms() const
|
|||||||
return m_fila_system->HasAms();
|
return m_fila_system->HasAms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MachineObject::command_with_dialog(int cmd_result)
|
||||||
|
{
|
||||||
|
if (!m_agent)
|
||||||
|
return -1;
|
||||||
|
if (cmd_result == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || cmd_result == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||||
|
show_unsupported_dlg(cmd_result);
|
||||||
|
return cmd_result;
|
||||||
|
}
|
||||||
|
|
||||||
void change_the_opacity(wxColour& colour)
|
void change_the_opacity(wxColour& colour)
|
||||||
{
|
{
|
||||||
if (colour.Alpha() == 255) {
|
if (colour.Alpha() == 255) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "boost/bimap/bimap.hpp"
|
#include "boost/bimap/bimap.hpp"
|
||||||
#include "libslic3r/calib.hpp"
|
#include "libslic3r/calib.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
|
#include "slic3r/Utils/PrinterNetworkTypes.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevDefs.h"
|
#include "DeviceCore/DevDefs.h"
|
||||||
#include "DeviceCore/DevConfigUtil.h"
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
@@ -100,7 +101,6 @@ struct DevPrintTaskRatingInfo;
|
|||||||
// given nozzle diameter (mm), bucketed per nozzle size to mirror the printer firmware.
|
// given nozzle diameter (mm), bucketed per nozzle size to mirror the printer firmware.
|
||||||
bool is_stringing_prone_filament(const std::string& filament_id, float nozzle_diameter);
|
bool is_stringing_prone_filament(const std::string& filament_id, float nozzle_diameter);
|
||||||
|
|
||||||
|
|
||||||
class MachineObject
|
class MachineObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -307,7 +307,7 @@ public:
|
|||||||
bool ams_support_virtual_tray { true };
|
bool ams_support_virtual_tray { true };
|
||||||
time_t ams_user_setting_start = 0;
|
time_t ams_user_setting_start = 0;
|
||||||
time_t ams_switch_filament_start = 0;
|
time_t ams_switch_filament_start = 0;
|
||||||
AmsStatusMain ams_status_main;
|
AmsStatusMain ams_status_main = AmsStatusMain::AMS_STATUS_MAIN_IDLE;
|
||||||
int ams_status_sub;
|
int ams_status_sub;
|
||||||
int ams_version = 0;
|
int ams_version = 0;
|
||||||
|
|
||||||
@@ -547,30 +547,12 @@ public:
|
|||||||
bool xcam_first_layer_inspector { false };
|
bool xcam_first_layer_inspector { false };
|
||||||
time_t xcam_first_layer_hold_start = 0;
|
time_t xcam_first_layer_hold_start = 0;
|
||||||
std::string local_rtsp_url;
|
std::string local_rtsp_url;
|
||||||
|
std::string webcam_stream_url;
|
||||||
std::string tutk_state;
|
std::string tutk_state;
|
||||||
enum LiveviewLocal {
|
LiveviewLocal liveview_local{ LiveviewLocal::LVL_None };
|
||||||
LVL_None,
|
LiveviewRemote liveview_remote{ LiveviewRemote::LVR_None};
|
||||||
LVL_Disable,
|
FileLocal file_local{ FileLocal::FL_None };
|
||||||
LVL_Local,
|
FileRemote file_remote{ FileRemote::FR_None };
|
||||||
LVL_Rtsps,
|
|
||||||
LVL_Rtsp
|
|
||||||
} liveview_local{ LVL_None };
|
|
||||||
enum LiveviewRemote {
|
|
||||||
LVR_None,
|
|
||||||
LVR_Tutk,
|
|
||||||
LVR_Agora,
|
|
||||||
LVR_TutkAgora
|
|
||||||
} liveview_remote{ LVR_None };
|
|
||||||
enum FileLocal {
|
|
||||||
FL_None,
|
|
||||||
FL_Local
|
|
||||||
} file_local{ FL_None };
|
|
||||||
enum FileRemote {
|
|
||||||
FR_None,
|
|
||||||
FR_Tutk,
|
|
||||||
FR_Agora,
|
|
||||||
FR_TutkAgora
|
|
||||||
} file_remote{ FR_None };
|
|
||||||
|
|
||||||
enum PlateMakerDectect : int
|
enum PlateMakerDectect : int
|
||||||
{
|
{
|
||||||
@@ -708,6 +690,8 @@ public:
|
|||||||
std::string subtask_id_;
|
std::string subtask_id_;
|
||||||
std::string job_id_;
|
std::string job_id_;
|
||||||
std::string last_subtask_id_;
|
std::string last_subtask_id_;
|
||||||
|
// note: printer-agent-supplied thumbnail url, empty when the agent supplies none.
|
||||||
|
std::string m_agent_thumbnail_url;
|
||||||
BBLSliceInfo* slice_info {nullptr};
|
BBLSliceInfo* slice_info {nullptr};
|
||||||
boost::thread* get_slice_info_thread { nullptr };
|
boost::thread* get_slice_info_thread { nullptr };
|
||||||
boost::thread* get_model_task_thread { nullptr };
|
boost::thread* get_model_task_thread { nullptr };
|
||||||
@@ -765,6 +749,7 @@ public:
|
|||||||
int command_set_printer_nozzle(std::string nozzle_type, float diameter);
|
int command_set_printer_nozzle(std::string nozzle_type, float diameter);
|
||||||
int command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter);
|
int command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter);
|
||||||
int command_get_access_code();
|
int command_get_access_code();
|
||||||
|
int command_start_camera();
|
||||||
int command_ack_proceed(json& proceed);
|
int command_ack_proceed(json& proceed);
|
||||||
int command_purification_disable();
|
int command_purification_disable();
|
||||||
int command_dont_remind_next_time(json& mqtt_guard_json);
|
int command_dont_remind_next_time(json& mqtt_guard_json);
|
||||||
@@ -894,6 +879,7 @@ public:
|
|||||||
static bool is_in_printing_status(std::string status);
|
static bool is_in_printing_status(std::string status);
|
||||||
|
|
||||||
void set_print_state(std::string status);
|
void set_print_state(std::string status);
|
||||||
|
void update_print_progress(const json& value);
|
||||||
|
|
||||||
bool is_connected();
|
bool is_connected();
|
||||||
bool is_connecting();
|
bool is_connecting();
|
||||||
@@ -961,6 +947,7 @@ public:
|
|||||||
/*for parse new info*/
|
/*for parse new info*/
|
||||||
bool check_enable_np(const json& print) const;
|
bool check_enable_np(const json& print) const;
|
||||||
void parse_new_info(json print);
|
void parse_new_info(json print);
|
||||||
|
void parse_new_info2(const json& info);
|
||||||
int get_flag_bits(std::string str, int start, int count = 1) const;
|
int get_flag_bits(std::string str, int start, int count = 1) const;
|
||||||
uint32_t get_flag_bits_no_border(std::string str, int start_idx, int count = 1) const;
|
uint32_t get_flag_bits_no_border(std::string str, int start_idx, int count = 1) const;
|
||||||
int get_flag_bits(int num, int start, int count = 1, int base = 10) const;
|
int get_flag_bits(int num, int start, int count = 1, int base = 10) const;
|
||||||
@@ -989,7 +976,7 @@ public:
|
|||||||
void command_set_save_remote_print_file_to_storage(bool save);
|
void command_set_save_remote_print_file_to_storage(bool save);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int command_with_dialog(int cmd_result);
|
||||||
/* xcam door open check*/
|
/* xcam door open check*/
|
||||||
bool is_support_door_open_check = false;
|
bool is_support_door_open_check = false;
|
||||||
DoorOpenCheckState xcam_door_open_check = DoorOpenCheckState::DOOR_OPEN_CHECK_DISABLE;
|
DoorOpenCheckState xcam_door_open_check = DoorOpenCheckState::DOOR_OPEN_CHECK_DISABLE;
|
||||||
|
|||||||
+20
-35
@@ -4,6 +4,7 @@
|
|||||||
#include "libslic3r/Platform.hpp"
|
#include "libslic3r/Platform.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "Shortcuts.hpp"
|
#include "Shortcuts.hpp"
|
||||||
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
#include "BindDialog.hpp"
|
#include "BindDialog.hpp"
|
||||||
#include "DeviceManager.hpp"
|
#include "DeviceManager.hpp"
|
||||||
#include "HMS.hpp"
|
#include "HMS.hpp"
|
||||||
@@ -24,7 +25,6 @@
|
|||||||
#include <boost/locale/encoding_utf.hpp>
|
#include <boost/locale/encoding_utf.hpp>
|
||||||
#include <boost/log/detail/native_typeof.hpp>
|
#include <boost/log/detail/native_typeof.hpp>
|
||||||
#include <libslic3r/Config.hpp>
|
#include <libslic3r/Config.hpp>
|
||||||
#include <mutex>
|
|
||||||
#include <slic3r/plugin/PythonPluginInterface.hpp>
|
#include <slic3r/plugin/PythonPluginInterface.hpp>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
|
|
||||||
@@ -41,9 +41,11 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <mutex>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
@@ -88,7 +90,6 @@
|
|||||||
#include "libslic3r/Thread.hpp"
|
#include "libslic3r/Thread.hpp"
|
||||||
#include "libslic3r/miniz_extension.hpp"
|
#include "libslic3r/miniz_extension.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Color.hpp"
|
|
||||||
#include "slic3r/plugin/PluginManager.hpp"
|
#include "slic3r/plugin/PluginManager.hpp"
|
||||||
#include "slic3r/plugin/host/PluginHostUi.hpp"
|
#include "slic3r/plugin/host/PluginHostUi.hpp"
|
||||||
#include "slic3r/plugin/PythonInterpreter.hpp"
|
#include "slic3r/plugin/PythonInterpreter.hpp"
|
||||||
@@ -108,19 +109,18 @@
|
|||||||
#include "../Utils/PrintHost.hpp"
|
#include "../Utils/PrintHost.hpp"
|
||||||
#include "../Utils/Process.hpp"
|
#include "../Utils/Process.hpp"
|
||||||
#include "../Utils/wxInspectorPlugins/Registration.hpp"
|
#include "../Utils/wxInspectorPlugins/Registration.hpp"
|
||||||
#include "../Utils/MacDarkMode.hpp"
|
|
||||||
#include "../Utils/Http.hpp"
|
#include "../Utils/Http.hpp"
|
||||||
#include "../Utils/InstanceID.hpp"
|
#include "../Utils/InstanceID.hpp"
|
||||||
#include "../Utils/UndoRedo.hpp"
|
#include "../Utils/UndoRedo.hpp"
|
||||||
#include "slic3r/Config/Snapshot.hpp"
|
#include "slic3r/Config/Snapshot.hpp"
|
||||||
#include "Preferences.hpp"
|
#include "Preferences.hpp"
|
||||||
#include "Tab.hpp"
|
#include "Tab.hpp"
|
||||||
#include "SysInfoDialog.hpp"
|
|
||||||
#include "UpdateDialogs.hpp"
|
#include "UpdateDialogs.hpp"
|
||||||
#include "Mouse3DController.hpp"
|
#include "Mouse3DController.hpp"
|
||||||
#include "RemovableDriveManager.hpp"
|
#include "RemovableDriveManager.hpp"
|
||||||
#include "InstanceCheck.hpp"
|
#include "InstanceCheck.hpp"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
#include "../Utils/MacDarkMode.hpp"
|
||||||
#include "DeepLinkHandlerMac.h"
|
#include "DeepLinkHandlerMac.h"
|
||||||
#endif
|
#endif
|
||||||
#include "NotificationManager.hpp"
|
#include "NotificationManager.hpp"
|
||||||
@@ -129,8 +129,6 @@
|
|||||||
#include "PrintHostDialogs.hpp"
|
#include "PrintHostDialogs.hpp"
|
||||||
#include "NetworkPluginDialog.hpp"
|
#include "NetworkPluginDialog.hpp"
|
||||||
#include "DesktopIntegrationDialog.hpp"
|
#include "DesktopIntegrationDialog.hpp"
|
||||||
#include "SendSystemInfoDialog.hpp"
|
|
||||||
#include "ParamsDialog.hpp"
|
|
||||||
#include "KBShortcutsDialog.hpp"
|
#include "KBShortcutsDialog.hpp"
|
||||||
#include "DownloadProgressDialog.hpp"
|
#include "DownloadProgressDialog.hpp"
|
||||||
#include "TroubleshootDialog.hpp"
|
#include "TroubleshootDialog.hpp"
|
||||||
@@ -141,7 +139,6 @@
|
|||||||
#include "Widgets/ProgressDialog.hpp"
|
#include "Widgets/ProgressDialog.hpp"
|
||||||
|
|
||||||
//BBS: DailyTip and UserGuide Dialog
|
//BBS: DailyTip and UserGuide Dialog
|
||||||
#include "WebDownPluginDlg.hpp"
|
|
||||||
#include "WebGuideDialog.hpp"
|
#include "WebGuideDialog.hpp"
|
||||||
#include "ReleaseNote.hpp"
|
#include "ReleaseNote.hpp"
|
||||||
#include "PrivacyUpdateDialog.hpp"
|
#include "PrivacyUpdateDialog.hpp"
|
||||||
@@ -2388,14 +2385,8 @@ bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
|||||||
{
|
{
|
||||||
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
if (!dev) return true;
|
if (!dev) return true;
|
||||||
std::string target_model;
|
|
||||||
if (obj_ == nullptr) {
|
if (obj_ == nullptr) {
|
||||||
obj_ = dev->get_selected_machine();
|
obj_ = dev->get_selected_machine();
|
||||||
if (obj_) {
|
|
||||||
target_model = obj_->printer_type;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
target_model = obj_->printer_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj_)
|
if (!obj_)
|
||||||
@@ -2406,14 +2397,7 @@ bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
|||||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||||
std::string source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
std::string source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||||
|
|
||||||
if (source_model != target_model) {
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
std::vector<std::string> compatible_machine = obj_->get_compatible_machine();
|
|
||||||
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
|
|
||||||
if (it == compatible_machine.end()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If formatted for github, plaintext with OpenGL extensions enclosed into <details>.
|
// If formatted for github, plaintext with OpenGL extensions enclosed into <details>.
|
||||||
@@ -3968,20 +3952,16 @@ void GUI_App::set_live_printer_agent(std::shared_ptr<IPrinterAgent> agent)
|
|||||||
m_agent->set_user_selected_machine("");
|
m_agent->set_user_selected_machine("");
|
||||||
// note: belt-and-suspenders (precedent: DeviceManagerRefresher::on_timer)
|
// note: belt-and-suspenders (precedent: DeviceManagerRefresher::on_timer)
|
||||||
dev->OnSelectedMachineLost(); // why: clear stale sidebar sync-status / AMS
|
dev->OnSelectedMachineLost(); // why: clear stale sidebar sync-status / AMS
|
||||||
// why: drop stale LAN discoveries; keep My Devices, but only those belonging to the
|
// why: retain agent-owned LAN discoveries so agents without automatic discovery (for
|
||||||
// agent we're about to swap to, so a device stamped by the outgoing agent doesn't
|
// example the Moonraker-based Qidi/Snapmaker agents) can reuse them after a switch.
|
||||||
// linger hidden - the new agent's start_discovery re-inserts and re-stamps it fresh.
|
dev->clear_other_devices();
|
||||||
// agent is null when clearing the live agent entirely (e.g. plugin unload); there's no
|
|
||||||
// target to filter against then, so fall back to the original "keep all My Devices"
|
|
||||||
// behavior rather than guessing.
|
|
||||||
dev->clear_other_devices(agent ? agent->get_agent_info().id : std::string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_agent->set_printer_agent(agent);
|
m_agent->set_printer_agent(agent);
|
||||||
sidebar().update_all_preset_comboboxes();
|
sidebar().update_all_preset_comboboxes();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GUI_App::resolve_printer_agent_id(const std::string& stored_id)
|
std::string GUI_App::resolve_printer_agent_id(const std::string& stored_id) const
|
||||||
{
|
{
|
||||||
if (!stored_id.empty())
|
if (!stored_id.empty())
|
||||||
return stored_id;
|
return stored_id;
|
||||||
@@ -4017,6 +3997,7 @@ void GUI_App::switch_printer_agent()
|
|||||||
|
|
||||||
std::string log_dir = data_dir();
|
std::string log_dir = data_dir();
|
||||||
std::string cloud_agent_id = agent_info.id == BBL_PRINTER_AGENT_ID ? BBL_CLOUD_PROVIDER : ORCA_CLOUD_PROVIDER;
|
std::string cloud_agent_id = agent_info.id == BBL_PRINTER_AGENT_ID ? BBL_CLOUD_PROVIDER : ORCA_CLOUD_PROVIDER;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << agent_info.id;
|
||||||
std::shared_ptr<ICloudServiceAgent> cloud_agent = m_agent->get_cloud_agent(cloud_agent_id);
|
std::shared_ptr<ICloudServiceAgent> cloud_agent = m_agent->get_cloud_agent(cloud_agent_id);
|
||||||
|
|
||||||
// Create new printer agent via registry
|
// Create new printer agent via registry
|
||||||
@@ -4030,8 +4011,10 @@ void GUI_App::switch_printer_agent()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The factory caches agents per ID, so an identical pointer means the agent type is unchanged.
|
// Compare the registered IDs, not only the implementation pointer. Different registry IDs
|
||||||
if (m_agent->get_printer_agent() == new_printer_agent) {
|
// may intentionally be backed by the same implementation object (especially for plugins).
|
||||||
|
const auto current_printer_agent = m_agent->get_printer_agent();
|
||||||
|
if (current_printer_agent && current_printer_agent->get_agent_info().id == effective_agent_id) {
|
||||||
// Orca: the agent type is unchanged (e.g. switching between two Moonraker/Klipper
|
// Orca: the agent type is unchanged (e.g. switching between two Moonraker/Klipper
|
||||||
// printer presets), so the selected machine and the agent's cached device_info still
|
// printer presets), so the selected machine and the agent's cached device_info still
|
||||||
// point at the previously active printer preset. Re-select the machine when the new
|
// point at the previously active printer preset. Re-select the machine when the new
|
||||||
@@ -5012,14 +4995,16 @@ bool GUI_App::is_user_login(const std::string& provider/* = ORCA_CLOUD_PROVIDER*
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& GUI_App::get_printer_cloud_provider() const
|
std::string GUI_App::get_printer_cloud_provider() const
|
||||||
{
|
{
|
||||||
// Orca todo: this need to be revisted. currently it is mainly used for device manager and related clausses and only bambu machines use them.
|
const std::string agent_id = resolve_printer_agent_id(
|
||||||
//
|
preset_bundle ? preset_bundle->printers.get_edited_preset().config.opt_string("printer_agent")
|
||||||
return BBL_CLOUD_PROVIDER;
|
: std::string());
|
||||||
|
return agent_id == BBL_PRINTER_AGENT_ID ? BBL_CLOUD_PROVIDER : ORCA_CLOUD_PROVIDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool GUI_App::check_login(const std::string& provider/* = ORCA_CLOUD_PROVIDER*/)
|
bool GUI_App::check_login(const std::string& provider/* = ORCA_CLOUD_PROVIDER*/)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|||||||
@@ -23,9 +23,6 @@
|
|||||||
#include <wx/snglinst.h>
|
#include <wx/snglinst.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
//#define BBL_HAS_FIRST_PAGE 1
|
//#define BBL_HAS_FIRST_PAGE 1
|
||||||
#define STUDIO_INACTIVE_TIMEOUT 15*60*1000
|
#define STUDIO_INACTIVE_TIMEOUT 15*60*1000
|
||||||
#define LOG_FILES_MAX_NUM 30
|
#define LOG_FILES_MAX_NUM 30
|
||||||
@@ -378,7 +375,7 @@ public:
|
|||||||
// Reconcile the live printer agent with the stored preset selection.
|
// Reconcile the live printer agent with the stored preset selection.
|
||||||
void switch_printer_agent();
|
void switch_printer_agent();
|
||||||
|
|
||||||
std::string resolve_printer_agent_id(const std::string& stored_id);
|
std::string resolve_printer_agent_id(const std::string& stored_id) const;
|
||||||
// ORCA TODO: in the future, bbl presets should specify "bbl" printer agent id
|
// ORCA TODO: in the future, bbl presets should specify "bbl" printer agent id
|
||||||
// then, all resolve and canonical would just be ORCA<->""
|
// then, all resolve and canonical would just be ORCA<->""
|
||||||
std::string canonical_printer_agent_id(const std::string& picked_id);
|
std::string canonical_printer_agent_id(const std::string& picked_id);
|
||||||
@@ -504,7 +501,7 @@ public:
|
|||||||
bool check_login(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
bool check_login(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||||
void get_login_info(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
void get_login_info(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||||
bool is_user_login(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
bool is_user_login(const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||||
const std::string& get_printer_cloud_provider() const;
|
std::string get_printer_cloud_provider() const;
|
||||||
|
|
||||||
void request_user_login(int online_login = 0, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
void request_user_login(int online_login = 0, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||||
void request_user_handle(int online_login = 0, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
void request_user_handle(int online_login = 0, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wx/mediactrl.h>
|
||||||
|
#include <wx/uri.h>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
class IMediaController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IMediaController() = default;
|
||||||
|
|
||||||
|
virtual void Load(wxURI url) = 0;
|
||||||
|
|
||||||
|
virtual void Play() = 0;
|
||||||
|
|
||||||
|
virtual void Stop() = 0;
|
||||||
|
|
||||||
|
virtual wxMediaState GetState() { return wxMediaState{}; }
|
||||||
|
|
||||||
|
virtual int GetLastError() const { return {}; };
|
||||||
|
|
||||||
|
virtual wxSize GetVideoSize() const { return {}; };
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||||
|
#include "NetworkAgent.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@@ -203,7 +204,7 @@ void PrintJob::process(Ctl &ctl)
|
|||||||
params.dev_ip = m_dev_ip;
|
params.dev_ip = m_dev_ip;
|
||||||
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||||
params.use_ssl_for_mqtt = m_local_use_ssl;
|
params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||||
params.username = "bblp";
|
params.username = m_agent->default_lan_username();
|
||||||
params.password = m_access_code;
|
params.password = m_access_code;
|
||||||
|
|
||||||
// check access code and ip address
|
// check access code and ip address
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ void SendJob::process(Ctl &ctl)
|
|||||||
if (m_is_check_mode) {
|
if (m_is_check_mode) {
|
||||||
PrintParams verify_params;
|
PrintParams verify_params;
|
||||||
verify_params.dev_ip = m_dev_ip;
|
verify_params.dev_ip = m_dev_ip;
|
||||||
verify_params.username = "bblp";
|
verify_params.username = agent->default_lan_username();
|
||||||
verify_params.password = m_access_code;
|
verify_params.password = m_access_code;
|
||||||
verify_params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
verify_params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||||
verify_params.use_ssl_for_mqtt = m_local_use_ssl;
|
verify_params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||||
@@ -211,7 +211,7 @@ void SendJob::process(Ctl &ctl)
|
|||||||
|
|
||||||
// local print access
|
// local print access
|
||||||
params.dev_ip = m_dev_ip;
|
params.dev_ip = m_dev_ip;
|
||||||
params.username = "bblp";
|
params.username = agent->default_lan_username();
|
||||||
params.password = m_access_code;
|
params.password = m_access_code;
|
||||||
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||||
params.use_ssl_for_mqtt = m_local_use_ssl;
|
params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||||
|
|||||||
@@ -3451,7 +3451,7 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
top_menu->AppendSeparator();
|
top_menu->AppendSeparator();
|
||||||
|
|
||||||
append_shortcut_item(
|
append_shortcut_item(
|
||||||
top_menu, Shortcut::SpeedDial, false, _L("Open speed dial"), "",
|
top_menu, Shortcut::SpeedDial, false, _L("Open Speed Dial"), "",
|
||||||
[](wxCommandEvent &) { wxGetApp().open_speed_dial(); },
|
[](wxCommandEvent &) { wxGetApp().open_speed_dial(); },
|
||||||
"", nullptr, []() { return true; }, this);
|
"", nullptr, []() { return true; }, this);
|
||||||
top_menu->AppendSeparator();
|
top_menu->AppendSeparator();
|
||||||
@@ -3558,7 +3558,7 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
// On Mac, the Apple menu ignores non-standard custom items, so add Preset Bundle to the File menu
|
// On Mac, the Apple menu ignores non-standard custom items, so add Preset Bundle to the File menu
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
append_shortcut_item(
|
append_shortcut_item(
|
||||||
fileMenu, Shortcut::SpeedDial, false, _L("Open speed dial"), "",
|
fileMenu, Shortcut::SpeedDial, false, _L("Open Speed Dial"), "",
|
||||||
[](wxCommandEvent&) { wxGetApp().open_speed_dial(); },
|
[](wxCommandEvent&) { wxGetApp().open_speed_dial(); },
|
||||||
"", nullptr, []() { return true; }, this);
|
"", nullptr, []() { return true; }, this);
|
||||||
append_menu_item(
|
append_menu_item(
|
||||||
@@ -4385,7 +4385,7 @@ void MainFrame::load_printer_url()
|
|||||||
if (auto *device_manager = wxGetApp().getDeviceManager()) {
|
if (auto *device_manager = wxGetApp().getDeviceManager()) {
|
||||||
auto *machine = device_manager->get_selected_machine();
|
auto *machine = device_manager->get_selected_machine();
|
||||||
if (!machine) {
|
if (!machine) {
|
||||||
auto machines = device_manager->get_my_machine_list();
|
auto machines = device_manager->get_my_machine_list(device_manager->get_current_printer_agent_id());
|
||||||
if (machines.size() == 1)
|
if (machines.size() == 1)
|
||||||
machine = machines.begin()->second;
|
machine = machines.begin()->second;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
|
#include "WebMediaController.hpp"
|
||||||
|
#include "IPrinterAgent.hpp"
|
||||||
#include "Widgets/Button.hpp"
|
#include "Widgets/Button.hpp"
|
||||||
#include "Widgets/CheckBox.hpp"
|
#include "Widgets/CheckBox.hpp"
|
||||||
#include "Widgets/Label.hpp"
|
#include "Widgets/Label.hpp"
|
||||||
@@ -7,6 +9,7 @@
|
|||||||
#include "DeviceManager.hpp"
|
#include "DeviceManager.hpp"
|
||||||
#include "DeviceCore/DevConfigUtil.h"
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||||
|
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||||
#include "libslic3r/Thread.hpp"
|
#include "libslic3r/Thread.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
@@ -15,11 +18,15 @@
|
|||||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/nowide/fstream.hpp>
|
#include <boost/nowide/fstream.hpp>
|
||||||
#include <boost/nowide/utf8_codecvt.hpp>
|
#include <boost/nowide/utf8_codecvt.hpp>
|
||||||
|
#include <slic3r/GUI/DeviceManager.hpp>
|
||||||
|
#include <wx/mediactrl.h>
|
||||||
#undef pid_t
|
#undef pid_t
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
@@ -48,6 +55,7 @@ namespace GUI {
|
|||||||
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const wxPoint &pos, const wxSize &size)
|
||||||
: wxPanel(parent, wxID_ANY, pos, size)
|
: wxPanel(parent, wxID_ANY, pos, size)
|
||||||
, m_media_ctrl(media_ctrl)
|
, m_media_ctrl(media_ctrl)
|
||||||
|
, m_active_media_controller(media_ctrl)
|
||||||
{
|
{
|
||||||
SetLabel("MediaPlayCtrl");
|
SetLabel("MediaPlayCtrl");
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
@@ -94,7 +102,10 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
|
m_button_play->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](auto &e) { TogglePlay(); });
|
||||||
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) { m_media_ctrl->Play(); });
|
m_button_play->Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
||||||
|
if (m_active_media_controller)
|
||||||
|
m_active_media_controller->Play();
|
||||||
|
});
|
||||||
// Orca: live-view FAQ link binding removed (vendor URL)
|
// Orca: live-view FAQ link binding removed (vendor URL)
|
||||||
|
|
||||||
Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
Bind(wxEVT_RIGHT_UP, [this](auto & e) {
|
||||||
@@ -139,9 +150,12 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl3 *media_ctrl, const w
|
|||||||
|
|
||||||
MediaPlayCtrl::~MediaPlayCtrl()
|
MediaPlayCtrl::~MediaPlayCtrl()
|
||||||
{
|
{
|
||||||
|
if (m_webrtc_ctrl)
|
||||||
|
m_webrtc_ctrl->Stop();
|
||||||
|
m_media_ctrl->EndExternalStream();
|
||||||
{
|
{
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<exit>");
|
m_tasks.push_back({"<exit>", nullptr});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
}
|
}
|
||||||
while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
|
while (!m_thread.try_join_for(boost::chrono::milliseconds(10))) {
|
||||||
@@ -151,59 +165,144 @@ MediaPlayCtrl::~MediaPlayCtrl()
|
|||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << this;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaPlayCtrl::SetWebMediaController(IMediaController *ctrl)
|
||||||
|
{
|
||||||
|
m_web_ctrl = ctrl;
|
||||||
|
set_active_media_controller(current_mode());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaPlayCtrl::set_active_media_controller(CameraStreamMode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case CameraStreamMode::http_snapshot:
|
||||||
|
if (auto *web_ctrl = dynamic_cast<WebMediaController *>(m_web_ctrl))
|
||||||
|
web_ctrl->set_mode(mode);
|
||||||
|
m_active_media_controller = m_web_ctrl;
|
||||||
|
break;
|
||||||
|
case CameraStreamMode::webrtc:
|
||||||
|
if (!m_webrtc_ctrl) {
|
||||||
|
m_webrtc_ctrl = std::make_unique<WebRtcMediaController>(
|
||||||
|
[this](const wxImage& image, wxSize size) { m_media_ctrl->SetExternalFrame(image, size); },
|
||||||
|
[this, token = std::weak_ptr<int>(m_token)](WebRtcMediaController::Status status) {
|
||||||
|
if (token.expired())
|
||||||
|
return;
|
||||||
|
CallAfter([this, status] { on_webrtc_status(status); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
m_active_media_controller = m_webrtc_ctrl.get();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_active_media_controller = m_media_ctrl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraStreamMode MediaPlayCtrl::current_mode() const
|
||||||
|
{
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
return agent ? agent->get_camera_stream_mode() : CameraStreamMode::none;
|
||||||
|
}
|
||||||
|
|
||||||
void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
||||||
{
|
{
|
||||||
std::string machine = obj ? obj->get_dev_id() : "";
|
const CameraStreamMode mode = current_mode();
|
||||||
if (obj) {
|
if (mode != m_last_mode) {
|
||||||
m_camera_exists = obj->has_ipcam;
|
if (m_last_state != MEDIASTATE_IDLE) {
|
||||||
m_dev_ver = obj->get_ota_version();
|
m_failed_code = 0; // a mode switch is not a stream failure - don't arm back-off
|
||||||
m_lan_mode = obj->is_lan_mode_printer();
|
Stop(" ");
|
||||||
m_lan_proto = obj->liveview_local;
|
|
||||||
m_remote_proto = obj->get_liveview_remote();
|
|
||||||
m_lan_ip = obj->get_dev_ip();
|
|
||||||
m_lan_passwd = obj->get_access_code();
|
|
||||||
m_device_busy = obj->is_camera_busy_off();
|
|
||||||
m_tutk_state = obj->tutk_state;
|
|
||||||
|
|
||||||
if (DevPrinterConfigUtil::get_printer_series_str(obj->printer_type) == "series_o" && BBLNetworkPlugin::instance().use_legacy_network()) {
|
|
||||||
// Legacy plugin cannot support remote play for H2D, force using local mode
|
|
||||||
m_remote_proto = MachineObject::LVR_None;
|
|
||||||
}
|
}
|
||||||
} else {
|
m_last_mode = mode;
|
||||||
m_camera_exists = false;
|
|
||||||
m_lan_mode = false;
|
|
||||||
m_lan_proto = MachineObject::LVL_None;
|
|
||||||
m_lan_ip.clear();
|
|
||||||
m_lan_passwd.clear();
|
|
||||||
m_dev_ver.clear();
|
|
||||||
m_tutk_state.clear();
|
|
||||||
m_remote_proto = 0;
|
|
||||||
m_device_busy = false;
|
|
||||||
}
|
}
|
||||||
Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
|
set_active_media_controller(mode);
|
||||||
if (machine == m_machine) {
|
|
||||||
if (m_last_state == MEDIASTATE_IDLE && IsEnabled())
|
const bool uses_local_camera_url = mode == CameraStreamMode::http || mode == CameraStreamMode::https ||
|
||||||
Play();
|
mode == CameraStreamMode::http_snapshot || mode == CameraStreamMode::rtsp;
|
||||||
|
const bool uses_webrtc = mode == CameraStreamMode::webrtc;
|
||||||
|
const std::string machine = obj ? obj->get_dev_id() : "";
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (uses_local_camera_url) {
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
std::string url = agent ? agent->get_local_camera_stream_url() : "";
|
||||||
|
m_camera_exists = !url.empty();
|
||||||
|
Enable(obj && m_camera_exists);
|
||||||
|
changed = machine != m_machine || url != m_agent_camera_url;
|
||||||
|
m_agent_camera_url = url;
|
||||||
|
m_url = from_u8(url);
|
||||||
|
} else if (uses_webrtc) {
|
||||||
|
m_camera_exists = obj != nullptr;
|
||||||
|
Enable(obj != nullptr);
|
||||||
|
changed = machine != m_machine;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetMachineObject webrtc: changed=" << changed
|
||||||
|
<< " last_state=" << m_last_state << " web_user_stopped=" << m_web_user_stopped;
|
||||||
|
m_url.clear();
|
||||||
|
m_agent_camera_url.clear();
|
||||||
|
} else {
|
||||||
|
if (obj) {
|
||||||
|
m_camera_exists = obj->has_ipcam;
|
||||||
|
m_dev_ver = obj->get_ota_version();
|
||||||
|
m_lan_mode = obj->is_lan_mode_printer();
|
||||||
|
m_lan_proto = obj->liveview_local;
|
||||||
|
m_remote_proto = obj->get_liveview_remote();
|
||||||
|
m_lan_ip = obj->get_dev_ip();
|
||||||
|
m_lan_passwd = obj->get_access_code();
|
||||||
|
m_device_busy = obj->is_camera_busy_off();
|
||||||
|
m_tutk_state = obj->tutk_state;
|
||||||
|
|
||||||
|
if (DevPrinterConfigUtil::get_printer_series_str(obj->printer_type) == "series_o" && BBLNetworkPlugin::instance().use_legacy_network()) {
|
||||||
|
// Legacy plugin cannot support remote play for H2D, force using local mode
|
||||||
|
m_remote_proto = LiveviewRemote::LVR_None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_camera_exists = false;
|
||||||
|
m_lan_mode = false;
|
||||||
|
m_lan_proto = LiveviewLocal::LVL_None;
|
||||||
|
m_lan_ip.clear();
|
||||||
|
m_lan_passwd.clear();
|
||||||
|
m_dev_ver.clear();
|
||||||
|
m_tutk_state.clear();
|
||||||
|
m_remote_proto = 0;
|
||||||
|
m_device_busy = false;
|
||||||
|
}
|
||||||
|
Enable(obj && obj->is_info_ready() && obj->m_push_count > 0);
|
||||||
|
if (machine == m_machine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_machine = machine;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
|
||||||
|
m_disable_lan = false;
|
||||||
|
m_failed_retry = 0;
|
||||||
|
m_last_failed_codes.clear();
|
||||||
|
m_last_user_play = wxDateTime::Now();
|
||||||
|
std::string stream_url;
|
||||||
|
if (get_stream_url(&stream_url)) {
|
||||||
|
m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
|
||||||
|
} else {
|
||||||
|
m_streaming = false;
|
||||||
|
}
|
||||||
|
if (m_last_state != MEDIASTATE_IDLE)
|
||||||
|
Stop(" ");
|
||||||
|
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
|
||||||
|
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
|
||||||
|
else
|
||||||
|
SetStatus("", false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_machine = machine;
|
m_machine = machine;
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl switch machine: " << m_machine;
|
if (!changed)
|
||||||
m_disable_lan = false;
|
return;
|
||||||
m_failed_retry = 0;
|
|
||||||
m_last_failed_codes.clear();
|
// A genuine target switch is not a stream failure and should clear the
|
||||||
m_last_user_play = wxDateTime::Now();
|
// manual-stop state before the new target is allowed to play.
|
||||||
std::string stream_url;
|
m_web_user_stopped = false;
|
||||||
if (get_stream_url(&stream_url)) {
|
if (uses_local_camera_url) {
|
||||||
m_streaming = boost::algorithm::contains(stream_url, "device=" + m_machine);
|
m_failed_code = 0;
|
||||||
} else {
|
m_failed_retry = 0;
|
||||||
m_streaming = false;
|
m_next_retry = wxDateTime();
|
||||||
}
|
}
|
||||||
if (m_last_state != MEDIASTATE_IDLE)
|
if (m_last_state != MEDIASTATE_IDLE)
|
||||||
Stop(" ");
|
Stop(" ");
|
||||||
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid state conflict
|
|
||||||
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
|
|
||||||
else
|
|
||||||
SetStatus("", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1)
|
wxString hide_id_middle_string(wxString const &str, size_t offset = 0, size_t length = -1)
|
||||||
@@ -254,13 +353,71 @@ void refresh_agora_url(char const* device, char const* dev_ver, char const* chan
|
|||||||
|
|
||||||
void MediaPlayCtrl::Play()
|
void MediaPlayCtrl::Play()
|
||||||
{
|
{
|
||||||
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
|
if ((m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry) || !IsShownOnScreen() || m_last_state != MEDIASTATE_IDLE)
|
||||||
return;
|
return;
|
||||||
if (!IsShownOnScreen())
|
|
||||||
return;
|
const CameraStreamMode mode = current_mode();
|
||||||
if (m_last_state != MEDIASTATE_IDLE) {
|
set_active_media_controller(mode);
|
||||||
|
m_last_mode = mode;
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
|
||||||
|
auto printer_agent = agent ? agent->get_printer_agent() : nullptr;
|
||||||
|
const bool is_bbl = (printer_agent ? printer_agent->get_agent_info().id : "") == BBL_PRINTER_AGENT_ID;
|
||||||
|
|
||||||
|
if (!is_bbl) {
|
||||||
|
const bool is_webrtc = mode == CameraStreamMode::webrtc;
|
||||||
|
const bool is_snapshot = mode == CameraStreamMode::http_snapshot;
|
||||||
|
const bool is_http_stream = mode == CameraStreamMode::http || mode == CameraStreamMode::https || mode == CameraStreamMode::rtsp;
|
||||||
|
if (!is_webrtc && !is_snapshot && !is_http_stream)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *webrtc_ctrl = is_webrtc ? dynamic_cast<WebRtcMediaController *>(m_active_media_controller) : nullptr;
|
||||||
|
if (is_webrtc && (!webrtc_ctrl || !m_media_ctrl)) {
|
||||||
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (webrtc_ctrl && webrtc_ctrl->is_active())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_failed_code = 0;
|
||||||
|
if (!m_active_media_controller || m_machine.empty() || !IsEnabled() || !m_camera_exists ||
|
||||||
|
(!is_webrtc && m_url.IsEmpty())) {
|
||||||
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_webrtc) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play webrtc: last_state=" << m_last_state << " failed_retry=" << m_failed_retry
|
||||||
|
<< " shown=" << IsShownOnScreen();
|
||||||
|
auto channel = agent ? agent->create_camera_signaling_channel(m_machine, wxGetApp().get_printer_cloud_provider()) : nullptr;
|
||||||
|
if (!channel) {
|
||||||
|
Stop(_L("Sign in to OrcaCloud to view the camera."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
webrtc_ctrl->set_signalling_channel(std::move(channel));
|
||||||
|
m_media_ctrl->BeginExternalStream();
|
||||||
|
m_last_state = MEDIASTATE_INITIALIZING;
|
||||||
|
SetStatus(_L("Initializing..."), false);
|
||||||
|
} else if (is_snapshot) {
|
||||||
|
m_last_state = wxMEDIASTATE_PLAYING;
|
||||||
|
SetStatus(_L("Playing..."), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_button_play->SetIcon("media_stop");
|
||||||
|
if (m_active_media_controller == m_media_ctrl) {
|
||||||
|
// wxMediaCtrl3 reports when it has a decoded frame; load() waits for
|
||||||
|
// that event before queuing Play so the stream is not marked stopped.
|
||||||
|
load();
|
||||||
|
} else {
|
||||||
|
m_active_media_controller->Load(wxURI(m_url));
|
||||||
|
m_active_media_controller->Play();
|
||||||
|
}
|
||||||
|
if (webrtc_ctrl) {
|
||||||
|
m_webrtc_epoch = webrtc_ctrl->epoch();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_failed_code = 0;
|
m_failed_code = 0;
|
||||||
if (m_machine.empty()) {
|
if (m_machine.empty()) {
|
||||||
Stop(_L("Please confirm if the printer is connected."));
|
Stop(_L("Please confirm if the printer is connected."));
|
||||||
@@ -281,16 +438,15 @@ void MediaPlayCtrl::Play()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
|
||||||
NetworkAgent *agent = wxGetApp().getAgent();
|
|
||||||
std::string agent_version = agent ? agent->get_version() : "";
|
std::string agent_version = agent ? agent->get_version() : "";
|
||||||
if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||||
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
|
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
|
||||||
std::string url;
|
std::string url;
|
||||||
if (m_lan_proto == MachineObject::LVL_Local)
|
if (m_lan_proto == LiveviewLocal::LVL_Local)
|
||||||
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
||||||
else if (m_lan_proto == MachineObject::LVL_Rtsps)
|
else if (m_lan_proto == LiveviewLocal::LVL_Rtsps)
|
||||||
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
||||||
else if (m_lan_proto == MachineObject::LVL_Rtsp)
|
else if (m_lan_proto == LiveviewLocal::LVL_Rtsp)
|
||||||
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
||||||
url += "&device=" + m_machine;
|
url += "&device=" + m_machine;
|
||||||
url += "&net_ver=" + agent_version;
|
url += "&net_ver=" + agent_version;
|
||||||
@@ -312,8 +468,8 @@ void MediaPlayCtrl::Play()
|
|||||||
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_Disable (*)
|
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_Disable (*)
|
||||||
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_None (x)
|
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_None (x)
|
||||||
|
|
||||||
if (m_lan_proto <= MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto)) {
|
if (m_lan_proto <= LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto)) {
|
||||||
Stop(m_lan_proto == MachineObject::LVL_None
|
Stop(m_lan_proto == LiveviewLocal::LVL_None
|
||||||
? _L("A problem occurred. Please update the printer firmware and try again.")
|
? _L("A problem occurred. Please update the printer firmware and try again.")
|
||||||
: _L("LAN Only Liveview is off. Please turn on the liveview on printer screen."));
|
: _L("LAN Only Liveview is off. Please turn on the liveview on printer screen."));
|
||||||
return;
|
return;
|
||||||
@@ -381,15 +537,78 @@ void MediaPlayCtrl::Play()
|
|||||||
|
|
||||||
void start_ping_test();
|
void start_ping_test();
|
||||||
|
|
||||||
|
void MediaPlayCtrl::StopWebStream()
|
||||||
|
{
|
||||||
|
if (m_last_state == MEDIASTATE_IDLE)
|
||||||
|
return;
|
||||||
|
if (m_active_media_controller && m_active_media_controller == m_web_ctrl)
|
||||||
|
m_active_media_controller->Stop();
|
||||||
|
m_button_play->SetIcon("media_play");
|
||||||
|
m_last_state = MEDIASTATE_IDLE;
|
||||||
|
SetStatus(_L("Video Stopped."), false);
|
||||||
|
}
|
||||||
|
|
||||||
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
||||||
{
|
{
|
||||||
|
const bool webrtc_active = m_last_mode == CameraStreamMode::webrtc &&
|
||||||
|
dynamic_cast<WebRtcMediaController *>(m_active_media_controller) != nullptr;
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Stop: last_state=" << m_last_state
|
||||||
|
<< " webrtc_active=" << webrtc_active << " failed_code=" << m_failed_code
|
||||||
|
<< " msg='" << msg.ToUTF8().data() << "'";
|
||||||
|
if (webrtc_active) {
|
||||||
|
m_active_media_controller->Stop();
|
||||||
|
m_media_ctrl->EndExternalStream();
|
||||||
|
}
|
||||||
|
switch (m_last_mode) {
|
||||||
|
case CameraStreamMode::http:
|
||||||
|
case CameraStreamMode::https:
|
||||||
|
case CameraStreamMode::http_snapshot: {
|
||||||
|
const bool snapshot = m_last_mode == CameraStreamMode::http_snapshot;
|
||||||
|
if (m_last_state != MEDIASTATE_IDLE) {
|
||||||
|
if (snapshot) {
|
||||||
|
if (m_active_media_controller)
|
||||||
|
m_active_media_controller->Stop();
|
||||||
|
} else {
|
||||||
|
// http/https mode plays through the ffmpeg backend (m_media_ctrl), not
|
||||||
|
// the webview - tear its read thread down too, otherwise it keeps
|
||||||
|
// pulling and painting frames after the UI says "Video Stopped".
|
||||||
|
boost::unique_lock lock(m_mutex);
|
||||||
|
m_tasks.push_back({"<stop>", m_active_media_controller});
|
||||||
|
m_cond.notify_all();
|
||||||
|
}
|
||||||
|
m_button_play->SetIcon("media_play");
|
||||||
|
m_last_state = MEDIASTATE_IDLE;
|
||||||
|
if (!msg.IsEmpty())
|
||||||
|
SetStatus(msg);
|
||||||
|
else
|
||||||
|
SetStatus(_L("Video Stopped."), false);
|
||||||
|
// Keep retries bounded for an explicit or retry-driven playback attempt.
|
||||||
|
// m_failed_retry is cleared on success (onStateChanged) and on a deliberate
|
||||||
|
// machine switch (SetMachineObject); manual playback via TogglePlay resets it.
|
||||||
|
if (m_failed_code != 0) {
|
||||||
|
const bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false";
|
||||||
|
++m_failed_retry;
|
||||||
|
m_next_retry = auto_retry
|
||||||
|
? wxDateTime::Now() + wxTimeSpan::Seconds(std::min(5 * m_failed_retry, 30))
|
||||||
|
: wxDateTime::Now() + wxTimeSpan::Days(1); // "off": wait for a manual retry
|
||||||
|
}
|
||||||
|
} else if (!msg.IsEmpty()) {
|
||||||
|
SetStatus(msg, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int last_state = m_last_state;
|
int last_state = m_last_state;
|
||||||
|
|
||||||
if (m_last_state != MEDIASTATE_IDLE) {
|
if (m_last_state != MEDIASTATE_IDLE) {
|
||||||
m_media_ctrl->InvalidateBestSize();
|
m_media_ctrl->InvalidateBestSize();
|
||||||
m_button_play->SetIcon("media_play");
|
m_button_play->SetIcon("media_play");
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<stop>");
|
if (!webrtc_active)
|
||||||
|
m_tasks.push_back({"<stop>", m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
if (!msg.IsEmpty())
|
if (!msg.IsEmpty())
|
||||||
SetStatus(msg);
|
SetStatus(msg);
|
||||||
@@ -454,15 +673,38 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
|
|||||||
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(5 * m_failed_retry);
|
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(5 * m_failed_retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaPlayCtrl::on_webrtc_status(WebRtcMediaController::Status status)
|
||||||
|
{
|
||||||
|
// Drop CallAfter-queued events from a superseded Play attempt.
|
||||||
|
if (status.epoch != m_webrtc_epoch)
|
||||||
|
return;
|
||||||
|
if (status.kind == WebRtcMediaController::Status::Connecting) {
|
||||||
|
m_last_state = MEDIASTATE_INITIALIZING;
|
||||||
|
SetStatus(_L("Initializing..."), false);
|
||||||
|
} else if (status.kind == WebRtcMediaController::Status::Playing) {
|
||||||
|
m_last_state = wxMEDIASTATE_PLAYING;
|
||||||
|
m_failed_code = 0;
|
||||||
|
m_failed_retry = 0;
|
||||||
|
SetStatus(_L("Playing..."), false);
|
||||||
|
} else if (status.kind == WebRtcMediaController::Status::Failed) {
|
||||||
|
m_failed_code = static_cast<int>(status.code) + 1;
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
// Status::Stopped needs no action: a genuine failure arrives as Failed, and
|
||||||
|
// a stop we initiated is already handled by Stop() itself.
|
||||||
|
}
|
||||||
|
|
||||||
void MediaPlayCtrl::TogglePlay()
|
void MediaPlayCtrl::TogglePlay()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::TogglePlay";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::TogglePlay";
|
||||||
if (m_last_state != MEDIASTATE_IDLE) {
|
if (m_last_state != MEDIASTATE_IDLE) {
|
||||||
m_next_retry = wxDateTime();
|
m_next_retry = wxDateTime();
|
||||||
|
m_web_user_stopped = true;
|
||||||
Stop();
|
Stop();
|
||||||
} else {
|
} else {
|
||||||
m_failed_retry = 0;
|
m_failed_retry = 0;
|
||||||
m_user_triggered = true;
|
m_user_triggered = true;
|
||||||
|
m_web_user_stopped = false;
|
||||||
if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
|
if (m_last_user_play + wxTimeSpan::Minutes(5) < wxDateTime::Now()) {
|
||||||
m_last_failed_codes.clear();
|
m_last_failed_codes.clear();
|
||||||
m_last_user_play = wxDateTime::Now();
|
m_last_user_play = wxDateTime::Now();
|
||||||
@@ -528,13 +770,13 @@ void MediaPlayCtrl::ToggleStream()
|
|||||||
wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1");
|
wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1");
|
||||||
if (res == wxID_CANCEL) return;
|
if (res == wxID_CANCEL) return;
|
||||||
}
|
}
|
||||||
if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||||
std::string url;
|
std::string url;
|
||||||
if (m_lan_proto == MachineObject::LVL_Local)
|
if (m_lan_proto == LiveviewLocal::LVL_Local)
|
||||||
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
||||||
else if (m_lan_proto == MachineObject::LVL_Rtsps)
|
else if (m_lan_proto == LiveviewLocal::LVL_Rtsps)
|
||||||
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
||||||
else if (m_lan_proto == MachineObject::LVL_Rtsp)
|
else if (m_lan_proto == LiveviewLocal::LVL_Rtsp)
|
||||||
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
||||||
url += "&device=" + into_u8(m_machine);
|
url += "&device=" + into_u8(m_machine);
|
||||||
url += "&dev_ver=" + m_dev_ver;
|
url += "&dev_ver=" + m_dev_ver;
|
||||||
@@ -594,7 +836,9 @@ void MediaPlayCtrl::jump_to_play()
|
|||||||
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
||||||
{
|
{
|
||||||
auto last_state = m_last_state;
|
auto last_state = m_last_state;
|
||||||
auto state = m_media_ctrl->GetState();
|
if (m_active_media_controller != m_media_ctrl)
|
||||||
|
return;
|
||||||
|
auto state = m_active_media_controller->GetState();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: " << state << ", last_state: " << last_state;
|
||||||
if ((int) state < 0) return;
|
if ((int) state < 0) return;
|
||||||
{
|
{
|
||||||
@@ -606,14 +850,14 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
|||||||
}
|
}
|
||||||
if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
|
if ((last_state == MEDIASTATE_IDLE || last_state == MEDIASTATE_INITIALIZING) && state == wxMEDIASTATE_STOPPED) { return; }
|
||||||
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
|
if ((last_state == wxMEDIASTATE_PAUSED || last_state == wxMEDIASTATE_PLAYING) && state == wxMEDIASTATE_STOPPED) {
|
||||||
m_failed_code = m_media_ctrl->GetLastError();
|
m_failed_code = m_active_media_controller->GetLastError();
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
|
if (last_state == MEDIASTATE_LOADING && (state == wxMEDIASTATE_STOPPED || state == wxMEDIASTATE_PAUSED)) {
|
||||||
wxSize size = m_media_ctrl->GetVideoSize();
|
wxSize size = m_active_media_controller->GetVideoSize();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
||||||
m_failed_code = m_media_ctrl->GetLastError();
|
m_failed_code = m_active_media_controller->GetLastError();
|
||||||
if (size.GetWidth() >= 320) {
|
if (size.GetWidth() >= 320) {
|
||||||
m_last_state = state;
|
m_last_state = state;
|
||||||
m_failed_code = 0;
|
m_failed_code = 0;
|
||||||
@@ -623,7 +867,7 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
|
|||||||
m_failed_retry = 0;
|
m_failed_retry = 0;
|
||||||
m_disable_lan = false;
|
m_disable_lan = false;
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back("<play>");
|
m_tasks.push_back({"<play>", m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
} else if (event.GetId()) {
|
} else if (event.GetId()) {
|
||||||
if (m_failed_code == 0)
|
if (m_failed_code == 0)
|
||||||
@@ -666,7 +910,8 @@ void MediaPlayCtrl::load()
|
|||||||
{
|
{
|
||||||
m_last_state = MEDIASTATE_LOADING;
|
m_last_state = MEDIASTATE_LOADING;
|
||||||
SetStatus(_L("Loading..."));
|
SetStatus(_L("Loading..."));
|
||||||
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
|
const auto mode = current_mode();
|
||||||
|
if (mode == CameraStreamMode::none && wxGetApp().app_config->get("internal_developer_mode") == "true") {
|
||||||
std::string file_h264 = data_dir() + "/video.h264";
|
std::string file_h264 = data_dir() + "/video.h264";
|
||||||
std::string file_info = data_dir() + "/video.info";
|
std::string file_info = data_dir() + "/video.info";
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
|
||||||
@@ -677,7 +922,7 @@ void MediaPlayCtrl::load()
|
|||||||
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
|
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
|
||||||
}
|
}
|
||||||
boost::unique_lock lock(m_mutex);
|
boost::unique_lock lock(m_mutex);
|
||||||
m_tasks.push_back(m_url);
|
m_tasks.push_back({m_url, m_active_media_controller});
|
||||||
m_cond.notify_all();
|
m_cond.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,9 +931,8 @@ void MediaPlayCtrl::on_show_hide(wxShowEvent &evt)
|
|||||||
evt.Skip();
|
evt.Skip();
|
||||||
if (m_isBeingDeleted) return;
|
if (m_isBeingDeleted) return;
|
||||||
m_failed_retry = 0;
|
m_failed_retry = 0;
|
||||||
if (m_next_retry.IsValid()) // Try open 2 seconds later, to avoid quick play/stop
|
if (!IsShownOnScreen())
|
||||||
m_next_retry = wxDateTime::Now() + wxTimeSpan::Seconds(2);
|
Stop();
|
||||||
IsShownOnScreen() ? Play() : Stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlayCtrl::media_proc()
|
void MediaPlayCtrl::media_proc()
|
||||||
@@ -698,30 +942,34 @@ void MediaPlayCtrl::media_proc()
|
|||||||
while (m_tasks.empty()) {
|
while (m_tasks.empty()) {
|
||||||
m_cond.wait(lock);
|
m_cond.wait(lock);
|
||||||
}
|
}
|
||||||
wxString url = m_tasks.front();
|
MediaTask task = m_tasks.front();
|
||||||
if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "<stop>") {
|
if (m_tasks.size() >= 2 && !task.command.IsEmpty() && task.command[0] != '<' &&
|
||||||
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << url;
|
m_tasks[1].command == "<stop>" && task.controller == m_tasks[1].controller) {
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "MediaPlayCtrl: busy skip url: " << task.command;
|
||||||
m_tasks.pop_front();
|
m_tasks.pop_front();
|
||||||
m_tasks.pop_front();
|
m_tasks.pop_front();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (url == "<stop>") {
|
if (task.command == "<stop>") {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start stop";
|
||||||
m_media_ctrl->Stop();
|
if (task.controller)
|
||||||
|
task.controller->Stop();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end stop";
|
||||||
}
|
}
|
||||||
else if (url == "<exit>") {
|
else if (task.command == "<exit>") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (url == "<play>") {
|
else if (task.command == "<play>") {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start play";
|
||||||
m_media_ctrl->Play();
|
if (task.controller)
|
||||||
|
task.controller->Play();
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end play";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
||||||
m_media_ctrl->Load(wxURI(url));
|
if (task.controller)
|
||||||
|
task.controller->Load(wxURI(task.command));
|
||||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
|
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: end load";
|
||||||
}
|
}
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#define MediaPlayCtrl_h
|
#define MediaPlayCtrl_h
|
||||||
|
|
||||||
#include "wxMediaCtrl3.h"
|
#include "wxMediaCtrl3.h"
|
||||||
|
#include "IMediaController.hpp"
|
||||||
|
#include "WebRtcMediaController.hpp"
|
||||||
|
#include "slic3r/Utils/IPrinterAgent.hpp"
|
||||||
|
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
|
|
||||||
@@ -36,6 +39,10 @@ public:
|
|||||||
|
|
||||||
void SetMachineObject(MachineObject * obj);
|
void SetMachineObject(MachineObject * obj);
|
||||||
|
|
||||||
|
void SetWebMediaController(IMediaController *ctrl);
|
||||||
|
|
||||||
|
void StopWebStream();
|
||||||
|
|
||||||
bool IsStreaming() const;
|
bool IsStreaming() const;
|
||||||
|
|
||||||
void ToggleStream();
|
void ToggleStream();
|
||||||
@@ -54,6 +61,7 @@ protected:
|
|||||||
void TogglePlay();
|
void TogglePlay();
|
||||||
|
|
||||||
void SetStatus(wxString const &msg, bool hyperlink = true);
|
void SetStatus(wxString const &msg, bool hyperlink = true);
|
||||||
|
void on_webrtc_status(WebRtcMediaController::Status status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load();
|
void load();
|
||||||
@@ -66,6 +74,9 @@ private:
|
|||||||
|
|
||||||
static bool get_stream_url(std::string *url = nullptr);
|
static bool get_stream_url(std::string *url = nullptr);
|
||||||
|
|
||||||
|
CameraStreamMode current_mode() const;
|
||||||
|
void set_active_media_controller(CameraStreamMode mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
|
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
|
||||||
static inline const wxMediaState MEDIASTATE_INITIALIZING = static_cast<wxMediaState>(4);
|
static inline const wxMediaState MEDIASTATE_INITIALIZING = static_cast<wxMediaState>(4);
|
||||||
@@ -76,6 +87,13 @@ private:
|
|||||||
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
||||||
|
|
||||||
wxMediaCtrl3 * m_media_ctrl;
|
wxMediaCtrl3 * m_media_ctrl;
|
||||||
|
IMediaController * m_active_media_controller = nullptr;
|
||||||
|
IMediaController * m_web_ctrl = nullptr;
|
||||||
|
std::unique_ptr<WebRtcMediaController> m_webrtc_ctrl;
|
||||||
|
CameraStreamMode m_last_mode = CameraStreamMode::none;
|
||||||
|
std::uint64_t m_webrtc_epoch = 0;
|
||||||
|
std::string m_agent_camera_url;
|
||||||
|
bool m_web_user_stopped = false;
|
||||||
wxMediaState m_last_state = MEDIASTATE_IDLE;
|
wxMediaState m_last_state = MEDIASTATE_IDLE;
|
||||||
std::string m_machine;
|
std::string m_machine;
|
||||||
int m_lan_proto = 0;
|
int m_lan_proto = 0;
|
||||||
@@ -91,7 +109,11 @@ private:
|
|||||||
bool m_disable_lan = false;
|
bool m_disable_lan = false;
|
||||||
wxString m_url;
|
wxString m_url;
|
||||||
|
|
||||||
std::deque<wxString> m_tasks;
|
struct MediaTask {
|
||||||
|
wxString command;
|
||||||
|
IMediaController *controller = nullptr;
|
||||||
|
};
|
||||||
|
std::deque<MediaTask> m_tasks;
|
||||||
boost::mutex m_mutex;
|
boost::mutex m_mutex;
|
||||||
boost::condition_variable m_cond;
|
boost::condition_variable m_cond;
|
||||||
boost::thread m_thread;
|
boost::thread m_thread;
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
#include "DeviceCore/DevManager.h"
|
#include "DeviceCore/DevManager.h"
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
@@ -259,6 +261,7 @@ void MonitorPanel::msw_rescale()
|
|||||||
|
|
||||||
void MonitorPanel::select_machine(std::string machine_sn)
|
void MonitorPanel::select_machine(std::string machine_sn)
|
||||||
{
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::select_machine queueing machine_sn=" << machine_sn;
|
||||||
wxCommandEvent *event = new wxCommandEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
wxCommandEvent *event = new wxCommandEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
||||||
event->SetString(machine_sn);
|
event->SetString(machine_sn);
|
||||||
wxQueueEvent(this, event);
|
wxQueueEvent(this, event);
|
||||||
@@ -276,13 +279,20 @@ void MonitorPanel::on_timer(wxTimerEvent& event)
|
|||||||
void MonitorPanel::on_select_printer(wxCommandEvent& event)
|
void MonitorPanel::on_select_printer(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
|
const std::string requested_dev_id = event.GetString().ToStdString();
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::on_select_printer requested_dev_id="
|
||||||
|
<< requested_dev_id << " device_manager=" << (dev ? "set" : "null");
|
||||||
if (!dev) return;
|
if (!dev) return;
|
||||||
|
|
||||||
if ( dev->get_selected_machine() && (dev->get_selected_machine()->get_dev_id() != event.GetString().ToStdString()) && m_hms_panel) {
|
if ( dev->get_selected_machine() && (dev->get_selected_machine()->get_dev_id() != event.GetString().ToStdString()) && m_hms_panel) {
|
||||||
m_hms_panel->clear_hms_tag();
|
m_hms_panel->clear_hms_tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev->set_selected_machine(event.GetString().ToStdString()))
|
const bool selected = dev->set_selected_machine(requested_dev_id);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Orca diagnostic: MonitorPanel::on_select_printer set_selected_machine result="
|
||||||
|
<< selected << " selected_dev_id="
|
||||||
|
<< (dev->get_selected_machine() ? dev->get_selected_machine()->get_dev_id() : "<null>");
|
||||||
|
if (!selected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_default();
|
set_default();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@@ -108,21 +109,12 @@ bool DeviceItem::is_blocking_printing(MachineObject* obj_)
|
|||||||
{
|
{
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
if (!dev) return true;
|
if (!dev) return true;
|
||||||
auto target_model = obj_->printer_type;
|
|
||||||
std::string source_model = "";
|
std::string source_model = "";
|
||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||||
|
|
||||||
if (source_model != target_model) {
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
std::vector<std::string> compatible_machine = obj_->get_compatible_machine();
|
|
||||||
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)
|
void DeviceItem::update_item(const DeviceItem* item)
|
||||||
|
|||||||
+89
-24
@@ -2026,12 +2026,14 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material, bool is_man
|
|||||||
std::string machine_print_name = obj->get_show_printer_type();
|
std::string machine_print_name = obj->get_show_printer_type();
|
||||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||||
std::string target_model_id = preset_bundle->printers.get_selected_preset().get_printer_type(preset_bundle);
|
std::string target_model_id = preset_bundle->printers.get_selected_preset().get_printer_type(preset_bundle);
|
||||||
Preset* machine_preset = get_printer_preset(obj);
|
const bool optional_printer_model = DevPrinterConfigUtil::is_optional_printer_model_id(obj->printer_type);
|
||||||
if (!machine_preset) {
|
const bool optional_target_model = DevPrinterConfigUtil::is_optional_printer_model_id(target_model_id);
|
||||||
|
Preset* machine_preset = optional_printer_model ? nullptr : get_printer_preset(obj);
|
||||||
|
if (!optional_printer_model && !optional_target_model && !machine_preset) {
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << "check error: machine_preset empty";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << "check error: machine_preset empty";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (machine_print_name != target_model_id) {
|
if (!optional_printer_model && !optional_target_model && machine_print_name != target_model_id) {
|
||||||
MessageDialog dlg(this->plater, _L("The currently selected machine preset is inconsistent with the connected printer type.\n"
|
MessageDialog dlg(this->plater, _L("The currently selected machine preset is inconsistent with the connected printer type.\n"
|
||||||
"Are you sure to continue syncing?"), _L("Sync printer information"), wxICON_WARNING | wxYES | wxNO);
|
"Are you sure to continue syncing?"), _L("Sync printer information"), wxICON_WARNING | wxYES | wxNO);
|
||||||
if (dlg.ShowModal() == wxID_NO) {
|
if (dlg.ShowModal() == wxID_NO) {
|
||||||
@@ -2223,6 +2225,11 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DevPrinterConfigUtil::is_optional_printer_model_id(obj->printer_type)) {
|
||||||
|
clear_all_sync_status();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool printer_synced = false;
|
bool printer_synced = false;
|
||||||
// 1. update printer status
|
// 1. update printer status
|
||||||
const Preset &cur_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
const Preset &cur_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||||
@@ -5823,11 +5830,30 @@ void Sidebar::load_ams_list(MachineObject* obj)
|
|||||||
filament_ams_list = build_filament_ams_list(obj);
|
filament_ams_list = build_filament_ams_list(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_change = false;
|
|
||||||
const std::string& device = obj ? obj->get_dev_id() : "";
|
const std::string& device = obj ? obj->get_dev_id() : "";
|
||||||
if (p->ams_list_device != device) {
|
const bool same_device = p->ams_list_device == device;
|
||||||
|
|
||||||
|
// Keep sync metadata out of the device payload, but preserve it across a
|
||||||
|
// subscription refresh when the physical filament in a slot is unchanged.
|
||||||
|
// Otherwise the refreshed configs differ only by the missing
|
||||||
|
// filament_changed key, causing combo boxes to rebuild and lose their
|
||||||
|
// transient post-sync badges.
|
||||||
|
auto &previous_filament_ams_list = wxGetApp().preset_bundle->filament_ams_list;
|
||||||
|
for (auto &entry : filament_ams_list) {
|
||||||
|
auto previous = previous_filament_ams_list.find(entry.first);
|
||||||
|
const auto *previous_changed = previous == previous_filament_ams_list.end() ? nullptr :
|
||||||
|
dynamic_cast<const ConfigOptionBool *>(previous->second.option("filament_changed"));
|
||||||
|
if (!same_device || previous_changed == nullptr ||
|
||||||
|
previous->second.opt_string("filament_id", 0u) != entry.second.opt_string("filament_id", 0u)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry.second.set_key_value("filament_changed",
|
||||||
|
new ConfigOptionBool{previous_changed->value});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool device_change = !same_device;
|
||||||
|
if (device_change) {
|
||||||
p->ams_list_device = device;
|
p->ams_list_device = device;
|
||||||
device_change = true;
|
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1% items") % filament_ams_list.size();
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1% items") % filament_ams_list.size();
|
||||||
if (wxGetApp().preset_bundle->filament_ams_list == filament_ams_list && !device_change)
|
if (wxGetApp().preset_bundle->filament_ams_list == filament_ams_list && !device_change)
|
||||||
@@ -5837,9 +5863,27 @@ void Sidebar::load_ams_list(MachineObject* obj)
|
|||||||
wxGetApp().preset_bundle->filament_ams_list = filament_ams_list;
|
wxGetApp().preset_bundle->filament_ams_list = filament_ams_list;
|
||||||
|
|
||||||
for (auto c : p->combos_filament){
|
for (auto c : p->combos_filament){
|
||||||
|
c->set_sync_badge(false);
|
||||||
c->update();
|
c->update();
|
||||||
if (device_change) {
|
}
|
||||||
c->ShowBadge(false);//change printer,then clear badge
|
|
||||||
|
if (!device_change) {
|
||||||
|
size_t combo_index = 0;
|
||||||
|
for (const auto &entry : filament_ams_list) {
|
||||||
|
const auto &tray = entry.second;
|
||||||
|
const bool has_filament = !tray.opt_string("filament_id", 0u).empty();
|
||||||
|
const bool is_placeholder = tray.has("filament_slot_placeholder") &&
|
||||||
|
tray.opt_bool("filament_slot_placeholder", 0u);
|
||||||
|
if (!has_filament && !is_placeholder) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (combo_index >= p->combos_filament.size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const auto *filament_changed = dynamic_cast<const ConfigOptionBool *>(tray.option("filament_changed"));
|
||||||
|
p->combos_filament[combo_index]->set_sync_badge(
|
||||||
|
has_filament && !is_placeholder && filament_changed != nullptr && filament_changed->value);
|
||||||
|
++combo_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6013,18 +6057,32 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
|
|||||||
auto tip = sync_color_only ? _L("Only filament color information has been synchronized from printer.") :
|
auto tip = sync_color_only ? _L("Only filament color information has been synchronized from printer.") :
|
||||||
_L("Filament type and color information have been synchronized, but slot information is not included.");
|
_L("Filament type and color information have been synchronized, but slot information is not included.");
|
||||||
c->SetToolTip(tip);
|
c->SetToolTip(tip);
|
||||||
c->ShowBadge(true);
|
c->set_sync_badge(true);
|
||||||
};
|
};
|
||||||
{ // badge ams filament
|
{ // badge ams filament
|
||||||
clear_combos_filament_badge();
|
clear_combos_filament_badge();
|
||||||
if (sync_result.direct_sync) {
|
if (sync_result.direct_sync) {
|
||||||
// Orca: PresetBundle::sync_ams_list rebuilds combos_filament
|
// A placeholder contributes a preserved project filament to the
|
||||||
// 1:1 from the AMS trays that produce a combo (loaded trays + placeholders; non-placeholder
|
// overwrite result, but it is not AMS-sourced and must not get a
|
||||||
// empty trays are skipped), so every resulting combo is AMS-sourced and gets a badge. The
|
// sync badge. Non-placeholder empty trays are omitted entirely.
|
||||||
// previous per-tray index walked the full filament_ams_list (including the skipped empties),
|
size_t combo_index = 0;
|
||||||
// so an empty slot before a loaded one dropped the badge for the trailing filaments.
|
for (const auto &entry : wxGetApp().preset_bundle->filament_ams_list) {
|
||||||
for (auto &c : p->combos_filament) {
|
const auto &tray = entry.second;
|
||||||
badge_combox_filament(c);
|
const bool has_filament = !tray.opt_string("filament_id", 0u).empty();
|
||||||
|
const bool is_placeholder = tray.has("filament_slot_placeholder") &&
|
||||||
|
tray.opt_bool("filament_slot_placeholder", 0u);
|
||||||
|
if (!has_filament && !is_placeholder) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (combo_index >= p->combos_filament.size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_placeholder) {
|
||||||
|
p->combos_filament[combo_index]->set_sync_badge(false);
|
||||||
|
} else {
|
||||||
|
badge_combox_filament(p->combos_filament[combo_index]);
|
||||||
|
}
|
||||||
|
++combo_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6292,6 +6350,11 @@ template<typename T> void setup_dialog_position(T& info)
|
|||||||
|
|
||||||
void Sidebar::pop_sync_nozzle_and_ams_dialog() {
|
void Sidebar::pop_sync_nozzle_and_ams_dialog() {
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " begin pop_sync_nozzle_and_ams_dialog";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " begin pop_sync_nozzle_and_ams_dialog";
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
if (!agent || agent->get_filament_sync_mode() == FilamentSyncMode::none) {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " filament synchronization is not supported; skipping dialog";
|
||||||
|
return;
|
||||||
|
}
|
||||||
wxTheApp->CallAfter([this]() {
|
wxTheApp->CallAfter([this]() {
|
||||||
SyncNozzleAndAmsDialog::InputInfo temp_na_info;
|
SyncNozzleAndAmsDialog::InputInfo temp_na_info;
|
||||||
wxPoint big_btn_pt;
|
wxPoint big_btn_pt;
|
||||||
@@ -6423,17 +6486,14 @@ void Sidebar::clear_combos_filament_badge()
|
|||||||
{
|
{
|
||||||
auto &combos_filament = p->combos_filament;
|
auto &combos_filament = p->combos_filament;
|
||||||
for (auto &c : combos_filament) { // clear flag
|
for (auto &c : combos_filament) { // clear flag
|
||||||
c->ShowBadge(false);
|
c->set_sync_badge(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sidebar::udpate_combos_filament_badge() {
|
void Sidebar::udpate_combos_filament_badge() {
|
||||||
auto &combos_filament = p->combos_filament;
|
auto &combos_filament = p->combos_filament;
|
||||||
for (auto &c : combos_filament) {
|
for (auto &c : combos_filament) {
|
||||||
auto selection = c->GetSelection();
|
c->update_badge_according_flag();
|
||||||
auto select_flag = c->GetFlag(selection);
|
|
||||||
auto ok = select_flag == (int) PresetComboBox::FilamentAMSType::FROM_AMS;
|
|
||||||
c->ShowBadge(ok);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12391,7 +12451,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
|||||||
sidebar->auto_calc_flushing_volumes(idx);
|
sidebar->auto_calc_flushing_volumes(idx);
|
||||||
}
|
}
|
||||||
auto select_flag = combo->GetFlag(selection);
|
auto select_flag = combo->GetFlag(selection);
|
||||||
combo->ShowBadge(select_flag == (int)PresetComboBox::FilamentAMSType::FROM_AMS);
|
combo->set_sync_badge(select_flag == (int)PresetComboBox::FilamentAMSType::FROM_AMS);
|
||||||
q->on_filament_change(idx);
|
q->on_filament_change(idx);
|
||||||
}
|
}
|
||||||
bool select_preset = !combo->selection_is_changed_according_to_physical_printers();
|
bool select_preset = !combo->selection_is_changed_according_to_physical_printers();
|
||||||
@@ -21010,9 +21070,14 @@ bool Plater::is_same_printer_for_connected_and_selected(bool popup_warning)
|
|||||||
}
|
}
|
||||||
if (!check_printer_initialized(obj, true, popup_warning))
|
if (!check_printer_initialized(obj, true, popup_warning))
|
||||||
return false;
|
return false;
|
||||||
Preset * machine_preset = get_printer_preset(obj);
|
const std::string machine_model = obj->printer_type;
|
||||||
if (!machine_preset)
|
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
const std::string selected_model = preset_bundle ? preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) : std::string();
|
||||||
|
if (!DevPrinterConfigUtil::is_optional_printer_model_id(machine_model) &&
|
||||||
|
!DevPrinterConfigUtil::is_optional_printer_model_id(selected_model) &&
|
||||||
|
!get_printer_preset(obj)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (wxGetApp().is_blocking_printing()) {
|
if (wxGetApp().is_blocking_printing()) {
|
||||||
if (popup_warning) {
|
if (popup_warning) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace Slic3r
|
|||||||
// IMPORTANT: ordinal order is the Plugins dialog Status sort priority.
|
// IMPORTANT: ordinal order is the Plugins dialog Status sort priority.
|
||||||
Activated,
|
Activated,
|
||||||
Error,
|
Error,
|
||||||
|
RuntimeError,
|
||||||
Inactive,
|
Inactive,
|
||||||
Loading
|
Loading
|
||||||
};
|
};
|
||||||
@@ -21,11 +22,28 @@ namespace Slic3r
|
|||||||
{
|
{
|
||||||
case PluginStatus::Activated: return "Activated";
|
case PluginStatus::Activated: return "Activated";
|
||||||
case PluginStatus::Error: return "Error";
|
case PluginStatus::Error: return "Error";
|
||||||
|
case PluginStatus::RuntimeError: return "RuntimeError";
|
||||||
case PluginStatus::Inactive: return "Inactive";
|
case PluginStatus::Inactive: return "Inactive";
|
||||||
case PluginStatus::Loading: return "Loading";
|
case PluginStatus::Loading: return "Loading";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Inactive";
|
return "Inactive";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why: a plugin whose module is live but whose catalog carries an error is a
|
||||||
|
// RUNTIME fault (e.g. a capability rejected at register time) - it stays
|
||||||
|
// loaded/checked and is only flagged, distinct from a load-time Error where
|
||||||
|
// the module never came up. Loading wins over both so an in-flight reload
|
||||||
|
// never flashes an error.
|
||||||
|
inline PluginStatus resolve_plugin_status(bool loading, bool has_error, bool is_loaded)
|
||||||
|
{
|
||||||
|
if (loading)
|
||||||
|
return PluginStatus::Loading;
|
||||||
|
if (has_error)
|
||||||
|
return is_loaded ? PluginStatus::RuntimeError : PluginStatus::Error;
|
||||||
|
if (is_loaded)
|
||||||
|
return PluginStatus::Activated;
|
||||||
|
return PluginStatus::Inactive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace Slic3r::GUI
|
} // namespace Slic3r::GUI
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ nlohmann::json build_plugin_payload_item(const PluginDialogItem& dialog_item)
|
|||||||
payload_item["label"] = dialog_item.display_name;
|
payload_item["label"] = dialog_item.display_name;
|
||||||
payload_item["source"] = to_string(dialog_item.source);
|
payload_item["source"] = to_string(dialog_item.source);
|
||||||
payload_item["status"] = to_string(dialog_item.status);
|
payload_item["status"] = to_string(dialog_item.status);
|
||||||
|
payload_item["is_loaded"] = dialog_item.is_loaded;
|
||||||
payload_item["error"] = dialog_item.error_text;
|
payload_item["error"] = dialog_item.error_text;
|
||||||
payload_item["update_status"] = to_string(dialog_item.update_status);
|
payload_item["update_status"] = to_string(dialog_item.update_status);
|
||||||
payload_item["unauthorized"] = dialog_item.unauthorized;
|
payload_item["unauthorized"] = dialog_item.unauthorized;
|
||||||
@@ -337,14 +338,7 @@ PluginDialogItem build_plugin_dialog_item(const PluginDescriptor& descriptor)
|
|||||||
item.sharing_token = descriptor.sharing_token;
|
item.sharing_token = descriptor.sharing_token;
|
||||||
item.thumbnail_url = descriptor.thumbnail_url;
|
item.thumbnail_url = descriptor.thumbnail_url;
|
||||||
|
|
||||||
if (item.loading)
|
item.status = resolve_plugin_status(item.loading, item.has_error, item.is_loaded);
|
||||||
item.status = PluginStatus::Loading;
|
|
||||||
else if (item.has_error)
|
|
||||||
item.status = PluginStatus::Error;
|
|
||||||
else if (item.is_loaded)
|
|
||||||
item.status = PluginStatus::Activated;
|
|
||||||
else
|
|
||||||
item.status = PluginStatus::Inactive;
|
|
||||||
|
|
||||||
item.available_actions = evaluate_action_policy(item);
|
item.available_actions = evaluate_action_policy(item);
|
||||||
const bool has_enabled_script = std::any_of(item.capabilities.begin(), item.capabilities.end(),
|
const bool has_enabled_script = std::any_of(item.capabilities.begin(), item.capabilities.end(),
|
||||||
@@ -790,6 +784,9 @@ void PluginsDialog::toggle_plugin(const std::string& plugin_key, bool enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Plugin unloaded from Plugins dialog: " << plugin_key;
|
BOOST_LOG_TRIVIAL(info) << "Plugin unloaded from Plugins dialog: " << plugin_key;
|
||||||
|
// A user-disabled plugin has no meaningful error state.
|
||||||
|
if (!manager.clear_plugin_error(plugin_key))
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "Failed to clear plugin error for " << plugin_key << " (failed to find)";
|
||||||
// A prior activation of this plugin is moot now; drop it so no stale "Activated" arrives later.
|
// A prior activation of this plugin is moot now; drop it so no stale "Activated" arrives later.
|
||||||
if (m_activating_plugin_key == plugin_key)
|
if (m_activating_plugin_key == plugin_key)
|
||||||
m_activating_plugin_key.clear();
|
m_activating_plugin_key.clear();
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ std::string PrePrintChecker::get_print_status_info(PrintDialogStatus status)
|
|||||||
case PrintStatusRackReading: return "PrintStatusRackReading";
|
case PrintStatusRackReading: return "PrintStatusRackReading";
|
||||||
case PrintStatusRackNozzleNumUnmeetWarning: return "PrintStatusRackNozzleNumUnmeetWarning";
|
case PrintStatusRackNozzleNumUnmeetWarning: return "PrintStatusRackNozzleNumUnmeetWarning";
|
||||||
case PrintStatusHasUnreliableNozzleWarning: return "PrintStatusHasUnreliableNozzleWarning";
|
case PrintStatusHasUnreliableNozzleWarning: return "PrintStatusHasUnreliableNozzleWarning";
|
||||||
|
case PrintStatusOptionalPrinterModel: return "PrintStatusOptionalPrinterModel";
|
||||||
case PrintStatusWarningExtFilamentNotMatch: return "PrintStatusWarningExtFilamentNotMatch";
|
case PrintStatusWarningExtFilamentNotMatch: return "PrintStatusWarningExtFilamentNotMatch";
|
||||||
case PrintStatusFilamentWarningNozzleHRC: return "PrintStatusFilamentWarningNozzleHRC";
|
case PrintStatusFilamentWarningNozzleHRC: return "PrintStatusFilamentWarningNozzleHRC";
|
||||||
case PrintStatusTPUUnsupportCaliOn: return "PrintStatusTPUUnsupportCaliOn";
|
case PrintStatusTPUUnsupportCaliOn: return "PrintStatusTPUUnsupportCaliOn";
|
||||||
@@ -104,6 +105,7 @@ wxString PrePrintChecker::get_pre_state_msg(PrintDialogStatus status)
|
|||||||
case PrintStatusNeedConsistencyUpgrading: return _L("Cannot send the print job to a printer whose firmware must be updated.");
|
case PrintStatusNeedConsistencyUpgrading: return _L("Cannot send the print job to a printer whose firmware must be updated.");
|
||||||
case PrintStatusBlankPlate: return _L("Cannot send a print job for an empty plate.");
|
case PrintStatusBlankPlate: return _L("Cannot send a print job for an empty plate.");
|
||||||
case PrintStatusTimelapseNoSdcard: return _L("Storage needs to be inserted to record timelapse.");
|
case PrintStatusTimelapseNoSdcard: return _L("Storage needs to be inserted to record timelapse.");
|
||||||
|
case PrintStatusOptionalPrinterModel: return _L("The selected printer model could not be identified, so compatibility with the print file configuration cannot be verified. Please verify the printer preset before sending.");
|
||||||
case PrintStatusMixAmsAndVtSlotWarning: return _L("You have selected both external and AMS filaments for an extruder. You will need to manually switch the external filament during printing.");
|
case PrintStatusMixAmsAndVtSlotWarning: return _L("You have selected both external and AMS filaments for an extruder. You will need to manually switch the external filament during printing.");
|
||||||
case PrintStatusTPUUnsupportAutoCali: return _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration.");
|
case PrintStatusTPUUnsupportAutoCali: return _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration.");
|
||||||
case PrintStatusWarningKvalueNotUsed: return _L("Set dynamic flow calibration to 'OFF' to enable custom dynamic flow value.");
|
case PrintStatusWarningKvalueNotUsed: return _L("Set dynamic flow calibration to 'OFF' to enable custom dynamic flow value.");
|
||||||
@@ -379,4 +381,3 @@ bool PrinterMsgPanel::UpdateInfos(const std::vector<prePrintInfo>& infos)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ enum PrintDialogStatus : unsigned int {
|
|||||||
// Orca: a nozzle diameter that differs from the one the printer remembers is a warning,
|
// Orca: a nozzle diameter that differs from the one the printer remembers is a warning,
|
||||||
// not an error, so non-standard nozzles can still be printed with.
|
// not an error, so non-standard nozzles can still be printed with.
|
||||||
PrintStatusNozzleDiameterMismatch,
|
PrintStatusNozzleDiameterMismatch,
|
||||||
|
PrintStatusOptionalPrinterModel,
|
||||||
PrintStatusPrinterWarningEnd,
|
PrintStatusPrinterWarningEnd,
|
||||||
|
|
||||||
// Warnings for filament
|
// Warnings for filament
|
||||||
|
|||||||
@@ -361,7 +361,8 @@ wxString PresetComboBox::get_preset_item_name(unsigned int index)
|
|||||||
return GetString(index);
|
return GetString(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, MachineObject *> machine_list = dev->get_my_machine_list();
|
std::map<std::string, MachineObject *> machine_list =
|
||||||
|
dev->get_my_machine_list(dev->get_current_printer_agent_id());
|
||||||
if (machine_list.empty()) {
|
if (machine_list.empty()) {
|
||||||
assert(false);
|
assert(false);
|
||||||
m_selected_dev_id.clear();
|
m_selected_dev_id.clear();
|
||||||
@@ -479,7 +480,8 @@ void PresetComboBox::add_connected_printers(std::string selected, bool alias_nam
|
|||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::map<std::string, MachineObject *> machine_list = dev->get_my_machine_list();
|
std::map<std::string, MachineObject *> machine_list =
|
||||||
|
dev->get_my_machine_list(dev->get_current_printer_agent_id());
|
||||||
if (machine_list.empty())
|
if (machine_list.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -999,7 +1001,13 @@ void PlaterPresetComboBox::update_badge_according_flag() {
|
|||||||
auto selection = GetSelection();
|
auto selection = GetSelection();
|
||||||
auto select_flag = GetFlag(selection);
|
auto select_flag = GetFlag(selection);
|
||||||
auto ok = select_flag == (int) PresetComboBox::FilamentAMSType::FROM_AMS;
|
auto ok = select_flag == (int) PresetComboBox::FilamentAMSType::FROM_AMS;
|
||||||
ShowBadge(ok);
|
ShowBadge(m_sync_badge || ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaterPresetComboBox::set_sync_badge(bool show)
|
||||||
|
{
|
||||||
|
m_sync_badge = show;
|
||||||
|
ShowBadge(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlaterPresetComboBox::switch_to_tab()
|
bool PlaterPresetComboBox::switch_to_tab()
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ public:
|
|||||||
void msw_rescale() override;
|
void msw_rescale() override;
|
||||||
void OnSelect(wxCommandEvent& evt) override;
|
void OnSelect(wxCommandEvent& evt) override;
|
||||||
void update_badge_according_flag();
|
void update_badge_according_flag();
|
||||||
|
void set_sync_badge(bool show);
|
||||||
|
|
||||||
FilamentColor get_cur_color_info();
|
FilamentColor get_cur_color_info();
|
||||||
void show_default_color_picker();
|
void show_default_color_picker();
|
||||||
@@ -214,6 +215,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// BBS
|
// BBS
|
||||||
wxColor m_color;
|
wxColor m_color;
|
||||||
|
bool m_sync_badge{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
#include <wx/dcgraph.h>
|
#include <wx/dcgraph.h>
|
||||||
|
#include <wx/filedlg.h>
|
||||||
#include <miniz.h>
|
#include <miniz.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include "DeviceCore/DevManager.h"
|
#include "DeviceCore/DevManager.h"
|
||||||
#include "DeviceCore/DevStorage.h"
|
#include "DeviceCore/DevStorage.h"
|
||||||
#include "md4c/src/md4c-html.h"
|
#include "md4c/src/md4c-html.h"
|
||||||
|
#include "../Utils/Http.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
@@ -1461,6 +1463,45 @@ InputIpAddressDialog::InputIpAddressDialog(wxWindow *parent)
|
|||||||
m_input_top_sizer->Add(0, 0, 0, wxTOP, FromDIP(4));
|
m_input_top_sizer->Add(0, 0, 0, wxTOP, FromDIP(4));
|
||||||
m_input_top_sizer->Add(m_input_area, 0, wxRIGHT | wxEXPAND, FromDIP(18));
|
m_input_top_sizer->Add(m_input_area, 0, wxRIGHT | wxEXPAND, FromDIP(18));
|
||||||
|
|
||||||
|
m_tips_cafile = new Label(ip_input_top_panel, _L("HTTPS CA File"));
|
||||||
|
m_input_cafile = new wxTextCtrl(ip_input_top_panel, wxID_ANY);
|
||||||
|
m_input_cafile->SetMinSize(wxSize(FromDIP(260), FromDIP(28)));
|
||||||
|
m_input_cafile->SetMaxSize(wxSize(FromDIP(260), FromDIP(28)));
|
||||||
|
|
||||||
|
m_button_cafile = new Button(ip_input_top_panel, _L("Browse") + " " + dots);
|
||||||
|
m_button_cafile->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
||||||
|
m_button_cafile->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||||
|
static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*");
|
||||||
|
wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks,
|
||||||
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
|
if (openFileDialog.ShowModal() != wxID_CANCEL)
|
||||||
|
m_input_cafile->SetValue(openFileDialog.GetPath());
|
||||||
|
});
|
||||||
|
|
||||||
|
auto cafile_input_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
cafile_input_sizer->Add(m_input_cafile, 1, wxALIGN_CENTER_VERTICAL);
|
||||||
|
cafile_input_sizer->Add(m_button_cafile, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
|
||||||
|
|
||||||
|
m_cafile_hint = new Label(ip_input_top_panel, _L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."));
|
||||||
|
m_cafile_hint->Wrap(FromDIP(352));
|
||||||
|
|
||||||
|
m_input_top_sizer->Add(m_tips_cafile, 0, wxTOP | wxEXPAND, FromDIP(10));
|
||||||
|
m_input_top_sizer->Add(cafile_input_sizer, 0, wxTOP | wxEXPAND, FromDIP(4));
|
||||||
|
m_input_top_sizer->Add(m_cafile_hint, 0, wxTOP | wxEXPAND, FromDIP(4));
|
||||||
|
|
||||||
|
if (!Http::ca_file_supported()) {
|
||||||
|
m_input_cafile->Disable();
|
||||||
|
m_button_cafile->Disable();
|
||||||
|
m_cafile_hint->SetLabel(_L("This system uses HTTPS certificates from the system Certificate Store or Keychain. To use a custom CA file, import it there."));
|
||||||
|
m_cafile_hint->Wrap(FromDIP(352));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wxGetApp().preset_bundle) {
|
||||||
|
const auto& config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
if (config.has("printhost_cafile"))
|
||||||
|
m_input_cafile->SetValue(from_u8(config.opt_string("printhost_cafile")));
|
||||||
|
}
|
||||||
|
|
||||||
ip_input_top_panel->SetSizer(m_input_top_sizer);
|
ip_input_top_panel->SetSizer(m_input_top_sizer);
|
||||||
ip_input_top_panel->Layout();
|
ip_input_top_panel->Layout();
|
||||||
ip_input_top_panel->Fit();
|
ip_input_top_panel->Fit();
|
||||||
@@ -1736,7 +1777,8 @@ void InputIpAddressDialog::set_machine_obj(MachineObject* obj)
|
|||||||
auto str_ip = m_input_ip->GetTextCtrl()->GetValue();
|
auto str_ip = m_input_ip->GetTextCtrl()->GetValue();
|
||||||
auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
||||||
// ORCA enabling / disabling buttons with conditions enough to change its style
|
// ORCA enabling / disabling buttons with conditions enough to change its style
|
||||||
m_button_ok->Enable(isIp(str_ip.ToStdString()) && str_access_code.Length() == 8);
|
m_button_ok->Enable(isIp(str_ip.ToStdString()) &&
|
||||||
|
(str_access_code.IsEmpty() || str_access_code.Length() >= 8));
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
Fit();
|
Fit();
|
||||||
@@ -1801,6 +1843,8 @@ void InputIpAddressDialog::on_ok(wxMouseEvent& evt)
|
|||||||
m_trouble_shoot->Hide();
|
m_trouble_shoot->Hide();
|
||||||
std::string str_ip = m_input_ip->GetTextCtrl()->GetValue().ToStdString();
|
std::string str_ip = m_input_ip->GetTextCtrl()->GetValue().ToStdString();
|
||||||
std::string str_access_code = m_input_access_code->GetTextCtrl()->GetValue().ToStdString();
|
std::string str_access_code = m_input_access_code->GetTextCtrl()->GetValue().ToStdString();
|
||||||
|
if (str_access_code.empty())
|
||||||
|
str_access_code = "88888888";
|
||||||
std::string str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both).ToStdString();
|
std::string str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both).ToStdString();
|
||||||
// Serial number should not contain lower case letters, and bambu_network plugin crashes
|
// Serial number should not contain lower case letters, and bambu_network plugin crashes
|
||||||
// if user entered the wrong serial number, so we call `Upper()` here.
|
// if user entered the wrong serial number, so we call `Upper()` here.
|
||||||
@@ -1820,6 +1864,12 @@ void InputIpAddressDialog::on_ok(wxMouseEvent& evt)
|
|||||||
Layout();
|
Layout();
|
||||||
Fit();
|
Fit();
|
||||||
|
|
||||||
|
if (wxGetApp().preset_bundle) {
|
||||||
|
auto& config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
if (Http::ca_file_supported())
|
||||||
|
config.opt_string("printhost_cafile") = m_input_cafile->GetValue().ToStdString();
|
||||||
|
}
|
||||||
|
|
||||||
token_.reset(this, nop_deleter);
|
token_.reset(this, nop_deleter);
|
||||||
m_thread = new boost::thread(boost::bind(&InputIpAddressDialog::workerThreadFunc, this, str_ip, str_access_code, str_sn, str_model_id, str_name));
|
m_thread = new boost::thread(boost::bind(&InputIpAddressDialog::workerThreadFunc, this, str_ip, str_access_code, str_sn, str_model_id, str_name));
|
||||||
}
|
}
|
||||||
@@ -1835,6 +1885,8 @@ void InputIpAddressDialog::on_send_retry()
|
|||||||
Fit();
|
Fit();
|
||||||
wxString ip = m_input_ip->GetTextCtrl()->GetValue();
|
wxString ip = m_input_ip->GetTextCtrl()->GetValue();
|
||||||
wxString str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
wxString str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
||||||
|
if (str_access_code.IsEmpty())
|
||||||
|
str_access_code = "88888888";
|
||||||
|
|
||||||
// check support function
|
// check support function
|
||||||
if (!m_obj) return;
|
if (!m_obj) return;
|
||||||
@@ -2056,7 +2108,7 @@ void InputIpAddressDialog::on_text(wxCommandEvent &evt)
|
|||||||
auto str_ip = m_input_ip->GetTextCtrl()->GetValue();
|
auto str_ip = m_input_ip->GetTextCtrl()->GetValue();
|
||||||
auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
auto str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
||||||
|
|
||||||
if (str_access_code.empty()) {
|
if (str_access_code.IsEmpty()) {
|
||||||
str_access_code = "88888888";
|
str_access_code = "88888888";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2072,7 +2124,8 @@ void InputIpAddressDialog::on_text(wxCommandEvent &evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ORCA enabling / disabling buttons with conditions enough to change its style
|
// ORCA enabling / disabling buttons with conditions enough to change its style
|
||||||
bool enable_btns = isIp(str_ip.ToStdString()) && str_access_code.Length() == 8 && invalid_access_code;
|
bool valid_access_code_length = str_access_code.IsEmpty() || str_access_code.Length() >= 8;
|
||||||
|
bool enable_btns = isIp(str_ip.ToStdString()) && valid_access_code_length && invalid_access_code;
|
||||||
m_button_manual_setup->Enable(enable_btns);
|
m_button_manual_setup->Enable(enable_btns);
|
||||||
m_button_ok->Enable(enable_btns);
|
m_button_ok->Enable(enable_btns);
|
||||||
|
|
||||||
@@ -2087,7 +2140,7 @@ InputIpAddressDialog::~InputIpAddressDialog()
|
|||||||
|
|
||||||
void InputIpAddressDialog::on_dpi_changed(const wxRect& suggested_rect)
|
void InputIpAddressDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||||
{
|
{
|
||||||
|
m_button_cafile->Rescale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -315,12 +315,16 @@ public:
|
|||||||
Button* m_button_manual_setup{ nullptr };
|
Button* m_button_manual_setup{ nullptr };
|
||||||
Label* m_tips_ip{ nullptr };
|
Label* m_tips_ip{ nullptr };
|
||||||
Label* m_tips_access_code{ nullptr };
|
Label* m_tips_access_code{ nullptr };
|
||||||
|
Label* m_tips_cafile{ nullptr };
|
||||||
|
Label* m_cafile_hint{ nullptr };
|
||||||
Label* m_tips_sn{nullptr};
|
Label* m_tips_sn{nullptr};
|
||||||
Label* m_tips_modelID{nullptr};
|
Label* m_tips_modelID{nullptr};
|
||||||
Label* m_test_right_msg{ nullptr };
|
Label* m_test_right_msg{ nullptr };
|
||||||
Label* m_test_wrong_msg{ nullptr };
|
Label* m_test_wrong_msg{ nullptr };
|
||||||
TextInput* m_input_ip{ nullptr };
|
TextInput* m_input_ip{ nullptr };
|
||||||
TextInput* m_input_access_code{ nullptr };
|
TextInput* m_input_access_code{ nullptr };
|
||||||
|
wxTextCtrl* m_input_cafile{ nullptr };
|
||||||
|
Button* m_button_cafile{ nullptr };
|
||||||
TextInput* m_input_printer_name{ nullptr };
|
TextInput* m_input_printer_name{ nullptr };
|
||||||
TextInput* m_input_sn{ nullptr };
|
TextInput* m_input_sn{ nullptr };
|
||||||
ComboBox* m_input_modelID{ nullptr };
|
ComboBox* m_input_modelID{ nullptr };
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "Jobs/PlaterWorker.hpp"
|
#include "Jobs/PlaterWorker.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevConfig.h"
|
#include "DeviceCore/DevConfig.h"
|
||||||
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
#include "DeviceCore/DevNozzleSystem.h"
|
#include "DeviceCore/DevNozzleSystem.h"
|
||||||
#include "DeviceCore/DevNozzleRack.h"
|
#include "DeviceCore/DevNozzleRack.h"
|
||||||
#include "DeviceCore/DevExtensionTool.h"
|
#include "DeviceCore/DevExtensionTool.h"
|
||||||
@@ -1125,7 +1126,10 @@ bool SelectMachineDialog::do_ams_mapping(MachineObject *obj_,bool use_ams)
|
|||||||
|
|
||||||
int filament_result = 0;
|
int filament_result = 0;
|
||||||
std::vector<bool> map_opt; //four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext
|
std::vector<bool> map_opt; //four values: use_left_ams, use_right_ams, use_left_ext, use_right_ext
|
||||||
if (nozzle_nums > 1){
|
// Orca: only do the per-physical-extruder left/right split when the device actually reports
|
||||||
|
// 2+ extruders. A non-BBL multi-nozzle printer (e.g. Snapmaker U1) reports a single extruder
|
||||||
|
// with one filament pool, so it maps as a single surface via the else branch below.
|
||||||
|
if (nozzle_nums > 1 && obj_->GetExtderSystem()->GetTotalExtderCount() > 1){
|
||||||
//get nozzle property, the extders are same?
|
//get nozzle property, the extders are same?
|
||||||
if (true/*!can_hybrid_mapping(obj_get_extder_data())*/){
|
if (true/*!can_hybrid_mapping(obj_get_extder_data())*/){
|
||||||
std::vector<FilamentInfo> m_ams_mapping_result_left, m_ams_mapping_result_right;
|
std::vector<FilamentInfo> m_ams_mapping_result_left, m_ams_mapping_result_right;
|
||||||
@@ -2284,9 +2288,7 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
|
|||||||
// Fill the real per-printer max color count into the %s template.
|
// Fill the real per-printer max color count into the %s template.
|
||||||
if (!params.empty())
|
if (!params.empty())
|
||||||
msg = wxString::Format(m_pre_print_checker.get_pre_state_msg(status), params[0], params[0]);
|
msg = wxString::Format(m_pre_print_checker.get_pre_state_msg(status), params[0], params[0]);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusAmsMappingU0Invalid) {
|
||||||
|
|
||||||
else if (status == PrintDialogStatus::PrintStatusAmsMappingU0Invalid) {
|
|
||||||
wxString msg_text;
|
wxString msg_text;
|
||||||
if (params.size() > 1)
|
if (params.size() > 1)
|
||||||
msg_text = wxString::Format(_L("Filament %s does not match the filament in AMS slot %s. Please update the printer firmware to support AMS slot assignment."), params[0], params[1]);
|
msg_text = wxString::Format(_L("Filament %s does not match the filament in AMS slot %s. Please update the printer firmware to support AMS slot assignment."), params[0], params[1]);
|
||||||
@@ -2312,8 +2314,10 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
|
|||||||
} else if (status == PrintDialogStatus::PrintStatusNoSdcard) {
|
} else if (status == PrintDialogStatus::PrintStatusNoSdcard) {
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
}else if (status == PrintDialogStatus::PrintStatusUnsupportedPrinter) {
|
} else if (status == PrintDialogStatus::PrintStatusUnsupportedPrinter ||
|
||||||
|
status == PrintDialogStatus::PrintStatusOptionalPrinterModel) {
|
||||||
wxString msg_text;
|
wxString msg_text;
|
||||||
|
const bool block_send = status == PrintDialogStatus::PrintStatusUnsupportedPrinter;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
@@ -2339,17 +2343,21 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
|
|||||||
|
|
||||||
auto target_print_name = wxString(DevPrinterConfigUtil::get_printer_display_name(target_model_id));
|
auto target_print_name = wxString(DevPrinterConfigUtil::get_printer_display_name(target_model_id));
|
||||||
target_print_name.Replace(wxT("Bambu Lab "), wxEmptyString);
|
target_print_name.Replace(wxT("Bambu Lab "), wxEmptyString);
|
||||||
msg_text = wxString::Format(_L("The selected printer (%s) is incompatible with the print file configuration (%s). Please adjust the printer preset in the prepare page or choose a compatible printer on this page."), sourcet_print_name, target_print_name);
|
if (block_send) {
|
||||||
|
msg_text = wxString::Format(_L("The selected printer (%s) is incompatible with the print file configuration (%s). Please adjust the printer preset in the prepare page or choose a compatible printer on this page."), sourcet_print_name, target_print_name);
|
||||||
|
} else {
|
||||||
|
msg_text = wxString::Format(_L("The selected printer (%s) has an unknown model, so compatibility with the print file configuration (%s) cannot be verified. Please verify the printer preset before sending."), sourcet_print_name, target_print_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
msg = msg_text;
|
msg = msg_text;
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(!block_send);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(!block_send);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2526,15 +2534,7 @@ bool SelectMachineDialog::is_blocking_printing(MachineObject* obj_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source_model != target_model) {
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
std::vector<std::string> compatible_machine = obj_->get_compatible_machine();
|
|
||||||
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
|
|
||||||
if (it == compatible_machine.end()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_set<int> _get_used_nozzle_idxes()
|
static std::unordered_set<int> _get_used_nozzle_idxes()
|
||||||
@@ -2622,6 +2622,10 @@ bool SelectMachineDialog::is_same_printer_model()
|
|||||||
if(preset_bundle == nullptr) return result;
|
if(preset_bundle == nullptr) return result;
|
||||||
const auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
const auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||||
const auto target_model = obj_->printer_type;
|
const auto target_model = obj_->printer_type;
|
||||||
|
if (DevPrinterConfigUtil::is_optional_printer_model_id(source_model) ||
|
||||||
|
DevPrinterConfigUtil::is_optional_printer_model_id(target_model)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Orca: ignore P1P -> P1S
|
// Orca: ignore P1P -> P1S
|
||||||
if (source_model != target_model) {
|
if (source_model != target_model) {
|
||||||
if ((source_model == "C12" && target_model == "C11") || (source_model == "C11" && target_model == "C12") ||
|
if ((source_model == "C12" && target_model == "C11") || (source_model == "C11" && target_model == "C12") ||
|
||||||
@@ -3696,10 +3700,32 @@ void SelectMachineDialog::on_send_print()
|
|||||||
m_print_job->on_success([this]() { finish_mode(); });
|
m_print_job->on_success([this]() { finish_mode(); });
|
||||||
|
|
||||||
m_print_job->on_check_ip_address_fail([this]() {
|
m_print_job->on_check_ip_address_fail([this]() {
|
||||||
wxCommandEvent* evt = new wxCommandEvent(EVT_CLEAR_IPADDRESS);
|
// Invoked from the PrintJob worker thread when the LAN pre-flight (file upload
|
||||||
wxQueueEvent(this, evt);
|
// verification) fails. Marshal device/UI access to the main thread.
|
||||||
wxGetApp().show_ip_address_enter_dialog();
|
CallAfter([this]()
|
||||||
});
|
{
|
||||||
|
// Reset the dialog out of sending mode so the user can retry.
|
||||||
|
wxCommandEvent* evt = new wxCommandEvent(EVT_CLEAR_IPADDRESS);
|
||||||
|
wxQueueEvent(this, evt);
|
||||||
|
|
||||||
|
DeviceManager* dev = wxGetApp().getDeviceManager();
|
||||||
|
MachineObject* obj = dev ? dev->get_selected_machine() : nullptr;
|
||||||
|
|
||||||
|
if (obj && obj->is_connected())
|
||||||
|
{
|
||||||
|
// Connected: failed on file upload
|
||||||
|
MessageDialog dlg(this,
|
||||||
|
_L("Failed to upload the file to the printer's storage. Please try again."),
|
||||||
|
_L("Send Failed"), wxOK | wxICON_ERROR);
|
||||||
|
dlg.ShowModal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not connected: reenter ip and access code
|
||||||
|
wxGetApp().show_ip_address_enter_dialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// update ota version
|
// update ota version
|
||||||
NetworkAgent* agent = wxGetApp().getAgent();
|
NetworkAgent* agent = wxGetApp().getAgent();
|
||||||
@@ -4533,11 +4559,13 @@ bool SelectMachineDialog::CheckErrorExtruderNozzleWithSlicing(MachineObject* obj
|
|||||||
|
|
||||||
// check nozzle data valid
|
// check nozzle data valid
|
||||||
{
|
{
|
||||||
if (installed_ext_nozzle.GetNozzleType() == NozzleType::ntUndefine ||
|
// Commented out the following as ntUndefine and 0.0f are default values
|
||||||
installed_ext_nozzle.GetNozzleDiameter() <= 0.0f) {
|
// (signifying that the value is not given) that should PASS, not fail
|
||||||
show_status(PrintDialogStatus::PrintStatusNozzleDataInvalid);
|
// if (installed_ext_nozzle.GetNozzleType() == NozzleType::ntUndefine ||
|
||||||
return false;
|
// installed_ext_nozzle.GetNozzleDiameter() <= 0.0f) {
|
||||||
}
|
// show_status(PrintDialogStatus::PrintStatusNozzleDataInvalid);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
if (obj_->is_nozzle_flow_type_supported() &&
|
if (obj_->is_nozzle_flow_type_supported() &&
|
||||||
installed_ext_nozzle.GetNozzleFlowType() == NozzleFlowType::NONE_FLOWTYPE) {
|
installed_ext_nozzle.GetNozzleFlowType() == NozzleFlowType::NONE_FLOWTYPE) {
|
||||||
@@ -4566,7 +4594,10 @@ bool SelectMachineDialog::CheckErrorExtruderNozzleWithSlicing(MachineObject* obj
|
|||||||
|
|
||||||
// check nozzle diameter
|
// check nozzle diameter
|
||||||
{
|
{
|
||||||
if (slicing_ext.nozzle_diameter != installed_ext_nozzle.GetNozzleDiameter()) {
|
// 0.0f is default when there is no nozzle diameter is given.
|
||||||
|
// In nozzle_diameter == 0.0f case, it passes and does not require a comparison
|
||||||
|
if (installed_ext_nozzle.GetNozzleDiameter() > 0.0f &&
|
||||||
|
slicing_ext.nozzle_diameter != installed_ext_nozzle.GetNozzleDiameter()) {
|
||||||
std::vector<wxString> msg_params;
|
std::vector<wxString> msg_params;
|
||||||
if (ext_sys->GetTotalExtderCount() == 2) {
|
if (ext_sys->GetTotalExtderCount() == 2) {
|
||||||
const wxString& mismatch_nozzle_str = _get_nozzle_name(ext_sys->GetTotalExtderCount(), slicing_ext_idx);
|
const wxString& mismatch_nozzle_str = _get_nozzle_name(ext_sys->GetTotalExtderCount(), slicing_ext_idx);
|
||||||
@@ -4760,6 +4791,22 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_optional_printer_model = DevPrinterConfigUtil::is_optional_printer_model_id(obj_->printer_type);
|
||||||
|
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
||||||
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
has_optional_printer_model = has_optional_printer_model ||
|
||||||
|
(preset_bundle && DevPrinterConfigUtil::is_optional_printer_model_id(
|
||||||
|
preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle)));
|
||||||
|
} else if (m_print_type == PrintFromType::FROM_SDCARD_VIEW && !m_required_data_plate_data_list.empty()) {
|
||||||
|
has_optional_printer_model = has_optional_printer_model ||
|
||||||
|
DevPrinterConfigUtil::is_optional_printer_model_id(
|
||||||
|
m_required_data_plate_data_list[m_print_plate_idx]->printer_model_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_optional_printer_model) {
|
||||||
|
show_status(PrintDialogStatus::PrintStatusOptionalPrinterModel);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_blocking_printing(obj_)) {
|
if (is_blocking_printing(obj_)) {
|
||||||
show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter);
|
show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter);
|
||||||
return;
|
return;
|
||||||
@@ -5482,8 +5529,8 @@ void SelectMachineDialog::reset_and_sync_ams_list()
|
|||||||
item = new MaterialItem(m_filament_left_panel, colour_rgb, _L(display_materials[extruder]));
|
item = new MaterialItem(m_filament_left_panel, colour_rgb, _L(display_materials[extruder]));
|
||||||
m_sizer_ams_mapping_left->Add(item, 0, wxALL, FromDIP(5));
|
m_sizer_ams_mapping_left->Add(item, 0, wxALL, FromDIP(5));
|
||||||
}
|
}
|
||||||
else if (m_filaments_map[extruder] == 2)
|
else // map == 2, or (non-BBL multi-nozzle) 3+; update_material_item_pos() collapses
|
||||||
{
|
{ // these into the single panel when the device reports < 2 extruders.
|
||||||
item = new MaterialItem(m_filament_right_panel, colour_rgb, _L(display_materials[extruder]));
|
item = new MaterialItem(m_filament_right_panel, colour_rgb, _L(display_materials[extruder]));
|
||||||
m_sizer_ams_mapping_right->Add(item, 0, wxALL, FromDIP(5));
|
m_sizer_ams_mapping_right->Add(item, 0, wxALL, FromDIP(5));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "BitmapCache.hpp"
|
#include "BitmapCache.hpp"
|
||||||
|
|
||||||
#include "DeviceCore/DevManager.h"
|
#include "DeviceCore/DevManager.h"
|
||||||
|
#include "DeviceCore/DevConfigUtil.h"
|
||||||
#include "DeviceCore/DevStorage.h"
|
#include "DeviceCore/DevStorage.h"
|
||||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||||
|
|
||||||
@@ -300,7 +301,7 @@ SendToPrinterDialog::SendToPrinterDialog(Plater *plater)
|
|||||||
m_storage_panel->Layout();
|
m_storage_panel->Layout();
|
||||||
|
|
||||||
// try to connect
|
// try to connect
|
||||||
m_statictext_printer_msg = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL);
|
m_statictext_printer_msg = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(400), -1), wxALIGN_CENTER_HORIZONTAL);
|
||||||
m_statictext_printer_msg->SetFont(::Label::Body_13);
|
m_statictext_printer_msg->SetFont(::Label::Body_13);
|
||||||
m_statictext_printer_msg->SetForegroundColour(*wxBLACK);
|
m_statictext_printer_msg->SetForegroundColour(*wxBLACK);
|
||||||
m_statictext_printer_msg->Hide();
|
m_statictext_printer_msg->Hide();
|
||||||
@@ -760,9 +761,25 @@ void SendToPrinterDialog::update_priner_status_msg(wxString msg, bool is_warning
|
|||||||
if (str_new != str_old) {
|
if (str_new != str_old) {
|
||||||
if (m_statictext_printer_msg->GetLabel() != msg) {
|
if (m_statictext_printer_msg->GetLabel() != msg) {
|
||||||
m_statictext_printer_msg->SetLabel(msg);
|
m_statictext_printer_msg->SetLabel(msg);
|
||||||
m_statictext_printer_msg->SetMinSize(wxSize(FromDIP(400), -1));
|
const int wrap_width = FromDIP(400);
|
||||||
m_statictext_printer_msg->SetMaxSize(wxSize(FromDIP(400), -1));
|
m_statictext_printer_msg->Wrap(wrap_width);
|
||||||
m_statictext_printer_msg->Wrap(FromDIP(400));
|
int line_count = 1;
|
||||||
|
const wxString wrapped_label = m_statictext_printer_msg->GetLabel();
|
||||||
|
for (size_t i = 0; i < wrapped_label.length(); ++i) {
|
||||||
|
if (wrapped_label[i] == '\n')
|
||||||
|
++line_count;
|
||||||
|
}
|
||||||
|
wxCoord text_width = 0;
|
||||||
|
wxCoord text_height = 0;
|
||||||
|
m_statictext_printer_msg->GetTextExtent(msg, &text_width, &text_height);
|
||||||
|
const int extent_line_count = text_width > 0 ?
|
||||||
|
std::max(1, (static_cast<int>(text_width) + wrap_width - 1) / wrap_width) : 1;
|
||||||
|
line_count = std::max(line_count, extent_line_count);
|
||||||
|
const int line_height = std::max(m_statictext_printer_msg->GetCharHeight(), static_cast<int>(text_height));
|
||||||
|
const int min_height = std::max(m_statictext_printer_msg->GetBestSize().GetHeight(),
|
||||||
|
line_count * line_height + FromDIP(2));
|
||||||
|
m_statictext_printer_msg->SetMinSize(wxSize(wrap_width, min_height));
|
||||||
|
m_statictext_printer_msg->SetMaxSize(wxDefaultSize);
|
||||||
m_statictext_printer_msg->Show();
|
m_statictext_printer_msg->Show();
|
||||||
Layout();
|
Layout();
|
||||||
Fit();
|
Fit();
|
||||||
@@ -1102,7 +1119,7 @@ void SendToPrinterDialog::update_user_printer()
|
|||||||
wxArrayString machine_list_name;
|
wxArrayString machine_list_name;
|
||||||
std::map<std::string, MachineObject*> option_list;
|
std::map<std::string, MachineObject*> option_list;
|
||||||
|
|
||||||
option_list = dev->get_my_machine_list();
|
option_list = dev->get_my_machine_list(dev->get_current_printer_agent_id());
|
||||||
|
|
||||||
// same machine only appear once
|
// same machine only appear once
|
||||||
for (auto it = option_list.begin(); it != option_list.end(); it++) {
|
for (auto it = option_list.begin(); it != option_list.end(); it++) {
|
||||||
@@ -1332,17 +1349,7 @@ bool SendToPrinterDialog::is_blocking_printing(MachineObject* obj_)
|
|||||||
|
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
auto source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||||
auto target_model = obj_->printer_type;
|
return !DevPrinterConfigUtil::is_printer_model_compatible(source_model, *obj_);
|
||||||
|
|
||||||
if (source_model != target_model) {
|
|
||||||
std::vector<std::string> compatible_machine = obj_->get_compatible_machine();
|
|
||||||
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
|
|
||||||
if (it == compatible_machine.end()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendToPrinterDialog::Enable_Refresh_Button(bool en)
|
void SendToPrinterDialog::Enable_Refresh_Button(bool en)
|
||||||
@@ -1413,79 +1420,68 @@ void SendToPrinterDialog::show_status(PrintDialogStatus status, std::vector<wxSt
|
|||||||
update_print_status_msg(wxEmptyString, false, false);
|
update_print_status_msg(wxEmptyString, false, false);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusInvalidPrinter) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusInvalidPrinter) {
|
|
||||||
update_print_status_msg(wxEmptyString, true, true);
|
update_print_status_msg(wxEmptyString, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusConnectingServer) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusConnectingServer) {
|
|
||||||
wxString msg_text = _L("Connecting to server...");
|
wxString msg_text = _L("Connecting to server...");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(true);
|
Enable_Send_Button(true);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusReading) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusReading) {
|
|
||||||
wxString msg_text = _L("Synchronizing device information...");
|
wxString msg_text = _L("Synchronizing device information...");
|
||||||
update_print_status_msg(msg_text, false, true);
|
update_print_status_msg(msg_text, false, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(false);
|
Enable_Refresh_Button(false);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusReadingFinished) {
|
||||||
|
|
||||||
else if (status == PrintDialogStatus::PrintStatusReadingFinished) {
|
|
||||||
update_print_status_msg(wxEmptyString, false, true);
|
update_print_status_msg(wxEmptyString, false, true);
|
||||||
Enable_Send_Button(true);
|
Enable_Send_Button(true);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusReadingTimeout) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusReadingTimeout) {
|
|
||||||
wxString msg_text = _L("Synchronizing device information timed out.");
|
wxString msg_text = _L("Synchronizing device information timed out.");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(true);
|
Enable_Send_Button(true);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusInUpgrading) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusInUpgrading) {
|
|
||||||
wxString msg_text = _L("Cannot send print tasks when an update is in progress");
|
wxString msg_text = _L("Cannot send print tasks when an update is in progress");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusUnsupportedPrinter) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusUnsupportedPrinter) {
|
|
||||||
wxString msg_text = _L("The selected printer is incompatible with the chosen printer presets.");
|
wxString msg_text = _L("The selected printer is incompatible with the chosen printer presets.");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(true);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusRefreshingMachineList) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusRefreshingMachineList) {
|
|
||||||
update_print_status_msg(wxEmptyString, false, true);
|
update_print_status_msg(wxEmptyString, false, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(false);
|
Enable_Refresh_Button(false);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusSending) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusSending) {
|
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(false);
|
Enable_Refresh_Button(false);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusSendingCanceled) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusSendingCanceled) {
|
|
||||||
Enable_Send_Button(true);
|
Enable_Send_Button(true);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusNoSdcard) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusNoSdcard) {
|
|
||||||
wxString msg_text = _L("Storage needs to be inserted before send to printer.");
|
wxString msg_text = _L("Storage needs to be inserted before send to printer.");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusNotOnTheSameLAN) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusNotOnTheSameLAN) {
|
|
||||||
wxString msg_text = _L("The printer is required to be on the same LAN as Orca Slicer.");
|
wxString msg_text = _L("The printer is required to be on the same LAN as Orca Slicer.");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
}
|
} else if (status == PrintDialogStatus::PrintStatusNotSupportedSendToSDCard) {
|
||||||
else if (status == PrintDialogStatus::PrintStatusNotSupportedSendToSDCard) {
|
|
||||||
wxString msg_text = _L("The printer does not support sending to printer storage.");
|
wxString msg_text = _L("The printer does not support sending to printer storage.");
|
||||||
update_print_status_msg(msg_text, true, true);
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
} else if (status == PrintDialogStatus::PrintStatusPublicInitFailed) {
|
} else if (status == PrintDialogStatus::PrintStatusPublicInitFailed) {
|
||||||
|
wxString msg_text = _L(
|
||||||
|
"Failed to initialize the printer file transfer. Please check the connection and try again.");
|
||||||
|
update_print_status_msg(msg_text, true, true);
|
||||||
Enable_Send_Button(false);
|
Enable_Send_Button(false);
|
||||||
Enable_Refresh_Button(true);
|
Enable_Refresh_Button(true);
|
||||||
} else if (status == PrintDialogStatus::PrintStatusPublicUploadFiled) {
|
} else if (status == PrintDialogStatus::PrintStatusPublicUploadFiled) {
|
||||||
@@ -1663,30 +1659,18 @@ extern void refresh_agora_url(char const *device, char const *dev_ver, char
|
|||||||
void SendToPrinterDialog::GetConnection()
|
void SendToPrinterDialog::GetConnection()
|
||||||
{
|
{
|
||||||
DeviceManager *dm = GUI::wxGetApp().getDeviceManager();
|
DeviceManager *dm = GUI::wxGetApp().getDeviceManager();
|
||||||
|
MachineObject *obj = dm ? dm->get_selected_machine() : nullptr;
|
||||||
|
|
||||||
MachineObject *obj = dm->get_selected_machine();
|
if (!obj)
|
||||||
if (obj == nullptr) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : obj is empty";
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : obj is empty";
|
||||||
m_connection_status = ConnectionStatus::NOT_START;
|
if (obj && !obj->get_file_remote())
|
||||||
}
|
|
||||||
|
|
||||||
int remote_proto = obj->get_file_remote();
|
|
||||||
if (!remote_proto) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : remote_proto is not support";
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : remote_proto is not support";
|
||||||
m_connection_status = ConnectionStatus::NOT_START;
|
if (obj && obj->is_camera_busy_off())
|
||||||
}
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : camera is busy";
|
||||||
|
|
||||||
if (obj->is_camera_busy_off()) {
|
NetworkAgent* agent = wxGetApp().getAgent();
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : camera is busy";
|
|
||||||
m_connection_status = ConnectionStatus::NOT_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkAgent *agent = wxGetApp().getAgent();
|
if (m_url_timer && m_url_timer->IsRunning())
|
||||||
std::string agent_version = agent ? agent->get_version() : "";
|
|
||||||
std::string dev_ver = obj->get_ota_version();
|
|
||||||
std::string dev_id = obj->get_dev_id();
|
|
||||||
|
|
||||||
if (m_url_timer && m_url_timer->IsRunning())
|
|
||||||
{
|
{
|
||||||
m_url_timer->Stop();
|
m_url_timer->Stop();
|
||||||
}
|
}
|
||||||
@@ -1709,19 +1693,40 @@ void SendToPrinterDialog::GetConnection()
|
|||||||
m_url_timer->GetId());
|
m_url_timer->GetId());
|
||||||
m_url_timer->StartOnce(8000);
|
m_url_timer->StartOnce(8000);
|
||||||
|
|
||||||
if (agent) {
|
if (obj && agent)
|
||||||
|
{
|
||||||
|
std::string dev_ver = obj->get_ota_version();
|
||||||
|
std::string dev_id = obj->get_dev_id();
|
||||||
|
|
||||||
if (m_tcp_try_connect) {
|
if (m_tcp_try_connect) {
|
||||||
std::string devIP = obj->get_dev_ip();
|
std::string devIP = obj->get_dev_ip();
|
||||||
std::string accessCode = obj->get_access_code();
|
std::string accessCode = obj->get_access_code();
|
||||||
std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
|
std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tcp";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tcp, dev_id=" << dev_id
|
||||||
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
<< ", dev_ip=" << devIP << ", access_code_len=" << accessCode.size();
|
||||||
m_filetransfer_tunnel->on_connection([this](bool is_success, int err_code, std::string error_msg) {
|
|
||||||
CallAfter([this, is_success, err_code, error_msg]() {
|
try
|
||||||
OnConnection(is_success, err_code, error_msg);
|
{
|
||||||
|
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
||||||
|
m_filetransfer_tunnel->on_connection([this](bool is_success, int err_code, std::string error_msg)
|
||||||
|
{
|
||||||
|
CallAfter([this, is_success, err_code, error_msg]()
|
||||||
|
{
|
||||||
|
OnConnection(is_success, err_code, error_msg);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
m_filetransfer_tunnel->start_connect();
|
||||||
m_filetransfer_tunnel->start_connect();
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": tcp FileTransferTunnel unavailable for dev_id=" <<
|
||||||
|
dev_id
|
||||||
|
<< " dev_ip=" << devIP << ": " << e.what();
|
||||||
|
if (m_url_timer && m_url_timer->IsRunning()) m_url_timer->Stop();
|
||||||
|
m_filetransfer_tunnel.reset();
|
||||||
|
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||||
|
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (m_tutk_try_connect)
|
else if (m_tutk_try_connect)
|
||||||
{
|
{
|
||||||
@@ -1749,11 +1754,28 @@ void SendToPrinterDialog::GetConnection()
|
|||||||
if (boost::algorithm::starts_with(url, "bambu:///"))
|
if (boost::algorithm::starts_with(url, "bambu:///"))
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tutk";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tutk";
|
||||||
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
try
|
||||||
m_filetransfer_tunnel->on_connection([this](bool is_success, int err_code, std::string error_msg) {
|
{
|
||||||
CallAfter([this, is_success, err_code, error_msg]() { OnConnection(is_success, err_code, error_msg); });
|
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
||||||
});
|
m_filetransfer_tunnel->on_connection(
|
||||||
m_filetransfer_tunnel->start_connect();
|
[this](bool is_success, int err_code, std::string error_msg)
|
||||||
|
{
|
||||||
|
CallAfter([this, is_success, err_code, error_msg]()
|
||||||
|
{
|
||||||
|
OnConnection(is_success, err_code, error_msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
m_filetransfer_tunnel->start_connect();
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": tutk FileTransferTunnel unavailable: " << e.
|
||||||
|
what();
|
||||||
|
if (m_url_timer && m_url_timer->IsRunning()) m_url_timer->Stop();
|
||||||
|
m_filetransfer_tunnel.reset();
|
||||||
|
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||||
|
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1852,8 +1874,17 @@ void SendToPrinterDialog::ResetTunnelAndJob()
|
|||||||
|
|
||||||
void SendToPrinterDialog::CreateMediaAbilityJob()
|
void SendToPrinterDialog::CreateMediaAbilityJob()
|
||||||
{
|
{
|
||||||
nlohmann::json media_ability = {{"cmd_type", 7}};
|
nlohmann::json media_ability = {{"cmd_type", 7}};
|
||||||
m_filetransfer_mediability_job = std::make_unique<FileTransferJob>(module(), std::string(media_ability.dump()));
|
try
|
||||||
|
{
|
||||||
|
m_filetransfer_mediability_job = std::make_unique<FileTransferJob>(module(), std::string(media_ability.dump()));
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": FileTransferJob unavailable: " << e.what();
|
||||||
|
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_filetransfer_mediability_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) {
|
m_filetransfer_mediability_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) {
|
||||||
//this pl
|
//this pl
|
||||||
CallAfter([this, res, resp_ec, json_res] {
|
CallAfter([this, res, resp_ec, json_res] {
|
||||||
@@ -1908,11 +1939,20 @@ void SendToPrinterDialog::CreateUploadFileJob(const std::string &path, const std
|
|||||||
{"cmd_type", 5},
|
{"cmd_type", 5},
|
||||||
};
|
};
|
||||||
upload_params["dest_storage"] = m_selected_storage;
|
upload_params["dest_storage"] = m_selected_storage;
|
||||||
upload_params["dest_name"] = name; // filenme no path
|
upload_params["dest_name"] = name; // filenme no path
|
||||||
upload_params["file_path"] = path;
|
upload_params["file_path"] = path;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Begin CreateUploadFileJob";
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Begin CreateUploadFileJob";
|
||||||
m_filetransfer_uploadfile_job = std::make_unique<FileTransferJob>(module(), std::string(upload_params.dump()));
|
try
|
||||||
|
{
|
||||||
|
m_filetransfer_uploadfile_job = std::make_unique<FileTransferJob>(module(), std::string(upload_params.dump()));
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": FileTransferJob unavailable: " << e.what();
|
||||||
|
show_status(PrintDialogStatus::PrintStatusPublicUploadFiled);
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_filetransfer_uploadfile_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) { //
|
m_filetransfer_uploadfile_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) { //
|
||||||
CallAfter([this, res, resp_ec, json_res, bin_res] {
|
CallAfter([this, res, resp_ec, json_res, bin_res] {
|
||||||
UploadFileRessultCallback(res, resp_ec,json_res, bin_res);
|
UploadFileRessultCallback(res, resp_ec,json_res, bin_res);
|
||||||
|
|||||||
+104
-103
@@ -22,6 +22,7 @@
|
|||||||
#include <wx/mstream.h>
|
#include <wx/mstream.h>
|
||||||
#include <wx/sstream.h>
|
#include <wx/sstream.h>
|
||||||
#include <wx/zstream.h>
|
#include <wx/zstream.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "DeviceCore/DevBed.h"
|
#include "DeviceCore/DevBed.h"
|
||||||
#include "DeviceCore/DevCtrl.h"
|
#include "DeviceCore/DevCtrl.h"
|
||||||
@@ -1493,27 +1494,26 @@ wxBoxSizer *StatusBasePanel::create_monitoring_page()
|
|||||||
m_setting_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
|
m_setting_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
|
||||||
m_setting_button->SetBackgroundColour(STATUS_TITLE_BG);
|
m_setting_button->SetBackgroundColour(STATUS_TITLE_BG);
|
||||||
|
|
||||||
m_camera_switch_button = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
|
// m_camera_switch_button = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
|
||||||
m_camera_switch_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
|
// m_camera_switch_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
|
||||||
m_camera_switch_button->SetBackgroundColour(STATUS_TITLE_BG);
|
// m_camera_switch_button->SetBackgroundColour(STATUS_TITLE_BG);
|
||||||
m_camera_switch_button->SetBitmap(m_bitmap_switch_camera.bmp());
|
// m_camera_switch_button->SetBitmap(m_bitmap_switch_camera.bmp());
|
||||||
m_camera_switch_button->Bind(wxEVT_LEFT_DOWN, &StatusBasePanel::on_camera_switch_toggled, this);
|
// m_camera_switch_button->Bind(wxEVT_RIGHT_DOWN, [this](auto& e) {
|
||||||
m_camera_switch_button->Bind(wxEVT_RIGHT_DOWN, [this](auto& e) {
|
// const std::string js_request_pip = R"(
|
||||||
const std::string js_request_pip = R"(
|
// document.querySelector('video').requestPictureInPicture();
|
||||||
document.querySelector('video').requestPictureInPicture();
|
// )";
|
||||||
)";
|
// m_custom_camera_view->RunScript(js_request_pip);
|
||||||
m_custom_camera_view->RunScript(js_request_pip);
|
// });
|
||||||
});
|
// m_camera_switch_button->Hide();
|
||||||
m_camera_switch_button->Hide();
|
|
||||||
|
|
||||||
m_bitmap_sdcard_img->SetToolTip(_L("Storage"));
|
m_bitmap_sdcard_img->SetToolTip(_L("Storage"));
|
||||||
m_bitmap_timelapse_img->SetToolTip(_L("Timelapse"));
|
m_bitmap_timelapse_img->SetToolTip(_L("Timelapse"));
|
||||||
m_bitmap_recording_img->SetToolTip(_L("Video"));
|
m_bitmap_recording_img->SetToolTip(_L("Video"));
|
||||||
m_bitmap_vcamera_img->SetToolTip(_L("Go Live"));
|
m_bitmap_vcamera_img->SetToolTip(_L("Go Live"));
|
||||||
m_setting_button->SetToolTip(_L("Camera Setting"));
|
m_setting_button->SetToolTip(_L("Camera Setting"));
|
||||||
m_camera_switch_button->SetToolTip(_L("Switch Camera View"));
|
// m_camera_switch_button->SetToolTip(_L("Switch Camera View"));
|
||||||
|
|
||||||
bSizer_monitoring_title->Add(m_camera_switch_button, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
// bSizer_monitoring_title->Add(m_camera_switch_button, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
||||||
bSizer_monitoring_title->Add(m_bitmap_sdcard_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
bSizer_monitoring_title->Add(m_bitmap_sdcard_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
||||||
bSizer_monitoring_title->Add(m_bitmap_timelapse_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
bSizer_monitoring_title->Add(m_bitmap_timelapse_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
||||||
bSizer_monitoring_title->Add(m_bitmap_recording_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
bSizer_monitoring_title->Add(m_bitmap_recording_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
|
||||||
@@ -1536,19 +1536,18 @@ wxBoxSizer *StatusBasePanel::create_monitoring_page()
|
|||||||
m_custom_camera_view = WebView::CreateWebView(this, wxEmptyString);
|
m_custom_camera_view = WebView::CreateWebView(this, wxEmptyString);
|
||||||
m_custom_camera_view->EnableContextMenu(false);
|
m_custom_camera_view->EnableContextMenu(false);
|
||||||
Bind(wxEVT_WEBVIEW_NAVIGATING, &StatusBasePanel::on_webview_navigating, this, m_custom_camera_view->GetId());
|
Bind(wxEVT_WEBVIEW_NAVIGATING, &StatusBasePanel::on_webview_navigating, this, m_custom_camera_view->GetId());
|
||||||
|
m_web_media_controller = std::make_unique<WebMediaController>(m_custom_camera_view);
|
||||||
|
|
||||||
m_media_play_ctrl = new MediaPlayCtrl(this, m_media_ctrl, wxDefaultPosition, wxSize(-1, FromDIP(40)));
|
m_media_play_ctrl = new MediaPlayCtrl(this, m_media_ctrl, wxDefaultPosition, wxSize(-1, FromDIP(40)));
|
||||||
|
m_media_play_ctrl->SetWebMediaController(m_web_media_controller.get());
|
||||||
m_custom_camera_view->Hide();
|
m_custom_camera_view->Hide();
|
||||||
m_custom_camera_view->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, [this](wxWebViewEvent& evt) {
|
// m_custom_camera_view->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, [this](wxWebViewEvent& evt) {
|
||||||
if (evt.GetString() == "leavepictureinpicture") {
|
// if (evt.GetString() == "leavepictureinpicture") {
|
||||||
// When leaving PiP, video gets paused in some cases and toggling play
|
// // When leaving PiP, video gets paused in some cases and toggling play
|
||||||
// programmatically does not work.
|
// // programmatically does not work.
|
||||||
m_custom_camera_view->Reload();
|
// m_custom_camera_view->Reload();
|
||||||
}
|
// }
|
||||||
else if (evt.GetString() == "enterpictureinpicture") {
|
// });
|
||||||
toggle_builtin_camera();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sizer->Add(m_media_ctrl, 1, wxEXPAND | wxALL, 0);
|
sizer->Add(m_media_ctrl, 1, wxEXPAND | wxALL, 0);
|
||||||
sizer->Add(m_custom_camera_view, 1, wxEXPAND | wxALL, 0);
|
sizer->Add(m_custom_camera_view, 1, wxEXPAND | wxALL, 0);
|
||||||
@@ -1558,10 +1557,6 @@ wxBoxSizer *StatusBasePanel::create_monitoring_page()
|
|||||||
//
|
//
|
||||||
// sizer->Add(media_ctrl_panel, 1, wxEXPAND | wxALL, 1);
|
// sizer->Add(media_ctrl_panel, 1, wxEXPAND | wxALL, 1);
|
||||||
|
|
||||||
if (wxGetApp().app_config->get("camera", "enable_custom_source") == "true") {
|
|
||||||
handle_camera_source_change();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sizer;
|
return sizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2311,6 +2306,27 @@ void StatusPanel::update_camera_state(MachineObject* obj)
|
|||||||
{
|
{
|
||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
|
|
||||||
|
auto agent = wxGetApp().getAgent();
|
||||||
|
const auto camera_mode = agent ? agent->get_camera_stream_mode() : CameraStreamMode::none;
|
||||||
|
const bool use_webview = camera_mode == CameraStreamMode::http_snapshot;
|
||||||
|
if (use_webview) {
|
||||||
|
//m_camera_switch_button->Hide();
|
||||||
|
if (!m_custom_camera_view->IsShown()) {
|
||||||
|
// why: do not reload the WebView URL per tick, or redirects can cause a reload loop.
|
||||||
|
// MediaPlayCtrl (via its WebMediaController) owns loading/playing the stream itself.
|
||||||
|
m_custom_camera_view->Show();
|
||||||
|
m_media_ctrl->Hide();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_custom_camera_view->IsShown()) {
|
||||||
|
m_custom_camera_view->Hide();
|
||||||
|
// Stop the snapshot WebView before switching to native playback
|
||||||
|
// or leaving the camera mode.
|
||||||
|
m_media_play_ctrl->StopWebStream();
|
||||||
|
}
|
||||||
|
m_media_ctrl->Show();
|
||||||
|
}
|
||||||
|
|
||||||
//sdcard
|
//sdcard
|
||||||
auto sdcard_state = obj->GetStorage()->get_sdcard_state();
|
auto sdcard_state = obj->GetStorage()->get_sdcard_state();
|
||||||
if (m_last_sdcard != sdcard_state) {
|
if (m_last_sdcard != sdcard_state) {
|
||||||
@@ -2342,7 +2358,12 @@ void StatusPanel::update_camera_state(MachineObject* obj)
|
|||||||
m_last_recording = obj->is_recording() ? 1 : 0;
|
m_last_recording = obj->is_recording() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bitmap_recording_img->IsShown()) {
|
if (use_webview) {
|
||||||
|
if (m_bitmap_recording_img->IsShown()) {
|
||||||
|
m_bitmap_recording_img->Hide();
|
||||||
|
m_panel_monitoring_title->Layout();
|
||||||
|
}
|
||||||
|
} else if (!m_bitmap_recording_img->IsShown()) {
|
||||||
m_bitmap_recording_img->Show();
|
m_bitmap_recording_img->Show();
|
||||||
m_panel_monitoring_title->Layout();
|
m_panel_monitoring_title->Layout();
|
||||||
}
|
}
|
||||||
@@ -2399,6 +2420,8 @@ void StatusPanel::update_camera_state(MachineObject* obj)
|
|||||||
bool show_vcamera = m_media_play_ctrl->IsStreaming();
|
bool show_vcamera = m_media_play_ctrl->IsStreaming();
|
||||||
m_camera_popup->update(show_vcamera);
|
m_camera_popup->update(show_vcamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_setting_button->Show(!use_webview);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
|
StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
|
||||||
@@ -3920,39 +3943,60 @@ void StatusPanel::update_cloud_subtask(MachineObject *obj)
|
|||||||
update_calib_bitmap();
|
update_calib_bitmap();
|
||||||
if (obj->slice_info) {
|
if (obj->slice_info) {
|
||||||
m_request_url = wxString(obj->slice_info->thumbnail_url);
|
m_request_url = wxString(obj->slice_info->thumbnail_url);
|
||||||
if (!m_request_url.IsEmpty()) {
|
load_thumbnail_from_url(m_request_url, obj);
|
||||||
wxImage img;
|
|
||||||
std::map<wxString, wxImage>::iterator it = img_list.find(m_request_url);
|
|
||||||
if (it != img_list.end()) {
|
|
||||||
if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) {
|
|
||||||
img = it->second;
|
|
||||||
wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y);
|
|
||||||
m_project_task_panel->set_thumbnail_img(resize_img, "");
|
|
||||||
m_project_task_panel->set_brightness_value(get_brightness_value(resize_img));
|
|
||||||
}
|
|
||||||
if (this->obj) {
|
|
||||||
m_project_task_panel->set_plate_index(obj->m_plate_index);
|
|
||||||
} else {
|
|
||||||
m_project_task_panel->set_plate_index(-1);
|
|
||||||
}
|
|
||||||
task_thumbnail_state = ThumbnailState::TASK_THUMBNAIL;
|
|
||||||
BOOST_LOG_TRIVIAL(trace) << "web_request: use cache image";
|
|
||||||
} else {
|
|
||||||
web_request = wxWebSession::GetDefault().CreateRequest(this, m_request_url);
|
|
||||||
BOOST_LOG_TRIVIAL(trace) << "monitor: start request thumbnail, url = " << m_request_url;
|
|
||||||
web_request.Start();
|
|
||||||
m_start_loading_thumbnail = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StatusPanel::load_thumbnail_from_url(const wxString &url, MachineObject *obj)
|
||||||
|
{
|
||||||
|
if (url.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxImage img;
|
||||||
|
std::map<wxString, wxImage>::iterator it = img_list.find(url);
|
||||||
|
if (it != img_list.end()) {
|
||||||
|
if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) {
|
||||||
|
img = it->second;
|
||||||
|
wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y);
|
||||||
|
m_project_task_panel->set_thumbnail_img(resize_img, "");
|
||||||
|
m_project_task_panel->set_brightness_value(get_brightness_value(resize_img));
|
||||||
|
}
|
||||||
|
if (this->obj) {
|
||||||
|
m_project_task_panel->set_plate_index(obj->m_plate_index);
|
||||||
|
} else {
|
||||||
|
m_project_task_panel->set_plate_index(-1);
|
||||||
|
}
|
||||||
|
task_thumbnail_state = ThumbnailState::TASK_THUMBNAIL;
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "web_request: use cache image";
|
||||||
|
} else {
|
||||||
|
m_request_url = url;
|
||||||
|
web_request = wxWebSession::GetDefault().CreateRequest(this, m_request_url);
|
||||||
|
BOOST_LOG_TRIVIAL(trace) << "monitor: start request thumbnail, url = " << m_request_url;
|
||||||
|
web_request.Start();
|
||||||
|
m_start_loading_thumbnail = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void StatusPanel::update_sdcard_subtask(MachineObject *obj)
|
void StatusPanel::update_sdcard_subtask(MachineObject *obj)
|
||||||
{
|
{
|
||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
|
|
||||||
if (!m_load_sdcard_thumbnail) {
|
const wxString thumbnail_url = wxString(obj->m_agent_thumbnail_url);
|
||||||
|
if (!thumbnail_url.IsEmpty()) {
|
||||||
|
if (m_request_url != thumbnail_url || !m_load_sdcard_thumbnail) {
|
||||||
|
if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active)
|
||||||
|
web_request.Cancel();
|
||||||
|
update_calib_bitmap();
|
||||||
|
m_request_url = thumbnail_url;
|
||||||
|
load_thumbnail_from_url(thumbnail_url, obj);
|
||||||
|
m_load_sdcard_thumbnail = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_load_sdcard_thumbnail || !m_request_url.IsEmpty()) {
|
||||||
update_calib_bitmap();
|
update_calib_bitmap();
|
||||||
if (m_current_print_mode != PrintingTaskType::CALIBRATION) {
|
if (m_current_print_mode != PrintingTaskType::CALIBRATION) {
|
||||||
m_project_task_panel->get_bitmap_thumbnail()->SetBitmap(m_thumbnail_sdcard.bmp());
|
m_project_task_panel->get_bitmap_thumbnail()->SetBitmap(m_thumbnail_sdcard.bmp());
|
||||||
@@ -3960,6 +4004,7 @@ void StatusPanel::update_sdcard_subtask(MachineObject *obj)
|
|||||||
}
|
}
|
||||||
task_thumbnail_state = ThumbnailState::SDCARD_THUMBNAIL;
|
task_thumbnail_state = ThumbnailState::SDCARD_THUMBNAIL;
|
||||||
m_load_sdcard_thumbnail = true;
|
m_load_sdcard_thumbnail = true;
|
||||||
|
m_request_url.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4959,7 +5004,6 @@ void StatusPanel::on_camera_enter(wxMouseEvent& event)
|
|||||||
}
|
}
|
||||||
sdcard_hint_dlg->on_show();
|
sdcard_hint_dlg->on_show();
|
||||||
});
|
});
|
||||||
m_camera_popup->Bind(EVT_CAM_SOURCE_CHANGE, &StatusPanel::on_camera_source_change, this);
|
|
||||||
wxWindow* ctrl = (wxWindow*)event.GetEventObject();
|
wxWindow* ctrl = (wxWindow*)event.GetEventObject();
|
||||||
wxPoint pos = ctrl->ClientToScreen(wxPoint(0, 0));
|
wxPoint pos = ctrl->ClientToScreen(wxPoint(0, 0));
|
||||||
wxSize sz = ctrl->GetSize();
|
wxSize sz = ctrl->GetSize();
|
||||||
@@ -4971,54 +5015,6 @@ void StatusPanel::on_camera_enter(wxMouseEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBasePanel::on_camera_source_change(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
handle_camera_source_change();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBasePanel::handle_camera_source_change()
|
|
||||||
{
|
|
||||||
const auto new_cam_url = wxGetApp().app_config->get("camera", "custom_source");
|
|
||||||
const auto enabled = wxGetApp().app_config->get("camera", "enable_custom_source") == "true";
|
|
||||||
|
|
||||||
if (enabled && !new_cam_url.empty()) {
|
|
||||||
m_custom_camera_view->LoadURL(new_cam_url);
|
|
||||||
toggle_custom_camera();
|
|
||||||
m_camera_switch_button->Show();
|
|
||||||
} else {
|
|
||||||
toggle_builtin_camera();
|
|
||||||
m_camera_switch_button->Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBasePanel::toggle_builtin_camera()
|
|
||||||
{
|
|
||||||
m_custom_camera_view->Hide();
|
|
||||||
m_media_ctrl->Show();
|
|
||||||
m_media_play_ctrl->Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBasePanel::toggle_custom_camera()
|
|
||||||
{
|
|
||||||
const auto enabled = wxGetApp().app_config->get("camera", "enable_custom_source") == "true";
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
m_custom_camera_view->Show();
|
|
||||||
m_media_ctrl->Hide();
|
|
||||||
m_media_play_ctrl->Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBasePanel::on_camera_switch_toggled(wxMouseEvent& event)
|
|
||||||
{
|
|
||||||
const auto enabled = wxGetApp().app_config->get("camera", "enable_custom_source") == "true";
|
|
||||||
if (enabled && m_media_ctrl->IsShown()) {
|
|
||||||
toggle_custom_camera();
|
|
||||||
} else {
|
|
||||||
toggle_builtin_camera();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBasePanel::remove_controls()
|
void StatusBasePanel::remove_controls()
|
||||||
{
|
{
|
||||||
const std::string js_cleanup_video_element = R"(
|
const std::string js_cleanup_video_element = R"(
|
||||||
@@ -5171,6 +5167,11 @@ bool StatusPanel::is_stage_list_info_changed(MachineObject *obj)
|
|||||||
void StatusPanel::set_default()
|
void StatusPanel::set_default()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(trace) << "status_panel: set_default";
|
BOOST_LOG_TRIVIAL(trace) << "status_panel: set_default";
|
||||||
|
if (m_custom_camera_view->IsShown()) {
|
||||||
|
m_custom_camera_view->Hide();
|
||||||
|
m_media_ctrl->Show();
|
||||||
|
m_media_play_ctrl->StopWebStream();
|
||||||
|
}
|
||||||
obj = nullptr;
|
obj = nullptr;
|
||||||
last_subtask = nullptr;
|
last_subtask = nullptr;
|
||||||
last_tray_exist_bits = -1;
|
last_tray_exist_bits = -1;
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/webrequest.h>
|
#include <wx/webrequest.h>
|
||||||
|
#include <memory>
|
||||||
#include "MediaPlayCtrl.h"
|
#include "MediaPlayCtrl.h"
|
||||||
|
#include "WebMediaController.hpp"
|
||||||
#include "AMSSetting.hpp"
|
#include "AMSSetting.hpp"
|
||||||
#include "Calibration.hpp"
|
#include "Calibration.hpp"
|
||||||
#include "CalibrationWizardPage.hpp"
|
#include "CalibrationWizardPage.hpp"
|
||||||
@@ -439,7 +441,7 @@ protected:
|
|||||||
wxStaticBitmap *m_bitmap_sdcard_img;
|
wxStaticBitmap *m_bitmap_sdcard_img;
|
||||||
wxStaticBitmap *m_bitmap_static_use_time;
|
wxStaticBitmap *m_bitmap_static_use_time;
|
||||||
wxStaticBitmap *m_bitmap_static_use_weight;
|
wxStaticBitmap *m_bitmap_static_use_weight;
|
||||||
wxStaticBitmap* m_camera_switch_button;
|
// wxStaticBitmap* m_camera_switch_button;
|
||||||
|
|
||||||
|
|
||||||
wxMediaCtrl3 * m_media_ctrl;
|
wxMediaCtrl3 * m_media_ctrl;
|
||||||
@@ -461,6 +463,8 @@ protected:
|
|||||||
ScalableButton *m_button_abort;
|
ScalableButton *m_button_abort;
|
||||||
Button * m_button_clean;
|
Button * m_button_clean;
|
||||||
wxWebView * m_custom_camera_view{nullptr};
|
wxWebView * m_custom_camera_view{nullptr};
|
||||||
|
std::unique_ptr<WebMediaController> m_web_media_controller;
|
||||||
|
|
||||||
wxSimplebook* m_extruder_book;
|
wxSimplebook* m_extruder_book;
|
||||||
std::vector<ExtruderImage *> m_extruderImage;
|
std::vector<ExtruderImage *> m_extruderImage;
|
||||||
|
|
||||||
@@ -576,13 +580,8 @@ protected:
|
|||||||
virtual void on_axis_ctrl_e_up_10(wxCommandEvent &event) { event.Skip(); }
|
virtual void on_axis_ctrl_e_up_10(wxCommandEvent &event) { event.Skip(); }
|
||||||
virtual void on_axis_ctrl_e_down_10(wxCommandEvent &event) { event.Skip(); }
|
virtual void on_axis_ctrl_e_down_10(wxCommandEvent &event) { event.Skip(); }
|
||||||
virtual void on_nozzle_selected(wxCommandEvent &event) { event.Skip(); }
|
virtual void on_nozzle_selected(wxCommandEvent &event) { event.Skip(); }
|
||||||
void on_camera_source_change(wxCommandEvent& event);
|
|
||||||
void handle_camera_source_change();
|
|
||||||
void remove_controls();
|
void remove_controls();
|
||||||
void on_webview_navigating(wxWebViewEvent& evt);
|
void on_webview_navigating(wxWebViewEvent& evt);
|
||||||
void on_camera_switch_toggled(wxMouseEvent& event);
|
|
||||||
void toggle_custom_camera();
|
|
||||||
void toggle_builtin_camera();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StatusBasePanel(wxWindow * parent,
|
StatusBasePanel(wxWindow * parent,
|
||||||
@@ -629,6 +628,7 @@ class StatusPanel : public StatusBasePanel
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
friend class MonitorPanel;
|
friend class MonitorPanel;
|
||||||
|
bool load_thumbnail_from_url(const wxString &url, MachineObject *obj);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<SliceInfoPopup> m_slice_info_popup;
|
std::shared_ptr<SliceInfoPopup> m_slice_info_popup;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user