From a4d4bfff27f83ec207fb3780014cc5c0db29243c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Wilczy=C5=84ski?= Date: Sun, 14 Dec 2025 09:30:11 +0100 Subject: [PATCH 01/45] Allow selecting specific network plugin versions --- CMakeLists.txt | 9 + build_release_macos.sh | 31 +- cmake/modules/FindGLEW.cmake | 27 +- deps/CMakeLists.txt | 6 + deps/wxWidgets/wxWidgets.cmake | 9 + src/libslic3r/AppConfig.cpp | 77 +++++ src/libslic3r/AppConfig.hpp | 20 ++ src/slic3r/CMakeLists.txt | 16 +- src/slic3r/GUI/DeviceCore/DevManager.cpp | 19 ++ src/slic3r/GUI/DeviceCore/DevManager.h | 2 +- src/slic3r/GUI/DeviceManager.hpp | 2 + src/slic3r/GUI/DownloadProgressDialog.cpp | 13 +- src/slic3r/GUI/GUI_App.cpp | 381 ++++++++++++++++++++-- src/slic3r/GUI/GUI_App.hpp | 6 + src/slic3r/GUI/Monitor.cpp | 14 + src/slic3r/GUI/Monitor.hpp | 1 + src/slic3r/GUI/NetworkPluginDialog.cpp | 371 +++++++++++++++++++++ src/slic3r/GUI/NetworkPluginDialog.hpp | 74 +++++ src/slic3r/GUI/Preferences.cpp | 112 ++++++- src/slic3r/GUI/Preferences.hpp | 2 + src/slic3r/GUI/Tabbook.cpp | 14 + src/slic3r/GUI/Tabbook.hpp | 7 + src/slic3r/Utils/NetworkAgent.cpp | 160 +++++++-- src/slic3r/Utils/NetworkAgent.hpp | 13 +- src/slic3r/Utils/PresetUpdater.cpp | 2 +- src/slic3r/Utils/bambu_networking.hpp | 31 +- tests/libslic3r/CMakeLists.txt | 1 + tests/libslic3r/test_appconfig.cpp | 45 +++ 28 files changed, 1388 insertions(+), 77 deletions(-) create mode 100644 src/slic3r/GUI/NetworkPluginDialog.cpp create mode 100644 src/slic3r/GUI/NetworkPluginDialog.hpp create mode 100644 tests/libslic3r/test_appconfig.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 162763621c..041c7b17cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,7 @@ +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "4.0") + set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE) +endif() + cmake_minimum_required(VERSION 3.13) # Verify that your CMake version is exactly 3.5 series or higher on windows @@ -571,6 +575,7 @@ endif() if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) endif() +set(Boost_NO_SYSTEM_PATHS TRUE) find_package(Boost 1.83.0 REQUIRED COMPONENTS system filesystem thread log log_setup locale regex chrono atomic date_time iostreams program_options nowide) add_library(boost_libs INTERFACE) @@ -688,6 +693,10 @@ find_package(PNG REQUIRED) set(OpenGL_GL_PREFERENCE "LEGACY") find_package(OpenGL REQUIRED) +if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE) +endif() + set(GLEW_ROOT "${CMAKE_PREFIX_PATH}") message("GLEW_ROOT: ${GLEW_ROOT}") # Find glew or use bundled version diff --git a/build_release_macos.sh b/build_release_macos.sh index e42490f1bd..1999c62b92 100755 --- a/build_release_macos.sh +++ b/build_release_macos.sh @@ -3,7 +3,7 @@ set -e set -o pipefail -while getopts ":dpa:snt:xbc:1h" opt; do +while getopts ":dpa:snt:xbc:1Th" opt; do case "${opt}" in d ) export BUILD_TARGET="deps" @@ -37,6 +37,9 @@ while getopts ":dpa:snt:xbc:1h" opt; do 1 ) export CMAKE_BUILD_PARALLEL_LEVEL=1 ;; + T ) + export BUILD_TESTS="1" + ;; h ) echo "Usage: ./build_release_macos.sh [-d]" echo " -d: Build deps only" echo " -a: Set ARCHITECTURE (arm64 or x86_64 or universal)" @@ -47,6 +50,7 @@ while getopts ":dpa:snt:xbc:1h" opt; do echo " -b: Build without reconfiguring CMake" echo " -c: Set CMake build configuration, default is Release" echo " -1: Use single job for building" + echo " -T: Build and run tests" exit 0 ;; * ) @@ -85,6 +89,15 @@ if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then export OSX_DEPLOYMENT_TARGET="11.3" fi +CMAKE_VERSION=$(cmake --version | head -1 | sed 's/[^0-9]*\([0-9]*\).*/\1/') +if [ "$CMAKE_VERSION" -ge 4 ] 2>/dev/null; then + export CMAKE_POLICY_VERSION_MINIMUM=3.5 + export CMAKE_POLICY_COMPAT="-DCMAKE_POLICY_VERSION_MINIMUM=3.5" + echo "Detected CMake 4.x, adding compatibility flag (env + cmake arg)" +else + export CMAKE_POLICY_COMPAT="" +fi + echo "Build params:" echo " - ARCH: $ARCH" echo " - BUILD_CONFIG: $BUILD_CONFIG" @@ -133,7 +146,8 @@ function build_deps() { -G "${DEPS_CMAKE_GENERATOR}" \ -DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \ -DCMAKE_OSX_ARCHITECTURES:STRING="${_ARCH}" \ - -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" + -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \ + ${CMAKE_POLICY_COMPAT} fi cmake --build . --config "$BUILD_CONFIG" --target deps ) @@ -170,13 +184,24 @@ function build_slicer() { -G "${SLICER_CMAKE_GENERATOR}" \ -DORCA_TOOLS=ON \ ${ORCA_UPDATER_SIG_KEY:+-DORCA_UPDATER_SIG_KEY="$ORCA_UPDATER_SIG_KEY"} \ + ${BUILD_TESTS:+-DBUILD_TESTS=ON} \ -DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \ -DCMAKE_OSX_ARCHITECTURES="${_ARCH}" \ - -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" + -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \ + ${CMAKE_POLICY_COMPAT} fi cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET" ) + if [ "1." == "$BUILD_TESTS". ]; then + echo "Running tests for $_ARCH..." + ( + set -x + cd "$PROJECT_BUILD_DIR" + ctest --build-config "$BUILD_CONFIG" --output-on-failure + ) + fi + echo "Verify localization with gettext..." ( cd "$PROJECT_DIR" diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 56661ffd33..5dd7b24df1 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -223,8 +223,13 @@ if(NOT TARGET GLEW::glew AND NOT GLEW_USE_STATIC_LIBS) PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") if(APPLE) - set_target_properties(GLEW::glew - PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set_target_properties(GLEW::glew + PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL") + else() + set_target_properties(GLEW::glew + PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + endif() endif() if(GLEW_SHARED_LIBRARY_RELEASE) @@ -258,8 +263,13 @@ elseif(NOT TARGET GLEW::glew_s AND GLEW_USE_STATIC_LIBS) set_target_properties(GLEW::glew_s PROPERTIES INTERFACE_COMPILE_DEFINITIONS GLEW_STATIC) if(APPLE) - set_target_properties(GLEW::glew_s - PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set_target_properties(GLEW::glew_s + PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL") + else() + set_target_properties(GLEW::glew_s + PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + endif() endif() if(GLEW_STATIC_LIBRARY_RELEASE) @@ -292,8 +302,13 @@ if(NOT TARGET GLEW::GLEW) PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") if(APPLE) - set_target_properties(GLEW::GLEW - PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set_target_properties(GLEW::GLEW + PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL") + else() + set_target_properties(GLEW::GLEW + PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL) + endif() endif() if(TARGET GLEW::glew) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 13f3945d0c..92e36d0cad 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,3 +1,7 @@ +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "4.0") + set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE) +endif() + # # This CMake project downloads, configures and builds OrcaSlicer dependencies on Unix and Windows. # @@ -177,6 +181,7 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE) DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname} ${_gen} CMAKE_ARGS + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR} -DCMAKE_MODULE_PATH:STRING=${PROJECT_SOURCE_DIR}/../cmake/modules -DCMAKE_PREFIX_PATH:STRING=${DESTDIR} @@ -221,6 +226,7 @@ else() DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname} ${_gen} CMAKE_ARGS + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR} -DCMAKE_PREFIX_PATH:STRING=${DESTDIR} -DBUILD_SHARED_LIBS:BOOL=OFF diff --git a/deps/wxWidgets/wxWidgets.cmake b/deps/wxWidgets/wxWidgets.cmake index e45979fb42..3a52d14198 100644 --- a/deps/wxWidgets/wxWidgets.cmake +++ b/deps/wxWidgets/wxWidgets.cmake @@ -24,6 +24,14 @@ else () set(_wx_edge "-DwxUSE_WEBVIEW_EDGE=OFF") endif () +set(_wx_opengl_override "") +if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set(_wx_opengl_override + -DOPENGL_gl_LIBRARY="-framework OpenGL" + -DOPENGL_glu_LIBRARY="-framework OpenGL" + ) +endif() + orcaslicer_add_cmake_project( wxWidgets GIT_REPOSITORY "https://github.com/SoftFever/Orca-deps-wxWidgets" @@ -31,6 +39,7 @@ orcaslicer_add_cmake_project( DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG} ${_wx_flatpak_patch} CMAKE_ARGS + ${_wx_opengl_override} -DwxBUILD_PRECOMP=ON ${_wx_toolkit} "-DCMAKE_DEBUG_POSTFIX:STRING=${_wx_debug_postfix}" diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index e592155d14..569613cb81 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -1427,6 +1428,82 @@ std::string AppConfig::get_nozzle_volume_types_from_config(const std::string& pr return nozzle_volume_types; } +std::string AppConfig::get_network_plugin_version() const +{ + return get(SETTING_NETWORK_PLUGIN_VERSION); +} + +void AppConfig::set_network_plugin_version(const std::string& version) +{ + set(SETTING_NETWORK_PLUGIN_VERSION, version); +} + +std::vector AppConfig::get_skipped_network_versions() const +{ + std::vector result; + std::string skipped = get(SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS); + if (skipped.empty()) + return result; + + std::stringstream ss(skipped); + std::string version; + while (std::getline(ss, version, ';')) { + if (!version.empty()) + result.push_back(version); + } + return result; +} + +void AppConfig::add_skipped_network_version(const std::string& version) +{ + auto skipped = get_skipped_network_versions(); + if (std::find(skipped.begin(), skipped.end(), version) == skipped.end()) { + skipped.push_back(version); + std::string joined; + for (size_t i = 0; i < skipped.size(); ++i) { + if (i > 0) joined += ";"; + joined += skipped[i]; + } + set(SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS, joined); + } +} + +bool AppConfig::is_network_version_skipped(const std::string& version) const +{ + auto skipped = get_skipped_network_versions(); + return std::find(skipped.begin(), skipped.end(), version) != skipped.end(); +} + +void AppConfig::clear_skipped_network_versions() +{ + set(SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS, ""); +} + +bool AppConfig::is_network_update_prompt_disabled() const +{ + return get_bool(SETTING_NETWORK_PLUGIN_UPDATE_DISABLED); +} + +void AppConfig::set_network_update_prompt_disabled(bool disabled) +{ + set_bool(SETTING_NETWORK_PLUGIN_UPDATE_DISABLED, disabled); +} + +bool AppConfig::should_remind_network_update_later() const +{ + return get_bool(SETTING_NETWORK_PLUGIN_REMIND_LATER); +} + +void AppConfig::set_remind_network_update_later(bool remind) +{ + set_bool(SETTING_NETWORK_PLUGIN_REMIND_LATER, remind); +} + +void AppConfig::clear_remind_network_update_later() +{ + set_bool(SETTING_NETWORK_PLUGIN_REMIND_LATER, false); +} + void AppConfig::reset_selections() { auto it = m_storage.find("presets"); diff --git a/src/libslic3r/AppConfig.hpp b/src/libslic3r/AppConfig.hpp index 9307877552..82d87677ac 100644 --- a/src/libslic3r/AppConfig.hpp +++ b/src/libslic3r/AppConfig.hpp @@ -24,6 +24,11 @@ using namespace nlohmann; #define OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK "always_ask" #define OPTION_PROJECT_LOAD_BEHAVIOUR_LOAD_GEOMETRY "load_geometry_only" +#define SETTING_NETWORK_PLUGIN_VERSION "network_plugin_version" +#define SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS "network_plugin_skipped_versions" +#define SETTING_NETWORK_PLUGIN_UPDATE_DISABLED "network_plugin_update_prompts_disabled" +#define SETTING_NETWORK_PLUGIN_REMIND_LATER "network_plugin_remind_later" + #define SUPPORT_DARK_MODE //#define _MSW_DARK_MODE @@ -347,6 +352,21 @@ public: static const std::string SECTION_MATERIALS; static const std::string SECTION_EMBOSS_STYLE; + std::string get_network_plugin_version() const; + void set_network_plugin_version(const std::string& version); + + std::vector get_skipped_network_versions() const; + void add_skipped_network_version(const std::string& version); + bool is_network_version_skipped(const std::string& version) const; + void clear_skipped_network_versions(); + + bool is_network_update_prompt_disabled() const; + void set_network_update_prompt_disabled(bool disabled); + + bool should_remind_network_update_later() const; + void set_remind_network_update_later(bool remind); + void clear_remind_network_update_later(); + private: template bool get_3dmouse_device_numeric_value(const std::string &device_name, const char *parameter_name, T &out) const diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index ca4f9c4123..5529cd04c5 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -456,6 +456,8 @@ set(SLIC3R_GUI_SOURCES GUI/UnsavedChangesDialog.hpp GUI/UpdateDialogs.cpp GUI/UpdateDialogs.hpp + GUI/NetworkPluginDialog.cpp + GUI/NetworkPluginDialog.hpp GUI/UpgradePanel.cpp GUI/UpgradePanel.hpp GUI/UserManager.cpp @@ -703,7 +705,13 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES}) encoding_check(libslic3r_gui) -target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo GLEW::GLEW OpenGL::GL hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise) +if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + set(_opengl_link_lib "") +else() + set(_opengl_link_lib OpenGL::GL) +endif() + +target_link_libraries(libslic3r_gui libslic3r cereal::cereal imgui imguizmo minilzo GLEW::GLEW ${_opengl_link_lib} hidapi ${wxWidgets_LIBRARIES} glfw libcurl OpenSSL::SSL OpenSSL::Crypto noise::noise) if (MSVC) target_link_libraries(libslic3r_gui Setupapi.lib) @@ -721,7 +729,11 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") ${CURL_LIBRARIES} ) elseif (APPLE) - target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY} "-framework Security") + if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0") + target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY} "-framework Security" "-framework OpenGL") + else() + target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY} "-framework Security") + endif() endif() if (SLIC3R_STATIC) diff --git a/src/slic3r/GUI/DeviceCore/DevManager.cpp b/src/slic3r/GUI/DeviceCore/DevManager.cpp index d19f1aa0dd..5c32f42c2b 100644 --- a/src/slic3r/GUI/DeviceCore/DevManager.cpp +++ b/src/slic3r/GUI/DeviceCore/DevManager.cpp @@ -90,6 +90,25 @@ namespace Slic3r userMachineList.clear(); } + void DeviceManager::set_agent(NetworkAgent* agent) + { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": updating agent for " + << localMachineList.size() << " local and " + << userMachineList.size() << " user machines"; + m_agent = agent; + + std::lock_guard lock(listMutex); + for (auto& it : localMachineList) { + if (it.second) { + it.second->set_agent(agent); + } + } + for (auto& it : userMachineList) { + if (it.second) { + it.second->set_agent(agent); + } + } + } void DeviceManager::EnableMultiMachine(bool enable) { diff --git a/src/slic3r/GUI/DeviceCore/DevManager.h b/src/slic3r/GUI/DeviceCore/DevManager.h index fbc30c0050..5ecb77401d 100644 --- a/src/slic3r/GUI/DeviceCore/DevManager.h +++ b/src/slic3r/GUI/DeviceCore/DevManager.h @@ -40,7 +40,7 @@ public: public: NetworkAgent* get_agent() const { return m_agent; } - void set_agent(NetworkAgent* agent) { m_agent = agent; } + void set_agent(NetworkAgent* agent); void start_refresher(); void stop_refresher(); diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 112b514ab3..f4362cc3f7 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -135,6 +135,8 @@ public: MachineObject(DeviceManager* manager, NetworkAgent* agent, std::string name, std::string id, std::string ip); ~MachineObject(); + void set_agent(NetworkAgent* agent) { m_agent = agent; } + public: enum ActiveState { NotActive, diff --git a/src/slic3r/GUI/DownloadProgressDialog.cpp b/src/slic3r/GUI/DownloadProgressDialog.cpp index 1c4f7a9bfb..76ef7afa92 100644 --- a/src/slic3r/GUI/DownloadProgressDialog.cpp +++ b/src/slic3r/GUI/DownloadProgressDialog.cpp @@ -19,6 +19,7 @@ //#include "ConfigWizard.hpp" #include "wxExtensions.hpp" #include "slic3r/GUI/MainFrame.hpp" +#include "slic3r/GUI/MsgDialog.hpp" #include "GUI_App.hpp" #include "Jobs/BoostThreadWorker.hpp" #include "Jobs/PlaterWorker.hpp" @@ -203,6 +204,16 @@ void DownloadProgressDialog::update_release_note(std::string release_note, std:: std::unique_ptr DownloadProgressDialog::make_job() { return std::make_unique(); } -void DownloadProgressDialog::on_finish() { wxGetApp().restart_networking(); } +void DownloadProgressDialog::on_finish() +{ + if (wxGetApp().hot_reload_network_plugin()) { + return; + } + + MessageDialog dlg(nullptr, + _L("The network plugin was installed but could not be loaded. Please restart the application."), + _L("Restart Required"), wxOK | wxICON_INFORMATION); + dlg.ShowModal(); +} }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 27816e2b67..a66092c437 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ #include "UnsavedChangesDialog.hpp" #include "SavePresetDialog.hpp" #include "PrintHostDialogs.hpp" +#include "NetworkPluginDialog.hpp" #include "DesktopIntegrationDialog.hpp" #include "SendSystemInfoDialog.hpp" #include "ParamsDialog.hpp" @@ -959,15 +961,7 @@ void GUI_App::post_init() m_show_gcode_window = app_config->get_bool("show_gcode_window"); if (m_networking_need_update) { - //updating networking - int ret = updating_bambu_networking(); - if (!ret) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__<<":networking plugin updated successfully"; - //restart_networking(); - } - else { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__<<":networking plugin updated failed"; - } + show_network_plugin_download_dialog(false); } // Start preset sync after project opened, otherwise we could have preset change during project opening which could cause crash @@ -1177,12 +1171,20 @@ std::string GUI_App::get_plugin_url(std::string name, std::string country_code) { std::string url = get_http_url(country_code); - std::string curr_version = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : BAMBU_NETWORK_AGENT_VERSION; + std::string curr_version; + if (NetworkAgent::use_legacy_network) { + curr_version = BAMBU_NETWORK_AGENT_VERSION_LEGACY; + } else if (name == "plugins" && app_config) { + std::string user_version = app_config->get_network_plugin_version(); + curr_version = user_version.empty() ? BBL::get_latest_network_version() : user_version; + } else { + curr_version = BBL::get_latest_network_version(); + } + std::string using_version = curr_version.substr(0, 9) + "00"; if (name == "cameratools") using_version = curr_version.substr(0, 6) + "00.00"; url += (boost::format("?slicer/%1%/cloud=%2%") % name % using_version).str(); - //url += (boost::format("?slicer/plugins/cloud=%1%") % "01.01.00.00").str(); return url; } @@ -1413,6 +1415,32 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP return InstallStatusUnzipFailed; } + boost::filesystem::path legacy_lib_path, legacy_lib_backup; + bool had_existing_legacy = false; + if (name == "plugins") { +#if defined(_MSC_VER) || defined(_WIN32) + legacy_lib_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll"); +#elif defined(__WXMAC__) + legacy_lib_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib"); +#else + legacy_lib_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so"); +#endif + legacy_lib_backup = legacy_lib_path; + legacy_lib_backup += ".backup"; + + if (boost::filesystem::exists(legacy_lib_path)) { + had_existing_legacy = true; + boost::system::error_code ec; + boost::filesystem::rename(legacy_lib_path, legacy_lib_backup, ec); + if (ec) { + BOOST_LOG_TRIVIAL(warning) << "[install_plugin] failed to backup existing legacy library: " << ec.message(); + had_existing_legacy = false; + } else { + BOOST_LOG_TRIVIAL(info) << "[install_plugin] backed up existing legacy library"; + } + } + } + mz_uint num_entries = mz_zip_reader_get_num_files(&archive); mz_zip_archive_file_stat stat; BOOST_LOG_TRIVIAL(error) << boost::format("[install_plugin]: %1%, got %2% files")%__LINE__ %num_entries; @@ -1487,6 +1515,38 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP } close_zip_reader(&archive); + + if (name == "plugins") { + std::string config_version = app_config->get_network_plugin_version(); + if (!config_version.empty() && boost::filesystem::exists(legacy_lib_path)) { +#if defined(_MSC_VER) || defined(_WIN32) + auto versioned_lib = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + config_version + ".dll"); +#elif defined(__WXMAC__) + auto versioned_lib = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + config_version + ".dylib"); +#else + auto versioned_lib = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + config_version + ".so"); +#endif + BOOST_LOG_TRIVIAL(info) << "[install_plugin] renaming newly extracted " << legacy_lib_path.string() << " to " << versioned_lib.string(); + boost::system::error_code ec; + if (boost::filesystem::exists(versioned_lib)) { + boost::filesystem::remove(versioned_lib, ec); + } + boost::filesystem::rename(legacy_lib_path, versioned_lib, ec); + if (ec) { + BOOST_LOG_TRIVIAL(error) << "[install_plugin] failed to rename to versioned: " << ec.message(); + } + } + + if (had_existing_legacy && boost::filesystem::exists(legacy_lib_backup)) { + BOOST_LOG_TRIVIAL(info) << "[install_plugin] restoring backed up legacy library"; + boost::system::error_code ec; + boost::filesystem::rename(legacy_lib_backup, legacy_lib_path, ec); + if (ec) { + BOOST_LOG_TRIVIAL(warning) << "[install_plugin] failed to restore legacy library backup: " << ec.message(); + } + } + } + { fs::path dir_path(plugin_folder); if (fs::exists(dir_path) && fs::is_directory(dir_path)) { @@ -1519,6 +1579,8 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP } } } + + if (pro_fn) pro_fn(InstallStatusInstallCompleted, 100, cancel); if (name == "plugins") @@ -1572,6 +1634,167 @@ void GUI_App::restart_networking() BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(" exit, m_agent=%1%")%m_agent; } +bool GUI_App::hot_reload_network_plugin() +{ + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": starting hot reload"; + + wxBusyCursor busy; + wxBusyInfo info(_L("Reloading network plugin..."), mainframe); + wxYield(); + wxWindowDisabler disabler; + + if (mainframe) { + int current_tab = mainframe->m_tabpanel->GetSelection(); + if (current_tab == MainFrame::TabPosition::tpMonitor) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": navigating away from Monitor tab before unload"; + mainframe->m_tabpanel->SetSelection(MainFrame::TabPosition::tp3DEditor); + } + } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": stopping sync thread before unload"; + if (m_user_sync_token) { + m_user_sync_token.reset(); + } + if (m_sync_update_thread.joinable()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": waiting for sync thread to finish"; + m_sync_update_thread.join(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": sync thread finished"; + } + + if (m_agent) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": clearing callbacks and stopping operations"; + + m_agent->set_on_ssdp_msg_fn(nullptr); + m_agent->set_on_user_login_fn(nullptr); + m_agent->set_on_printer_connected_fn(nullptr); + m_agent->set_on_server_connected_fn(nullptr); + m_agent->set_on_http_error_fn(nullptr); + m_agent->set_on_subscribe_failure_fn(nullptr); + m_agent->set_on_message_fn(nullptr); + m_agent->set_on_user_message_fn(nullptr); + m_agent->set_on_local_connect_fn(nullptr); + m_agent->set_on_local_message_fn(nullptr); + m_agent->set_queue_on_main_fn(nullptr); + + m_agent->start_discovery(false, false); + m_agent->disconnect_printer(); + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": destroying network agent"; + delete m_agent; + m_agent = nullptr; + + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + + if (Slic3r::NetworkAgent::is_network_module_loaded()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unloading old module"; + int unload_result = Slic3r::NetworkAgent::unload_network_module(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unload result = " << unload_result; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": calling restart_networking"; + restart_networking(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": restart_networking returned"; + + std::string loaded_version = Slic3r::NetworkAgent::get_version(); + bool success = m_agent != nullptr && !loaded_version.empty() && loaded_version != "00.00.00.00"; + bool user_logged_in = m_agent && m_agent->is_user_login(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": after restart_networking, is_user_login = " << user_logged_in + << ", m_agent = " << (m_agent ? "valid" : "null") + << ", version = " << loaded_version; + + if (success && m_agent && m_device_manager) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": connecting to cloud server"; + m_agent->connect_server(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": re-subscribing to cloud printers"; + m_device_manager->add_user_subscribe(); + } + + if (mainframe && mainframe->m_monitor) { + mainframe->m_monitor->update_network_version_footer(); + mainframe->m_monitor->set_default(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": reset monitor panel"; + } + + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": hot reload " << (success ? "successful" : "failed"); + return success; +} + +std::string GUI_App::get_latest_network_version() const +{ + return BBL::get_latest_network_version(); +} + +bool GUI_App::has_network_update_available() const +{ + std::string current = Slic3r::NetworkAgent::get_version(); + std::string latest = get_latest_network_version(); + + if (current.empty() || current == "00.00.00.00") + return false; + + return current.substr(0, 8) != latest.substr(0, 8); +} + +void GUI_App::show_network_plugin_download_dialog(bool is_update) +{ + auto load_error = Slic3r::NetworkAgent::get_load_error(); + + NetworkPluginDownloadDialog::Mode mode; + if (load_error.has_error) { + mode = NetworkPluginDownloadDialog::Mode::CorruptedPlugin; + } else if (is_update) { + mode = NetworkPluginDownloadDialog::Mode::UpdateAvailable; + } else { + mode = NetworkPluginDownloadDialog::Mode::MissingPlugin; + } + + std::string current_version = Slic3r::NetworkAgent::get_version(); + + NetworkPluginDownloadDialog dlg(mainframe, mode, current_version, + load_error.message, load_error.technical_details); + + int result = dlg.ShowModal(); + + switch (result) { + case NetworkPluginDownloadDialog::RESULT_DOWNLOAD: + { + std::string selected = dlg.get_selected_version(); + app_config->set_network_plugin_version(selected); + app_config->save(); + + DownloadProgressDialog download_dlg(_L("Downloading Network Plugin")); + download_dlg.ShowModal(); + } + break; + + case NetworkPluginDownloadDialog::RESULT_REMIND_LATER: + app_config->set_remind_network_update_later(true); + app_config->save(); + break; + + case NetworkPluginDownloadDialog::RESULT_SKIP_VERSION: + { + std::string latest = get_latest_network_version(); + app_config->add_skipped_network_version(latest); + app_config->save(); + } + break; + + case NetworkPluginDownloadDialog::RESULT_DONT_ASK: + app_config->set_network_update_prompt_disabled(true); + app_config->save(); + break; + + case NetworkPluginDownloadDialog::RESULT_SKIP: + default: + break; + } +} + void GUI_App::remove_old_networking_plugins() { std::string data_dir_str = data_dir(); @@ -1601,8 +1824,20 @@ bool GUI_App::check_networking_version() if (!network_ver.empty()) { BOOST_LOG_TRIVIAL(info) << "get_network_agent_version=" << network_ver; } - std::string studio_ver = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : BAMBU_NETWORK_AGENT_VERSION; - if (network_ver.length() >= 8) { + + std::string studio_ver; + if (NetworkAgent::use_legacy_network) { + studio_ver = BAMBU_NETWORK_AGENT_VERSION_LEGACY; + } else if (app_config) { + std::string user_version = app_config->get_network_plugin_version(); + studio_ver = user_version.empty() ? BBL::get_latest_network_version() : user_version; + } else { + studio_ver = BBL::get_latest_network_version(); + } + + BOOST_LOG_TRIVIAL(info) << "check_networking_version: network_ver=" << network_ver << ", expected=" << studio_ver; + + if (network_ver.length() >= 8 && studio_ver.length() >= 8) { if (network_ver.substr(0,8) == studio_ver.substr(0,8)) { m_networking_compatible = true; return true; @@ -2857,78 +3092,103 @@ void GUI_App::copy_network_if_available() { if (app_config->get("update_network_plugin") != "true") return; - std::string network_library, player_library, live555_library, network_library_dst, player_library_dst, live555_library_dst; + std::string data_dir_str = data_dir(); boost::filesystem::path data_dir_path(data_dir_str); auto plugin_folder = data_dir_path / "plugins"; auto cache_folder = data_dir_path / "ota"; std::string changelog_file = cache_folder.string() + "/network_plugins.json"; + + std::string cached_version; + if (boost::filesystem::exists(changelog_file)) { + try { + boost::nowide::ifstream ifs(changelog_file); + json j; + ifs >> j; + if (j.contains("version")) + cached_version = j["version"]; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": cached_version = " << cached_version; + } catch (nlohmann::detail::parse_error& err) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << changelog_file << " failed: " << err.what(); + } + } + + if (cached_version.empty()) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": no version found in changelog, aborting copy"; + app_config->set("update_network_plugin", "false"); + return; + } + + std::string network_library, player_library, live555_library, network_library_dst, player_library_dst, live555_library_dst; #if defined(_MSC_VER) || defined(_WIN32) network_library = cache_folder.string() + "/bambu_networking.dll"; - player_library = cache_folder.string() + "/BambuSource.dll"; - live555_library = cache_folder.string() + "/live555.dll"; - network_library_dst = plugin_folder.string() + "/bambu_networking.dll"; - player_library_dst = plugin_folder.string() + "/BambuSource.dll"; + player_library = cache_folder.string() + "/BambuSource.dll"; + live555_library = cache_folder.string() + "/live555.dll"; + network_library_dst = plugin_folder.string() + "/" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + cached_version + ".dll"; + player_library_dst = plugin_folder.string() + "/BambuSource.dll"; live555_library_dst = plugin_folder.string() + "/live555.dll"; #elif defined(__WXMAC__) network_library = cache_folder.string() + "/libbambu_networking.dylib"; player_library = cache_folder.string() + "/libBambuSource.dylib"; live555_library = cache_folder.string() + "/liblive555.dylib"; - network_library_dst = plugin_folder.string() + "/libbambu_networking.dylib"; + network_library_dst = plugin_folder.string() + "/lib" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + cached_version + ".dylib"; player_library_dst = plugin_folder.string() + "/libBambuSource.dylib"; live555_library_dst = plugin_folder.string() + "/liblive555.dylib"; #else network_library = cache_folder.string() + "/libbambu_networking.so"; - player_library = cache_folder.string() + "/libBambuSource.so"; - live555_library = cache_folder.string() + "/liblive555.so"; - network_library_dst = plugin_folder.string() + "/libbambu_networking.so"; - player_library_dst = plugin_folder.string() + "/libBambuSource.so"; + player_library = cache_folder.string() + "/libBambuSource.so"; + live555_library = cache_folder.string() + "/liblive555.so"; + network_library_dst = plugin_folder.string() + "/lib" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + cached_version + ".so"; + player_library_dst = plugin_folder.string() + "/libBambuSource.so"; live555_library_dst = plugin_folder.string() + "/liblive555.so"; #endif - BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": checking network_library " << network_library << ", player_library " << player_library; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": checking network_library " << network_library << ", player_library " << player_library; if (!boost::filesystem::exists(plugin_folder)) { - BOOST_LOG_TRIVIAL(info)<< __FUNCTION__ << ": create directory "<set(SETTING_NETWORK_PLUGIN_VERSION, cached_version); + app_config->save(); } if (boost::filesystem::exists(player_library)) { CopyFileResult cfr = copy_file(player_library, player_library_dst, error_message, false); if (cfr != CopyFileResult::SUCCESS) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": Copying failed(" << cfr << "): " << error_message; + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": Copying failed(" << cfr << "): " << error_message; return; } static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; fs::permissions(player_library_dst, perms); fs::remove(player_library); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": Copying player library from" << player_library << " to " << player_library_dst<<" successfully."; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Copying player library from " << player_library << " to " << player_library_dst << " successfully."; } if (boost::filesystem::exists(live555_library)) { CopyFileResult cfr = copy_file(live555_library, live555_library_dst, error_message, false); if (cfr != CopyFileResult::SUCCESS) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": Copying failed(" << cfr << "): " << error_message; + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": Copying failed(" << cfr << "): " << error_message; return; } static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; fs::permissions(live555_library_dst, perms); fs::remove(live555_library); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< ": Copying live555 library from" << live555_library << " to " << live555_library_dst<<" successfully."; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Copying live555 library from " << live555_library << " to " << live555_library_dst << " successfully."; } if (boost::filesystem::exists(changelog_file)) fs::remove(changelog_file); @@ -2939,13 +3199,39 @@ bool GUI_App::on_init_network(bool try_backup) { bool create_network_agent = false; auto should_load_networking_plugin = app_config->get_bool("installed_networking"); + + std::string config_version = app_config->get_network_plugin_version(); + + if (should_load_networking_plugin && Slic3r::NetworkAgent::legacy_library_exists() && config_version.empty()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": migration: legacy library found with no config version, removing and requesting download"; + Slic3r::NetworkAgent::remove_legacy_library(); + m_networking_need_update = true; + return false; + } + if(!should_load_networking_plugin) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "Don't load plugin as installed_networking is false"; } else { - int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(); + if (config_version.empty()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": no version configured, need to download"; + m_networking_need_update = true; + return false; + } + int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); __retry: if (!load_agent_dll) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll ok"; + + std::string loaded_version = Slic3r::NetworkAgent::get_version(); + if (app_config && !loaded_version.empty() && loaded_version != "00.00.00.00") { + std::string config_version = app_config->get_network_plugin_version(); + if (config_version != loaded_version) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": syncing config version from " << config_version << " to loaded " << loaded_version; + app_config->set(SETTING_NETWORK_PLUGIN_VERSION, loaded_version); + app_config->save(); + } + } + if (check_networking_version()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, compatibility version"; auto bambu_source = Slic3r::NetworkAgent::get_bambu_source_entry(); @@ -2962,7 +3248,7 @@ __retry: if (try_backup) { int result = Slic3r::NetworkAgent::unload_network_module(); BOOST_LOG_TRIVIAL(info) << "on_init_network, version mismatch, unload_network_module, result = " << result; - load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(true); + load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(true, config_version); try_backup = false; goto __retry; } @@ -3041,6 +3327,24 @@ __retry: m_user_manager = new Slic3r::UserManager(); } + if (create_network_agent && m_networking_compatible && !NetworkAgent::use_legacy_network) { + app_config->clear_remind_network_update_later(); + + if (has_network_update_available()) { + std::string latest = get_latest_network_version(); + + bool should_prompt = !app_config->is_network_update_prompt_disabled() + && !app_config->is_network_version_skipped(latest) + && !app_config->should_remind_network_update_later(); + + if (should_prompt) { + CallAfter([this]() { + show_network_plugin_download_dialog(true); + }); + } + } + } + return true; } @@ -4880,6 +5184,17 @@ bool GUI_App::process_network_msg(std::string dev_id, std::string msg) { if (dev_id.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << msg; + + if (msg == "unsigned_studio") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, unsigned_studio"; + MessageDialog msg_dlg(nullptr, + _L("Bambu Lab has implemented a signature verification check in their network plugin that restricts " + "third-party software from communicating with your printer.\n\n" + "As a result, some printing functions are unavailable in OrcaSlicer."), + _L("Network Plugin Restriction"), wxICON_WARNING | wxOK); + msg_dlg.ShowModal(); + return true; + } } else if (msg == "device_cert_installed") { BOOST_LOG_TRIVIAL(info) << "process_network_msg, device_cert_installed"; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index f3900f6128..476dfc6f68 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -686,6 +686,11 @@ public: void restart_networking(); void check_config_updates_from_updater() { check_updates(false); } + void show_network_plugin_download_dialog(bool is_update = false); + bool hot_reload_network_plugin(); + std::string get_latest_network_version() const; + bool has_network_update_available() const; + private: int updating_bambu_networking(); bool on_init_inner(); @@ -712,6 +717,7 @@ private: bool m_init_app_config_from_older { false }; bool m_datadir_redefined { false }; std::string m_older_data_dir_path; + bool m_unsigned_plugin_warning_shown { false }; boost::optional m_last_config_version; bool m_config_corrupted { false }; std::string m_open_method; diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index aa1e3e2ea8..fd4249863f 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -195,6 +195,11 @@ void MonitorPanel::init_tabpanel() m_hms_panel = new HMSPanel(m_tabpanel); m_tabpanel->AddPage(m_hms_panel, _L("Assistant(HMS)"), "", false); + std::string network_ver = Slic3r::NetworkAgent::get_version(); + if (!network_ver.empty()) { + m_tabpanel->SetFooterText(wxString::Format("Network plugin v%s", network_ver)); + } + m_initialized = true; show_status((int)MonitorStatus::MONITOR_NO_PRINTER); } @@ -407,6 +412,7 @@ bool MonitorPanel::Show(bool show) DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (show) { start_update(); + update_network_version_footer(); m_refresh_timer->Stop(); m_refresh_timer->SetOwner(this); @@ -517,5 +523,13 @@ void MonitorPanel::jump_to_LiveView() m_status_info_panel->get_media_play_ctrl()->jump_to_play(); } +void MonitorPanel::update_network_version_footer() +{ + std::string network_ver = Slic3r::NetworkAgent::get_version(); + if (!network_ver.empty()) { + m_tabpanel->SetFooterText(wxString::Format("Network plugin v%s", network_ver)); + } +} + } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index a7f7126534..b7502b9d51 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -157,6 +157,7 @@ public: void jump_to_HMS(); void jump_to_LiveView(); + void update_network_version_footer(); }; diff --git a/src/slic3r/GUI/NetworkPluginDialog.cpp b/src/slic3r/GUI/NetworkPluginDialog.cpp new file mode 100644 index 0000000000..ca1ae3bea2 --- /dev/null +++ b/src/slic3r/GUI/NetworkPluginDialog.cpp @@ -0,0 +1,371 @@ +#include "NetworkPluginDialog.hpp" +#include "I18N.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" +#include "MsgDialog.hpp" +#include "Widgets/Label.hpp" +#include "BitmapCache.hpp" +#include "wxExtensions.hpp" +#include "slic3r/Utils/bambu_networking.hpp" + +#include +#include +#include + +namespace Slic3r { +namespace GUI { + +NetworkPluginDownloadDialog::NetworkPluginDownloadDialog(wxWindow* parent, Mode mode, + const std::string& current_version, + const std::string& error_message, + const std::string& error_details) + : DPIDialog(parent, wxID_ANY, mode == Mode::UpdateAvailable ? + _L("Network Plugin Update Available") : _L("Bambu Network Plugin Required"), + wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) + , m_mode(mode) + , m_error_message(error_message) + , m_error_details(error_details) +{ + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + main_sizer->Add(m_line_top, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + + SetSizer(main_sizer); + + if (mode == Mode::UpdateAvailable) { + create_update_available_ui(current_version); + } else { + create_missing_plugin_ui(); + } + Layout(); + Fit(); + CentreOnParent(); + wxGetApp().UpdateDlgDarkUI(this); +} + +void NetworkPluginDownloadDialog::create_missing_plugin_ui() +{ + wxBoxSizer* main_sizer = static_cast(GetSizer()); + + auto* desc = new wxStaticText(this, wxID_ANY, + m_mode == Mode::CorruptedPlugin ? + _L("The Bambu Network Plugin is corrupted or incompatible. Please reinstall it.") : + _L("The Bambu Network Plugin is required for cloud features, printer discovery, and remote printing.")); + desc->SetFont(::Label::Body_13); + desc->Wrap(FromDIP(400)); + main_sizer->Add(desc, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + + if (!m_error_message.empty()) { + auto* error_label = new wxStaticText(this, wxID_ANY, + wxString::Format(_L("Error: %s"), wxString::FromUTF8(m_error_message))); + error_label->SetFont(::Label::Body_13); + error_label->SetForegroundColour(wxColour(208, 93, 93)); + error_label->Wrap(FromDIP(400)); + main_sizer->Add(error_label, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + if (!m_error_details.empty()) { + m_details_pane = new wxCollapsiblePane(this, wxID_ANY, _L("Show details")); + auto* pane = m_details_pane->GetPane(); + auto* pane_sizer = new wxBoxSizer(wxVERTICAL); + + auto* details_text = new wxStaticText(pane, wxID_ANY, wxString::FromUTF8(m_error_details)); + details_text->SetFont(wxGetApp().code_font()); + details_text->Wrap(FromDIP(380)); + pane_sizer->Add(details_text, 0, wxALL, FromDIP(10)); + + pane->SetSizer(pane_sizer); + main_sizer->Add(m_details_pane, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + } + } + + auto* version_label = new wxStaticText(this, wxID_ANY, _L("Version to install:")); + version_label->SetFont(::Label::Body_13); + main_sizer->Add(version_label, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5)); + + setup_version_selector(); + main_sizer->Add(m_version_combo, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + + auto* btn_sizer = new wxBoxSizer(wxHORIZONTAL); + btn_sizer->Add(0, 0, 1, wxEXPAND, 0); + + StateColor btn_bg_green( + std::pair(wxColour(0, 137, 123), StateColor::Pressed), + std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + + StateColor btn_bg_white( + std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + + auto* btn_download = new Button(this, _L("Download and Install")); + btn_download->SetBackgroundColor(btn_bg_green); + btn_download->SetBorderColor(*wxWHITE); + btn_download->SetTextColor(*wxWHITE); + btn_download->SetFont(::Label::Body_12); + btn_download->SetMinSize(wxSize(FromDIP(120), FromDIP(24))); + btn_download->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_download, this); + btn_sizer->Add(btn_download, 0, wxRIGHT, FromDIP(10)); + + auto* btn_skip = new Button(this, _L("Skip for Now")); + btn_skip->SetBackgroundColor(btn_bg_white); + btn_skip->SetBorderColor(wxColour(38, 46, 48)); + btn_skip->SetFont(::Label::Body_12); + btn_skip->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_skip->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_skip, this); + btn_sizer->Add(btn_skip, 0, wxRIGHT, FromDIP(10)); + + main_sizer->Add(btn_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); + main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(20)); +} + +void NetworkPluginDownloadDialog::create_update_available_ui(const std::string& current_version) +{ + wxBoxSizer* main_sizer = static_cast(GetSizer()); + + auto* desc = new wxStaticText(this, wxID_ANY, + _L("A new version of the Bambu Network Plugin is available.")); + desc->SetFont(::Label::Body_13); + desc->Wrap(FromDIP(400)); + main_sizer->Add(desc, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(15)); + + auto* version_text = new wxStaticText(this, wxID_ANY, + wxString::Format(_L("Current version: %s"), wxString::FromUTF8(current_version))); + version_text->SetFont(::Label::Body_13); + main_sizer->Add(version_text, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + auto* update_label = new wxStaticText(this, wxID_ANY, _L("Update to version:")); + update_label->SetFont(::Label::Body_13); + main_sizer->Add(update_label, 0, wxLEFT | wxRIGHT, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5)); + + setup_version_selector(); + main_sizer->Add(m_version_combo, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(25)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + + auto* btn_sizer = new wxBoxSizer(wxHORIZONTAL); + btn_sizer->Add(0, 0, 1, wxEXPAND, 0); + + StateColor btn_bg_green( + std::pair(wxColour(0, 137, 123), StateColor::Pressed), + std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + + StateColor btn_bg_white( + std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + + auto* btn_download = new Button(this, _L("Update Now")); + btn_download->SetBackgroundColor(btn_bg_green); + btn_download->SetBorderColor(*wxWHITE); + btn_download->SetTextColor(*wxWHITE); + btn_download->SetFont(::Label::Body_12); + btn_download->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_download->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_download, this); + btn_sizer->Add(btn_download, 0, wxRIGHT, FromDIP(10)); + + auto* btn_remind = new Button(this, _L("Remind Later")); + btn_remind->SetBackgroundColor(btn_bg_white); + btn_remind->SetBorderColor(wxColour(38, 46, 48)); + btn_remind->SetFont(::Label::Body_12); + btn_remind->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_remind->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_remind_later, this); + btn_sizer->Add(btn_remind, 0, wxRIGHT, FromDIP(10)); + + auto* btn_skip = new Button(this, _L("Skip Version")); + btn_skip->SetBackgroundColor(btn_bg_white); + btn_skip->SetBorderColor(wxColour(38, 46, 48)); + btn_skip->SetFont(::Label::Body_12); + btn_skip->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_skip->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_skip_version, this); + btn_sizer->Add(btn_skip, 0, wxRIGHT, FromDIP(10)); + + auto* btn_dont_ask = new Button(this, _L("Don't Ask Again")); + btn_dont_ask->SetBackgroundColor(btn_bg_white); + btn_dont_ask->SetBorderColor(wxColour(38, 46, 48)); + btn_dont_ask->SetFont(::Label::Body_12); + btn_dont_ask->SetMinSize(wxSize(FromDIP(110), FromDIP(24))); + btn_dont_ask->Bind(wxEVT_BUTTON, &NetworkPluginDownloadDialog::on_dont_ask, this); + btn_sizer->Add(btn_dont_ask, 0, wxRIGHT, FromDIP(10)); + + main_sizer->Add(btn_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); + main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(20)); +} + +void NetworkPluginDownloadDialog::setup_version_selector() +{ + m_version_combo = new ComboBox(this, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxSize(FromDIP(380), FromDIP(28)), 0, nullptr, wxCB_READONLY); + m_version_combo->SetFont(::Label::Body_13); + + for (size_t i = 0; i < BBL::AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) { + const auto& ver = BBL::AVAILABLE_NETWORK_VERSIONS[i]; + wxString label = wxString::FromUTF8(ver.display_name); + if (ver.is_latest) { + label += wxString(" ") + _L("(Latest)"); + } + m_version_combo->Append(label); + } + + m_version_combo->SetSelection(0); +} + +std::string NetworkPluginDownloadDialog::get_selected_version() const +{ + if (!m_version_combo) { + return ""; + } + + int selection = m_version_combo->GetSelection(); + if (selection < 0 || selection >= static_cast(BBL::AVAILABLE_NETWORK_VERSIONS_COUNT)) { + return ""; + } + + return BBL::AVAILABLE_NETWORK_VERSIONS[selection].version; +} + +void NetworkPluginDownloadDialog::on_download(wxCommandEvent& evt) +{ + int selection = m_version_combo ? m_version_combo->GetSelection() : 0; + if (selection >= 0 && selection < static_cast(BBL::AVAILABLE_NETWORK_VERSIONS_COUNT)) { + const char* warning = BBL::AVAILABLE_NETWORK_VERSIONS[selection].warning; + if (warning) { + MessageDialog warn_dlg(this, wxString::FromUTF8(warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); + if (warn_dlg.ShowModal() != wxID_OK) { + return; + } + } + } + EndModal(RESULT_DOWNLOAD); +} + +void NetworkPluginDownloadDialog::on_skip(wxCommandEvent& evt) +{ + EndModal(RESULT_SKIP); +} + +void NetworkPluginDownloadDialog::on_remind_later(wxCommandEvent& evt) +{ + EndModal(RESULT_REMIND_LATER); +} + +void NetworkPluginDownloadDialog::on_skip_version(wxCommandEvent& evt) +{ + EndModal(RESULT_SKIP_VERSION); +} + +void NetworkPluginDownloadDialog::on_dont_ask(wxCommandEvent& evt) +{ + EndModal(RESULT_DONT_ASK); +} + +void NetworkPluginDownloadDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + Layout(); + Fit(); +} + +NetworkPluginRestartDialog::NetworkPluginRestartDialog(wxWindow* parent) + : DPIDialog(parent, wxID_ANY, _L("Restart Required"), + wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) +{ + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + main_sizer->Add(m_line_top, 0, wxEXPAND, 0); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + + auto* icon_sizer = new wxBoxSizer(wxHORIZONTAL); + auto* icon_bitmap = new wxStaticBitmap(this, wxID_ANY, + create_scaled_bitmap("info", nullptr, 64)); + icon_sizer->Add(icon_bitmap, 0, wxALL, FromDIP(10)); + + auto* text_sizer = new wxBoxSizer(wxVERTICAL); + + auto* desc = new wxStaticText(this, wxID_ANY, + _L("The Bambu Network Plugin has been installed successfully.")); + desc->SetFont(::Label::Body_14); + desc->Wrap(FromDIP(350)); + text_sizer->Add(desc, 0, wxTOP, FromDIP(10)); + text_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + auto* restart_msg = new wxStaticText(this, wxID_ANY, + _L("A restart is required to load the new plugin. Would you like to restart now?")); + restart_msg->SetFont(::Label::Body_13); + restart_msg->Wrap(FromDIP(350)); + text_sizer->Add(restart_msg, 0, wxBOTTOM, FromDIP(10)); + + icon_sizer->Add(text_sizer, 1, wxEXPAND | wxRIGHT, FromDIP(20)); + main_sizer->Add(icon_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(15)); + main_sizer->Add(0, 0, 0, wxTOP, FromDIP(20)); + + auto* btn_sizer = new wxBoxSizer(wxHORIZONTAL); + btn_sizer->Add(0, 0, 1, wxEXPAND, 0); + + StateColor btn_bg_green( + std::pair(wxColour(0, 137, 123), StateColor::Pressed), + std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + + StateColor btn_bg_white( + std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + + auto* btn_restart = new Button(this, _L("Restart Now")); + btn_restart->SetBackgroundColor(btn_bg_green); + btn_restart->SetBorderColor(*wxWHITE); + btn_restart->SetTextColor(*wxWHITE); + btn_restart->SetFont(::Label::Body_12); + btn_restart->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_restart->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + m_restart_now = true; + EndModal(wxID_OK); + }); + btn_sizer->Add(btn_restart, 0, wxRIGHT, FromDIP(10)); + + auto* btn_later = new Button(this, _L("Restart Later")); + btn_later->SetBackgroundColor(btn_bg_white); + btn_later->SetBorderColor(wxColour(38, 46, 48)); + btn_later->SetFont(::Label::Body_12); + btn_later->SetMinSize(wxSize(FromDIP(100), FromDIP(24))); + btn_later->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + m_restart_now = false; + EndModal(wxID_CANCEL); + }); + btn_sizer->Add(btn_later, 0, wxRIGHT, FromDIP(10)); + + main_sizer->Add(btn_sizer, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20)); + main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(20)); + + SetSizer(main_sizer); + Layout(); + Fit(); + CentreOnParent(); + wxGetApp().UpdateDlgDarkUI(this); +} + +void NetworkPluginRestartDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + Layout(); + Fit(); +} + +} +} diff --git a/src/slic3r/GUI/NetworkPluginDialog.hpp b/src/slic3r/GUI/NetworkPluginDialog.hpp new file mode 100644 index 0000000000..7e28fe2114 --- /dev/null +++ b/src/slic3r/GUI/NetworkPluginDialog.hpp @@ -0,0 +1,74 @@ +#ifndef slic3r_GUI_NetworkPluginDialog_hpp_ +#define slic3r_GUI_NetworkPluginDialog_hpp_ + +#include "GUI_Utils.hpp" +#include "MsgDialog.hpp" +#include "Widgets/ComboBox.hpp" +#include "Widgets/Button.hpp" +#include + +namespace Slic3r { +namespace GUI { + +class NetworkPluginDownloadDialog : public DPIDialog +{ +public: + enum class Mode { + MissingPlugin, + UpdateAvailable, + CorruptedPlugin + }; + + NetworkPluginDownloadDialog(wxWindow* parent, Mode mode, + const std::string& current_version = "", + const std::string& error_message = "", + const std::string& error_details = ""); + + std::string get_selected_version() const; + + enum ResultCode { + RESULT_DOWNLOAD = wxID_OK, + RESULT_SKIP = wxID_CANCEL, + RESULT_REMIND_LATER = wxID_APPLY, + RESULT_SKIP_VERSION = wxID_IGNORE, + RESULT_DONT_ASK = wxID_ABORT + }; + +protected: + void on_dpi_changed(const wxRect& suggested_rect) override; + +private: + void create_missing_plugin_ui(); + void create_update_available_ui(const std::string& current_version); + void setup_version_selector(); + void on_download(wxCommandEvent& evt); + void on_skip(wxCommandEvent& evt); + void on_remind_later(wxCommandEvent& evt); + void on_skip_version(wxCommandEvent& evt); + void on_dont_ask(wxCommandEvent& evt); + + Mode m_mode; + ComboBox* m_version_combo{nullptr}; + wxCollapsiblePane* m_details_pane{nullptr}; + std::string m_error_message; + std::string m_error_details; +}; + +class NetworkPluginRestartDialog : public DPIDialog +{ +public: + NetworkPluginRestartDialog(wxWindow* parent); + + bool should_restart_now() const { return m_restart_now; } + +protected: + void on_dpi_changed(const wxRect& suggested_rect) override; + +private: + bool m_restart_now{false}; +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GUI_NetworkPluginDialog_hpp_ diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 9cc05d5cf1..e2ee8c36c3 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -14,6 +14,8 @@ #include "NetworkTestDialog.hpp" #include "Widgets/StaticLine.hpp" #include "Widgets/RadioGroup.hpp" +#include "slic3r/Utils/bambu_networking.hpp" +#include "DownloadProgressDialog.hpp" #ifdef __WINDOWS__ #ifdef _MSW_DARK_MODE @@ -842,7 +844,7 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too if (param == "enable_high_low_temp_mixed_printing") { if (checkbox->GetValue()) { const wxString warning_title = _L("Bed Temperature Difference Warning"); - const wxString warning_message = + const wxString warning_message = _L("Using filaments with significantly different temperatures may cause:\n" "• Extruder clogging\n" "• Nozzle damage\n" @@ -876,6 +878,14 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too } } + if (param == "legacy_networking") { + bool legacy_mode = checkbox->GetValue(); + if (m_network_version_sizer != nullptr) { + m_network_version_sizer->Show(!legacy_mode); + m_parent->Layout(); + } + } + e.Skip(); }); @@ -1344,6 +1354,92 @@ void PreferencesDialog::create_items() auto item_legacy_network = create_item_checkbox(_L("Use legacy network plugin"), _L("Disable to use latest network plugin that supports new BambuLab firmwares."), "legacy_networking", _L("(Requires restart)")); g_sizer->Add(item_legacy_network); + m_network_version_sizer = new wxBoxSizer(wxHORIZONTAL); + m_network_version_sizer->AddSpacer(FromDIP(DESIGN_LEFT_MARGIN)); + + auto version_title = new wxStaticText(m_parent, wxID_ANY, _L("Network plugin version"), wxDefaultPosition, DESIGN_TITLE_SIZE, wxST_NO_AUTORESIZE); + version_title->SetForegroundColour(DESIGN_GRAY900_COLOR); + version_title->SetFont(::Label::Body_14); + version_title->SetToolTip(_L("Select the network plugin version to use")); + version_title->Wrap(DESIGN_TITLE_SIZE.x); + m_network_version_sizer->Add(version_title, 0, wxALIGN_CENTER); + + m_network_version_combo = new ::ComboBox(m_parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(180), -1), 0, nullptr, wxCB_READONLY); + m_network_version_combo->SetFont(::Label::Body_14); + m_network_version_combo->GetDropDown().SetFont(::Label::Body_14); + + std::string current_version = app_config->get("network_plugin_version"); + int current_selection = 0; + + for (size_t i = 0; i < BBL::AVAILABLE_NETWORK_VERSIONS_COUNT; i++) { + wxString label = wxString::FromUTF8(BBL::AVAILABLE_NETWORK_VERSIONS[i].display_name); + if (BBL::AVAILABLE_NETWORK_VERSIONS[i].is_latest) { + label += " " + _L("(Latest)"); + } + m_network_version_combo->Append(label); + if (current_version == BBL::AVAILABLE_NETWORK_VERSIONS[i].version) { + current_selection = i; + } + } + + m_network_version_combo->SetSelection(current_selection); + m_network_version_sizer->Add(m_network_version_combo, 0, wxALIGN_CENTER | wxLEFT, FromDIP(5)); + + m_network_version_combo->GetDropDown().Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& e) { + int selection = e.GetSelection(); + if (selection >= 0 && selection < (int)BBL::AVAILABLE_NETWORK_VERSIONS_COUNT) { + std::string new_version = BBL::AVAILABLE_NETWORK_VERSIONS[selection].version; + std::string old_version = app_config->get_network_plugin_version(); + if (old_version.empty()) { + old_version = BBL::get_latest_network_version(); + } + + app_config->set(SETTING_NETWORK_PLUGIN_VERSION, new_version); + app_config->save(); + + if (new_version != old_version) { + BOOST_LOG_TRIVIAL(info) << "Network plugin version changed from " << old_version << " to " << new_version; + + const char* warning = BBL::AVAILABLE_NETWORK_VERSIONS[selection].warning; + if (warning) { + MessageDialog warn_dlg(this, wxString::FromUTF8(warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); + if (warn_dlg.ShowModal() != wxID_OK) { + app_config->set(SETTING_NETWORK_PLUGIN_VERSION, old_version); + app_config->save(); + e.Skip(); + return; + } + } + + if (Slic3r::NetworkAgent::versioned_library_exists(new_version)) { + BOOST_LOG_TRIVIAL(info) << "Version " << new_version << " already exists on disk, triggering hot reload"; + if (wxGetApp().hot_reload_network_plugin()) { + MessageDialog dlg(this, _L("Network plugin switched successfully."), _L("Success"), wxOK | wxICON_INFORMATION); + dlg.ShowModal(); + } else { + MessageDialog dlg(this, _L("Failed to load network plugin. Please restart the application."), _L("Restart Required"), wxOK | wxICON_WARNING); + dlg.ShowModal(); + } + } else { + wxString msg = wxString::Format( + _L("You've selected network plugin version %s.\n\nWould you like to download and install this version now?\n\nNote: The application may need to restart after installation."), + wxString::FromUTF8(new_version)); + + MessageDialog dlg(this, msg, _L("Download Network Plugin"), wxYES_NO | wxICON_QUESTION); + if (dlg.ShowModal() == wxID_YES) { + DownloadProgressDialog progress_dlg(_L("Downloading Network Plugin")); + progress_dlg.ShowModal(); + } + } + } + } + e.Skip(); + }); + + bool legacy_mode = app_config->get_bool("legacy_networking"); + m_network_version_sizer->Show(!legacy_mode); + g_sizer->Add(m_network_version_sizer); + g_sizer->AddSpacer(FromDIP(10)); sizer_page->Add(g_sizer, 0, wxEXPAND); @@ -1413,6 +1509,18 @@ void PreferencesDialog::create_items() auto loglevel_combox = create_item_loglevel_combobox(_L("Log Level"), _L("Log Level"), log_level_list); g_sizer->Add(loglevel_combox); + g_sizer->Add(create_item_title(_L("Network Plugin")), 1, wxEXPAND); + auto item_reload_plugin = create_item_button(_L("Network plugin"), _L("Reload"), _L("Reload the network plugin without restarting the application"), "", [this]() { + if (wxGetApp().hot_reload_network_plugin()) { + MessageDialog dlg(this, _L("Network plugin reloaded successfully."), _L("Reload"), wxOK | wxICON_INFORMATION); + dlg.ShowModal(); + } else { + MessageDialog dlg(this, _L("Failed to reload network plugin. Please restart the application."), _L("Reload Failed"), wxOK | wxICON_ERROR); + dlg.ShowModal(); + } + }); + g_sizer->Add(item_reload_plugin); + //// DEVELOPER > Debug #if !BBL_RELEASE_TO_PUBLIC g_sizer->Add(create_item_title(_L("Debug")), 1, wxEXPAND); @@ -1613,7 +1721,7 @@ wxBoxSizer* PreferencesDialog::create_debug_page() bSizer->Add(enable_ssl_for_mqtt, 0, wxTOP, FromDIP(3)); bSizer->Add(enable_ssl_for_ftp, 0, wxTOP, FromDIP(3)); bSizer->Add(item_internal_developer, 0, wxTOP, FromDIP(3)); - bSizer->Add(title_host, 0, wxEXPAND); + bSizer->Add(title_host, 0, wxEXPAND | wxTOP, FromDIP(10)); bSizer->Add(radio_group, 0, wxEXPAND | wxLEFT, FromDIP(DESIGN_LEFT_MARGIN)); bSizer->Add(debug_button, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(15)); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index c6fa92a498..06d9a46f04 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -68,6 +68,8 @@ public: ::CheckBox * m_dark_mode_ckeckbox = {nullptr}; ::TextInput *m_backup_interval_textinput = {nullptr}; ::CheckBox * m_legacy_networking_ckeckbox = {nullptr}; + ::ComboBox * m_network_version_combo = {nullptr}; + wxBoxSizer * m_network_version_sizer = {nullptr}; wxString m_developer_mode_def; wxString m_internal_developer_mode_def; diff --git a/src/slic3r/GUI/Tabbook.cpp b/src/slic3r/GUI/Tabbook.cpp index ce26f3c658..db8cd3ba10 100644 --- a/src/slic3r/GUI/Tabbook.cpp +++ b/src/slic3r/GUI/Tabbook.cpp @@ -197,6 +197,20 @@ void TabButtonsListCtrl::SetPaddingSize(const wxSize& size) { } } +void TabButtonsListCtrl::SetFooterText(const wxString& text) +{ + if (!m_footer_text) { + m_footer_text = new wxStaticText(this, wxID_ANY, text); + m_footer_text->SetForegroundColour(wxColour(128, 128, 128)); + m_footer_text->SetFont(Label::Body_10); + int em = em_unit(this); + m_sizer->Add(m_footer_text, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, em / 2); + } else { + m_footer_text->SetLabel(text); + } + m_sizer->Layout(); +} + //#endif // _WIN32 diff --git a/src/slic3r/GUI/Tabbook.hpp b/src/slic3r/GUI/Tabbook.hpp index 7dd19389de..0cea1b8326 100644 --- a/src/slic3r/GUI/Tabbook.hpp +++ b/src/slic3r/GUI/Tabbook.hpp @@ -32,6 +32,7 @@ public: wxString GetPageText(size_t n) const; const wxSize& GetPaddingSize(size_t n); void SetPaddingSize(const wxSize& size); + void SetFooterText(const wxString& text); TabButton* pageButton; private: @@ -43,6 +44,7 @@ private: int m_selection {-1}; int m_btn_margin; int m_line_margin; + wxStaticText* m_footer_text {nullptr}; }; class Tabbook: public wxBookCtrlBase @@ -261,6 +263,11 @@ public: GetBtnsListCtrl()->Rescale(); } + void SetFooterText(const wxString& text) + { + GetBtnsListCtrl()->SetFooterText(text); + } + void OnNavigationKey(wxNavigationKeyEvent& event) { if (event.IsWindowChange()) { diff --git a/src/slic3r/Utils/NetworkAgent.cpp b/src/slic3r/Utils/NetworkAgent.cpp index 5f19e8f4e2..fc70630419 100644 --- a/src/slic3r/Utils/NetworkAgent.cpp +++ b/src/slic3r/Utils/NetworkAgent.cpp @@ -27,6 +27,7 @@ static void* source_module = NULL; #endif bool NetworkAgent::use_legacy_network = true; +NetworkLibraryLoadError NetworkAgent::s_load_error = {}; typedef int (*func_start_print_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn); typedef int (*func_start_local_print_with_record_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn); @@ -219,10 +220,72 @@ std::string NetworkAgent::get_libpath_in_current_directory(std::string library_n return lib_path; } - -int NetworkAgent::initialize_network_module(bool using_backup) +std::string NetworkAgent::get_versioned_library_path(const std::string& version) { - //int ret = -1; + std::string data_dir_str = data_dir(); + boost::filesystem::path data_dir_path(data_dir_str); + auto plugin_folder = data_dir_path / "plugins"; + +#if defined(_MSC_VER) || defined(_WIN32) + return (plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll")).string(); +#elif defined(__WXMAC__) + return (plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dylib")).string(); +#else + return (plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".so")).string(); +#endif +} + +bool NetworkAgent::versioned_library_exists(const std::string& version) +{ + if (version.empty()) return false; + std::string path = get_versioned_library_path(version); + return boost::filesystem::exists(path); +} + +bool NetworkAgent::legacy_library_exists() +{ + std::string data_dir_str = data_dir(); + boost::filesystem::path data_dir_path(data_dir_str); + auto plugin_folder = data_dir_path / "plugins"; + +#if defined(_MSC_VER) || defined(_WIN32) + auto legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll"); +#elif defined(__WXMAC__) + auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib"); +#else + auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so"); +#endif + return boost::filesystem::exists(legacy_path); +} + +void NetworkAgent::remove_legacy_library() +{ + std::string data_dir_str = data_dir(); + boost::filesystem::path data_dir_path(data_dir_str); + auto plugin_folder = data_dir_path / "plugins"; + +#if defined(_MSC_VER) || defined(_WIN32) + auto legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll"); +#elif defined(__WXMAC__) + auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib"); +#else + auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so"); +#endif + + if (boost::filesystem::exists(legacy_path)) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": removing legacy library at " << legacy_path.string(); + boost::system::error_code ec; + boost::filesystem::remove(legacy_path, ec); + if (ec) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": failed to remove legacy library: " << ec.message(); + } + } +} + +int NetworkAgent::initialize_network_module(bool using_backup, const std::string& version) +{ + clear_load_error(); + std::string library; std::string data_dir_str = data_dir(); boost::filesystem::path data_dir_path(data_dir_str); @@ -232,25 +295,33 @@ int NetworkAgent::initialize_network_module(bool using_backup) plugin_folder = plugin_folder/"backup"; } - //first load the library + if (version.empty()) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": version is required but not provided"; + set_load_error( + "Network library version not specified", + "A version must be specified to load the network library", + "" + ); + return -1; + } + #if defined(_MSC_VER) || defined(_WIN32) - library = plugin_folder.string() + "\\" + std::string(BAMBU_NETWORK_LIBRARY) + ".dll"; - wchar_t lib_wstr[128]; + library = plugin_folder.string() + "\\" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll"; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library; + wchar_t lib_wstr[256]; memset(lib_wstr, 0, sizeof(lib_wstr)); ::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0])); netwoking_module = LoadLibrary(lib_wstr); - /*if (!netwoking_module) { - library = std::string(BAMBU_NETWORK_LIBRARY) + ".dll"; - memset(lib_wstr, 0, sizeof(lib_wstr)); - ::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str()) + 1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0])); - netwoking_module = LoadLibrary(lib_wstr); - }*/ if (!netwoking_module) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", try load library directly from current directory"); - + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": versioned library not found, trying current directory"; std::string library_path = get_libpath_in_current_directory(std::string(BAMBU_NETWORK_LIBRARY)); if (library_path.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % BAMBU_NETWORK_LIBRARY; + set_load_error( + "Network library not found", + "Could not locate versioned library: " + library, + library + ); return -1; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path; @@ -260,28 +331,36 @@ int NetworkAgent::initialize_network_module(bool using_backup) } #else #if defined(__WXMAC__) - library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib"; + std::string lib_ext = ".dylib"; #else - library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so"; + std::string lib_ext = ".so"; #endif - printf("loading network module at %s\n", library.c_str()); - netwoking_module = dlopen( library.c_str(), RTLD_LAZY); + + library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + lib_ext; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library; + + netwoking_module = dlopen(library.c_str(), RTLD_LAZY); if (!netwoking_module) { - /*#if defined(__WXMAC__) - library = std::string("lib") + BAMBU_NETWORK_LIBRARY + ".dylib"; - #else - library = std::string("lib") + BAMBU_NETWORK_LIBRARY + ".so"; - #endif*/ - //netwoking_module = dlopen( library.c_str(), RTLD_LAZY); char* dll_error = dlerror(); - printf("error, dlerror is %s\n", dll_error); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", error, dlerror is %1%")%dll_error; + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": dlopen failed: " << (dll_error ? dll_error : "unknown error"); + set_load_error( + "Failed to load network library", + dll_error ? std::string(dll_error) : "Unknown dlopen error", + library + ); } printf("after dlopen, network_module is %p\n", netwoking_module); #endif if (!netwoking_module) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not Load Library for %1%")%library; + if (!s_load_error.has_error) { + set_load_error( + "Network library failed to load", + "LoadLibrary/dlopen returned null", + library + ); + } return -1; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", successfully loaded library %1%, module %2%")%library %netwoking_module; @@ -391,6 +470,12 @@ int NetworkAgent::initialize_network_module(bool using_backup) get_mw_user_preference_ptr = reinterpret_cast(get_network_function("bambu_network_get_mw_user_preference")); get_mw_user_4ulist_ptr = reinterpret_cast(get_network_function("bambu_network_get_mw_user_4ulist")); + if (get_version_ptr) { + std::string version = get_version_ptr(); + printf("network plugin version: %s\n", version.c_str()); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": network plugin version = " << version; + } + return 0; } @@ -515,6 +600,11 @@ int NetworkAgent::unload_network_module() return 0; } +bool NetworkAgent::is_network_module_loaded() +{ + return netwoking_module != nullptr; +} + #if defined(_MSC_VER) || defined(_WIN32) HMODULE NetworkAgent::get_bambu_source_entry() #else @@ -610,6 +700,24 @@ std::string NetworkAgent::get_version() return "00.00.00.00"; } +NetworkLibraryLoadError NetworkAgent::get_load_error() +{ + return s_load_error; +} + +void NetworkAgent::clear_load_error() +{ + s_load_error = NetworkLibraryLoadError{}; +} + +void NetworkAgent::set_load_error(const std::string& message, const std::string& technical_details, const std::string& attempted_path) +{ + s_load_error.has_error = true; + s_load_error.message = message; + s_load_error.technical_details = technical_details; + s_load_error.attempted_path = attempted_path; +} + int NetworkAgent::init_log() { int ret = 0; diff --git a/src/slic3r/Utils/NetworkAgent.hpp b/src/slic3r/Utils/NetworkAgent.hpp index 01d16d660b..e03106068e 100644 --- a/src/slic3r/Utils/NetworkAgent.hpp +++ b/src/slic3r/Utils/NetworkAgent.hpp @@ -116,8 +116,13 @@ class NetworkAgent public: static std::string get_libpath_in_current_directory(std::string library_name); - static int initialize_network_module(bool using_backup = false); + static std::string get_versioned_library_path(const std::string& version); + static bool versioned_library_exists(const std::string& version); + static bool legacy_library_exists(); + static void remove_legacy_library(); + static int initialize_network_module(bool using_backup = false, const std::string& version = ""); static int unload_network_module(); + static bool is_network_module_loaded(); #if defined(_MSC_VER) || defined(_WIN32) static HMODULE get_bambu_source_entry(); #else @@ -126,6 +131,10 @@ public: static std::string get_version(); static void* get_network_function(const char* name); static bool use_legacy_network; + + static NetworkLibraryLoadError get_load_error(); + static void clear_load_error(); + static void set_load_error(const std::string& message, const std::string& technical_details, const std::string& attempted_path); NetworkAgent(std::string log_dir); ~NetworkAgent(); @@ -232,6 +241,8 @@ private: bool enable_track = false; void* network_agent { nullptr }; + static NetworkLibraryLoadError s_load_error; + static func_check_debug_consistent check_debug_consistent_ptr; static func_get_version get_version_ptr; static func_create_agent create_agent_ptr; diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 0af6cd459f..26df92f7d4 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -849,7 +849,7 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_ BOOST_LOG_TRIVIAL(info) << "non need to sync plugins for there is no plugins currently."; return; } - std::string curr_version = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : BAMBU_NETWORK_AGENT_VERSION; + std::string curr_version = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : BBL::get_latest_network_version(); std::string using_version = curr_version.substr(0, 9) + "00"; std::string cached_version; diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index 710e171c7e..f18d29e0b2 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -98,7 +98,6 @@ namespace BBL { #define BAMBU_NETWORK_AGENT_NAME "bambu_network_agent" #define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.01" -#define BAMBU_NETWORK_AGENT_VERSION "02.03.00.62" //iot preset type strings #define IOT_PRINTER_TYPE_STRING "printer" @@ -306,6 +305,36 @@ struct CertificateInformation { std::string serial_number; }; +struct NetworkLibraryVersion { + const char* version; + const char* display_name; + const char* url_override; + bool is_latest; + const char* warning; +}; + +static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = { + {"02.03.00.62", "02.03.00.62", nullptr, true, nullptr}, + {"02.01.01.52", "02.01.01.52", nullptr, false, nullptr}, + {"02.00.02.50", "02.00.02.50", nullptr, false, "This version may crash on startup due to Bambu Lab's signature verification."}, +}; + +static const size_t AVAILABLE_NETWORK_VERSIONS_COUNT = sizeof(AVAILABLE_NETWORK_VERSIONS) / sizeof(AVAILABLE_NETWORK_VERSIONS[0]); + +inline const char* get_latest_network_version() { + for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) { + if (AVAILABLE_NETWORK_VERSIONS[i].is_latest) + return AVAILABLE_NETWORK_VERSIONS[i].version; + } + return AVAILABLE_NETWORK_VERSIONS[0].version; +} + +struct NetworkLibraryLoadError { + bool has_error = false; + std::string message; + std::string technical_details; + std::string attempted_path; +}; enum class MessageFlag : int { diff --git a/tests/libslic3r/CMakeLists.txt b/tests/libslic3r/CMakeLists.txt index 265feb660f..51e8e1ea6b 100644 --- a/tests/libslic3r/CMakeLists.txt +++ b/tests/libslic3r/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests.cpp test_3mf.cpp test_aabbindirect.cpp + test_appconfig.cpp test_clipper_offset.cpp test_clipper_utils.cpp test_config.cpp diff --git a/tests/libslic3r/test_appconfig.cpp b/tests/libslic3r/test_appconfig.cpp new file mode 100644 index 0000000000..59f9d11808 --- /dev/null +++ b/tests/libslic3r/test_appconfig.cpp @@ -0,0 +1,45 @@ +#include + +#include "libslic3r/AppConfig.hpp" + +using namespace Slic3r; + +TEST_CASE("AppConfig network version helpers", "[AppConfig]") { + AppConfig config; + + SECTION("skipped versions starts empty") { + auto skipped = config.get_skipped_network_versions(); + REQUIRE(skipped.empty()); + } + + SECTION("add and check skipped version") { + config.add_skipped_network_version("02.01.01.52"); + REQUIRE(config.is_network_version_skipped("02.01.01.52")); + REQUIRE_FALSE(config.is_network_version_skipped("02.03.00.62")); + } + + SECTION("multiple skipped versions") { + config.add_skipped_network_version("02.01.01.52"); + config.add_skipped_network_version("02.00.02.50"); + + auto skipped = config.get_skipped_network_versions(); + REQUIRE(skipped.size() == 2); + REQUIRE(config.is_network_version_skipped("02.01.01.52")); + REQUIRE(config.is_network_version_skipped("02.00.02.50")); + } + + SECTION("clear skipped versions") { + config.add_skipped_network_version("02.01.01.52"); + config.clear_skipped_network_versions(); + REQUIRE_FALSE(config.is_network_version_skipped("02.01.01.52")); + } + + SECTION("duplicate add is idempotent") { + config.add_skipped_network_version("02.01.01.52"); + config.add_skipped_network_version("02.01.01.52"); + + auto skipped = config.get_skipped_network_versions(); + REQUIRE(skipped.size() == 1); + REQUIRE(config.is_network_version_skipped("02.01.01.52")); + } +} From 0df673b0d3fd9b2d4adb9097fc817f9047dd8668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Wilczy=C5=84ski?= Date: Sun, 14 Dec 2025 15:27:56 +0100 Subject: [PATCH 02/45] Implement support for loading custom plugin binaries --- src/slic3r/GUI/GUI_App.cpp | 3 +- src/slic3r/GUI/Monitor.cpp | 20 +++- src/slic3r/GUI/NetworkPluginDialog.cpp | 26 ++++-- src/slic3r/GUI/NetworkPluginDialog.hpp | 2 + src/slic3r/GUI/Preferences.cpp | 28 ++++-- src/slic3r/GUI/Preferences.hpp | 2 + src/slic3r/Utils/NetworkAgent.cpp | 108 ++++++++++++++++++++++ src/slic3r/Utils/NetworkAgent.hpp | 1 + src/slic3r/Utils/bambu_networking.hpp | 43 +++++++++ tests/libslic3r/CMakeLists.txt | 2 + tests/libslic3r/test_bambu_networking.cpp | 98 ++++++++++++++++++++ 11 files changed, 310 insertions(+), 23 deletions(-) create mode 100644 tests/libslic3r/test_bambu_networking.cpp diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a66092c437..ba6a211fb7 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3225,7 +3225,8 @@ __retry: std::string loaded_version = Slic3r::NetworkAgent::get_version(); if (app_config && !loaded_version.empty() && loaded_version != "00.00.00.00") { std::string config_version = app_config->get_network_plugin_version(); - if (config_version != loaded_version) { + std::string config_base = BBL::extract_base_version(config_version); + if (config_base != loaded_version) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": syncing config version from " << config_version << " to loaded " << loaded_version; app_config->set(SETTING_NETWORK_PLUGIN_VERSION, loaded_version); app_config->save(); diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index fd4249863f..02b2306ff3 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -1,6 +1,8 @@ #include "Tab.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Model.hpp" +#include "libslic3r/AppConfig.hpp" +#include "slic3r/Utils/bambu_networking.hpp" #include #include @@ -525,10 +527,22 @@ void MonitorPanel::jump_to_LiveView() void MonitorPanel::update_network_version_footer() { - std::string network_ver = Slic3r::NetworkAgent::get_version(); - if (!network_ver.empty()) { - m_tabpanel->SetFooterText(wxString::Format("Network plugin v%s", network_ver)); + std::string binary_version = Slic3r::NetworkAgent::get_version(); + if (binary_version.empty()) + return; + + std::string configured_version = wxGetApp().app_config->get_network_plugin_version(); + std::string suffix = BBL::extract_suffix(configured_version); + std::string configured_base = BBL::extract_base_version(configured_version); + + wxString footer_text; + if (!suffix.empty() && configured_base == binary_version) { + footer_text = wxString::Format("Network plugin v%s (%s)", binary_version, suffix); + } else { + footer_text = wxString::Format("Network plugin v%s", binary_version); } + + m_tabpanel->SetFooterText(footer_text); } } // GUI diff --git a/src/slic3r/GUI/NetworkPluginDialog.cpp b/src/slic3r/GUI/NetworkPluginDialog.cpp index ca1ae3bea2..5c1e158748 100644 --- a/src/slic3r/GUI/NetworkPluginDialog.cpp +++ b/src/slic3r/GUI/NetworkPluginDialog.cpp @@ -211,11 +211,17 @@ void NetworkPluginDownloadDialog::setup_version_selector() wxDefaultPosition, wxSize(FromDIP(380), FromDIP(28)), 0, nullptr, wxCB_READONLY); m_version_combo->SetFont(::Label::Body_13); - for (size_t i = 0; i < BBL::AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) { - const auto& ver = BBL::AVAILABLE_NETWORK_VERSIONS[i]; - wxString label = wxString::FromUTF8(ver.display_name); - if (ver.is_latest) { - label += wxString(" ") + _L("(Latest)"); + m_available_versions = BBL::get_all_available_versions(); + for (size_t i = 0; i < m_available_versions.size(); ++i) { + const auto& ver = m_available_versions[i]; + wxString label; + if (!ver.suffix.empty()) { + label = wxString::FromUTF8("\xE2\x94\x94 ") + wxString::FromUTF8(ver.display_name); + } else { + label = wxString::FromUTF8(ver.display_name); + if (ver.is_latest) { + label += wxString(" ") + _L("(Latest)"); + } } m_version_combo->Append(label); } @@ -230,19 +236,19 @@ std::string NetworkPluginDownloadDialog::get_selected_version() const } int selection = m_version_combo->GetSelection(); - if (selection < 0 || selection >= static_cast(BBL::AVAILABLE_NETWORK_VERSIONS_COUNT)) { + if (selection < 0 || selection >= static_cast(m_available_versions.size())) { return ""; } - return BBL::AVAILABLE_NETWORK_VERSIONS[selection].version; + return m_available_versions[selection].version; } void NetworkPluginDownloadDialog::on_download(wxCommandEvent& evt) { int selection = m_version_combo ? m_version_combo->GetSelection() : 0; - if (selection >= 0 && selection < static_cast(BBL::AVAILABLE_NETWORK_VERSIONS_COUNT)) { - const char* warning = BBL::AVAILABLE_NETWORK_VERSIONS[selection].warning; - if (warning) { + if (selection >= 0 && selection < static_cast(m_available_versions.size())) { + const std::string& warning = m_available_versions[selection].warning; + if (!warning.empty()) { MessageDialog warn_dlg(this, wxString::FromUTF8(warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); if (warn_dlg.ShowModal() != wxID_OK) { return; diff --git a/src/slic3r/GUI/NetworkPluginDialog.hpp b/src/slic3r/GUI/NetworkPluginDialog.hpp index 7e28fe2114..88d4a3813c 100644 --- a/src/slic3r/GUI/NetworkPluginDialog.hpp +++ b/src/slic3r/GUI/NetworkPluginDialog.hpp @@ -5,6 +5,7 @@ #include "MsgDialog.hpp" #include "Widgets/ComboBox.hpp" #include "Widgets/Button.hpp" +#include "slic3r/Utils/bambu_networking.hpp" #include namespace Slic3r { @@ -52,6 +53,7 @@ private: wxCollapsiblePane* m_details_pane{nullptr}; std::string m_error_message; std::string m_error_details; + std::vector m_available_versions; }; class NetworkPluginRestartDialog : public DPIDialog diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index e2ee8c36c3..b595cbd04f 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1371,13 +1371,23 @@ void PreferencesDialog::create_items() std::string current_version = app_config->get("network_plugin_version"); int current_selection = 0; - for (size_t i = 0; i < BBL::AVAILABLE_NETWORK_VERSIONS_COUNT; i++) { - wxString label = wxString::FromUTF8(BBL::AVAILABLE_NETWORK_VERSIONS[i].display_name); - if (BBL::AVAILABLE_NETWORK_VERSIONS[i].is_latest) { + m_available_versions = BBL::get_all_available_versions(); + + for (size_t i = 0; i < m_available_versions.size(); i++) { + const auto& ver = m_available_versions[i]; + wxString label; + + if (!ver.suffix.empty()) { + label = wxString::FromUTF8("\xE2\x94\x94 ") + wxString::FromUTF8(ver.display_name); + } else { + label = wxString::FromUTF8(ver.display_name); + } + + if (ver.is_latest) { label += " " + _L("(Latest)"); } m_network_version_combo->Append(label); - if (current_version == BBL::AVAILABLE_NETWORK_VERSIONS[i].version) { + if (current_version == ver.version) { current_selection = i; } } @@ -1387,8 +1397,9 @@ void PreferencesDialog::create_items() m_network_version_combo->GetDropDown().Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& e) { int selection = e.GetSelection(); - if (selection >= 0 && selection < (int)BBL::AVAILABLE_NETWORK_VERSIONS_COUNT) { - std::string new_version = BBL::AVAILABLE_NETWORK_VERSIONS[selection].version; + if (selection >= 0 && selection < (int)m_available_versions.size()) { + const auto& selected_ver = m_available_versions[selection]; + std::string new_version = selected_ver.version; std::string old_version = app_config->get_network_plugin_version(); if (old_version.empty()) { old_version = BBL::get_latest_network_version(); @@ -1400,9 +1411,8 @@ void PreferencesDialog::create_items() if (new_version != old_version) { BOOST_LOG_TRIVIAL(info) << "Network plugin version changed from " << old_version << " to " << new_version; - const char* warning = BBL::AVAILABLE_NETWORK_VERSIONS[selection].warning; - if (warning) { - MessageDialog warn_dlg(this, wxString::FromUTF8(warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); + if (!selected_ver.warning.empty()) { + MessageDialog warn_dlg(this, wxString::FromUTF8(selected_ver.warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); if (warn_dlg.ShowModal() != wxID_OK) { app_config->set(SETTING_NETWORK_PLUGIN_VERSION, old_version); app_config->save(); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 06d9a46f04..90c3af1dee 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -13,6 +13,7 @@ #include "Widgets/CheckBox.hpp" #include "Widgets/TextInput.hpp" #include "Widgets/TabCtrl.hpp" +#include "slic3r/Utils/bambu_networking.hpp" namespace Slic3r { namespace GUI { @@ -70,6 +71,7 @@ public: ::CheckBox * m_legacy_networking_ckeckbox = {nullptr}; ::ComboBox * m_network_version_combo = {nullptr}; wxBoxSizer * m_network_version_sizer = {nullptr}; + std::vector m_available_versions; wxString m_developer_mode_def; wxString m_internal_developer_mode_def; diff --git a/src/slic3r/Utils/NetworkAgent.cpp b/src/slic3r/Utils/NetworkAgent.cpp index fc70630419..cbbc645682 100644 --- a/src/slic3r/Utils/NetworkAgent.cpp +++ b/src/slic3r/Utils/NetworkAgent.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #if defined(_MSC_VER) || defined(_WIN32) #include #else @@ -282,6 +284,52 @@ void NetworkAgent::remove_legacy_library() } } +std::vector NetworkAgent::scan_plugin_versions() +{ + std::vector discovered_versions; + std::string data_dir_str = data_dir(); + boost::filesystem::path plugin_folder = boost::filesystem::path(data_dir_str) / "plugins"; + + if (!boost::filesystem::is_directory(plugin_folder)) { + return discovered_versions; + } + +#if defined(_MSC_VER) || defined(_WIN32) + std::string prefix = std::string(BAMBU_NETWORK_LIBRARY) + "_"; + std::string extension = ".dll"; +#elif defined(__WXMAC__) + std::string prefix = std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_"; + std::string extension = ".dylib"; +#else + std::string prefix = std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_"; + std::string extension = ".so"; +#endif + + boost::system::error_code ec; + for (auto& entry : boost::filesystem::directory_iterator(plugin_folder, ec)) { + if (ec) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": error iterating directory: " << ec.message(); + break; + } + if (!boost::filesystem::is_regular_file(entry.status())) + continue; + + std::string filename = entry.path().filename().string(); + + if (filename.rfind(prefix, 0) != 0) + continue; + if (filename.size() <= extension.size() || + filename.compare(filename.size() - extension.size(), extension.size(), extension) != 0) + continue; + + std::string version = filename.substr(prefix.size(), + filename.size() - prefix.size() - extension.size()); + discovered_versions.push_back(version); + } + + return discovered_versions; +} + int NetworkAgent::initialize_network_module(bool using_backup, const std::string& version) { clear_load_error(); @@ -1770,3 +1818,63 @@ int NetworkAgent::get_model_mall_rating_result(int job_id, std::string &rating_r } } //namespace + +std::vector BBL::get_all_available_versions() +{ + std::vector result; + std::set known_base_versions; + std::set all_known_versions; + + for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) { + result.push_back(NetworkLibraryVersionInfo::from_static(AVAILABLE_NETWORK_VERSIONS[i])); + known_base_versions.insert(AVAILABLE_NETWORK_VERSIONS[i].version); + all_known_versions.insert(AVAILABLE_NETWORK_VERSIONS[i].version); + } + + std::vector discovered = Slic3r::NetworkAgent::scan_plugin_versions(); + + std::vector> suffixed_versions; + + for (const auto& version : discovered) { + if (all_known_versions.count(version) > 0) + continue; + + std::string base = extract_base_version(version); + std::string suffix = extract_suffix(version); + + if (suffix.empty()) + continue; + + if (known_base_versions.count(base) == 0) + continue; + + suffixed_versions.emplace_back(base, version); + all_known_versions.insert(version); + } + + std::sort(suffixed_versions.begin(), suffixed_versions.end(), + [](const auto& a, const auto& b) { + if (a.first != b.first) return a.first > b.first; + return a.second < b.second; + }); + + for (const auto& [base, full] : suffixed_versions) { + size_t insert_pos = 0; + for (size_t i = 0; i < result.size(); ++i) { + if (result[i].base_version == base) { + insert_pos = i + 1; + while (insert_pos < result.size() && + result[insert_pos].base_version == base) { + ++insert_pos; + } + break; + } + } + + std::string sfx = extract_suffix(full); + result.insert(result.begin() + insert_pos, + NetworkLibraryVersionInfo::from_discovered(full, base, sfx)); + } + + return result; +} diff --git a/src/slic3r/Utils/NetworkAgent.hpp b/src/slic3r/Utils/NetworkAgent.hpp index e03106068e..50bb35474e 100644 --- a/src/slic3r/Utils/NetworkAgent.hpp +++ b/src/slic3r/Utils/NetworkAgent.hpp @@ -120,6 +120,7 @@ public: static bool versioned_library_exists(const std::string& version); static bool legacy_library_exists(); static void remove_legacy_library(); + static std::vector scan_plugin_versions(); static int initialize_network_module(bool using_backup = false, const std::string& version = ""); static int unload_network_module(); static bool is_network_module_loaded(); diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index f18d29e0b2..b9a5b6b225 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -4,6 +4,7 @@ #include #include #include +#include extern std::string g_log_folder; extern std::string g_log_start_time; @@ -329,6 +330,48 @@ inline const char* get_latest_network_version() { return AVAILABLE_NETWORK_VERSIONS[0].version; } +struct NetworkLibraryVersionInfo { + std::string version; + std::string base_version; + std::string suffix; + std::string display_name; + std::string url_override; + bool is_latest; + std::string warning; + bool is_discovered; + + static NetworkLibraryVersionInfo from_static(const NetworkLibraryVersion& v) { + return { + v.version, + v.version, + "", + v.display_name, + v.url_override ? v.url_override : "", + v.is_latest, + v.warning ? v.warning : "", + false + }; + } + + static NetworkLibraryVersionInfo from_discovered(const std::string& full_version, + const std::string& base, + const std::string& sfx) { + return {full_version, base, sfx, full_version, "", false, "", true}; + } +}; + +inline std::string extract_base_version(const std::string& full_version) { + auto pos = full_version.find('-'); + return (pos == std::string::npos) ? full_version : full_version.substr(0, pos); +} + +inline std::string extract_suffix(const std::string& full_version) { + auto pos = full_version.find('-'); + return (pos == std::string::npos) ? "" : full_version.substr(pos + 1); +} + +std::vector get_all_available_versions(); + struct NetworkLibraryLoadError { bool has_error = false; std::string message; diff --git a/tests/libslic3r/CMakeLists.txt b/tests/libslic3r/CMakeLists.txt index 51e8e1ea6b..38ff543336 100644 --- a/tests/libslic3r/CMakeLists.txt +++ b/tests/libslic3r/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(${_TEST_NAME}_tests test_3mf.cpp test_aabbindirect.cpp test_appconfig.cpp + test_bambu_networking.cpp test_clipper_offset.cpp test_clipper_utils.cpp test_config.cpp @@ -30,6 +31,7 @@ if (TARGET OpenVDB::openvdb) endif() target_link_libraries(${_TEST_NAME}_tests test_common libslic3r Catch2::Catch2WithMain) +target_include_directories(${_TEST_NAME}_tests PRIVATE ${CMAKE_SOURCE_DIR}/src) set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests") if (WIN32) diff --git a/tests/libslic3r/test_bambu_networking.cpp b/tests/libslic3r/test_bambu_networking.cpp new file mode 100644 index 0000000000..c15f3b3d39 --- /dev/null +++ b/tests/libslic3r/test_bambu_networking.cpp @@ -0,0 +1,98 @@ +#include + +#include "slic3r/Utils/bambu_networking.hpp" + +using namespace BBL; + +TEST_CASE("extract_base_version", "[BambuNetworking]") { + SECTION("version without suffix returns unchanged") { + REQUIRE(extract_base_version("02.03.00.62") == "02.03.00.62"); + REQUIRE(extract_base_version("01.00.00.00") == "01.00.00.00"); + } + + SECTION("version with suffix returns base only") { + REQUIRE(extract_base_version("02.03.00.62-mod") == "02.03.00.62"); + REQUIRE(extract_base_version("02.03.00.62-patched") == "02.03.00.62"); + REQUIRE(extract_base_version("02.03.00.62-test-build") == "02.03.00.62"); + } + + SECTION("empty string returns empty") { + REQUIRE(extract_base_version("") == ""); + } + + SECTION("suffix only returns empty") { + REQUIRE(extract_base_version("-mod") == ""); + } +} + +TEST_CASE("extract_suffix", "[BambuNetworking]") { + SECTION("version without suffix returns empty") { + REQUIRE(extract_suffix("02.03.00.62") == ""); + REQUIRE(extract_suffix("01.00.00.00") == ""); + } + + SECTION("version with suffix returns suffix without dash") { + REQUIRE(extract_suffix("02.03.00.62-mod") == "mod"); + REQUIRE(extract_suffix("02.03.00.62-patched") == "patched"); + } + + SECTION("version with multiple dashes returns everything after first dash") { + REQUIRE(extract_suffix("02.03.00.62-test-build") == "test-build"); + } + + SECTION("empty string returns empty") { + REQUIRE(extract_suffix("") == ""); + } + + SECTION("suffix only returns suffix without leading dash") { + REQUIRE(extract_suffix("-mod") == "mod"); + } +} + +TEST_CASE("NetworkLibraryVersionInfo::from_static", "[BambuNetworking]") { + SECTION("converts static version info correctly") { + NetworkLibraryVersion static_ver{"02.03.00.62", "02.03.00.62", nullptr, true, nullptr}; + auto info = NetworkLibraryVersionInfo::from_static(static_ver); + + REQUIRE(info.version == "02.03.00.62"); + REQUIRE(info.base_version == "02.03.00.62"); + REQUIRE(info.suffix == ""); + REQUIRE(info.display_name == "02.03.00.62"); + REQUIRE(info.url_override == ""); + REQUIRE(info.is_latest == true); + REQUIRE(info.warning == ""); + REQUIRE(info.is_discovered == false); + } + + SECTION("handles version with warning") { + NetworkLibraryVersion static_ver{"02.00.02.50", "02.00.02.50", nullptr, false, "This is a warning"}; + auto info = NetworkLibraryVersionInfo::from_static(static_ver); + + REQUIRE(info.version == "02.00.02.50"); + REQUIRE(info.is_latest == false); + REQUIRE(info.warning == "This is a warning"); + REQUIRE(info.is_discovered == false); + } + + SECTION("handles version with url override") { + NetworkLibraryVersion static_ver{"02.01.01.52", "02.01.01.52", "https://custom.url/plugin.zip", false, nullptr}; + auto info = NetworkLibraryVersionInfo::from_static(static_ver); + + REQUIRE(info.url_override == "https://custom.url/plugin.zip"); + } +} + +TEST_CASE("NetworkLibraryVersionInfo::from_discovered", "[BambuNetworking]") { + SECTION("creates discovered version info correctly") { + auto info = NetworkLibraryVersionInfo::from_discovered("02.03.00.62-mod", "02.03.00.62", "mod"); + + REQUIRE(info.version == "02.03.00.62-mod"); + REQUIRE(info.base_version == "02.03.00.62"); + REQUIRE(info.suffix == "mod"); + REQUIRE(info.display_name == "02.03.00.62-mod"); + REQUIRE(info.url_override == ""); + REQUIRE(info.is_latest == false); + REQUIRE(info.warning == ""); + REQUIRE(info.is_discovered == true); + } +} From f232c9cf08cfd926237f81373cb0b6bcfdf01bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Wilczy=C5=84ski?= Date: Sun, 14 Dec 2025 16:49:17 +0100 Subject: [PATCH 03/45] Port all plugin error messages from Studio --- src/slic3r/GUI/GUI_App.cpp | 76 +++++++++++++++++++++++++++++++++++--- src/slic3r/GUI/GUI_App.hpp | 1 + 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ba6a211fb7..9edf8553dc 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -5184,16 +5184,82 @@ void GUI_App::check_new_version_sf(bool show_tips, int by_user) bool GUI_App::process_network_msg(std::string dev_id, std::string msg) { if (dev_id.empty()) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << msg; - - if (msg == "unsigned_studio") { + if (msg == "wait_info") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, wait_info"; + Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) + return true; + MachineObject* obj = dev->get_selected_machine(); + if (obj && m_agent) + m_agent->install_device_cert(obj->get_dev_id(), obj->is_lan_mode_printer()); + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("Retrieving printer information, please try again later."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "update_studio") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, update_studio"; + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("Please try updating OrcaSlicer and then try again."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "update_fixed_studio") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, update_fixed_studio"; + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("Please try updating OrcaSlicer and then try again."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "cert_expired") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, cert_expired"; + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("The certificate has expired. Please check the time settings or update OrcaSlicer and try again."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "cert_revoked") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, cert_revoked"; + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("The certificate is no longer valid and the printing functions are unavailable."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "update_firmware_studio") { + BOOST_LOG_TRIVIAL(info) << "process_network_msg, firmware internal error"; + if (!m_show_error_msgdlg) { + MessageDialog msg_dlg(nullptr, _L("Internal error. Please try upgrading the firmware and OrcaSlicer version. If the issue persists, contact support."), "", wxAPPLY | wxOK); + m_show_error_msgdlg = true; + msg_dlg.ShowModal(); + m_show_error_msgdlg = false; + } + return true; + } + else if (msg == "unsigned_studio") { BOOST_LOG_TRIVIAL(info) << "process_network_msg, unsigned_studio"; MessageDialog msg_dlg(nullptr, _L("Bambu Lab has implemented a signature verification check in their network plugin that restricts " "third-party software from communicating with your printer.\n\n" "As a result, some printing functions are unavailable in OrcaSlicer."), - _L("Network Plugin Restriction"), wxICON_WARNING | wxOK); + _L("Network Plugin Restriction"), wxAPPLY | wxOK); + m_show_error_msgdlg = true; msg_dlg.ShowModal(); + m_show_error_msgdlg = false; return true; } } @@ -5204,7 +5270,6 @@ bool GUI_App::process_network_msg(std::string dev_id, std::string msg) obj->update_device_cert_state(true); } } - return true; } else if (msg == "device_cert_uninstalled") { @@ -5214,7 +5279,6 @@ bool GUI_App::process_network_msg(std::string dev_id, std::string msg) obj->update_device_cert_state(false); } } - return true; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 476dfc6f68..9827e64fae 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -312,6 +312,7 @@ private: bool m_adding_script_handler { false }; bool m_side_popup_status{false}; bool m_show_http_errpr_msgdlg{false}; + bool m_show_error_msgdlg{false}; wxString m_info_dialog_content; HttpServer m_http_server; bool m_show_gcode_window{true}; From 8d8ab5911d84560516cb473b4f2372274f136ba8 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Fri, 19 Dec 2025 22:16:34 +0800 Subject: [PATCH 04/45] Update build_orca.yml to disable cache miss failure --- .github/workflows/build_orca.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index aef491f006..5a315bed74 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -35,7 +35,7 @@ jobs: with: path: ${{ inputs.cache-path }} key: ${{ inputs.cache-key }} - fail-on-cache-miss: true + fail-on-cache-miss: false - uses: lukka/get-cmake@latest with: From 0e5a816318d019734c5c808b4a5762c1a999dfa0 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 28 Dec 2025 19:57:08 +0800 Subject: [PATCH 05/45] Migrate legacy networking configuration to new network plugin versioning system. Remove legacy networking setting and update related GUI components to reflect the changes. Implement auto-migration for legacy libraries to ensure compatibility with the new versioning scheme. --- src/libslic3r/AppConfig.cpp | 22 ++++++++-- src/libslic3r/AppConfig.hpp | 1 + src/slic3r/GUI/GUI_App.cpp | 14 +++--- src/slic3r/GUI/Preferences.cpp | 34 ++++++--------- src/slic3r/GUI/Preferences.hpp | 1 - src/slic3r/Utils/NetworkAgent.cpp | 62 ++++++++++++++++++++++----- src/slic3r/Utils/bambu_networking.hpp | 3 +- 7 files changed, 93 insertions(+), 44 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index ad0a8e5932..4d91275010 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -135,6 +135,25 @@ void AppConfig::set_defaults() if (!get("use_legacy_opengl").empty()) erase("app", "use_legacy_opengl"); + // Migrate legacy_networking boolean to network_plugin_version string + std::string legacy_networking = get("legacy_networking"); + std::string network_version = get("network_plugin_version"); + + if (!legacy_networking.empty()) { + // Old legacy_networking setting exists - migrate it + bool was_legacy = (legacy_networking == "true" || legacy_networking == "1"); + + if (was_legacy && network_version.empty()) { + // User had legacy mode enabled - set to legacy version number + BOOST_LOG_TRIVIAL(info) << "Migrating legacy_networking=true to network_plugin_version=01.10.01.01"; + set("network_plugin_version", BAMBU_NETWORK_AGENT_VERSION_LEGACY); + } + // Note: If was_legacy=false, we leave the version empty and let the GUI layer set it to the latest version + + // Remove the old setting + erase("app", "legacy_networking"); + } + #ifdef __APPLE__ if (get("use_retina_opengl").empty()) set_bool("use_retina_opengl", true); @@ -278,9 +297,6 @@ void AppConfig::set_defaults() if (get("allow_abnormal_storage").empty()) { set_bool("allow_abnormal_storage", false); } - if (get("legacy_networking").empty()) { - set_bool("legacy_networking", false); - } if(get("check_stable_update_only").empty()) { set_bool("check_stable_update_only", false); diff --git a/src/libslic3r/AppConfig.hpp b/src/libslic3r/AppConfig.hpp index 82d87677ac..b521410ce9 100644 --- a/src/libslic3r/AppConfig.hpp +++ b/src/libslic3r/AppConfig.hpp @@ -28,6 +28,7 @@ using namespace nlohmann; #define SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS "network_plugin_skipped_versions" #define SETTING_NETWORK_PLUGIN_UPDATE_DISABLED "network_plugin_update_prompts_disabled" #define SETTING_NETWORK_PLUGIN_REMIND_LATER "network_plugin_remind_later" +#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.01" #define SUPPORT_DARK_MODE //#define _MSW_DARK_MODE diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 9edf8553dc..c0293d9e17 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2903,8 +2903,11 @@ bool GUI_App::on_init_inner() std::map extra_headers = get_extra_header(); Slic3r::Http::set_extra_headers(extra_headers); - // Orca: select network plugin version - NetworkAgent::use_legacy_network = app_config->get_bool("legacy_networking"); + // Orca: select network plugin version based on configured version string + std::string configured_version = app_config->get_network_plugin_version(); + NetworkAgent::use_legacy_network = (configured_version == BAMBU_NETWORK_AGENT_VERSION_LEGACY); + BOOST_LOG_TRIVIAL(info) << "Network plugin mode: " + << (NetworkAgent::use_legacy_network ? ("legacy (version: " + std::string(BAMBU_NETWORK_AGENT_VERSION_LEGACY) + ")") : ("modern (version: " + configured_version + ")")); // Force legacy network plugin if debugger attached // See https://github.com/bambulab/BambuStudio/issues/6726 /* if (!NetworkAgent::use_legacy_network) { @@ -3202,13 +3205,6 @@ bool GUI_App::on_init_network(bool try_backup) std::string config_version = app_config->get_network_plugin_version(); - if (should_load_networking_plugin && Slic3r::NetworkAgent::legacy_library_exists() && config_version.empty()) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": migration: legacy library found with no config version, removing and requesting download"; - Slic3r::NetworkAgent::remove_legacy_library(); - m_networking_need_update = true; - return false; - } - if(!should_load_networking_plugin) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "Don't load plugin as installed_networking is false"; } else { diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index abcf4d2af4..7dc2329f21 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -884,7 +884,6 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too if (pbool) { GUI::wxGetApp().CallAfter([] { GUI::wxGetApp().ShowDownNetPluginDlg(); }); } - if (m_legacy_networking_ckeckbox != nullptr) { m_legacy_networking_ckeckbox->Enable(pbool); } } #endif // __WXMSW__ @@ -946,25 +945,12 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxString too } } - if (param == "legacy_networking") { - bool legacy_mode = checkbox->GetValue(); - if (m_network_version_sizer != nullptr) { - m_network_version_sizer->Show(!legacy_mode); - m_parent->Layout(); - } - } - e.Skip(); }); //// for debug mode if (param == "developer_mode") { m_developer_mode_ckeckbox = checkbox; } if (param == "internal_developer_mode") { m_internal_developer_mode_ckeckbox = checkbox; } - if (param == "legacy_networking") { - m_legacy_networking_ckeckbox = checkbox; - bool pbool = app_config->get_bool("installed_networking"); - checkbox->Enable(pbool); - } return m_sizer_checkbox; } @@ -1424,9 +1410,6 @@ void PreferencesDialog::create_items() auto item_enable_plugin = create_item_checkbox(_L("Enable network plugin"), "", "installed_networking"); g_sizer->Add(item_enable_plugin); - - auto item_legacy_network = create_item_checkbox(_L("Use legacy network plugin"), _L("Disable to use latest network plugin that supports new BambuLab firmwares."), "legacy_networking", _L("(Requires restart)")); - g_sizer->Add(item_legacy_network); m_network_version_sizer = new wxBoxSizer(wxHORIZONTAL); m_network_version_sizer->AddSpacer(FromDIP(DESIGN_LEFT_MARGIN)); @@ -1442,7 +1425,10 @@ void PreferencesDialog::create_items() m_network_version_combo->SetFont(::Label::Body_14); m_network_version_combo->GetDropDown().SetFont(::Label::Body_14); - std::string current_version = app_config->get("network_plugin_version"); + std::string current_version = app_config->get_network_plugin_version(); + if (current_version.empty()) { + current_version = BBL::get_latest_network_version(); + } int current_selection = 0; m_available_versions = BBL::get_all_available_versions(); @@ -1485,16 +1471,26 @@ void PreferencesDialog::create_items() if (new_version != old_version) { BOOST_LOG_TRIVIAL(info) << "Network plugin version changed from " << old_version << " to " << new_version; + // Update the use_legacy_network flag immediately + bool is_legacy = (new_version == BAMBU_NETWORK_AGENT_VERSION_LEGACY); + bool was_legacy = (old_version == BAMBU_NETWORK_AGENT_VERSION_LEGACY); + if (is_legacy != was_legacy) { + Slic3r::NetworkAgent::use_legacy_network = is_legacy; + BOOST_LOG_TRIVIAL(info) << "Updated use_legacy_network flag to " << is_legacy; + } + if (!selected_ver.warning.empty()) { MessageDialog warn_dlg(this, wxString::FromUTF8(selected_ver.warning), _L("Warning"), wxOK | wxCANCEL | wxICON_WARNING); if (warn_dlg.ShowModal() != wxID_OK) { app_config->set(SETTING_NETWORK_PLUGIN_VERSION, old_version); app_config->save(); + Slic3r::NetworkAgent::use_legacy_network = was_legacy; e.Skip(); return; } } + // Check if the selected version already exists on disk if (Slic3r::NetworkAgent::versioned_library_exists(new_version)) { BOOST_LOG_TRIVIAL(info) << "Version " << new_version << " already exists on disk, triggering hot reload"; if (wxGetApp().hot_reload_network_plugin()) { @@ -1520,8 +1516,6 @@ void PreferencesDialog::create_items() e.Skip(); }); - bool legacy_mode = app_config->get_bool("legacy_networking"); - m_network_version_sizer->Show(!legacy_mode); g_sizer->Add(m_network_version_sizer); g_sizer->AddSpacer(FromDIP(10)); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index 53182fd475..5f98174bf2 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -68,7 +68,6 @@ public: ::CheckBox * m_internal_developer_mode_ckeckbox = {nullptr}; ::CheckBox * m_dark_mode_ckeckbox = {nullptr}; ::TextInput *m_backup_interval_textinput = {nullptr}; - ::CheckBox * m_legacy_networking_ckeckbox = {nullptr}; ::ComboBox * m_network_version_combo = {nullptr}; wxBoxSizer * m_network_version_sizer = {nullptr}; std::vector m_available_versions; diff --git a/src/slic3r/Utils/NetworkAgent.cpp b/src/slic3r/Utils/NetworkAgent.cpp index cbbc645682..8220105f10 100644 --- a/src/slic3r/Utils/NetworkAgent.cpp +++ b/src/slic3r/Utils/NetworkAgent.cpp @@ -241,7 +241,17 @@ bool NetworkAgent::versioned_library_exists(const std::string& version) { if (version.empty()) return false; std::string path = get_versioned_library_path(version); - return boost::filesystem::exists(path); + + // Check if versioned library exists + if (boost::filesystem::exists(path)) return true; + + // For legacy version, also check if unversioned legacy library exists + // (it will be auto-migrated to versioned format when loaded) + if (version == BAMBU_NETWORK_AGENT_VERSION_LEGACY) { + return legacy_library_exists(); + } + + return false; } bool NetworkAgent::legacy_library_exists() @@ -353,9 +363,50 @@ int NetworkAgent::initialize_network_module(bool using_backup, const std::string return -1; } + // Auto-migration: If loading legacy version and versioned library doesn't exist, + // but unversioned legacy library does exist, rename it to versioned format + if (version == BAMBU_NETWORK_AGENT_VERSION_LEGACY) { + boost::filesystem::path versioned_path; + boost::filesystem::path legacy_path; +#if defined(_MSC_VER) || defined(_WIN32) + versioned_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll"); + legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll"); +#elif defined(__WXMAC__) + versioned_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dylib"); + legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib"); +#else + versioned_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".so"); + legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so"); +#endif + if (!boost::filesystem::exists(versioned_path) && boost::filesystem::exists(legacy_path)) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": auto-migrating unversioned legacy library to versioned format"; + + try { + // Rename unversioned to versioned in the same folder (main or backup). + boost::filesystem::rename(legacy_path, versioned_path); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": successfully renamed " << legacy_path.string() << " to " + << versioned_path.string(); + } catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to rename legacy library: " << e.what(); + } + } + } + + // Load versioned library #if defined(_MSC_VER) || defined(_WIN32) library = plugin_folder.string() + "\\" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll"; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library; +#else + #if defined(__WXMAC__) + std::string lib_ext = ".dylib"; + #else + std::string lib_ext = ".so"; + #endif + library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + lib_ext; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library; +#endif + +#if defined(_MSC_VER) || defined(_WIN32) wchar_t lib_wstr[256]; memset(lib_wstr, 0, sizeof(lib_wstr)); ::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0])); @@ -378,15 +429,6 @@ int NetworkAgent::initialize_network_module(bool using_backup, const std::string netwoking_module = LoadLibrary(lib_wstr); } #else - #if defined(__WXMAC__) - std::string lib_ext = ".dylib"; - #else - std::string lib_ext = ".so"; - #endif - - library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + lib_ext; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library; - netwoking_module = dlopen(library.c_str(), RTLD_LAZY); if (!netwoking_module) { char* dll_error = dlerror(); diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index b9a5b6b225..e9f756e705 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -6,6 +6,7 @@ #include #include +#include "libslic3r/AppConfig.hpp" extern std::string g_log_folder; extern std::string g_log_start_time; @@ -98,7 +99,6 @@ namespace BBL { #define BAMBU_NETWORK_LIBRARY "bambu_networking" #define BAMBU_NETWORK_AGENT_NAME "bambu_network_agent" -#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.01" //iot preset type strings #define IOT_PRINTER_TYPE_STRING "printer" @@ -318,6 +318,7 @@ static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = { {"02.03.00.62", "02.03.00.62", nullptr, true, nullptr}, {"02.01.01.52", "02.01.01.52", nullptr, false, nullptr}, {"02.00.02.50", "02.00.02.50", nullptr, false, "This version may crash on startup due to Bambu Lab's signature verification."}, + {BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, "Legacy version - may not support newer firmware features. Only use if you have issues with modern versions."}, }; static const size_t AVAILABLE_NETWORK_VERSIONS_COUNT = sizeof(AVAILABLE_NETWORK_VERSIONS) / sizeof(AVAILABLE_NETWORK_VERSIONS[0]); From 3dc80593bdb88e8b93d6bcb39b4c3d877971be96 Mon Sep 17 00:00:00 2001 From: Kiss Lorand <50251547+kisslorand@users.noreply.github.com> Date: Mon, 29 Dec 2025 03:35:44 +0200 Subject: [PATCH 06/45] Brim: optionally generate brim from Elephant Foot Compensation outline (#11760) * Brim can follow EFC outline * Optimization * Update Spanish EFC brim description Adopt reviewer-proposed wording from RF47. Co-authored-by: RF47 * Tag Orca specific changes Tag Orca specific changes vs. Bambu using the comment //ORCA: . This helps when reviewing merge commits from upstream Bambu so we don't end up causing regressions when pulling in commits from upstream * Tooltip update --------- Co-authored-by: RF47 Co-authored-by: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> --- localization/i18n/OrcaSlicer.pot | 13 + localization/i18n/ca/OrcaSlicer_ca.po | 20 + localization/i18n/cs/OrcaSlicer_cs.po | 20 + localization/i18n/de/OrcaSlicer_de.po | 20 + localization/i18n/en/OrcaSlicer_en.po | 20 + localization/i18n/es/OrcaSlicer_es.po | 20 + localization/i18n/fr/OrcaSlicer_fr.po | 20 + localization/i18n/hu/OrcaSlicer_hu.po | 20 + localization/i18n/it/OrcaSlicer_it.po | 20 + localization/i18n/ja/OrcaSlicer_ja.po | 20 + localization/i18n/ko/OrcaSlicer_ko.po | 20 + localization/i18n/lt/OrcaSlicer_lt.po | 20 + localization/i18n/nl/OrcaSlicer_nl.po | 20 + localization/i18n/pl/OrcaSlicer_pl.po | 20 + localization/i18n/pt_BR/OrcaSlicer_pt_BR.po | 20 + localization/i18n/ru/OrcaSlicer_ru.po | 20 + localization/i18n/sv/OrcaSlicer_sv.po | 20 + localization/i18n/tr/OrcaSlicer_tr.po | 20 + localization/i18n/uk/OrcaSlicer_uk.po | 20 + localization/i18n/vi/OrcaSlicer_vi.po | 20 + localization/i18n/zh_CN/OrcaSlicer_zh_CN.po | 22 +- localization/i18n/zh_TW/OrcaSlicer_zh_TW.po | 22 +- src/libslic3r/Brim.cpp | 1169 +++---------------- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 10 + src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/PrintObject.cpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 1 + src/slic3r/GUI/GUI_Factories.cpp | 16 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 31 files changed, 624 insertions(+), 1016 deletions(-) diff --git a/localization/i18n/OrcaSlicer.pot b/localization/i18n/OrcaSlicer.pot index accaf4ea66..4901a6b7a5 100644 --- a/localization/i18n/OrcaSlicer.pot +++ b/localization/i18n/OrcaSlicer.pot @@ -11108,6 +11108,19 @@ msgid "" "easily." msgstr "" +msgid "Brim follows compensated outline" +msgstr "" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" + msgid "Brim ears" msgstr "" diff --git a/localization/i18n/ca/OrcaSlicer_ca.po b/localization/i18n/ca/OrcaSlicer_ca.po index cfb35a2480..d29d05b06b 100644 --- a/localization/i18n/ca/OrcaSlicer_ca.po +++ b/localization/i18n/ca/OrcaSlicer_ca.po @@ -12177,6 +12177,26 @@ msgstr "" "Un espai entre la línia de la Vora d'Adherència més interna i l'objecte pot " "fer que la Vora d'Adherència s'elimini més fàcilment" +msgid "Brim follows compensated outline" +msgstr "Vora d'Adherència segueix un esquema compensat" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Quan està activat, vora d'adherència s'alinea amb la geometria del perímetre de la primera capa " +"després d'aplicar la compensació del peu d'elefant.\n" +"Aquesta opció està pensada per als casos en què la compensació del peu d'elefant " +"altera significativament la petjada de la primera capa.\n" +"\n" +"Si la vostra configuració actual ja funciona bé, activar-la pot ser innecessari i " +"pot fer que el vora d'adherència es fusioni amb les capes superiors." + msgid "Brim ears" msgstr "Orelles de la Vora d'Adherència" diff --git a/localization/i18n/cs/OrcaSlicer_cs.po b/localization/i18n/cs/OrcaSlicer_cs.po index 9cc4976536..933c3b3504 100644 --- a/localization/i18n/cs/OrcaSlicer_cs.po +++ b/localization/i18n/cs/OrcaSlicer_cs.po @@ -11730,6 +11730,26 @@ msgid "" msgstr "" "Mezera mezi nejvnitřnějším límcem a předmětem může usnadnit odstranění límce" +msgid "Brim follows compensated outline" +msgstr "Límec sleduje kompenzovaný obrys" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Když je povoleno, límec je zarovnán s obvodovou geometrií první vrstvy " +"po použití kompenzace sloní nohy.\n" +"Tato možnost je určena pro případy, kdy je kompenzace sloní nohy " +"výrazně mění stopu první vrstvy.\n" +"\n" +"Pokud vaše aktuální nastavení již funguje dobře, jeho povolení může být zbytečné a " +"může způsobit spojení límec s horními vrstvami." + msgid "Brim ears" msgstr "Uši límce" diff --git a/localization/i18n/de/OrcaSlicer_de.po b/localization/i18n/de/OrcaSlicer_de.po index f0a0be35b4..15b84734a4 100644 --- a/localization/i18n/de/OrcaSlicer_de.po +++ b/localization/i18n/de/OrcaSlicer_de.po @@ -12766,6 +12766,26 @@ msgstr "" "Eine Lücke zwischen der innersten Randlinie und dem Objekt kann das Abnehmen " "des Randes erleichtern" +msgid "Brim follows compensated outline" +msgstr "Umrandung folgt einem kompensierten Umriss" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Wenn diese Option aktiviert ist, wird umrandung an der Umfangsgeometrie der ersten Ebene ausgerichtet " +"nach Anwendung der Elefantenfußkompensation.\n" +"Diese Option ist für Fälle gedacht, in denen eine Elefantenfuß-Entschädigung vorliegt " +"verändert den Footprint der ersten Schicht erheblich.\n" +"\n" +"Wenn Ihr aktuelles Setup bereits gut funktioniert, kann es unnötig sein, es zu aktivieren " +"kann dazu führen, dass der umrandung mit den oberen Schichten verschmilzt." + msgid "Brim ears" msgstr "Brim Ohren" diff --git a/localization/i18n/en/OrcaSlicer_en.po b/localization/i18n/en/OrcaSlicer_en.po index 647f62ee13..02b4dd6c18 100644 --- a/localization/i18n/en/OrcaSlicer_en.po +++ b/localization/i18n/en/OrcaSlicer_en.po @@ -11327,6 +11327,26 @@ msgstr "" "This creates a gap between the innermost brim line and the object and can " "make the brim easier to remove." +msgid "Brim follows compensated outline" +msgstr "Brim follows compensated outline" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." + msgid "Brim ears" msgstr "" diff --git a/localization/i18n/es/OrcaSlicer_es.po b/localization/i18n/es/OrcaSlicer_es.po index 85079d85fe..19c81d480d 100644 --- a/localization/i18n/es/OrcaSlicer_es.po +++ b/localization/i18n/es/OrcaSlicer_es.po @@ -12147,6 +12147,26 @@ msgstr "" "Un hueco entre la línea más interna del borde de adherencia y el objeto " "puede hacer que el borde de adherencia se retire más fácilmente" +msgid "Brim follows compensated outline" +msgstr "Borde de adherencia sigue el esquema compensado" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Cuando está habilitado, el borde de adherencia está alineado con la geometría del perímetro de la primera capa " +"después de aplicar la compensación de pata de elefante.\n" +"Esta opción está destinada a casos en los que la Compensación por pata de elefante " +"altera significativamente la huella de la primera capa.\n" +"\n" +"Si su configuración actual ya funciona bien, habilitarla puede ser innecesario y " +"puede hacer que el borde de adherencia se fusione con las capas superiores." + msgid "Brim ears" msgstr "Orejas de borde" diff --git a/localization/i18n/fr/OrcaSlicer_fr.po b/localization/i18n/fr/OrcaSlicer_fr.po index 1dd903bc10..5a80f34757 100644 --- a/localization/i18n/fr/OrcaSlicer_fr.po +++ b/localization/i18n/fr/OrcaSlicer_fr.po @@ -12298,6 +12298,26 @@ msgstr "" "Un espace entre la ligne de bord la plus interne et l'objet peut faciliter " "le retrait du bord" +msgid "Brim follows compensated outline" +msgstr "Bordure suit le contour compensé" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Lorsqu'il est activé, le bordure est aligné avec la géométrie du périmètre de la première couche " +"après l'application de la compensation du pied d'éléphant.\n" +"Cette option est destinée aux cas où la compensation du pied d'éléphant " +"modifie considérablement l’empreinte de la première couche.\n" +"\n" +"Si votre configuration actuelle fonctionne déjà bien, son activation peut être inutile et " +"peut provoquer la fusion du bordure avec les couches supérieures." + msgid "Brim ears" msgstr "Bordures à oreilles" diff --git a/localization/i18n/hu/OrcaSlicer_hu.po b/localization/i18n/hu/OrcaSlicer_hu.po index ddd70907ba..ba898f64ac 100644 --- a/localization/i18n/hu/OrcaSlicer_hu.po +++ b/localization/i18n/hu/OrcaSlicer_hu.po @@ -11603,6 +11603,26 @@ msgstr "" "A legbelső peremvonal és a tárgy közötti rés, ami megkönnyítheti a perem " "eltávolítását" +msgid "Brim follows compensated outline" +msgstr "A Perem a kompenzált körvonalat követi" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Ha engedélyezve van, a perem igazodik az első réteg kerületi geometriájához " +"az elefánttalp-kompenzáció alkalmazása után.\n" +"Ez az opció arra az esetre szolgál, amikor az elefánttalp-kompenzáció " +"jelentősen megváltoztatja az első réteg alapterületét.\n" +"\n" +"Ha a jelenlegi beállítás már jól működik, előfordulhat, hogy az engedélyezése felesleges és " +"a perem összeolvadását okozhatja a felső rétegekkel." + msgid "Brim ears" msgstr "Karimás fülek" diff --git a/localization/i18n/it/OrcaSlicer_it.po b/localization/i18n/it/OrcaSlicer_it.po index 43ee2d09c0..222467d02a 100644 --- a/localization/i18n/it/OrcaSlicer_it.po +++ b/localization/i18n/it/OrcaSlicer_it.po @@ -12234,6 +12234,26 @@ msgstr "" "Crea uno spazio tra la linea più interna della tesa e l'oggetto per rendere " "più facile la rimozione della tesa." +msgid "Brim follows compensated outline" +msgstr "Tesa segue il contorno compensato" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Quando abilitato, tesa è allineato con la geometria perimetrale del primo strato " +"dopo l'applicazione della compensazione del piede di elefante.\n" +"Questa opzione è prevista per i casi in cui è prevista la compensazione del piede di elefante " +"altera significativamente l'impronta del primo strato.\n" +"\n" +"Se la tua configurazione attuale funziona già bene, abilitarla potrebbe non essere necessaria e " +"può causare la fusione del tesa con gli strati superiori." + msgid "Brim ears" msgstr "Tesa ad orecchio" diff --git a/localization/i18n/ja/OrcaSlicer_ja.po b/localization/i18n/ja/OrcaSlicer_ja.po index 120ccae558..3258a45800 100644 --- a/localization/i18n/ja/OrcaSlicer_ja.po +++ b/localization/i18n/ja/OrcaSlicer_ja.po @@ -11394,6 +11394,26 @@ msgstr "" "ブリムを取り外しやすくする為、一番内側のブリムラインをモデルと少し距離を設け" "ます。" +msgid "Brim follows compensated outline" +msgstr "ブリム は補正されたアウトラインに従います" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"有効にすると、ブリム は最初の層の周囲ジオメトリと位置合わせされます。 " +"エレファント・フット・コンペンセーション適用後。\n" +"このオプションは、象の足の補正が必要な場合を対象としています。 " +"最初の層のフットプリントを大幅に変更します。\n" +"\n" +"現在の設定がすでにうまく機能している場合は、それを有効にする必要はないかもしれません。 " +"ブリム が上位層と融合する可能性があります。" + msgid "Brim ears" msgstr "" diff --git a/localization/i18n/ko/OrcaSlicer_ko.po b/localization/i18n/ko/OrcaSlicer_ko.po index fbc550e415..cf3d9dea71 100644 --- a/localization/i18n/ko/OrcaSlicer_ko.po +++ b/localization/i18n/ko/OrcaSlicer_ko.po @@ -11817,6 +11817,26 @@ msgstr "" "가장 안쪽 브림 라인과 객체 사이에 간격을 주어 쉽게 브림을 제거 할 수 있게 합" "니다" +msgid "Brim follows compensated outline" +msgstr "브림는 보상된 아웃라인을 따릅니다." + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"활성화되면 브림은 첫 번째 레이어 주변 형상과 정렬됩니다 " +"코끼리 발 보정이 적용된 후.\n" +"이 옵션은 코끼리 발 보상이 적용되는 경우를 위한 것입니다 " +"첫 번째 레이어 공간을 크게 변경합니다.\n" +"\n" +"현재 설정이 이미 잘 작동하는 경우 활성화할 필요가 없으며 " +"브림이 상위 레이어와 융합될 수 있습니다." + msgid "Brim ears" msgstr "브림 귀" diff --git a/localization/i18n/lt/OrcaSlicer_lt.po b/localization/i18n/lt/OrcaSlicer_lt.po index 052250e63f..ec9f6ce417 100644 --- a/localization/i18n/lt/OrcaSlicer_lt.po +++ b/localization/i18n/lt/OrcaSlicer_lt.po @@ -12183,6 +12183,26 @@ msgstr "" "Sukuriamas tarpas tarp vidinės krašto linijos ir objekto, todėl galima " "lengviau jį atskirti." +msgid "Brim follows compensated outline" +msgstr "Kraštas atitinka kompensuotą kontūrą" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Kai įjungta, kraštas yra sulygiuotas su pirmojo sluoksnio perimetro geometrija " +"pritaikius dramblio pėdos kompensaciją.\n" +"Ši parinktis skirta tais atvejais, kai kompensuojama dramblio pėda " +"žymiai pakeičia pirmojo sluoksnio pėdsaką.\n" +"\n" +"Jei dabartinė sąranka jau veikia gerai, jos įjungti gali nebūti ir " +"gali sukelti kraštas susiliejimą su viršutiniais sluoksniais." + msgid "Brim ears" msgstr "Krašto \"ausys\"" diff --git a/localization/i18n/nl/OrcaSlicer_nl.po b/localization/i18n/nl/OrcaSlicer_nl.po index 2f1c24f60d..923ea51aec 100644 --- a/localization/i18n/nl/OrcaSlicer_nl.po +++ b/localization/i18n/nl/OrcaSlicer_nl.po @@ -11751,6 +11751,26 @@ msgstr "" "Dit creëert ruimte tussen de binnenste brimlijn en het object en zorgt " "ervoor dat het object eenvoudiger van het printbed kan worden verwijderd." +msgid "Brim follows compensated outline" +msgstr "Rand volgt de gecompenseerde omtrek" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Indien ingeschakeld, wordt de rand uitgelijnd met de omtrekgeometrie van de eerste laag " +"nadat olifantenvoetcompensatie is toegepast.\n" +"Deze optie is bedoeld voor gevallen waarin sprake is van olifantenvoetcompensatie " +"verandert de voetafdruk van de eerste laag aanzienlijk.\n" +"\n" +"Als uw huidige configuratie al goed werkt, kan het inschakelen hiervan niet nodig zijn " +"kan ervoor zorgen dat de rand samensmelt met de bovenste lagen." + msgid "Brim ears" msgstr "Rand oren" diff --git a/localization/i18n/pl/OrcaSlicer_pl.po b/localization/i18n/pl/OrcaSlicer_pl.po index 81afc09e9b..5c2896d962 100644 --- a/localization/i18n/pl/OrcaSlicer_pl.po +++ b/localization/i18n/pl/OrcaSlicer_pl.po @@ -12130,6 +12130,26 @@ msgstr "" "Szczelina między najbardziej wewnętrzną linią brimu a obiektem może ułatwić " "usunięcie brimu" +msgid "Brim follows compensated outline" +msgstr "Brim podąża za skompensowanym konturem" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Po włączeniu brim jest wyrównany z geometrią obwodu pierwszej warstwy " +"po zastosowaniu Kompensacji Stopy Słonia.\n" +"Ta opcja jest przeznaczona dla przypadków, w których występuje kompensacja stopy słonia " +"znacząco zmienia ślad pierwszej warstwy.\n" +"\n" +"Jeśli Twoja bieżąca konfiguracja już działa dobrze, włączenie jej może być niepotrzebne i " +"może spowodować stopienie brim z górnymi warstwami." + msgid "Brim ears" msgstr "Uszy brim" diff --git a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po index 73fcdb50ea..cffab32de6 100644 --- a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po +++ b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po @@ -12555,6 +12555,26 @@ msgstr "" "Um espaço entre a linha mais interna da borda e o objeto pode facilitar a " "remoção da borda." +msgid "Brim follows compensated outline" +msgstr "Borda segue contorno compensado" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Quando ativado, o borda fica alinhado com a geometria do perímetro da primeira camada " +"após a aplicação da Compensação da Pé de Elefante.\n" +"Esta opção destina-se aos casos em que a Compensação da Pé de Elefante " +"altera significativamente a pegada da primeira camada.\n" +"\n" +"Se a sua configuração atual já funciona bem, ativá-la pode ser desnecessário e " +"pode fazer com que o borda se funda com as camadas superiores." + msgid "Brim ears" msgstr "Orelhas da borda" diff --git a/localization/i18n/ru/OrcaSlicer_ru.po b/localization/i18n/ru/OrcaSlicer_ru.po index d9ff700c16..4364ce8306 100644 --- a/localization/i18n/ru/OrcaSlicer_ru.po +++ b/localization/i18n/ru/OrcaSlicer_ru.po @@ -12291,6 +12291,26 @@ msgid "" "easily." msgstr "Смещение каймы от печатаемой модели, может облегчить её удаление." +msgid "Brim follows compensated outline" +msgstr "Кайма соответствует компенсированному контуру" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Если этот параметр включен, кайма выравнивается по геометрии периметра первого слоя " +"после применения компенсации «слоновьей стопы».\n" +"Эта опция предназначена для случаев, когда «Компенсация слоновой стопы» " +"существенно изменяет след первого слоя.\n" +"\n" +"Если ваша текущая настройка уже работает хорошо, ее включение может быть ненужным и " +"может привести к слиянию кайма с верхними слоями." + msgid "Brim ears" msgstr "Ушки каймы" diff --git a/localization/i18n/sv/OrcaSlicer_sv.po b/localization/i18n/sv/OrcaSlicer_sv.po index 04c2d4d565..ab1944d79e 100644 --- a/localization/i18n/sv/OrcaSlicer_sv.po +++ b/localization/i18n/sv/OrcaSlicer_sv.po @@ -11574,6 +11574,26 @@ msgstr "" "Mellanrum mellan innersta brim linjen och objektet kan underlätta vid " "borttagande av brim" +msgid "Brim follows compensated outline" +msgstr "Brim följer kompenserad disposition" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"När den är aktiverad, är brim justerad med det första lagrets omkretsgeometri " +"efter att elefantfotskompensation tillämpas.\n" +"Detta alternativ är avsett för fall där elefantfotskompensation " +"förändrar det första skiktets fotavtryck avsevärt.\n" +"\n" +"Om din nuvarande inställning redan fungerar bra kan det vara onödigt att aktivera det och " +"kan få brim att smälta samman med de övre lagren." + msgid "Brim ears" msgstr "Brätte öron" diff --git a/localization/i18n/tr/OrcaSlicer_tr.po b/localization/i18n/tr/OrcaSlicer_tr.po index a817dd919e..b10eacfc6e 100644 --- a/localization/i18n/tr/OrcaSlicer_tr.po +++ b/localization/i18n/tr/OrcaSlicer_tr.po @@ -12097,6 +12097,26 @@ msgstr "" "En içteki kenar çizgisi ile nesne arasındaki boşluk, kenarlığın daha kolay " "çıkarılmasını sağlayabilir." +msgid "Brim follows compensated outline" +msgstr "Kenar telafi edilen taslağı takip ediyor" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Etkinleştirildiğinde, kenar birinci katmanın çevre geometrisiyle hizalanır " +"Fil Ayağı Telafisi uygulandıktan sonra.\n" +"Bu seçenek Fil Ayağı Telafisinin geçerli olmadığı durumlar için tasarlanmıştır " +"ilk katmanın ayak izini önemli ölçüde değiştirir.\n" +"\n" +"Mevcut kurulumunuz zaten iyi çalışıyorsa, bunu etkinleştirmek gereksiz olabilir ve " +"kenar'in üst katmanlarla kaynaşmasına neden olabilir." + msgid "Brim ears" msgstr "Kenar kulakları" diff --git a/localization/i18n/uk/OrcaSlicer_uk.po b/localization/i18n/uk/OrcaSlicer_uk.po index 05482e66d1..296efbe5bd 100644 --- a/localization/i18n/uk/OrcaSlicer_uk.po +++ b/localization/i18n/uk/OrcaSlicer_uk.po @@ -12138,6 +12138,26 @@ msgstr "" "Зазор між першою внутрішньою лінією кайми та об'єктом може сприяти легшому " "відокремленню кайми" +msgid "Brim follows compensated outline" +msgstr "Кайма має компенсований контур" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Якщо ввімкнено, кайма вирівнюється з геометрією периметра першого рівня " +"після застосування Elephant Foot Compensation.\n" +"Ця опція призначена для випадків компенсації слонячої стопи " +"значно змінює поверхню першого шару.\n" +"\n" +"Якщо ваші поточні налаштування вже працюють добре, увімкнення їх може бути непотрібним " +"може призвести до злиття кайма з верхніми шарами." + msgid "Brim ears" msgstr "Вушка кайми" diff --git a/localization/i18n/vi/OrcaSlicer_vi.po b/localization/i18n/vi/OrcaSlicer_vi.po index f14576ceed..5017bc246f 100644 --- a/localization/i18n/vi/OrcaSlicer_vi.po +++ b/localization/i18n/vi/OrcaSlicer_vi.po @@ -11926,6 +11926,26 @@ msgstr "" "Khoảng cách giữa đường brim trong cùng và đối tượng có thể làm cho brim dễ " "dàng tháo hơn." +msgid "Brim follows compensated outline" +msgstr "Brim tuân theo phác thảo được bù đắp" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"Khi được bật, brim sẽ được căn chỉnh theo hình học chu vi lớp đầu tiên " +"sau khi áp dụng Bồi thường bàn chân voi.\n" +"Tùy chọn này dành cho các trường hợp Bồi thường chân voi " +"làm thay đổi đáng kể dấu chân lớp đầu tiên.\n" +"\n" +"Nếu thiết lập hiện tại của bạn đã hoạt động tốt, việc bật nó có thể không cần thiết và " +"có thể khiến brim kết hợp với các lớp trên." + msgid "Brim ears" msgstr "Tai brim" diff --git a/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po b/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po index 952bd49555..8cad4e58a5 100644 --- a/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po +++ b/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po @@ -2490,7 +2490,7 @@ msgid "Plate" msgstr "盘" msgid "Brim" -msgstr "Brim" +msgstr "边缘" msgid "Object/Part Setting" msgstr "对象/零件设置" @@ -11493,6 +11493,26 @@ msgid "" "easily." msgstr "在brim和模型之间设置间隙,能够让brim更容易剥离" +msgid "Brim follows compensated outline" +msgstr "边缘 遵循补偿轮廓" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"启用后,边缘 与第一层周边几何体对齐 " +"应用象脚补偿后。\n" +"此选项适用于象脚补偿的情况 " +"显着改变第一层足迹。\n" +"\n" +"如果您当前的设置已经运行良好,则可能没有必要启用它,并且 " +"可以导致 边缘 与上层融合。" + msgid "Brim ears" msgstr "圆盘" diff --git a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po index 01c3669856..51d89cca21 100644 --- a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po +++ b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po @@ -2493,7 +2493,7 @@ msgid "Plate" msgstr "列印板" msgid "Brim" -msgstr "Brim" +msgstr "邊緣" msgid "Object/Part Setting" msgstr "物件/零件 設定" @@ -11560,6 +11560,26 @@ msgid "" "easily." msgstr "在 Brim 和模型之間設定間隙,能夠讓 Brim 更容易拆除" +msgid "Brim follows compensated outline" +msgstr "邊緣 遵循補償輪廓" + +msgid "" +"When enabled, the brim is aligned with the first-layer perimeter geometry " +"after Elephant Foot Compensation is applied.\n" +"This option is intended for cases where Elephant Foot Compensation " +"significantly alters the first-layer footprint.\n" +"\n" +"If your current setup already works well, enabling it may be unnecessary and " +"can cause the brim to fuse with upper layers." +msgstr "" +"啟用後,邊緣 與第一層周邊幾何體對齊 " +"應用像腳補償後。\n" +"此選項適用於像腳補償的情況 " +"顯著改變第一層足跡。\n" +"\n" +"如果您當前的設置已經運行良好,則可能沒有必要啟用它,並且 " +"可以導致 邊緣 與上層融合。" + msgid "Brim ears" msgstr "耳狀 Brim" diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index d21ed2e544..35d971a465 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -1,5 +1,3 @@ -#include "clipper/clipper_z.hpp" - #include "ClipperUtils.hpp" #include "EdgeGrid.hpp" #include "Layer.hpp" @@ -10,8 +8,8 @@ #include "MaterialType.hpp" #include "Model.hpp" #include -#include -#include +#include +#include #include #include @@ -54,16 +52,63 @@ static void append_and_translate(Polygons &dst, const Polygons &src, const Print dst[dst_idx].translate(instance_shift); } -static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects) +//ORCA: Brim can follow the post-EFC outline when enabled. +static bool use_brim_efc_outline(const PrintObject &object) { - assert(!objects.empty()); - return float(std::accumulate(objects.begin(), objects.end(), 0., - [](double partial_result, const PrintObject *object) { - return std::max(partial_result, object->config().brim_type == btNoBrim ? 0. : object->config().brim_width.value); - })); + return object.config().brim_use_efc_outline.value + && object.config().elefant_foot_compensation.value > 0. + && object.config().elefant_foot_compensation_layers.value > 0 + && object.config().raft_layers.value == 0; } -// Returns ExPolygons of the bottom layer of the print object after elephant foot compensation. +//ORCA: Helper for snapping painted ears to the EFC outline. +static bool closest_point_on_expolygons(const ExPolygons &polygons, const Point &from, Point &closest_out) +{ + double min_dist2 = std::numeric_limits::max(); + bool found = false; + + for (const ExPolygon &poly : polygons) { + for (int i = 0; i < poly.num_contours(); ++i) { + const Point *candidate = poly.contour_or_hole(i).closest_point(from); + if (candidate == nullptr) + continue; + const int64_t dx = int64_t(candidate->x()) - int64_t(from.x()); + const int64_t dy = int64_t(candidate->y()) - int64_t(from.y()); + const double dist2 = double(dx * dx + dy * dy); + if (dist2 < min_dist2) { + min_dist2 = dist2; + closest_out = *candidate; + found = true; + } + } + } + return found; +} + +//ORCA: Helper for matching painted ears to their original island before EFC snapping. +static int find_containing_expolygon_index(const ExPolygons &polygons, const Point &from) +{ + for (size_t idx = 0; idx < polygons.size(); ++idx) { + if (polygons[idx].contains(from)) + return int(idx); + } + return -1; +} + +//ORCA: Keep painted ear snapping on the matching island when using EFC outline. +static bool closest_point_on_matching_island(const ExPolygons &raw_outline, const ExPolygons &efc_outline, const Point &from, Point &closest_out) +{ + const int island_idx = find_containing_expolygon_index(raw_outline, from); + if (island_idx >= 0) { + ExPolygons island_outline = intersection_ex(efc_outline, raw_outline[island_idx]); + if (!island_outline.empty()) + return closest_point_on_expolygons(island_outline, from, closest_out); + } + return closest_point_on_expolygons(efc_outline, from, closest_out); +} +//ORCA: Use post-processed first-layer slices (including EFC) for brim outline. +// Returns ExPolygons of the bottom layer after all first-layer modifiers +// (including elephant foot compensation, if enabled) have been applied. static ExPolygons get_print_object_bottom_layer_expolygons(const PrintObject &print_object) { ExPolygons ex_polygons; @@ -71,506 +116,6 @@ static ExPolygons get_print_object_bottom_layer_expolygons(const PrintObject &pr Slic3r::append(ex_polygons, closing_ex(region->slices.surfaces, float(SCALED_EPSILON))); return ex_polygons; } - -// Returns ExPolygons of bottom layer for every print object in Print after elephant foot compensation. -static std::vector get_print_bottom_layers_expolygons(const Print &print) -{ - std::vector bottom_layers_expolygons; - bottom_layers_expolygons.reserve(print.objects().size()); - for (const PrintObject *object : print.objects()) - bottom_layers_expolygons.emplace_back(get_print_object_bottom_layer_expolygons(*object)); - - return bottom_layers_expolygons; -} - -static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print, const std::vector &bottom_layers_expolygons) -{ - assert(print.objects().size() == bottom_layers_expolygons.size()); - Polygons islands; - ConstPrintObjectPtrs island_to_object; - for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { - const PrintObject *object = print.objects()[print_object_idx]; - Polygons islands_object; - islands_object.reserve(bottom_layers_expolygons[print_object_idx].size()); - for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) - islands_object.emplace_back(ex_poly.contour); - - islands.reserve(islands.size() + object->instances().size() * islands_object.size()); - for (const PrintInstance& instance : object->instances()) { - Point instance_shift = instance.shift_without_plate_offset(); - for (Polygon& poly : islands_object) { - islands.emplace_back(poly); - islands.back().translate(instance_shift); - island_to_object.emplace_back(object); - } - } - } - assert(islands.size() == island_to_object.size()); - - ClipperLib_Z::Paths islands_clip; - islands_clip.reserve(islands.size()); - for (const Polygon &poly : islands) { - islands_clip.emplace_back(); - ClipperLib_Z::Path &island_clip = islands_clip.back(); - island_clip.reserve(poly.points.size()); - int island_idx = int(&poly - &islands.front()); - // The Z coordinate carries index of the island used to get the pointer to the object. - for (const Point &pt : poly.points) - island_clip.emplace_back(pt.x(), pt.y(), island_idx + 1); - } - - // Init Clipper - ClipperLib_Z::Clipper clipper; - // Assign the maximum Z from four points. This values is valid index of the island - clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot, - const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) { - pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z())); - }); - // Add islands - clipper.AddPaths(islands_clip, ClipperLib_Z::ptSubject, true); - // Execute union operation to construct polytree - ClipperLib_Z::PolyTree islands_polytree; - //FIXME likely pftNonZero or ptfPositive would be better. Why are we using ptfEvenOdd for Unions? - clipper.Execute(ClipperLib_Z::ctUnion, islands_polytree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd); - - std::unordered_set processed_objects_idx; - ConstPrintObjectPtrs top_level_objects_with_brim; - for (int i = 0; i < islands_polytree.ChildCount(); ++i) { - for (const ClipperLib_Z::IntPoint &point : islands_polytree.Childs[i]->Contour) { - if (point.z() != 0 && processed_objects_idx.find(island_to_object[point.z() - 1]->id().id) == processed_objects_idx.end()) { - top_level_objects_with_brim.emplace_back(island_to_object[point.z() - 1]); - processed_objects_idx.insert(island_to_object[point.z() - 1]->id().id); - } - } - } - return top_level_objects_with_brim; -} - -static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_level_objects_with_brim, const double scaled_resolution) -{ - Polygons islands; - for (const PrintObject *object : top_level_objects_with_brim) { - if (!object->has_brim()) - continue; - - //FIXME how about the brim type? - auto brim_object_gap = float(scale_(object->config().brim_object_gap.value)); - Polygons islands_object; - for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { - Polygons contour_offset = offset(ex_poly.contour, brim_object_gap, ClipperLib::jtSquare); - for (Polygon &poly : contour_offset) - poly.douglas_peucker(scaled_resolution); - - polygons_append(islands_object, std::move(contour_offset)); - } - - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - Polygons contour_offset = offset(support_contour, brim_object_gap, ClipperLib::jtSquare); - for (Polygon& poly : contour_offset) - poly.douglas_peucker(scaled_resolution); - - polygons_append(islands_object, std::move(contour_offset)); - } - } - - for (const PrintInstance &instance : object->instances()) - append_and_translate(islands, islands_object, instance); - } - return islands; -} - -static ExPolygons top_level_outer_brim_area(const Print &print, - const ConstPrintObjectPtrs &top_level_objects_with_brim, - const std::vector &bottom_layers_expolygons, - const float no_brim_offset, - // BBS - double& brim_width_max, - std::map& brim_width_map) -{ - const auto scaled_resolution = scaled(print.config().resolution.value); - - assert(print.objects().size() == bottom_layers_expolygons.size()); - std::unordered_set top_level_objects_idx; - top_level_objects_idx.reserve(top_level_objects_with_brim.size()); - for (const PrintObject *object : top_level_objects_with_brim) - top_level_objects_idx.insert(object->id().id); - - ExPolygons brim_area; - ExPolygons no_brim_area; - brim_width_max = 0; - for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { - const PrintObject *object = print.objects()[print_object_idx]; - const BrimType brim_type = object->config().brim_type.value; - const float brim_object_gap = scale_(object->config().brim_object_gap.value); - // recording the autoAssigned brimWidth and corresponding objs - double brimWidthAuto = object->config().brim_width.value; - double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR; - brimWidthAuto = floor(brimWidthAuto / flowWidth / 2) * flowWidth * 2; - brim_width_map.insert(std::make_pair(object->id(), brimWidthAuto)); - brim_width_max = std::max(brim_width_max, brimWidthAuto); - const float brim_width = scale_(brimWidthAuto); - const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); - - ExPolygons brim_area_object; - ExPolygons no_brim_area_object; - for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { - if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_object_gap, ClipperLib::jtRound, scaled_resolution), offset(ex_poly.contour, brim_object_gap, ClipperLib::jtSquare))); - - // After 7ff76d07684858fd937ef2f5d863f105a10f798e offset and shrink don't work with CW polygons (holes), so let's make it CCW. - Polygons ex_poly_holes_reversed = ex_poly.holes; - polygons_reverse(ex_poly_holes_reversed); - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, shrink_ex(ex_poly_holes_reversed, no_brim_offset, ClipperLib::jtSquare)); - - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly_holes_reversed)); - - if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_object_gap, ClipperLib::jtSquare)); - - no_brim_area_object.emplace_back(ex_poly.contour); - } - - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(support_contour, brim_width + brim_object_gap, ClipperLib::jtRound, scaled_resolution), offset(support_contour, brim_object_gap))); - - if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(support_contour), brim_object_gap)); - - no_brim_area_object.emplace_back(support_contour); - } - } - - for (const PrintInstance &instance : object->instances()) { - append_and_translate(brim_area, brim_area_object, instance); - append_and_translate(no_brim_area, no_brim_area_object, instance); - } - } - - return diff_ex(brim_area, no_brim_area); -} - -// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders -static ExPolygons top_level_outer_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim, - const float no_brim_offset, double& brim_width_max, std::map& brim_width_map, - std::map& brimAreaMap, - std::map& supportBrimAreaMap, std::vector>& objPrintVec) -{ - std::unordered_set top_level_objects_idx; - top_level_objects_idx.reserve(top_level_objects_with_brim.size()); - for (const PrintObject* object : top_level_objects_with_brim) - top_level_objects_idx.insert(object->id().id); - - unsigned int support_material_extruder = 1; - if (print.has_support_material()) { - assert(top_level_objects_with_brim.front()->config().support_filament >= 0); - if (top_level_objects_with_brim.front()->config().support_filament > 0) - support_material_extruder = top_level_objects_with_brim.front()->config().support_filament; - } - - ExPolygons brim_area; - ExPolygons no_brim_area; - brim_width_max = 0; - struct brimWritten { - bool obj; - bool sup; - }; - std::map brimToWrite; - for (const auto& objectWithExtruder : objPrintVec) - brimToWrite.insert({ objectWithExtruder.first, {true,true} }); - - for (unsigned int extruderNo : print.extruders()) { - ++extruderNo; - for (const auto &objectWithExtruder : objPrintVec) { - const PrintObject* object = print.get_object(objectWithExtruder.first); - const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_object_gap.value); - // recording the autoAssigned brimWidth and corresponding objs - double brimWidthAuto = object->config().brim_width.value; - double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR; - brimWidthAuto = floor(brimWidthAuto / flowWidth / 2) * flowWidth * 2; - brim_width_map.insert(std::make_pair(object->id(), brimWidthAuto)); - brim_width_max = std::max(brim_width_max, brimWidthAuto); - const float brim_width = scale_(brimWidthAuto); - const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); - - ExPolygons nullBrim; - brimAreaMap.insert(std::make_pair(object->id(), nullBrim)); - ExPolygons brim_area_object; - ExPolygons brim_area_support; - ExPolygons no_brim_area_object; - ExPolygons no_brim_area_support; - if (objectWithExtruder.second == extruderNo && brimToWrite.at(object->id()).obj) { - for (const ExPolygon& ex_poly : object->layers().front()->lslices) { - if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) && is_top_outer_brim) { - append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset, jtRound, SCALED_RESOLUTION), - offset_ex(ex_poly.contour, brim_offset))); - } - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); - - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); - - if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_offset)); - - no_brim_area_object.emplace_back(ex_poly.contour); - } - brimToWrite.at(object->id()).obj = false; - for (const PrintInstance& instance : object->instances()) { - if (!brim_area_object.empty()) - append_and_translate(brim_area, brim_area_object, instance, print, brimAreaMap); - append_and_translate(no_brim_area, no_brim_area_object, instance); - } - if (brimAreaMap.find(object->id()) != brimAreaMap.end()) - expolygons_append(brim_area, brimAreaMap[object->id()]); - } - if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) { - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - //BBS: no brim offset for supports - if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) && is_top_outer_brim) - append(brim_area_support, diff_ex(offset(support_contour, brim_width, jtRound, SCALED_RESOLUTION), offset(support_contour, 0))); - - if (brim_type != BrimType::btNoBrim) - append(no_brim_area_support, offset_ex(support_contour, 0)); - - no_brim_area_support.emplace_back(support_contour); - } - } - - brimToWrite.at(object->id()).sup = false; - for (const PrintInstance& instance : object->instances()) { - if (!brim_area_support.empty()) - append_and_translate(brim_area, brim_area_support, instance, print, supportBrimAreaMap); - append_and_translate(no_brim_area, no_brim_area_support, instance); - } - if (supportBrimAreaMap.find(object->id()) != supportBrimAreaMap.end()) - expolygons_append(brim_area, supportBrimAreaMap[object->id()]); - } - } - } - for (const PrintObject* object : print.objects()) { - if (brimAreaMap.find(object->id()) != brimAreaMap.end()) - brimAreaMap[object->id()] = diff_ex(brimAreaMap[object->id()], no_brim_area); - if (supportBrimAreaMap.find(object->id()) != supportBrimAreaMap.end()) - supportBrimAreaMap[object->id()] = diff_ex(supportBrimAreaMap[object->id()], no_brim_area); - } - return diff_ex(std::move(brim_area), no_brim_area); -} -static ExPolygons inner_brim_area(const Print &print, - const ConstPrintObjectPtrs &top_level_objects_with_brim, - const std::vector &bottom_layers_expolygons, - const float no_brim_offset) -{ - assert(print.objects().size() == bottom_layers_expolygons.size()); - std::unordered_set top_level_objects_idx; - top_level_objects_idx.reserve(top_level_objects_with_brim.size()); - for (const PrintObject *object : top_level_objects_with_brim) - top_level_objects_idx.insert(object->id().id); - - ExPolygons brim_area; - ExPolygons no_brim_area; - Polygons holes; - for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { - const PrintObject *object = print.objects()[print_object_idx]; - const BrimType brim_type = object->config().brim_type.value; - const float brim_object_gap = scale_(object->config().brim_object_gap.value); - double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR; - const float brim_width = scale_(floor(object->config().brim_width.value / flowWidth / 2) * flowWidth * 2); - const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); - - ExPolygons brim_area_object; - ExPolygons no_brim_area_object; - Polygons holes_object; - for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) { - if (top_outer_brim) - no_brim_area_object.emplace_back(ex_poly); - else - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_object_gap, ClipperLib::jtSquare), offset(ex_poly.contour, brim_object_gap, ClipperLib::jtSquare))); - } - - // After 7ff76d07684858fd937ef2f5d863f105a10f798e offset and shrink don't work with CW polygons (holes), so let's make it CCW. - Polygons ex_poly_holes_reversed = ex_poly.holes; - polygons_reverse(ex_poly_holes_reversed); - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) - append(brim_area_object, diff_ex(shrink_ex(ex_poly_holes_reversed, brim_object_gap, ClipperLib::jtSquare), shrink_ex(ex_poly_holes_reversed, brim_width + brim_object_gap, ClipperLib::jtSquare))); - - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly_holes_reversed)); - - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(ExPolygon(ex_poly.contour), shrink_ex(ex_poly_holes_reversed, no_brim_offset, ClipperLib::jtSquare))); - - append(holes_object, ex_poly_holes_reversed); - } - append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_object_gap, ClipperLib::jtSquare)); - - for (const PrintInstance &instance : object->instances()) { - append_and_translate(brim_area, brim_area_object, instance); - append_and_translate(no_brim_area, no_brim_area_object, instance); - append_and_translate(holes, holes_object, instance); - } - } - - return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area); -} - -// BBS: the brims of different objs will not overlapped with each other, and are stored by objs and by extruders -static ExPolygons inner_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim, - const float no_brim_offset, std::map& brimAreaMap, - std::map& supportBrimAreaMap, - std::vector>& objPrintVec) -{ - std::unordered_set top_level_objects_idx; - top_level_objects_idx.reserve(top_level_objects_with_brim.size()); - for (const PrintObject* object : top_level_objects_with_brim) - top_level_objects_idx.insert(object->id().id); - - unsigned int support_material_extruder = 1; - if (print.has_support_material()) { - assert(top_level_objects_with_brim.front()->config().support_filament >= 0); - if (top_level_objects_with_brim.front()->config().support_filament > 0) - support_material_extruder = top_level_objects_with_brim.front()->config().support_filament; - } - - ExPolygons brim_area; - ExPolygons no_brim_area; - Polygons holes; - Polygon bedShape(get_bed_shape(print.config())); - holes.emplace_back(get_bed_shape(print.config())); - std::map innerBrimAreaMap; - std::map innerSupportBrimAreaMap; - - struct brimWritten { - bool obj; - bool sup; - }; - std::map brimToWrite; - for (const auto& objectWithExtruder : objPrintVec) - brimToWrite.insert({ objectWithExtruder.first, {true,true} }); - - - for (unsigned int extruderNo : print.extruders()) { - ++extruderNo; - for (const auto& objectWithExtruder : objPrintVec) { - const PrintObject* object = print.get_object(objectWithExtruder.first); - const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_object_gap.value); - double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR; - const float brim_width = scale_(floor(object->config().brim_width.value / flowWidth / 2) * flowWidth * 2); - const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); - - ExPolygons brim_area_object; - ExPolygons no_brim_area_object; - ExPolygons brim_area_support; - ExPolygons no_brim_area_support; - Polygons holes_object; - Polygons holes_support; - if (objectWithExtruder.second == extruderNo && brimToWrite.at(object->id()).obj) { - for (const ExPolygon& ex_poly : object->layers().front()->lslices) { - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) { - if (top_outer_brim) - no_brim_area_object.emplace_back(ex_poly); - else - append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset, jtRound, SCALED_RESOLUTION), offset_ex(ex_poly.contour, brim_offset))); - } - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) - append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset))); - if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); - append(holes_object, ex_poly.holes); - } - append(no_brim_area_object, offset_ex(object->layers().front()->lslices, brim_offset)); - brimToWrite.at(object->id()).obj = false; - for (const PrintInstance& instance : object->instances()) { - if (!brim_area_object.empty()) - append_and_translate(brim_area, brim_area_object, instance, print, innerBrimAreaMap); - append_and_translate(no_brim_area, no_brim_area_object, instance); - append_and_translate(holes, holes_object, instance); - } - if (innerBrimAreaMap.find(object->id()) != innerBrimAreaMap.end()) - expolygons_append(brim_area, innerBrimAreaMap[object->id()]); - } - if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) { - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner || brim_type == BrimType::btAutoBrim) { - if (!top_outer_brim) - append(brim_area_support, diff_ex(offset_ex(support_contour, brim_width + brim_offset, jtRound, SCALED_RESOLUTION), offset_ex(support_contour, brim_offset))); - } - if (brim_type != BrimType::btNoBrim) - append(no_brim_area_support, offset_ex(support_contour, 0)); - no_brim_area_support.emplace_back(support_contour); - } - } - } - brimToWrite.at(object->id()).sup = false; - for (const PrintInstance& instance : object->instances()) { - if (!brim_area_support.empty()) - append_and_translate(brim_area, brim_area_support, instance, print, innerSupportBrimAreaMap); - append_and_translate(no_brim_area, no_brim_area_support, instance); - append_and_translate(holes, holes_support, instance); - } - if (innerSupportBrimAreaMap.find(object->id()) != innerSupportBrimAreaMap.end()) - expolygons_append(brim_area, innerSupportBrimAreaMap[object->id()]); - } - } - for (const PrintObject* object : print.objects()) { - if (innerBrimAreaMap.find(object->id()) != innerBrimAreaMap.end()) { - innerBrimAreaMap[object->id()] = intersection_ex(to_polygons(innerBrimAreaMap[object->id()]), holes); - append(brimAreaMap[object->id()], innerBrimAreaMap[object->id()]); - } - if (innerSupportBrimAreaMap.find(object->id()) != innerSupportBrimAreaMap.end()) { - innerSupportBrimAreaMap[object->id()] = intersection_ex(to_polygons(innerSupportBrimAreaMap[object->id()]), holes); - append(supportBrimAreaMap[object->id()], innerSupportBrimAreaMap[object->id()]); - } - } - for (const PrintObject* object : print.objects()) { - if (brimAreaMap.find(object->id()) != brimAreaMap.end()) - brimAreaMap[object->id()] = diff_ex(brimAreaMap[object->id()], no_brim_area); - if (supportBrimAreaMap.find(object->id()) != supportBrimAreaMap.end()) - supportBrimAreaMap[object->id()] = diff_ex(supportBrimAreaMap[object->id()], no_brim_area); - } - brim_area = intersection_ex(to_polygons(brim_area), holes); - append(no_brim_area, brim_area); - return no_brim_area; -} - -//BBS maximum temperature difference from print object class -double getTemperatureFromExtruder(const PrintObject* printObject) { - auto print = printObject->print(); - std::vector extrudersFirstLayer; - auto firstLayerRegions = printObject->layers().front()->regions(); - if (!firstLayerRegions.empty()) { - for (const LayerRegion* regionPtr : firstLayerRegions) { - if (regionPtr->has_extrusions()) - extrudersFirstLayer.push_back(regionPtr->region().extruder(frExternalPerimeter)); - } - } - - const PrintConfig& config = print->config(); - int curr_bed_type = config.option("curr_bed_type")->getInt(); - const ConfigOptionInts* bed_temp_1st_layer_opt = config.option(get_bed_temp_1st_layer_key((BedType)curr_bed_type)); - - double maxDeltaTemp = 0; - for (auto extruderID : extrudersFirstLayer) { - int bedTemp = bed_temp_1st_layer_opt->get_at(extruderID - 1); - if (bedTemp > maxDeltaTemp) - maxDeltaTemp = bedTemp; - } - - return maxDeltaTemp; -} //BBS adhesion coefficients from print object class double getadhesionCoeff(const PrintObject* printObject) { @@ -711,50 +256,6 @@ bool compSecondMoment(const ExPolygons& expolys, double& smExpolysX, double& smE return true; } - - - -//BBS: config brimwidth by volumes -double configBrimWidthByVolumes(double deltaT, double adhesion, double maxSpeed, const ModelVolume* modelVolumePtr, const ExPolygons& expolys) -{ - // height of a volume - double height = 0; - if (modelVolumePtr->is_model_part()) { - auto rawBoundingbox = modelVolumePtr->mesh().transformed_bounding_box(modelVolumePtr->get_matrix()); - auto bbox = modelVolumePtr->get_object()->instances.front()->transform_bounding_box(rawBoundingbox); - auto bbox_size = bbox.size(); - height = bbox_size(2); - } - - // sencond moment of the expolygons of the first layer of the volume - double Ixx = -1.e30, Iyy = -1.e30; - if (!expolys.empty()) { - if (!compSecondMoment(expolys, Ixx, Iyy)) - Ixx = Iyy = -1.e30; - } - Ixx = Ixx * SCALING_FACTOR * SCALING_FACTOR * SCALING_FACTOR * SCALING_FACTOR; - Iyy = Iyy * SCALING_FACTOR * SCALING_FACTOR * SCALING_FACTOR * SCALING_FACTOR; - - // bounding box of the expolygons of the first layer of the volume - BoundingBox bbox2; - for (const auto& expoly : expolys) - bbox2.merge(get_extents(expoly.contour)); - const double& bboxX = bbox2.size()(0); - const double& bboxY = bbox2.size()(1); - double thermalLength = sqrt(bboxX * bboxX + bboxY * bboxY) * SCALING_FACTOR; - double thermalLengthRef = Model::getThermalLength(modelVolumePtr); - - double height_to_area = std::max(height / Ixx * (bbox2.size()(1) * SCALING_FACTOR), height / Iyy * (bbox2.size()(0) * SCALING_FACTOR)); - double brim_width = adhesion * std::min(std::min(std::max(height_to_area * maxSpeed / 24, thermalLength * 8. / thermalLengthRef * std::min(height, 30.) / 30.), 18.), 1.5 * thermalLength); - // small brims are omitted - if (brim_width < 5 && brim_width < 1.5 * thermalLength) - brim_width = 0; - // large brims are omitted - if (brim_width > 18) brim_width = 18.; - - return brim_width; -} - //BBS: config brimwidth by group of volumes double configBrimWidthByVolumeGroups(double adhesion, double maxSpeed, const std::vector modelVolumePtrs, const ExPolygons& expolys, double &groupHeight) { @@ -857,6 +358,14 @@ static ExPolygons make_brim_ears(const PrintObject* object, const double& flowWi if (brim_ear_points.size() <= 0) { return mouse_ears_ex; } + //ORCA: Painted ears can snap to the EFC-adjusted outline when enabled. + const bool use_efc_outline = use_brim_efc_outline(*object); + const ExPolygons &raw_outline = object->layers().front()->lslices; + //ORCA: Lazily computed EFC-adjusted bottom outline. + //Stored separately so we can avoid recomputation unless EFC snapping is used. + ExPolygons efc_outline_storage; + const ExPolygons* efc_outline = nullptr; + const Geometry::Transformation& trsf = object->model_object()->instances[0]->get_transformation(); Transform3d model_trsf = trsf.get_matrix_no_offset(); const Point ¢er_offset = object->center_offset(); @@ -880,6 +389,29 @@ static ExPolygons make_brim_ears(const PrintObject* object, const double& flowWi Vec3f pos = pt.transform(model_trsf); int32_t pt_x = scale_(pos.x()); int32_t pt_y = scale_(pos.y()); + + //ORCA: Snap painted ears to the EFC-adjusted outline when enabled. + if (use_efc_outline) { + if (efc_outline == nullptr) { + //ORCA: Compute EFC-adjusted outline lazily for painted ear snapping. + efc_outline_storage = get_print_object_bottom_layer_expolygons(*object); + efc_outline = &efc_outline_storage; + } + + if (!efc_outline->empty()) { + Point closest_point; + //ORCA: Snap within the matching island to avoid drifting to another island. + if (closest_point_on_matching_island( + raw_outline, + *efc_outline, + Point(pt_x, pt_y), + closest_point)) { + pt_x = closest_point.x(); + pt_y = closest_point.y(); + } + } + } + mouse_ears_ex.back().contour.translate(Point(pt_x, pt_y)); } return mouse_ears_ex; @@ -926,6 +458,14 @@ static ExPolygons outer_inner_brim_area(const Print& print, const bool has_outer_brim = brim_type == btOuterOnly || brim_type == btOuterAndInner || brim_type == btAutoBrim || use_auto_brim_ears || use_brim_ears; coord_t ear_detection_length = scale_(object->config().brim_ears_detection_length.value); coordf_t brim_ears_max_angle = object->config().brim_ears_max_angle.value; + //ORCA: Select brim base slices from EFC-compensated outline when enabled. + const bool use_efc_outline = use_brim_efc_outline(*object); + ExPolygons brim_slices_storage; + const ExPolygons* brim_slices = nullptr; + //ORCA: Select EFC-adjusted bottom outline when enabled. + if (use_efc_outline) + brim_slices_storage = get_print_object_bottom_layer_expolygons(*object); + brim_slices = use_efc_outline ? &brim_slices_storage : &object->layers().front()->lslices; ExPolygons brim_area_object; ExPolygons no_brim_area_object; @@ -961,64 +501,72 @@ static ExPolygons outer_inner_brim_area(const Print& print, double brimWidthRaw = configBrimWidthByVolumeGroups(adhesion, maxSpeed, groupVolumePtrs, volumeGroup.slices, groupHeight); brim_width = scale_(floor(brimWidthRaw / flowWidth / 2) * flowWidth * 2); } - for (const ExPolygon& ex_poly : volumeGroup.slices) { - // BBS: additional brim width will be added if part's adhesion area is too small and brim is not generated - float brim_width_mod; - if (brim_width < scale_(5.) && has_brim_auto && groupHeight > 10.) { - brim_width_mod = ex_poly.area() / ex_poly.contour.length() < scaled_half_min_adh_length - && brim_width < scaled_flow_width ? brim_width + scaled_additional_brim_width : brim_width; - } - else { - brim_width_mod = brim_width; - } - //BBS: brim width should be limited to the 1.5*boundingboxSize of a single polygon. - if (has_brim_auto) { - BoundingBox bbox2 = ex_poly.contour.bounding_box(); - brim_width_mod = std::min(brim_width_mod, float(std::max(bbox2.size()(0), bbox2.size()(1)))); - } - brim_width_mod = floor(brim_width_mod / scaled_flow_width / 2) * scaled_flow_width * 2; - - Polygons ex_poly_holes_reversed = ex_poly.holes; - polygons_reverse(ex_poly_holes_reversed); - - if (has_outer_brim) { - // BBS: inner and outer boundary are offset from the same polygon incase of round off error. - auto innerExpoly = offset_ex(ex_poly.contour, brim_offset, jtRound, SCALED_RESOLUTION); - ExPolygons outerExpoly; - if (use_brim_ears) { - outerExpoly = make_brim_ears(object, flowWidth, brim_offset, flow, true); - //outerExpoly = offset_ex(outerExpoly, brim_width_mod, jtRound, SCALED_RESOLUTION); - } else if (use_auto_brim_ears) { - coord_t size_ear = (brim_width_mod - brim_offset - flow.scaled_spacing()); - outerExpoly = make_brim_ears_auto(innerExpoly, size_ear, ear_detection_length, brim_ears_max_angle, true); - }else { - outerExpoly = offset_ex(innerExpoly, brim_width_mod, jtRound, SCALED_RESOLUTION); - } - append(brim_area_object, diff_ex(outerExpoly, innerExpoly)); - } - if (has_inner_brim) { - ExPolygons outerExpoly; - auto innerExpoly = offset_ex(ex_poly_holes_reversed, -brim_width - brim_offset); - if (use_brim_ears) { - outerExpoly = make_brim_ears(object, flowWidth, brim_offset, flow, false); - } else if (use_auto_brim_ears) { - coord_t size_ear = (brim_width - brim_offset - flow.scaled_spacing()); - outerExpoly = make_brim_ears_auto(offset_ex(ex_poly_holes_reversed, -brim_offset), size_ear, ear_detection_length, brim_ears_max_angle, false); - }else { - outerExpoly = offset_ex(ex_poly_holes_reversed, -brim_offset); - } - append(brim_area_object, intersection_ex(diff_ex(outerExpoly, innerExpoly), ex_poly_holes_reversed)); - } - if (!has_inner_brim) { - // BBS: brim should be apart from holes - append(no_brim_area_object, diff_ex(ex_poly_holes_reversed, offset_ex(ex_poly_holes_reversed, -no_brim_offset))); - } - if (!has_outer_brim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly_holes_reversed)); - append(holes_object, ex_poly_holes_reversed); + ExPolygons volume_group_slices_efc; + const ExPolygons* volume_group_slices = &volumeGroup.slices; + if (use_efc_outline) { + //ORCA: When using EFC outline, restrict per-volume-group slices to the + // EFC-adjusted bottom footprint to keep brim width heuristics consistent. + volume_group_slices_efc = intersection_ex(*brim_slices, volumeGroup.slices); + volume_group_slices = &volume_group_slices_efc; } - } - auto objectIsland = offset_ex(object->layers().front()->lslices, brim_offset, jtRound, SCALED_RESOLUTION); + for (const ExPolygon& ex_poly : *volume_group_slices) { + // BBS: additional brim width will be added if part's adhesion area is too small and brim is not generated + float brim_width_mod; + if (brim_width < scale_(5.) && has_brim_auto && groupHeight > 10.) { + brim_width_mod = ex_poly.area() / ex_poly.contour.length() < scaled_half_min_adh_length + && brim_width < scaled_flow_width ? brim_width + scaled_additional_brim_width : brim_width; + } + else { + brim_width_mod = brim_width; + } + //BBS: brim width should be limited to the 1.5*boundingboxSize of a single polygon. + if (has_brim_auto) { + BoundingBox bbox2 = ex_poly.contour.bounding_box(); + brim_width_mod = std::min(brim_width_mod, float(std::max(bbox2.size()(0), bbox2.size()(1)))); + } + brim_width_mod = floor(brim_width_mod / scaled_flow_width / 2) * scaled_flow_width * 2; + + Polygons ex_poly_holes_reversed = ex_poly.holes; + polygons_reverse(ex_poly_holes_reversed); + + if (has_outer_brim) { + // BBS: inner and outer boundary are offset from the same polygon incase of round off error. + auto innerExpoly = offset_ex(ex_poly.contour, brim_offset, jtRound, SCALED_RESOLUTION); + ExPolygons outerExpoly; + if (use_brim_ears) { + outerExpoly = make_brim_ears(object, flowWidth, brim_offset, flow, true); + //outerExpoly = offset_ex(outerExpoly, brim_width_mod, jtRound, SCALED_RESOLUTION); + } else if (use_auto_brim_ears) { + coord_t size_ear = (brim_width_mod - brim_offset - flow.scaled_spacing()); + outerExpoly = make_brim_ears_auto(innerExpoly, size_ear, ear_detection_length, brim_ears_max_angle, true); + }else { + outerExpoly = offset_ex(innerExpoly, brim_width_mod, jtRound, SCALED_RESOLUTION); + } + append(brim_area_object, diff_ex(outerExpoly, innerExpoly)); + } + if (has_inner_brim) { + ExPolygons outerExpoly; + auto innerExpoly = offset_ex(ex_poly_holes_reversed, -brim_width - brim_offset); + if (use_brim_ears) { + outerExpoly = make_brim_ears(object, flowWidth, brim_offset, flow, false); + } else if (use_auto_brim_ears) { + coord_t size_ear = (brim_width - brim_offset - flow.scaled_spacing()); + outerExpoly = make_brim_ears_auto(offset_ex(ex_poly_holes_reversed, -brim_offset), size_ear, ear_detection_length, brim_ears_max_angle, false); + }else { + outerExpoly = offset_ex(ex_poly_holes_reversed, -brim_offset); + } + append(brim_area_object, intersection_ex(diff_ex(outerExpoly, innerExpoly), ex_poly_holes_reversed)); + } + if (!has_inner_brim) { + // BBS: brim should be apart from holes + append(no_brim_area_object, diff_ex(ex_poly_holes_reversed, offset_ex(ex_poly_holes_reversed, -no_brim_offset))); + } + if (!has_outer_brim) + append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly_holes_reversed)); + append(holes_object, ex_poly_holes_reversed); + } + } + auto objectIsland = offset_ex(*brim_slices, brim_offset, jtRound, SCALED_RESOLUTION); append(no_brim_area_object, objectIsland); brimToWrite.at(object->id()).obj = false; @@ -1261,393 +809,8 @@ static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_ return std::move(polylines); } - -// BBS: this function is used to generate brim for inner island inside holes -// Collect island + brim area to be minused when generating inner brim for holes -static void make_inner_island_brim(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim, - ExtrusionEntityCollection &brim, ExPolygons &islands_area_ex) -{ - const auto scaled_resolution = scaled(print.config().resolution.value); - - auto save_polygon_if_is_inner_island = [scaled_resolution](const Polygons& holes_area, Polygon& contour, std::map& hole_island_pair) { - for (size_t i = 0; i < holes_area.size(); i++) { - Polygons contour_polys; - contour_polys.push_back(contour); - if (diff_ex(contour_polys, { holes_area[i] }).empty()) { - // BBS: this is an inner island inside holes_area[i], save - contour.douglas_peucker(scaled_resolution); - hole_island_pair[i].push_back(contour); - break; - } - } - }; - - Flow flow = print.brim_flow(); - for (const PrintObject* object : top_level_objects_with_brim) { - const BrimType brim_type = object->config().brim_type.value; - // BBS: don't need to handle this object if hasn't enabled outer_brim - if (brim_type == BrimType::btNoBrim) - continue; - - //BBS: 1 collect holes area which is used to limit the brim of inner island - Polygons holes_area; - for (const ExPolygon& ex_poly : object->layers().front()->lslices) - polygons_append(holes_area, ex_poly.holes); - - - //BBS: 2 get the island polygons inside holes, saved as map - std::map hole_island_pair; - for (const ExPolygon& ex_poly : object->layers().front()->lslices) { - Polygon counter = ex_poly.contour; - save_polygon_if_is_inner_island(holes_area, counter, hole_island_pair); - } - - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - Polygon counter = support_contour; - save_polygon_if_is_inner_island(holes_area, counter, hole_island_pair); - } - } - - //BBS: 3 generate loops, only save part of loop which inside hole - const float brim_offset = scale_(object->config().brim_object_gap.value); - const float brim_width = scale_(object->config().brim_width.value); - if (brim_type == BrimType::btInnerOnly) { - // If brim_type is btInnerOnly, we actually doesn't generate loops for inner island. - // Only update islands_area_ex and return - for (auto it = hole_island_pair.begin(); it != hole_island_pair.end(); it++) { - ExPolygons islands_area_ex_object = intersection_ex(offset(it->second, brim_offset), offset(holes_area[it->first], -brim_offset)); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_object, instance); - } - } - else { - size_t num_loops = size_t(floor(brim_width / float(flow.scaled_spacing()))); - for (auto it = hole_island_pair.begin(); it != hole_island_pair.end(); it++) { - Polygons loops; - Polygons inner_islands = offset(it->second, brim_offset); - Polygons brimable_area = offset(holes_area[it->first], -brim_offset); //offset to keep away from hole - Polygons contour = inner_islands; - for (size_t i = 0; i < num_loops; ++i) { - contour = offset(contour, float(flow.scaled_spacing()), jtSquare); - for (Polygon& poly : contour) - poly.douglas_peucker(scaled_resolution); - polygons_append(loops, offset(contour, -0.5f * float(flow.scaled_spacing()))); - } - // BBS: to be checked. - //loops = union_pt_chained_outside_in(loops, false); - loops = union_pt_chained_outside_in(loops); - - std::vector loops_pl_by_levels; - { - Polylines loops_pl = to_polylines(loops); - loops_pl_by_levels.assign(loops_pl.size(), Polylines()); - tbb::parallel_for(tbb::blocked_range(0, loops_pl.size()), - [&loops_pl_by_levels, &loops_pl, &brimable_area](const tbb::blocked_range& range) { - for (size_t i = range.begin(); i < range.end(); ++i) { - loops_pl_by_levels[i] = chain_polylines(intersection_pl({ std::move(loops_pl[i]) }, brimable_area)); - } - }); - } - - // BBS: Reduce down to the ordered list of polylines. - Polylines all_loops_object; - for (Polylines& polylines : loops_pl_by_levels) - append(all_loops_object, std::move(polylines)); - loops_pl_by_levels.clear(); - - optimize_polylines_by_reversing(&all_loops_object); - all_loops_object = connect_brim_lines(std::move(all_loops_object), offset(inner_islands, float(SCALED_EPSILON)), float(flow.scaled_spacing()) * 2.f); - - Polylines final_loops; - for (const PrintInstance& instance : object->instances()) { - size_t dst_idx = final_loops.size(); - final_loops.insert(final_loops.end(), all_loops_object.begin(), all_loops_object.end()); - Point instance_shift = instance.shift_without_plate_offset(); - for (; dst_idx < final_loops.size(); ++dst_idx) - final_loops[dst_idx].translate(instance_shift); - - } - extrusion_entities_append_loops_and_paths(brim.entities, std::move(final_loops), - erBrim, float(flow.mm3_per_mm()), float(flow.width()), - float(print.skirt_first_layer_height())); - - //BBS: save all inner island and inner island brim area here, which is necesary if generate inner brim for holes - //Inner brim of holes must not occupy this area - ExPolygons islands_area_ex_object = intersection_ex(contour, brimable_area); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_object, instance); - } - } - } -} - -//BBS: the brim are generated one by one, and sorted by objs/supports and extruders -static void make_inner_island_brim(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim, - std::map& innerbrimAreaMap, - std::map& innerSupportBrimAreaMap, - ExPolygons& islands_area_ex, ExPolygons& NobrimArea, - std::vector>& objPrintVec) -{ - auto save_polygon_if_is_inner_island = [](const Polygons& holes_area, Polygon& counter, std::map& hole_island_pair) { - for (size_t i = 0; i < holes_area.size(); i++) { - if (diff_ex(Polygons{ counter }, { holes_area[i] }).empty()) { - // BBS: this is an inner island inside holes_area[i], save - counter.douglas_peucker(SCALED_RESOLUTION); - hole_island_pair[i].push_back(counter); - break; - } - } - }; - - unsigned int support_material_extruder = 1; - if (print.has_support_material()) { - assert(top_level_objects_with_brim.front()->config().support_filament >= 0); - if (top_level_objects_with_brim.front()->config().support_filament > 0) - support_material_extruder = top_level_objects_with_brim.front()->config().support_filament; - } - - std::unordered_set top_level_objects_idx; - top_level_objects_idx.reserve(top_level_objects_with_brim.size()); - for (const PrintObject* object : top_level_objects_with_brim) - top_level_objects_idx.insert(object->id().id); - - struct brimWritten { - bool obj; - bool sup; - }; - std::map brimToWrite; - for (const auto& objectWithExtruder : objPrintVec) - if (top_level_objects_idx.find(objectWithExtruder.first.id) != top_level_objects_idx.end()) - brimToWrite.insert({ objectWithExtruder.first, {true,true} }); - - Flow flow = print.brim_flow(); - for (unsigned int extruderNo : print.extruders()) { - ++extruderNo; - for (const auto& objectWithExtruder : objPrintVec) { - if (top_level_objects_idx.find(objectWithExtruder.first.id) != top_level_objects_idx.end()) { - const PrintObject* object = print.get_object(objectWithExtruder.first); - const BrimType brim_type = object->config().brim_type.value; - // BBS: don't need to handle this object if hasn't enabled outer_brim - if (brim_type == BrimType::btNoBrim) - continue; - - //BBS: 1 collect holes area which is used to limit the brim of inner island - Polygons holes_area; - for (const ExPolygon& ex_poly : object->layers().front()->lslices) - polygons_append(holes_area, ex_poly.holes); - - - //BBS: 2 get the island polygons inside holes, saved as map - std::map hole_island_pair; - for (const ExPolygon& ex_poly : object->layers().front()->lslices) { - Polygon counter = ex_poly.contour; - save_polygon_if_is_inner_island(holes_area, counter, hole_island_pair); - } - std::map hole_island_pair_supports; - if (!object->support_layers().empty()) { - for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { - Polygon counter = support_contour; - save_polygon_if_is_inner_island(holes_area, counter, hole_island_pair_supports); - } - } - - //BBS: 3 generate loops, only save part of loop which inside hole - const float brim_offset = scale_(object->config().brim_object_gap.value); - const float brim_width = floor(scale_(object->config().brim_width.value) / 2 / flow.scaled_spacing()) * 2 * flow.scaled_spacing(); - if (objectWithExtruder.second == extruderNo && brimToWrite.at(object->id()).obj) { - if (brim_type == BrimType::btInnerOnly) { - // If brim_type is btInnerOnly, we actually doesn't generate loops for inner island. - // Only update islands_area_ex and return - for (auto it = hole_island_pair.begin(); it != hole_island_pair.end(); it++) { - ExPolygons islands_area_ex_object = intersection_ex(offset(it->second, brim_offset), offset(holes_area[it->first], -brim_offset)); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_object, instance); - } - brimToWrite.at(object->id()).obj = false; - } - else { - for (auto it = hole_island_pair.begin(); it != hole_island_pair.end(); it++) { - Polygons loops; - Polygons inner_islands = offset(it->second, brim_offset); - Polygons brimable_area = offset(holes_area[it->first], -brim_offset); //offset to keep away from hole - Polygons contour = offset(inner_islands, brim_offset + brim_width, jtRound, SCALED_RESOLUTION); - for (Polygon& poly : contour) - poly.douglas_peucker(SCALED_RESOLUTION); - - - //BBS: save all inner island and inner island brim area here, which is necesary if generate inner brim for holes - //Inner brim of holes must not occupy this area - ExPolygons islands_area_ex_object = intersection_ex(contour, brimable_area); - ExPolygons inner_islands_exp = offset_ex(inner_islands, 0.); - islands_area_ex_object = diff_ex(islands_area_ex_object, inner_islands_exp); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_object, instance, print, innerbrimAreaMap); - } - brimToWrite.at(object->id()).obj = false; - } - if (innerbrimAreaMap.find(object->id()) != innerbrimAreaMap.end()) - expolygons_append(islands_area_ex, innerbrimAreaMap[object->id()]); - } - - - if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) { - if (brim_type == BrimType::btInnerOnly) { - // If brim_type is btInnerOnly, we actually doesn't generate loops for inner island. - // Only update islands_area_ex and return - for (auto it = hole_island_pair_supports.begin(); it != hole_island_pair_supports.end(); it++) { - ExPolygons islands_area_ex_support = intersection_ex(offset(it->second, 0), offset(holes_area[it->first], 0)); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_support, instance); - } - brimToWrite.at(object->id()).sup = false; - } - else { - for (auto it = hole_island_pair_supports.begin(); it != hole_island_pair_supports.end(); it++) { - Polygons loops; - Polygons inner_islands = offset(it->second, 0); - Polygons brimable_area = offset(holes_area[it->first], -float(flow.scaled_spacing())); //offset to keep away from hole - Polygons contour = offset(inner_islands, brim_width, jtRound, SCALED_RESOLUTION); - for (Polygon& poly : contour) - poly.douglas_peucker(SCALED_RESOLUTION); - - - //BBS: save all inner island and inner island brim area here, which is necesary if generate inner brim for holes - //Inner brim of holes must not occupy this area - ExPolygons islands_area_ex_support = intersection_ex(contour, brimable_area); - ExPolygons inner_islands_exp = offset_ex(inner_islands, 0.); - islands_area_ex_support = diff_ex(islands_area_ex_support, inner_islands_exp); - for (const PrintInstance& instance : object->instances()) - append_and_translate(islands_area_ex, islands_area_ex_support, instance, print, innerSupportBrimAreaMap); - - } - brimToWrite.at(object->id()).sup = false; - } - if (innerSupportBrimAreaMap.find(object->id()) != innerSupportBrimAreaMap.end()) - expolygons_append(islands_area_ex, innerSupportBrimAreaMap[object->id()]); - } - } - } - } - islands_area_ex = diff_ex(islands_area_ex, NobrimArea); - for (const PrintObject* object : print.objects()) { - if (innerbrimAreaMap.find(object->id()) != innerbrimAreaMap.end()) - innerbrimAreaMap[object->id()] = diff_ex(innerbrimAreaMap[object->id()], NobrimArea); - if (innerSupportBrimAreaMap.find(object->id()) != innerSupportBrimAreaMap.end()) - innerSupportBrimAreaMap[object->id()] = diff_ex(innerSupportBrimAreaMap[object->id()], NobrimArea); - } -} -static void make_inner_brim(const Print &print, - const ConstPrintObjectPtrs &top_level_objects_with_brim, - const std::vector &bottom_layers_expolygons, - ExtrusionEntityCollection &brim) -{ - assert(print.objects().size() == bottom_layers_expolygons.size()); - const auto scaled_resolution = scaled(print.config().resolution.value); - - //BBS: generate brim for inner island first - ExPolygons inner_islands_ex; - make_inner_island_brim(print, top_level_objects_with_brim, brim, inner_islands_ex); - -#ifdef INNER_ISLAND_BRIM_DEBUG_TO_SVG - static int irun = 0; - BoundingBox bbox_svg; - bbox_svg.merge(get_extents(inner_islands_ex)); - { - std::stringstream stri; - stri << "inner_island_and_brim_area_" << irun << ".svg"; - SVG svg(stri.str(), bbox_svg); - svg.draw(to_polylines(inner_islands_ex), "blue"); - svg.Close(); - } - ++ irun; -#endif - - Flow flow = print.brim_flow(); - ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing())); - //BBS: brim of hole must not overlap with inner island and inner island brim - if (!inner_islands_ex.empty()) { - islands_ex = diff_ex(islands_ex, inner_islands_ex); - } - - Polygons loops; - islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()));// jtSquare seems not working when expandign the holes - for (size_t i = 0; !islands_ex.empty(); ++i) { - for (ExPolygon &poly_ex : islands_ex) - poly_ex.douglas_peucker(scaled_resolution); - polygons_append(loops, to_polygons(islands_ex));// jtSquare seems not working when expandign the holes - islands_ex = offset_ex(islands_ex, -1.3f * float(flow.scaled_spacing())); - islands_ex = offset_ex(islands_ex, .3f * float(flow.scaled_spacing())); - } - - loops = union_pt_chained_outside_in(loops); - std::reverse(loops.begin(), loops.end()); - extrusion_entities_append_loops(brim.entities, std::move(loops), erBrim, float(flow.mm3_per_mm()), - float(flow.width()), float(print.skirt_first_layer_height())); -} - -// BBS: generate inner brim by objs -static void make_inner_brim(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim, - std::map& brimAreaMap, std::map& supportBrimAreaMap, - std::vector>& objPrintVec) -{ - //BBS: generate brim for inner island first - - -#ifdef INNER_ISLAND_BRIM_DEBUG_TO_SVG - static int irun = 0; - BoundingBox bbox_svg; - bbox_svg.merge(get_extents(inner_islands_ex)); - { - std::stringstream stri; - stri << "inner_island_and_brim_area_" << irun << ".svg"; - SVG svg(stri.str(), bbox_svg); - svg.draw(to_polylines(inner_islands_ex), "blue"); - svg.Close(); - } - ++irun; -#endif - - Flow flow = print.brim_flow(); - ExPolygons NoBrim = inner_brim_area(print, top_level_objects_with_brim, - float(flow.scaled_spacing()), brimAreaMap, supportBrimAreaMap, objPrintVec); - - ExPolygons inner_islands_ex; - std::map innerBrimAreaMap; - std::map innerSupportBrimAreaMap; - /*make_inner_island_brim(print, top_level_objects_with_brim, innerBrimAreaMap, innerSupportBrimAreaMap, - inner_islands_ex, NoBrim, objPrintVec);*/ - - //BBS: brim of hole must not overlap with inner island and inner island brim - if (!inner_islands_ex.empty()) { - if (brimAreaMap.size() > 0) { - for (auto iter = brimAreaMap.begin(); iter != brimAreaMap.end(); ++iter) { - if (!iter->second.empty()) { - iter->second = diff_ex(iter->second, inner_islands_ex); - }; - } - } - if (supportBrimAreaMap.size() > 0) { - for (auto iter = supportBrimAreaMap.begin(); iter != supportBrimAreaMap.end(); ++iter) { - if (!iter->second.empty()) { - iter->second = diff_ex(iter->second, inner_islands_ex); - }; - } - } - for (const PrintObject* object : print.objects()) { - if (innerBrimAreaMap.find(object->id()) != innerBrimAreaMap.end()) { - append(brimAreaMap[object->id()], innerBrimAreaMap[object->id()]); - } - if (innerSupportBrimAreaMap.find(object->id()) != innerSupportBrimAreaMap.end()) { - append(supportBrimAreaMap[object->id()], innerSupportBrimAreaMap[object->id()]); - } - } - } -} - - //BBS: generate out brim by offseting ExPolygons 'islands_area_ex' -Polygons tryExPolygonOffset(const ExPolygons islandAreaEx, const Print& print) +Polygons tryExPolygonOffset(const ExPolygons& islandAreaEx, const Print& print) { const auto scaled_resolution = scaled(print.config().resolution.value); Polygons loops; @@ -1718,8 +881,6 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_ std::vector> &objPrintVec, std::vector& printExtruders) { - - double brim_width_max = 0; std::map brim_width_map; std::map brimAreaMap; std::map supportBrimAreaMap; @@ -1732,7 +893,10 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_ for (const ObjectID printObjID : print.print_object_ids()) { BoundingBox bbx; PrintObject* object = const_cast(print.get_object(printObjID)); - for (const ExPolygon& ex_poly : object->layers().front()->lslices) + //ORCA: Use EFC-compensated outline for brim bounding box when enabled. + const ExPolygons brim_slices = use_brim_efc_outline(*object) ? + get_print_object_bottom_layer_expolygons(*object) : object->layers().front()->lslices; + for (const ExPolygon& ex_poly : brim_slices) for (const PrintInstance& instance : object->instances()) { auto ex_poly_translated = ex_poly; ex_poly_translated.translate(instance.shift_without_plate_offset()); @@ -1774,9 +938,6 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_ supportBrimMap.insert(std::make_pair(iter->first, makeBrimInfill(iter->second, print, islands_area))); }; } - - size_t num_loops = size_t(floor(brim_width_max / flow.spacing())); - BOOST_LOG_TRIVIAL(debug) << "brim_width_max, num_loops: " << brim_width_max << ", " << num_loops; } } // namespace Slic3r diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3ca75d28f3..4e78b31b46 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -904,7 +904,7 @@ static std::vector s_Preset_print_options { "top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap", "support_interface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed", "outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height","single_loop_draft_shield", "draft_shield", - "brim_width", "brim_object_gap", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers", + "brim_width", "brim_object_gap", "brim_use_efc_outline", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style", // BBS diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 37fc895411..054a57f797 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1562,6 +1562,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.)); + def = this->add("brim_use_efc_outline", coBool); + def->label = L("Brim follows compensated outline"); + def->category = L("Support"); + def->tooltip = L("When enabled, the brim is aligned with the first-layer perimeter geometry after Elephant Foot Compensation is applied.\n" + "This option is intended for cases where Elephant Foot Compensation significantly alters the first-layer footprint.\n" + "\n" + "If your current setup already works well, enabling it may be unnecessary and can cause the brim to fuse with upper layers." ); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("brim_ears", coBool); def->label = L("Brim ears"); def->category = L("Support"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 3e34a8362b..1dac4b7057 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -874,6 +874,7 @@ PRINT_CONFIG_CLASS_DEFINE( PrintObjectConfig, ((ConfigOptionFloat, brim_object_gap)) + ((ConfigOptionBool, brim_use_efc_outline)) ((ConfigOptionEnum, brim_type)) ((ConfigOptionFloat, brim_width)) ((ConfigOptionFloat, brim_ears_detection_length)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 7cc98209cf..4b4237dca1 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1006,6 +1006,7 @@ bool PrintObject::invalidate_state_by_config_options( for (const t_config_option_key &opt_key : opt_keys) { if ( opt_key == "brim_width" || opt_key == "brim_object_gap" + || opt_key == "brim_use_efc_outline" || opt_key == "brim_type" || opt_key == "brim_ears_max_angle" || opt_key == "brim_ears_detection_length" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 6c5fa69534..90944e673e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -705,6 +705,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool have_brim = (config->opt_enum("brim_type") != btNoBrim); toggle_field("brim_object_gap", have_brim); + toggle_field("brim_use_efc_outline", have_brim); bool have_brim_width = (config->opt_enum("brim_type") != btNoBrim) && config->opt_enum("brim_type") != btAutoBrim && config->opt_enum("brim_type") != btPainted; toggle_field("brim_width", have_brim_width); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index e7520b5b51..44dd7b8f6e 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -87,14 +87,14 @@ std::map> SettingsFactory::OBJECT_C {"precise_z_height", "",10} }}, - { L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3}, - {"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6}, {"support_threshold_overlap", "",6}, {"support_on_build_plate_only", "",7}, - {"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25}, - {"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10},{"tree_support_branch_angle_organic","",10}, {"tree_support_wall_count", "",11},{"tree_support_branch_diameter_angle", "",11},//tree support - {"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15}, - {"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19}, - {"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23},{"support_remove_small_overhang","",27}, - {"support_object_first_layer_gap","",28} + { L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},{"brim_use_efc_outline", "",4}, + {"enable_support", "",5},{"support_type", "",6},{"support_threshold_angle", "",7}, {"support_threshold_overlap", "",8}, {"support_on_build_plate_only", "",9}, + {"support_filament", "",10},{"support_interface_filament", "",11},{"support_expansion", "",12},{"support_style", "",13}, + {"tree_support_brim_width", "",14}, {"tree_support_branch_angle", "",15},{"tree_support_branch_angle_organic","",16}, {"tree_support_wall_count", "",17},{"tree_support_branch_diameter_angle", "",18},//tree support + {"support_bottom_z_distance", "",19},{"support_top_z_distance", "",20},{"support_base_pattern", "",21},{"support_base_pattern_spacing", "",22}, + {"support_interface_top_layers", "",23},{"support_interface_bottom_layers", "",24},{"support_interface_spacing", "",25},{"support_bottom_interface_spacing", "",26}, + {"support_object_xy_distance", "",27}, {"bridge_no_support", "",28},{"max_bridge_length", "",29},{"support_critical_regions_only", "",30},{"support_remove_small_overhang","",31}, + {"support_object_first_layer_gap","",32} }}, { L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13} }} diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cc67ee11fd..059955a7cc 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4670,7 +4670,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "nozzle_height", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", - "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation", + "brim_width", "brim_object_gap", "brim_use_efc_outline", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework", "prime_tower_infill_gap", "prime_volume", "extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fd8ede92d2..d4d31a3573 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2663,6 +2663,7 @@ void TabPrint::build() optgroup->append_single_option_line("brim_type", "others_settings_brim#type"); optgroup->append_single_option_line("brim_width", "others_settings_brim#width"); optgroup->append_single_option_line("brim_object_gap", "others_settings_brim#brim-object-gap"); + optgroup->append_single_option_line("brim_use_efc_outline", "others_settings_brim#brim-use-efc-outline"); optgroup->append_single_option_line("brim_ears_max_angle", "others_settings_brim#ear-max-angle"); optgroup->append_single_option_line("brim_ears_detection_length", "others_settings_brim#ear-detection-radius"); From e8af78d032a0dadf2e4a8e44a8b4c9ca48912efd Mon Sep 17 00:00:00 2001 From: yw4z Date: Mon, 29 Dec 2025 18:37:36 +0300 Subject: [PATCH 07/45] Custom grouping options for user filament presets (All, None, By Vendor, By Type) (#11681) * Update PresetComboBoxes.cpp * add option on preferences * simplify changes * update * Update PresetComboBoxes.cpp * Update PresetComboBoxes.cpp * support lowercase on sorting non submenu list * minor changes --------- Co-authored-by: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Co-authored-by: SoftFever --- src/libslic3r/AppConfig.cpp | 4 +++ src/slic3r/GUI/Preferences.cpp | 10 +++++-- src/slic3r/GUI/Preferences.hpp | 2 +- src/slic3r/GUI/PresetComboBoxes.cpp | 41 +++++++++++++++++++++++++---- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 16f6a4a606..f91c83ad82 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -318,6 +318,10 @@ void AppConfig::set_defaults() set_bool("remember_printer_config", true); } + if (get("group_filament_presets").empty()) { + set("group_filament_presets", "1"); // All "0" / None "1" / By Type "2" / By Vendor "3" + } + if (get("enable_high_low_temp_mixed_printing").empty()){ set_bool("enable_high_low_temp_mixed_printing", false); } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index db330f84c8..61352e18dd 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -78,7 +78,7 @@ std::tuple PreferencesDialog::create_item_combobox_base( return {m_sizer_combox, combobox}; } -wxBoxSizer* PreferencesDialog::create_item_combobox(wxString title, wxString tooltip, std::string param, std::vector vlist) +wxBoxSizer* PreferencesDialog::create_item_combobox(wxString title, wxString tooltip, std::string param, std::vector vlist, std::function onchange) { unsigned int current_index = 0; @@ -90,8 +90,10 @@ wxBoxSizer* PreferencesDialog::create_item_combobox(wxString title, wxString too auto [sizer, combobox] = create_item_combobox_base(title, tooltip, param, vlist, current_index); //// save config - combobox->GetDropDown().Bind(wxEVT_COMBOBOX, [this, param](wxCommandEvent& e) { + combobox->GetDropDown().Bind(wxEVT_COMBOBOX, [this, param, onchange](wxCommandEvent& e) { app_config->set(param, std::to_string(e.GetSelection())); + if (onchange) + onchange(std::to_string(e.GetSelection())); e.Skip(); }); @@ -1289,6 +1291,10 @@ void PreferencesDialog::create_items() auto item_remember_printer = create_item_checkbox(_L("Remember printer configuration"), _L("If enabled, Orca will remember and switch filament/process configuration for each printer automatically."), "remember_printer_config"); g_sizer->Add(item_remember_printer); + auto item_filament_preset_grouping = create_item_combobox(_L("Group user filament presets"), _L("Group user filament presets based on selection"), + "group_filament_presets", {_L("All"), _L("None"), _L("By type"), _L("By vendor")}, [](wxString value) {wxGetApp().plater()->sidebar().update_presets(Preset::TYPE_FILAMENT);}); + g_sizer->Add(item_filament_preset_grouping); + //// GENERAL > Features g_sizer->Add(create_item_title(_L("Features")), 1, wxEXPAND); diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index ecd591e089..28ce3afb97 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -77,7 +77,7 @@ public: std::vector f_sizers; wxBoxSizer *create_item_title(wxString title); - wxBoxSizer *create_item_combobox(wxString title, wxString tooltip, std::string param, std::vector vlist); + wxBoxSizer *create_item_combobox(wxString title, wxString tooltip, std::string param, std::vector vlist, std::function onchange = {}); wxBoxSizer *create_item_combobox(wxString title, wxString tooltip, std::string param, std::vector vlist, std::vector config_name_index); wxBoxSizer *create_item_region_combobox(wxString title, wxString tooltip); wxBoxSizer *create_item_language_combobox(wxString title, wxString tooltip); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 5006c5eab0..2e5f83c211 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -1132,6 +1132,7 @@ void PlaterPresetComboBox::update() std::map preset_descriptions; std::map preset_filament_vendors; std::map preset_filament_types; + std::map preset_filament_names; // ORCA //BBS: move system to the end wxString selected_system_preset; wxString selected_user_preset; @@ -1174,7 +1175,8 @@ void PlaterPresetComboBox::update() bitmap_key += single_bar ? filament_rgb : filament_rgb + extruder_rgb; #endif - if (preset.is_system) { + // ORCA allow caching vendor and type values for all presets instead just system ones + // if (preset.is_system) { if (!preset.is_compatible && preset_filament_vendors.count(name) > 0) continue; else if (preset.is_compatible && preset_filament_vendors.count(name) > 0) @@ -1183,7 +1185,8 @@ void PlaterPresetComboBox::update() if (preset_filament_vendors[name] == "Bambu Lab") preset_filament_vendors[name] = "Bambu"; preset_filament_types[name] = preset.config.option("filament_type")->values.at(0); - } + preset_filament_names[name] = name.ToStdString(); // ORCA + //} } wxBitmap* bmp = get_bmp(preset); assert(bmp); @@ -1251,7 +1254,7 @@ void PlaterPresetComboBox::update() "Bambu PLA Galaxy", "Bambu PLA Metal", "Bambu PLA Marble", "Bambu PETG-CF", "Bambu PETG Translucent", "Bambu ABS-GF"}; std::vector first_vendors = {"", "Bambu", "Generic"}; // Empty vendor for non-system presets std::vector first_types = {"PLA", "PETG", "ABS", "TPU"}; - auto add_presets = [this, &preset_descriptions, &filament_orders, &preset_filament_vendors, &first_vendors, &preset_filament_types, &first_types, &selected_in_ams] + auto add_presets = [this, &preset_descriptions, &filament_orders, &preset_filament_vendors, &first_vendors, &preset_filament_types, &preset_filament_names, &first_types, &selected_in_ams] (std::map const &presets, wxString const &selected, std::string const &group, wxString const &groupName) { if (!presets.empty()) { set_label_marker(Append(_L(group), wxNullBitmap, DD_ITEM_STYLE_SPLIT_ITEM)); @@ -1285,9 +1288,31 @@ void PlaterPresetComboBox::update() } return l->first < r->first; }); + // ORCA add sorting support for vendor / type for user presets. also non grouped items + if (groupName == "by_vendor" || groupName == "by_type" || groupName == ""){ + auto by = groupName == "by_vendor" ? preset_filament_vendors + : groupName == "by_type" ? preset_filament_types + : preset_filament_names; + std::sort(list.begin(), list.end(), [&by](auto *l, auto *r) { + auto get_key = [&](auto* item) -> std::pair { + std::string str = by.count(item->first) ? by.at(item->first) : ""; + std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c);}); + return {!str.empty(), str}; // is_valid, lower_case + }; + auto [l_valid, l_lower] = get_key(l); + auto [r_valid, r_lower] = get_key(r); + return (l_valid != r_valid) ? l_valid > r_valid + : (l_lower != r_lower) ? l_lower < r_lower + : l->first < r->first; + }); + } bool unsupported = group == "Unsupported presets"; for (auto it : list) { - auto groupName2 = groupByGroup ? groupName : preset_filament_vendors[it->first]; + // ORCA add sorting support for vendor / type for user presets + auto groupName2 = groupName == "by_type" ? (preset_filament_types[it->first].empty() ? _L("Unspecified") : preset_filament_types[it->first]) + : groupName == "by_vendor" ? (preset_filament_vendors[it->first].empty() ? _L("Unspecified") : preset_filament_vendors[it->first]) + : groupByGroup ? groupName + : preset_filament_vendors[it->first]; int index = Append(it->first, *it->second, groupName2, nullptr, unsupported ? DD_ITEM_STYLE_DISABLED : 0); if (unsupported) set_label_marker(index, LABEL_ITEM_DISABLED); @@ -1311,7 +1336,13 @@ void PlaterPresetComboBox::update() //BBS: add project embedded preset logic add_presets(project_embedded_presets, selected_user_preset, L("Project-inside presets"), _L("Project") + " "); - add_presets(nonsys_presets, selected_user_preset, L("User presets"), _L("Custom") + " "); + // ORCA add sorting support for vendor / type for user presets + auto group_filament_presets = wxGetApp().app_config->get("group_filament_presets"); + auto group_filament_presets_by = group_filament_presets == "0" ? (_L("Custom") + " ") // Append all to "Custom" sub menu + : group_filament_presets == "2" ? "by_type" // Create sub menus with filament type + : group_filament_presets == "3" ? "by_vendor" // Create sub menus with filament vendor + : ""; // Use without sub menu + add_presets(nonsys_presets, selected_user_preset, L("User presets"), group_filament_presets_by); // BBS: move system to the end add_presets(system_presets, selected_system_preset, L("System presets"), _L("System")); add_presets(uncompatible_presets, {}, L("Unsupported presets"), _L("Unsupported") + " "); From 0f397492e7aab2bb8743fecda41ed9751613200f Mon Sep 17 00:00:00 2001 From: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Tue, 30 Dec 2025 09:28:09 +0000 Subject: [PATCH 08/45] Fix non bambu wipe tower issues (skirt overlapping with tower, extreme travel moves outside plate boundary) (#11748) * Fix prime/purge tower extreme travel for non BBL printers * Fix wipe tower skirt not generating correctly for non bambu printers --- src/libslic3r/GCode/WipeTower2.cpp | 4 ++++ src/libslic3r/GCode/WipeTower2.hpp | 16 ++++++++++++---- src/libslic3r/Print.cpp | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/WipeTower2.cpp b/src/libslic3r/GCode/WipeTower2.cpp index cf5a68b436..6bec4168f4 100644 --- a/src/libslic3r/GCode/WipeTower2.cpp +++ b/src/libslic3r/GCode/WipeTower2.cpp @@ -1215,6 +1215,10 @@ WipeTower::ToolChangeResult WipeTower2::construct_tcr(WipeTowerWriter2& writer, result.extrusions = std::move(writer.extrusions()); result.wipe_path = std::move(writer.wipe_path()); result.is_finish_first = is_finish; + // ORCA: Always initialize the tool_change_start_pos with a valid position + // to avoid undefined variable travel on X in Gcode.cpp function std::string WipeTowerIntegration::post_process_wipe_tower_moves + result.tool_change_start_pos = result.start_pos; // always valid fallback + return result; } diff --git a/src/libslic3r/GCode/WipeTower2.hpp b/src/libslic3r/GCode/WipeTower2.hpp index 3dbc066634..6242b634a8 100644 --- a/src/libslic3r/GCode/WipeTower2.hpp +++ b/src/libslic3r/GCode/WipeTower2.hpp @@ -58,10 +58,18 @@ public: std::vector> get_z_and_depth_pairs() const; float get_brim_width() const { return m_wipe_tower_brim_width_real; } float get_wipe_tower_height() const { return m_wipe_tower_height; } - - - - + // ORCA: Match WipeTower API used by Print skirt/brim planning. + // Returned bounding box is in WIPE-TOWER-LOCAL coordinates (before placement on the bed). + // Include brim and y-shift to match what WT gcode actually prints. + BoundingBoxf get_bbx() const{ + const float brim = m_wipe_tower_brim_width_real; + const Vec2d min(-brim, -brim + double(m_y_shift)); + const Vec2d max(double(m_wipe_tower_width) + brim, double(m_wipe_tower_depth) + brim + double(m_y_shift)); + return BoundingBoxf(min, max); + } + // WT2 doesn't currently compute a rib-origin compensation like WipeTower (m_rib_offset), + // so expose a zero offset for consistency purposes (to maintain API parity). + Vec2f get_rib_offset() const { return Vec2f::Zero(); } // Switch to a next layer. void set_layer( diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 330b489141..7a0a6dd867 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -3333,6 +3333,8 @@ void Print::_make_wipe_tower() m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs(); m_wipe_tower_data.brim_width = wipe_tower.get_brim_width(); m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height(); + m_wipe_tower_data.bbx = wipe_tower.get_bbx(); + m_wipe_tower_data.rib_offset = wipe_tower.get_rib_offset(); // Unload the current filament over the purge tower. coordf_t layer_height = m_objects.front()->config().layer_height.value; From 2877c6032dfbcbd3b86ff9d6efccde72ce3a39e9 Mon Sep 17 00:00:00 2001 From: Rodrigo Faselli <162915171+RF47@users.noreply.github.com> Date: Tue, 30 Dec 2025 06:30:35 -0300 Subject: [PATCH 09/45] Improve connect infill for multiline (#11765) * Improve connect infill for multiline * Simplify multiline infill connection logic --- src/libslic3r/Fill/FillBase.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index c585329079..eff83efe3e 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -1707,6 +1707,12 @@ void Fill::connect_infill(Polylines &&infill_ordered, const std::vectorcontour_idx]; + + // Orca: If multiline infill is requested, skip connections that are too short. + if (params.multiline > 1 && arc.arc_length < scale_(spacing) * params.multiline) { + continue; + } + const std::vector &contour_params = graph.boundary_params[cp1->contour_idx]; if (polyline_idx1 != polyline_idx2) { Polyline &polyline1 = infill_ordered[polyline_idx1]; From 81dd1537982f620c006a0de8fade7b1fe7cd8129 Mon Sep 17 00:00:00 2001 From: Ian Bassi Date: Tue, 30 Dec 2025 10:34:14 -0300 Subject: [PATCH 10/45] Small area flow compensator improvements (#11716) * Replace spline with PchipInterpolatorHelper in flow compensator Swapped out the tk::spline implementation for PchipInterpolatorHelper in SmallAreaInfillFlowCompensator. Updated member types and method calls to use the new interpolator for improved flow compensation modeling. * Enforce strictly increasing flow compensation factors Added a check to ensure that flow compensation factors in SmallAreaInfillFlowCompensator strictly increase with extrusion length, throwing an exception if this condition is not met. This improves input validation and prevents invalid compensation models. * Add context to Small Area Flow Compensation errors Prefixed error messages in SmallAreaInfillFlowCompensator with 'Small Area Flow Compensation' for improved clarity and debugging. Also rethrows exceptions after logging to ensure proper error propagation. * Remove spline library from dependencies Eliminated the spline header-only library from the project by deleting its CMake configuration and header file, and updating documentation and build scripts to remove references to spline. This streamlines the dependencies and build process. --- deps_src/CMakeLists.txt | 1 - deps_src/README_CMAKE_INTERFACES.md | 22 +- deps_src/spline/CMakeLists.txt | 37 - deps_src/spline/spline.h | 944 ------------------ .../GCode/SmallAreaInfillFlowCompensator.cpp | 27 +- .../GCode/SmallAreaInfillFlowCompensator.hpp | 8 +- 6 files changed, 21 insertions(+), 1018 deletions(-) delete mode 100644 deps_src/spline/CMakeLists.txt delete mode 100644 deps_src/spline/spline.h diff --git a/deps_src/CMakeLists.txt b/deps_src/CMakeLists.txt index 11457c0d18..390cffad30 100644 --- a/deps_src/CMakeLists.txt +++ b/deps_src/CMakeLists.txt @@ -10,7 +10,6 @@ add_subdirectory(earcut) add_subdirectory(fast_float) add_subdirectory(nanosvg) add_subdirectory(nlohmann) -add_subdirectory(spline) # Header-only spline library add_subdirectory(stb_dxt) # Header-only STB DXT compression library # Static libraries diff --git a/deps_src/README_CMAKE_INTERFACES.md b/deps_src/README_CMAKE_INTERFACES.md index 78a806fc0b..6ab88c63af 100644 --- a/deps_src/README_CMAKE_INTERFACES.md +++ b/deps_src/README_CMAKE_INTERFACES.md @@ -24,18 +24,7 @@ target_link_libraries(your_target PRIVATE semver::semver) target_link_libraries(your_target PRIVATE hints) ``` -### 3. **spline** (Interface Library) -- **Type**: Interface library (header-only) -- **Target**: `spline` or `spline::spline` -- **Headers**: `spline.h` -- **Usage**: -```cmake -target_link_libraries(your_target PRIVATE spline) -# or -target_link_libraries(your_target PRIVATE spline::spline) -``` - -### 4. **stb_dxt** (Interface Library) +### 3. **stb_dxt** (Interface Library) - **Type**: Interface library (header-only) - **Target**: `stb_dxt` or `stb_dxt::stb_dxt` - **Headers**: `stb_dxt.h` @@ -53,10 +42,9 @@ target_link_libraries(your_target PRIVATE stb_dxt::stb_dxt) 1. **In your CMakeLists.txt**, simply link the library: ```cmake add_executable(my_app main.cpp) -target_link_libraries(my_app - PRIVATE +target_link_libraries(my_app + PRIVATE semver::semver # For version parsing - spline::spline # For spline interpolation stb_dxt::stb_dxt # For DXT texture compression hints # For hints functionality ) @@ -67,9 +55,6 @@ target_link_libraries(my_app // For semver #include -// For spline -#include - // For stb_dxt #include @@ -100,7 +85,6 @@ target_link_libraries(mycomponent PUBLIC semver::semver # Version handling is part of public API PRIVATE - spline::spline # Used internally for interpolation stb_dxt::stb_dxt # Used internally for texture compression ) diff --git a/deps_src/spline/CMakeLists.txt b/deps_src/spline/CMakeLists.txt deleted file mode 100644 index ee6d5c9cb3..0000000000 --- a/deps_src/spline/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(spline) - -# Create interface library for spline (header-only library) -add_library(spline INTERFACE) - -# Set include directories for the interface library -target_include_directories(spline SYSTEM - INTERFACE - $ - $ -) - -# Add compile features -target_compile_features(spline INTERFACE cxx_std_11) - -# Create an alias for consistent naming -add_library(spline::spline ALIAS spline) - -# Install headers if needed -install(FILES - spline.h - DESTINATION include/spline -) - -# Install the interface library -install(TARGETS spline - EXPORT splineTargets - INCLUDES DESTINATION include -) - -# Export the targets -install(EXPORT splineTargets - FILE splineTargets.cmake - NAMESPACE spline:: - DESTINATION lib/cmake/spline -) diff --git a/deps_src/spline/spline.h b/deps_src/spline/spline.h deleted file mode 100644 index 4b1ddd6134..0000000000 --- a/deps_src/spline/spline.h +++ /dev/null @@ -1,944 +0,0 @@ -/* - * spline.h - * - * simple cubic spline interpolation library without external - * dependencies - * - * --------------------------------------------------------------------- - * Copyright (C) 2011, 2014, 2016, 2021 Tino Kluge (ttk448 at gmail.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * --------------------------------------------------------------------- - * - */ - - -#ifndef TK_SPLINE_H -#define TK_SPLINE_H - -#include -#include -#include -#include -#include -#ifdef HAVE_SSTREAM -#include -#include -#endif // HAVE_SSTREAM - -// not ideal but disable unused-function warnings -// (we get them because we have implementations in the header file, -// and this is because we want to be able to quickly separate them -// into a cpp file if necessary) -#if !defined(_MSC_VER) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#endif - -namespace tk -{ - -// spline interpolation -class spline -{ -public: - // spline types - enum spline_type { - linear = 10, // linear interpolation - cspline = 30, // cubic splines (classical C^2) - cspline_hermite = 31 // cubic hermite splines (local, only C^1) - }; - - // boundary condition type for the spline end-points - enum bd_type { - first_deriv = 1, - second_deriv = 2, - not_a_knot = 3 - }; - -protected: - std::vector m_x,m_y; // x,y coordinates of points - // interpolation parameters - // f(x) = a_i + b_i*(x-x_i) + c_i*(x-x_i)^2 + d_i*(x-x_i)^3 - // where a_i = y_i, or else it won't go through grid points - std::vector m_b,m_c,m_d; // spline coefficients - double m_c0; // for left extrapolation - spline_type m_type; - bd_type m_left, m_right; - double m_left_value, m_right_value; - bool m_made_monotonic; - void set_coeffs_from_b(); // calculate c_i, d_i from b_i - size_t find_closest(double x) const; // closest idx so that m_x[idx]<=x - -public: - // default constructor: set boundary condition to be zero curvature - // at both ends, i.e. natural splines - spline(): m_type(cspline), - m_left(second_deriv), m_right(second_deriv), - m_left_value(0.0), m_right_value(0.0), m_made_monotonic(false) - { - ; - } - spline(const std::vector& X, const std::vector& Y, - spline_type type = cspline, - bool make_monotonic = false, - bd_type left = second_deriv, double left_value = 0.0, - bd_type right = second_deriv, double right_value = 0.0 - ): - m_type(type), - m_left(left), m_right(right), - m_left_value(left_value), m_right_value(right_value), - m_made_monotonic(false) // false correct here: make_monotonic() sets it - { - this->set_points(X,Y,m_type); - if(make_monotonic) { - this->make_monotonic(); - } - } - - - // modify boundary conditions: if called it must be before set_points() - void set_boundary(bd_type left, double left_value, - bd_type right, double right_value); - - // set all data points (cubic_spline=false means linear interpolation) - void set_points(const std::vector& x, - const std::vector& y, - spline_type type=cspline); - - // adjust coefficients so that the spline becomes piecewise monotonic - // where possible - // this is done by adjusting slopes at grid points by a non-negative - // factor and this will break C^2 - // this can also break boundary conditions if adjustments need to - // be made at the boundary points - // returns false if no adjustments have been made, true otherwise - bool make_monotonic(); - - // evaluates the spline at point x - double operator() (double x) const; - double deriv(int order, double x) const; - - // solves for all x so that: spline(x) = y - std::vector solve(double y, bool ignore_extrapolation=true) const; - - // returns the input data points - std::vector get_x() const { return m_x; } - std::vector get_y() const { return m_y; } - double get_x_min() const { assert(!m_x.empty()); return m_x.front(); } - double get_x_max() const { assert(!m_x.empty()); return m_x.back(); } - -#ifdef HAVE_SSTREAM - // spline info string, i.e. spline type, boundary conditions etc. - std::string info() const; -#endif // HAVE_SSTREAM - -}; - - - -namespace internal -{ - -// band matrix solver -class band_matrix -{ -private: - std::vector< std::vector > m_upper; // upper band - std::vector< std::vector > m_lower; // lower band -public: - band_matrix() {}; // constructor - band_matrix(int dim, int n_u, int n_l); // constructor - ~band_matrix() {}; // destructor - void resize(int dim, int n_u, int n_l); // init with dim,n_u,n_l - int dim() const; // matrix dimension - int num_upper() const - { - return (int)m_upper.size()-1; - } - int num_lower() const - { - return (int)m_lower.size()-1; - } - // access operator - double & operator () (int i, int j); // write - double operator () (int i, int j) const; // read - // we can store an additional diagonal (in m_lower) - double& saved_diag(int i); - double saved_diag(int i) const; - void lu_decompose(); - std::vector r_solve(const std::vector& b) const; - std::vector l_solve(const std::vector& b) const; - std::vector lu_solve(const std::vector& b, - bool is_lu_decomposed=false); - -}; - -double get_eps(); - -std::vector solve_cubic(double a, double b, double c, double d, - int newton_iter=0); - -} // namespace internal - - - - -// --------------------------------------------------------------------- -// implementation part, which could be separated into a cpp file -// --------------------------------------------------------------------- - -// spline implementation -// ----------------------- - -void spline::set_boundary(spline::bd_type left, double left_value, - spline::bd_type right, double right_value) -{ - assert(m_x.size()==0); // set_points() must not have happened yet - m_left=left; - m_right=right; - m_left_value=left_value; - m_right_value=right_value; -} - - -void spline::set_coeffs_from_b() -{ - assert(m_x.size()==m_y.size()); - assert(m_x.size()==m_b.size()); - assert(m_x.size()>2); - size_t n=m_b.size(); - if(m_c.size()!=n) - m_c.resize(n); - if(m_d.size()!=n) - m_d.resize(n); - - for(size_t i=0; i& x, - const std::vector& y, - spline_type type) -{ - assert(x.size()==y.size()); - assert(x.size()>=3); - // not-a-knot with 3 points has many solutions - if(m_left==not_a_knot || m_right==not_a_knot) - assert(x.size()>=4); - m_type=type; - m_made_monotonic=false; - m_x=x; - m_y=y; - int n = (int) x.size(); - // check strict monotonicity of input vector x - for(int i=0; i rhs(n); - for(int i=1; i2); - bool modified = false; - const int n=(int)m_x.size(); - // make sure: input data monotonic increasing --> b_i>=0 - // input data monotonic decreasing --> b_i<=0 - for(int i=0; i=m_y[i]) && (m_y[i]>=m_y[ip1]) && m_b[i]>0.0) ) { - modified=true; - m_b[i]=0.0; - } - } - // if input data is monotonic (b[i], b[i+1], avg have all the same sign) - // ensure a sufficient criteria for monotonicity is satisfied: - // sqrt(b[i]^2+b[i+1]^2) <= 3 |avg|, with avg=(y[i+1]-y[i])/h, - for(int i=0; i=0.0 && m_b[i+1]>=0.0 && avg>0.0) || - (m_b[i]<=0.0 && m_b[i+1]<=0.0 && avg<0.0) ) { - // input data is monotonic - double r = sqrt(m_b[i]*m_b[i]+m_b[i+1]*m_b[i+1])/std::fabs(avg); - if(r>3.0) { - // sufficient criteria for monotonicity: r<=3 - // adjust b[i] and b[i+1] - modified=true; - m_b[i] *= (3.0/r); - m_b[i+1] *= (3.0/r); - } - } - } - - if(modified==true) { - set_coeffs_from_b(); - m_made_monotonic=true; - } - - return modified; -} - -// return the closest idx so that m_x[idx] <= x (return 0 if x::const_iterator it; - it=std::upper_bound(m_x.begin(),m_x.end(),x); // *it > x - size_t idx = std::max( int(it-m_x.begin())-1, 0); // m_x[idx] <= x - return idx; -} - -double spline::operator() (double x) const -{ - // polynomial evaluation using Horner's scheme - // TODO: consider more numerically accurate algorithms, e.g.: - // - Clenshaw - // - Even-Odd method by A.C.R. Newbery - // - Compensated Horner Scheme - size_t n=m_x.size(); - size_t idx=find_closest(x); - - double h=x-m_x[idx]; - double interpol; - if(xm_x[n-1]) { - // extrapolation to the right - interpol=(m_c[n-1]*h + m_b[n-1])*h + m_y[n-1]; - } else { - // interpolation - interpol=((m_d[idx]*h + m_c[idx])*h + m_b[idx])*h + m_y[idx]; - } - return interpol; -} - -double spline::deriv(int order, double x) const -{ - assert(order>0); - size_t n=m_x.size(); - size_t idx = find_closest(x); - - double h=x-m_x[idx]; - double interpol; - if(xm_x[n-1]) { - // extrapolation to the right - switch(order) { - case 1: - interpol=2.0*m_c[n-1]*h + m_b[n-1]; - break; - case 2: - interpol=2.0*m_c[n-1]; - break; - default: - interpol=0.0; - break; - } - } else { - // interpolation - switch(order) { - case 1: - interpol=(3.0*m_d[idx]*h + 2.0*m_c[idx])*h + m_b[idx]; - break; - case 2: - interpol=6.0*m_d[idx]*h + 2.0*m_c[idx]; - break; - case 3: - interpol=6.0*m_d[idx]; - break; - default: - interpol=0.0; - break; - } - } - return interpol; -} - -std::vector spline::solve(double y, bool ignore_extrapolation) const -{ - std::vector x; // roots for the entire spline - std::vector root; // roots for each piecewise cubic - const size_t n=m_x.size(); - - // left extrapolation - if(ignore_extrapolation==false) { - root = internal::solve_cubic(m_y[0]-y,m_b[0],m_c0,0.0,1); - for(size_t j=0; j0) ? (m_x[i]-m_x[i-1]) : 0.0; - double eps = internal::get_eps()*512.0*std::min(h,1.0); - if( (-eps<=root[j]) && (root[j]0 && x.back()+eps > new_root) { - x.back()=new_root; // avoid spurious duplicate roots - } else { - x.push_back(new_root); - } - } - } - } - - // right extrapolation - if(ignore_extrapolation==false) { - root = internal::solve_cubic(m_y[n-1]-y,m_b[n-1],m_c[n-1],0.0,1); - for(size_t j=0; j0); - assert(n_u>=0); - assert(n_l>=0); - m_upper.resize(n_u+1); - m_lower.resize(n_l+1); - for(size_t i=0; i0) { - return (int)m_upper[0].size(); - } else { - return 0; - } -} - - -// defines the new operator (), so that we can access the elements -// by A(i,j), index going from i=0,...,dim()-1 -double & band_matrix::operator () (int i, int j) -{ - int k=j-i; // what band is the entry - assert( (i>=0) && (i=0) && (j diagonal, k<0 lower left part, k>0 upper right part - if(k>=0) return m_upper[k][i]; - else return m_lower[-k][i]; -} -double band_matrix::operator () (int i, int j) const -{ - int k=j-i; // what band is the entry - assert( (i>=0) && (i=0) && (j diagonal, k<0 lower left part, k>0 upper right part - if(k>=0) return m_upper[k][i]; - else return m_lower[-k][i]; -} -// second diag (used in LU decomposition), saved in m_lower -double band_matrix::saved_diag(int i) const -{ - assert( (i>=0) && (i=0) && (idim(); i++) { - assert(this->operator()(i,i)!=0.0); - this->saved_diag(i)=1.0/this->operator()(i,i); - j_min=std::max(0,i-this->num_lower()); - j_max=std::min(this->dim()-1,i+this->num_upper()); - for(int j=j_min; j<=j_max; j++) { - this->operator()(i,j) *= this->saved_diag(i); - } - this->operator()(i,i)=1.0; // prevents rounding errors - } - - // Gauss LR-Decomposition - for(int k=0; kdim(); k++) { - i_max=std::min(this->dim()-1,k+this->num_lower()); // num_lower not a mistake! - for(int i=k+1; i<=i_max; i++) { - assert(this->operator()(k,k)!=0.0); - x=-this->operator()(i,k)/this->operator()(k,k); - this->operator()(i,k)=-x; // assembly part of L - j_max=std::min(this->dim()-1,k+this->num_upper()); - for(int j=k+1; j<=j_max; j++) { - // assembly part of R - this->operator()(i,j)=this->operator()(i,j)+x*this->operator()(k,j); - } - } - } -} -// solves Ly=b -std::vector band_matrix::l_solve(const std::vector& b) const -{ - assert( this->dim()==(int)b.size() ); - std::vector x(this->dim()); - int j_start; - double sum; - for(int i=0; idim(); i++) { - sum=0; - j_start=std::max(0,i-this->num_lower()); - for(int j=j_start; joperator()(i,j)*x[j]; - x[i]=(b[i]*this->saved_diag(i)) - sum; - } - return x; -} -// solves Rx=y -std::vector band_matrix::r_solve(const std::vector& b) const -{ - assert( this->dim()==(int)b.size() ); - std::vector x(this->dim()); - int j_stop; - double sum; - for(int i=this->dim()-1; i>=0; i--) { - sum=0; - j_stop=std::min(this->dim()-1,i+this->num_upper()); - for(int j=i+1; j<=j_stop; j++) sum += this->operator()(i,j)*x[j]; - x[i]=( b[i] - sum ) / this->operator()(i,i); - } - return x; -} - -std::vector band_matrix::lu_solve(const std::vector& b, - bool is_lu_decomposed) -{ - assert( this->dim()==(int)b.size() ); - std::vector x,y; - if(is_lu_decomposed==false) { - this->lu_decompose(); - } - y=this->l_solve(b); - x=this->r_solve(y); - return x; -} - -// machine precision of a double, i.e. the successor of 1 is 1+eps -double get_eps() -{ - //return std::numeric_limits::epsilon(); // __DBL_EPSILON__ - return 2.2204460492503131e-16; // 2^-52 -} - -// solutions for a + b*x = 0 -std::vector solve_linear(double a, double b) -{ - std::vector x; // roots - if(b==0.0) { - if(a==0.0) { - // 0*x = 0 - x.resize(1); - x[0] = 0.0; // any x solves it but we need to pick one - return x; - } else { - // 0*x + ... = 0, no solution - return x; - } - } else { - x.resize(1); - x[0] = -a/b; - return x; - } -} - -// solutions for a + b*x + c*x^2 = 0 -std::vector solve_quadratic(double a, double b, double c, - int newton_iter=0) -{ - if(c==0.0) { - return solve_linear(a,b); - } - // rescale so that we solve x^2 + 2p x + q = (x+p)^2 + q - p^2 = 0 - double p=0.5*b/c; - double q=a/c; - double discr = p*p-q; - const double eps=0.5*internal::get_eps(); - double discr_err = (6.0*(p*p)+3.0*fabs(q)+fabs(discr))*eps; - - std::vector x; // roots - if(fabs(discr)<=discr_err) { - // discriminant is zero --> one root - x.resize(1); - x[0] = -p; - } else if(discr<0) { - // no root - } else { - // two roots - x.resize(2); - x[0] = -p - sqrt(discr); - x[1] = -p + sqrt(discr); - } - - // improve solution via newton steps - for(size_t i=0; i1e-8) { - x[i] -= f/f1; - } - } - } - - return x; -} - -// solutions for the cubic equation: a + b*x +c*x^2 + d*x^3 = 0 -// this is a naive implementation of the analytic solution without -// optimisation for speed or numerical accuracy -// newton_iter: number of newton iterations to improve analytical solution -// see also -// gsl: gsl_poly_solve_cubic() in solve_cubic.c -// octave: roots.m - via eigenvalues of the Frobenius companion matrix -std::vector solve_cubic(double a, double b, double c, double d, - int newton_iter) -{ - if(d==0.0) { - return solve_quadratic(a,b,c,newton_iter); - } - - // convert to normalised form: a + bx + cx^2 + x^3 = 0 - if(d!=1.0) { - a/=d; - b/=d; - c/=d; - } - - // convert to depressed cubic: z^3 - 3pz - 2q = 0 - // via substitution: z = x + c/3 - std::vector z; // roots of the depressed cubic - double p = -(1.0/3.0)*b + (1.0/9.0)*(c*c); - double r = 2.0*(c*c)-9.0*b; - double q = -0.5*a - (1.0/54.0)*(c*r); - double discr=p*p*p-q*q; // discriminant - // calculating numerical round-off errors with assumptions: - // - each operation is precise but each intermediate result x - // when stored has max error of x*eps - // - only multiplication with a power of 2 introduces no new error - // - a,b,c,d and some fractions (e.g. 1/3) have rounding errors eps - // - p_err << |p|, q_err << |q|, ... (this is violated in rare cases) - // would be more elegant to use boost::numeric::interval - const double eps = internal::get_eps(); - double p_err = eps*((3.0/3.0)*fabs(b)+(4.0/9.0)*(c*c)+fabs(p)); - double r_err = eps*(6.0*(c*c)+18.0*fabs(b)+fabs(r)); - double q_err = 0.5*fabs(a)*eps + (1.0/54.0)*fabs(c)*(r_err+fabs(r)*3.0*eps) - + fabs(q)*eps; - double discr_err = (p*p) * (3.0*p_err + fabs(p)*2.0*eps) - + fabs(q) * (2.0*q_err + fabs(q)*eps) + fabs(discr)*eps; - - // depending on the discriminant we get different solutions - if(fabs(discr)<=discr_err) { - // discriminant zero: one or two real roots - if(fabs(p)<=p_err) { - // p and q are zero: single root - z.resize(1); - z[0] = 0.0; // triple root - } else { - z.resize(2); - z[0] = 2.0*q/p; // single root - z[1] = -0.5*z[0]; // double root - } - } else if(discr>0) { - // three real roots: via trigonometric solution - z.resize(3); - double ac = (1.0/3.0) * acos( q/(p*sqrt(p)) ); - double sq = 2.0*sqrt(p); - z[0] = sq * cos(ac); - z[1] = sq * cos(ac-2.0*M_PI/3.0); - z[2] = sq * cos(ac-4.0*M_PI/3.0); - } else if (discr<0.0) { - // single real root: via Cardano's fromula - z.resize(1); - double sgnq = (q >= 0 ? 1 : -1); - double basis = fabs(q) + sqrt(-discr); - double C = sgnq * pow(basis, 1.0/3.0); // c++11 has std::cbrt() - z[0] = C + p/C; - } - for(size_t i=0; i1e-8) { - z[i] -= f/f1; - } - } - } - // ensure if a=0 we get exactly x=0 as root - // TODO: remove this fudge - if(a==0.0) { - assert(z.size()>0); // cubic should always have at least one root - double xmin=fabs(z[0]); - size_t imin=0; - for(size_t i=1; ifabs(z[i])) { - xmin=fabs(z[i]); - imin=i; - } - } - z[imin]=0.0; // replace the smallest absolute value with 0 - } - std::sort(z.begin(), z.end()); - return z; -} - - -} // namespace internal - - -} // namespace tk - - -#if !defined(_MSC_VER) -#pragma GCC diagnostic pop -#endif - -#endif /* TK_SPLINE_H */ diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp index e472b20794..20377cfe8d 100644 --- a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp @@ -15,7 +15,6 @@ #include "../PrintConfig.hpp" #include "SmallAreaInfillFlowCompensator.hpp" -#include "spline/spline.h" #include namespace Slic3r { @@ -47,37 +46,43 @@ SmallAreaInfillFlowCompensator::SmallAreaInfillFlowCompensator(const Slic3r::GCo } } catch (...) { std::stringstream ss; - ss << "Error parsing data point in small area infill compensation model:" << line << std::endl; + ss << "Small Area Flow Compensation: Error parsing data point in small area infill compensation model:" << line << std::endl; throw Slic3r::InvalidArgument(ss.str()); } } } - for (int i = 0; i < eLengths.size(); i++) { + for (size_t i = 0; i < eLengths.size(); i++) { if (i == 0) { if (!nearly_equal(eLengths[i], 0.0)) { - throw Slic3r::InvalidArgument("First extrusion length for small area infill compensation model must be 0"); + throw Slic3r::InvalidArgument("Small Area Flow Compensation: First extrusion length for small area infill compensation model must be 0"); } } else { if (nearly_equal(eLengths[i], 0.0)) { - throw Slic3r::InvalidArgument("Only the first extrusion length for small area infill compensation model can be 0"); + throw Slic3r::InvalidArgument("Small Area Flow Compensation: Only the first extrusion length for small area infill compensation model can be 0"); } if (eLengths[i] <= eLengths[i - 1]) { - throw Slic3r::InvalidArgument("Extrusion lengths for subsequent points must be increasing"); + throw Slic3r::InvalidArgument("Small Area Flow Compensation: Extrusion lengths for subsequent points must be increasing"); } } } - if (!flowComps.empty() && !nearly_equal(flowComps.back(), 1.0)) { - throw Slic3r::InvalidArgument("Final compensation factor for small area infill flow compensation model must be 1.0"); + for (size_t i = 1; i < flowComps.size(); ++i) { + if (flowComps[i] <= flowComps[i - 1]) { + throw Slic3r::InvalidArgument("Small Area Flow Compensation: Flow compensation factors must strictly increase with extrusion length"); + } } - flowModel = std::make_unique(); - flowModel->set_points(eLengths, flowComps); + if (!flowComps.empty() && !nearly_equal(flowComps.back(), 1.0)) { + throw Slic3r::InvalidArgument("Small Area Flow Compensation: Final compensation factor for small area infill flow compensation model must be 1.0"); + } + + flowModel = std::make_unique(eLengths, flowComps); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Error parsing small area infill compensation model: " << e.what(); + throw; } } @@ -92,7 +97,7 @@ double SmallAreaInfillFlowCompensator::flow_comp_model(const double line_length) return 1.0; } - return (*flowModel)(line_length); + return flowModel->interpolate(line_length); } double SmallAreaInfillFlowCompensator::modify_flow(const double line_length, const double dE, const ExtrusionRole role) diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp index 1bfa5149f7..de1df98170 100644 --- a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp @@ -4,12 +4,9 @@ #include "../libslic3r.h" #include "../PrintConfig.hpp" #include "../ExtrusionEntity.hpp" +#include "PchipInterpolatorHelper.hpp" #include -namespace tk { -class spline; -} // namespace tk - namespace Slic3r { class SmallAreaInfillFlowCompensator @@ -26,8 +23,7 @@ private: std::vector eLengths; std::vector flowComps; - // TODO: Cubic Spline - std::unique_ptr flowModel; + std::unique_ptr flowModel; double flow_comp_model(const double line_length); From 0330e8600760f9185b98ffadf41f39a3b56e5872 Mon Sep 17 00:00:00 2001 From: yw4z Date: Tue, 30 Dec 2025 19:02:48 +0300 Subject: [PATCH 11/45] Introduce canvas menu (#11618) * init * update * Update GLCanvas3D.cpp * Update GLCanvas3D.cpp * cleanup * fix icon size --------- Co-authored-by: SoftFever --- resources/images/axis_toggle.svg | 167 ----------------- resources/images/axis_toggle_dark.svg | 167 ----------------- resources/images/axis_toggle_hover.svg | 167 ----------------- resources/images/axis_toggle_hover_dark.svg | 167 ----------------- resources/images/canvas_menu.svg | 1 + resources/images/canvas_menu_dark.svg | 1 + resources/images/canvas_menu_dark_hover.svg | 1 + resources/images/canvas_menu_hover.svg | 1 + resources/images/canvas_zoom.svg | 1 + resources/images/canvas_zoom_dark.svg | 1 + resources/images/canvas_zoom_dark_hover.svg | 1 + resources/images/canvas_zoom_hover.svg | 1 + src/libslic3r/AppConfig.cpp | 4 + src/slic3r/GUI/GLCanvas3D.cpp | 188 ++++++++++++++++---- src/slic3r/GUI/GLCanvas3D.hpp | 4 +- src/slic3r/GUI/GUI_App.hpp | 3 + src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 36 +++- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 12 +- 18 files changed, 209 insertions(+), 714 deletions(-) delete mode 100644 resources/images/axis_toggle.svg delete mode 100644 resources/images/axis_toggle_dark.svg delete mode 100644 resources/images/axis_toggle_hover.svg delete mode 100644 resources/images/axis_toggle_hover_dark.svg create mode 100644 resources/images/canvas_menu.svg create mode 100644 resources/images/canvas_menu_dark.svg create mode 100644 resources/images/canvas_menu_dark_hover.svg create mode 100644 resources/images/canvas_menu_hover.svg create mode 100644 resources/images/canvas_zoom.svg create mode 100644 resources/images/canvas_zoom_dark.svg create mode 100644 resources/images/canvas_zoom_dark_hover.svg create mode 100644 resources/images/canvas_zoom_hover.svg diff --git a/resources/images/axis_toggle.svg b/resources/images/axis_toggle.svg deleted file mode 100644 index 679c34e5ca..0000000000 --- a/resources/images/axis_toggle.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - diff --git a/resources/images/axis_toggle_dark.svg b/resources/images/axis_toggle_dark.svg deleted file mode 100644 index 08c52a8398..0000000000 --- a/resources/images/axis_toggle_dark.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - diff --git a/resources/images/axis_toggle_hover.svg b/resources/images/axis_toggle_hover.svg deleted file mode 100644 index 1d462ffb1d..0000000000 --- a/resources/images/axis_toggle_hover.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - diff --git a/resources/images/axis_toggle_hover_dark.svg b/resources/images/axis_toggle_hover_dark.svg deleted file mode 100644 index 14f9bd2767..0000000000 --- a/resources/images/axis_toggle_hover_dark.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - diff --git a/resources/images/canvas_menu.svg b/resources/images/canvas_menu.svg new file mode 100644 index 0000000000..b94a4952f0 --- /dev/null +++ b/resources/images/canvas_menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_menu_dark.svg b/resources/images/canvas_menu_dark.svg new file mode 100644 index 0000000000..6578d79a9c --- /dev/null +++ b/resources/images/canvas_menu_dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_menu_dark_hover.svg b/resources/images/canvas_menu_dark_hover.svg new file mode 100644 index 0000000000..e71a5c9787 --- /dev/null +++ b/resources/images/canvas_menu_dark_hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_menu_hover.svg b/resources/images/canvas_menu_hover.svg new file mode 100644 index 0000000000..83fbddee17 --- /dev/null +++ b/resources/images/canvas_menu_hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_zoom.svg b/resources/images/canvas_zoom.svg new file mode 100644 index 0000000000..5448cd7cee --- /dev/null +++ b/resources/images/canvas_zoom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_zoom_dark.svg b/resources/images/canvas_zoom_dark.svg new file mode 100644 index 0000000000..9e598f8cba --- /dev/null +++ b/resources/images/canvas_zoom_dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_zoom_dark_hover.svg b/resources/images/canvas_zoom_dark_hover.svg new file mode 100644 index 0000000000..6d7e4e5fcb --- /dev/null +++ b/resources/images/canvas_zoom_dark_hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/canvas_zoom_hover.svg b/resources/images/canvas_zoom_hover.svg new file mode 100644 index 0000000000..53f272d28d --- /dev/null +++ b/resources/images/canvas_zoom_hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index f91c83ad82..6c1b8622e4 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -314,6 +314,10 @@ void AppConfig::set_defaults() set("auto_calculate_flush","all"); } + if (get("show_canvas_zoom_button").empty()) { + set_bool("show_canvas_zoom_button", true); + } + if (get("remember_printer_config").empty()) { set_bool("remember_printer_config", true); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 00d15ddadd..ce859e1a7b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6044,6 +6044,7 @@ static const float cameraProjection[16] = {1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0. void GLCanvas3D::_render_3d_navigator() { if (!wxGetApp().show_3d_navigator()) { + m_canvas_toolbar_pos[0] = 0; return; } @@ -6090,7 +6091,7 @@ void GLCanvas3D::_render_3d_navigator() } const float size = 128 * sc; - m_axis_button_pos[0] = size - 10; + m_canvas_toolbar_pos[0] = size; const auto result = ImGuizmo::ViewManipulate(cameraView, cameraProjection, ImGuizmo::OPERATION::ROTATE, ImGuizmo::MODE::WORLD, nullptr, camDistance, ImVec2(viewManipulateLeft, viewManipulateTop - size), ImVec2(size, size), 0x00101010); @@ -6126,7 +6127,6 @@ void GLCanvas3D::_render_3d_navigator() request_extra_frame(); } - _render_camera_toolbar(); } #define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0 @@ -7989,6 +7989,8 @@ void GLCanvas3D::_render_overlays() m_labels.render(sorted_instances); _render_3d_navigator(); + + _render_canvas_toolbar(); } void GLCanvas3D::_render_style_editor() @@ -8627,47 +8629,169 @@ void GLCanvas3D::_render_return_toolbar() const imgui.end(); } -void GLCanvas3D::_render_camera_toolbar() +void GLCanvas3D::_render_canvas_toolbar() { - float font_size = ImGui::GetFontSize(); - float sc = get_scale(); - ImVec2 button_icon_size = ImVec2(font_size * 2.5, font_size * 2.5); + ImGuiWrapper &imgui = *wxGetApp().imgui(); + float sc = get_scale(); - ImGuiWrapper &imgui = *wxGetApp().imgui(); - float window_width = button_icon_size.x + imgui.scaled(2.0f); - float window_height = button_icon_size.y + imgui.scaled(2.0f); + #ifdef WIN32 + const int dpi = get_dpi_for_window(wxGetApp().GetTopWindow()); + sc *= (float) dpi / (float) DPI_DEFAULT; + #endif // WIN32 - Size cnv_size = get_canvas_size(); - m_axis_button_pos[1] = cnv_size.get_height() - button_icon_size[1] - 20 * sc; - imgui.set_next_window_pos(m_axis_button_pos[0], m_axis_button_pos[1], ImGuiCond_Always, 0, 0); -#ifdef __WINDOWS__ - imgui.set_next_window_size(window_width, window_height, ImGuiCond_Always); -#endif + ImVec2 btn_size = ImVec2(36.f, 36.f) * sc; + ImVec2 margin = ImVec2(m_canvas_toolbar_pos[0] > 0 ? 0.f : (10.f * sc), 10.f * sc); + ImVec2 spacing = ImVec2(6.f, 6.f) * sc; + ImVec2 padding = ImVec2(2.f, 2.f) * sc; + Vec2i32 pos = { + m_canvas_toolbar_pos[0] + margin.x, + get_canvas_size().get_height() - margin.y + }; + bool zoom_btn = wxGetApp().show_canvas_zoom_button(); - imgui.begin(_L("Toggle Axis"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | + imgui.set_next_window_pos(pos[0], pos[1], ImGuiCond_Always, 0, 1); // pivot bottom-left + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0 ); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding , {0,0}); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , {0,0}); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , padding); // without padding images clipping + + imgui.begin(_L("Canvas Toolbar"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);// - ImTextureID normal_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_AXIS_TOGGLE_DARK : GLGizmosManager::MENU_ICON_NAME::IC_AXIS_TOGGLE); - ImTextureID hover_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_AXIS_TOGGLE_DARK_HOVER : GLGizmosManager::MENU_ICON_NAME::IC_AXIS_TOGGLE_HOVER); + ImTextureID m_normal_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_MENU_DARK : GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_MENU); + ImTextureID m_hover_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_MENU_DARK_HOVER : GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_MENU_HOVER); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {0, 0}); - - if (ImGui::ImageButton3(normal_id, hover_id, button_icon_size, ImVec2(0, 0), ImVec2(1, 1), -1, - ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1), ImVec2(10, 0))) { - //select_view("plate"); - - if (m_canvas_type == ECanvasType::CanvasView3D || m_canvas_type == ECanvasType::CanvasPreview) { - toggle_world_axes_visibility(false); + if (ImGui::ImageButton3(m_normal_id, m_hover_id, btn_size)) { + if(!ImGui::IsPopupOpen("CanvasToolbarMenu")){ + ImGui::SetNextWindowPos(ImVec2(pos[0] + padding.x, pos[1] - padding.y - (zoom_btn ? (btn_size.y + spacing.y) : 0.f)), ImGuiCond_Always, ImVec2(0, 1)); // pivot bottom-left + ImGui::OpenPopup("CanvasToolbarMenu"); } + } + if(zoom_btn){ + ImGui::Dummy({ 0, spacing.y}); + + ImTextureID z_normal_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_ZOOM_DARK : GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_ZOOM); + ImTextureID z_hover_id = m_gizmos.get_icon_texture_id(m_is_dark ? GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_ZOOM_DARK_HOVER : GLGizmosManager::MENU_ICON_NAME::IC_CANVAS_ZOOM_HOVER); + + if (ImGui::ImageButton3(z_normal_id, z_hover_id, btn_size)) { + select_view("plate"); + if (m_selection.is_empty()) { + if (m_canvas_type == ECanvasType::CanvasAssembleView) + zoom_to_volumes(); + else + zoom_to_bed(); + } else { + zoom_to_selection(); + } + } else if (ImGui::IsItemHovered()) { + auto tooltip = _L("Fit camera to scene or selected object."); + auto width = ImGui::CalcTextSize(tooltip.c_str()).x + imgui.scaled(2.0f); + imgui.tooltip(tooltip, width); + } } - if (ImGui::IsItemHovered()) { - auto temp_tooltip = _L("Toggle Axis"); - auto width = ImGui::CalcTextSize(temp_tooltip.c_str()).x + imgui.scaled(2.0f); - imgui.tooltip(temp_tooltip, width); + + ImGui::PopStyleVar(4); // Window + + ImGui::PushStyleColor(ImGuiCol_PopupBg , m_is_dark ? ImGuiWrapper::COL_TOOLBAR_BG_DARK : ImGuiWrapper::COL_TOOLBAR_BG); + ImGui::PushStyleColor(ImGuiCol_Separator , m_is_dark ? ImVec4(1, 1, 1, .20f) : ImVec4(0, 0, 0, .2f)); + ImGui::PushStyleColor(ImGuiCol_Text , m_is_dark ? ImVec4(1, 1, 1, .88f) : ImVec4(50 / 255.f, 58 / 255.f, 61 / 255.f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_TextDisabled , m_is_dark ? ImVec4(1, 1, 1, .44f) : ImVec4(50 / 255.f, 58 / 255.f, 61 / 255.f, .5f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered , ImVec4(0, 0, 0, 0.f)); // bg color for menu item + ImGui::PushStyleColor(ImGuiCol_BorderActive , ImGuiWrapper::COL_ORCA); + ImGui::PushStyleVar(ImGuiStyleVar_PopupBorderSize, 0.f ); + ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding , 8.f * sc); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f * sc); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding , 2.f * sc); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , ImVec2(4.f, 10.f) * sc); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , ImVec2(0.f, 8.f ) * sc); + + if (ImGui::BeginPopup("CanvasToolbarMenu")) { + ImGui::PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true); + + Plater* p = wxGetApp().plater(); + AppConfig* cfg = wxGetApp().app_config; + + auto create_menu_item = [this, sc]( + const std::string& name, + bool enable, + bool condition, + const std::function& action + ) { + ImGui::Dummy({2.f * sc,0}); + ImGui::SameLine(); + if (ImGui::BBLMenuItem((" " + _u8L(name)).c_str(), nullptr, false, enable, ImGui::CalcTextSize(_u8L(name).c_str()).y)) + action(); + ImGui::SameLine(12.f * sc); + ImGui::TextColored(enable ? ImVec4(1,1,1,1) : ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled), "%s", into_u8(condition ? ImGui::VisibleIcon : ImGui::HiddenIcon).c_str()); + }; + + create_menu_item( "3D Navigator", + m_canvas_type != ECanvasType::CanvasAssembleView, // not work on assembly + wxGetApp().show_3d_navigator(), + [this]{ + wxGetApp().toggle_show_3d_navigator(); + ImGui::CloseCurrentPopup(); // Close popup to show changes on UI + } + ); + + create_menu_item( "Zoom button", + true, // work on all + wxGetApp().show_canvas_zoom_button(), + [this]{ + wxGetApp().toggle_canvas_zoom_button(); + ImGui::CloseCurrentPopup(); // Close popup to show changes on UI + } + ); + + ImGui::Separator(); + + create_menu_item( "Overhangs", + m_canvas_type == ECanvasType::CanvasView3D, // work only on prepare + p->is_view3D_overhang_shown(), + [this, p]{p->show_view3D_overhang(!p->is_view3D_overhang_shown());} + ); + + create_menu_item( "Outline", + m_canvas_type != ECanvasType::CanvasPreview, // not work on preview + wxGetApp().show_outline(), + [this]{wxGetApp().toggle_show_outline();} + ); + + ImGui::Separator(); + + create_menu_item( "Perspective", + true, // work on all + cfg->get_bool("use_perspective_camera"), + [this, &cfg]{ + cfg->set_bool("use_perspective_camera", !(cfg->get_bool("use_perspective_camera"))); + wxGetApp().update_ui_from_settings(); + } + ); + + ImGui::Separator(); + + create_menu_item( "Axes", + m_canvas_type != ECanvasType::CanvasAssembleView, // not work on assembly + m_show_world_axes, + [this]{toggle_world_axes_visibility(false);} + ); + + // will add an option for gridlines in here + + create_menu_item( "Labels", + m_canvas_type == ECanvasType::CanvasView3D, // work only on prepare + p->are_view3D_labels_shown(), + [this, p]{p->show_view3D_labels(!p->are_view3D_labels_shown());} + ); + + ImGui::PopItemFlag(); + ImGui::EndPopup(); } - ImGui::PopStyleVar(2); + + ImGui::PopStyleColor(6); + ImGui::PopStyleVar(6); imgui.end(); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index aab67615d9..6931b305d6 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -543,7 +543,7 @@ private: mutable IMToolbar m_sel_plate_toolbar; mutable GLToolbar m_assemble_view_toolbar; mutable IMReturnToolbar m_return_toolbar; - mutable Vec2i32 m_axis_button_pos = {128, 5}; + mutable Vec2i32 m_canvas_toolbar_pos = {140, 5}; mutable float m_sc{1}; mutable float m_paint_toolbar_width; @@ -1246,7 +1246,7 @@ private: void _render_imgui_select_plate_toolbar(); void _render_assemble_view_toolbar() const; void _render_return_toolbar() const; - void _render_camera_toolbar(); + void _render_canvas_toolbar(); void _render_separator_toolbar_right() const; void _render_separator_toolbar_left() const; void _render_collapse_toolbar() const; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index f3900f6128..fbf61a5084 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -355,6 +355,9 @@ public: bool show_3d_navigator() const { return app_config->get_bool("show_3d_navigator"); } void toggle_show_3d_navigator() const { app_config->set_bool("show_3d_navigator", !show_3d_navigator()); } + bool show_canvas_zoom_button() const { return app_config->get_bool("show_canvas_zoom_button"); } + void toggle_canvas_zoom_button() const { app_config->set_bool("show_canvas_zoom_button", !show_canvas_zoom_button()); } + bool show_outline() const { return app_config->get_bool("show_outline"); } void toggle_show_outline() const { app_config->set_bool("show_outline", !show_outline()); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 04e65fc88a..0ca62d849a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -281,23 +281,43 @@ bool GLGizmosManager::init_icon_textures() else return false; - if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/axis_toggle.svg", 64, 64, texture_id)) - icon_list.insert(std::make_pair((int) IC_AXIS_TOGGLE, texture_id)); + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_menu.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_MENU, texture_id)); else return false; - if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/axis_toggle_hover.svg", 64, 64, texture_id)) - icon_list.insert(std::make_pair((int) IC_AXIS_TOGGLE_HOVER, texture_id)); + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_menu_hover.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_MENU_HOVER, texture_id)); else return false; - if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/axis_toggle_dark.svg", 64, 64, texture_id)) - icon_list.insert(std::make_pair((int) IC_AXIS_TOGGLE_DARK, texture_id)); + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_menu_dark.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_MENU_DARK, texture_id)); else return false; - if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/axis_toggle_hover_dark.svg", 64, 64, texture_id)) - icon_list.insert(std::make_pair((int) IC_AXIS_TOGGLE_DARK_HOVER, texture_id)); + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_menu_dark_hover.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_MENU_DARK_HOVER, texture_id)); + else + return false; + + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_zoom.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_ZOOM, texture_id)); + else + return false; + + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_zoom_hover.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_ZOOM_HOVER, texture_id)); + else + return false; + + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_zoom_dark.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_ZOOM_DARK, texture_id)); + else + return false; + + if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/canvas_zoom_dark_hover.svg", 72, 72, texture_id)) + icon_list.insert(std::make_pair((int) IC_CANVAS_ZOOM_DARK_HOVER, texture_id)); else return false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index ba7d5afdb9..5897c2a512 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -170,10 +170,14 @@ public: IC_TOOLBAR_TOOLTIP, IC_TOOLBAR_TOOLTIP_HOVER, IC_NAME_COUNT, - IC_AXIS_TOGGLE, - IC_AXIS_TOGGLE_HOVER, - IC_AXIS_TOGGLE_DARK, - IC_AXIS_TOGGLE_DARK_HOVER, + IC_CANVAS_MENU, + IC_CANVAS_MENU_HOVER, + IC_CANVAS_MENU_DARK, + IC_CANVAS_MENU_DARK_HOVER, + IC_CANVAS_ZOOM, + IC_CANVAS_ZOOM_HOVER, + IC_CANVAS_ZOOM_DARK, + IC_CANVAS_ZOOM_DARK_HOVER, }; explicit GLGizmosManager(GLCanvas3D& parent); From 7c91459c371f85aa1a38f74fa1b9268c43d74959 Mon Sep 17 00:00:00 2001 From: Ian Bassi Date: Tue, 30 Dec 2025 13:16:47 -0300 Subject: [PATCH 12/45] Emit Disable Power Loss Recovery (#11616) * Emit Disable Power Loss Recovery Now only works if it's enabled but the goal it's to force disable it. With this change it will always emit the command for BBL or Marlin 2. Co-Authored-By: Michael Rook <54159303+michaelr0@users.noreply.github.com> * Refactor power loss recovery G-code comments * Return empty power loss recovery when no compatible printer * Update power loss recovery comments Update label and tooltip for power loss recovery * Add enum for power loss recovery mode Refactored power loss recovery configuration to use a new PowerLossRecoveryMode enum instead of a boolean. Updated GCodeWriter and related logic to handle the new enum, allowing for 'printer_configuration', 'enable', and 'disable' options. Updated config handling, legacy value conversion, and default values accordingly. * Update PrintConfig.cpp --------- Co-authored-by: Michael Rook <54159303+michaelr0@users.noreply.github.com> Co-authored-by: SoftFever --- .../BBL/machine/fdm_machine_common.json | 2 +- src/libslic3r/GCode.cpp | 20 ++++++------- src/libslic3r/GCodeWriter.cpp | 21 ++++++++----- src/libslic3r/GCodeWriter.hpp | 2 +- src/libslic3r/PrintConfig.cpp | 30 ++++++++++++++++--- src/libslic3r/PrintConfig.hpp | 10 ++++++- 6 files changed, 60 insertions(+), 25 deletions(-) diff --git a/resources/profiles/BBL/machine/fdm_machine_common.json b/resources/profiles/BBL/machine/fdm_machine_common.json index 0073ac6a8a..566d3960ed 100644 --- a/resources/profiles/BBL/machine/fdm_machine_common.json +++ b/resources/profiles/BBL/machine/fdm_machine_common.json @@ -136,7 +136,7 @@ "60" ], "scan_first_layer": "0", - "enable_power_loss_recovery": "1", + "enable_power_loss_recovery": "printer_configuration", "silent_mode": "0", "single_extruder_multi_material": "1", "support_air_filtration": "0", diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 707dadd9f9..0e07e3fdb8 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3084,10 +3084,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_sorted_layer_filaments.emplace_back(lt.extruders); } - // Orca: finish tracking power lost recovery + // Orca: disable power loss recovery if it was enabled earlier { - if (m_second_layer_things_done && print.config().enable_power_loss_recovery.value == true) { - file.write(m_writer.enable_power_loss_recovery(false)); + const auto plr_mode = print.config().enable_power_loss_recovery.value; + if (m_second_layer_things_done && plr_mode == PowerLossRecoveryMode::Enable) { + file.write(m_writer.enable_power_loss_recovery(PowerLossRecoveryMode::Disable)); } } ++ finished_objects; @@ -3165,9 +3166,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_sorted_layer_filaments.emplace_back(lt.extruders); } - // Orca: finish tracking power lost recovery - if (m_second_layer_things_done && print.config().enable_power_loss_recovery.value == true) { - file.write(m_writer.enable_power_loss_recovery(false)); + // Orca: disable power loss recovery + if (m_second_layer_things_done && print.config().enable_power_loss_recovery.value == PowerLossRecoveryMode::Enable) { + file.write(m_writer.enable_power_loss_recovery(PowerLossRecoveryMode::Disable)); } if (m_wipe_tower) // Purge the extruder, pull out the active filament. @@ -4381,10 +4382,9 @@ LayerResult GCode::process_layer( } if (!first_layer && !m_second_layer_things_done) { - // Orca: start tracking power lost recovery - if (print.config().enable_power_loss_recovery.value == true) { - gcode += m_writer.enable_power_loss_recovery(true); - } + // Orca: set power loss recovery + const auto plr_mode = print.config().enable_power_loss_recovery.value; + gcode += m_writer.enable_power_loss_recovery(plr_mode); if (print.is_BBL_printer()) { // BBS: open first layer inspection at second layer diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index f3d218750b..1008e5eab1 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -444,23 +444,28 @@ std::string GCodeWriter::reset_e(bool force) } } -std::string GCodeWriter::enable_power_loss_recovery(bool enable) +std::string GCodeWriter::enable_power_loss_recovery(PowerLossRecoveryMode mode) { std::ostringstream gcode; - + + if (mode == PowerLossRecoveryMode::PrinterConfiguration) + return std::string(); + + const bool enable = mode == PowerLossRecoveryMode::Enable; + if (m_is_bbl_printers) { - gcode << "; start tracking Power Loss Recovery https://wiki.bambulab.com/en/knowledge-sharing/power-loss-recovery\n"; - gcode << "M1003 S" << (enable ? "1" : "0") << "\n"; + gcode << "M1003 S" << (enable ? "1" : "0"); } else if (FLAVOR_IS(gcfMarlinFirmware)) { - gcode << "; start tracking Power-loss Recovery https://marlinfw.org/docs/gcode/M413.html\n"; - gcode << "M413 S" << (enable ? "1" : "0") << "\n"; + gcode << "M413 S" << (enable ? "1" : "0"); + } else { + return std::string(); } - + if (GCodeWriter::full_gcode_comment) gcode << " ; set Power-loss Recovery"; + gcode << "\n"; return gcode.str(); } - std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, bool allow_100) const { if (FLAVOR_IS_NOT(gcfMakerWare) && FLAVOR_IS_NOT(gcfSailfish)) diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 32e737164d..dbc64694e2 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -61,7 +61,7 @@ public: std::string set_input_shaping(char axis, float damp, float freq, std::string type) const; std::string reset_e(bool force = false); std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const; - std::string enable_power_loss_recovery(bool enable); + std::string enable_power_loss_recovery(PowerLossRecoveryMode mode); // return false if this extruder was already selected bool need_toolchange(unsigned int filament_id) const; std::string set_extruder(unsigned int filament_id); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 054a57f797..7549eb821d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -161,6 +161,14 @@ static t_config_enum_values s_keys_map_BedTempFormula { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BedTempFormula) +// Orca +static t_config_enum_values s_keys_map_PowerLossRecoveryMode { + { "printer_configuration", int(PowerLossRecoveryMode::PrinterConfiguration) }, + { "enable", int(PowerLossRecoveryMode::Enable) }, + { "disable", int(PowerLossRecoveryMode::Disable) } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PowerLossRecoveryMode) + static t_config_enum_values s_keys_map_FuzzySkinType { { "none", int(FuzzySkinType::None) }, { "external", int(FuzzySkinType::External) }, @@ -3376,11 +3384,18 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(false)); // Orca - def = this->add("enable_power_loss_recovery", coBool); - def->label = L("Turn on Power Loss Recovery"); - def->tooltip = L("Enable this to insert power loss recovery commands in generated G-code.(Only for Bambu Lab printers and Marlin firmware based printers)"); + def = this->add("enable_power_loss_recovery", coEnum); + def->label = L("Power Loss Recovery"); + def->tooltip = L("Choose how to control power loss recovery. When set to Printer configuration, the slicer will not emit power loss recovery G-code and will leave the printer's configuration unchanged. Applicable to Bambu Lab or Marlin 2 firmware based printers."); def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("printer_configuration"); + def->enum_values.push_back("enable"); + def->enum_values.push_back("disable"); + def->enum_labels.push_back(L("Printer configuration")); + def->enum_labels.push_back(L("Enable")); + def->enum_labels.push_back(L("Disable")); + def->set_default_value(new ConfigOptionEnum(PowerLossRecoveryMode::PrinterConfiguration)); //BBS // def = this->add("spaghetti_detector", coBool); @@ -7442,6 +7457,13 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va else if (opt_key == "extruder_type") { ReplaceString(value, "DirectDrive", "Direct Drive"); } + else if (opt_key == "enable_power_loss_recovery") { + if (value == "1" || boost::iequals(value, "true")) { + value = "enable"; + } else if (value == "0" || boost::iequals(value, "false")) { + value = "disable"; + } + } else if(opt_key == "ensure_vertical_shell_thickness") { if(value == "1") { value = "ensure_all"; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 1dac4b7057..998764f292 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -102,6 +102,13 @@ enum class BedTempFormula { count, }; +// Orca +enum class PowerLossRecoveryMode { + PrinterConfiguration, + Enable, + Disable, +}; + // BBS enum class WallSequence { InnerOuter, @@ -507,6 +514,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PowerLossRecoveryMode) #undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS @@ -1272,7 +1280,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionIntsNullable, filament_flush_temp)) // BBS ((ConfigOptionBool, scan_first_layer)) - ((ConfigOptionBool, enable_power_loss_recovery)) + ((ConfigOptionEnum, enable_power_loss_recovery)) ((ConfigOptionBool, enable_wrapping_detection)) ((ConfigOptionInt, wrapping_detection_layers)) ((ConfigOptionPoints, wrapping_exclude_area)) From 32cf44fc0a43ca77d7b81680b23835bd14914083 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Wed, 31 Dec 2025 23:36:32 +0800 Subject: [PATCH 13/45] Don't emit the preheat command if ooze_prevention is disabled. (#11791) --- src/libslic3r/GCode/GCodeProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 9f7687d2c6..bd413d3782 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1846,7 +1846,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config) // sanity check if(m_preheat_steps < 1) m_preheat_steps = 1; - m_result.backtrace_enabled = m_preheat_time > 0 && (m_is_XL_printer || (!m_single_extruder_multi_material && filament_count > 1)); + m_result.backtrace_enabled = config.ooze_prevention && m_preheat_time > 0 && (m_is_XL_printer || (!m_single_extruder_multi_material && filament_count > 1)); assert(config.nozzle_volume.size() == config.nozzle_diameter.size()); m_nozzle_volume.resize(config.nozzle_volume.size()); From 69861b57f9ceeff531228e2989749c6a79c54c4a Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Thu, 1 Jan 2026 05:23:46 +0800 Subject: [PATCH 14/45] Fix float number not working properly for option min/max (#11211) * ConfigOptionDef: min/max values type are changed from INT to FLOAT. (cherry picked from commit f277bc80c22e0c9a067481a4301922e2c96aed47) * Fix infinite loop and crash when `fuzzy_skin_point_distance` = 0 (SoftFever/OrcaSlicer#11069) * Fix Linux build issue * Fix float comparison due to precision loss --- src/libslic3r/Config.cpp | 13 +++++++++++++ src/libslic3r/Config.hpp | 8 +++++--- src/libslic3r/PrintConfig.cpp | 16 ++++++++-------- src/slic3r/GUI/Field.cpp | 18 +++++++++--------- src/slic3r/GUI/Widgets/SpinInput.hpp | 3 +++ 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index ce1a8d6799..d43d1ca1a3 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -318,6 +318,19 @@ ConfigOption* ConfigOptionDef::create_default_option() const return this->create_empty_option(); } +bool ConfigOptionDef::is_value_valid(const double value, const int max_precision /*= 4*/) const +{ + if (this->min == 0.f && value < 0) { // Special handling of 0 + return false; + } + + const double ep = std::pow(0.1, max_precision); + if (is_approx(value, (double) this->min, ep) || is_approx(value, (double) this->max, ep)) + return true; + + return this->min <= value && value <= this->max; +} + // Assignment of the serialization IDs is not thread safe. The Defs shall be initialized from the main thread! ConfigOptionDef* ConfigDef::add(const t_config_option_key &opt_key, ConfigOptionType type) { diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index f99b07c8d2..1c7a2dcd67 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -2455,10 +2456,11 @@ public: // Optional width of an input field. int width = -1; // limit of a numeric input. - // If not set, the is set to + // If not set, the is set to <-FLT_MAX, FLT_MAX> // By setting min=0, only nonnegative input is allowed. - int min = INT_MIN; - int max = INT_MAX; + float min = -FLT_MAX; + float max = FLT_MAX; + bool is_value_valid(double value, int max_precision = 4) const; // To check if it's not a typo and a % is missing double max_literal = 1; ConfigOptionMode mode = comSimple; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7549eb821d..290d89edc5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2150,7 +2150,7 @@ void PrintConfigDef::init_fff_params() "\n\nThe final object flow ratio is this value multiplied by the filament flow ratio."); def->mode = comAdvanced; def->max = 2; - def->min = 0.01; + def->min = 0.01f; def->set_default_value(new ConfigOptionFloat(1)); def = this->add("enable_pressure_advance", coBools); @@ -3245,7 +3245,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Others"); def->tooltip = L("The average distance between the random points introduced on each line segment."); def->sidetext = L("mm"); // milimeters, CIS languages need translation - def->min = 0; + def->min = 0.01f; // point distance cannot be 0! Otherwise we get infinite loop + OOM due to infinite line division. def->max = 5; def->mode = comSimple; def->set_default_value(new ConfigOptionFloat(0.3)); @@ -3308,7 +3308,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Others"); def->tooltip = L("The base size of the coherent noise features, in mm. Higher values will result in larger features."); def->sidetext = L("mm"); // milimeters, CIS languages need translation - def->min = 0.1; + def->min = 0.1f; def->max = 500; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(1.0)); @@ -3326,7 +3326,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Fuzzy skin noise persistence"); def->category = L("Others"); def->tooltip = L("The decay rate for higher octaves of the coherent noise. Lower values will result in smoother noise."); - def->min = 0.01; + def->min = 0.01f; def->max = 1; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.5)); @@ -9555,13 +9555,13 @@ std::map validate(const FullPrintConfig &cfg, bool und case coFloatOrPercent: { auto *fopt = static_cast(opt); - out_of_range = fopt->value < optdef->min || fopt->value > optdef->max; + out_of_range = !optdef->is_value_valid(fopt->value); break; } case coFloats: case coPercents: for (double v : static_cast*>(opt)->values) - if (v < optdef->min || v > optdef->max) { + if (!optdef->is_value_valid(v)) { out_of_range = true; break; } @@ -9569,12 +9569,12 @@ std::map validate(const FullPrintConfig &cfg, bool und case coInt: { auto *iopt = static_cast(opt); - out_of_range = iopt->value < optdef->min || iopt->value > optdef->max; + out_of_range = !optdef->is_value_valid(iopt->value); break; } case coInts: for (int v : static_cast*>(opt)->values) - if (v < optdef->min || v > optdef->max) { + if (!optdef->is_value_valid(v)) { out_of_range = true; break; } diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 55f754e91a..0bd3874af5 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -309,7 +309,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true show_error(m_parent, _(L("Invalid numeric."))); set_value(double_to_string(val), true); } - if (m_opt.min > val || val > m_opt.max) + if (!m_opt.is_value_valid(val)) { if (!check_value) { m_value.clear(); @@ -1107,8 +1107,8 @@ void SpinCtrl::BUILD() { break; } - const int min_val = m_opt.min == INT_MIN ? 0 : m_opt.min; - const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; + const int min_val = m_opt.min == -FLT_MAX ? 0 : (int)m_opt.min; + const int max_val = m_opt.max < FLT_MAX ? (int)m_opt.max : INT_MAX; static Builder builder; auto temp = builder.build(m_parent, "", "", wxDefaultPosition, size, @@ -1164,7 +1164,7 @@ void SpinCtrl::BUILD() { if (!parsed || value < INT_MIN || value > INT_MAX) tmp_value = UNDEF_VALUE; else { - tmp_value = std::min(std::max((int)value, m_opt.min), m_opt.max); + tmp_value = std::min(std::max((int)value, temp->GetMin()), temp->GetMax()); #ifdef __WXOSX__ #ifdef UNDEFINED__WXOSX__ // BBS // Forcibly set the input value for SpinControl, since the value @@ -1217,7 +1217,7 @@ void SpinCtrl::set_value(const boost::any& value, bool change_event) { m_disable_change_event = !change_event; m_value = value; if (value.empty()) { // BBS: null value - dynamic_cast(window)->SetValue(m_opt.min); + dynamic_cast(window)->SetValue(dynamic_cast(window)->GetMin()); dynamic_cast(window)->GetTextCtrl()->SetValue(""); } else { @@ -2158,8 +2158,8 @@ boost::any& PointCtrl::get_value() show_error(m_parent, _L("Invalid numeric.")); } else - if (m_opt.min > x || x > m_opt.max || - m_opt.min > y || y > m_opt.max) + if (!m_opt.is_value_valid(x) || + !m_opt.is_value_valid(y)) { if (m_opt.min > x) x = m_opt.min; if (x > m_opt.max) x = m_opt.max; @@ -2218,8 +2218,8 @@ void SliderCtrl::BUILD() auto temp = new wxBoxSizer(wxHORIZONTAL); auto def_val = m_opt.get_default_value()->value; - auto min = m_opt.min == INT_MIN ? 0 : m_opt.min; - auto max = m_opt.max == INT_MAX ? 100 : m_opt.max; + auto min = m_opt.min == -FLT_MAX ? 0 : (int)m_opt.min; + auto max = m_opt.max == FLT_MAX ? 100 : INT_MAX; m_slider = new wxSlider(m_parent, wxID_ANY, def_val * m_scale, min * m_scale, max * m_scale, diff --git a/src/slic3r/GUI/Widgets/SpinInput.hpp b/src/slic3r/GUI/Widgets/SpinInput.hpp index 030eb56942..275d42a95d 100644 --- a/src/slic3r/GUI/Widgets/SpinInput.hpp +++ b/src/slic3r/GUI/Widgets/SpinInput.hpp @@ -78,6 +78,9 @@ public: void SetRange(int min, int max); + int GetMin() const { return this->min; } + int GetMax() const { return this->max; } + protected: void DoSetToolTipText(wxString const &tip) override; From 263b5928855d3261a6057ac42181477b013eeb04 Mon Sep 17 00:00:00 2001 From: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Wed, 31 Dec 2025 22:37:58 +0000 Subject: [PATCH 15/45] Revert "Fix float number not working properly for option min/max" (#11794) Revert "Fix float number not working properly for option min/max (#11211)" This reverts commit 69861b57f9ceeff531228e2989749c6a79c54c4a. --- src/libslic3r/Config.cpp | 13 ------------- src/libslic3r/Config.hpp | 8 +++----- src/libslic3r/PrintConfig.cpp | 16 ++++++++-------- src/slic3r/GUI/Field.cpp | 18 +++++++++--------- src/slic3r/GUI/Widgets/SpinInput.hpp | 3 --- 5 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index d43d1ca1a3..ce1a8d6799 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -318,19 +318,6 @@ ConfigOption* ConfigOptionDef::create_default_option() const return this->create_empty_option(); } -bool ConfigOptionDef::is_value_valid(const double value, const int max_precision /*= 4*/) const -{ - if (this->min == 0.f && value < 0) { // Special handling of 0 - return false; - } - - const double ep = std::pow(0.1, max_precision); - if (is_approx(value, (double) this->min, ep) || is_approx(value, (double) this->max, ep)) - return true; - - return this->min <= value && value <= this->max; -} - // Assignment of the serialization IDs is not thread safe. The Defs shall be initialized from the main thread! ConfigOptionDef* ConfigDef::add(const t_config_option_key &opt_key, ConfigOptionType type) { diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 1c7a2dcd67..f99b07c8d2 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -2456,11 +2455,10 @@ public: // Optional width of an input field. int width = -1; // limit of a numeric input. - // If not set, the is set to <-FLT_MAX, FLT_MAX> + // If not set, the is set to // By setting min=0, only nonnegative input is allowed. - float min = -FLT_MAX; - float max = FLT_MAX; - bool is_value_valid(double value, int max_precision = 4) const; + int min = INT_MIN; + int max = INT_MAX; // To check if it's not a typo and a % is missing double max_literal = 1; ConfigOptionMode mode = comSimple; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 290d89edc5..7549eb821d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2150,7 +2150,7 @@ void PrintConfigDef::init_fff_params() "\n\nThe final object flow ratio is this value multiplied by the filament flow ratio."); def->mode = comAdvanced; def->max = 2; - def->min = 0.01f; + def->min = 0.01; def->set_default_value(new ConfigOptionFloat(1)); def = this->add("enable_pressure_advance", coBools); @@ -3245,7 +3245,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Others"); def->tooltip = L("The average distance between the random points introduced on each line segment."); def->sidetext = L("mm"); // milimeters, CIS languages need translation - def->min = 0.01f; // point distance cannot be 0! Otherwise we get infinite loop + OOM due to infinite line division. + def->min = 0; def->max = 5; def->mode = comSimple; def->set_default_value(new ConfigOptionFloat(0.3)); @@ -3308,7 +3308,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Others"); def->tooltip = L("The base size of the coherent noise features, in mm. Higher values will result in larger features."); def->sidetext = L("mm"); // milimeters, CIS languages need translation - def->min = 0.1f; + def->min = 0.1; def->max = 500; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(1.0)); @@ -3326,7 +3326,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Fuzzy skin noise persistence"); def->category = L("Others"); def->tooltip = L("The decay rate for higher octaves of the coherent noise. Lower values will result in smoother noise."); - def->min = 0.01f; + def->min = 0.01; def->max = 1; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0.5)); @@ -9555,13 +9555,13 @@ std::map validate(const FullPrintConfig &cfg, bool und case coFloatOrPercent: { auto *fopt = static_cast(opt); - out_of_range = !optdef->is_value_valid(fopt->value); + out_of_range = fopt->value < optdef->min || fopt->value > optdef->max; break; } case coFloats: case coPercents: for (double v : static_cast*>(opt)->values) - if (!optdef->is_value_valid(v)) { + if (v < optdef->min || v > optdef->max) { out_of_range = true; break; } @@ -9569,12 +9569,12 @@ std::map validate(const FullPrintConfig &cfg, bool und case coInt: { auto *iopt = static_cast(opt); - out_of_range = !optdef->is_value_valid(iopt->value); + out_of_range = iopt->value < optdef->min || iopt->value > optdef->max; break; } case coInts: for (int v : static_cast*>(opt)->values) - if (!optdef->is_value_valid(v)) { + if (v < optdef->min || v > optdef->max) { out_of_range = true; break; } diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 0bd3874af5..55f754e91a 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -309,7 +309,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true show_error(m_parent, _(L("Invalid numeric."))); set_value(double_to_string(val), true); } - if (!m_opt.is_value_valid(val)) + if (m_opt.min > val || val > m_opt.max) { if (!check_value) { m_value.clear(); @@ -1107,8 +1107,8 @@ void SpinCtrl::BUILD() { break; } - const int min_val = m_opt.min == -FLT_MAX ? 0 : (int)m_opt.min; - const int max_val = m_opt.max < FLT_MAX ? (int)m_opt.max : INT_MAX; + const int min_val = m_opt.min == INT_MIN ? 0 : m_opt.min; + const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; static Builder builder; auto temp = builder.build(m_parent, "", "", wxDefaultPosition, size, @@ -1164,7 +1164,7 @@ void SpinCtrl::BUILD() { if (!parsed || value < INT_MIN || value > INT_MAX) tmp_value = UNDEF_VALUE; else { - tmp_value = std::min(std::max((int)value, temp->GetMin()), temp->GetMax()); + tmp_value = std::min(std::max((int)value, m_opt.min), m_opt.max); #ifdef __WXOSX__ #ifdef UNDEFINED__WXOSX__ // BBS // Forcibly set the input value for SpinControl, since the value @@ -1217,7 +1217,7 @@ void SpinCtrl::set_value(const boost::any& value, bool change_event) { m_disable_change_event = !change_event; m_value = value; if (value.empty()) { // BBS: null value - dynamic_cast(window)->SetValue(dynamic_cast(window)->GetMin()); + dynamic_cast(window)->SetValue(m_opt.min); dynamic_cast(window)->GetTextCtrl()->SetValue(""); } else { @@ -2158,8 +2158,8 @@ boost::any& PointCtrl::get_value() show_error(m_parent, _L("Invalid numeric.")); } else - if (!m_opt.is_value_valid(x) || - !m_opt.is_value_valid(y)) + if (m_opt.min > x || x > m_opt.max || + m_opt.min > y || y > m_opt.max) { if (m_opt.min > x) x = m_opt.min; if (x > m_opt.max) x = m_opt.max; @@ -2218,8 +2218,8 @@ void SliderCtrl::BUILD() auto temp = new wxBoxSizer(wxHORIZONTAL); auto def_val = m_opt.get_default_value()->value; - auto min = m_opt.min == -FLT_MAX ? 0 : (int)m_opt.min; - auto max = m_opt.max == FLT_MAX ? 100 : INT_MAX; + auto min = m_opt.min == INT_MIN ? 0 : m_opt.min; + auto max = m_opt.max == INT_MAX ? 100 : m_opt.max; m_slider = new wxSlider(m_parent, wxID_ANY, def_val * m_scale, min * m_scale, max * m_scale, diff --git a/src/slic3r/GUI/Widgets/SpinInput.hpp b/src/slic3r/GUI/Widgets/SpinInput.hpp index 275d42a95d..030eb56942 100644 --- a/src/slic3r/GUI/Widgets/SpinInput.hpp +++ b/src/slic3r/GUI/Widgets/SpinInput.hpp @@ -78,9 +78,6 @@ public: void SetRange(int min, int max); - int GetMin() const { return this->min; } - int GetMax() const { return this->max; } - protected: void DoSetToolTipText(wxString const &tip) override; From d1f4e8abe10e913f941f04bd71762fdd960a354c Mon Sep 17 00:00:00 2001 From: SoftFever Date: Fri, 2 Jan 2026 10:04:56 +0800 Subject: [PATCH 16/45] New OrcaSlicer wiki URL (#11800) --- README.md | 22 +++++++++---------- ...o.github.softfever.OrcaSlicer.metainfo.xml | 2 +- src/slic3r/GUI/MainFrame.cpp | 4 ++-- src/slic3r/GUI/OptionsGroup.cpp | 2 +- src/slic3r/GUI/StepMeshDialog.cpp | 2 +- src/slic3r/GUI/calib_dlg.cpp | 18 +++++++-------- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 59fb76034b..afd418ea0a 100644 --- a/README.md +++ b/README.md @@ -44,19 +44,19 @@ If you come across any of these in search results, please report them as # Main features -- **[Advanced Calibration Tools](https://github.com/OrcaSlicer/OrcaSlicer/wiki/Calibration)** +- **[Advanced Calibration Tools](https://www.orcaslicer.com/wiki/Calibration)** Comprehensive suite: temperature towers, flow rate, retraction & more for optimal performance. -- **[Precise Wall](https://github.com/OrcaSlicer/OrcaSlicer/wiki/quality_settings_precision#precise-wall) and [Seam Control](https://github.com/OrcaSlicer/OrcaSlicer/wiki/quality_settings_seam)** +- **[Precise Wall](https://www.orcaslicer.com/wiki/quality_settings_precision#precise-wall) and [Seam Control](https://www.orcaslicer.com/wiki/quality_settings_seam)** Adjust outer wall spacing and apply scarf seams to enhance print accuracy. -- **[Sandwich Mode](https://github.com/OrcaSlicer/OrcaSlicer/wiki/quality_settings_wall_and_surfaces#innerouterinner) and [Polyholes](https://github.com/OrcaSlicer/OrcaSlicer/wiki/quality_settings_precision#polyholes) Support** - Use varied infill [patterns](https://github.com/OrcaSlicer/OrcaSlicer/wiki/strength_settings_patterns) and accurate hole shapes for improved clarity. -- **[Overhang](https://github.com/OrcaSlicer/OrcaSlicer/wiki/quality_settings_overhangs) and [Support Optimization](https://github.com/OrcaSlicer/OrcaSlicer/wiki#support-settings)** +- **[Sandwich Mode](https://www.orcaslicer.com/wiki/quality_settings_wall_and_surfaces#innerouterinner) and [Polyholes](https://www.orcaslicer.com/wiki/quality_settings_precision#polyholes) Support** + Use varied infill [patterns](https://www.orcaslicer.com/wiki/strength_settings_patterns) and accurate hole shapes for improved clarity. +- **[Overhang](https://www.orcaslicer.com/wiki/quality_settings_overhangs) and [Support Optimization](https://www.orcaslicer.com/wiki#support-settings)** Modify geometry for printable overhangs with precise support placement. -- **[Granular Controls and Customization](https://github.com/OrcaSlicer/OrcaSlicer/wiki#process-settings)** +- **[Granular Controls and Customization](https://www.orcaslicer.com/wiki#process-settings)** Fine-tune print speed, layer height, pressure, and temperature with precision. - **Network Printer Support** Seamless integration with Klipper, PrusaLink, and OctoPrint for remote control. -- **[Mouse Ear Brims](https://github.com/OrcaSlicer/OrcaSlicer/wiki/others_settings_brim) & [Adaptive Bed Mesh](https://github.com/OrcaSlicer/OrcaSlicer/wiki/printer_basic_information_adaptive_bed_mesh)** +- **[Mouse Ear Brims](https://www.orcaslicer.com/wiki/others_settings_brim) & [Adaptive Bed Mesh](https://www.orcaslicer.com/wiki/printer_basic_information_adaptive_bed_mesh)** Automatic brims and adaptive mesh calibration ensure consistent adhesion. - **User-Friendly Interface** Intuitive drag-and-drop design with pre-made profiles for popular printers. @@ -68,10 +68,10 @@ If you come across any of these in search results, please report them as # Wiki -The [wiki](https://github.com/OrcaSlicer/OrcaSlicer/wiki) aims to provide a detailed explanation of the slicer settings, including how to maximize their use and how to calibrate and set up your printer. +The [wiki](https://www.orcaslicer.com/wiki) aims to provide a detailed explanation of the slicer settings, including how to maximize their use and how to calibrate and set up your printer. -- **[Access the wiki here](https://github.com/OrcaSlicer/OrcaSlicer/wiki)** -- **[Contribute to the wiki](https://github.com/OrcaSlicer/OrcaSlicer/wiki/How-to-wiki)** +- **[Access the wiki here](https://www.orcaslicer.com/wiki)** +- **[Contribute to the wiki](https://www.orcaslicer.com/wiki/How-to-wiki)** # Download @@ -144,7 +144,7 @@ winget install --id=SoftFever.OrcaSlicer -e # How to Compile -All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://github.com/OrcaSlicer/OrcaSlicer/wiki/How-to-build) page. +All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://www.orcaslicer.com/wiki/How-to-build) page. Please refer to the wiki to ensure you're following the latest and most accurate steps for your platform. diff --git a/scripts/flatpak/io.github.softfever.OrcaSlicer.metainfo.xml b/scripts/flatpak/io.github.softfever.OrcaSlicer.metainfo.xml index 96fd4c3ad7..c63f02d96b 100755 --- a/scripts/flatpak/io.github.softfever.OrcaSlicer.metainfo.xml +++ b/scripts/flatpak/io.github.softfever.OrcaSlicer.metainfo.xml @@ -11,7 +11,7 @@ Get even more perfect prints! SoftFever https://github.com/OrcaSlicer/OrcaSlicer - https://github.com/OrcaSlicer/OrcaSlicer/wiki + https://www.orcaslicer.com/wiki https://github.com/OrcaSlicer/OrcaSlicer/issues/ https://ko-fi.com/SoftFever 0BSD diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 6d0023a0ba..b6d1a7b7d8 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -3113,7 +3113,7 @@ void MainFrame::init_menubar_as_editor() // help append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Tutorial"), _L("Calibration help"), [this](wxCommandEvent&) { - std::string url = "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Calibration"; + std::string url = "https://www.orcaslicer.com/wiki/Calibration"; if (const std::string country_code = wxGetApp().app_config->get_country_code(); country_code == "CN") { // Use gitee mirror for China users url = "https://gitee.com/n0isyfox/orca-slicer-docs/wikis/%E6%A0%A1%E5%87%86/%E6%89%93%E5%8D%B0%E5%8F%82%E6%95%B0%E6%A0%A1%E5%87%86"; @@ -3229,7 +3229,7 @@ void MainFrame::init_menubar_as_editor() [this]() {return m_plater->is_view3D_shown();; }, this); // help append_menu_item(calib_menu, wxID_ANY, _L("Tutorial"), _L("Calibration help"), - [this](wxCommandEvent&) { wxLaunchDefaultBrowser("https://github.com/OrcaSlicer/OrcaSlicer/wiki/Calibration", wxBROWSER_NEW_WINDOW); }, "", nullptr, + [this](wxCommandEvent&) { wxLaunchDefaultBrowser("https://www.orcaslicer.com/wiki/Calibration", wxBROWSER_NEW_WINDOW); }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); m_menubar->Append(calib_menu,wxString::Format("&%s", _L("Calibration"))); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 3d0318f663..5b4f9d3504 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -1312,7 +1312,7 @@ wxString OptionsGroup::get_url(const std::string& path_end) str = str.Left(pos) + anchor; } // Orca: point to sf wiki for seam parameters - return wxString::Format(L"https://github.com/OrcaSlicer/OrcaSlicer/wiki/%s", from_u8(path_end)); + return wxString::Format(L"https://www.orcaslicer.com/wiki/%s", from_u8(path_end)); } diff --git a/src/slic3r/GUI/StepMeshDialog.cpp b/src/slic3r/GUI/StepMeshDialog.cpp index db281a8ebf..b1b8041cd2 100644 --- a/src/slic3r/GUI/StepMeshDialog.cpp +++ b/src/slic3r/GUI/StepMeshDialog.cpp @@ -123,7 +123,7 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, Slic3r::Step& file, double line tips->SetForegroundColour(StateColor::darkModeColorFor(wxColour(0, 151, 137))); tips->SetFont(font); tips->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { - wxLaunchDefaultBrowser("https://github.com/OrcaSlicer/OrcaSlicer/wiki/stl-transformation"); + wxLaunchDefaultBrowser("https://www.orcaslicer.com/wiki/stl-transformation"); }); info->Wrap(FromDIP(400)); tips_sizer->Add(info, 0, wxALIGN_LEFT); diff --git a/src/slic3r/GUI/calib_dlg.cpp b/src/slic3r/GUI/calib_dlg.cpp index 24eb46b4a5..ffd995a89b 100644 --- a/src/slic3r/GUI/calib_dlg.cpp +++ b/src/slic3r/GUI/calib_dlg.cpp @@ -176,12 +176,12 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* // Help links auto help_sizer = new wxBoxSizer(wxVERTICAL); auto help_link_pa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Pressure Advance Guide"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/pressure-advance-calib"); + "https://www.orcaslicer.com/wiki/pressure-advance-calib"); help_link_pa->SetForegroundColour(wxColour("#1890FF")); help_sizer->Add(help_link_pa, 0, wxALL, FromDIP(5)); auto help_link_apa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Adaptive Pressure Advance Guide"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/adaptive-pressure-advance-calib"); + "https://www.orcaslicer.com/wiki/adaptive-pressure-advance-calib"); help_link_apa->SetForegroundColour(wxColour("#1890FF")); help_sizer->Add(help_link_apa, 0, wxALL, FromDIP(5)); @@ -400,7 +400,7 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Temperature Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/temp-calib"); + "https://www.orcaslicer.com/wiki/temp-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -579,7 +579,7 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Volumetric Speed Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/volumetric-speed-calib"); + "https://www.orcaslicer.com/wiki/volumetric-speed-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -685,7 +685,7 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater) v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: VFA"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/vfa-calib"); + "https://www.orcaslicer.com/wiki/vfa-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -792,7 +792,7 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Retraction Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/retraction-calib"); + "https://www.orcaslicer.com/wiki/retraction-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -969,7 +969,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/input-shaping-calib"); + "https://www.orcaslicer.com/wiki/input-shaping-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -1166,7 +1166,7 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/input-shaping-calib"); + "https://www.orcaslicer.com/wiki/input-shaping-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); @@ -1357,7 +1357,7 @@ Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* v_sizer->AddSpacer(FromDIP(5)); auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Cornering Calibration"), - "https://github.com/OrcaSlicer/OrcaSlicer/wiki/cornering-calib"); + "https://www.orcaslicer.com/wiki/cornering-calib"); help_link->SetForegroundColour(wxColour("#1890FF")); v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); From a30fa08e1be7843f8aa8b15bf36db36f1826f936 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 10:05:33 +0800 Subject: [PATCH 17/45] Bump actions/upload-artifact from 5 to 6 (#11797) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_all.yml | 4 ++-- .github/workflows/build_deps.yml | 2 +- .github/workflows/build_orca.yml | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 1e944a7667..43f23e0a64 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -106,7 +106,7 @@ jobs: tar -xvf build_tests.tar scripts/run_unit_tests.sh - name: Upload Test Logs - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 if: ${{ failure() }} with: name: unit-test-logs @@ -170,7 +170,7 @@ jobs: arch: ${{ matrix.variant.arch }} upload-artifact: false - name: Upload artifacts Flatpak - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak path: '/__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak' diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index 045f9f7f2a..668d00038b 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -97,7 +97,7 @@ jobs: - name: Upload OrcaSlicer_dep director(ies) for use later if: ${{ !cancelled() && ! env.ACT}} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ env.ARTIFACT_NAME }} path: ${{ env.DEPS_PATH }} diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 986ac4059c..8285f61a98 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -180,14 +180,14 @@ jobs: - name: Upload artifacts mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Mac_universal_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg - name: Upload OrcaSlicer_profile_validator DMG mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Mac_universal_DMG_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg @@ -254,28 +254,28 @@ jobs: - name: Upload artifacts Win zip if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Windows_${{ env.ver }}_portable path: ${{ github.workspace }}/build/OrcaSlicer - name: Upload artifacts Win installer if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/OrcaSlicer*.exe - name: Upload artifacts Win PDB if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: PDB path: ${{ github.workspace }}/build/src/Release/Debug_PDB_${{ env.ver }}_for_developers_only.7z - name: Upload OrcaSlicer_profile_validator Win if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe @@ -335,7 +335,7 @@ jobs: # and doesn't preserve file permissions - name: Upload Test Artifact if: inputs.os == 'ubuntu-24.04' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ github.sha }}-tests overwrite: true @@ -357,7 +357,7 @@ jobs: env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage' @@ -366,7 +366,7 @@ jobs: if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }} env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/src/Release/OrcaSlicer_profile_validator' From d021da1487268285cc85fff1d873bc18fdf0831c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 10:05:41 +0800 Subject: [PATCH 18/45] Bump actions/cache from 4 to 5 (#11798) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_deps.yml | 4 ++-- .github/workflows/shellcheck.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index 668d00038b..c6288330a1 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -35,7 +35,7 @@ jobs: # So building XOR cache loading. # We use `lookup-only` to skip pulling cache. - name: load cached deps - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 id: cache-load with: path: ${{ env.DEPS_PATH }} @@ -106,7 +106,7 @@ jobs: - name: Save cache from main branch if: ${{ !cancelled() && github.ref == 'refs/heads/main' && steps.cache-load.outputs.cache-hit != 'true' }} - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: ${{ env.DEPS_PATH }} key: ${{ steps.cache-load.outputs.cache-primary-key }} diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 336636bbcc..d5fe5a35d2 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Cache shellcheck download id: cache-shellcheck-v0_11 - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/shellcheck key: ${{ runner.os }}-shellcheck-v0_11 From 8147f8d5fa05eba6ef55e83d06bb6d2567914d69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 10:05:47 +0800 Subject: [PATCH 19/45] Bump actions/download-artifact from 4 to 7 (#11799) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 7. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_all.yml | 2 +- .github/workflows/build_orca.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 43f23e0a64..0cae85189b 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -94,7 +94,7 @@ jobs: - name: Apt-Install Dependencies uses: ./.github/actions/apt-install-deps - name: Restore Test Artifact - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: ${{ github.sha }}-tests - uses: lukka/get-cmake@latest diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 8285f61a98..d70b4c9200 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -31,7 +31,7 @@ jobs: lfs: 'true' - name: Download deps artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: ${{ inputs.artifact-name }} path: ${{ inputs.artifact-path }} From 11018ba0f368e11418470ff658cc2d1b84a667a5 Mon Sep 17 00:00:00 2001 From: innovatiQ Date: Fri, 2 Jan 2026 03:06:53 +0100 Subject: [PATCH 20/45] Polymaker Polymax PETG updated - Grauts HPP4GF25 added (#11665) * Added InnovatiQ Vendor Files * Cover image corrected * Corrected Texture Image * Support Interface Pattern modified * Fix file name casing * Added new filament(PETG) * changed three parameters * Added 6 new printer files 0.25, 0.6, 0.8 printer profiles are added to TiQ2 and TiQ8 * Added 6 new machines in machine list * 6 new machines added in machine list * Modified the PACF filament and process file * Added two new filament file and one process file * Modified one filament and one process file * PETG Polymax profile for TiQ2 updated * HPP4GF25 Grauts filament-process addeed to TiQ2 --------- Co-authored-by: MohanS Co-authored-by: Noisyfox Co-authored-by: Ashidsha Jaleel Co-authored-by: SoftFever Co-authored-by: ash-innovatiq --- resources/profiles/iQ.json | 8 + ...rauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json | 303 ++++++++++++++++++ ... Polymax black P1 @iQ TiQ2 0.4 Nozzle.json | 14 +- ...iQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json | 70 ++++ ...- PETG Polymax Polymaker (0.4 Nozzle).json | 8 +- 5 files changed, 394 insertions(+), 9 deletions(-) create mode 100644 resources/profiles/iQ/filament/Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json create mode 100644 resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json diff --git a/resources/profiles/iQ.json b/resources/profiles/iQ.json index 17d813bac9..c904ad1a1f 100644 --- a/resources/profiles/iQ.json +++ b/resources/profiles/iQ.json @@ -80,6 +80,10 @@ { "name": "0.20mm Standard @iQ TiQ2 P2 - PACF Pro Fiberthree + VXL90 Xioneer (0.4 Nozzle)", "sub_path": "process/0.20mm Standard @iQ TiQ2 P2 - PACF Pro Fiberthree + VXL90 Xioneer (0.4 Nozzle).json" + }, + { + "name": "0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle)", + "sub_path": "process/0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json" } ], "filament_list": [ @@ -106,6 +110,10 @@ { "name": "VXL90 TiQ2 P2 @iQ TiQ2 0.4 Nozzle", "sub_path": "filament/VXL90 TiQ2 P2 @iQ TiQ2 0.4 Nozzle.json" + }, + { + "name": "Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle", + "sub_path": "filament/Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json" } ] } diff --git a/resources/profiles/iQ/filament/Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json b/resources/profiles/iQ/filament/Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json new file mode 100644 index 0000000000..20146fa309 --- /dev/null +++ b/resources/profiles/iQ/filament/Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle.json @@ -0,0 +1,303 @@ +{ + "type": "filament", + "name": "Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle", + "inherits": "fdm_filament_common", + "from": "system", + "setting_id": "IQS1", + "filament_id": "IQM1", + "instantiation": "true", + "compatible_prints": [ + "0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle)" + ], + "filament_cost": [ + "70.58" + ], + "filament_density": [ + "1.09" + ], + "filament_end_gcode": [ + "; filament end gcode\n{if current_extruder==0}\nG1 Z{layer_z+2} F900 ; safe distance for T0 while tool change\nG1 X-17 Y1 F9000\nG1 X-17 Y45 F9000\nG1 Y1 F9000\nG1 Y45 F9000\n{endif}\n\n{if current_extruder==1}\n{if current_extruder==0}T1{endif}\nG1 X-23 Y3 F9000\nG1 Y45 F9000\nG1 Y3 F9000\nG1 Y45 F9000\n{endif}\n" + ], + "filament_flow_ratio": [ + "0.926" + ], + "filament_settings_id": [ + "Grauts HPP4GF25 P1 @iQ TiQ2 0.4 Nozzle" + ], + "filament_shrink": [ + "98.994%" + ], + "filament_shrinkage_compensation_z": [ + "99%" + ], + "filament_start_gcode": [ + "; Filament gcode\n{if current_extruder==0}\nG1 X-17 Y1 F9000\nG1 Y45 F9000\nG1 Y1 F9000\nG1 Y45 F9000\n{if layer_z==0}G1 Z{first_layer_height + 2.0}{endif}\n{if layer_z==0}G1 X[first_layer_print_min_0] Y[first_layer_print_min_1]{endif}\n{if layer_z==0}G1 Z{layer_z}{endif}\n{endif}\n\n{if current_extruder==1}\nG1 X-23 Y3 F9000\nG1 Y45 F9000\nG1 Y3 F9000\nG1 Y45 F9000\n{endif}\n" + ], + "filament_type": [ + "HPP4GF25" + ], + "hot_plate_temp": [ + "110" + ], + "hot_plate_temp_initial_layer": [ + "110" + ], + "idle_temperature": [ + "180" + ], + "is_custom_defined": "0", + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "280" + ], + "nozzle_temperature_range_low": [ + "220" + ], + "temperature_vitrification": [ + "127" + ], + "version": "2.3.1.10", + + + "activate_air_filtration": [ + "0" + ], + "activate_chamber_temp_control": [ + "0" + ], + "adaptive_pressure_advance": [ + "0" + ], + "adaptive_pressure_advance_bridges": [ + "0" + ], + "adaptive_pressure_advance_model": [ + "0,0,0\n0,0,0" + ], + "adaptive_pressure_advance_overhangs": [ + "0" + ], + "additional_cooling_fan_speed": [ + "0" + ], + "chamber_temperature": [ + "0" + ], + "close_fan_the_first_x_layers": [ + "3" + ], + "compatible_printers": [ + "iQ TiQ2 0.4 Nozzle" + ], + "compatible_printers_condition": "", + "compatible_prints_condition": "", + "complete_print_exhaust_fan_speed": [ + "80" + ], + "cool_plate_temp": [ + "105" + ], + "cool_plate_temp_initial_layer": [ + "105" + ], + "default_filament_colour": [ + "#000000" + ], + "dont_slow_down_outer_wall": [ + "0" + ], + "during_print_exhaust_fan_speed": [ + "60" + ], + "enable_overhang_bridge_fan": [ + "1" + ], + "enable_pressure_advance": [ + "0" + ], + "eng_plate_temp": [ + "105" + ], + "eng_plate_temp_initial_layer": [ + "105" + ], + "fan_cooling_layer_time": [ + "30" + ], + "fan_max_speed": [ + "80" + ], + "fan_min_speed": [ + "10" + ], + "filament_cooling_final_speed": [ + "3.5" + ], + "filament_cooling_initial_speed": [ + "10" + ], + "filament_cooling_moves": [ + "2" + ], + "filament_deretraction_speed": [ + "nil" + ], + "filament_diameter": [ + "1.75" + ], + "filament_is_support": [ + "0" + ], + "filament_loading_speed": [ + "10" + ], + "filament_loading_speed_start": [ + "50" + ], + "filament_long_retractions_when_cut": [ + "nil" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_multitool_ramming": [ + "1" + ], + "filament_multitool_ramming_flow": [ + "40" + ], + "filament_multitool_ramming_volume": [ + "10" + ], + "filament_notes": [ + "" + ], + "filament_ramming_parameters": [ + "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" + ], + "filament_retract_before_wipe": [ + "nil" + ], + "filament_retract_lift_above": [ + "nil" + ], + "filament_retract_lift_below": [ + "nil" + ], + "filament_retract_lift_enforce": [ + "nil" + ], + "filament_retract_restart_extra": [ + "nil" + ], + "filament_retract_when_changing_layer": [ + "nil" + ], + "filament_retraction_distances_when_cut": [ + "nil" + ], + "filament_retraction_length": [ + "4" + ], + "filament_retraction_minimum_travel": [ + "nil" + ], + "filament_retraction_speed": [ + "40" + ], + "filament_soluble": [ + "0" + ], + "filament_stamping_distance": [ + "45" + ], + "filament_stamping_loading_speed": [ + "29" + ], + "filament_toolchange_delay": [ + "0" + ], + "filament_unloading_speed": [ + "100" + ], + "filament_unloading_speed_start": [ + "100" + ], + "filament_vendor": [ + "iQ Materials" + ], + "filament_wipe": [ + "nil" + ], + "filament_wipe_distance": [ + "nil" + ], + "filament_z_hop": [ + "nil" + ], + "filament_z_hop_types": [ + "nil" + ], + "full_fan_speed_layer": [ + "0" + ], + "internal_bridge_fan_speed": [ + "-1" + ], + "overhang_fan_speed": [ + "80" + ], + "overhang_fan_threshold": [ + "25%" + ], + "pellet_flow_coefficient": [ + "0.4157" + ], + "pressure_advance": [ + "0.02" + ], + "reduce_fan_stop_start_freq": [ + "1" + ], + "required_nozzle_HRC": [ + "0" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "slow_down_layer_time": [ + "3" + ], + "slow_down_min_speed": [ + "10" + ], + "supertack_plate_temp": [ + "35" + ], + "supertack_plate_temp_initial_layer": [ + "35" + ], + "support_material_interface_fan_speed": [ + "-1" + ], + "textured_cool_plate_temp": [ + "40" + ], + "textured_cool_plate_temp_initial_layer": [ + "40" + ], + "textured_plate_temp": [ + "105" + ], + "textured_plate_temp_initial_layer": [ + "105" + ] +} diff --git a/resources/profiles/iQ/filament/Polymaker PETG Polymax black P1 @iQ TiQ2 0.4 Nozzle.json b/resources/profiles/iQ/filament/Polymaker PETG Polymax black P1 @iQ TiQ2 0.4 Nozzle.json index 457b37f8cd..054350acfc 100644 --- a/resources/profiles/iQ/filament/Polymaker PETG Polymax black P1 @iQ TiQ2 0.4 Nozzle.json +++ b/resources/profiles/iQ/filament/Polymaker PETG Polymax black P1 @iQ TiQ2 0.4 Nozzle.json @@ -30,9 +30,6 @@ "chamber_temperature": [ "0" ], - "close_fan_the_first_x_layers": [ - "3" - ], "compatible_printers": [ "iQ TiQ2 0.4 Nozzle" ], @@ -89,6 +86,9 @@ "filament_cooling_moves": [ "4" ], + "close_fan_the_first_x_layers": [ + "1000" + ], "filament_cost": [ "29.99" ], @@ -162,7 +162,7 @@ "nil" ], "filament_retraction_length": [ - "0.2" + "0.4" ], "filament_retraction_minimum_travel": [ "nil" @@ -222,7 +222,7 @@ "0" ], "hot_plate_temp": [ - "80" + "70" ], "hot_plate_temp_initial_layer": [ "80" @@ -237,7 +237,7 @@ "-1" ], "nozzle_temperature": [ - "250" + "240" ], "nozzle_temperature_initial_layer": [ "250" @@ -261,7 +261,7 @@ "0.02" ], "reduce_fan_stop_start_freq": [ - "1" + "0" ], "required_nozzle_HRC": [ "3" diff --git a/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json b/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json new file mode 100644 index 0000000000..0a542fe938 --- /dev/null +++ b/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle).json @@ -0,0 +1,70 @@ +{ + "type": "process", + "inherits": "fdm_process_tiq_common", + "from": "system", + "instantiation": "true", + "default_acceleration": "1500", + "enable_extra_bridge_layer": "apply_to_all", + "enable_prime_tower": "0", + "initial_layer_infill_speed": "100", + "inner_wall_acceleration": "1500", + "inner_wall_speed": "100", + "is_custom_defined": "0", + "name": "0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle)", + "notes": "Pre-Select: FBA Time Delay: 0 EPC Factor: 0\n\nDeutsch P1 HPP4GF25\n\n1. Überprüfen Sie, dass sich das Grauts HPP4GF25 im linken Extruder befindet. Halten Sie das Filament trocken! Detailierte Trocknungsanleitung, siehe unten.\n\n2. Überprüfen Sie, dass sich eine 0,4 mm Wolfram-Kupfer Düse im linken Extruder befindet.\n\n3. Verwenden Sie Magigoo Kleber für PPGF auf der PET-Folie, um eine bessere Haftung zu gewährleisten, im Singledruck in der Regel auf PET-Folie nicht erforderlich.\n\n4. Reinigen Sie ggf. die Düse mit einer Messing-Drahtbürste.\nNun sind sie bereit, um Ihren Druck zu starten.\n\n\nTipp: Am besten lässt sich das Bauteil bei einer Druckplattentemperatur von 80°C entfernen, da dann der Kleber weich wird.\n\n\nEnglish P1 HPP4GF25\n\n1. Check Left extruder filament: Grauts HPP4GF25 - Keep the filament dry!! Detailed drying instruction below.\n\n2. Check left extruder nozzle: 0.4mm Wolfram\n\n3. Check bed: PET with Magigoo glue for PPGF\n\n4. Check nozzle: Clean it with brush\n\nWELLDONE! YOU ARE READY NOW TO START YOUR PRINT JOB!\n\n\nTip: The component is best removed at a printing plate temperature of 80°C, as this softens the adhesive.", + "outer_wall_acceleration": "1500", + "outer_wall_speed": "80", + "print_settings_id": "0.20mm Standard @iQ TiQ2 P1 - HPP4GF25 Grauts (0.4 Nozzle)", + "sparse_infill_speed": "100", + "support_angle": "0", + "support_base_pattern": "default", + "support_interface_bottom_layers": "0", + "support_interface_top_layers": "3", + "support_object_first_layer_gap": "0.3", + "support_object_xy_distance": "0.35", + "support_on_build_plate_only": "0", + "support_speed": "100", + "support_style": "snug", + "support_top_z_distance": "0.2", + "support_type": "normal(auto)", + "top_surface_acceleration": "1500", + "top_surface_speed": "80", + "travel_acceleration": "1500", + "version": "2.3.1.10", + + "bridge_flow": "1.07", + "bridge_speed": "25", + "brim_type": "no_brim", + "enable_support": "1", + "exclude_object": "0", + "gcode_label_objects": "0", + "compatible_printers": [ + "iQ TiQ2 0.4 Nozzle" + ], + "internal_bridge_speed": "50%", + "internal_solid_infill_speed": "60", + "ironing_pattern": "concentric", + "prime_tower_width": "80", + "layer_height": "0.2", + "reduce_crossing_wall": "1", + "skirt_height": "1", + "skirt_loops": "2", + "small_perimeter_speed": "30%", + "small_perimeter_threshold": "5", + "sparse_infill_density": "30%", + "sparse_infill_pattern": "triangles", + "support_base_pattern_spacing": "1", + "support_bottom_interface_spacing": "0.3", + "support_bottom_z_distance": "0.24", + "support_expansion": "0.5", + "support_filament": "1", + "support_interface_filament": "1", + "support_interface_pattern": "rectilinear_interlaced", + "support_interface_spacing": "0", + "top_shell_thickness": "0", + "top_solid_infill_flow_ratio": "0.98", + "tree_support_branch_diameter_angle": "10", + "tree_support_branch_diameter_organic": "3", + "tree_support_tip_diameter": "2", + "wall_loops": "2" +} diff --git a/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - PETG Polymax Polymaker (0.4 Nozzle).json b/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - PETG Polymax Polymaker (0.4 Nozzle).json index 096eb82e13..1093c7c1c7 100644 --- a/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - PETG Polymax Polymaker (0.4 Nozzle).json +++ b/resources/profiles/iQ/process/0.20mm Standard @iQ TiQ2 P1 - PETG Polymax Polymaker (0.4 Nozzle).json @@ -20,6 +20,9 @@ "enable_overhang_speed": "0", "enable_prime_tower": "0", "gap_infill_speed": "50", + "thick_internal_bridges": "0", + "enable_extra_bridge_layer": "apply_to_all", + "bottom_shell_thickness": "0.8", "initial_layer_infill_speed": "25", "initial_layer_speed": "25", "initial_layer_travel_speed": "50%", @@ -63,10 +66,11 @@ "tree_support_wall_count": "2", "wall_direction": "ccw", "wall_loops": "3", - "wall_sequence": "inner-outer-inner wall", + "wall_sequence": "inner wall/outer wall", "support_base_pattern": "rectilinear-grid", "support_interface_pattern": "rectilinear_interlaced", "support_interface_spacing": "0", - "small_perimeter_speed": "30%", + "small_perimeter_speed": "50", + "support_interface_speed": "50", "brim_type": "no_brim" } \ No newline at end of file From af9688e619df676f5764df37e1abe519949cd4d6 Mon Sep 17 00:00:00 2001 From: neo-jayfeather <156867325+neo-jayfeather@users.noreply.github.com> Date: Fri, 2 Jan 2026 04:26:27 -0500 Subject: [PATCH 21/45] Small Printer Thumbnail Orientation and Typo Fixes (#11807) # Description - Centered P2S image and removed unnecessary padding (different source image). - Renamed Ginger Additive G1 (ginger --> Ginger, no image change). - Renamed Magic maker hj SK (sk --> SK, no image change). - Renamed Wondermaker ZR Ultra S (ULtra --> Ultra, no image change). - Replaced Geeetech A10M (to hide spool on top, better framing) - Edited M3D Enabler so the white background is transparent (same image, edited & cropped). > [!NOTE] > All images were edited using GIMP on Linux, are 240x240 px @ 144 dpi. > (and no AI was used for this description or image processing, if that matters) # Screenshots/Recordings/Graphs | Printer | Old | New | |----|-----|----| |P2S|image | image | |Ginger Additive G1|image|image| |Magic Maker hj SK|image|image| |Wondermaker ZR Ultra S|image|image| |Geeetech A10 M|image|image| |M3D Enabler|image|image| ## Tests No code was changed, so no logic was tested. I have tested the import UI and have made sure that the images follow previous standards (appears to be 240x240, 144 ppi). --- .../profiles/BBL/Bambu Lab P2S_cover.png | Bin 31633 -> 31704 bytes .../Geeetech/Geeetech A10 M_cover.png | Bin 7204 -> 42946 bytes ...inger G1_cover.png => Ginger G1_cover.png} | Bin .../M3D/M3D Enabler D8500 MM Model_cover.png | Bin 417255 -> 29956 bytes ...{MM hj sk_cover.png => MM hj SK_cover.png} | Bin ...r.png => WonderMaker ZR Ultra S_cover.png} | Bin 6 files changed, 0 insertions(+), 0 deletions(-) rename resources/profiles/Ginger Additive/{ginger G1_cover.png => Ginger G1_cover.png} (100%) rename resources/profiles/MagicMaker/{MM hj sk_cover.png => MM hj SK_cover.png} (100%) rename resources/profiles/WonderMaker/{WonderMaker ZR ULtra S_cover.png => WonderMaker ZR Ultra S_cover.png} (100%) diff --git a/resources/profiles/BBL/Bambu Lab P2S_cover.png b/resources/profiles/BBL/Bambu Lab P2S_cover.png index febba125eedd53c83e11e1c422511a5c178ad9d2..30982b863a0cfa0af8b4cc433cbb0e9a3c420e09 100644 GIT binary patch literal 31704 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�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⁣iwB+QgW zgtXU#-g?`jO_z|>G-CK1Pa|Wbvj^)l(U-vVt>~ENEmM`4Y_PDB@Z*qz-anWV-yt7$ zJi}?>;2FvTD9Nhxr-ylzI_>QX6_DDLS&xr-1?n?idYoiYUZZSK^idPNe_8*j7Z57C zO|)V@cWNNy0l`WT?yHp*W{wN+ghX6j5it1A!be@c^EG-knDdA6-MlJu-8ZZ?um5Ss z(_T-<4Bvcq=0#^JjTy0bIblV zTfygQ#zBsMKV$u*Z+I{@5Ks3fDlyB#GGTfy_@<+XYpbBB-q+NREspd*{DHV#Y2!x0Fr+2Q>ww+4YZV%$=Gr?F{%W5?OwN)_njqH(++2BO%mETYva+dvH5wxBDzbebvmEvjs32{?XkX^$g`AC zKMD4H`IiPT#lQmC$2GyJXKtdWpBeE#*ljDkvLPB!1Xdf!e`(+Es%$nf(OI*pCEJnK zGFcyqIH>wGMd@T6UVT6%@BH)LK(}9WiepohonXf<5yNE}0mLMHWoQ(WcVC0xTyrK- z?i>VopiepeV$G`9@r68~moNj98xVTHeZawE5^gJx8nda${tfQ$|6Y~uje*z+pjChL z*`CTOI7IR+Qph;Fr-bj6-mD7SuFE#6U;QjEn^Fe(NqA7&$d_oa8BA-h&)R4aB;7Z3b zu7HyrhAU#4#1sl3;RqJn%m*OoY`Tdkz#-bh(R@0hVc)s}@j$RUp}g(S60xS=;VqDO z$7W_sgyCx@fk0YiwIU3P#y8>TYe}8;`Q5bM%Xg>41gBfWj|WV@=0OCW>$`))UT!YU z%h!B=sN*z*zew<6+z&r`JR_W`>;Cd)=+)w}u$olO>=@8c>OivD>1xIA90ZHI0I}an zb8mSXLwilllz>0GAfLO>ES-Z5GHrQTSqS7$p)dU^wehUCP~)W*SLXo%9GY)DuhTSm zKh(foe`>EymK1KlGcc%7B=p7j)`>3wB25NXR^g?k%$@A&u?F$8VD+5dKONQpA6n3Q zE+vyU4#xilIOap**Yn!>`IP+!pofB_Kq`znWa0)imhJ6)xE~Y|Z;}SbCMHBFBI1?4 zU$l85Y;J)&T)ZA~NOUGtc{_Z8QWV<4Q7vRo6V-m{3Y25u=}zRluj>NGX}qdY%;)J) zcCKn#qBWKQ>#nfb=u`1S1OW(#<~>bex-M`WoCA@GRdcFD9T()gfMW-?F_2ItP;~wc zfc(J8%&=Q5=w-TISyt_J-cA`(bofEZ2M2F!%-<(*YV~G}>%C#BJa3d#&lu*eei7B1 z-Mb#ZbshVgdxT3{HqJlk9F8IalsG$Wj>_|G`u~=GMx=1wjpf zNt6p7j{Qq%ZNZy|J=s-wCm`>+*-dPj%n75>?aw+5t@Gb*06`U%`6Fb1JKiw9Bhq3R z84E|ss?6TbhTKH_1*0AC^C3x`7TCxbuP5B^Rs?fjZMKQWV4hw#>D*9s{He9T2_{pH z^!FgPC-MJg2$=c;k?G&f?Q2ja>;@9N;)?a;dPrVAr(b*cgqCfPghY}PC-xi0UfOuT z^Kd5r7!72Iw3;ppVH`an0thNE_;iTw)RF~-%;Bj-Y-=f84$dO#+uS*SGbQV1JX$dm zQnkyROnKKQNv}TKA(GrGtExNJx^7GBW(=a&4i+jG{eCNOjp_^a%!A66?VHoZ`K!z5*9wih&pn5lQwV#!%BIXNj+dtpahldZVFr|xC>ftDe_jz}`q z0ck@Y&2@QYW^;jsz#|LE4tzER`bYN_bnSOzOlTuvewWJf3g=n)$u+?`C7P-Uq56=C@LMF`8{A9HRThCAVp z!BpzePV7cQB+L!l6oAD&n4m5e{JT?!$xeeK#n@6Lhz8m)W_&5{%@NB?wTVr^)?GLf zrqriAgkx%6>s1%aXM25r>HpDm7C=?6(b}gDASIpB(jeX45`u&@(p`dppoFxfG}6){ zAdP@@r%0Dd3kXOHNPTPHd%v0EnKQ@H*_*xp@4MEsp69pb`JZ%F+B_}sAd__4Jmu-p z#EfJrQaN30@#Wv!+w(guGqZt)k>R(2bT-pO`k!%Zu0|t$RZzE$8=QI5g(e^QfBH|W zFidwO(;P1h=a-NL%R?qYgKYsSMFB26O8d%k8|suD9KJ2fDNkSR)vtm?pVzPu z$W>EQj12_svun2TeYh+C{M43m-}RN-MHP8qSb zD$Js$9aE^5&N=ETnh6VVQPNq3rz?R%Ato-a0*6w-<(@nBwe+NY3R!lnwIS)}rGPI7 z{?g1GCXQ=LqQ4;+29YCYF}3Z)oU~^>h3a`>s1r)jk7K6Zk0ic6|Mc$tK0Q0*&iF%)*JnC{otkJ_Z7@664nEpyubml^%bO&d8cdc_o%I-u zbj6Rf7O0ArN>wt;QN-KRm3$IVW9S=4%ZKI%tkSZQIIxg&k zr&=os_`yq;txNpv$KvgbbRXQMVd@C;DCwzcEYIASy5R6LdkM+TzWx3E%|~u8iJ;n% zk*PNMszS`owB)8V6Uk24xzWG_nPpk^n&)gH19f)<#_MpTXlMV(*fqm3?ztgusYi*% z)PHjm0D%pdXSvtC0Gk(LHWHnREX=zq{-;rXWMt$WA{G=aR|J<+jsGPHriIV>in8VJ zbv3Naq&@qoS^NUZyyX=A_q62XAG#?Jm4ww>N!x&f5L&eBW)xB^ofumG#G7&br2XBv z*i-6#pNMmnNtwW`h-vNa-oy^=@>?z&)~%&o(XOYq^eQF%tZXWaYz?kIhSt~b>*(mX zqYn4{x#0MWOFlI`JIiEiZdpYM)NP6aR%&Ht;) z<_d_SpVxn0)IQ(T80TA7D~IUipO#|{USVOozkhxh+dUS{mz_gt3+;Cn==#vv+A8^W zL&RF_3xS@POuph&JoZb9fq&A6(eXnb*WB%!BrYw3@-2oGAB2|0?Y}Bd9jzB?N64ay zv8?!WqKMgwO5Dp|IRx7-c={-zs!q?npa6GIAB>X&#f08m7fA7BjviqI9$-jc=H2z* zYC~j0y=)5B|BL=-!B~V#Ah-z+0i+8!Q=(9qB0oU^(Q#<%?FINzqH zy>4@%u6zU8jRlE|^`z(_rda#q<1t#RC8AeV;t|`Xf4hAE1W6m$jJvWNHb&xL+;>0s@LhbI(7kGxkg4@8U%t^RY={Ri@Cgfw8nhxn8^q zKNxB%U|m|c-nTbxOmS`*^km(RW&AIxIYd&u79~%D(BolV38{yc;V5~m3}>mx1mAM* z0oI&JVpP?EjX3jkq=3+bMuDfcK41AcMJA=8I(nkV=$vFly``S@hryYFLe{)^z4wz$ zOkEFG2g&lPjZoBC9h?fOQwbxdW%I(VKhF$1cPNnQE|90A49gnGHoe!t&{mq%=<*<} z_Z5#;!LO)KJX$XL^a#gUNiJ-h7zqZ!`|0;YeD%?-*Ma{~k8Q5)^8P+A z*Cux$i!OX%EmI^QXmf^NMeJ_&YzO6&34Ym6^U@uRxco9oIcn20rMiV4zQ+2^m|rIK zpKgyRo>|7H*X_nnx#op+U{b#_=(izhU@1!!cPE%lqcpYa_Y`w8@w|3z|eq zG%1O}B1RF~bzGd*7jj!XF`vRZR}*RK@urDU3QCiTT`E%U+H?IbpEyNriB-w}7P&)H zPcuV}PH(K%AX9F0*rBDbYBl*qX{IkEyrf(RB_ysiSuEq@d*i+@6Rj?ZJ8f?)*%an< zt-CJt8F-~oV(uW}yX}RRLIeUN6@pNUhh0gmzVPH zo&i~G$1_>W!ga+{R>d0B(YmZdkBD!BM4}XOf|Tx8wdLIWOo~TFP8(FuJX;eV-6(Mj zI&giz%eUh7C^1oOAojBnt!LwI+T!aF!!NQ{A<3kPGD0je=|lxWp(KPqcQm(B4?pdu z3~yxo%+ckE?ZI;3YsD8(BJgow`~8bWQQ|deibp!moO@QIq4Yyym$JqxpZ{|d}KU&Wl z4YyK;VQ2m}5!U%_-@x))DCB8qQQeFOc@>fc4g)8n1CHvu*VrzJYx+1{m~~aF_+=Zu z`fZ!7#7sg>cW^vZ)a4_}#Ywd6lSaEL>c6Ak3+)?!UsiOIS5Tu}NOUjsQ69Nw8JUmb zX2WPW}#3K~E3icc*+v>>wZ8kr+FJ^7+1 zK0kz)m&7sAs~WW+JLPZt+rR8i-GrxS>wndj%4M`ZVGsx$pQJc>H8f{WM%}OVHThwV z@y{0}j&*^eCAI@ue}{49Czr zs&R+ODhhS0&)WAKqZMN~=sz$b*Ut?92~zykYg(R3N;m)X$(*x& z{YGG5m-Fv(#ZG$*4S5oIEO9dFZ%sQ24J$XisJf$NeaHyke!*1u(e3og0e8D7(5=Eo zV7a%&t~&WkpFma%*VyF{&z$Xh-P-+pA$}GDC&lG7=j0ey%FKG4a~r(8M@gZ5q5Ahx zBnq`yi$ccp2V_d)Um88-DK4tl^VqsKx>qqd(1kW@Jo8I(wn4!sx|-C`Ss<^_e`-U{UYCoiVaS73!OcC8(%& zQa7zCuQ$}at)hHOC93SZ9yb~$mUAlYJh!-DZM0M} zI<+7Scu(eR%___Ojr4=UWZ-bT{+tq4?gT)+TkwY^`rtp_F>wUNR_YH7(cB!zoE?27Er~U#Hnyi--|lv zsMhL>T`0ckz(v_Zd#^PqtIBTBAaOWk)V41?8kDJJwzk-H(AZSzI+fsRx}UNVgv(1i zbHBT!`3q|@-+P-D`a=BrneG`Qtul}{oBxD43mH4igz08#lV{`$*%x&?hJ1=1Vi?>U z=!hL($+G|PTh6iO>C8C$DZL)eTs9NOxNdn5IIlm>*qd+v_qqBU5mA6-_$O1YWs6 zFlp?7nZ>7_BSc4%CFM`K*g%E%LoC7Ek+L>&n3nfg?yJn+Yq#_RKB}rWniB>Zx>TWc zzq|6ySv_&{NG^-oQpKQ=M)y znt`2ws!A3E6$vT5aIxWA`3A2!TgdjVpkiFnhI?U*LZ_n06ZxLmis`xbn$-PEL|z4K zNr>@Zkqb4vGsylIxadWJpjU(p1%oaQN?cMoG*hRGz) z@M#V{43LYqtqPj>VI{A zDkoVX%-KAIV9YU$b>auDAtTFL^g);1{Y&0QQZ|z4hiW`?OK%TG8CF!R1nff+=wlol ziwam@e9~pFxSO*<&P|z9!>&7nU!1Nlcp7?FCs0m#z}Bgv#RMX(Vq#(_Z#isCl%l#_ z%)tJqVf-r2`2lv#(;}unSGe4jSm_4$9eXS4)zMp~B$oRY^IulRIfW)XH2QJv=3?5G zvKAycR-j$_7{UdPHtKmN65Lr077vSbbju#3c!UiOsw5v#4XNkj?O=+{{Z@NZQShqC z!(0ZFW59s{uY6{uvRDsWNU-~fs)g+LaPPxaMfMb|Fu9dBz_XT({Gn;yc?aXb&m!M^Y~7td-|){bl7+DQ4llYdX~2 zPh|zsClmKx5@-`a767~A;VW&`-gOuAW6KC9;v)g zmNMQb;;C4q!RMaqG~Avj64F$jsIB$bt_N&j%E#M(^?QnKXoC-4CDZMaWBpKC+X+*x z+fv)RnKXfXrB%tP`<4M&R7}78Z{Muk7X4mIBTW9HTX#%rs4{=g3I}G4PNT*@k4Rzo zf_Oo)@mK0))9eVV8mX#7L;KCGdEcLYB9sD?sLOWbr2a0^j?U8usY7&PmjBlCk?pz2 zTGZ)Ck!37mG#-{ePMVFBtjBQ*4cH2k6rgmGxd@PW{z&dINbA>z{o*NeA8>~#)L*i3mz?=w;Fz!8(CxO zo+0B8wWWVmkSB1{PL@ekm+bRBKWITs0e?__r$`AscBPp&JUyKP#>3sf0)m6&yp2|v z7pWQ}RXZ3znd3=v!8bYcJb4sN)Tb*=0|G1fKC7}z^nW{dcTI*p(*6rmqAMg}jP2~? z;8ltcOHRm+(0_z+QArR~^#zlNiH!+lB#DC#)JHEac6WCxXs@@FM16)ur}RaR;QqW}CVu$WJzzJh%aUf-z~3F0{k_Ud_Dol@H)&HarToOBE}9OTU({ z?~Pj}Rx)8Kdg+XP_hA)$^|NrIaQ|{-bQEYyh|p`pUh^5v^lQ_~;PI-*rTMWDm@gle zZYpE+?M8T+J0O|;S9ISBCP3<%V?B8M!$6obPN^=$_#i9?j%=4TaC;*1cVH!QhqLVYtmz8?kz}HX4aNqRwp1E^%{);j zn8?5}F1S}WUPfg_{!}n#O$3Z!g~^DS_jTRo5^8Ht%yo(V>wpzG`fgA0FxDq9xew&Mg!o|Jr>U=P%qp1 zo?w|_P*iTdd|05>*7f`c`GBsf_KcLx=cqazYvM*0#F0HDndd=JS9i|V-ln-3_?>;H% z_Ppci!{)Zbz6mb~ie=}tv%FDLLM48v1J!C%)p?dA{0F80J1 zJ6o@5yzu_s^gh(2RJZZj3JP%b{x^wnF=8i0=@?1VF-P z1Ca@VnV}krwp!isuYa0;W9r2jtwn3Cl~I^9o7)6UNBfZXL-JQ|6d;YmM;>R%qAm9en_&NCy~u2`SK{Jq)VjEVP+EEQ5xdk4tR`$$g5(hlF!4 zuZ2Bl$1*bmFOir>lK+w0JF6$jmTiwa5`)9S{##f)e#n-dkzombA5XFCd>Y|xS+kLW zOy6~-20gLtxZ7VM8oMj`vxz1NvVv`?1NKz<>?t3QGh*MG9a#!Vq^*f~`FhlT$mcx^ ztTysyJfhwh1{#^6-qkVKAusC9E(Jfe9H}BQeyfEOdCukPKKu7ylZXH6Gmm~>Xs<=( z#LR_VAwbsO&)ck6*hhCh|T|^9NidiohA$fXwKKt`s6b|D< z|6G8~OfD^HLS2WWZBQ5+F*Pm2V1TL=<`W@<895bP&d5W8YhQ?io^yvYhM@7&nN@V% zjlKc58udBCRv38oR$6Fsa?<&G-5q+IF>3$ti7AScE`g7HW;!QvuNh_)FR)^iE&@J$ zBS4Y?r<;wpw-8(iI>1gq{_Tru5%*wt9+40vHn`Oh4Ht~_!N3IE_4z6bREU>Z zPJeuY2vq}62E01(Doq-n1)2RTGQ)bO(=fVpv$y1Nx%U}RXIgD?NNhOgPeQ$AcMNu@ z7%J*8S?)L_Erg=r(}fm(E=f}to8((g>xR>M4BUT?H-Gp8`<()Rl^}PnPjR9IWk|lY z6Q64c`H+gboxGl+fQq%pQOLvUg0FM{_v+iA8)P6JGIjs5UGb=GDK*sTE}BzQ^Wwc$ z_U%nO`abGd9~(v0jCq)p`?<_4)XM_b(BDM!5ZA)DO;{x1IHLSeS(gI9SQihfJwf z7#1F;o4U)}VGZ%j!~!QIgACOhG&Tz(NnW04){${>5>RD$vitnpk|ManxG<&Fmd;slKMXy?_aE8L{bu6VbyLS& zUV-!qF)uYAJp!B?guD*VJeuyIn!pDKjJaRGegU-M@VO$5Shfb_CDz8ek0mCyJx$L| zOLZY0j7Wqb0DXQ^v>_0=5NZ_ad+hP!Sx>oADId8oULFBmSh2||ez=Uc@AN9Cbg1DQ;?SQ?1=Qe$&EZcD+Sm+)SR|=Hsds zkL&Cv)^+yg^s3l67cIeY1K)h)rQ>(m*}dNPvUpg&+SWp=o&kF_`YvjAngQm;E3E%s zyR^n}njPK(+_Laqa(pcBN}uY?@=5Y{_defjbUro0+(`wuGni7~q9h_B2MGbXkCU@A z=&jV?&B7~86If6S8yW4|R6I4P_N;X0+ZU$aIO)Wowf6KBaAk+(32+FQLQZ>cwr z_7-m^sjALZR3^bmIMuR7y^q8(`bYSN;F9(n(@Fm>J!f~2-P@yJn)_+4{TeDQU1;0e z^3_M?s#xp=pR2DwQu*9`NBjIKEIady=<_4ARG0r~X0S9Y+0f*o-qGO)@s8X6mAK0m zOc=5G%A78DzvK8y1b|TysHHlID|K}!ZUnkKt4)0ZQ)(%CbE&ZtAL9rVlP4qpjeqbW zkU6JesFrpSNG->8=SNc|m7D2%vK8NXU*WMHeS$tmh1^;yaxL2kV;E)-dp7w3<;NgP zv?1Y#YL+o(w=|9!9@Y0Disk+%!}Eju%Xz$aL zp_clEQq64eA;X2lV80+1qrgvLZMw*h=&{?%M+-b%kWRIMCMszKSb{Pf%ik~!6X=qhEL*Y%BQfZ1DN3Lph&nMH$wPEGE43bou z|6$skSfG`7gj<%rAts!~mKt$pR-3M{RN)Zl>S$zPX5JAuSD1TyPi>YEk320X%f&gw zR_jdrzBc~sV=wcAw#|Me^01|ZYK%;iysKq=E!F?-6BDE?mY+9qiO*%l?M=~lxqoF1 zIWVPLZT7@f{y=}}RrzG#nN%gF@@#17YgHT<((x4?ssN&C&pNzZ#s>-iX^U#5$16;~ zKKQn?N4*Xc!hK9*bCpi7S?9ItK!3{Fki?_$Aw?7#DMQnq1~lw7JKnP9^z>5#XlCDp z-ITmDA#OEc=Wa{>s9IZh-(fE8ioZ$^23Bsb;qm3B;hTZ*aKXeKgjrot-RgsY1Iy@*R|(AERm z$oBuJOfk`d8$#-7`jz4ISQWC;G5Z`jum13m**-8g^p;Up zfAa&#X*|N>RKIO8KC2B!;o{)1@Ag&%xh7;)#^CDU542(3*EY&~LHN*NrPv5H zrx;oL9i0XbKiKUND|9AM+4e__FP$?*mFWXjIN3TxZ;(PlXAOpzt944F%HY$g?KTaalC7tUWBTib$p%1xc+r(olJY#*Qs1?W}xAHrhc5fa+ea z!l;+~_K3R{4rm1Z7n1nzGBWZ@N-_r{RqBM`S}6c;qg4!j?pUqwv29=9Q-n#q-(AFW z>)D6_q1?0UQ(;6k7m1M)?Omn7n+cvEr)9O^5{z!T-b9{3;lay(K} zUn8WiSgye9=4tZcum9-vndF=Qg)D>lhF4H@bipN_@ByFr8>ahhDCsq;7W?G?O+0ol z^L*j8=0xrD^k$Qpk!w24i%qh&h~|>wwwdK zH0#%Ch7eqzDOpShLm|0=#z5hta_A2|ns7ScXV|s(dFd;hgH}Hefr)G>e=+Okk3Hs9 zs)wrB2Tc`V*L$H3gsYCVNW^#be%Wk!v4Kg4J7)~NYi(9`_6GF+VAbr)dj*$Vk@lUX zGqBhoaD(&ngP>sphHw+ny9o!Z2_wMoKP!I>leHcEXKQB%>{;vDd67-E)O<=RVsHgH zWEnZp_#Mc8oMy+y#s<}+_stO~%frA(voha>&QbboDKL=y$Gc_|-g8$ALm|l~oE)C4 z%y)ME_0qj-n!EjPjHWgW2>ZQ1B$q+is2$`S(HZ)~*~0AN?PFCVG*-f7<{gi?p0R{r z_2d5V+gn13qYp-h1B`DEfI}MsaE060dH2y6fc$}Gf(VWxfTq4s>~W`#zJA_h@-5yq zgg5vijBxSO+{nVI6Ho*Gz8)8OBeGP>$-%ly6>|7QgpuVjTk=Cr2Yl5&Iv~lbKYDZs zv;gF#Gx;bRacxz=$ig=qAH2wL62QZyrP`a^16E#P+(6FZsLXA}4@e-LST#*S_B7yF zI4~*Gtu1|ge7up=ls(1gPtzs6y=4WIGroPd80ND!0s{X1{h!=#uS6RDb3>QR3@ z#Zy!Tb)D|;Q?L=zJ#jIz;8MlHiz1hB{zX9LT6z7zsgEisOkhMSI;eN+LnW;oZOVLN zkz|Fy(&fzyil>4D`&VBB*8uz?0pArhzW*2nlimn^X84dy7-Um2U_AjlyQ~ech6?$S zSqVrF>hE}HOK{`84MW=dFQhtubXf$CjQgoIpV}0;HHz1^oS2B1FLtPW|G$mhhNRit0GfZq3|icV;RX(}qng=`v$T1oJ6BCMN=b z*VfL~-pz@TWJZ^al(dR7TD6FB^SU$A#rVA!0&Vb@nasaEszFvUZ{&i0L!~0?mh?7%Fu>~dU}k|SAci{JMJvMZFOte zzFbzn>Nt`?1M^^zTx6%a^QDq`e<5?Fi=bo{<;lbz%;f< zM8EfIF+(i;JtndM!NM0NE?rBJ%>7HR6J0tqU6R{>6|a16F08JG_T0MN?*ZA14Kl$Y zo4)Q#pZ76HUYlL@nn6A7d4W4eEVeb2p;=%aU0s!29I5%Lx8$oGvb_bR-KB6tP;N z=luM-Wv*H6Se0^aMw1DT)8i-?ay!ISYT7;M(- zI=TOJTP_%qTXor|scp4YwM%vBT=)eanFZ29hXKJ1+GVJU5Ro)0*Tx{kE(Wh~+LQw4 zVHAgNISeVP)sKbhU|fVxzQ^cAa&@mE{?Lvk)OPy)YTE4?PPRil!$V#ad7KjI53g64 ziexb{DkKW)9_P^N3RTHqNsQgSJN!6ZkusSZnIQQ~S7M%vp-;}8{&`hvgQ5cyk}AxU z{M{D^XGGY4xpe;&rYcm``Sjv+B}0NA@sH=xEZ#=iEC;#$l-J)xB72Y} z??56{f62PXP=_|W%%S*7`PI2_nDLz=D_sIAvO20+gMw$nHRWQir=Uwf8kYNxO>Dx% z<2RCTFxeqsVX^3)9raM)!$=K^ZnFv7aSxFuOcmjVdP~I&h2oCX*axM1(~Y=T+*y4* zrbpyW&Lqm3x$Am?_w_~gd;0IAcg$myE_H~XS9ZX_Tf*)pf#Lbo?_J4!-`&O zN|bAm%|;wlJJv=?l9ix1z~cZ3)~gmIDE8DfG+>A~`}7qT99k_Gqi&$F2sxXKNyEs` zr%gHVmglYXg+M9^<^{!GUZK)Ms&59VbeT>pOF3&@Jqqz@FQxh_S09dc9N@RNxM0A} zf!hdecA>-%yr8=s=?9+bgVw|&DEMSkG6|h3$b0-!>eXN8dwD(Mvdl!c5^yj>n+;ZY zs3!YGeQHFlZ*Q(ag@>{EJghK)@1on)1qs&i;VT04x}$`N)gIlTwj0^0!RMG(2kZ}y zJ%ap{m9yL&QIAR9z5DC1pV3K5U0CD5Nu@B&lv&S~MjV%<=oHB%*oD3)`yj0o+;OVt zlqN>;L%-iU+o;7XW3$P}87DL8hB(KSY zj6b_=oCWM(x7=Ru_rF*eeBq^)o^AJ&V@)mELxdPG7TC&^#mp@80eeDy8reNQ0UgW} z8F1>m|J^l=5kibZAcg~450GU+(hJ=nlNS0^h-G!eF;7^ci$6jAe;A)T%SGY&N=W)I zUI>F$0zwaC57Z}6YOnY{RsZSc8T#(XgHCChh($DWodi~}b{^-jfgqms*OUG}kBjNx)K{my0W($^dIK+Ul+TgGA? z9bGN-u%4hS4Eu}o{AqgUPxTHVBEmd@3BI~|0vz0L@qC81p}Xv8p<*+AN=CuS^&M18bKPlex=1TiieQ!Y(M(Z$vg^l=&X6hieoEvHa`Ew? zW)MH7mg#@XN3*m}{+==v^_H2nCV^g64L*E0lz{9^4dXOwZBQ}RDfoH0R-HTpkk6!QAKNYStrRoNV5W%EnJI;W(+cZmT2CP z;R5jFk~y&S5Ij2sg%a^W>y?@KZlrvFb+$QJJVDPit{f$xy&#g>S=qdD{*F#_#JZ-j z4bQ;7Pu?LY5xvNzN_*g&xY7?r6{B1mL+AOLFk`n?L8Y&Zy8MIpr~ttQBP_&tTD@xE z5*DOF@?zUl3=_Ypu@KkYD)x$2T-(T#}^mAu%485bM({B>Sa`P(%L)S zyKKl}OuQ5EiIh5CD#j>_carrBxvbV7E+0-IM+moQtxycuIh!o?lcLO?su;#QILUwL zFve1w{NWTrpgSZ*gYxAOGzn z*Y+l@kW6+vNbb>4`M7~)thBiOJHyJmLHNNVi{KM3AgTSHDxKqa;q5&W`Cuw<+Jg8A zh(}QMHkrghxKX*qfc2V)e;HgmhufNg3rL7OCWK0$z7E^D@F^aNY(1;C_<@gcm%2YY z+xEvd_L%*A9{Ys6?g#EG2WQ)?WQS2wqU@k(nMfm*HGlac3XCJ=xO*#+EIG>%l6{*n z&3a`Dc<&b96m5tnHtOPg^3oG{t6~^>bbNOvpC{P+>RuSiHCaG?|%aDrT8bT&| zq+(*Wc7eh|l>CdKsDJB3}#>5 z4HyL1nB{RLDH7S|i2Aa88o*l9VK097Zrj@HZ69`P37+qILxN9V{IFcx`GWt zx~lQN|H4ie*FP6g(M){qf}LmA%@?L^`}~4}Bx~F%DJj-x`bFBHMXX&)Ey48iqAB-M zlwVAY{i!!9NY5=Wi;BBFJRXyFlY)4iV!cZtSDNKwRUwaW#)Wo*Nk5X3X2E@OdS26= zXVzhDo(W_cQgQquQR<>5pLdK9tCOJDf}a*_vZxBUehFB0XyZ!d4Kf86gu_LK^f`&i zs$8g`VuGm*0tlEylypAy7MF48&hdo=K=NUM)5PSYyj1R6!S^&Tx9Abwvu!N|e(8$} zE8Drhc@ZXd=F#KPimHmG$T{BKxb$gb&K|}n@g6|sPF5Wm(MYNmOm#UJw?{!ylUf?g z5OkV@yYa2W5hiekVxE`4(N*QWX9U46gD>7Lrg4iO4735-ots-Jj+uY(fUrNBAqJDj zM0HDp4RMb60MQSA6ZW;~ROkVGfftE6bon2Z_wn3a+5$e`jIi1gHq5sZCJCLfi`6ZB z*iY}2w7%6YB@aE|Jyi|C`;bRAW=lbXBD|3_j5)MHc=1=@+LnvmA9Yf`pxSK5_0%1m3r9{Z>MK6>@dI_KVS{=F zZ+nh_Uwi?77bL9ubF4fZ#g@tKYGIH+@#6;~-PrgWwuB#bZgIfovGR`}NDctgEAoj5 z6%Q^~xR1dhsFFUF&m+bzOcLGuPRlALQaQ@!>GC|+aDFZ0SiQd4D6Dn)hMDCVp5BDg zYD&SWruB(^S6#fRp#lF2bNxyE_<37|i<;ls8dZd@n0&o5)4FfEFl%!kjioMpud({<*Pem*(6!V@jXVYh^^jo~N(vd0E1)f{)^Mw3+8mbhU zoM^22>@62uZmR>LWW%bw-s`;gDaBJt;1TZXaaY~oE3yppC{=Bfqz%tx`1Mrs-W-0P)hnqFXxoB zVu^OH@L8F*n3p;Hn2JSEVT_D`p24wb|C0C@me&VZO8MTu`AhTvkdT%2?_w8eKZ}aU zmiV+kKAFjqG#tK8934%RG{=XzV?wg-VE-YRgB7iT2`caBTg$Rh8`^#zFzcL~Gq}2e zc<>`*W8)u#xiNAKYq6@2$FH3iwfG9IYR5(otmh`r!ugbmkSsA`y8uDfTc}5zC2?Qwta&8647J z>m+VnSog4esC0&JHlMUKZJ^Yr9U*EbBL5s%G2rzXyl5=a7b-yJYeiG}&0-+;64dCC z>=$imj8-g-B9aj&9~*m7a#Fg7|LU-RAup)rNj4qrasIEJC+LA@K3}VI(?4dVBQ~)G zeu?^?dZS`ubuf~+P`pD|1}Oh`A@%qsN%zZc*V z?ASocqyg*uE(zmHEpK&1#qd*f-fvnR#lIRj zUz0G-Y@V0^+pwGOuyNzR-(|d*G(O9+pT0L|UyF8~2PY4N)9W8<43K7El(I4Dh_!!!`=5c8Moc=;2=; zReQt@*?rYI4;>go!2imP-WeZHPRyQDqUg}? z^H*L49fkZ5$%&yjr5ZdO90XW)VPRpFxPq4?>)pF$Y_s!V-+75D-f)O5XCMObK%K<0 zdG>E+jbyWGTx3Gdq1UeolEUJ3hujdgf^uM+9!g-nAn{Qk#y${)Ko$TV|xOh z;4LK8oEfdJlp|}VFS{&jswL;$NrFrgFk#$&KVsWv*r^oZk2#(*zXR_MtDZ%((9={>j z16XkXcWa8LL`Ayac603$>hi;hD-!e$3_Ksv(TlYdgmC;R!F$zTFq_DEjT!7cT9`2X zhAJUg^0fTs`PzekL__V+Oq@c*h|kLjNq@wYgJda{#5BcHdaX=)1hTC#0jo|esZDLIUq zYig2z6st~fte~L8dg;OawB;eVdAgTuyE`+HUk-+_4+@p(l>vCCxk_~Pw-S>mk*l8i zqZCFq$+CJ|N5?4OCZOAw$D5nqjz8aRwiO@S6W2V;aETd1cW!KGFqw90xziP zu#d`jy6h>5vO3Ji;eoh@i&e6$9-#4$;Gb7J8HmK&S*Vx0+|G7UdcO~2X-hfv@ z;xPPPjlZ0FTb{hvsj@w)7F&v8l2muLT!xxa)RV)(Ud2*rYHiVg*#U=*@jWx;z1FHK zd|I@@nJ;1$rObTQgZNSlTk|GyD^Jp@eTO%E+VWSMF)dayWzfvmiXRy?kPyuy3zaX) zl$zif*!6V@6ZWgXPFFG5_Ji-lplosc?b~A+KliNHoij6}5r?rWuC+A=+PHiurTI#s z&~I^QDBbg-u74S|u<~B6y2IM={&pDH;pBVcJB-EVAAHTpT(&b4MAHk;na(WLBN;lY z3M(aw2;4DV8mjpGa|jlALemL4!*j6JKqH4hjHj7;Q-J&fMtvSpQ3?>^&T4_34SZ|p zW%8hcK#VcK^jJ`D3q#%So|BINDgv_*1dRkC(}434VOU3OMS-t5Of9;TBd6T`dvy(uXtC#RXU#PCmM@|MGQ zxAA{4(m`;SM>Tt1`!6B(2p9k6xY?$<9ZI`hS^Dr2ixF+e8YDhR$yR?H9Gs*v>!xy! z(S~sX)eS=GZ0eJ<7yRF(U)wCgOmJx^NWMQ|JMJ->yg9=%9YGhfq!sZ4{jzEDxu^l0 z4G&RQm~rI3b?VTft~GfuOL;-{&pIiyW&Abcex}6ZP<&vQqoYU6wb)?8$e@Hrn)a&_ z-Y>?@BU9%uR~`!XCxCDk$J?2yD9~oJil>8~_S=$lM~c2lXYu$Wh1!IID?vx%w*v1H z>AeatU#&U0G3S&0s5GkJ6Bh2jy7G%hA;EGtwwbQz+ZR`5q!hN(mZ58VgqCeO{c$zy zf>{2?-pRrfld%%JXKz;hc=e1TKiM#?2fxbc2Pe}b*R~5=1Y8#o;pdm_x37>8@pE_@ zp)G)Os_l==^)KP}L6{`YngvRNy%lC89w%GlA{hQBs0!7Aw*jz?fyZna^Z*3GaMATkEMlVJfB6?iTAdM6C-hH`&7SJaYB!OL)nTzmGg%=W_rD&D-NhO~2qTf10D0u751`p7{ry>IVwuurY-KkL#V; zd6-!Td3TA_X(??W-mWiA#9eBkF7Na2WbJ*|(ta89=_(#g5&=bB&7)rkUNY!?uPU#7Vp;bd5Ktv!F869@G)%%YU;?lroh+ z2IGN*F^r9rhbc9{HJ+qGp|pN+uUY{u^~23Q!T0y2%am3hW>u#i`b>i$q5=Nzy_^gc{L0Imwjp6UQT8j z7#O@6KY$4nzmO1m2f{}HmSu#)7hy%FvhzF$L|ENK2io?*8rEHh0k`bM_0p|B*jEw5 z{g4n}bEH`>#7fgS@CJeki!f>B^J&Cs`rmL|E#_>xt6{IdiYQgj2J{fuwzGKA{2hr|8*f+8sU_mLwg$ZDc&?VK z{XM-rt6diL{Mv`GSu|wEZ0iy%;_2f1kgXVP9;cq)E`FI=ZurV~ofRGTr{+O}wRnw{ zc--Cxjf_I?h0t$%=o7;Ys9|Pk;fCaMd^pY#LFs!u-AL3o-Me4EdK=mfB^s)#y-2Jw zu5qzfRWUBFCkG3w*B;`zpZRih#LyAv_3RBu7I* zZn?d=gogwH)0aAo)O-)rE5H^XyljQ>6){bqNm0~G00p}rEX($Sm7j`m8Gxikg;-f8WR6G7llCkZ}|;OWCqN$KEr<>DXnIWY3h9 z8HKFuak8^lr<2IYQMQB#r6Tct&hO8k%XRs~ACC8UUe9yi&wbxJLACAeaI<2-TCZXv z;r3;4paR9_fA_B%$6T)@FYMMd(tv<@*G_-{A_Qp5d_SJ~VwRKDRc!~3w-kf*{na^) zIk`!?as;bnSN~wWDaZ;Wy0ZA-qX*roH zNLsb=lTXu?@Z7vu2mW;o-vX{sC4gTUIihe>1ggV=kAkBN&%*7?1tRqQkJ9>eqp}e$ z%g+2yRuwonsHnBN`iiG~PySx|dM?&?^9_wioT7?Uri!ww)xhqqG`MP`ZEO+&3_ds& zPi<#w8#RFehKdndMk5D@$J5i(sSmq>{sksB8c=OgWhur*+dorU1vwRL@-iVvmUb{C zZ~BG+1wu+9yAIamK@_BDswIG7WRll>6y8ry$AeYLdd=^>y(d@~{>L=%kaof9`OeJT z5t5XOL;4W#VgPq^;yVvi>-ooKNCn+ap zswTXl1yybPH?2pS8U(7HamvgFWRhKu$nB=T>pR;E>Ol+94}zO@RilR8 zDSHv#?f;lvY$z~PCp|Z>Y!h!CR~+aIrr5in9Tg|ise2>jX=S{1kdPO_?P4|1cK?9} z3NMhR)7`h6YU2zGY)TJT!*T^rN< zHtnxmZQn-f(w$v`D8sk@lCGGhd9ps_EoI^3cSfc76#Xb`+IQ&{9u@VoA>7OJr#94I zWtHq6tV?yWMB7G@m4#UFL$lO_Y3Oxo0%z48?5nPgs?wxxPOF$Mph|TLR1ye9I`K+AGAmZXAxUcQj(7X zA5gIUu&U85$#}ux^+N!rI7XC@mEbXqahFNBcz;dr4>-ta;i({%=+x6IfsY16K;2^a zS=E?DotCfB;H#ic57@MlAue_vN_WgcHs&_?qKj^@&Fc$CD%-V{)bhn1|Ji@w^7^oUWMOO`QHkVbniHV4y+VhtwhBU8_sJq z{9g-PAAy@mvM3Ev3c~S&odKM%jx}WRzIN~xi#&OTNUs;lwA{ZX6kXeP}yl8~gPA~2?U6?=J z`Abp8+gnwpHSFrWUycC*uLN00%iW}9!-PWgXL3SNWPxC(^*N9_3r#g>hi_v3e zzmN>#oqc_c@-~RXR2druJ}nfo7kXDFD7t77jc6LQL>}p-cjTr97XG`Wq+}Qc4Rd;! z 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

Fraf%{T3Oqo^Ca1RPo|Q!xS9?ZM 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 diff --git a/resources/profiles/MagicMaker/MM hj sk_cover.png b/resources/profiles/MagicMaker/MM hj SK_cover.png similarity index 100% rename from resources/profiles/MagicMaker/MM hj sk_cover.png rename to resources/profiles/MagicMaker/MM hj SK_cover.png diff --git a/resources/profiles/WonderMaker/WonderMaker ZR ULtra S_cover.png b/resources/profiles/WonderMaker/WonderMaker ZR Ultra S_cover.png similarity index 100% rename from resources/profiles/WonderMaker/WonderMaker ZR ULtra S_cover.png rename to resources/profiles/WonderMaker/WonderMaker ZR Ultra S_cover.png From 504a5d3b704fba8c0fac410cf9702f7bcf611f95 Mon Sep 17 00:00:00 2001 From: mosfet80 <10235105+mosfet80@users.noreply.github.com> Date: Fri, 2 Jan 2026 17:36:04 +0100 Subject: [PATCH 22/45] Update Qhull.cmake (#10848) # Description [Updated Qhull] changelog https://github.com/qhull/qhull/releases/tag/v8.0.2 # Screenshots/Recordings/Graphs ## Tests --- deps/Qhull/Qhull.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/Qhull/Qhull.cmake b/deps/Qhull/Qhull.cmake index 9376700428..97667021c0 100644 --- a/deps/Qhull/Qhull.cmake +++ b/deps/Qhull/Qhull.cmake @@ -1,11 +1,11 @@ include(GNUInstallDirs) orcaslicer_add_cmake_project(Qhull - URL "https://github.com/qhull/qhull/archive/v8.0.1.zip" - URL_HASH SHA256=5287f5edd6a0372588f5d6640799086a4033d89d19711023ef8229dd9301d69b + URL "https://github.com/qhull/qhull/archive/v8.0.2.zip" + URL_HASH SHA256=a378e9a39e718e289102c20d45632f873bfdc58a7a5f924246ea4b176e185f1e CMAKE_ARGS -DINCLUDE_INSTALL_DIR=${CMAKE_INSTALL_INCLUDEDIR} ) if (MSVC) add_debug_dep(dep_Qhull) -endif () \ No newline at end of file +endif () From bed3cf154a972b9de591050c20e9e035f7de2314 Mon Sep 17 00:00:00 2001 From: "Dipl.-Ing. Raoul Rubien, BSc" Date: Sat, 3 Jan 2026 09:30:14 +0100 Subject: [PATCH 23/45] Fixes 11 Compiler Warnings (#10753) * fixes: wxTimerEvent not supposed to be created by user code [-Wdeprecated-declarations] * use wxTimerEvent instead of wxCommandEvent. --------- Co-authored-by: SoftFever --- src/slic3r/GUI/CalibrationPanel.cpp | 6 +++--- src/slic3r/GUI/MultiMachineManagerPage.cpp | 2 +- src/slic3r/GUI/MultiMachinePage.cpp | 6 +++--- src/slic3r/GUI/MultiTaskManagerPage.cpp | 2 +- src/slic3r/GUI/SendMultiMachinePage.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/CalibrationPanel.cpp b/src/slic3r/GUI/CalibrationPanel.cpp index 055cbe905d..12162615aa 100644 --- a/src/slic3r/GUI/CalibrationPanel.cpp +++ b/src/slic3r/GUI/CalibrationPanel.cpp @@ -269,7 +269,7 @@ void SelectMObjectPopup::Popup(wxWindow* WXUNUSED(focus)) } } - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxTimerEvent(*m_refresh_timer)); PopupWindow::Popup(); } @@ -505,7 +505,7 @@ void CalibrationPanel::init_timer() m_refresh_timer = new wxTimer(); m_refresh_timer->SetOwner(this); m_refresh_timer->Start(REFRESH_INTERVAL); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxCommandEvent(wxEVT_TIMER)); } void CalibrationPanel::on_timer(wxTimerEvent& event) { @@ -634,7 +634,7 @@ bool CalibrationPanel::Show(bool show) { m_refresh_timer->Stop(); m_refresh_timer->SetOwner(this); m_refresh_timer->Start(REFRESH_INTERVAL); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxCommandEvent(wxEVT_TIMER)); DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); if (dev) { diff --git a/src/slic3r/GUI/MultiMachineManagerPage.cpp b/src/slic3r/GUI/MultiMachineManagerPage.cpp index 3956f89072..5b0ca791b7 100644 --- a/src/slic3r/GUI/MultiMachineManagerPage.cpp +++ b/src/slic3r/GUI/MultiMachineManagerPage.cpp @@ -653,7 +653,7 @@ void MultiMachineManagerPage::start_timer() m_flipping_timer->SetOwner(this); m_flipping_timer->Start(1000); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxTimerEvent(*m_flipping_timer)); } void MultiMachineManagerPage::update_page_number() diff --git a/src/slic3r/GUI/MultiMachinePage.cpp b/src/slic3r/GUI/MultiMachinePage.cpp index f7cb05a80e..b9b71ad670 100644 --- a/src/slic3r/GUI/MultiMachinePage.cpp +++ b/src/slic3r/GUI/MultiMachinePage.cpp @@ -61,7 +61,7 @@ bool MultiMachinePage::Show(bool show) m_refresh_timer->Stop(); m_refresh_timer->SetOwner(this); m_refresh_timer->Start(2000); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxTimerEvent(*m_refresh_timer)); } else { m_refresh_timer->Stop(); @@ -96,7 +96,7 @@ void MultiMachinePage::init_timer() m_refresh_timer = new wxTimer(); //m_refresh_timer->SetOwner(this); //m_refresh_timer->Start(8000); - //wxPostEvent(this, wxTimerEvent()); + //wxPostEvent(this, wxTimerEvent(*m_refresh_timer)); } void MultiMachinePage::on_timer(wxTimerEvent& event) @@ -482,7 +482,7 @@ bool MultiMachinePickPage::Show(bool show) //m_refresh_timer->Stop(); //m_refresh_timer->SetOwner(this); //m_refresh_timer->Start(4000); - //wxPostEvent(this, wxTimerEvent()); + //wxPostEvent(this, wxTimerEvent(*m_refresh_timer)); } else { //m_refresh_timer->Stop(); diff --git a/src/slic3r/GUI/MultiTaskManagerPage.cpp b/src/slic3r/GUI/MultiTaskManagerPage.cpp index 37321063f8..0b0b422eb4 100644 --- a/src/slic3r/GUI/MultiTaskManagerPage.cpp +++ b/src/slic3r/GUI/MultiTaskManagerPage.cpp @@ -1402,7 +1402,7 @@ void CloudTaskManagerPage::start_timer() m_flipping_timer->SetOwner(this); m_flipping_timer->Start(1000); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxTimerEvent(*m_flipping_timer)); } void CloudTaskManagerPage::on_timer(wxTimerEvent& event) diff --git a/src/slic3r/GUI/SendMultiMachinePage.cpp b/src/slic3r/GUI/SendMultiMachinePage.cpp index 1060dc253c..3578e4047c 100644 --- a/src/slic3r/GUI/SendMultiMachinePage.cpp +++ b/src/slic3r/GUI/SendMultiMachinePage.cpp @@ -801,7 +801,7 @@ bool SendMultiMachinePage::Show(bool show) m_refresh_timer->Stop(); m_refresh_timer->SetOwner(this); m_refresh_timer->Start(4000); - wxPostEvent(this, wxTimerEvent()); + wxPostEvent(this, wxTimerEvent(*m_refresh_timer)); } else { m_refresh_timer->Stop(); From a2c90e2de4784aafd8412eefc1b6bb93e1fe61a6 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 3 Jan 2026 17:52:19 +0800 Subject: [PATCH 24/45] deploy doxygen doc to internals.orcaslicer.com --- .doxygen | 6 ++--- .github/workflows/doxygen-docs.yml | 41 ++++++++++++++++++++++++++++++ .gitignore | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/doxygen-docs.yml diff --git a/.doxygen b/.doxygen index fb8ae5f045..8d9f2471f6 100644 --- a/.doxygen +++ b/.doxygen @@ -48,7 +48,7 @@ PROJECT_NAME = OrcaSlicer # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.6.3 +PROJECT_NUMBER = latest # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -68,7 +68,7 @@ PROJECT_LOGO = ./resources/images/OrcaSlicer_32px.png # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = ../ +OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format @@ -1286,7 +1286,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = OrcaSlicer_Dev_Document +HTML_OUTPUT = internal_docs # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/.github/workflows/doxygen-docs.yml b/.github/workflows/doxygen-docs.yml new file mode 100644 index 0000000000..ad48aab77d --- /dev/null +++ b/.github/workflows/doxygen-docs.yml @@ -0,0 +1,41 @@ +name: Generate Doxygen Documentation + +on: + schedule: + - cron: '0 0 * * 1' # Every Monday at midnight UTC + workflow_dispatch: # Manual trigger + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + build-and-deploy: + name: Build and Deploy Docs + runs-on: ubuntu-latest + # Only run on main branch of the main repository + if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Install Doxygen and Graphviz + run: | + sudo apt-get update + sudo apt-get install -y doxygen graphviz + + - name: Generate documentation + run: | + doxygen .doxygen + # Verify documentation was generated + if [ ! -f "internal_docs/index.html" ]; then + echo "Error: Documentation generation failed - index.html not found" + exit 1 + fi + + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy internal_docs --project-name=orcaslicer-internals diff --git a/.gitignore b/.gitignore index 09abcc8dee..5b369a47fe 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ deps_src/build/ test.js /.cache/ .clangd +internal_docs/ From 06544bce9de3a0fb3246cb0a9e4f10e0be043ecf Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 3 Jan 2026 18:02:42 +0800 Subject: [PATCH 25/45] Update Doxygen workflow to set DOT_NUM_THREADS to 1 to prevent parallel processing issues --- .github/workflows/doxygen-docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/doxygen-docs.yml b/.github/workflows/doxygen-docs.yml index ad48aab77d..61e47b4873 100644 --- a/.github/workflows/doxygen-docs.yml +++ b/.github/workflows/doxygen-docs.yml @@ -26,6 +26,8 @@ jobs: - name: Generate documentation run: | + # Override DOT_NUM_THREADS to avoid parallel dot race condition bug + sed -i 's/^DOT_NUM_THREADS.*/DOT_NUM_THREADS = 1/' .doxygen doxygen .doxygen # Verify documentation was generated if [ ! -f "internal_docs/index.html" ]; then From 0bee82cee54a4df3dc665d0f7b6029d74c3e8a23 Mon Sep 17 00:00:00 2001 From: yw4z Date: Sat, 3 Jan 2026 18:06:57 +0300 Subject: [PATCH 26/45] Hyperlink class (#9947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### FIXES • 3mf file version check dialog opens bambu releases page instead Orca ### CODE COMPARISON Screenshot-20251128125737 **wxHyperlinkCtrl** • System decides what colors to use. so blue color is visible even with colors set • No need to use SetCursor() ``` auto wiki_url = "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables"; wxHyperlinkCtrl* wiki = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide"), wiki_url); wiki->SetToolTip(wiki_url); // required to showing navigation point to user wiki->SetFont(Label::Body_14); // not works properly wiki->SetVisitedColour(wxColour("#009687")); // not works properly wiki->SetHoverColour( wxColour("#26A69A")); // not works properly wiki->SetNormalColour( wxColour("#009687")); // not works properly ``` Screenshot-20251128125847 **wxStaticText** • Works reliably on colors and fonts • All event has to defined manually ``` wxStaticText* wiki = new wxStaticText(this, wxID_ANY, _L("Wiki Guide")); auto wiki_url = "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables"; wiki->SetToolTip(wiki_url); // required to showing navigation point to user wiki->SetForegroundColour(wxColour("#009687")); wiki->SetCursor(wxCURSOR_HAND); wxFont font = Label::Body_14; font.SetUnderlined(true); wiki->SetFont(font); wiki->Bind(wxEVT_LEFT_DOWN ,[this, wiki_url](wxMouseEvent e) {wxLaunchDefaultBrowser(wiki_url);}); wiki->Bind(wxEVT_ENTER_WINDOW,[this, wiki ](wxMouseEvent e) {SetForegroundColour(wxColour("#26A69A"));}); wiki->Bind(wxEVT_LEAVE_WINDOW,[this, wiki ](wxMouseEvent e) {SetForegroundColour(wxColour("#009687"));}); ``` Screenshot-20251128125847 **HyperLink** • Fully automated and single line solution • Colors can be controllable from one place • Works reliably on colors and fonts • Reduces duplicate code ``` HyperLink* wiki = new HyperLink(this, _L("Wiki Guide"), "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables"); wiki->SetFont(Label::Body_14) // OPTIONAL default is Label::Body_14; ``` ### CHANGES • Unifies all hyperlinks with same style and makes them controllable from one place • Replaces all wxHyperlink with simple custom class. Problem with wxHyperlink it mostly rendered as blue even color set • Reduces duplicate code • Adds wiki links for calibration dialogs • Probably will add "Wiki Guide" to more dialogs overtime Screenshot-20251127212007 Screenshot-20251127212021 Screenshot-20251127212046 Screenshot-20250824171339 Screenshot-20251127212403 Screenshot-20251127212515 Screenshot-20251127212541 Screenshot-20251127213243 --- src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/AMSMaterialsSetting.cpp | 6 +- src/slic3r/GUI/AMSMaterialsSetting.hpp | 4 +- src/slic3r/GUI/BindDialog.cpp | 41 ++------ src/slic3r/GUI/BindDialog.hpp | 8 +- src/slic3r/GUI/CalibrationWizardPage.cpp | 15 +-- src/slic3r/GUI/CalibrationWizardPage.hpp | 3 +- src/slic3r/GUI/CreatePresetsDialog.cpp | 5 +- src/slic3r/GUI/DownloadProgressDialog.cpp | 8 +- src/slic3r/GUI/FilamentGroupPopup.cpp | 9 +- src/slic3r/GUI/GUI_App.cpp | 10 +- src/slic3r/GUI/GUI_App.hpp | 4 +- src/slic3r/GUI/MsgDialog.cpp | 15 ++- src/slic3r/GUI/MsgDialog.hpp | 5 +- src/slic3r/GUI/NotificationManager.hpp | 2 +- src/slic3r/GUI/ObjColorDialog.cpp | 9 +- src/slic3r/GUI/PrintOptionsDialog.cpp | 10 +- src/slic3r/GUI/PrintOptionsDialog.hpp | 5 +- src/slic3r/GUI/ReleaseNote.cpp | 3 +- src/slic3r/GUI/ReleaseNote.hpp | 2 +- src/slic3r/GUI/SelectMachine.cpp | 7 +- src/slic3r/GUI/SelectMachine.hpp | 3 +- src/slic3r/GUI/SelectMachinePop.cpp | 5 +- src/slic3r/GUI/SelectMachinePop.hpp | 2 +- src/slic3r/GUI/SendToPrinter.cpp | 6 +- src/slic3r/GUI/SendToPrinter.hpp | 2 +- src/slic3r/GUI/StepMeshDialog.cpp | 13 +-- src/slic3r/GUI/WebUserLoginDialog.cpp | 8 +- src/slic3r/GUI/Widgets/HyperLink.cpp | 49 ++++++++++ src/slic3r/GUI/Widgets/HyperLink.hpp | 26 +++++ src/slic3r/GUI/Widgets/SideTools.cpp | 11 +-- src/slic3r/GUI/Widgets/SideTools.hpp | 6 +- src/slic3r/GUI/calib_dlg.cpp | 114 +++++++++++----------- 33 files changed, 222 insertions(+), 196 deletions(-) create mode 100644 src/slic3r/GUI/Widgets/HyperLink.cpp create mode 100644 src/slic3r/GUI/Widgets/HyperLink.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index ca4f9c4123..69875f4ca6 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -492,6 +492,8 @@ set(SLIC3R_GUI_SOURCES GUI/Widgets/ErrorMsgStaticText.hpp GUI/Widgets/FanControl.cpp GUI/Widgets/FanControl.hpp + GUI/Widgets/HyperLink.cpp + GUI/Widgets/HyperLink.hpp GUI/Widgets/ImageSwitchButton.cpp GUI/Widgets/ImageSwitchButton.hpp GUI/Widgets/Label.cpp diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index a649f6b833..19a32c2d21 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -298,11 +298,7 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent) if (language.find("zh") == 0) region = "zh"; wxString link_url = wxString::Format("https://wiki.bambulab.com/%s/software/bambu-studio/calibration_pa", region); - m_wiki_ctrl = new wxHyperlinkCtrl(parent, wxID_ANY, "Wiki", link_url); - m_wiki_ctrl->SetNormalColour(*wxBLUE); - m_wiki_ctrl->SetHoverColour(wxColour(0, 0, 200)); - m_wiki_ctrl->SetVisitedColour(*wxBLUE); - m_wiki_ctrl->SetFont(Label::Head_14); + m_wiki_ctrl = new HyperLink(parent, "Wiki Guide", link_url); cali_title_sizer->Add(m_ratio_text, 0, wxALIGN_CENTER_VERTICAL); cali_title_sizer->Add(m_wiki_ctrl, 0, wxALIGN_CENTER_VERTICAL); diff --git a/src/slic3r/GUI/AMSMaterialsSetting.hpp b/src/slic3r/GUI/AMSMaterialsSetting.hpp index c678ec0717..84688896e6 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.hpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.hpp @@ -14,8 +14,8 @@ #include "Widgets/CheckBox.hpp" #include "Widgets/ComboBox.hpp" #include "Widgets/TextInput.hpp" +#include "Widgets/HyperLink.hpp" #include "slic3r/Utils/CalibUtils.hpp" -#include #define AMS_MATERIALS_SETTING_DEF_COLOUR wxColour(255, 255, 255) #define AMS_MATERIALS_SETTING_GREY900 wxColour(38, 46, 48) @@ -174,7 +174,7 @@ protected: wxPanel * m_panel_kn; wxStaticText* m_ratio_text; - wxHyperlinkCtrl * m_wiki_ctrl; + HyperLink * m_wiki_ctrl; wxStaticText* m_k_param; TextInput* m_input_k_val; wxStaticText* m_n_param; diff --git a/src/slic3r/GUI/BindDialog.cpp b/src/slic3r/GUI/BindDialog.cpp index 7610fbe820..3847f8f2f1 100644 --- a/src/slic3r/GUI/BindDialog.cpp +++ b/src/slic3r/GUI/BindDialog.cpp @@ -98,18 +98,8 @@ PingCodeBindDialog::PingCodeBindDialog(Plater* plater /*= nullptr*/) m_status_text->Wrap(FromDIP(440)); m_status_text->SetForegroundColour(wxColour(38, 46, 48)); - m_link_show_ping_code_wiki = new wxStaticText(request_bind_panel, wxID_ANY, _L("Can't find Pin Code?")); - m_link_show_ping_code_wiki->SetFont(Label::Body_14); - m_link_show_ping_code_wiki->SetBackgroundColour(*wxWHITE); - m_link_show_ping_code_wiki->SetForegroundColour(wxColour(31, 142, 234)); - - m_link_show_ping_code_wiki->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_link_show_ping_code_wiki->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); - - m_link_show_ping_code_wiki->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { - m_ping_code_wiki = "https://wiki.bambulab.com/en/bambu-studio/manual/pin-code"; - wxLaunchDefaultBrowser(m_ping_code_wiki); - }); + // ORCA standardized HyperLink + m_link_show_ping_code_wiki = new HyperLink(request_bind_panel, _L("Can't find Pin Code?"), "https://wiki.bambulab.com/en/bambu-studio/manual/pin-code"); m_text_input_title = new wxStaticText(request_bind_panel, wxID_ANY, _L("Pin Code")); m_text_input_title->SetFont(Label::Body_14); @@ -453,11 +443,11 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_st_privacy_title->SetFont(Label::Body_13); m_st_privacy_title->SetForegroundColour(wxColour(38, 46, 48)); - auto m_link_Terms_title = new Label(m_panel_agreement, _L("Terms and Conditions")); + // ORCA standardized HyperLink + auto m_link_Terms_title = new HyperLink(m_panel_agreement, _L("Terms and Conditions")); m_link_Terms_title->SetFont(Label::Head_13); m_link_Terms_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_Terms_title->Wrap(FromDIP(450)); - m_link_Terms_title->SetForegroundColour(wxColour("#009688")); m_link_Terms_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { wxString txt = _L("Thank you for purchasing a Bambu Lab device. Before using your Bambu Lab device, please read the terms and conditions. " "By clicking to agree to use your Bambu Lab device, you agree to abide by the Privacy Policy and Terms of Use (collectively, the \"Terms\"). " @@ -467,18 +457,16 @@ PingCodeBindDialog::~PingCodeBindDialog() { confirm_dlg.CenterOnParent(); confirm_dlg.on_show(); }); - m_link_Terms_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_link_Terms_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); auto m_st_and_title = new Label(m_panel_agreement, _L("and")); m_st_and_title->SetFont(Label::Body_13); m_st_and_title->SetForegroundColour(wxColour(38, 46, 48)); - auto m_link_privacy_title = new Label(m_panel_agreement, _L("Privacy Policy")); + // ORCA standardized HyperLink + auto m_link_privacy_title = new HyperLink(m_panel_agreement, _L("Privacy Policy")); m_link_privacy_title->SetFont(Label::Head_13); m_link_privacy_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_privacy_title->Wrap(FromDIP(450)); - m_link_privacy_title->SetForegroundColour(wxColour("#009688")); m_link_privacy_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { std::string url; std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code(); @@ -491,8 +479,6 @@ PingCodeBindDialog::~PingCodeBindDialog() { } wxLaunchDefaultBrowser(url); }); - m_link_privacy_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND);}); - m_link_privacy_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW);}); sizere_notice_agreement->Add(0, 0, 0, wxTOP, FromDIP(4)); sizer_privacy_agreement->Add(m_st_privacy_title, 0, wxALIGN_CENTER, 0); @@ -514,13 +500,11 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_st_notice_title->SetFont(Label::Body_13); m_st_notice_title->SetForegroundColour(wxColour(38, 46, 48)); - auto m_link_notice_title = new Label(m_panel_agreement, notice_link_title); + // ORCA standardized HyperLink + auto m_link_notice_title = new HyperLink(m_panel_agreement, notice_link_title); m_link_notice_title->SetFont(Label::Head_13); m_link_notice_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_notice_title->Wrap(FromDIP(450)); - m_link_notice_title->SetForegroundColour(wxColour("#009688")); - m_link_notice_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_link_notice_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); m_link_notice_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { wxString txt = _L("In the 3D Printing community, we learn from each other's successes and failures to adjust " "our own slicing parameters and settings. %s follows the same principle and uses machine " @@ -580,13 +564,8 @@ PingCodeBindDialog::~PingCodeBindDialog() { wxBoxSizer* m_sizer_bind_failed_info = new wxBoxSizer(wxVERTICAL); m_sw_bind_failed_info->SetSizer( m_sizer_bind_failed_info ); - m_link_network_state = new wxHyperlinkCtrl(m_sw_bind_failed_info, wxID_ANY,_L("Check the status of current system services"),""); - m_link_network_state->SetFont(::Label::Body_12); - m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); }); - m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); }); - m_link_network_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_ARROW); }); - - + // ORCA standardized HyperLink + m_link_network_state = new HyperLink(m_sw_bind_failed_info, _L("Check the status of current system services"), wxGetApp().link_to_network_check()); wxBoxSizer* sizer_error_code = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL); diff --git a/src/slic3r/GUI/BindDialog.hpp b/src/slic3r/GUI/BindDialog.hpp index a4ffd8fbff..b809bc523b 100644 --- a/src/slic3r/GUI/BindDialog.hpp +++ b/src/slic3r/GUI/BindDialog.hpp @@ -17,13 +17,13 @@ #include #include #include -#include #include "wxExtensions.hpp" #include "Widgets/StepCtrl.hpp" #include "Widgets/ProgressDialog.hpp" #include "Widgets/Button.hpp" #include "Widgets/ProgressBar.hpp" #include "Widgets/RoundedRectangle.hpp" +#include "Widgets/HyperLink.hpp" #include "Jobs/BindJob.hpp" #include "BBLStatusBar.hpp" #include "BBLStatusBarBind.hpp" @@ -56,7 +56,7 @@ private: Label* m_status_text; wxStaticText* m_text_input_title; - wxStaticText* m_link_show_ping_code_wiki; + HyperLink* m_link_show_ping_code_wiki; // ORCA TextInput* m_text_input_single_code[PING_CODE_LENGTH]; Button* m_button_bind; Button* m_button_cancel; @@ -70,7 +70,7 @@ private: Label* m_st_txt_error_code{ nullptr }; Label* m_st_txt_error_desc{ nullptr }; Label* m_st_txt_extra_info{ nullptr }; - wxHyperlinkCtrl* m_link_network_state{ nullptr }; + HyperLink* m_link_network_state{ nullptr }; wxString m_result_info; wxString m_result_extra; wxString m_ping_code_wiki; @@ -114,7 +114,7 @@ private: Label* m_st_txt_error_code{ nullptr }; Label* m_st_txt_error_desc{ nullptr }; Label* m_st_txt_extra_info{ nullptr }; - wxHyperlinkCtrl* m_link_network_state{ nullptr }; + HyperLink* m_link_network_state{ nullptr }; wxString m_result_info; wxString m_result_extra; bool m_show_error_info_state = true; diff --git a/src/slic3r/GUI/CalibrationWizardPage.cpp b/src/slic3r/GUI/CalibrationWizardPage.cpp index 3da543e79d..13e7023190 100644 --- a/src/slic3r/GUI/CalibrationWizardPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPage.cpp @@ -466,21 +466,12 @@ void CaliPageCaption::init_bitmaps() { void CaliPageCaption::create_wiki(wxWindow* parent) { - m_wiki_text = new Label(parent, _L("Wiki")); - m_wiki_text->SetFont(Label::Head_14); - m_wiki_text->SetForegroundColour({ 0, 88, 220 }); - m_wiki_text->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent& e) { - e.Skip(); - SetCursor(wxCURSOR_HAND); - }); - m_wiki_text->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) { - e.Skip(); - SetCursor(wxCURSOR_ARROW); - }); + // ORCA standardized HyperLink + m_wiki_text = new HyperLink(parent, _L("Wiki Guide")); m_wiki_text->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) { if (!m_wiki_url.empty()) wxLaunchDefaultBrowser(m_wiki_url); - }); + }); } void CaliPageCaption::show_prev_btn(bool show) diff --git a/src/slic3r/GUI/CalibrationWizardPage.hpp b/src/slic3r/GUI/CalibrationWizardPage.hpp index d03979cd55..524b1a6029 100644 --- a/src/slic3r/GUI/CalibrationWizardPage.hpp +++ b/src/slic3r/GUI/CalibrationWizardPage.hpp @@ -7,6 +7,7 @@ #include "Widgets/TextInput.hpp" #include "Widgets/AMSControl.hpp" #include "Widgets/ProgressBar.hpp" +#include "Widgets/HyperLink.hpp" #include "wxExtensions.hpp" #include "PresetComboBoxes.hpp" @@ -140,7 +141,7 @@ private: void init_bitmaps(); void create_wiki(wxWindow* parent); - Label* m_wiki_text; + HyperLink* m_wiki_text; // ORCA wxString m_wiki_url; ScalableBitmap m_prev_bmp_normal; ScalableBitmap m_prev_bmp_hover; diff --git a/src/slic3r/GUI/CreatePresetsDialog.cpp b/src/slic3r/GUI/CreatePresetsDialog.cpp index 7eb3beda82..269cd6ed12 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.cpp +++ b/src/slic3r/GUI/CreatePresetsDialog.cpp @@ -17,6 +17,7 @@ #include "Tab.hpp" #include "MainFrame.hpp" #include "libslic3r_version.h" +#include "Widgets/HyperLink.hpp" // ORCA #define NAME_OPTION_COMBOBOX_SIZE wxSize(FromDIP(200), FromDIP(24)) #define FILAMENT_PRESET_COMBOBOX_SIZE wxSize(FromDIP(300), FromDIP(24)) @@ -5027,8 +5028,8 @@ wxPanel *PresetTree::get_child_item(wxPanel *parent, std::shared_ptr pre bool base_id_error = false; if (preset->inherits() == "" && preset->base_id != "") base_id_error = true; if (base_id_error) { - std::string wiki_url = "https://wiki.bambulab.com/en/software/bambu-studio/custom-filament-issue"; - wxHyperlinkCtrl *m_download_hyperlink = new wxHyperlinkCtrl(panel, wxID_ANY, _L("[Delete Required]"), wiki_url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); + // ORCA standardized HyperLink + HyperLink *m_download_hyperlink = new HyperLink(panel, _L("[Delete Required]"), "https://wiki.bambulab.com/en/software/bambu-studio/custom-filament-issue"); m_download_hyperlink->SetFont(Label::Body_10); sizer->Add(m_download_hyperlink, 0, wxEXPAND | wxALL, 5); } diff --git a/src/slic3r/GUI/DownloadProgressDialog.cpp b/src/slic3r/GUI/DownloadProgressDialog.cpp index 1c4f7a9bfb..5f3624c469 100644 --- a/src/slic3r/GUI/DownloadProgressDialog.cpp +++ b/src/slic3r/GUI/DownloadProgressDialog.cpp @@ -23,6 +23,8 @@ #include "Jobs/BoostThreadWorker.hpp" #include "Jobs/PlaterWorker.hpp" +#include "Widgets/HyperLink.hpp" // ORCA + #define DESIGN_INPUT_SIZE wxSize(FromDIP(100), -1) namespace Slic3r { @@ -72,7 +74,8 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title) sizer_download_failed->Add(m_statictext_download_failed, 0, wxALIGN_CENTER | wxALL, 5); - auto m_download_hyperlink = new wxHyperlinkCtrl(m_panel_download_failed, wxID_ANY, _L("click here to see more info"), download_failed_url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); + // ORCA standardized HyperLink + auto m_download_hyperlink = new HyperLink(m_panel_download_failed, _L("click here to see more info"), download_failed_url); sizer_download_failed->Add(m_download_hyperlink, 0, wxALIGN_CENTER | wxALL, 5); @@ -93,7 +96,8 @@ DownloadProgressDialog::DownloadProgressDialog(wxString title) sizer_install_failed->Add(m_statictext_install_failed, 0, wxALIGN_CENTER | wxALL, 5); - auto m_install_hyperlink = new wxHyperlinkCtrl(m_panel_install_failed, wxID_ANY, _L("click here to see more info"), install_failed_url, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); + // ORCA standardized HyperLink + auto m_install_hyperlink = new HyperLink(m_panel_install_failed, _L("click here to see more info"), install_failed_url); sizer_install_failed->Add(m_install_hyperlink, 0, wxALIGN_CENTER | wxALL, 5); diff --git a/src/slic3r/GUI/FilamentGroupPopup.cpp b/src/slic3r/GUI/FilamentGroupPopup.cpp index 89c9dbd8de..df78e69a80 100644 --- a/src/slic3r/GUI/FilamentGroupPopup.cpp +++ b/src/slic3r/GUI/FilamentGroupPopup.cpp @@ -147,15 +147,10 @@ FilamentGroupPopup::FilamentGroupPopup(wxWindow *parent) : PopupWindow(parent, w { wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); - const std::string wiki_path = Slic3r::resources_dir() + "/wiki/filament_group_wiki_zh.html"; + const std::string wiki_path = Slic3r::resources_dir() + "/wiki/filament_group_wiki_zh.html"; // NEEDFIX this link is broken auto* wiki_sizer = new wxBoxSizer(wxHORIZONTAL); - wiki_link = new wxStaticText(this, wxID_ANY, _L("Learn more")); - wiki_link->SetBackgroundColour(BackGroundColor); - wiki_link->SetForegroundColour(GreenColor); - wiki_link->SetFont(Label::Body_12.Underlined()); - wiki_link->SetCursor(wxCursor(wxCURSOR_HAND)); - wiki_link->Bind(wxEVT_LEFT_DOWN, [wiki_path](wxMouseEvent &) { wxLaunchDefaultBrowser(wxString(wiki_path.c_str())); }); + wiki_link = new HyperLink(this, _L("Wiki Guide"), wxString(wiki_path.c_str())); // ORCA wiki_sizer->Add(wiki_link, 0, wxALIGN_CENTER | wxALL, FromDIP(3)); button_sizer->Add(wiki_sizer, 0, wxLEFT, horizontal_margin); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 27816e2b67..2fd25bd520 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3414,7 +3414,7 @@ void GUI_App::set_side_menu_popup_status(bool status) m_side_popup_status = status; } -void GUI_App::link_to_network_check() +std::string GUI_App::link_to_network_check() { std::string url; std::string country_code = app_config->get_country_code(); @@ -3429,10 +3429,11 @@ void GUI_App::link_to_network_check() else { url = "https://status.bambulab.com"; } - wxLaunchDefaultBrowser(url); + //wxLaunchDefaultBrowser(url); + return url; // ORCA } -void GUI_App::link_to_lan_only_wiki() +std::string GUI_App::link_to_lan_only_wiki() { std::string url; std::string country_code = app_config->get_country_code(); @@ -3446,7 +3447,8 @@ void GUI_App::link_to_lan_only_wiki() else { url = "https://wiki.bambulab.com/en/knowledge-sharing/enable-lan-mode"; } - wxLaunchDefaultBrowser(url); + //wxLaunchDefaultBrowser(url); + return url; // ORCA } bool GUI_App::tabs_as_menu() const diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index fbf61a5084..e8b696f7d3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -406,8 +406,8 @@ public: //update side popup status bool get_side_menu_popup_status(); void set_side_menu_popup_status(bool status); - void link_to_network_check(); - void link_to_lan_only_wiki(); + std::string link_to_network_check(); // ORCA + std::string link_to_lan_only_wiki(); // ORCA const wxColour& get_label_clr_modified() { return m_color_label_modified; } const wxColour& get_label_clr_sys() { return m_color_label_sys; } diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 0e6e1a324d..049a6b00f2 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -586,7 +586,8 @@ wxBoxSizer *Newer3mfVersionDialog::get_msg_sizer() if (file_version_newer) { text1 = new wxStaticText(this, wxID_ANY, _L("The 3MF file version is in Beta and it is newer than the current OrcaSlicer version.")); wxStaticText * text2 = new wxStaticText(this, wxID_ANY, _L("If you would like to try Orca Slicer Beta, you may click to")); - wxHyperlinkCtrl *github_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Download Beta Version"), "https://github.com/bambulab/BambuStudio/releases"); + // ORCA standardized HyperLink + HyperLink * github_link = new HyperLink(this, _L("Download Beta Version"), "https://github.com/SoftFever/OrcaSlicer/releases"); horizontal_sizer->Add(text2, 0, wxEXPAND, 0); horizontal_sizer->Add(github_link, 0, wxEXPAND | wxLEFT, 5); @@ -672,11 +673,9 @@ NetworkErrorDialog::NetworkErrorDialog(wxWindow* parent) wxBoxSizer* sizer_link = new wxBoxSizer(wxVERTICAL); - m_link_server_state = new wxHyperlinkCtrl(this, wxID_ANY, _L("Check the status of current system services"), ""); + // ORCA standardized HyperLink + m_link_server_state = new HyperLink(this, _L("Check the status of current system services"), wxGetApp().link_to_network_check()); m_link_server_state->SetFont(::Label::Body_13); - m_link_server_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); }); - m_link_server_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_link_server_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); sizer_link->Add(m_link_server_state, 0, wxALL, 0); @@ -690,11 +689,9 @@ NetworkErrorDialog::NetworkErrorDialog(wxWindow* parent) m_text_proposal->SetFont(::Label::Body_14); m_text_proposal->SetForegroundColour(0x323A3C); - m_text_wiki = new wxHyperlinkCtrl(this, wxID_ANY, _L("How to use LAN only mode"), ""); + // ORCA standardized HyperLink + m_text_wiki = new HyperLink(this, _L("How to use LAN only mode"), wxGetApp().link_to_lan_only_wiki()); m_text_wiki->SetFont(::Label::Body_13); - m_text_wiki->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_lan_only_wiki(); }); - m_text_wiki->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); - m_text_wiki->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); sizer_help->Add(m_text_proposal, 0, wxEXPAND, 0); sizer_help->Add(m_text_wiki, 0, wxALL, 0); diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index 7b4eb71612..bb3abde75c 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -14,6 +14,7 @@ #include "Widgets/Button.hpp" #include "Widgets/CheckBox.hpp" #include "Widgets/TextInput.hpp" +#include "Widgets/HyperLink.hpp" #include "BBLStatusBar.hpp" #include "BBLStatusBarSend.hpp" #include "libslic3r/Semver.hpp" @@ -424,9 +425,9 @@ public: private: Label* m_text_basic; - wxHyperlinkCtrl* m_link_server_state; + HyperLink* m_link_server_state; // ORCA Label* m_text_proposal; - wxHyperlinkCtrl* m_text_wiki; + HyperLink* m_text_wiki; // ORCA Button * m_button_confirm; public: diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 9abf49323a..c9bb132f68 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -980,7 +980,7 @@ private: NotificationData{NotificationType::BBLUserPresetExceedLimit, NotificationLevel::WarningNotificationLevel, BBL_NOTICE_MAX_INTERVAL, _u8L("The number of user presets cached in the cloud has exceeded the upper limit, newly created user presets can only be used locally."), - _u8L("Wiki"), + _u8L("Wiki Guide"), [](wxEvtHandler* evnthndlr) { wxLaunchDefaultBrowser("https://wiki.bambulab.com/en/software/bambu-studio/3rd-party-printer-profile#cloud-user-presets-limit"); return false; diff --git a/src/slic3r/GUI/ObjColorDialog.cpp b/src/slic3r/GUI/ObjColorDialog.cpp index 6d3b277c03..7575777507 100644 --- a/src/slic3r/GUI/ObjColorDialog.cpp +++ b/src/slic3r/GUI/ObjColorDialog.cpp @@ -47,14 +47,7 @@ wxBoxSizer* ObjColorDialog::create_btn_sizer(long flags,bool exist_error) auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); if (!exist_error) { btn_sizer->AddSpacer(FromDIP(25)); - wxStaticText *tips = new wxStaticText(this, wxID_ANY, _L("Open Wiki for more information >")); - /* wxFont font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false); - font.SetUnderlined(true); - tips->SetFont(font);*/ - auto font = tips->GetFont(); - font.SetUnderlined(true); - tips->SetFont(font); - tips->SetForegroundColour(wxColour("#009687")); + auto *tips = new HyperLink(this, _L("Wiki Guide")); // ORCA tips->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { bool is_zh = wxGetApp().app_config->get("language") == "zh_CN"; if (is_zh) { diff --git a/src/slic3r/GUI/PrintOptionsDialog.cpp b/src/slic3r/GUI/PrintOptionsDialog.cpp index 02329a36b7..56cc764356 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.cpp +++ b/src/slic3r/GUI/PrintOptionsDialog.cpp @@ -1153,11 +1153,8 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) change_nozzle_tips->SetFont(Label::Body_13); change_nozzle_tips->SetForegroundColour(STATIC_TEXT_CAPTION_COL); - m_wiki_link = new Label(single_panel, _L("View wiki")); + m_wiki_link = new HyperLink(single_panel, _L("Wiki Guide")); // ORCA m_wiki_link->SetFont(Label::Body_13); - m_wiki_link->SetForegroundColour(wxColour("#009688")); - m_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); - m_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); m_wiki_link->Bind(wxEVT_LEFT_DOWN, &PrinterPartsDialog::OnWikiClicked, this); h_tips_sizer->Add(change_nozzle_tips, 0, wxLEFT); @@ -1267,11 +1264,8 @@ PrinterPartsDialog::PrinterPartsDialog(wxWindow* parent) multiple_change_nozzle_tips->SetFont(Label::Body_13); multiple_change_nozzle_tips->SetForegroundColour(STATIC_TEXT_CAPTION_COL); - multiple_wiki_link = new Label(multiple_panel, _L("View wiki")); + multiple_wiki_link = new HyperLink(multiple_panel, _L("Wiki Guide")); // ORCA multiple_wiki_link->SetFont(Label::Body_13); - multiple_wiki_link->SetForegroundColour(wxColour("#009688")); - multiple_wiki_link->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_HAND); }); - multiple_wiki_link->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) { SetCursor(wxCURSOR_ARROW); }); multiple_wiki_link->Bind(wxEVT_LEFT_DOWN, &PrinterPartsDialog::OnWikiClicked, this); wxSizer* multiple_change_tips_sizer = new wxBoxSizer(wxHORIZONTAL); diff --git a/src/slic3r/GUI/PrintOptionsDialog.hpp b/src/slic3r/GUI/PrintOptionsDialog.hpp index d555c8237b..9918cfb80e 100644 --- a/src/slic3r/GUI/PrintOptionsDialog.hpp +++ b/src/slic3r/GUI/PrintOptionsDialog.hpp @@ -16,6 +16,7 @@ #include "Widgets/CheckBox.hpp" #include "Widgets/StaticLine.hpp" #include "Widgets/ComboBox.hpp" +#include "Widgets/HyperLink.hpp" // Previous definitions class SwitchBoard; @@ -33,7 +34,7 @@ protected: Label* nozzle_flow_type_label; ComboBox* nozzle_flow_type_checkbox; Label *change_nozzle_tips; - Label* m_wiki_link; + HyperLink* m_wiki_link; Button* m_single_update_nozzle_button; Button* m_multiple_update_nozzle_button; @@ -46,7 +47,7 @@ protected: ComboBox *multiple_right_nozzle_flow_checkbox; Label *multiple_change_nozzle_tips; - Label* multiple_wiki_link; + HyperLink* multiple_wiki_link; wxPanel *single_panel; wxPanel *multiple_panel; diff --git a/src/slic3r/GUI/ReleaseNote.cpp b/src/slic3r/GUI/ReleaseNote.cpp index 2dd0a7baf2..9b156c5228 100644 --- a/src/slic3r/GUI/ReleaseNote.cpp +++ b/src/slic3r/GUI/ReleaseNote.cpp @@ -1510,7 +1510,8 @@ InputIpAddressDialog::InputIpAddressDialog(wxWindow *parent) m_tip4->SetMinSize(wxSize(FromDIP(355), -1)); m_tip4->SetMaxSize(wxSize(FromDIP(355), -1)); - m_trouble_shoot = new wxHyperlinkCtrl(this, wxID_ANY, "How to trouble shooting", ""); + // ORCA standardized HyperLink + m_trouble_shoot = new HyperLink(this, "How to trouble shooting"); m_img_help = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("input_access_code_x1_en", this, 198), wxDefaultPosition, wxSize(FromDIP(355), -1), 0); diff --git a/src/slic3r/GUI/ReleaseNote.hpp b/src/slic3r/GUI/ReleaseNote.hpp index 838df0efd5..37b7c58935 100644 --- a/src/slic3r/GUI/ReleaseNote.hpp +++ b/src/slic3r/GUI/ReleaseNote.hpp @@ -326,7 +326,7 @@ public: wxStaticBitmap* m_img_step1{ nullptr }; wxStaticBitmap* m_img_step2{ nullptr }; wxStaticBitmap* m_img_step3{ nullptr }; - wxHyperlinkCtrl* m_trouble_shoot{ nullptr }; + HyperLink* m_trouble_shoot{ nullptr }; // ORCA wxTimer* closeTimer{ nullptr }; int closeCount{3}; bool m_show_access_code{ false }; diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index 56ecd56ce2..eeb472e98a 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -688,12 +688,9 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) sizer_extra_info->Add(st_title_extra_info_doc, 0, wxALL, 0); sizer_extra_info->Add(m_st_txt_extra_info, 0, wxALL, 0); - - m_link_network_state = new wxHyperlinkCtrl(m_sw_print_failed_info, wxID_ANY,_L("Check the status of current system services"),""); + // ORCA standardized HyperLink + m_link_network_state = new HyperLink(m_sw_print_failed_info, _L("Check the status of current system services"), wxGetApp().link_to_network_check()); m_link_network_state->SetFont(::Label::Body_12); - m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check();}); - m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND);}); - m_link_network_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_ARROW);}); sizer_print_failed_info->Add(m_link_network_state, 0, wxLEFT, 5); sizer_print_failed_info->Add(sizer_error_code, 0, wxLEFT, 5); diff --git a/src/slic3r/GUI/SelectMachine.hpp b/src/slic3r/GUI/SelectMachine.hpp index 42bf251b7c..302b37b553 100644 --- a/src/slic3r/GUI/SelectMachine.hpp +++ b/src/slic3r/GUI/SelectMachine.hpp @@ -42,6 +42,7 @@ #include "Widgets/ComboBox.hpp" #include "Widgets/ScrolledWindow.hpp" #include "Widgets/PopupWindow.hpp" +#include "Widgets/HyperLink.hpp" // ORCA #include #include @@ -371,7 +372,7 @@ protected: Label* m_st_txt_error_desc{nullptr}; Label* m_st_txt_extra_info{nullptr}; Label* m_ams_backup_tip{nullptr}; - wxHyperlinkCtrl* m_link_network_state{ nullptr }; + HyperLink* m_link_network_state{ nullptr }; // ORCA wxSimplebook* m_rename_switch_panel{nullptr}; wxSimplebook* m_simplebook{nullptr}; wxStaticText* m_rename_text{nullptr}; diff --git a/src/slic3r/GUI/SelectMachinePop.cpp b/src/slic3r/GUI/SelectMachinePop.cpp index aef994d067..ddca6df8a7 100644 --- a/src/slic3r/GUI/SelectMachinePop.cpp +++ b/src/slic3r/GUI/SelectMachinePop.cpp @@ -596,8 +596,9 @@ void SelectMachinePopup::update_other_devices() m_placeholder_panel = new wxWindow(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxSize(-1,FromDIP(26))); wxBoxSizer* placeholder_sizer = new wxBoxSizer(wxVERTICAL); - m_hyperlink = new wxHyperlinkCtrl(m_placeholder_panel, wxID_ANY, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); - m_hyperlink->SetNormalColour(StateColor::darkModeColorFor("#009789")); + // ORCA standardized HyperLink + m_hyperlink = new HyperLink(m_placeholder_panel, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer")); + m_hyperlink->SetFont(::Label::Body_12); placeholder_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5); diff --git a/src/slic3r/GUI/SelectMachinePop.hpp b/src/slic3r/GUI/SelectMachinePop.hpp index d1a34f9b3a..757cb08ed5 100644 --- a/src/slic3r/GUI/SelectMachinePop.hpp +++ b/src/slic3r/GUI/SelectMachinePop.hpp @@ -180,7 +180,7 @@ private: PinCodePanel* m_panel_ping_code{nullptr}; PinCodePanel* m_panel_direct_connection{nullptr}; wxWindow* m_placeholder_panel{nullptr}; - wxHyperlinkCtrl* m_hyperlink{nullptr}; + HyperLink* m_hyperlink{nullptr}; // ORCA Label* m_ping_code_text{nullptr}; wxStaticBitmap* m_img_ping_code{nullptr}; wxBoxSizer * m_sizer_body{nullptr}; diff --git a/src/slic3r/GUI/SendToPrinter.cpp b/src/slic3r/GUI/SendToPrinter.cpp index 5f5cf9925e..670a8bcad4 100644 --- a/src/slic3r/GUI/SendToPrinter.cpp +++ b/src/slic3r/GUI/SendToPrinter.cpp @@ -446,11 +446,9 @@ SendToPrinterDialog::SendToPrinterDialog(Plater *plater) sizer_extra_info->Add(st_title_extra_info_doc, 0, wxALL, 0); sizer_extra_info->Add(m_st_txt_extra_info, 0, wxALL, 0); - m_link_network_state = new wxHyperlinkCtrl(m_sw_print_failed_info, wxID_ANY,_L("Check the status of current system services"),""); + // ORCA standardized HyperLink + m_link_network_state = new HyperLink(m_sw_print_failed_info, _L("Check the status of current system services"), wxGetApp().link_to_network_check()); m_link_network_state->SetFont(::Label::Body_12); - m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); }); - m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); }); - m_link_network_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_ARROW); }); sizer_print_failed_info->Add(m_link_network_state, 0, wxLEFT, 5); sizer_print_failed_info->Add(sizer_error_code, 0, wxLEFT, 5); diff --git a/src/slic3r/GUI/SendToPrinter.hpp b/src/slic3r/GUI/SendToPrinter.hpp index de284e31d6..14493a1f20 100644 --- a/src/slic3r/GUI/SendToPrinter.hpp +++ b/src/slic3r/GUI/SendToPrinter.hpp @@ -110,7 +110,7 @@ private: Label* m_st_txt_error_code{ nullptr }; Label* m_st_txt_error_desc{ nullptr }; Label* m_st_txt_extra_info{ nullptr }; - wxHyperlinkCtrl* m_link_network_state{ nullptr }; + HyperLink* m_link_network_state{ nullptr }; StateColor btn_bg_enable; wxBoxSizer* rename_sizer_v{ nullptr }; wxBoxSizer* rename_sizer_h{ nullptr }; diff --git a/src/slic3r/GUI/StepMeshDialog.cpp b/src/slic3r/GUI/StepMeshDialog.cpp index b1b8041cd2..196c0ff8e0 100644 --- a/src/slic3r/GUI/StepMeshDialog.cpp +++ b/src/slic3r/GUI/StepMeshDialog.cpp @@ -117,14 +117,11 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, Slic3r::Step& file, double line wxBoxSizer* tips_sizer = new wxBoxSizer(wxVERTICAL); wxStaticText* info = new wxStaticText(this, wxID_ANY, _L("Smaller linear and angular deflections result in higher-quality transformations but increase the processing time.")); info->SetForegroundColour(StateColor::darkModeColorFor(FONT_COLOR)); - wxStaticText *tips = new wxStaticText(this, wxID_ANY, _L("View Wiki for more information")); - wxFont font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false); - font.SetUnderlined(true); - tips->SetForegroundColour(StateColor::darkModeColorFor(wxColour(0, 151, 137))); - tips->SetFont(font); - tips->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { - wxLaunchDefaultBrowser("https://www.orcaslicer.com/wiki/stl-transformation"); - }); + + // ORCA standardized HyperLink + HyperLink *tips = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/stl-transformation"); + tips->SetFont(::Label::Body_12); + info->Wrap(FromDIP(400)); tips_sizer->Add(info, 0, wxALIGN_LEFT); tips_sizer->Add(tips, 0, wxALIGN_LEFT); diff --git a/src/slic3r/GUI/WebUserLoginDialog.cpp b/src/slic3r/GUI/WebUserLoginDialog.cpp index fba6547f65..2522efbf4f 100644 --- a/src/slic3r/GUI/WebUserLoginDialog.cpp +++ b/src/slic3r/GUI/WebUserLoginDialog.cpp @@ -25,6 +25,7 @@ #include #include +#include // ORCA using namespace std; using namespace nlohmann; @@ -57,11 +58,12 @@ ZUserLogin::ZUserLogin() : wxDialog((wxWindow *) (wxGetApp().mainframe), wxID_AN m_message->SetForegroundColour(*wxBLACK); m_message->Wrap(FromDIP(360)); - auto m_download_hyperlink = new wxHyperlinkCtrl(this, wxID_ANY, _L("Click here to download it."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); - m_download_hyperlink->Bind(wxEVT_HYPERLINK, [this](wxCommandEvent& event) { + // ORCA standardized HyperLink + auto m_download_hyperlink = new HyperLink(this, _L("Click here to download it.")); + m_download_hyperlink->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& event) { this->Close(); wxGetApp().ShowDownNetPluginDlg(); - }); + }); m_sizer_main->Add(m_message, 0, wxALIGN_CENTER | wxALL, FromDIP(15)); m_sizer_main->Add(m_download_hyperlink, 0, wxALIGN_CENTER | wxALL, FromDIP(10)); m_sizer_main->Add(0, 0, 1, wxBOTTOM, 10); diff --git a/src/slic3r/GUI/Widgets/HyperLink.cpp b/src/slic3r/GUI/Widgets/HyperLink.cpp new file mode 100644 index 0000000000..7fdb236199 --- /dev/null +++ b/src/slic3r/GUI/Widgets/HyperLink.cpp @@ -0,0 +1,49 @@ +#include "HyperLink.hpp" +#include "Label.hpp" + +namespace Slic3r { namespace GUI { + +HyperLink::HyperLink(wxWindow* parent, const wxString& label, const wxString& url, long style) + : wxStaticText(parent, wxID_ANY, label) + , m_url(url) + , m_normalColor(wxColour("#009687")) // used slightly different color otherwise automatically uses ColorForDark that not visible enough + , m_hoverColor(wxColour("#26A69A")) +{ + SetForegroundColour(m_normalColor); + HyperLink::SetFont(Label::Head_14); + SetCursor(wxCursor(wxCURSOR_HAND)); + + if (!m_url.IsEmpty()) + SetToolTip(m_url); + + Bind(wxEVT_LEFT_DOWN, ([this](wxMouseEvent& e) { + if (!m_url.IsEmpty()) + wxLaunchDefaultBrowser(m_url); + })); + + Bind(wxEVT_ENTER_WINDOW, ([this](wxMouseEvent& e) { + SetForegroundColour(m_hoverColor); + Refresh(); + })); + Bind(wxEVT_LEAVE_WINDOW, ([this](wxMouseEvent& e) { + SetForegroundColour(m_normalColor); + Refresh(); + })); +} + +bool HyperLink::SetFont(const wxFont& font) +{ // ensure it stays underlined + wxFont f = font; + f.SetUnderlined(true); + return wxStaticText::SetFont(f); +} + +void HyperLink::SetURL(const wxString& url) +{ + m_url = url; + SetToolTip(m_url); +} + +wxString HyperLink::GetURL() const { return m_url; } + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Widgets/HyperLink.hpp b/src/slic3r/GUI/Widgets/HyperLink.hpp new file mode 100644 index 0000000000..48e2245e3b --- /dev/null +++ b/src/slic3r/GUI/Widgets/HyperLink.hpp @@ -0,0 +1,26 @@ +#ifndef slic3r_GUI_HyperLink_hpp_ +#define slic3r_GUI_HyperLink_hpp_ + +#include +#include + +namespace Slic3r { namespace GUI { + +class HyperLink : public wxStaticText +{ +public: + HyperLink(wxWindow* parent, const wxString& label = wxEmptyString, const wxString& url = wxEmptyString, const long style = 0); + + void SetURL(const wxString& url); + wxString GetURL() const; + + bool SetFont(const wxFont& font); + +private: + wxString m_url; + wxColour m_normalColor; + wxColour m_hoverColor; +}; + +}} // namespace Slic3r::GUI +#endif // !slic3r_GUI_HyperLink_hpp_ diff --git a/src/slic3r/GUI/Widgets/SideTools.cpp b/src/slic3r/GUI/Widgets/SideTools.cpp index 4288647e53..377253e707 100644 --- a/src/slic3r/GUI/Widgets/SideTools.cpp +++ b/src/slic3r/GUI/Widgets/SideTools.cpp @@ -274,8 +274,8 @@ SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxBoxSizer* connection_sizer_V = new wxBoxSizer(wxVERTICAL); wxBoxSizer* connection_sizer_H = new wxBoxSizer(wxHORIZONTAL); - m_hyperlink = new wxHyperlinkCtrl(m_connection_info, wxID_ANY, _L("Failed to connect to the server"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE); - m_hyperlink->SetBackgroundColour(wxColour(255, 111, 0)); + // ORCA standardized HyperLink + m_hyperlink = new HyperLink(m_connection_info, _L("Failed to connect to the server"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer")); m_more_err_open = ScalableBitmap(this, "monitir_err_open", 16); m_more_err_close = ScalableBitmap(this, "monitir_err_close", 16); @@ -328,13 +328,10 @@ SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* sizer_extra_info = new wxBoxSizer(wxHORIZONTAL); - m_link_network_state = new wxHyperlinkCtrl(m_side_error_panel, wxID_ANY,_L("Check the status of current system services"),"",wxDefaultPosition,wxDefaultSize, wxHL_ALIGN_CENTRE |wxST_ELLIPSIZE_END); - m_link_network_state->SetMinSize(wxSize(FromDIP(220), -1)); + // ORCA standardized HyperLink + m_link_network_state = new HyperLink(m_side_error_panel, _L("Check the status of current system services"), wxGetApp().link_to_network_check(), wxST_ELLIPSIZE_END); m_link_network_state->SetMaxSize(wxSize(FromDIP(220), -1)); m_link_network_state->SetFont(::Label::Body_12); - m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); }); - m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); }); - m_link_network_state->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_ARROW); }); auto st_title_error_code = new wxStaticText(m_side_error_panel, wxID_ANY, _L("code"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END); auto st_title_error_code_doc = new wxStaticText(m_side_error_panel, wxID_ANY, ": "); diff --git a/src/slic3r/GUI/Widgets/SideTools.hpp b/src/slic3r/GUI/Widgets/SideTools.hpp index 4f1cf7c667..24cbae4fd2 100644 --- a/src/slic3r/GUI/Widgets/SideTools.hpp +++ b/src/slic3r/GUI/Widgets/SideTools.hpp @@ -4,9 +4,9 @@ #include #include #include -#include #include "Button.hpp" #include "Label.hpp" +#include "HyperLink.hpp" // ORCA #include "../GUI/Tabbook.hpp" #include "../DeviceManager.hpp" #include "../wxExtensions.hpp" @@ -99,13 +99,13 @@ public: private: SideToolsPanel* m_side_tools{ nullptr }; Tabbook* m_tabpanel{ nullptr }; - wxHyperlinkCtrl* m_link_network_state{ nullptr }; + HyperLink* m_link_network_state{ nullptr }; // ORCA Label* m_st_txt_error_code{ nullptr }; Label* m_st_txt_error_desc{ nullptr }; Label* m_st_txt_extra_info{ nullptr }; wxWindow* m_side_error_panel{ nullptr }; Button* m_connection_info{ nullptr }; - wxHyperlinkCtrl* m_hyperlink{ nullptr }; + HyperLink* m_hyperlink{ nullptr }; // ORCA ScalableButton* m_more_button{ nullptr }; ScalableBitmap m_more_err_open; ScalableBitmap m_more_err_close; diff --git a/src/slic3r/GUI/calib_dlg.cpp b/src/slic3r/GUI/calib_dlg.cpp index ffd995a89b..79735f6901 100644 --- a/src/slic3r/GUI/calib_dlg.cpp +++ b/src/slic3r/GUI/calib_dlg.cpp @@ -5,6 +5,7 @@ #include #include "MainFrame.hpp" #include "Widgets/DialogButtons.hpp" +#include "Widgets/HyperLink.hpp" #include #include #include "libslic3r/PrintConfig.hpp" @@ -173,22 +174,14 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - // Help links - auto help_sizer = new wxBoxSizer(wxVERTICAL); - auto help_link_pa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Pressure Advance Guide"), - "https://www.orcaslicer.com/wiki/pressure-advance-calib"); - help_link_pa->SetForegroundColour(wxColour("#1890FF")); - help_sizer->Add(help_link_pa, 0, wxALL, FromDIP(5)); - - auto help_link_apa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Adaptive Pressure Advance Guide"), - "https://www.orcaslicer.com/wiki/adaptive-pressure-advance-calib"); - help_link_apa->SetForegroundColour(wxColour("#1890FF")); - help_sizer->Add(help_link_apa, 0, wxALL, FromDIP(5)); - - v_sizer->Add(help_sizer, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/pressure-advance-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &PA_Calibration_Dlg::on_start, this); @@ -399,13 +392,14 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Temperature Calibration"), - "https://www.orcaslicer.com/wiki/temp-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/temp-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Temp_Calibration_Dlg::on_start, this); @@ -578,13 +572,14 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Volumetric Speed Calibration"), - "https://www.orcaslicer.com/wiki/volumetric-speed-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/volumetric-speed-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &MaxVolumetricSpeed_Test_Dlg::on_start, this); @@ -684,13 +679,14 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater) v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: VFA"), - "https://www.orcaslicer.com/wiki/vfa-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/vfa-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &VFA_Test_Dlg::on_start, this); @@ -791,13 +787,14 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Retraction Calibration"), - "https://www.orcaslicer.com/wiki/retraction-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/retraction-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Retraction_Test_Dlg::on_start, this); @@ -968,13 +965,14 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), - "https://www.orcaslicer.com/wiki/input-shaping-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/input-shaping-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Input_Shaping_Freq_Test_Dlg::on_start, this); @@ -1165,13 +1163,14 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), - "https://www.orcaslicer.com/wiki/input-shaping-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/input-shaping-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Input_Shaping_Damp_Test_Dlg::on_start, this); @@ -1356,13 +1355,14 @@ Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); - auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Cornering Calibration"), - "https://www.orcaslicer.com/wiki/cornering-calib"); - help_link->SetForegroundColour(wxColour("#1890FF")); - v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); - auto dlg_btns = new DialogButtons(this, {"OK"}); - v_sizer->Add(dlg_btns , 0, wxEXPAND); + + auto bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + auto wiki = new HyperLink(this, _L("Wiki Guide"), "https://www.orcaslicer.com/wiki/cornering-calib"); + bottom_sizer->Add(wiki, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(20)); + bottom_sizer->AddStretchSpacer(); + bottom_sizer->Add(dlg_btns, 0, wxEXPAND); + v_sizer->Add(bottom_sizer, 0, wxEXPAND); dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Cornering_Test_Dlg::on_start, this); From 9d39f5a5a10f6db2a95680b85588b81629afcd39 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 3 Jan 2026 23:13:01 +0800 Subject: [PATCH 27/45] update .doxygen --- .doxygen | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doxygen b/.doxygen index 8d9f2471f6..eda965cc73 100644 --- a/.doxygen +++ b/.doxygen @@ -1565,7 +1565,7 @@ TOC_EXPAND = NO # protocol see https://www.sitemaps.org # This tag requires that the tag GENERATE_HTML is set to YES. -SITEMAP_URL = +SITEMAP_URL = internals.orcaslicer.com # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that From fed4a120e4d139f3be0df8851ecfe71547d5826b Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 3 Jan 2026 23:29:53 +0800 Subject: [PATCH 28/45] enable swap for doxygen --- .github/workflows/doxygen-docs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/doxygen-docs.yml b/.github/workflows/doxygen-docs.yml index 61e47b4873..e95ba6d5e5 100644 --- a/.github/workflows/doxygen-docs.yml +++ b/.github/workflows/doxygen-docs.yml @@ -16,6 +16,12 @@ jobs: # Only run on main branch of the main repository if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' steps: + - uses: thejerrybao/setup-swap-space@v1 + with: + swap-space-path: /swapfile + swap-size-gb: 8 + remove-existing-swap-files: true + - name: Checkout repository uses: actions/checkout@v6 From 86c6cf7b913a6179597b40171ccd7878bddd2d64 Mon Sep 17 00:00:00 2001 From: Rodrigo Faselli <162915171+RF47@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:48:45 -0300 Subject: [PATCH 29/45] Double seam paint on fuzzy skin bug-fix (#11808) * double seam fuzzy bugfix * Update FuzzySkin.cpp * 3 point minimum for loop * Update FuzzySkin.cpp * close the loop is redundant * cambio minimo * Update FuzzySkin.cpp * Update FuzzySkin.cpp --- src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp index 2e6f7efd9d..a9b5099383 100644 --- a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp +++ b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp @@ -162,8 +162,8 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice } if (ext_lines.back().p == ext_lines.front().p) { // Connect endpoints. - out.front().p = out.back().p; - out.front().w = out.back().w; + out.back().p = out.front().p; + out.back().w = out.front().w; } if (out.size() >= 3) From 2e53e9db02533993b5bf616c5a45854288a33b99 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 4 Jan 2026 11:12:28 +0800 Subject: [PATCH 30/45] doxygen doc are too big for pages, use R2 --- .doxygen | 6 ++++- .github/workflows/doxygen-docs.yml | 43 +++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/.doxygen b/.doxygen index eda965cc73..d557f6ba85 100644 --- a/.doxygen +++ b/.doxygen @@ -1059,7 +1059,11 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */deps/* +EXCLUDE_PATTERNS = */build/* +EXCLUDE_PATTERNS = */deps_src/* + + # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/.github/workflows/doxygen-docs.yml b/.github/workflows/doxygen-docs.yml index e95ba6d5e5..f30c3e0d0e 100644 --- a/.github/workflows/doxygen-docs.yml +++ b/.github/workflows/doxygen-docs.yml @@ -13,25 +13,30 @@ jobs: build-and-deploy: name: Build and Deploy Docs runs-on: ubuntu-latest + timeout-minutes: 60 # Only run on main branch of the main repository if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' + permissions: + contents: read steps: - uses: thejerrybao/setup-swap-space@v1 with: swap-space-path: /swapfile swap-size-gb: 8 remove-existing-swap-files: true - + - name: Checkout repository uses: actions/checkout@v6 - name: Install Doxygen and Graphviz run: | + set -euo pipefail sudo apt-get update sudo apt-get install -y doxygen graphviz - name: Generate documentation run: | + set -euo pipefail # Override DOT_NUM_THREADS to avoid parallel dot race condition bug sed -i 's/^DOT_NUM_THREADS.*/DOT_NUM_THREADS = 1/' .doxygen doxygen .doxygen @@ -40,10 +45,34 @@ jobs: echo "Error: Documentation generation failed - index.html not found" exit 1 fi + - name: Install Rclone + run: | + set -euo pipefail + sudo -v + curl -fsSL https://rclone.org/install.sh | sudo bash - - name: Deploy to Cloudflare Pages - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: pages deploy internal_docs --project-name=orcaslicer-internals + - name: optimize + run: | + set -euo pipefail + rm -f internal_docs/Nodes.xml internal_docs/Tokens.xml + find internal_docs -name "*.map" -type f -delete || true + find internal_docs -name "*.md5" -type f -delete || true + + - name: upload + # We configure rclone dynamically using environment variables + run: | + set -euo pipefail + # Remove existing config if it exists to avoid conflicts + rclone config delete cloudflare 2>/dev/null || true + rclone config create cloudflare s3 \ + provider Cloudflare \ + access_key_id ${{ secrets.R2_ACCESS_KEY_ID }} \ + secret_access_key ${{ secrets.R2_SECRET_ACCESS_KEY }} \ + endpoint ${{ secrets.R2_ENDPOINT }} + + rclone sync internal_docs/ cloudflare:orcaslicer-internals \ + --progress \ + --transfers 512 \ + --checkers 512 + + echo "Documentation upload completed successfully" \ No newline at end of file From ad88d43db84870a9098c34ec458d80c11fe9a63c Mon Sep 17 00:00:00 2001 From: mjfsch <99204506+mjfsch@users.noreply.github.com> Date: Sun, 4 Jan 2026 06:14:54 +0000 Subject: [PATCH 31/45] CoPrint Profiles Update (#11818) # Description Accurate color change calculations for coprint setups by specifying the nozzle volume, reduced risk of jamming by removing parking position setting. ## Tests Settings tested on N3+ and K1 equipped with coprint kits. --- ...Print ChromaSet 0.4 nozzle - Ender-3 V3 Plus.json | 12 +++++++++--- .../Co Print ChromaSet 0.4 nozzle - Ender-3 V3.json | 12 +++++++++--- .../machine/Co Print ChromaSet 0.4 nozzle fast.json | 12 +++++++++--- .../machine/Co Print ChromaSet 0.4 nozzle.json | 12 +++++++++--- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3 Plus.json b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3 Plus.json index b7c03f3f96..b7605cb457 100644 --- a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3 Plus.json +++ b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3 Plus.json @@ -11,6 +11,9 @@ "nozzle_diameter": [ "0.4" ], + "nozzle_volume": [ + "156" + ], "retract_before_wipe": [ "0%" ], @@ -132,7 +135,7 @@ "0" ], "parking_pos_retraction": [ - "25" + "0" ], "retract_when_changing_layer": [ "0" @@ -141,7 +144,10 @@ "0" ], "high_current_on_filament_swap": [ - "1" + "0" + ], + "enable_filament_ramming": [ + "0" ], "z_hop_types": "Spiral Lift" -} \ No newline at end of file +} diff --git a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3.json b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3.json index 7dabbd7f08..391b37301d 100644 --- a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3.json +++ b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle - Ender-3 V3.json @@ -11,6 +11,9 @@ "nozzle_diameter": [ "0.4" ], + "nozzle_volume": [ + "156" + ], "retract_before_wipe": [ "0%" ], @@ -132,7 +135,7 @@ "0" ], "parking_pos_retraction": [ - "25" + "0" ], "retract_when_changing_layer": [ "0" @@ -141,7 +144,10 @@ "0" ], "high_current_on_filament_swap": [ - "1" + "0" + ], + "enable_filament_ramming": [ + "0" ], "z_hop_types": "Spiral Lift" -} \ No newline at end of file +} diff --git a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle fast.json b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle fast.json index 518acb39cd..b33d7e5a5c 100644 --- a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle fast.json +++ b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle fast.json @@ -11,6 +11,9 @@ "nozzle_diameter": [ "0.4" ], + "nozzle_volume": [ + "156" + ], "retract_before_wipe": [ "0%" ], @@ -132,7 +135,7 @@ "0" ], "parking_pos_retraction": [ - "25" + "0" ], "retract_when_changing_layer": [ "0" @@ -141,7 +144,10 @@ "0" ], "high_current_on_filament_swap": [ - "1" + "0" + ], + "enable_filament_ramming": [ + "0" ], "z_hop_types": "Spiral Lift" -} \ No newline at end of file +} diff --git a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle.json b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle.json index 8a49ec2f87..3ee7b4e79b 100644 --- a/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle.json +++ b/resources/profiles/Co Print/machine/Co Print ChromaSet 0.4 nozzle.json @@ -10,6 +10,9 @@ "printer_variant": "0.4", "nozzle_diameter": [ "0.4" + ], + "nozzle_volume": [ + "156" ], "retract_before_wipe": [ "0%" @@ -132,7 +135,7 @@ "0" ], "parking_pos_retraction": [ - "25" + "0" ], "retract_when_changing_layer": [ "0" @@ -141,7 +144,10 @@ "0" ], "high_current_on_filament_swap": [ - "1" + "0" + ], + "enable_filament_ramming": [ + "0" ], "z_hop_types": "Spiral Lift" -} \ No newline at end of file +} From 03c8541b09e79e005e6e1d4159810571d06e8a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sezgin=20A=C3=87IKG=C3=96Z?= Date: Sun, 4 Jan 2026 09:15:31 +0300 Subject: [PATCH 32/45] Update machine profile for OpenEYE Peacock V2 (#11790) # Description This PR updates the machine start G-code and adaptive bed mesh options of the **OpenEYE Peacock V2** printer profile. There are no breaking changes. Existing profiles and workflows remain fully compatible. ## Tests - Loaded the updated profile in Orca Slicer. - Generated sample G-code files and verified the updated startup sequence. - Confirmed no impact on slicing behavior, materials, or process settings. --- .../OpenEYE/machine/OpenEYE Peacock V2 0.4 nozzle.json | 9 ++++++--- .../profiles/OpenEYE/machine/fdm_openeye_common.json | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/profiles/OpenEYE/machine/OpenEYE Peacock V2 0.4 nozzle.json b/resources/profiles/OpenEYE/machine/OpenEYE Peacock V2 0.4 nozzle.json index 4528b72fe1..2912a51b45 100644 --- a/resources/profiles/OpenEYE/machine/OpenEYE Peacock V2 0.4 nozzle.json +++ b/resources/profiles/OpenEYE/machine/OpenEYE Peacock V2 0.4 nozzle.json @@ -4,6 +4,9 @@ "from": "system", "inherits": "fdm_openeye_common", "instantiation": "true", + "adaptive_bed_mesh_margin": "10", + "bed_mesh_max": "211,211", + "bed_mesh_min": "1.5,7", "layer_change_gcode": "SET_PRINT_STATS_INFO CURRENT_LAYER={layer_num + 1}\n_MMU_UPDATE_HEIGHT", "machine_end_gcode": "MMU_END\nEND_PRINT", "machine_load_filament_time": "30", @@ -24,8 +27,8 @@ "30" ], "machine_pause_gcode": "PAUSE", - "machine_start_gcode": "SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\nMMU_START_SETUP INITIAL_TOOL={initial_tool} TOTAL_TOOLCHANGES=!total_toolchanges! REFERENCED_TOOLS=!referenced_tools! TOOL_COLORS=!colors! TOOL_TEMPS=!temperatures! TOOL_MATERIALS=!materials! FILAMENT_NAMES=!filament_names! PURGE_VOLUMES=!purge_volumes!\nMMU_START_CHECK\nSTART_PRINT BED_TEMP=[bed_temperature_initial_layer] EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TYPE=\"{curr_bed_type}\"\n; Enter YOUR exist start_print macro call here (minus purging logic because tool may not be loaded yet)\nMMU_START_LOAD_INITIAL_TOOL\n; Optionally add YOUR additional start logic (like purging) here to run just prior to start\nSTART_PRINT_SECONDARY\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} ; For pause at layer functionality and better print stats", - "machine_unload_filament_time": "30", + "machine_start_gcode": "SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\nMMU_START_SETUP INITIAL_TOOL={initial_tool} TOTAL_TOOLCHANGES=!total_toolchanges! REFERENCED_TOOLS=!referenced_tools! TOOL_COLORS=!colors! TOOL_TEMPS=!temperatures! TOOL_MATERIALS=!materials! FILAMENT_NAMES=!filament_names! PURGE_VOLUMES=!purge_volumes!\nMMU_START_CHECK\nSTART_PRINT BED_TEMP=[bed_temperature_initial_layer] EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TYPE=\"{curr_bed_type}\" MESH_MIN={adaptive_bed_mesh_min[0]},{adaptive_bed_mesh_min[1]} MESH_MAX={adaptive_bed_mesh_max[0]},{adaptive_bed_mesh_max[1]} ALGORITHM=[bed_mesh_algo] PROBE_COUNT={bed_mesh_probe_count[0]},{bed_mesh_probe_count[1]} ADAPTIVE_MARGIN={adaptive_bed_mesh_margin}\n; Enter YOUR exist start_print macro call here (minus purging logic because tool may not be loaded yet)\nMMU_START_LOAD_INITIAL_TOOL\n; Optionally add YOUR additional start logic (like purging) here to run just prior to start\nSTART_PRINT_SECONDARY\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} ; For pause at layer functionality and better print stats", + "machine_unload_filament_time": "30", "name": "OpenEYE Peacock V2 0.4 nozzle", "nozzle_diameter": [ "0.4" @@ -45,4 +48,4 @@ ], "setting_id": "GM001", "type": "machine" -} \ No newline at end of file +} diff --git a/resources/profiles/OpenEYE/machine/fdm_openeye_common.json b/resources/profiles/OpenEYE/machine/fdm_openeye_common.json index 130e3b189f..a428532958 100644 --- a/resources/profiles/OpenEYE/machine/fdm_openeye_common.json +++ b/resources/profiles/OpenEYE/machine/fdm_openeye_common.json @@ -124,8 +124,8 @@ "0" ], "machine_pause_gcode": "PAUSE", - "machine_start_gcode": "SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\nMMU_START_SETUP INITIAL_TOOL={initial_tool} TOTAL_TOOLCHANGES=!total_toolchanges! REFERENCED_TOOLS=!referenced_tools! TOOL_COLORS=!colors! TOOL_TEMPS=!temperatures! TOOL_MATERIALS=!materials! FILAMENT_NAMES=!filament_names! PURGE_VOLUMES=!purge_volumes!\nMMU_START_CHECK\nSTART_PRINT BED_TEMP=[bed_temperature_initial_layer] EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TYPE=\"{curr_bed_type}\"\n; Enter YOUR exist start_print macro call here (minus purging logic because tool may not be loaded yet)\nMMU_START_LOAD_INITIAL_TOOL\n; Optionally add YOUR additional start logic (like purging) here to run just prior to start\nSTART_PRINT_SECONDARY\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} ; For pause at layer functionality and better print stats", - "machine_tool_change_time": "0", + "machine_start_gcode": "SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\nMMU_START_SETUP INITIAL_TOOL={initial_tool} TOTAL_TOOLCHANGES=!total_toolchanges! REFERENCED_TOOLS=!referenced_tools! TOOL_COLORS=!colors! TOOL_TEMPS=!temperatures! TOOL_MATERIALS=!materials! FILAMENT_NAMES=!filament_names! PURGE_VOLUMES=!purge_volumes!\nMMU_START_CHECK\nSTART_PRINT BED_TEMP=[bed_temperature_initial_layer] EXTRUDER_TEMP=[nozzle_temperature_initial_layer] BED_TYPE=\"{curr_bed_type}\" MESH_MIN={adaptive_bed_mesh_min[0]},{adaptive_bed_mesh_min[1]} MESH_MAX={adaptive_bed_mesh_max[0]},{adaptive_bed_mesh_max[1]} ALGORITHM=[bed_mesh_algo] PROBE_COUNT={bed_mesh_probe_count[0]},{bed_mesh_probe_count[1]} ADAPTIVE_MARGIN={adaptive_bed_mesh_margin}\n; Enter YOUR exist start_print macro call here (minus purging logic because tool may not be loaded yet)\nMMU_START_LOAD_INITIAL_TOOL\n; Optionally add YOUR additional start logic (like purging) here to run just prior to start\nSTART_PRINT_SECONDARY\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count} ; For pause at layer functionality and better print stats", + "machine_tool_change_time": "0", "machine_unload_filament_time": "0", "manual_filament_change": "0", "max_layer_height": [ From 0c5f6c9865642f7ba923aee412f54f79f29531a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Faselli <162915171+RF47@users.noreply.github.com> Date: Sun, 4 Jan 2026 03:16:30 -0300 Subject: [PATCH 33/45] =?UTF-8?q?=F0=9F=A7=B9Fix=20some=20compile=20warnin?= =?UTF-8?q?gs=20(#10158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some compile warnings image --- src/slic3r/GUI/GUI_App.cpp | 8 +++++++- src/slic3r/GUI/MediaPlayCtrl.cpp | 2 +- src/slic3r/GUI/Widgets/LabeledStaticBox.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 2fd25bd520..a8eaf03848 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2071,7 +2071,13 @@ void GUI_App::init_app_config() } // Change current dirtory of application - [[maybe_unused]] auto unused_result = chdir(encode_path((Slic3r::data_dir() + "/log").c_str()).c_str()); + +#ifdef _WIN32 + [[maybe_unused]] auto unused_result = _chdir(encode_path((Slic3r::data_dir() + "/log").c_str()).c_str()); +#else + [[maybe_unused]] auto unused_result = chdir(encode_path((Slic3r::data_dir() + "/log").c_str()).c_str()); +#endif + } else { m_datadir_redefined = true; } diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index 7869662d7c..c412b5585a 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -769,7 +769,7 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install) auto file_dll = tools_dir + dll; auto file_dll2 = plugins_dir + dll; if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2)) - boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists); + boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_options::overwrite_existing); } boost::process::child process_source(file_source, file_url2.ToStdWstring(), boost::process::start_dir(tools_dir), boost::process::windows::create_no_window, diff --git a/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp b/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp index 93e4596aa5..c8e054593f 100644 --- a/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp +++ b/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp @@ -160,7 +160,7 @@ void LabeledStaticBox::DrawBorderAndLabel(wxDC& dc) wxSize wSz = GetSize(); dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.SetPen(wxPen(border_color.colorForStates(state_handler.states()), m_border_width, wxSOLID)); + dc.SetPen(wxPen(border_color.colorForStates(state_handler.states()), m_border_width, wxPENSTYLE_SOLID)); dc.DrawRoundedRectangle( // Border std::max(0, m_pos.x), std::max(0, m_pos.y) + m_label_height * .5, From 1b782d82bc4c6ab774c20d157391c8636b6f0b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Wilczy=C5=84ski?= Date: Sun, 4 Jan 2026 15:25:44 +0100 Subject: [PATCH 34/45] Fix fresh install issues --- src/slic3r/GUI/GUI_App.cpp | 12 ++++++++++++ src/slic3r/GUI/StatusPanel.cpp | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c0293d9e17..8223c913e1 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1518,6 +1518,12 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP if (name == "plugins") { std::string config_version = app_config->get_network_plugin_version(); + if (config_version.empty()) { + config_version = BBL::get_latest_network_version(); + BOOST_LOG_TRIVIAL(info) << "[install_plugin] config_version was empty, using latest: " << config_version; + app_config->set_network_plugin_version(config_version); + app_config->save(); + } if (!config_version.empty() && boost::filesystem::exists(legacy_lib_path)) { #if defined(_MSC_VER) || defined(_WIN32) auto versioned_lib = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + config_version + ".dll"); @@ -3211,6 +3217,12 @@ bool GUI_App::on_init_network(bool try_backup) if (config_version.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": no version configured, need to download"; m_networking_need_update = true; + + if (!m_device_manager) + m_device_manager = new Slic3r::DeviceManager(); + if (!m_user_manager) + m_user_manager = new Slic3r::UserManager(); + return false; } int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index dc717aca39..8a85e556de 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -2503,6 +2503,8 @@ StatusPanel::~StatusPanel() void StatusPanel::init_scaled_buttons() { + if (!m_project_task_panel) return; + m_project_task_panel->init_scaled_buttons(); m_bpButton_z_10->SetMinSize(Z_BUTTON_SIZE); m_bpButton_z_10->SetCornerRadius(0); From c8a4a7db29ccae72c61d27c9bb006de20bb757de Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 16:48:34 +0800 Subject: [PATCH 35/45] pack deps artifact to better support symbolic links --- .github/workflows/build_deps.yml | 9 ++++++++- .github/workflows/build_orca.yml | 14 +++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index c6288330a1..46340d1a97 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -95,12 +95,19 @@ jobs: run: | ./build_linux.sh -dr + - name: Pack dependencies + if: ${{ !cancelled() && ! env.ACT}} + working-directory: ${{ github.workspace }} + shell: bash + run: | + tar -cf deps_packet.tar -C ${{ env.DEPS_PATH }} . + - name: Upload OrcaSlicer_dep director(ies) for use later if: ${{ !cancelled() && ! env.ACT}} uses: actions/upload-artifact@v6 with: name: ${{ env.ARTIFACT_NAME }} - path: ${{ env.DEPS_PATH }} + path: deps_packet.tar retention-days: 10 # It's not too big, but we don't need it for a very long time. if-no-files-found: error diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index d70b4c9200..3f6c70e70a 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -34,7 +34,19 @@ jobs: uses: actions/download-artifact@v7 with: name: ${{ inputs.artifact-name }} - path: ${{ inputs.artifact-path }} + path: . + + - name: Unpack dependencies + shell: bash + run: | + if [ ! -f deps_packet.tar ]; then + echo "Error: deps_packet.tar not found" + ls -R + exit 1 + fi + mkdir -p ${{ inputs.artifact-path }} + tar -xf deps_packet.tar -C ${{ inputs.artifact-path }} + rm deps_packet.tar - uses: lukka/get-cmake@latest with: From cf9de8e444d66b3c0739e0402192062b17487e8e Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 17:45:15 +0800 Subject: [PATCH 36/45] Revert "pack deps artifact to better support symbolic links" This reverts commit c8a4a7db29ccae72c61d27c9bb006de20bb757de. --- .github/workflows/build_deps.yml | 9 +-------- .github/workflows/build_orca.yml | 14 +------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index 46340d1a97..c6288330a1 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -95,19 +95,12 @@ jobs: run: | ./build_linux.sh -dr - - name: Pack dependencies - if: ${{ !cancelled() && ! env.ACT}} - working-directory: ${{ github.workspace }} - shell: bash - run: | - tar -cf deps_packet.tar -C ${{ env.DEPS_PATH }} . - - name: Upload OrcaSlicer_dep director(ies) for use later if: ${{ !cancelled() && ! env.ACT}} uses: actions/upload-artifact@v6 with: name: ${{ env.ARTIFACT_NAME }} - path: deps_packet.tar + path: ${{ env.DEPS_PATH }} retention-days: 10 # It's not too big, but we don't need it for a very long time. if-no-files-found: error diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 3f6c70e70a..d70b4c9200 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -34,19 +34,7 @@ jobs: uses: actions/download-artifact@v7 with: name: ${{ inputs.artifact-name }} - path: . - - - name: Unpack dependencies - shell: bash - run: | - if [ ! -f deps_packet.tar ]; then - echo "Error: deps_packet.tar not found" - ls -R - exit 1 - fi - mkdir -p ${{ inputs.artifact-path }} - tar -xf deps_packet.tar -C ${{ inputs.artifact-path }} - rm deps_packet.tar + path: ${{ inputs.artifact-path }} - uses: lukka/get-cmake@latest with: From 189371206398837f138a8a562489522fffcdb78e Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 17:49:52 +0800 Subject: [PATCH 37/45] Revert "Fix missing force-build, use non-docker publish action, be nice to cache (#11688)" This reverts commit 8989e2102d403111aebcd51d69c54261cbba2fee. --- .github/workflows/build_all.yml | 9 +-- .github/workflows/build_check_cache.yml | 62 ++++++++++++++++ .github/workflows/build_deps.yml | 97 ++++++++++++++----------- .github/workflows/build_orca.yml | 31 ++++---- build_linux.sh | 2 +- 5 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/build_check_cache.yml diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 0cae85189b..41d489d4d8 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -48,17 +48,16 @@ concurrency: jobs: - build_linux: # Separate so unit tests can wait on just Linux builds to complete. + build_linux: name: Build Linux strategy: fail-fast: false # Don't run scheduled builds on forks: if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }} - uses: ./.github/workflows/build_deps.yml + uses: ./.github/workflows/build_check_cache.yml with: os: ubuntu-24.04 build-deps-only: ${{ inputs.build-deps-only || false }} - force-build: ${{ github.event_name == 'schedule' }} secrets: inherit build_all: name: Build Non-Linux @@ -71,7 +70,7 @@ jobs: arch: arm64 # Don't run scheduled builds on forks: if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }} - uses: ./.github/workflows/build_deps.yml + uses: ./.github/workflows/build_check_cache.yml with: os: ${{ matrix.os }} arch: ${{ matrix.arch }} @@ -113,7 +112,7 @@ jobs: path: build/tests/**/*.log - name: Publish Test Results if: always() - uses: EnricoMi/publish-unit-test-result-action/linux@v2 + uses: EnricoMi/publish-unit-test-result-action@v2 with: files: "ctest_results.xml" flatpak: diff --git a/.github/workflows/build_check_cache.yml b/.github/workflows/build_check_cache.yml new file mode 100644 index 0000000000..00b5f71ecd --- /dev/null +++ b/.github/workflows/build_check_cache.yml @@ -0,0 +1,62 @@ +name: Check Cache + +on: + workflow_call: + inputs: + os: + required: true + type: string + arch: + required: false + type: string + build-deps-only: + required: false + type: boolean + force-build: + required: false + type: boolean + +jobs: + check_cache: # determines if there is a cache and outputs variables used in caching process + name: Check Cache + runs-on: ${{ inputs.os }} + outputs: + cache-key: ${{ steps.set_outputs.outputs.cache-key }} + cache-path: ${{ steps.set_outputs.outputs.cache-path }} + valid-cache: ${{ steps.cache_deps.outputs.cache-hit }} + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + lfs: 'true' + + - name: set outputs + id: set_outputs + env: + dep-folder-name: ${{ inputs.os != 'macos-14' && '/OrcaSlicer_dep' || '' }} + output-cmd: ${{ inputs.os == 'windows-latest' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}} + run: | + echo cache-key=${{ inputs.os }}-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }} >> ${{ env.output-cmd }} + echo cache-path=${{ github.workspace }}/deps/build${{ env.dep-folder-name }} >> ${{ env.output-cmd }} + + - name: load cache + id: cache_deps + uses: actions/cache@v4 + with: + path: ${{ steps.set_outputs.outputs.cache-path }} + key: ${{ steps.set_outputs.outputs.cache-key }} + lookup-only: true + + build_deps: # call next step + name: Build Deps + needs: [check_cache] + uses: ./.github/workflows/build_deps.yml + with: + cache-key: ${{ needs.check_cache.outputs.cache-key }} + cache-path: ${{ needs.check_cache.outputs.cache-path }} + valid-cache: ${{ needs.check_cache.outputs.valid-cache == 'true' }} + os: ${{ inputs.os }} + arch: ${{ inputs.arch }} + build-deps-only: ${{ inputs.build-deps-only }} + force-build: ${{ inputs.force-build }} + secrets: inherit diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index c6288330a1..b255b6abf7 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -1,6 +1,15 @@ on: workflow_call: inputs: + cache-key: + required: true + type: string + cache-path: + required: true + type: string + valid-cache: + required: true + type: boolean os: required: true type: string @@ -17,62 +26,55 @@ on: jobs: build_deps: name: Build Deps + if: ${{ !cancelled() && (inputs.build-deps-only || inputs.force-build || inputs.valid-cache != true) }} runs-on: ${{ inputs.os }} - outputs: - artifact-name: ${{ env.ARTIFACT_NAME }} - artifact-path: ${{ env.DEPS_PATH }} env: - DO_BUILD: ${{ inputs.build-deps-only || inputs.force-build }} - DEPS_PATH: ${{ github.workspace }}/deps/build${{ inputs.os != 'macos-14' && '/OrcaSlicer_dep' || '' }} - ARTIFACT_NAME: OrcaSlicer_dep_${{ inputs.os }}_${{ inputs.arch }} + date: steps: + + # Setup the environment - name: Checkout uses: actions/checkout@v6 with: lfs: 'true' - # Cached deps are just the final outputs, no intermediate files. - # So building XOR cache loading. - # We use `lookup-only` to skip pulling cache. - name: load cached deps - uses: actions/cache/restore@v5 - id: cache-load + uses: actions/cache@v4 with: - path: ${{ env.DEPS_PATH }} - key: ${{ inputs.os }}-${{ inputs.arch }}-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }} - lookup-only: ${{ env.DO_BUILD == 'true' }} # Doing this instead of `if` preserves the outputs of this step + path: ${{ inputs.cache-path }} + key: ${{ inputs.cache-key }} - uses: lukka/get-cmake@latest - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') }} with: cmakeVersion: "~3.28.0" # use most recent 3.28.x version - name: setup dev on Windows - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os == 'windows-latest' }} + if: inputs.os == 'windows-latest' uses: microsoft/setup-msbuild@v2 - name: Get the date on Ubuntu and macOS - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os != 'windows-latest' }} + if: inputs.os != 'windows-latest' run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_ENV shell: bash - name: Get the date on Windows - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os == 'windows-latest' }} + if: inputs.os == 'windows-latest' run: echo "date=$(Get-Date -Format 'yyyyMMdd')" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8 shell: pwsh + + # Build Dependencies - name: Build on Windows - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os == 'windows-latest' }} + if: inputs.os == 'windows-latest' working-directory: ${{ github.workspace }} run: | choco install strawberryperl .\build_release_vs.bat deps + .\build_release_vs.bat pack + cd ${{ github.workspace }}/deps/build - # Windows and Linux don't need to delete any directories, because they only package up deps/build/OrcaSlicer_dep. - # But Mac has multiple and we're preserving their directory structure relationship. - # So the garbage siblings of OrcaSlicer_dep can be deleted to save artifact and cache space. - name: Build on Mac ${{ inputs.arch }} - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os == 'macos-14' }} + if: inputs.os == 'macos-14' working-directory: ${{ github.workspace }} run: | brew install automake texinfo libtool @@ -85,40 +87,53 @@ jobs: done brew install zstd + - name: Apt-Install Dependencies - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && inputs.os == 'ubuntu-24.04' }} + if: inputs.os == 'ubuntu-24.04' uses: ./.github/actions/apt-install-deps - name: Build on Ubuntu - if: ${{ !cancelled() && (env.DO_BUILD == 'true' || steps.cache-load.outputs.cache-hit != 'true') && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }} + if: inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' working-directory: ${{ github.workspace }} run: | + mkdir -p ${{ github.workspace }}/deps/build/destdir ./build_linux.sh -dr + cd deps/build + tar -czvf OrcaSlicer_dep_ubuntu_$(date +"%Y%m%d").tar.gz destdir - - name: Upload OrcaSlicer_dep director(ies) for use later - if: ${{ !cancelled() && ! env.ACT}} - uses: actions/upload-artifact@v6 - with: - name: ${{ env.ARTIFACT_NAME }} - path: ${{ env.DEPS_PATH }} - retention-days: 10 # It's not too big, but we don't need it for a very long time. - if-no-files-found: error - - name: Save cache from main branch - if: ${{ !cancelled() && github.ref == 'refs/heads/main' && steps.cache-load.outputs.cache-hit != 'true' }} - uses: actions/cache/save@v5 + # Upload Artifacts + # - name: Upload Mac ${{ inputs.arch }} artifacts + # if: inputs.os == 'macos-14' + # uses: actions/upload-artifact@v5 + # with: + # name: OrcaSlicer_dep_mac_${{ env.date }} + # path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.tar.gz + + - name: Upload Windows artifacts + if: inputs.os == 'windows-latest' + uses: actions/upload-artifact@v5 with: - path: ${{ env.DEPS_PATH }} - key: ${{ steps.cache-load.outputs.cache-primary-key }} + name: OrcaSlicer_dep_win64_${{ env.date }} + path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.zip + + - name: Upload Ubuntu artifacts + if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }} + env: + ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} + uses: actions/upload-artifact@v5 + with: + name: OrcaSlicer_dep_ubuntu_${{ env.ubuntu-ver }}_${{ env.date }} + path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep_ubuntu_*.tar.gz build_orca: name: Build OrcaSlicer needs: [build_deps] - if: ${{ !cancelled() && (!inputs.build-deps-only || inputs.force-build) }} + if: ${{ !cancelled() && !inputs.build-deps-only && (inputs.force-build || (inputs.valid-cache == true && needs.build_deps.result == 'skipped') || (inputs.valid-cache != true && success())) }} uses: ./.github/workflows/build_orca.yml with: - artifact-name: ${{ needs.build_deps.outputs.artifact-name }} - artifact-path: ${{ needs.build_deps.outputs.artifact-path }} + cache-key: ${{ inputs.cache-key }} + cache-path: ${{ inputs.cache-path }} os: ${{ inputs.os }} arch: ${{ inputs.arch }} secrets: inherit diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index d70b4c9200..aef491f006 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -1,10 +1,10 @@ on: workflow_call: inputs: - artifact-name: + cache-key: required: true type: string - artifact-path: + cache-path: required: true type: string os: @@ -30,11 +30,12 @@ jobs: with: lfs: 'true' - - name: Download deps artifacts - uses: actions/download-artifact@v7 + - name: load cached deps + uses: actions/cache@v4 with: - name: ${{ inputs.artifact-name }} - path: ${{ inputs.artifact-path }} + path: ${{ inputs.cache-path }} + key: ${{ inputs.cache-key }} + fail-on-cache-miss: true - uses: lukka/get-cmake@latest with: @@ -180,14 +181,14 @@ jobs: - name: Upload artifacts mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_Mac_universal_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg - name: Upload OrcaSlicer_profile_validator DMG mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_profile_validator_Mac_universal_DMG_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg @@ -254,28 +255,28 @@ jobs: - name: Upload artifacts Win zip if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_Windows_${{ env.ver }}_portable path: ${{ github.workspace }}/build/OrcaSlicer - name: Upload artifacts Win installer if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/OrcaSlicer*.exe - name: Upload artifacts Win PDB if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: PDB path: ${{ github.workspace }}/build/src/Release/Debug_PDB_${{ env.ver }}_for_developers_only.7z - name: Upload OrcaSlicer_profile_validator Win if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_profile_validator_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe @@ -335,7 +336,7 @@ jobs: # and doesn't preserve file permissions - name: Upload Test Artifact if: inputs.os == 'ubuntu-24.04' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: ${{ github.sha }}-tests overwrite: true @@ -357,7 +358,7 @@ jobs: env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }} - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage' @@ -366,7 +367,7 @@ jobs: if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }} env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v5 with: name: OrcaSlicer_profile_validator_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/src/Release/OrcaSlicer_profile_validator' diff --git a/build_linux.sh b/build_linux.sh index 3159557146..9a9a9160ba 100755 --- a/build_linux.sh +++ b/build_linux.sh @@ -21,7 +21,7 @@ function usage() { echo " -p: boost ccache hit rate by disabling precompiled headers (default: ON)" echo " -r: skip RAM and disk checks (low RAM compiling)" echo " -s: build the Orca Slicer (optional)" - echo " -t: build tests (optional)" + echo " -t: build tests (optional), requires -s flag" echo " -u: install system dependencies (asks for sudo password; build prerequisite)" echo " -l: use Clang instead of GCC (default: GCC)" echo " -L: use ld.lld as linker (if available)" From 57f9112b7c5bef711b4fea82dd2e9791761e5039 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 17:54:59 +0800 Subject: [PATCH 38/45] Update GitHub Actions workflows to use actions/cache@v5 and actions/upload-artifact@v6 --- .github/workflows/build_check_cache.yml | 2 +- .github/workflows/build_deps.yml | 8 ++++---- .github/workflows/build_orca.yml | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_check_cache.yml b/.github/workflows/build_check_cache.yml index 00b5f71ecd..fee5a6e955 100644 --- a/.github/workflows/build_check_cache.yml +++ b/.github/workflows/build_check_cache.yml @@ -41,7 +41,7 @@ jobs: - name: load cache id: cache_deps - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ steps.set_outputs.outputs.cache-path }} key: ${{ steps.set_outputs.outputs.cache-key }} diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index b255b6abf7..6cec66f24b 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -39,7 +39,7 @@ jobs: lfs: 'true' - name: load cached deps - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ inputs.cache-path }} key: ${{ inputs.cache-key }} @@ -105,14 +105,14 @@ jobs: # Upload Artifacts # - name: Upload Mac ${{ inputs.arch }} artifacts # if: inputs.os == 'macos-14' - # uses: actions/upload-artifact@v5 + # uses: actions/upload-artifact@v6 # with: # name: OrcaSlicer_dep_mac_${{ env.date }} # path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.tar.gz - name: Upload Windows artifacts if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_dep_win64_${{ env.date }} path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.zip @@ -121,7 +121,7 @@ jobs: if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }} env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_dep_ubuntu_${{ env.ubuntu-ver }}_${{ env.date }} path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep_ubuntu_*.tar.gz diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index aef491f006..131766e49e 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -31,7 +31,7 @@ jobs: lfs: 'true' - name: load cached deps - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ inputs.cache-path }} key: ${{ inputs.cache-key }} @@ -181,14 +181,14 @@ jobs: - name: Upload artifacts mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Mac_universal_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg - name: Upload OrcaSlicer_profile_validator DMG mac if: inputs.os == 'macos-14' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Mac_universal_DMG_${{ env.ver }} path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg @@ -255,28 +255,28 @@ jobs: - name: Upload artifacts Win zip if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Windows_${{ env.ver }}_portable path: ${{ github.workspace }}/build/OrcaSlicer - name: Upload artifacts Win installer if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/OrcaSlicer*.exe - name: Upload artifacts Win PDB if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: PDB path: ${{ github.workspace }}/build/src/Release/Debug_PDB_${{ env.ver }}_for_developers_only.7z - name: Upload OrcaSlicer_profile_validator Win if: inputs.os == 'windows-latest' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Windows_${{ env.ver }} path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe @@ -336,7 +336,7 @@ jobs: # and doesn't preserve file permissions - name: Upload Test Artifact if: inputs.os == 'ubuntu-24.04' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: ${{ github.sha }}-tests overwrite: true @@ -358,7 +358,7 @@ jobs: env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage' @@ -367,7 +367,7 @@ jobs: if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }} env: ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: OrcaSlicer_profile_validator_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }} path: './build/src/Release/OrcaSlicer_profile_validator' From 8670bb65f2bdb772b2b957ca05876a3ca5531fd0 Mon Sep 17 00:00:00 2001 From: Pepe-Polymaker Date: Mon, 5 Jan 2026 18:12:56 +0800 Subject: [PATCH 39/45] Refactor Polymaker folder within Snapmaker profile directory and add more profiles (#11613) # Description * What issue does this PR address or fix? 1. Refactor Polymaker folder within Snapmaker profile directory, so that the structure is more clear. 2. Add more Polymaker filament presets for Snapmaker printers. * What new features or enhancements does this PR introduce? 1. None * Are there any breaking changes or dependencies that need to be considered? 1. None --- resources/profiles/BBL.json | 168 +++++++------- ...nchroma PLA Satin @BBL A1 0.2 nozzle.json} | 7 +- ....json => Panchroma PLA Satin @BBL A1.json} | 7 +- ...chroma PLA Satin @BBL A1M 0.2 nozzle.json} | 7 +- ...json => Panchroma PLA Satin @BBL A1M.json} | 7 +- ...chroma PLA Satin @BBL P1P 0.2 nozzle.json} | 7 +- ...json => Panchroma PLA Satin @BBL P1P.json} | 7 +- ...nchroma PLA Satin @BBL X1 0.2 nozzle.json} | 7 +- ....json => Panchroma PLA Satin @BBL X1.json} | 7 +- ...chroma PLA Satin @BBL X1C 0.2 nozzle.json} | 7 +- ...json => Panchroma PLA Satin @BBL X1C.json} | 7 +- ...se.json => Panchroma PLA Satin @base.json} | 5 +- resources/profiles/OrcaFilamentLibrary.json | 175 +++++++------- ....json => Panchroma PLA Satin @System.json} | 7 +- ...se.json => Panchroma PLA Satin @base.json} | 5 +- resources/profiles/Snapmaker.json | 218 ++++++++++++++++-- .../PolyLite Dual PLA @0.2 nozzle.json | 19 -- .../filament/PolyLite J1 PLA @0.2 nozzle.json | 11 - .../Snapmaker/filament/PolyLite J1 PLA.json | 13 -- .../filament/PolyLite PLA @0.2 nozzle.json | 21 -- .../filament/PolyLite PLA @U1 base.json | 20 -- .../Snapmaker/filament/PolyLite PLA @U1.json | 11 - .../filament/PolyLite PLA @base.json | 20 -- .../PolyTerra Dual PLA @0.2 nozzle.json | 19 -- .../PolyTerra J1 PLA @0.2 nozzle.json | 11 - .../Snapmaker/filament/PolyTerra J1 PLA.json | 13 -- .../filament/PolyTerra PLA @0.2 nozzle.json | 21 -- .../filament/PolyTerra PLA @U1 base.json | 20 -- .../Snapmaker/filament/PolyTerra PLA @U1.json | 11 - .../Polymaker/Panchroma CoPE @U1 base.json | 41 ++++ .../Polymaker/Panchroma CoPE @U1.json | 26 +++ .../Polymaker/Panchroma PLA @U1 base.json | 44 ++++ .../filament/Polymaker/Panchroma PLA @U1.json | 26 +++ .../Panchroma PLA Celestial @U1 base.json | 41 ++++ .../Panchroma PLA Celestial @U1.json | 26 +++ .../Panchroma PLA Galaxy @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Galaxy @U1.json | 26 +++ .../Panchroma PLA Glow @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Glow @U1.json | 26 +++ .../Panchroma PLA Luminous @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Luminous @U1.json | 26 +++ .../Panchroma PLA Marble @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Marble @U1.json | 23 ++ .../Panchroma PLA Matte @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Matte @U1.json | 23 ++ .../Panchroma PLA Metallic @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Metallic @U1.json | 26 +++ .../Panchroma PLA Neon @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Neon @U1.json | 26 +++ .../Panchroma PLA Satin @U1 base.json | 42 ++++ .../Polymaker/Panchroma PLA Satin @U1.json | 27 +++ .../Panchroma PLA Silk @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA Silk @U1.json | 26 +++ .../Panchroma PLA Starlight @U1 base.json | 41 ++++ .../Panchroma PLA Starlight @U1.json | 26 +++ .../Panchroma PLA Temp Shift @U1 base.json | 41 ++++ .../Panchroma PLA Temp Shift @U1.json | 26 +++ .../Panchroma PLA Translucent @U1 base.json | 41 ++++ .../Panchroma PLA Translucent @U1.json | 26 +++ .../Panchroma PLA UV Shift @U1 base.json | 41 ++++ .../Polymaker/Panchroma PLA UV Shift @U1.json | 26 +++ .../PolyLite Dual PLA @0.2 nozzle.json | 19 ++ .../PolyLite J1 PLA @0.2 nozzle.json | 11 + .../filament/Polymaker/PolyLite J1 PLA.json | 13 ++ .../Polymaker/PolyLite PETG @Base.json | 29 +++ .../PolyLite PETG @Snapmaker U1.json | 117 ++++++++++ .../Polymaker/PolyLite PLA @0.2 nozzle.json | 21 ++ .../Polymaker/PolyLite PLA @U1 base.json | 20 ++ .../filament/Polymaker/PolyLite PLA @U1.json | 11 + .../Polymaker/PolyLite PLA @base.json | 20 ++ .../Polymaker/PolyLite PLA Pro @U1 base.json | 41 ++++ .../Polymaker/PolyLite PLA Pro @U1.json | 26 +++ .../PolyTerra Dual PLA @0.2 nozzle.json | 19 ++ .../PolyTerra J1 PLA @0.2 nozzle.json | 11 + .../filament/Polymaker/PolyTerra J1 PLA.json | 13 ++ .../Polymaker/PolyTerra PLA @0.2 nozzle.json | 21 ++ .../Polymaker/PolyTerra PLA @U1 base.json | 20 ++ .../filament/Polymaker/PolyTerra PLA @U1.json | 11 + .../Polymaker/Polymaker HT-PLA @Base.json | 29 +++ .../Polymaker HT-PLA @Snapmaker U1.json | 96 ++++++++ .../Polymaker/Polymaker HT-PLA @U1 base.json | 53 +++++ .../Polymaker/Polymaker HT-PLA @U1.json | 26 +++ .../Polymaker/Polymaker HT-PLA-GF @Base.json | 29 +++ .../Polymaker HT-PLA-GF @Snapmaker U1.json | 96 ++++++++ .../Polymaker HT-PLA-GF @U1 base.json | 53 +++++ .../Polymaker/Polymaker HT-PLA-GF @U1.json | 26 +++ .../Polymaker/Polymaker PETG @Base.json | 29 +++ .../Polymaker PETG @Snapmaker U1.json | 111 +++++++++ .../Polymaker/Polymaker PLA Pro @Base.json | 29 +++ .../Polymaker PLA Pro @Snapmaker U1.json | 96 ++++++++ 90 files changed, 2594 insertions(+), 431 deletions(-) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL A1 0.2 nozzle.json => Panchroma PLA Satin @BBL A1 0.2 nozzle.json} (74%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL A1.json => Panchroma PLA Satin @BBL A1.json} (79%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL A1M 0.2 nozzle.json => Panchroma PLA Satin @BBL A1M 0.2 nozzle.json} (74%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL A1M.json => Panchroma PLA Satin @BBL A1M.json} (79%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL P1P 0.2 nozzle.json => Panchroma PLA Satin @BBL P1P 0.2 nozzle.json} (74%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL P1P.json => Panchroma PLA Satin @BBL P1P.json} (79%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL X1 0.2 nozzle.json => Panchroma PLA Satin @BBL X1 0.2 nozzle.json} (74%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL X1.json => Panchroma PLA Satin @BBL X1.json} (79%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL X1C 0.2 nozzle.json => Panchroma PLA Satin @BBL X1C 0.2 nozzle.json} (77%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @BBL X1C.json => Panchroma PLA Satin @BBL X1C.json} (84%) rename resources/profiles/BBL/filament/Polymaker/{Panchroma PLA Stain @base.json => Panchroma PLA Satin @base.json} (88%) rename resources/profiles/OrcaFilamentLibrary/filament/Polymaker/{Panchroma PLA Stain @System.json => Panchroma PLA Satin @System.json} (60%) rename resources/profiles/OrcaFilamentLibrary/filament/Polymaker/{Panchroma PLA Stain @base.json => Panchroma PLA Satin @base.json} (87%) delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite Dual PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite J1 PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite J1 PLA.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite PLA @U1 base.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite PLA @U1.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyLite PLA @base.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra Dual PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra J1 PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra J1 PLA.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra PLA @0.2 nozzle.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra PLA @U1 base.json delete mode 100644 resources/profiles/Snapmaker/filament/PolyTerra PLA @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite Dual PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Snapmaker U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra Dual PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @0.2 nozzle.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Snapmaker U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Snapmaker U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1 base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Snapmaker U1.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Base.json create mode 100644 resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Snapmaker U1.json diff --git a/resources/profiles/BBL.json b/resources/profiles/BBL.json index 9425300cb4..fdc096c888 100644 --- a/resources/profiles/BBL.json +++ b/resources/profiles/BBL.json @@ -1405,6 +1405,10 @@ "name": "Generic PLA-CF @base", "sub_path": "filament/Generic PLA-CF @base.json" }, + { + "name": "Numakers PLA+ @base", + "sub_path": "filament/Numakers/Numakers PLA+ @base.json" + }, { "name": "Overture Matte PLA @base", "sub_path": "filament/Overture/Overture Matte PLA @base.json" @@ -1458,12 +1462,12 @@ "sub_path": "filament/Polymaker/Panchroma PLA Neon @base.json" }, { - "name": "Panchroma PLA Silk @base", - "sub_path": "filament/Polymaker/Panchroma PLA Silk @base.json" + "name": "Panchroma PLA Satin @base", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @base.json" }, { - "name": "Panchroma PLA Stain @base", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @base.json" + "name": "Panchroma PLA Silk @base", + "sub_path": "filament/Polymaker/Panchroma PLA Silk @base.json" }, { "name": "Panchroma PLA Starlight @base", @@ -5101,6 +5105,42 @@ "name": "Generic PLA-CF @BBL P2S", "sub_path": "filament/Generic PLA-CF @BBL P2S.json" }, + { + "name": "Numakers PLA+ @BBL A1", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1.json" + }, + { + "name": "Numakers PLA+ @BBL A1 0.2 nozzle", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1 0.2 nozzle.json" + }, + { + "name": "Numakers PLA+ @BBL A1M", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1M.json" + }, + { + "name": "Numakers PLA+ @BBL A1M 0.2 nozzle", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1M 0.2 nozzle.json" + }, + { + "name": "Numakers PLA+ @BBL P1P", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL P1P.json" + }, + { + "name": "Numakers PLA+ @BBL P1P 0.2 nozzle", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL P1P 0.2 nozzle.json" + }, + { + "name": "Numakers PLA+ @BBL X1", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1.json" + }, + { + "name": "Numakers PLA+ @BBL X1C", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1C.json" + }, + { + "name": "Numakers PLA+ @BBL X1C 0.2 nozzle", + "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1C 0.2 nozzle.json" + }, { "name": "Overture Matte PLA @BBL A1", "sub_path": "filament/Overture/Overture Matte PLA @BBL A1.json" @@ -5641,6 +5681,46 @@ "name": "Panchroma PLA Neon @BBL X1C 0.2 nozzle", "sub_path": "filament/Polymaker/Panchroma PLA Neon @BBL X1C 0.2 nozzle.json" }, + { + "name": "Panchroma PLA Satin @BBL A1", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL A1.json" + }, + { + "name": "Panchroma PLA Satin @BBL A1 0.2 nozzle", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL A1 0.2 nozzle.json" + }, + { + "name": "Panchroma PLA Satin @BBL A1M", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL A1M.json" + }, + { + "name": "Panchroma PLA Satin @BBL A1M 0.2 nozzle", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL A1M 0.2 nozzle.json" + }, + { + "name": "Panchroma PLA Satin @BBL P1P", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL P1P.json" + }, + { + "name": "Panchroma PLA Satin @BBL P1P 0.2 nozzle", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL P1P 0.2 nozzle.json" + }, + { + "name": "Panchroma PLA Satin @BBL X1", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL X1.json" + }, + { + "name": "Panchroma PLA Satin @BBL X1 0.2 nozzle", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL X1 0.2 nozzle.json" + }, + { + "name": "Panchroma PLA Satin @BBL X1C", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL X1C.json" + }, + { + "name": "Panchroma PLA Satin @BBL X1C 0.2 nozzle", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @BBL X1C 0.2 nozzle.json" + }, { "name": "Panchroma PLA Silk @BBL A1", "sub_path": "filament/Polymaker/Panchroma PLA Silk @BBL A1.json" @@ -5677,46 +5757,6 @@ "name": "Panchroma PLA Silk @BBL X1C", "sub_path": "filament/Polymaker/Panchroma PLA Silk @BBL X1C.json" }, - { - "name": "Panchroma PLA Stain @BBL A1", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL A1.json" - }, - { - "name": "Panchroma PLA Stain @BBL A1 0.2 nozzle", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL A1 0.2 nozzle.json" - }, - { - "name": "Panchroma PLA Stain @BBL A1M", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL A1M.json" - }, - { - "name": "Panchroma PLA Stain @BBL A1M 0.2 nozzle", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL A1M 0.2 nozzle.json" - }, - { - "name": "Panchroma PLA Stain @BBL P1P", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL P1P.json" - }, - { - "name": "Panchroma PLA Stain @BBL P1P 0.2 nozzle", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL P1P 0.2 nozzle.json" - }, - { - "name": "Panchroma PLA Stain @BBL X1", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL X1.json" - }, - { - "name": "Panchroma PLA Stain @BBL X1 0.2 nozzle", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL X1 0.2 nozzle.json" - }, - { - "name": "Panchroma PLA Stain @BBL X1C", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL X1C.json" - }, - { - "name": "Panchroma PLA Stain @BBL X1C 0.2 nozzle", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @BBL X1C 0.2 nozzle.json" - }, { "name": "Panchroma PLA Starlight @BBL A1", "sub_path": "filament/Polymaker/Panchroma PLA Starlight @BBL A1.json" @@ -7661,46 +7701,6 @@ "name": "Overture TPU @BBL X1C 0.2 nozzle", "sub_path": "filament/Overture/Overture TPU @BBL X1C 0.2 nozzle.json" }, - { - "name": "Numakers PLA+ @base", - "sub_path": "filament/Numakers/Numakers PLA+ @base.json" - }, - { - "name": "Numakers PLA+ @BBL A1", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1.json" - }, - { - "name": "Numakers PLA+ @BBL A1 0.2 nozzle", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1 0.2 nozzle.json" - }, - { - "name": "Numakers PLA+ @BBL A1M", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1M.json" - }, - { - "name": "Numakers PLA+ @BBL A1M 0.2 nozzle", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL A1M 0.2 nozzle.json" - }, - { - "name": "Numakers PLA+ @BBL P1P", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL P1P.json" - }, - { - "name": "Numakers PLA+ @BBL P1P 0.2 nozzle", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL P1P 0.2 nozzle.json" - }, - { - "name": "Numakers PLA+ @BBL X1", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1.json" - }, - { - "name": "Numakers PLA+ @BBL X1C", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1C.json" - }, - { - "name": "Numakers PLA+ @BBL X1C 0.2 nozzle", - "sub_path": "filament/Numakers/Numakers PLA+ @BBL X1C 0.2 nozzle.json" - }, { "name": "fdm_filament_dual_common", "sub_path": "filament/fdm_filament_dual_common.json" diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1 0.2 nozzle.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1 0.2 nozzle.json similarity index 74% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1 0.2 nozzle.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1 0.2 nozzle.json index 1db86a72e8..886b3217cc 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1 0.2 nozzle.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL A1 0.2 nozzle", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL A1 0.2 nozzle", + "renamed_from": "Panchroma PLA Stain @BBL A1 0.2 nozzle", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_01", "instantiation": "true", @@ -26,4 +27,4 @@ "slow_down_layer_time": [ "5" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1.json similarity index 79% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1.json index 6f573a8f19..93520a1eda 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL A1", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL A1", + "renamed_from": "Panchroma PLA Stain @BBL A1", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_00", "instantiation": "true", @@ -28,4 +29,4 @@ "slow_down_layer_time": [ "5" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M 0.2 nozzle.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M 0.2 nozzle.json similarity index 74% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M 0.2 nozzle.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M 0.2 nozzle.json index 7510aa9ebf..b6689b1ee8 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M 0.2 nozzle.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL A1M 0.2 nozzle", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL A1M 0.2 nozzle", + "renamed_from": "Panchroma PLA Stain @BBL A1M 0.2 nozzle", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_03", "instantiation": "true", @@ -26,4 +27,4 @@ "slow_down_layer_time": [ "5" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M.json similarity index 79% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M.json index 620a76ffe4..800a4bb8bc 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL A1M.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL A1M.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL A1M", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL A1M", + "renamed_from": "Panchroma PLA Stain @BBL A1M", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_02", "instantiation": "true", @@ -28,4 +29,4 @@ "slow_down_layer_time": [ "5" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P 0.2 nozzle.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P 0.2 nozzle.json similarity index 74% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P 0.2 nozzle.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P 0.2 nozzle.json index 00cf4852a1..e6b2d27440 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P 0.2 nozzle.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL P1P 0.2 nozzle", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL P1P 0.2 nozzle", + "renamed_from": "Panchroma PLA Stain @BBL P1P 0.2 nozzle", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_05", "instantiation": "true", @@ -26,4 +27,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P.json similarity index 79% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P.json index 88678c3159..7e9c805c63 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL P1P.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL P1P.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL P1P", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL P1P", + "renamed_from": "Panchroma PLA Stain @BBL P1P", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_04", "instantiation": "true", @@ -28,4 +29,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1 0.2 nozzle.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1 0.2 nozzle.json similarity index 74% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1 0.2 nozzle.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1 0.2 nozzle.json index 435a9c991a..3a07dcb602 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1 0.2 nozzle.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL X1 0.2 nozzle", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL X1 0.2 nozzle", + "renamed_from": "Panchroma PLA Stain @BBL X1 0.2 nozzle", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_07", "instantiation": "true", @@ -26,4 +27,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1.json similarity index 79% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1.json index e5d9bfdf3a..be4651c5f4 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL X1", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL X1", + "renamed_from": "Panchroma PLA Stain @BBL X1", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_06", "instantiation": "true", @@ -28,4 +29,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C 0.2 nozzle.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C 0.2 nozzle.json similarity index 77% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C 0.2 nozzle.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C 0.2 nozzle.json index d4f02ff39a..0254f8e61e 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C 0.2 nozzle.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C 0.2 nozzle.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL X1C 0.2 nozzle", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL X1C 0.2 nozzle", + "renamed_from": "Panchroma PLA Stain @BBL X1C 0.2 nozzle", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_09", "instantiation": "true", @@ -28,4 +29,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C.json similarity index 84% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C.json index 1d50deee52..0449da66b0 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @BBL X1C.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @BBL X1C.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @BBL X1C", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @BBL X1C", + "renamed_from": "Panchroma PLA Stain @BBL X1C", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "GFSPM005_08", "instantiation": "true", @@ -34,4 +35,4 @@ "slow_down_layer_time": [ "15" ] -} \ No newline at end of file +} diff --git a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @base.json b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @base.json similarity index 88% rename from resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @base.json rename to resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @base.json index b2cb2b8cf3..26d3344d4b 100644 --- a/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Stain @base.json +++ b/resources/profiles/BBL/filament/Polymaker/Panchroma PLA Satin @base.json @@ -1,6 +1,7 @@ { "type": "filament", - "name": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @base", + "renamed_from": "Panchroma PLA Stain @base", "inherits": "fdm_filament_pla", "from": "system", "filament_id": "GFPM005", @@ -38,4 +39,4 @@ "temperature_vitrification": [ "59" ] -} \ No newline at end of file +} diff --git a/resources/profiles/OrcaFilamentLibrary.json b/resources/profiles/OrcaFilamentLibrary.json index 1f4b2cf779..8e6ac439b1 100644 --- a/resources/profiles/OrcaFilamentLibrary.json +++ b/resources/profiles/OrcaFilamentLibrary.json @@ -108,6 +108,10 @@ "name": "COEX ABS PRIME @base", "sub_path": "filament/COEX/COEX ABS PRIME @base.json" }, + { + "name": "Eolas Prints ABS @System", + "sub_path": "filament/Eolas Prints/Eolas Prints ABS @System.json" + }, { "name": "FDplast ABS @base", "sub_path": "filament/FDplast/FDplast ABS @base.json" @@ -144,6 +148,10 @@ "name": "COEX ASA PRIME @base", "sub_path": "filament/COEX/COEX ASA PRIME @base.json" }, + { + "name": "Eolas Prints ASA @System", + "sub_path": "filament/Eolas Prints/Eolas Prints ASA @System.json" + }, { "name": "Generic ASA @System", "sub_path": "filament/Generic ASA @System.json" @@ -288,6 +296,18 @@ "name": "COEX PETG @base", "sub_path": "filament/COEX/COEX PETG @base.json" }, + { + "name": "Eolas Prints PETG @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PETG @System.json" + }, + { + "name": "Eolas Prints PETG Transition @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PETG Transition @System.json" + }, + { + "name": "Eolas Prints PETG UV Resistant @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PETG UV Resistant @System.json" + }, { "name": "FDplast PETG @base", "sub_path": "filament/FDplast/FDplast PETG @base.json" @@ -420,6 +440,42 @@ "name": "COEX PLA PRIME @base", "sub_path": "filament/COEX/COEX PLA PRIME @base.json" }, + { + "name": "Eolas Prints PLA Antibacterial @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Antibacterial @System.json" + }, + { + "name": "Eolas Prints PLA High Speed @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA High Speed @System.json" + }, + { + "name": "Eolas Prints PLA INGEO 850 @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA INGEO 850 @System.json" + }, + { + "name": "Eolas Prints PLA INGEO 870 @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA INGEO 870 @System.json" + }, + { + "name": "Eolas Prints PLA Matte @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Matte @System.json" + }, + { + "name": "Eolas Prints PLA Neon @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Neon @System.json" + }, + { + "name": "Eolas Prints PLA Premium @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Premium @System.json" + }, + { + "name": "Eolas Prints PLA Silk @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Silk @System.json" + }, + { + "name": "Eolas Prints PLA Transition @System", + "sub_path": "filament/Eolas Prints/Eolas Prints PLA Transition @System.json" + }, { "name": "FDplast PLA @base", "sub_path": "filament/FDplast/FDplast PLA @base.json" @@ -444,6 +500,10 @@ "name": "NIT PLA @base", "sub_path": "filament/NIT/NIT PLA @base.json" }, + { + "name": "Numakers PLA+ @base", + "sub_path": "filament/Numakers/Numakers PLA+ @base.json" + }, { "name": "Overture Air PLA @base", "sub_path": "filament/Overture/Overture Air PLA @base.json" @@ -517,12 +577,12 @@ "sub_path": "filament/Polymaker/Panchroma PLA Neon @base.json" }, { - "name": "Panchroma PLA Silk @base", - "sub_path": "filament/Polymaker/Panchroma PLA Silk @base.json" + "name": "Panchroma PLA Satin @base", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @base.json" }, { - "name": "Panchroma PLA Stain @base", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @base.json" + "name": "Panchroma PLA Silk @base", + "sub_path": "filament/Polymaker/Panchroma PLA Silk @base.json" }, { "name": "Panchroma PLA Starlight @base", @@ -680,6 +740,22 @@ "name": "COEX TPU 60A @base", "sub_path": "filament/COEX/COEX TPU 60A @base.json" }, + { + "name": "Eolas Prints TPU D60 UV Resistant @System", + "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex D60 UV Resistant @System.json" + }, + { + "name": "Eolas Prints TPU Flex 93A @System", + "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex 93A @System.json" + }, + { + "name": "Eolas Prints TPU Flex D53 @System", + "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex D53 @System.json" + }, + { + "name": "Eolas Prints TPU Transition @System", + "sub_path": "filament/Eolas Prints/Eolas Prints TPU Transition @System.json" + }, { "name": "FDplast TPU @base", "sub_path": "filament/FDplast/FDplast TPU @base.json" @@ -692,10 +768,6 @@ "name": "Overture TPU @base", "sub_path": "filament/Overture/Overture TPU @base.json" }, - { - "name": "Numakers PLA+ @base", - "sub_path": "filament/Numakers/Numakers PLA+ @base.json" - }, { "name": "Bambu ABS @System", "sub_path": "filament/Bambu/Bambu ABS @System.json" @@ -980,6 +1052,10 @@ "name": "NIT PLA @System", "sub_path": "filament/NIT/NIT PLA @System.json" }, + { + "name": "Numakers PLA+ @System", + "sub_path": "filament/Numakers/Numakers PLA+ @System.json" + }, { "name": "Overture Air PLA @System", "sub_path": "filament/Overture/Overture Air PLA @System.json" @@ -1053,12 +1129,12 @@ "sub_path": "filament/Polymaker/Panchroma PLA Neon @System.json" }, { - "name": "Panchroma PLA Silk @System", - "sub_path": "filament/Polymaker/Panchroma PLA Silk @System.json" + "name": "Panchroma PLA Satin @System", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @System.json" }, { - "name": "Panchroma PLA Stain @System", - "sub_path": "filament/Polymaker/Panchroma PLA Stain @System.json" + "name": "Panchroma PLA Silk @System", + "sub_path": "filament/Polymaker/Panchroma PLA Silk @System.json" }, { "name": "Panchroma PLA Starlight @System", @@ -1211,81 +1287,6 @@ { "name": "COEX PLA+Silk @System", "sub_path": "filament/COEX/COEX PLA+Silk @System.json" - }, - { "name": "Numakers PLA+ @System", - "sub_path": "filament/Numakers/Numakers PLA+ @System.json" - }, - { - "name": "Eolas Prints PLA Premium @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Premium @System.json" - }, - { - "name": "Eolas Prints PLA Matte @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Matte @System.json" - }, - { - "name": "Eolas Prints PLA Silk @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Silk @System.json" - }, - { - "name": "Eolas Prints PLA Neon @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Neon @System.json" - }, - { - "name": "Eolas Prints PLA High Speed @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA High Speed @System.json" - }, - { - "name": "Eolas Prints PLA INGEO 850 @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA INGEO 850 @System.json" - }, - { - "name": "Eolas Prints PLA INGEO 870 @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA INGEO 870 @System.json" - }, - { - "name": "Eolas Prints PLA Antibacterial @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Antibacterial @System.json" - }, - { - "name": "Eolas Prints PLA Transition @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PLA Transition @System.json" - }, - { - "name": "Eolas Prints PETG @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PETG @System.json" - }, - { - "name": "Eolas Prints PETG UV Resistant @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PETG UV Resistant @System.json" - }, - { - "name": "Eolas Prints PETG Transition @System", - "sub_path": "filament/Eolas Prints/Eolas Prints PETG Transition @System.json" - }, - { - "name": "Eolas Prints TPU Flex 93A @System", - "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex 93A @System.json" - }, - { - "name": "Eolas Prints TPU Flex D53 @System", - "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex D53 @System.json" - }, - { - "name": "Eolas Prints TPU Flex D60 UV Resistant @System", - "sub_path": "filament/Eolas Prints/Eolas Prints TPU Flex D60 UV Resistant @System.json" - }, - { - "name": "Eolas Prints TPU Transition @System", - "sub_path": "filament/Eolas Prints/Eolas Prints TPU Transition @System.json" - }, - { - "name": "Eolas Prints ABS @System", - "sub_path": "filament/Eolas Prints/Eolas Prints ABS @System.json" - }, - { - "name": "Eolas Prints ASA @System", - "sub_path": "filament/Eolas Prints/Eolas Prints ASA @System.json" } ], "process_list": [], diff --git a/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @System.json b/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @System.json similarity index 60% rename from resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @System.json rename to resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @System.json index 96e40e373f..bbb5b658f6 100644 --- a/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @System.json +++ b/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @System.json @@ -1,7 +1,8 @@ { "type": "filament", - "name": "Panchroma PLA Stain @System", - "inherits": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @System", + "renamed_from": "Panchroma PLA Stain @System", + "inherits": "Panchroma PLA Satin @base", "from": "system", "setting_id": "OGFSPM005", "instantiation": "true", @@ -11,4 +12,4 @@ "filament_max_volumetric_speed": [ "16" ] -} \ No newline at end of file +} diff --git a/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @base.json b/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @base.json similarity index 87% rename from resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @base.json rename to resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @base.json index 4021abe0c3..a3ae93632b 100644 --- a/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Stain @base.json +++ b/resources/profiles/OrcaFilamentLibrary/filament/Polymaker/Panchroma PLA Satin @base.json @@ -1,6 +1,7 @@ { "type": "filament", - "name": "Panchroma PLA Stain @base", + "name": "Panchroma PLA Satin @base", + "renamed_from": "Panchroma PLA Stain @base", "inherits": "fdm_filament_pla", "from": "system", "filament_id": "OGFPM005", @@ -32,4 +33,4 @@ "temperature_vitrification": [ "59" ] -} \ No newline at end of file +} diff --git a/resources/profiles/Snapmaker.json b/resources/profiles/Snapmaker.json index e5b3b2b155..a468a8edf1 100644 --- a/resources/profiles/Snapmaker.json +++ b/resources/profiles/Snapmaker.json @@ -462,7 +462,7 @@ "filament_list": [ { "name": "PolyTerra PLA @0.2 nozzle", - "sub_path": "filament/PolyTerra PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyTerra PLA @0.2 nozzle.json" }, { "name": "Snapmaker PLA Lite @U1 base", @@ -482,11 +482,11 @@ }, { "name": "PolyTerra Dual PLA @0.2 nozzle", - "sub_path": "filament/PolyTerra Dual PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyTerra Dual PLA @0.2 nozzle.json" }, { "name": "PolyTerra J1 PLA @0.2 nozzle", - "sub_path": "filament/PolyTerra J1 PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyTerra J1 PLA @0.2 nozzle.json" }, { "name": "Snapmaker PLA Lite @U1", @@ -608,6 +608,14 @@ "name": "Snapmaker PET @base", "sub_path": "filament/Snapmaker PET @base.json" }, + { + "name": "PolyLite PETG @Base", + "sub_path": "filament/Polymaker/PolyLite PETG @Base.json" + }, + { + "name": "Polymaker PETG @Base", + "sub_path": "filament/Polymaker/Polymaker PETG @Base.json" + }, { "name": "Snapmaker Dual PETG @base", "sub_path": "filament/Snapmaker Dual PETG @base.json" @@ -640,17 +648,105 @@ "name": "Snapmaker PETG-CF @base", "sub_path": "filament/Snapmaker PETG-CF @base.json" }, + { + "name": "Panchroma CoPE @U1 base", + "sub_path": "filament/Polymaker/Panchroma CoPE @U1 base.json" + }, + { + "name": "Panchroma PLA @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA @U1 base.json" + }, + { + "name": "Panchroma PLA Celestial @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Celestial @U1 base.json" + }, + { + "name": "Panchroma PLA Galaxy @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Galaxy @U1 base.json" + }, + { + "name": "Panchroma PLA Glow @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Glow @U1 base.json" + }, + { + "name": "Panchroma PLA Luminous @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Luminous @U1 base.json" + }, + { + "name": "Panchroma PLA Marble @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Marble @U1 base.json" + }, + { + "name": "Panchroma PLA Matte @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Matte @U1 base.json" + }, + { + "name": "Panchroma PLA Metallic @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Metallic @U1 base.json" + }, + { + "name": "Panchroma PLA Neon @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Neon @U1 base.json" + }, + { + "name": "Panchroma PLA Satin @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @U1 base.json" + }, + { + "name": "Panchroma PLA Silk @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Silk @U1 base.json" + }, + { + "name": "Panchroma PLA Starlight @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Starlight @U1 base.json" + }, + { + "name": "Panchroma PLA Temp Shift @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Temp Shift @U1 base.json" + }, + { + "name": "Panchroma PLA Translucent @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA Translucent @U1 base.json" + }, + { + "name": "Panchroma PLA UV Shift @U1 base", + "sub_path": "filament/Polymaker/Panchroma PLA UV Shift @U1 base.json" + }, { "name": "PolyLite PLA @U1 base", - "sub_path": "filament/PolyLite PLA @U1 base.json" + "sub_path": "filament/Polymaker/PolyLite PLA @U1 base.json" }, { "name": "PolyLite PLA @base", - "sub_path": "filament/PolyLite PLA @base.json" + "sub_path": "filament/Polymaker/PolyLite PLA @base.json" + }, + { + "name": "PolyLite PLA Pro @U1 base", + "sub_path": "filament/Polymaker/PolyLite PLA Pro @U1 base.json" }, { "name": "PolyTerra PLA @U1 base", - "sub_path": "filament/PolyTerra PLA @U1 base.json" + "sub_path": "filament/Polymaker/PolyTerra PLA @U1 base.json" + }, + { + "name": "Polymaker HT-PLA @Base", + "sub_path": "filament/Polymaker/Polymaker HT-PLA @Base.json" + }, + { + "name": "Polymaker HT-PLA @U1 base", + "sub_path": "filament/Polymaker/Polymaker HT-PLA @U1 base.json" + }, + { + "name": "Polymaker HT-PLA-GF @Base", + "sub_path": "filament/Polymaker/Polymaker HT-PLA-GF @Base.json" + }, + { + "name": "Polymaker HT-PLA-GF @U1 base", + "sub_path": "filament/Polymaker/Polymaker HT-PLA-GF @U1 base.json" + }, + { + "name": "Polymaker PLA Pro @Base", + "sub_path": "filament/Polymaker/Polymaker PLA Pro @Base.json" }, { "name": "Snapmaker Dual PLA @base", @@ -884,6 +980,14 @@ "name": "Snapmaker PET", "sub_path": "filament/Snapmaker PET.json" }, + { + "name": "PolyLite PETG @Snapmaker U1", + "sub_path": "filament/Polymaker/PolyLite PETG @Snapmaker U1.json" + }, + { + "name": "Polymaker PETG @Snapmaker U1", + "sub_path": "filament/Polymaker/Polymaker PETG @Snapmaker U1.json" + }, { "name": "Snapmaker Dual PETG", "sub_path": "filament/Snapmaker Dual PETG.json" @@ -936,21 +1040,109 @@ "name": "Snapmaker PETG-CF", "sub_path": "filament/Snapmaker PETG-CF.json" }, + { + "name": "Panchroma CoPE @U1", + "sub_path": "filament/Polymaker/Panchroma CoPE @U1.json" + }, + { + "name": "Panchroma PLA @U1", + "sub_path": "filament/Polymaker/Panchroma PLA @U1.json" + }, + { + "name": "Panchroma PLA Celestial @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Celestial @U1.json" + }, + { + "name": "Panchroma PLA Galaxy @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Galaxy @U1.json" + }, + { + "name": "Panchroma PLA Glow @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Glow @U1.json" + }, + { + "name": "Panchroma PLA Luminous @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Luminous @U1.json" + }, + { + "name": "Panchroma PLA Marble @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Marble @U1.json" + }, + { + "name": "Panchroma PLA Matte @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Matte @U1.json" + }, + { + "name": "Panchroma PLA Metallic @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Metallic @U1.json" + }, + { + "name": "Panchroma PLA Neon @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Neon @U1.json" + }, + { + "name": "Panchroma PLA Satin @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Satin @U1.json" + }, + { + "name": "Panchroma PLA Silk @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Silk @U1.json" + }, + { + "name": "Panchroma PLA Starlight @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Starlight @U1.json" + }, + { + "name": "Panchroma PLA Temp Shift @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Temp Shift @U1.json" + }, + { + "name": "Panchroma PLA Translucent @U1", + "sub_path": "filament/Polymaker/Panchroma PLA Translucent @U1.json" + }, + { + "name": "Panchroma PLA UV Shift @U1", + "sub_path": "filament/Polymaker/Panchroma PLA UV Shift @U1.json" + }, { "name": "PolyLite PLA @U1", - "sub_path": "filament/PolyLite PLA @U1.json" + "sub_path": "filament/Polymaker/PolyLite PLA @U1.json" }, { "name": "PolyLite J1 PLA", - "sub_path": "filament/PolyLite J1 PLA.json" + "sub_path": "filament/Polymaker/PolyLite J1 PLA.json" }, { "name": "PolyLite PLA @0.2 nozzle", - "sub_path": "filament/PolyLite PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyLite PLA @0.2 nozzle.json" + }, + { + "name": "PolyLite PLA Pro @U1", + "sub_path": "filament/Polymaker/PolyLite PLA Pro @U1.json" }, { "name": "PolyTerra PLA @U1", - "sub_path": "filament/PolyTerra PLA @U1.json" + "sub_path": "filament/Polymaker/PolyTerra PLA @U1.json" + }, + { + "name": "Polymaker HT-PLA @Snapmaker U1", + "sub_path": "filament/Polymaker/Polymaker HT-PLA @Snapmaker U1.json" + }, + { + "name": "Polymaker HT-PLA @U1", + "sub_path": "filament/Polymaker/Polymaker HT-PLA @U1.json" + }, + { + "name": "Polymaker HT-PLA-GF @Snapmaker U1", + "sub_path": "filament/Polymaker/Polymaker HT-PLA-GF @Snapmaker U1.json" + }, + { + "name": "Polymaker HT-PLA-GF @U1", + "sub_path": "filament/Polymaker/Polymaker HT-PLA-GF @U1.json" + }, + { + "name": "Polymaker PLA Pro @Snapmaker U1", + "sub_path": "filament/Polymaker/Polymaker PLA Pro @Snapmaker U1.json" }, { "name": "Snapmaker Dual PLA", @@ -1158,11 +1350,11 @@ }, { "name": "PolyLite Dual PLA @0.2 nozzle", - "sub_path": "filament/PolyLite Dual PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyLite Dual PLA @0.2 nozzle.json" }, { "name": "PolyLite J1 PLA @0.2 nozzle", - "sub_path": "filament/PolyLite J1 PLA @0.2 nozzle.json" + "sub_path": "filament/Polymaker/PolyLite J1 PLA @0.2 nozzle.json" }, { "name": "Snapmaker Dual PLA Eco", @@ -1206,7 +1398,7 @@ }, { "name": "PolyTerra J1 PLA", - "sub_path": "filament/PolyTerra J1 PLA.json" + "sub_path": "filament/Polymaker/PolyTerra J1 PLA.json" }, { "name": "Snapmaker PLA Matte @U1 base", diff --git a/resources/profiles/Snapmaker/filament/PolyLite Dual PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyLite Dual PLA @0.2 nozzle.json deleted file mode 100644 index 6528cd8ca0..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite Dual PLA @0.2 nozzle.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite Dual PLA @0.2 nozzle", - "inherits": "PolyLite PLA @0.2 nozzle", - "from": "system", - "setting_id": "490991920", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker A250 Dual (0.2 nozzle)", - "Snapmaker A250 Dual BKit (0.2 nozzle)", - "Snapmaker A250 Dual QS+B Kit (0.2 nozzle)", - "Snapmaker A250 Dual QSKit (0.2 nozzle)", - "Snapmaker A350 Dual (0.2 nozzle)", - "Snapmaker A350 Dual BKit (0.2 nozzle)", - "Snapmaker A350 Dual QS+B Kit (0.2 nozzle)", - "Snapmaker A350 Dual QSKit (0.2 nozzle)", - "Snapmaker Artisan (0.2 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite J1 PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyLite J1 PLA @0.2 nozzle.json deleted file mode 100644 index 65a87c28d8..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite J1 PLA @0.2 nozzle.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite J1 PLA @0.2 nozzle", - "inherits": "PolyLite PLA @0.2 nozzle", - "from": "system", - "setting_id": "431382384", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker J1 (0.2 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite J1 PLA.json b/resources/profiles/Snapmaker/filament/PolyLite J1 PLA.json deleted file mode 100644 index 0d09c5528a..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite J1 PLA.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite J1 PLA", - "inherits": "PolyLite PLA @base", - "from": "system", - "setting_id": "116125055", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker J1 (0.4 nozzle)", - "Snapmaker J1 (0.6 nozzle)", - "Snapmaker J1 (0.8 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyLite PLA @0.2 nozzle.json deleted file mode 100644 index 69999b740a..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite PLA @0.2 nozzle.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite PLA @0.2 nozzle", - "inherits": "PolyLite PLA @base", - "from": "system", - "setting_id": "1592803578", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker A250 (0.2 nozzle)", - "Snapmaker A250 BKit (0.2 nozzle)", - "Snapmaker A250 QS+B Kit (0.2 nozzle)", - "Snapmaker A250 QSKit (0.2 nozzle)", - "Snapmaker A350 (0.2 nozzle)", - "Snapmaker A350 BKit (0.2 nozzle)", - "Snapmaker A350 QS+B Kit (0.2 nozzle)", - "Snapmaker A350 QSKit (0.2 nozzle)" - ], - "filament_max_volumetric_speed": [ - "1.6" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite PLA @U1 base.json b/resources/profiles/Snapmaker/filament/PolyLite PLA @U1 base.json deleted file mode 100644 index fb9c55cdc7..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite PLA @U1 base.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite PLA @U1 base", - "inherits": "fdm_filament_pla", - "from": "system", - "filament_id": "13938660340", - "instantiation": "false", - "filament_flow_ratio": [ - "0.95" - ], - "filament_cost": [ - "90" - ], - "filament_max_volumetric_speed": [ - "15" - ], - "default_filament_colour": [ - "" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite PLA @U1.json b/resources/profiles/Snapmaker/filament/PolyLite PLA @U1.json deleted file mode 100644 index 0648fdde39..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite PLA @U1.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite PLA @U1", - "inherits": "PolyLite PLA @U1 base", - "from": "system", - "setting_id": "6486836500", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker U1 (0.4 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyLite PLA @base.json b/resources/profiles/Snapmaker/filament/PolyLite PLA @base.json deleted file mode 100644 index e4db1c70b6..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyLite PLA @base.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "filament", - "name": "PolyLite PLA @base", - "inherits": "fdm_filament_pla", - "from": "system", - "filament_id": "1393866034", - "instantiation": "false", - "filament_flow_ratio": [ - "0.95" - ], - "filament_cost": [ - "90" - ], - "filament_max_volumetric_speed": [ - "15" - ], - "default_filament_colour": [ - "" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra Dual PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyTerra Dual PLA @0.2 nozzle.json deleted file mode 100644 index 9ce3e9f972..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra Dual PLA @0.2 nozzle.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra Dual PLA @0.2 nozzle", - "inherits": "PolyTerra PLA @0.2 nozzle", - "from": "system", - "setting_id": "1258531391", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker A250 Dual (0.2 nozzle)", - "Snapmaker A250 Dual BKit (0.2 nozzle)", - "Snapmaker A250 Dual QS+B Kit (0.2 nozzle)", - "Snapmaker A250 Dual QSKit (0.2 nozzle)", - "Snapmaker A350 Dual (0.2 nozzle)", - "Snapmaker A350 Dual BKit (0.2 nozzle)", - "Snapmaker A350 Dual QS+B Kit (0.2 nozzle)", - "Snapmaker A350 Dual QSKit (0.2 nozzle)", - "Snapmaker Artisan (0.2 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA @0.2 nozzle.json deleted file mode 100644 index a2f99fd132..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA @0.2 nozzle.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra J1 PLA @0.2 nozzle", - "inherits": "PolyTerra PLA @0.2 nozzle", - "from": "system", - "setting_id": "1072374370", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker J1 (0.2 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA.json b/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA.json deleted file mode 100644 index c696f52735..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra J1 PLA.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra J1 PLA", - "inherits": "PolyTerra PLA @base", - "from": "system", - "setting_id": "3958200796", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker J1 (0.4 nozzle)", - "Snapmaker J1 (0.6 nozzle)", - "Snapmaker J1 (0.8 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/PolyTerra PLA @0.2 nozzle.json deleted file mode 100644 index f996844ce1..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra PLA @0.2 nozzle.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra PLA @0.2 nozzle", - "inherits": "PolyTerra PLA @base", - "from": "system", - "setting_id": "409934824", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker A250 (0.2 nozzle)", - "Snapmaker A250 BKit (0.2 nozzle)", - "Snapmaker A250 QS+B Kit (0.2 nozzle)", - "Snapmaker A250 QSKit (0.2 nozzle)", - "Snapmaker A350 (0.2 nozzle)", - "Snapmaker A350 BKit (0.2 nozzle)", - "Snapmaker A350 QS+B Kit (0.2 nozzle)", - "Snapmaker A350 QSKit (0.2 nozzle)" - ], - "filament_max_volumetric_speed": [ - "1.4" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1 base.json b/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1 base.json deleted file mode 100644 index 3b7b9a8b94..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1 base.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra PLA @U1 base", - "inherits": "fdm_filament_pla", - "from": "system", - "filament_id": "37895926870", - "instantiation": "false", - "filament_cost": [ - "80" - ], - "filament_density": [ - "1.31" - ], - "filament_max_volumetric_speed": [ - "14.4" - ], - "default_filament_colour": [ - "" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1.json b/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1.json deleted file mode 100644 index 478c008d7a..0000000000 --- a/resources/profiles/Snapmaker/filament/PolyTerra PLA @U1.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "filament", - "name": "PolyTerra PLA @U1", - "inherits": "PolyTerra PLA @U1 base", - "from": "system", - "setting_id": "12580059400", - "instantiation": "true", - "compatible_printers": [ - "Snapmaker U1 (0.4 nozzle)" - ] -} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1 base.json new file mode 100644 index 0000000000..1575543964 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma CoPE @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM016", + "instantiation": "false", + "filament_cost": [ + "19.99" + ], + "filament_density": [ + "1.29" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "230" + ], + "nozzle_temperature_initial_layer": [ + "230" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "58" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1.json new file mode 100644 index 0000000000..abd252e87a --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma CoPE @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma CoPE @U1", + "inherits": "Panchroma CoPE @U1 base", + "from": "system", + "setting_id": "GFSPM016_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1 base.json new file mode 100644 index 0000000000..a09edc3df1 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1 base.json @@ -0,0 +1,44 @@ +{ + "type": "filament", + "name": "Panchroma PLA @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM001", + "instantiation": "false", + "filament_cost": [ + "19.99" + ], + "filament_density": [ + "1.32" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "filament_wipe": [ + "0" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "58" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1.json new file mode 100644 index 0000000000..a77038834b --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA @U1", + "inherits": "Panchroma PLA @U1 base", + "from": "system", + "setting_id": "GFSPM001_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1 base.json new file mode 100644 index 0000000000..305c3b8476 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Celestial @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM008", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1.json new file mode 100644 index 0000000000..cfd1b918b1 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Celestial @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Celestial @U1", + "inherits": "Panchroma PLA Celestial @U1 base", + "from": "system", + "setting_id": "GFSPM008_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1 base.json new file mode 100644 index 0000000000..9129ce17a7 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Galaxy @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM007", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1.json new file mode 100644 index 0000000000..465e8b461d --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Galaxy @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Galaxy @U1", + "inherits": "Panchroma PLA Galaxy @U1 base", + "from": "system", + "setting_id": "GFSPM007_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1 base.json new file mode 100644 index 0000000000..21177be0db --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Glow @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM010", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1.json new file mode 100644 index 0000000000..5cbf021349 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Glow @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Glow @U1", + "inherits": "Panchroma PLA Glow @U1 base", + "from": "system", + "setting_id": "GFSPM010_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1 base.json new file mode 100644 index 0000000000..c8afc7bc16 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Luminous @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM011", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1.json new file mode 100644 index 0000000000..7747c1ccfb --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Luminous @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Luminous @U1", + "inherits": "Panchroma PLA Luminous @U1 base", + "from": "system", + "setting_id": "GFSPM011_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1 base.json new file mode 100644 index 0000000000..8a462959a8 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Marble @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM003", + "instantiation": "false", + "filament_cost": [ + "21.99" + ], + "filament_density": [ + "1.31" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1.json new file mode 100644 index 0000000000..8fb2780b8f --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Marble @U1.json @@ -0,0 +1,23 @@ +{ + "type": "filament", + "name": "Panchroma PLA Marble @U1", + "inherits": "Panchroma PLA Marble @U1 base", + "from": "system", + "setting_id": "GFSPM003_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1 base.json new file mode 100644 index 0000000000..9ab72e1484 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Matte @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM002", + "instantiation": "false", + "filament_cost": [ + "20.99" + ], + "filament_density": [ + "1.31" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1.json new file mode 100644 index 0000000000..9823adaa0c --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Matte @U1.json @@ -0,0 +1,23 @@ +{ + "type": "filament", + "name": "Panchroma PLA Matte @U1", + "inherits": "Panchroma PLA Matte @U1 base", + "from": "system", + "setting_id": "GFSPM002_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1 base.json new file mode 100644 index 0000000000..f9a33ba035 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Metallic @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM012", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1.json new file mode 100644 index 0000000000..0196929a54 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Metallic @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Metallic @U1", + "inherits": "Panchroma PLA Metallic @U1 base", + "from": "system", + "setting_id": "GFSPM012_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1 base.json new file mode 100644 index 0000000000..70332dc961 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Neon @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM013", + "instantiation": "false", + "filament_cost": [ + "24.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1.json new file mode 100644 index 0000000000..cc5ab3fbaf --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Neon @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Neon @U1", + "inherits": "Panchroma PLA Neon @U1 base", + "from": "system", + "setting_id": "GFSPM013_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1 base.json new file mode 100644 index 0000000000..1f38ea1a45 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1 base.json @@ -0,0 +1,42 @@ +{ + "type": "filament", + "name": "Panchroma PLA Satin @U1 base", + "renamed_from": "Panchroma PLA Stain @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM005", + "instantiation": "false", + "filament_cost": [ + "20.99" + ], + "filament_density": [ + "1.24" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "230" + ], + "nozzle_temperature_initial_layer": [ + "230" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "59" + ] +} diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1.json new file mode 100644 index 0000000000..6e914b56a4 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Satin @U1.json @@ -0,0 +1,27 @@ +{ + "type": "filament", + "name": "Panchroma PLA Satin @U1", + "renamed_from": "Panchroma PLA Stain @U1", + "inherits": "Panchroma PLA Satin @U1 base", + "from": "system", + "setting_id": "GFSPM005_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1 base.json new file mode 100644 index 0000000000..43e9f98164 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Silk @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM004", + "instantiation": "false", + "filament_cost": [ + "24.99" + ], + "filament_density": [ + "1.31" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "230" + ], + "nozzle_temperature_initial_layer": [ + "230" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "58" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1.json new file mode 100644 index 0000000000..52102ab63b --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Silk @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Silk @U1", + "inherits": "Panchroma PLA Silk @U1 base", + "from": "system", + "setting_id": "GFSPM004_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "12" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1 base.json new file mode 100644 index 0000000000..0c9fd9bf52 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Starlight @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM009", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1.json new file mode 100644 index 0000000000..9029dc250c --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Starlight @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Starlight @U1", + "inherits": "Panchroma PLA Starlight @U1 base", + "from": "system", + "setting_id": "GFSPM009_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1 base.json new file mode 100644 index 0000000000..c86779555f --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Temp Shift @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM015", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1.json new file mode 100644 index 0000000000..5d7e17696b --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Temp Shift @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Temp Shift @U1", + "inherits": "Panchroma PLA Temp Shift @U1 base", + "from": "system", + "setting_id": "GFSPM015_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1 base.json new file mode 100644 index 0000000000..cb786e6f9a --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA Translucent @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM006", + "instantiation": "false", + "filament_cost": [ + "24.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1.json new file mode 100644 index 0000000000..6e35878869 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA Translucent @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA Translucent @U1", + "inherits": "Panchroma PLA Translucent @U1 base", + "from": "system", + "setting_id": "GFSPM006_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1 base.json new file mode 100644 index 0000000000..c209198398 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "Panchroma PLA UV Shift @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM014", + "instantiation": "false", + "filament_cost": [ + "29.99" + ], + "filament_density": [ + "1.17" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "240" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "61" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1.json new file mode 100644 index 0000000000..f85802624c --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Panchroma PLA UV Shift @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Panchroma PLA UV Shift @U1", + "inherits": "Panchroma PLA UV Shift @U1 base", + "from": "system", + "setting_id": "GFSPM014_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite Dual PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite Dual PLA @0.2 nozzle.json new file mode 100644 index 0000000000..f47614d710 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite Dual PLA @0.2 nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyLite Dual PLA @0.2 nozzle", + "setting_id": "490991920", + "inherits": "PolyLite PLA @0.2 nozzle", + "compatible_printers": [ + "Snapmaker A250 Dual (0.2 nozzle)", + "Snapmaker A250 Dual BKit (0.2 nozzle)", + "Snapmaker A250 Dual QS+B Kit (0.2 nozzle)", + "Snapmaker A250 Dual QSKit (0.2 nozzle)", + "Snapmaker A350 Dual (0.2 nozzle)", + "Snapmaker A350 Dual BKit (0.2 nozzle)", + "Snapmaker A350 Dual QS+B Kit (0.2 nozzle)", + "Snapmaker A350 Dual QSKit (0.2 nozzle)", + "Snapmaker Artisan (0.2 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA @0.2 nozzle.json new file mode 100644 index 0000000000..4e2b21f785 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA @0.2 nozzle.json @@ -0,0 +1,11 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyLite J1 PLA @0.2 nozzle", + "setting_id": "431382384", + "inherits": "PolyLite PLA @0.2 nozzle", + "compatible_printers": [ + "Snapmaker J1 (0.2 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA.json new file mode 100644 index 0000000000..ac3cdd9ba9 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite J1 PLA.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyLite J1 PLA", + "setting_id": "116125055", + "inherits": "PolyLite PLA @base", + "compatible_printers": [ + "Snapmaker J1 (0.4 nozzle)", + "Snapmaker J1 (0.6 nozzle)", + "Snapmaker J1 (0.8 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Base.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Base.json new file mode 100644 index 0000000000..ed8ea01808 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Base.json @@ -0,0 +1,29 @@ +{ + "filament_density": [ + "1.25" + ], + "temp_min": [ + "230" + ], + "temp_max": [ + "240" + ], + "temperture_vitrification": [ + "75" + ], + "idle_temperture": [ + "0" + ], + "filament_soluble": [ + "0" + ], + "description": "", + "inherits": "fdm_filament_petg", + "name": "PolyLite PETG @Base", + "type": "filament", + "instantiation": "false", + "from": "system", + "filament_vendor": [ + "Polymaker" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Snapmaker U1.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Snapmaker U1.json new file mode 100644 index 0000000000..2e8a0e0943 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PETG @Snapmaker U1.json @@ -0,0 +1,117 @@ +{ + "type": "filament", + "name": "PolyLite PETG @Snapmaker U1", + "from": "system", + "instantiation": "true", + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "0" + ], + "hot_plate_temp": [ + "80" + ], + "textured_plate_temp": [ + "80" + ], + "cool_plate_temp_initial_layer": [ + "60" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "hot_plate_temp_initial_layer": [ + "80" + ], + "textured_plate_temp_initial_layer": [ + "80" + ], + "overhang_fan_threshold": [ + "95%" + ], + "overhang_fan_speed": [ + "100" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "close_fan_the_first_x_layers": [ + "3" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_flow_ratio": [ + "0.92" + ], + "fan_cooling_layer_time": [ + "20" + ], + "filament_cost": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "filament_max_volumetric_speed": [ + "7.5" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "bed_type": [ + "Cool Plate" + ], + "nozzle_temperature_initial_layer": [ + "260" + ], + "full_fan_speed_layer": [ + "0" + ], + "fan_max_speed": [ + "40" + ], + "fan_min_speed": [ + "0" + ], + "slow_down_min_speed": [ + "10" + ], + "slow_down_layer_time": [ + "6" + ], + "filament_start_gcode": [ + "; Filament gcode\n" + ], + "nozzle_temperature": [ + "260" + ], + "temperature_vitrification": [ + "81" + ], + "filament_id": "PMPE04", + "nozzle_temperature_range_high": [ + "260" + ], + "nozzle_temperature_range_low": [ + "230" + ], + "supertack_plate_temp": [ + "70" + ], + "supertack_plate_temp_initial_layer": [ + "70" + ], + "setting_id": "PMPE04_U1", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "pressure_advance": [ + "0.05" + ], + "inherits": "PolyLite PETG @Base" +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @0.2 nozzle.json new file mode 100644 index 0000000000..b3c643a042 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @0.2 nozzle.json @@ -0,0 +1,21 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyLite PLA @0.2 nozzle", + "setting_id": "1592803578", + "inherits": "PolyLite PLA @base", + "compatible_printers": [ + "Snapmaker A250 (0.2 nozzle)", + "Snapmaker A250 BKit (0.2 nozzle)", + "Snapmaker A250 QS+B Kit (0.2 nozzle)", + "Snapmaker A250 QSKit (0.2 nozzle)", + "Snapmaker A350 (0.2 nozzle)", + "Snapmaker A350 BKit (0.2 nozzle)", + "Snapmaker A350 QS+B Kit (0.2 nozzle)", + "Snapmaker A350 QSKit (0.2 nozzle)" + ], + "filament_max_volumetric_speed": [ + "1.6" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1 base.json new file mode 100644 index 0000000000..d0547572b6 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1 base.json @@ -0,0 +1,20 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "false", + "name": "PolyLite PLA @U1 base", + "filament_id": "13938660340", + "inherits": "fdm_filament_pla", + "filament_flow_ratio": [ + "0.95" + ], + "filament_cost": [ + "90" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "default_filament_colour": [ + "" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1.json new file mode 100644 index 0000000000..ad81f2d79d --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @U1.json @@ -0,0 +1,11 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyLite PLA @U1", + "setting_id": "6486836500", + "inherits": "PolyLite PLA @U1 base", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @base.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @base.json new file mode 100644 index 0000000000..2a7310f405 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA @base.json @@ -0,0 +1,20 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "false", + "name": "PolyLite PLA @base", + "filament_id": "1393866034", + "inherits": "fdm_filament_pla", + "filament_flow_ratio": [ + "0.95" + ], + "filament_cost": [ + "90" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "default_filament_colour": [ + "" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1 base.json new file mode 100644 index 0000000000..f5d87e4277 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1 base.json @@ -0,0 +1,41 @@ +{ + "type": "filament", + "name": "PolyLite PLA Pro @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM019", + "instantiation": "false", + "filament_cost": [ + "24.99" + ], + "filament_density": [ + "1.22" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "220" + ], + "nozzle_temperature_range_low": [ + "190" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "62" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1.json new file mode 100644 index 0000000000..f0b65f7717 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyLite PLA Pro @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "PolyLite PLA Pro @U1", + "inherits": "PolyLite PLA Pro @U1 base", + "from": "system", + "setting_id": "GFSPM019_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra Dual PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra Dual PLA @0.2 nozzle.json new file mode 100644 index 0000000000..c3673b4d3c --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra Dual PLA @0.2 nozzle.json @@ -0,0 +1,19 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyTerra Dual PLA @0.2 nozzle", + "setting_id": "1258531391", + "inherits": "PolyTerra PLA @0.2 nozzle", + "compatible_printers": [ + "Snapmaker A250 Dual (0.2 nozzle)", + "Snapmaker A250 Dual BKit (0.2 nozzle)", + "Snapmaker A250 Dual QS+B Kit (0.2 nozzle)", + "Snapmaker A250 Dual QSKit (0.2 nozzle)", + "Snapmaker A350 Dual (0.2 nozzle)", + "Snapmaker A350 Dual BKit (0.2 nozzle)", + "Snapmaker A350 Dual QS+B Kit (0.2 nozzle)", + "Snapmaker A350 Dual QSKit (0.2 nozzle)", + "Snapmaker Artisan (0.2 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA @0.2 nozzle.json new file mode 100644 index 0000000000..24fda4c652 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA @0.2 nozzle.json @@ -0,0 +1,11 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyTerra J1 PLA @0.2 nozzle", + "setting_id": "1072374370", + "inherits": "PolyTerra PLA @0.2 nozzle", + "compatible_printers": [ + "Snapmaker J1 (0.2 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA.json new file mode 100644 index 0000000000..9592d5cbd0 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra J1 PLA.json @@ -0,0 +1,13 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyTerra J1 PLA", + "setting_id": "3958200796", + "inherits": "PolyTerra PLA @base", + "compatible_printers": [ + "Snapmaker J1 (0.4 nozzle)", + "Snapmaker J1 (0.6 nozzle)", + "Snapmaker J1 (0.8 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @0.2 nozzle.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @0.2 nozzle.json new file mode 100644 index 0000000000..215685b8e3 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @0.2 nozzle.json @@ -0,0 +1,21 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyTerra PLA @0.2 nozzle", + "setting_id": "409934824", + "inherits": "PolyTerra PLA @base", + "compatible_printers": [ + "Snapmaker A250 (0.2 nozzle)", + "Snapmaker A250 BKit (0.2 nozzle)", + "Snapmaker A250 QS+B Kit (0.2 nozzle)", + "Snapmaker A250 QSKit (0.2 nozzle)", + "Snapmaker A350 (0.2 nozzle)", + "Snapmaker A350 BKit (0.2 nozzle)", + "Snapmaker A350 QS+B Kit (0.2 nozzle)", + "Snapmaker A350 QSKit (0.2 nozzle)" + ], + "filament_max_volumetric_speed": [ + "1.4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1 base.json new file mode 100644 index 0000000000..861179ca06 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1 base.json @@ -0,0 +1,20 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "false", + "name": "PolyTerra PLA @U1 base", + "filament_id": "37895926870", + "inherits": "fdm_filament_pla", + "filament_cost": [ + "80" + ], + "filament_density": [ + "1.31" + ], + "filament_max_volumetric_speed": [ + "14.4" + ], + "default_filament_colour": [ + "" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1.json new file mode 100644 index 0000000000..f77d1d8082 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/PolyTerra PLA @U1.json @@ -0,0 +1,11 @@ +{ + "type": "filament", + "from": "system", + "instantiation": "true", + "name": "PolyTerra PLA @U1", + "setting_id": "12580059400", + "inherits": "PolyTerra PLA @U1 base", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Base.json new file mode 100644 index 0000000000..77e155ade4 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Base.json @@ -0,0 +1,29 @@ +{ + "filament_density": [ + "1.28" + ], + "temp_min": [ + "210" + ], + "temp_max": [ + "230" + ], + "temperture_vitrification": [ + "156" + ], + "idle_temperture": [ + "0" + ], + "filament_soluble": [ + "0" + ], + "description": "", + "inherits": "fdm_filament_pla", + "name": "Polymaker HT-PLA @Base", + "type": "filament", + "instantiation": "false", + "from": "system", + "filament_vendor": [ + "Polymaker" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Snapmaker U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Snapmaker U1.json new file mode 100644 index 0000000000..b466d702fe --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @Snapmaker U1.json @@ -0,0 +1,96 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA @Snapmaker U1", + "from": "system", + "instantiation": "true", + "cool_plate_temp": [ + "50" + ], + "eng_plate_temp": [ + "50" + ], + "hot_plate_temp": [ + "65" + ], + "textured_plate_temp": [ + "50" + ], + "cool_plate_temp_initial_layer": [ + "50" + ], + "eng_plate_temp_initial_layer": [ + "50" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "50" + ], + "overhang_fan_threshold": [ + "50%" + ], + "overhang_fan_speed": [ + "100" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_flow_ratio": [ + "0.96" + ], + "filament_cost": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "bed_type": [ + "Cool Plate" + ], + "full_fan_speed_layer": [ + "0" + ], + "fan_max_speed": [ + "100" + ], + "slow_down_min_speed": [ + "5" + ], + "slow_down_layer_time": [ + "6" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ], + "nozzle_temperature": [ + "220" + ], + "temperature_vitrification": [ + "60" + ], + "nozzle_temperature_range_high": [ + "230" + ], + "additional_cooling_fan_speed": [ + "0" + ], + "setting_id": "PMPL02_U1", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "inherits": "Polymaker HT-PLA @Base", + "filament_id": "PMPL02" +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1 base.json new file mode 100644 index 0000000000..9a997d8e3f --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1 base.json @@ -0,0 +1,53 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM017", + "instantiation": "false", + "filament_cost": [ + "26.99" + ], + "filament_density": [ + "1.28" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "230" + ], + "nozzle_temperature_range_low": [ + "210" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "60" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1.json new file mode 100644 index 0000000000..da678d8a4c --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA @U1", + "inherits": "Polymaker HT-PLA @U1 base", + "from": "system", + "setting_id": "GFSPM017_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Base.json new file mode 100644 index 0000000000..4cd066b3d0 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Base.json @@ -0,0 +1,29 @@ +{ + "filament_density": [ + "1.34" + ], + "temp_min": [ + "210" + ], + "temp_max": [ + "230" + ], + "temperture_vitrification": [ + "148" + ], + "idle_temperture": [ + "0" + ], + "filament_soluble": [ + "0" + ], + "description": "", + "inherits": "fdm_filament_pla", + "name": "Polymaker HT-PLA-GF @Base", + "type": "filament", + "instantiation": "false", + "from": "system", + "filament_vendor": [ + "Polymaker" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Snapmaker U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Snapmaker U1.json new file mode 100644 index 0000000000..b18f79d461 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @Snapmaker U1.json @@ -0,0 +1,96 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA-GF @Snapmaker U1", + "from": "system", + "instantiation": "true", + "cool_plate_temp": [ + "50" + ], + "eng_plate_temp": [ + "50" + ], + "hot_plate_temp": [ + "65" + ], + "textured_plate_temp": [ + "50" + ], + "cool_plate_temp_initial_layer": [ + "50" + ], + "eng_plate_temp_initial_layer": [ + "50" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "50" + ], + "overhang_fan_threshold": [ + "50%" + ], + "overhang_fan_speed": [ + "100" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_flow_ratio": [ + "1.04" + ], + "filament_cost": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "bed_type": [ + "Cool Plate" + ], + "full_fan_speed_layer": [ + "0" + ], + "fan_max_speed": [ + "100" + ], + "slow_down_min_speed": [ + "5" + ], + "slow_down_layer_time": [ + "6" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ], + "nozzle_temperature": [ + "220" + ], + "temperature_vitrification": [ + "60" + ], + "nozzle_temperature_range_high": [ + "230" + ], + "additional_cooling_fan_speed": [ + "0" + ], + "setting_id": "PMPL01_U1", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "inherits": "Polymaker HT-PLA-GF @Base", + "filament_id": "PMPL01" +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1 base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1 base.json new file mode 100644 index 0000000000..fb70c1df40 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1 base.json @@ -0,0 +1,53 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA-GF @U1 base", + "inherits": "fdm_filament_pla", + "from": "system", + "filament_id": "GFPM018", + "instantiation": "false", + "filament_cost": [ + "32.99" + ], + "filament_density": [ + "1.34" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "filament_vendor": [ + "Polymaker" + ], + "hot_plate_temp": [ + "65" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "nozzle_temperature": [ + "220" + ], + "nozzle_temperature_initial_layer": [ + "220" + ], + "nozzle_temperature_range_high": [ + "230" + ], + "nozzle_temperature_range_low": [ + "210" + ], + "slow_down_layer_time": [ + "4" + ], + "temperature_vitrification": [ + "60" + ], + "textured_plate_temp": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "65" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1.json new file mode 100644 index 0000000000..554d1452be --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker HT-PLA-GF @U1.json @@ -0,0 +1,26 @@ +{ + "type": "filament", + "name": "Polymaker HT-PLA-GF @U1", + "inherits": "Polymaker HT-PLA-GF @U1 base", + "from": "system", + "setting_id": "GFSPM018_00", + "instantiation": "true", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "fan_max_speed": [ + "100" + ], + "fan_min_speed": [ + "100" + ], + "filament_flow_ratio": [ + "0.98" + ], + "filament_max_volumetric_speed": [ + "20" + ], + "slow_down_layer_time": [ + "4" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Base.json new file mode 100644 index 0000000000..04b25b012d --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Base.json @@ -0,0 +1,29 @@ +{ + "filament_density": [ + "1.3" + ], + "temp_min": [ + "240" + ], + "temp_max": [ + "260" + ], + "temperture_vitrification": [ + "75" + ], + "idle_temperture": [ + "0" + ], + "filament_soluble": [ + "0" + ], + "description": "", + "inherits": "fdm_filament_petg", + "name": "Polymaker PETG @Base", + "type": "filament", + "instantiation": "false", + "from": "system", + "filament_vendor": [ + "Polymaker" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Snapmaker U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Snapmaker U1.json new file mode 100644 index 0000000000..c7559a65f7 --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PETG @Snapmaker U1.json @@ -0,0 +1,111 @@ +{ + "type": "filament", + "name": "Polymaker PETG @Snapmaker U1", + "from": "system", + "instantiation": "true", + "cool_plate_temp": [ + "60" + ], + "eng_plate_temp": [ + "0" + ], + "hot_plate_temp": [ + "80" + ], + "textured_plate_temp": [ + "80" + ], + "cool_plate_temp_initial_layer": [ + "60" + ], + "eng_plate_temp_initial_layer": [ + "0" + ], + "hot_plate_temp_initial_layer": [ + "80" + ], + "textured_plate_temp_initial_layer": [ + "80" + ], + "overhang_fan_threshold": [ + "95%" + ], + "overhang_fan_speed": [ + "100" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "close_fan_the_first_x_layers": [ + "3" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_flow_ratio": [ + "0.96" + ], + "filament_cost": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "bed_type": [ + "Cool Plate" + ], + "nozzle_temperature_initial_layer": [ + "260" + ], + "full_fan_speed_layer": [ + "0" + ], + "fan_max_speed": [ + "10" + ], + "fan_min_speed": [ + "50" + ], + "slow_down_min_speed": [ + "10" + ], + "slow_down_layer_time": [ + "6" + ], + "filament_start_gcode": [ + "; Filament gcode\n" + ], + "nozzle_temperature": [ + "260" + ], + "temperature_vitrification": [ + "71" + ], + "filament_id": "PMPE01", + "nozzle_temperature_range_high": [ + "260" + ], + "nozzle_temperature_range_low": [ + "240" + ], + "supertack_plate_temp": [ + "70" + ], + "supertack_plate_temp_initial_layer": [ + "70" + ], + "setting_id": "PMPE01_U1", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "inherits": "Polymaker PETG @Base" +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Base.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Base.json new file mode 100644 index 0000000000..d25cf0270d --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Base.json @@ -0,0 +1,29 @@ +{ + "filament_density": [ + "1.23" + ], + "temp_min": [ + "190" + ], + "temp_max": [ + "230" + ], + "temperture_vitrification": [ + "55" + ], + "idle_temperture": [ + "0" + ], + "filament_soluble": [ + "0" + ], + "description": "", + "inherits": "fdm_filament_pla", + "name": "Polymaker PLA Pro @Base", + "type": "filament", + "instantiation": "false", + "from": "system", + "filament_vendor": [ + "Polymaker" + ] +} \ No newline at end of file diff --git a/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Snapmaker U1.json b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Snapmaker U1.json new file mode 100644 index 0000000000..8b77ae186f --- /dev/null +++ b/resources/profiles/Snapmaker/filament/Polymaker/Polymaker PLA Pro @Snapmaker U1.json @@ -0,0 +1,96 @@ +{ + "type": "filament", + "name": "Polymaker PLA Pro @Snapmaker U1", + "from": "system", + "instantiation": "true", + "cool_plate_temp": [ + "50" + ], + "eng_plate_temp": [ + "50" + ], + "hot_plate_temp": [ + "65" + ], + "textured_plate_temp": [ + "50" + ], + "cool_plate_temp_initial_layer": [ + "50" + ], + "eng_plate_temp_initial_layer": [ + "50" + ], + "hot_plate_temp_initial_layer": [ + "65" + ], + "textured_plate_temp_initial_layer": [ + "50" + ], + "overhang_fan_threshold": [ + "50%" + ], + "overhang_fan_speed": [ + "100" + ], + "slow_down_for_layer_cooling": [ + "1" + ], + "filament_end_gcode": [ + "; filament end gcode \n" + ], + "filament_flow_ratio": [ + "0.96" + ], + "filament_cost": [ + "0" + ], + "filament_diameter": [ + "1.75" + ], + "filament_max_volumetric_speed": [ + "15" + ], + "filament_minimal_purge_on_wipe_tower": [ + "15" + ], + "filament_vendor": [ + "Polymaker" + ], + "bed_type": [ + "Cool Plate" + ], + "full_fan_speed_layer": [ + "0" + ], + "fan_max_speed": [ + "100" + ], + "slow_down_min_speed": [ + "5" + ], + "slow_down_layer_time": [ + "6" + ], + "filament_start_gcode": [ + "; filament start gcode\n" + ], + "nozzle_temperature": [ + "220" + ], + "temperature_vitrification": [ + "61" + ], + "nozzle_temperature_range_high": [ + "230" + ], + "additional_cooling_fan_speed": [ + "0" + ], + "setting_id": "PMPL03_U1", + "compatible_printers": [ + "Snapmaker U1 (0.4 nozzle)" + ], + "inherits": "Polymaker PLA Pro @Base", + "filament_id": "PMPL03" +} \ No newline at end of file From ef876fe5770f1822720927ba692de11605ac646f Mon Sep 17 00:00:00 2001 From: Rodrigo Faselli <162915171+RF47@users.noreply.github.com> Date: Mon, 5 Jan 2026 09:15:23 -0300 Subject: [PATCH 40/45] Wipe Tower Auto Brim bug-fix (Non BBL printers) (#11831) # Description Fix application freeze when Prime Tower brim is set to Auto This PR fixes an issue where enabling Auto brim width for the Prime Tower caused the application to freeze and consume unbounded amounts of memory. Root cause https://github.com/OrcaSlicer/OrcaSlicer/blob/0c5f6c9865642f7ba923aee412f54f79f29531a2/src/libslic3r/GCode/WipeTower2.cpp#L2036-L2039 When Auto brim is selected, the brim width was not being computed and the raw configuration value (-1) was used directly. This resulted in an effectively infinite loop during Prime Tower brim generation, leading to runaway memory allocation instead of a controlled failure or a crash. Solution The Auto brim width is now properly computed based on the Prime Tower height, matching the intended behavior and existing logic used in other slicer implementations. --- src/libslic3r/GCode/WipeTower2.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode/WipeTower2.cpp b/src/libslic3r/GCode/WipeTower2.cpp index 6bec4168f4..19e98e4a09 100644 --- a/src/libslic3r/GCode/WipeTower2.cpp +++ b/src/libslic3r/GCode/WipeTower2.cpp @@ -2036,7 +2036,11 @@ WipeTower::ToolChangeResult WipeTower2::finish_layer() // brim (first layer only) if (first_layer) { writer.append("; WIPE_TOWER_BRIM_START\n"); - size_t loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing; + float brim_width = m_wipe_tower_brim_width; + if (brim_width < 0.f) + brim_width = WipeTower::get_auto_brim_by_height(m_wipe_tower_height); + + size_t loops_num = (brim_width + spacing / 2.f) / spacing; for (size_t i = 0; i < loops_num; ++ i) { poly = offset(poly, scale_(spacing)).front(); From 044a1d5ba4295509c10b90f3832e9813d55722b5 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 20:33:13 +0800 Subject: [PATCH 41/45] Fixed an issue where the wipe tower did not account for `z_offset`, especially when "No sparse layers" is enabled. (#11833) # Description This PR addresses the issue that WipeTower's start z position didn't consider the z_offset. fixes #11611 # Screenshots/Recordings/Graphs ## Tests --- src/libslic3r/GCode.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 2bf29aa002..30c48df054 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -97,7 +97,8 @@ public: m_enable_timelapse_print(print_config.timelapse_type.value == TimelapseType::tlSmooth), m_enable_wrapping_detection(print_config.enable_wrapping_detection && (print_config.wrapping_exclude_area.values.size() > 2) && (slice_used_filaments.size() <= 1)), m_is_first_print(true), - m_print_config(&print_config) + m_print_config(&print_config), + m_last_wipe_tower_print_z(print_config.z_offset.value) { // initialize with the extruder offset of master extruder id m_extruder_offsets.resize(print_config.filament_map.size(), print_config.extruder_offset.get_at(print_config.master_extruder_id.value - 1)); @@ -143,7 +144,7 @@ private: // Current layer index. int m_layer_idx; int m_tool_change_idx; - double m_last_wipe_tower_print_z = 0.f; + double m_last_wipe_tower_print_z; // BBS Vec3d m_plate_origin; From 01f5c4caaaf0897389307e9f69346acd24bf71ba Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 23:28:33 +0800 Subject: [PATCH 42/45] Fix an error that AppConfig::save is called from non main thread --- src/libslic3r/AppConfig.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index a5fda9f9cb..4fd9b565b3 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -146,7 +146,7 @@ void AppConfig::set_defaults() if (was_legacy && network_version.empty()) { // User had legacy mode enabled - set to legacy version number BOOST_LOG_TRIVIAL(info) << "Migrating legacy_networking=true to network_plugin_version=01.10.01.01"; - set("network_plugin_version", BAMBU_NETWORK_AGENT_VERSION_LEGACY); + set_network_plugin_version(BAMBU_NETWORK_AGENT_VERSION_LEGACY); } // Note: If was_legacy=false, we leave the version empty and let the GUI layer set it to the latest version diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index fef82357ae..7e32dab4ed 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1522,7 +1522,10 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP config_version = BBL::get_latest_network_version(); BOOST_LOG_TRIVIAL(info) << "[install_plugin] config_version was empty, using latest: " << config_version; app_config->set_network_plugin_version(config_version); + GUI::wxGetApp().CallAfter([this] { + if (app_config) app_config->save(); + }); } if (!config_version.empty() && boost::filesystem::exists(legacy_lib_path)) { #if defined(_MSC_VER) || defined(_WIN32) From b908c33eea748b7e8f3fcdba07918d9430d4262e Mon Sep 17 00:00:00 2001 From: SoftFever Date: Mon, 5 Jan 2026 23:29:22 +0800 Subject: [PATCH 43/45] Improve hot reload plugin --- src/slic3r/GUI/GUI_App.cpp | 104 ++++++++++++++++++++++++++++++++----- src/slic3r/GUI/GUI_App.hpp | 2 + 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 7e32dab4ed..fda19112d4 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1524,7 +1524,7 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP app_config->set_network_plugin_version(config_version); GUI::wxGetApp().CallAfter([this] { if (app_config) - app_config->save(); + app_config->save(); }); } if (!config_version.empty() && boost::filesystem::exists(legacy_lib_path)) { @@ -1643,6 +1643,70 @@ void GUI_App::restart_networking() BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(" exit, m_agent=%1%")%m_agent; } +// Network plugin hot reload timeout constants (in milliseconds) +namespace { + constexpr int CALLBACK_DRAIN_TIMEOUT_MS = 200; // Time to drain pending CallAfter callbacks + constexpr int NETWORK_IDLE_TIMEOUT_MS = 500; // Max wait for network operations to complete + constexpr int FINAL_DRAIN_TIMEOUT_MS = 100; // Final event processing before destruction + constexpr int POLL_INTERVAL_MS = 50; // Polling interval for state checks + constexpr int MAX_YIELD_ITERATIONS = 20; // Maximum wxYield calls per drain cycle +} + +// Process pending wx events with bounded iteration count +void GUI_App::drain_pending_events(int timeout_ms) +{ + const auto deadline = std::chrono::steady_clock::now() + + std::chrono::milliseconds(timeout_ms); + int yield_count = 0; + + while (std::chrono::steady_clock::now() < deadline) { + // Process pending events + if (wxTheApp) { + wxTheApp->ProcessPendingEvents(); + } + + // Bounded wxYield to prevent infinite loops + if (yield_count < MAX_YIELD_ITERATIONS) { + wxYield(); + ++yield_count; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(POLL_INTERVAL_MS)); + } +} + +// Wait for network operations to complete with state verification +bool GUI_App::wait_for_network_idle(int timeout_ms) +{ + const auto deadline = std::chrono::steady_clock::now() + + std::chrono::milliseconds(timeout_ms); + + while (std::chrono::steady_clock::now() < deadline) { + if (!m_agent) { + return true; // Agent already gone + } + + // Verify all operations completed + bool server_disconnected = !m_agent->is_server_connected(); + + if (server_disconnected) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": network is idle"; + return true; + } + + // Process events while waiting + if (wxTheApp) { + wxTheApp->ProcessPendingEvents(); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(POLL_INTERVAL_MS)); + } + + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": timeout after " << timeout_ms + << "ms, server_connected=" << (m_agent ? m_agent->is_server_connected() : false); + return false; +} + bool GUI_App::hot_reload_network_plugin() { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": starting hot reload"; @@ -1671,8 +1735,8 @@ bool GUI_App::hot_reload_network_plugin() } if (m_agent) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": clearing callbacks and stopping operations"; - + // Phase 1: Clear all callbacks (stops new invocations) + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 1 - clearing callbacks"; m_agent->set_on_ssdp_msg_fn(nullptr); m_agent->set_on_user_login_fn(nullptr); m_agent->set_on_printer_connected_fn(nullptr); @@ -1685,23 +1749,39 @@ bool GUI_App::hot_reload_network_plugin() m_agent->set_on_local_message_fn(nullptr); m_agent->set_queue_on_main_fn(nullptr); - m_agent->start_discovery(false, false); - m_agent->disconnect_printer(); + // Phase 2: Drain pending CallAfter callbacks (bounded) + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 2 - draining callbacks"; + drain_pending_events(CALLBACK_DRAIN_TIMEOUT_MS); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // Phase 3: Stop operations and verify return values + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 3 - stopping operations"; + bool discovery_stopped = m_agent->start_discovery(false, false); + int disconnect_result = m_agent->disconnect_printer(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": discovery_stopped=" << discovery_stopped + << ", disconnect_result=" << disconnect_result; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": destroying network agent"; + // Phase 4: Wait for idle with state verification + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 4 - waiting for idle"; + bool became_idle = wait_for_network_idle(NETWORK_IDLE_TIMEOUT_MS); + if (!became_idle) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": proceeding despite timeout"; + } + + // Phase 5: Final bounded drain before destruction + drain_pending_events(FINAL_DRAIN_TIMEOUT_MS); + + // Phase 6: Destroy agent + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 6 - destroying agent"; delete m_agent; m_agent = nullptr; - - std::this_thread::sleep_for(std::chrono::milliseconds(300)); } + // Phase 7: Unload module if (Slic3r::NetworkAgent::is_network_module_loaded()) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unloading old module"; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Phase 7 - unloading module"; + drain_pending_events(FINAL_DRAIN_TIMEOUT_MS); int unload_result = Slic3r::NetworkAgent::unload_network_module(); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unload result = " << unload_result; - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unload_result=" << unload_result; } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": calling restart_networking"; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 7e78003497..b84dc97c54 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -703,6 +703,8 @@ private: void init_networking_callbacks(); void init_app_config(); void remove_old_networking_plugins(); + void drain_pending_events(int timeout_ms); + bool wait_for_network_idle(int timeout_ms); //BBS set extra header for http request std::map get_extra_header(); void init_http_extra_header(); From 883c095a53fc66cc6fa269880021c7590a930bb6 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 6 Jan 2026 00:04:59 +0800 Subject: [PATCH 44/45] Remove the warning message for legacy version to keep it consistent with the original "legacy option." --- src/slic3r/Utils/bambu_networking.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index e9f756e705..c4eafe6988 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -318,7 +318,7 @@ static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = { {"02.03.00.62", "02.03.00.62", nullptr, true, nullptr}, {"02.01.01.52", "02.01.01.52", nullptr, false, nullptr}, {"02.00.02.50", "02.00.02.50", nullptr, false, "This version may crash on startup due to Bambu Lab's signature verification."}, - {BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, "Legacy version - may not support newer firmware features. Only use if you have issues with modern versions."}, + {BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, nullptr}, }; static const size_t AVAILABLE_NETWORK_VERSIONS_COUNT = sizeof(AVAILABLE_NETWORK_VERSIONS) / sizeof(AVAILABLE_NETWORK_VERSIONS[0]); From eab86797dd5ac8b89ed8a386852654b8b6e79e7d Mon Sep 17 00:00:00 2001 From: Ioannis Giannakas <59056762+igiannakas@users.noreply.github.com> Date: Mon, 5 Jan 2026 22:41:04 +0000 Subject: [PATCH 45/45] Relax flushing volume thresholds for printers needing higher purge. (#11778) * Relax flushing volume thresholds for printers needing higher purge. * Revert multiplier UI color handling --- resources/web/flush/WipingDialog.html | 5 +++-- src/libslic3r/FlushVolCalc.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/web/flush/WipingDialog.html b/resources/web/flush/WipingDialog.html index efaea1c8ea..249ee03449 100644 --- a/resources/web/flush/WipingDialog.html +++ b/resources/web/flush/WipingDialog.html @@ -432,10 +432,11 @@ return (0.299 * r + 0.587 * g + 0.114 * b) / 255; } - function updateVolumeRange(min_volume,max_volume){ + // Orca: "Typical" guidance only unlinked from upper bound in the slicer. + const TYPICAL_MAX_FLUSH_VOLUME = 900; const panel = document.getElementById('volume_range_panel'); - panel.innerText = panel.innerText.replace(/\[.*\]/, `[${min_volume}, ${max_volume}]`); + panel.innerText = panel.innerText.replace(/\[.*\]/, `[${min_volume}, ${TYPICAL_MAX_FLUSH_VOLUME}]`); } function updateMultiplierRange(min_multiplier,max_multiplier){ diff --git a/src/libslic3r/FlushVolCalc.cpp b/src/libslic3r/FlushVolCalc.cpp index 675732d767..9bdbc1737d 100644 --- a/src/libslic3r/FlushVolCalc.cpp +++ b/src/libslic3r/FlushVolCalc.cpp @@ -10,7 +10,8 @@ namespace Slic3r { const int g_min_flush_volume_from_support = 700; const int g_flush_volume_to_support = 230; -const int g_max_flush_volume = 900; +const int g_max_flush_volume = 20000; //Orca: increase limit to 20k vs 900 in upstream BBS code. + // Retain a clamp to guard against extreme values entered in the UI static float to_radians(float degree) {

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 z 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͹ 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%0ADE#~isdgm8$k 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