Compare commits

..
Author SHA1 Message Date
Ian Chua b73e9df4f4 test: update profiles for ota update 2026-09-25 14:29:48 +08:00
279 changed files with 2660 additions and 14817 deletions
+47 -40
View File
@@ -12,9 +12,9 @@ name: Daily OFL OTA Update
# vendor-dispatch path is also what makes post_merge_profiles.yml call the OTA auto-publish API after # vendor-dispatch path is also what makes post_merge_profiles.yml call the OTA auto-publish API after
# uploading - see post_merge_profiles.yml for both sides of that contract. # uploading - see post_merge_profiles.yml for both sides of that contract.
# #
# At the start of each run, the pending-publish table is cleared up to a captured # If at least one branch was dispatched this run, a final step clears OFL's pending-publish
# timestamp (POST /api/v1/ota/ofl/pending/clear?timestamp=...). Changes merged after # table (POST /api/v1/ota/ofl/pending/clear) - the daily "published everything, reset" signal.
# that timestamp remain pending for the next run. # That table is populated only by this pipeline's own auto-publish calls.
on: on:
schedule: schedule:
@@ -34,32 +34,6 @@ jobs:
if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' }} if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Capture start timestamp and clear OFL pending queue
id: start
shell: bash
env:
OTA_API_BASE_URL: ${{ vars.OTA_API_BASE_URL }}
OTA_API_KEY: ${{ secrets.OFL_OTA_PUBLISH_KEY }}
run: |
set -euo pipefail
[ -n "$OTA_API_BASE_URL" ] || { echo "::error::vars.OTA_API_BASE_URL is not set"; exit 1; }
[ -n "$OTA_API_KEY" ] || { echo "::error::secrets.OFL_OTA_PUBLISH_KEY is not set"; exit 1; }
timestamp="$(date -u +%s)"
echo "timestamp=$timestamp" >> "$GITHUB_OUTPUT"
resp_file="$RUNNER_TEMP/ota-pending-clear-response.json"
status="$(curl -sS -o "$resp_file" -w '%{http_code}' -X POST \
"${OTA_API_BASE_URL%/}/api/v1/ota/ofl/pending/clear?timestamp=$timestamp" \
-H "Authorization: Bearer $OTA_API_KEY")"
body="$(cat "$resp_file")"
echo "$body"
if [ "$status" != "200" ]; then
echo "::error::OTA pending-clear call failed with HTTP $status"
exit 1
fi
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v7
with: with:
@@ -72,12 +46,13 @@ jobs:
run: git fetch origin '+refs/heads/*:refs/remotes/origin/*' run: git fetch origin '+refs/heads/*:refs/remotes/origin/*'
- name: Scan branches and publish changed OFL profiles - name: Scan branches and publish changed OFL profiles
id: scan
shell: bash shell: bash
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SCAN_UNTIL: ${{ steps.start.outputs.timestamp }}
run: | run: |
set -euo pipefail set -euo pipefail
published_any=false
mapfile -t branches < <( mapfile -t branches < <(
gh api "repos/${{ github.repository }}/branches" --paginate --jq '.[].name' \ gh api "repos/${{ github.repository }}/branches" --paginate --jq '.[].name' \
@@ -104,36 +79,68 @@ jobs:
--jq '.workflow_runs[0].run_started_at // empty')" --jq '.workflow_runs[0].run_started_at // empty')"
if [ -z "$since" ]; then if [ -z "$since" ]; then
echo "No prior successful run for $branch; checking OFL changes up to $SCAN_UNTIL." echo "No prior successful run for $branch; treating OFL as changed."
changed_files="$(git log --until="$SCAN_UNTIL" --name-only --pretty=format: "origin/$branch" -- \ changed=true
resources/profiles/OrcaFilamentLibrary resources/profiles/OrcaFilamentLibrary.json \
| sed '/^$/d')"
else else
changed_files="$(git log --since="$since" --until="$SCAN_UNTIL" --name-only --pretty=format: "origin/$branch" -- \ changed_files="$(git log --since="$since" --name-only --pretty=format: "origin/$branch" -- \
resources/profiles/OrcaFilamentLibrary resources/profiles/OrcaFilamentLibrary.json \ resources/profiles/OrcaFilamentLibrary resources/profiles/OrcaFilamentLibrary.json \
| sed '/^$/d')" | sed '/^$/d')"
fi
if [ -n "$changed_files" ]; then if [ -n "$changed_files" ]; then
echo "OFL changed on $branch from ${since:-the beginning} through $SCAN_UNTIL:" echo "OFL changed on $branch since $since:"
echo "$changed_files" echo "$changed_files"
changed=true changed=true
else else
echo "No OFL changes on $branch through $SCAN_UNTIL." echo "No OFL changes on $branch since $since."
changed=false changed=false
fi fi
fi
if [ "$changed" = true ]; then if [ "$changed" = true ]; then
# Tolerate a per-branch failure (e.g. a pre-existing release branch # Tolerate a per-branch failure (e.g. a pre-existing release branch
# whose post_merge_profiles.yml predates the vendor/auto_publish # whose post_merge_profiles.yml predates the vendor/auto_publish
# inputs) rather than aborting the whole scan under set -e. # inputs) rather than aborting the whole scan under set -e.
if ! gh workflow run post_merge_profiles.yml \ if gh workflow run post_merge_profiles.yml \
--repo "${{ github.repository }}" \ --repo "${{ github.repository }}" \
--ref "$branch" \ --ref "$branch" \
-f vendor="$VENDOR" -f auto_publish=true; then -f vendor="$VENDOR" -f auto_publish=true; then
published_any=true
else
echo "::warning::failed to dispatch post_merge_profiles.yml for $branch - its post_merge_profiles.yml at this ref may predate the vendor/auto_publish inputs" echo "::warning::failed to dispatch post_merge_profiles.yml for $branch - its post_merge_profiles.yml at this ref may predate the vendor/auto_publish inputs"
fi fi
fi fi
echo "::endgroup::" echo "::endgroup::"
done done
echo "published_any=$published_any" >> "$GITHUB_OUTPUT"
- name: Clear OFL pending queue
# Only when this run actually kicked off at least one publish - the
# daily reset is scoped to today's real activity, not called on a day
# where every branch reported no changes. Note "published_any" reflects
# a successful DISPATCH, not a confirmed live publish: gh workflow run
# is fire-and-forget, so this workflow never learns whether the
# dispatched post_merge_profiles.yml run actually reached its own
# auto-publish call. Acceptable since the table is populated only by
# our own auto-publish calls, not by anything else.
if: steps.scan.outputs.published_any == 'true'
shell: bash
env:
OTA_API_BASE_URL: ${{ vars.OTA_API_BASE_URL }}
OTA_API_KEY: ${{ secrets.OFL_OTA_PUBLISH_KEY }}
run: |
set -euo pipefail
[ -n "$OTA_API_BASE_URL" ] || { echo "::error::vars.OTA_API_BASE_URL is not set"; exit 1; }
[ -n "$OTA_API_KEY" ] || { echo "::error::secrets.OFL_OTA_PUBLISH_KEY is not set"; exit 1; }
resp_file="$RUNNER_TEMP/ota-pending-clear-response.json"
status="$(curl -sS -o "$resp_file" -w '%{http_code}' -X POST \
"${OTA_API_BASE_URL%/}/api/v1/ota/ofl/pending/clear" \
-H "Authorization: Bearer $OTA_API_KEY")"
body="$(cat "$resp_file")"
echo "$body"
if [ "$status" != "200" ]; then
echo "::error::OTA pending-clear call failed with HTTP $status"
exit 1
fi
+3 -49
View File
@@ -56,9 +56,9 @@ You can do this in Environment Variables settings.
endif () endif ()
if (APPLE) if (APPLE)
# if CMAKE_OSX_DEPLOYMENT_TARGET is not set, set it to 12.0 (the lowest Xcode 27 accepts) # if CMAKE_OSX_DEPLOYMENT_TARGET is not set, set it to 11.3
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET) if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum OS X deployment version" FORCE) set(CMAKE_OSX_DEPLOYMENT_TARGET "11.3" CACHE STRING "Minimum OS X deployment version" FORCE)
endif () endif ()
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}") message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif () endif ()
@@ -279,11 +279,6 @@ if (APPLE)
endif() endif()
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer") SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
# The macOS CI jobs build with Ninja (build_release_macos.sh -x), so the Xcode generator
# is not covered. Xcode adds -Wshorten-64-to-32 by default ("Implicit Conversion to 32 Bit
# Type"); Ninja/-Wall does not, and under -Werror it fails Xcode builds on code CI accepts.
set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION "NO")
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}") message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_INSTALL_RPATH "$ORIGIN") set(CMAKE_INSTALL_RPATH "$ORIGIN")
@@ -834,37 +829,6 @@ find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED) find_package(CURL REQUIRED)
find_package(Freetype REQUIRED) find_package(Freetype REQUIRED)
if (SLIC3R_GUI)
# LibDataChannel's installed export references its bundled dependencies,
# but does not install their CMake targets. Recreate those targets from
# the same dependency prefix before loading the LibDataChannel config.
if (NOT TARGET Usrsctp::usrsctp)
find_library(_ORCA_USRSCTP_LIBRARY NAMES usrsctp
PATHS "${CMAKE_PREFIX_PATH}/lib" NO_DEFAULT_PATH)
if (_ORCA_USRSCTP_LIBRARY)
add_library(Usrsctp::usrsctp UNKNOWN IMPORTED GLOBAL)
set_target_properties(Usrsctp::usrsctp PROPERTIES
IMPORTED_LOCATION "${_ORCA_USRSCTP_LIBRARY}"
IMPORTED_LINK_INTERFACE_LANGUAGES C
INTERFACE_LINK_LIBRARIES "Threads::Threads")
endif()
endif()
if (NOT TARGET LibJuice::LibJuice)
find_library(_ORCA_LIBJUICE_LIBRARY NAMES juice
PATHS "${CMAKE_PREFIX_PATH}/lib" NO_DEFAULT_PATH)
if (_ORCA_LIBJUICE_LIBRARY)
add_library(LibJuice::LibJuice UNKNOWN IMPORTED GLOBAL)
set_target_properties(LibJuice::LibJuice PROPERTIES
IMPORTED_LOCATION "${_ORCA_LIBJUICE_LIBRARY}"
IMPORTED_LINK_INTERFACE_LANGUAGES C
INTERFACE_LINK_LIBRARIES "Threads::Threads")
endif()
endif()
find_package(LibDataChannel CONFIG REQUIRED)
endif()
add_library(libcurl INTERFACE) add_library(libcurl INTERFACE)
target_link_libraries(libcurl INTERFACE CURL::libcurl) target_link_libraries(libcurl INTERFACE CURL::libcurl)
@@ -1145,7 +1109,6 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
endif () endif ()
file(COPY ${_occt_dlls} file(COPY ${_occt_dlls}
${CMAKE_PREFIX_PATH}/bin/freetype.dll ${CMAKE_PREFIX_PATH}/bin/freetype.dll
${CMAKE_PREFIX_PATH}/bin/avformat-61.dll
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll ${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll ${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll ${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
@@ -1158,7 +1121,6 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
${_out_dir}/WebView2Loader.dll ${_out_dir}/WebView2Loader.dll
${_out_dir}/freetype.dll ${_out_dir}/freetype.dll
${_out_dir}/avformat-61.dll
${_out_dir}/avcodec-61.dll ${_out_dir}/avcodec-61.dll
${_out_dir}/swresample-5.dll ${_out_dir}/swresample-5.dll
${_out_dir}/swscale-8.dll ${_out_dir}/swscale-8.dll
@@ -1182,10 +1144,7 @@ function(orcaslicer_copy_sos target config postfix output_sos)
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}") set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}")
endif () endif ()
file(COPY ${CMAKE_PREFIX_PATH}/lib/libavformat.so file(COPY ${CMAKE_PREFIX_PATH}/lib/libavcodec.so
${CMAKE_PREFIX_PATH}/lib/libavformat.so.61
${CMAKE_PREFIX_PATH}/lib/libavformat.so.61.1.100
${CMAKE_PREFIX_PATH}/lib/libavcodec.so
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61 ${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100 ${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100
${CMAKE_PREFIX_PATH}/lib/libavutil.so ${CMAKE_PREFIX_PATH}/lib/libavutil.so
@@ -1200,9 +1159,6 @@ function(orcaslicer_copy_sos target config postfix output_sos)
DESTINATION ${_out_dir}) DESTINATION ${_out_dir})
set(${output_sos} set(${output_sos}
${_out_dir}/libavformat.so
${_out_dir}/libavformat.so.61
${_out_dir}/libavformat.so.61.1.100
${_out_dir}/libavcodec.so ${_out_dir}/libavcodec.so
${_out_dir}/libavcodec.so.61 ${_out_dir}/libavcodec.so.61
${_out_dir}/libavcodec.so.61.3.100 ${_out_dir}/libavcodec.so.61.3.100
@@ -1332,8 +1288,6 @@ endif ()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux") if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LIBRARY_FILES set(LIBRARY_FILES
${LIBDIR_BIN}/libavformat.so.61
${LIBDIR_BIN}/libavformat.so.61.1.100
${LIBDIR_BIN}/libavcodec.so.61 ${LIBDIR_BIN}/libavcodec.so.61
${LIBDIR_BIN}/libavcodec.so.61.3.100 ${LIBDIR_BIN}/libavcodec.so.61.3.100
${LIBDIR_BIN}/libavutil.so.59 ${LIBDIR_BIN}/libavutil.so.59
+2 -2
View File
@@ -53,7 +53,7 @@ while getopts ":dpa:snt:xbc:i:j:Tuh" opt; do
echo " -s: Build slicer only" echo " -s: Build slicer only"
echo " -u: Build universal app only (requires existing arm64 and x86_64 app bundles)" echo " -u: Build universal app only (requires existing arm64 and x86_64 app bundles)"
echo " -n: Nightly build" echo " -n: Nightly build"
echo " -t: Specify minimum version of the target platform, default is 12.0" echo " -t: Specify minimum version of the target platform, default is 11.3"
echo " -x: Use Ninja Multi-Config CMake generator, default is Xcode" echo " -x: Use Ninja Multi-Config CMake generator, default is Xcode"
echo " -b: Build without reconfiguring CMake" echo " -b: Build without reconfiguring CMake"
echo " -c: Set CMake build configuration, default is Release" echo " -c: Set CMake build configuration, default is Release"
@@ -95,7 +95,7 @@ if [ -z "$DEPS_CMAKE_GENERATOR" ]; then
fi fi
if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then
export OSX_DEPLOYMENT_TARGET="12.0" export OSX_DEPLOYMENT_TARGET="11.3"
fi fi
if [ -z "$CMAKE_IGNORE_PREFIX_PATH" ]; then if [ -z "$CMAKE_IGNORE_PREFIX_PATH" ]; then
+8 -20
View File
@@ -26,9 +26,9 @@ endif()
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.2)
if (APPLE) if (APPLE)
# if CMAKE_OSX_DEPLOYMENT_TARGET is not set, set it to 12.0 (the lowest Xcode 27 accepts) # if CMAKE_OSX_DEPLOYMENT_TARGET is not set, set it to 11.3
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET) if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum OS X deployment version" FORCE) set(CMAKE_OSX_DEPLOYMENT_TARGET "11.3" CACHE STRING "Minimum OS X deployment version" FORCE)
endif () endif ()
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}") message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
@@ -164,7 +164,7 @@ if (NOT _is_multi AND NOT CMAKE_BUILD_TYPE)
endif () endif ()
function(orcaslicer_add_cmake_project projectname) function(orcaslicer_add_cmake_project projectname)
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND;SOURCE_DIR" "CMAKE_ARGS" ${ARGN}) cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
# MSVC is true for clang-cl as well, so the sub-build toolchain has to key on the # MSVC is true for clang-cl as well, so the sub-build toolchain has to key on the
# generator. A non-Visual-Studio superbuild passes its own generator down, and with # generator. A non-Visual-Studio superbuild passes its own generator down, and with
@@ -210,18 +210,12 @@ function(orcaslicer_add_cmake_project projectname)
set(_build_j "-j${NPROC}") set(_build_j "-j${NPROC}")
endif () endif ()
set(_source_dir_arg "")
if (P_ARGS_SOURCE_DIR)
set(_source_dir_arg SOURCE_DIR ${P_ARGS_SOURCE_DIR})
endif ()
if (NOT IS_CROSS_COMPILE OR NOT APPLE) if (NOT IS_CROSS_COMPILE OR NOT APPLE)
ExternalProject_Add( ExternalProject_Add(
dep_${projectname} dep_${projectname}
EXCLUDE_FROM_ALL ON EXCLUDE_FROM_ALL ON
INSTALL_DIR ${DESTDIR} INSTALL_DIR ${DESTDIR}
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname} DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_source_dir_arg}
${_gen} ${_gen}
CMAKE_ARGS CMAKE_ARGS
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_POLICY_VERSION_MINIMUM=3.5
@@ -255,14 +249,12 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE)
# note for future devs: shared libs may actually create a size reduction # note for future devs: shared libs may actually create a size reduction
# but orcaslicer_deps tends to get really funny regarding linking after that (notably boost) # but orcaslicer_deps tends to get really funny regarding linking after that (notably boost)
# so, as much as I would like to use that, it's not happening # so, as much as I would like to use that, it's not happening
if (NOT P_ARGS_SOURCE_DIR)
ExternalProject_Add_Step(dep_${projectname} free_download_space ExternalProject_Add_Step(dep_${projectname} free_download_space
DEPENDEES download # do after download DEPENDEES download # do after download
COMMENT "Freeing Space: Removing source archive" COMMENT "Freeing Space: Removing source archive"
WORKING_DIRECTORY ${DEP_DOWNLOAD_DIR} WORKING_DIRECTORY ${DEP_DOWNLOAD_DIR}
COMMAND ${CMAKE_COMMAND} -E rm -rf ${projectname} COMMAND ${CMAKE_COMMAND} -E rm -r ${projectname}
) )
endif ()
ExternalProject_Add_Step(dep_${projectname} free_build_space ExternalProject_Add_Step(dep_${projectname} free_build_space
DEPENDEES install # do after install DEPENDEES install # do after install
COMMENT "Freeing Space: Removing source and build files" COMMENT "Freeing Space: Removing source and build files"
@@ -276,7 +268,6 @@ else()
EXCLUDE_FROM_ALL ON EXCLUDE_FROM_ALL ON
INSTALL_DIR ${DESTDIR} INSTALL_DIR ${DESTDIR}
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname} DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_source_dir_arg}
${_gen} ${_gen}
CMAKE_ARGS CMAKE_ARGS
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_POLICY_VERSION_MINIMUM=3.5
@@ -405,6 +396,10 @@ include(libnoise/libnoise.cmake)
include(Draco/Draco.cmake) include(Draco/Draco.cmake)
include(FFMPEG/FFMPEG.cmake)
include(Assimp/Assimp.cmake)
# I *think* 1.1 is used for *just* md5 hashing? # I *think* 1.1 is used for *just* md5 hashing?
# 3.1 has everything in the right place, but the md5 funcs used are deprecated # 3.1 has everything in the right place, but the md5 funcs used are deprecated
# a grep across the repo shows it is used for other things # a grep across the repo shows it is used for other things
@@ -415,12 +410,6 @@ if(NOT OPENSSL_FOUND)
set(OPENSSL_PKG dep_OpenSSL) set(OPENSSL_PKG dep_OpenSSL)
endif() endif()
include(FFMPEG/FFMPEG.cmake)
include(Assimp/Assimp.cmake)
include(DataChannel/DataChannel.cmake)
set(DATACHANNEL_PKG dep_DataChannel)
# we don't want to load a "wrong" openssl when loading curl # we don't want to load a "wrong" openssl when loading curl
# so, just don't even bother # so, just don't even bother
# ...i think this is how it works? change if wrong # ...i think this is how it works? change if wrong
@@ -494,7 +483,6 @@ set(_dep_list
dep_wxInspector dep_wxInspector
dep_FFMPEG dep_FFMPEG
dep_Assimp dep_Assimp
${DATACHANNEL_PKG}
) )
if (MSVC) if (MSVC)
-37
View File
@@ -1,37 +0,0 @@
# libdatachannel is the native ICE/DTLS/SCTP implementation used by the
# GUI WebRTC camera controller. Keep the source revision fixed: the signaling
# protocol is evolving independently of this transport dependency.
#
# It vendors plog, usrsctp and libjuice as git submodules, which a plain
# GitHub tag tarball does not include. The flatpak sandbox has no network
# access during the build, so there the manifest itself clones the repo
# (submodules and all) into the dependency download directory before the
# sandbox closes. ExternalProject_Add is pointed at that existing checkout
# instead of being given its own network-dependent download method.
if (FLATPAK)
set(_datachannel_source
SOURCE_DIR ${DEP_DOWNLOAD_DIR}/DataChannel
)
else()
set(_datachannel_source
GIT_REPOSITORY https://github.com/paullouisageneau/libdatachannel.git
GIT_TAG v0.24.5
GIT_SHALLOW ON
GIT_SUBMODULES_RECURSE ON
)
endif()
orcaslicer_add_cmake_project(DataChannel
DEPENDS ${OPENSSL_PKG}
CMAKE_ARGS
-DNO_EXAMPLES=ON
-DNO_TESTS=ON
-DNO_WEBSOCKET=ON
-DNO_MEDIA=ON
-DUSE_NICE=OFF
-DUSE_SYSTEM_JUICE=OFF
-DUSE_SYSTEM_USRSCTP=OFF
-DOPENSSL_ROOT_DIR:PATH=${DESTDIR}
-DOPENSSL_USE_STATIC_LIBS=ON
${_datachannel_source}
)
+7 -23
View File
@@ -1,26 +1,14 @@
set(_conf_cmd ./configure) set(_conf_cmd ./configure)
set(_ffmpeg_depends)
set(_ffmpeg_configure_command ${_conf_cmd})
if (TARGET dep_OpenSSL)
set(_ffmpeg_depends DEPENDS dep_OpenSSL)
set(_ffmpeg_configure_command
${CMAKE_COMMAND} -E env
"PKG_CONFIG_PATH=${DESTDIR}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}"
${_conf_cmd}
)
endif()
if (MSVC) if (MSVC)
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG") set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-09-18-16-50/ffmpeg-n7.0.3-33-g887d4b4919-winarm64-orca-shared-7.0.zip") set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-winarm64-orca-shared-7.0.zip")
set(PREBUILD_HASH_arm64 "da480cbb39680056de824c57ec4dc3bd577b479ebbc310ff1f9dc55cf014b4c1") set(PREBUILD_HASH_arm64 "12f4140279f2f8469885e1b5b2e8be9d788882914c21523cacd56989f3548054")
set(PREBUILD_URL_x64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-09-18-16-50/ffmpeg-n7.0.3-33-g887d4b4919-win64-orca-shared-7.0.zip") set(PREBUILD_URL_x64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-win64-orca-shared-7.0.zip")
set(PREBUILD_HASH_x64 "85da19daf198f5548259d8aabb349db84997a3f6e6886d8d7764114add9c6dae") set(PREBUILD_HASH_x64 "e65916020ddb9ef84b2666dfbcbfc9b1d67f69d15b4a66db53754637bf2d498c")
ExternalProject_Add(dep_FFMPEG ExternalProject_Add(dep_FFMPEG
${_ffmpeg_depends}
URL ${PREBUILD_URL_${DEPS_ARCH}} URL ${PREBUILD_URL_${DEPS_ARCH}}
URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}} URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}}
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
@@ -33,8 +21,6 @@ if (MSVC)
) )
else () else ()
set(_openssl_cmd --enable-openssl)
if (APPLE) if (APPLE)
set(_minos_cmd set(_minos_cmd
"--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}" "--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
@@ -66,11 +52,10 @@ else ()
endif() endif()
ExternalProject_Add(dep_FFMPEG ExternalProject_Add(dep_FFMPEG
${_ffmpeg_depends}
URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
CONFIGURE_COMMAND ${_ffmpeg_configure_command} CONFIGURE_COMMAND ${_conf_cmd}
${_cross_cmd} ${_cross_cmd}
${_pic_cmd} ${_pic_cmd}
${_arch_cmd} ${_arch_cmd}
@@ -78,21 +63,20 @@ else ()
"--prefix=${DESTDIR}" "--prefix=${DESTDIR}"
${_link_cmd} ${_link_cmd}
${_minos_cmd} ${_minos_cmd}
${_openssl_cmd}
--disable-doc --disable-doc
--enable-small --enable-small
--disable-outdevs --disable-outdevs
--disable-filters --disable-filters
--enable-filter=*null*,afade,*fifo,*format,*resample,aeval,allrgb,allyuv,atempo,pan,*bars,color,*key,crop,draw*,eq*,framerate,*_qsv,*_vaapi,*v4l2*,hw*,scale,volume,test* --enable-filter=*null*,afade,*fifo,*format,*resample,aeval,allrgb,allyuv,atempo,pan,*bars,color,*key,crop,draw*,eq*,framerate,*_qsv,*_vaapi,*v4l2*,hw*,scale,volume,test*
--disable-protocols --disable-protocols
--enable-protocol=file,fd,pipe,http,https,rtp,tcp,udp --enable-protocol=file,fd,pipe,rtp,udp
--disable-muxers --disable-muxers
--enable-muxer=rtp --enable-muxer=rtp
--disable-encoders --disable-encoders
--disable-decoders --disable-decoders
--enable-decoder=*aac*,h264*,mp3*,mjpeg,rv* --enable-decoder=*aac*,h264*,mp3*,mjpeg,rv*
--disable-demuxers --disable-demuxers
--enable-demuxer=h264,mp3,mov,mpjpeg,rtsp,sdp --enable-demuxer=h264,mp3,mov
--disable-zlib --disable-zlib
--disable-avdevice --disable-avdevice
BUILD_IN_SOURCE ON BUILD_IN_SOURCE ON
+185 -102
View File
@@ -2,136 +2,219 @@
## Why it exists ## Why it exists
The main window is a notebook of tabs, and only one of them is on screen when the first The main window is a notebook of tabs. When the first frame appears, one tab is on
frame appears. Others are opened later in the session, some never, and some only exist screen and the others are not; some of them are opened later in the session, some
for certain printers. Building every tab before the first frame makes each startup pay for never, and some only exist for certain printers. Building a tab before the first frame
tabs the user may never open. adds its cost to every startup, whether or not the tab is used.
This subsystem builds a tab the first time it is shown, and builds the rest in small units This subsystem builds a tab's panel the first time the tab is shown. It also builds the
while the user is idle after startup. Startup pays only for what the first frame shows, remaining tabs while the user is idle after startup, in units of tens of milliseconds,
the other tabs are usually ready before anyone opens them, and a click that lands in the so a click that lands in the middle of one waits for that unit and no longer. Startup
middle of the idle build waits for one unit at most. Work that is not a tab, such as a pays only for what the first frame shows, and the other tabs are usually built before
dialog or the 3D view's GL resources, uses the same machinery. anyone opens them.
## The parts ## The parts
The parts are independent. A holder can hold anything a factory makes, a placeholder page `src/slic3r/GUI/Lazy.hpp`, `LazyPage.hpp`, `StagedBuild.hpp` and `IdleScheduler.hpp/.cpp`
is a holder with a widget, a staged object can live outside a holder, and the scheduler (with its wx-free `PrebuildQueue.hpp`) are independent. A holder can hold anything a
knows none of them; it runs tasks, which the main window makes from the holders. factory makes, a page is a holder with a placeholder widget, a staged object can live
outside a holder, and the scheduler knows none of them; it runs tasks, which `MainFrame`
makes from the holders.
### The holder: `Lazy<T>` ### Lazy<T>: the holder
A holder keeps one object and the factory that makes it. The rest of the app reads the Holds an object that a factory makes on first use, under a name for the log and a place
object if it exists, makes sure it exists now when about to show or navigate to it, or runs in the idle queue, both given by the owner. The header has no wx dependency; the busy
something once it exists. A type with one instance in the app gets these as statics cursor for an on-demand build lives in `Lazy.cpp` and is skipped when there is no app,
through `LazyInstance<T>`, so callers need no reference to the main window, and all of them so the holder is unit-tested.
are harmless while no holder exists.
The holder guarantees that callers see the object only once it is completely built. A - `get()` is null until the object is completely built; `built()` says the same.
build cannot re-enter itself, so a nested request finds nothing yet, and a factory that - `ensure()` builds whatever is left now, under a busy cursor, and returns the object, or
returns null or a unit that throws leaves the holder and the scheduler able to carry on. null in the two cases below. A click on an unbuilt tab or a first open of a dialog goes
The holder does not own the object; its wx parent does, as for any window. The holder has through this, and it logs the units and time it took.
no wx dependency and is unit-tested. - `build_step()` runs one unit of construction and returns true while more remain. The
first unit is the factory call, and each later unit is one `StagedBuild` step if the
type has them.
- `when_built(fn)` runs `fn(object)` now if it exists, otherwise once it is built.
- `pending()` says whether the idle prebuild has work here: not built, and the factory
has not returned null. A null factory result is logged and the holder stays unbuilt.
- A unit that pumps the event loop cannot re-enter the holder; a nested `build_step()`
does nothing and a nested `ensure()` returns null.
- After a unit throws, the holder and the scheduler still run the next one.
### The placeholder page: `LazyPage<Panel>` The holder does not own the object; its wx parent does, as for any window. A type with
one instance in the app derives from `LazyInstance<T>`, which points at that instance's
holder (the holder registers itself, and a recreated `MainFrame`'s holder replaces the
old frame's) and gives the type the static entry points the rest of the app uses,
`T::if_built()`, `T::ensure()` and `T::when_built(fn)`. They return null, or do
nothing, while no holder exists, so a caller needs no `mainframe` check.
The notebook needs a page object for a tab to exist and for tabs to be inserted and `built()` is an atomic flag, since a job worker reads it through the statics
removed by pointer, and the placeholder is that object. It builds the real panel inside (`MainFrame::get_calibration_curr_tab()`); it is set after the object is complete.
itself the first time it is shown and forwards showing and hiding afterwards, so a panel's
own show handling stays its activation hook. Nothing builds while the main window is
hidden; the window's first show builds the start page. A page that is out of the book is
not prebuilt. A panel built while its page is hidden stays hidden, and gets the theming
the window applied before the panel existed.
### Staged construction: `StagedBuild` `LazyBase` is the holder's type-free interface (`name()`, `built()`, `pending()`,
`build_step()`, `prebuild_order()`) and is what the scheduler side sees.
A constructor too big to be one unit builds a skeleton and queues the rest as steps, which ### LazyPage<Panel>: the placeholder
run one per unit. A child panel's steps can be forwarded to its parent, and the parent is
complete only once the child is. Nothing may use what a step builds before the last step
has run, so staged panels follow these constraints:
- members created in steps start out null, so a partly built panel can be destroyed; A `wxPanel` placed in the parent in place of the real panel, and a `Lazy<Panel>` whose
- timers, event handlers and destructors that touch step content check that the panel is factory makes the panel inside it (by default `new Panel(parent)`). The notebook needs a
complete first; page object for the tab to exist and for `show_device()` to insert and remove tabs by
- nothing takes focus while off screen, since a unit may run while the user is typing pointer, and the placeholder is that object. `MainFrame` creates every page once, named
after its `TAB_ID_*`, and keeps it for the frame's life; `show_device()` only moves
pages in and out of the book.
- `Show()` is forwarded to the panel, so a panel's own `Show()` override stays its
activation hook (refresh timers, machine sync) and `SelectPageByName()` works
unchanged. A show builds the panel unless the frame itself is still hidden, because
the book selects its first page as it is inserted; `MainFrame::Show()` shows the
current page again when the frame becomes visible, which builds it.
- `in_book()` says whether the parent notebook currently lists the page, and
`pending()` is that and not built, so a tab `show_device()` has taken out of the book
is not prebuilt.
- A panel built while its page is hidden stays hidden, and a completed panel gets the
dark-mode pass the frame ran before it existed.
The Compare presets dialog is a holder without a page. `MainFrame` keeps a
`Lazy<DiffPresetDialog>` whose factory constructs the dialog and binds its events, the
dialog derives from `LazyInstance`, and its callers use
`DiffPresetDialog::ensure()->show()` and `DiffPresetDialog::if_built()` like a tab's
callers do. Saving a preset refreshes the dialog only while it is shown, since `show()`
reloads the presets.
### StagedBuild: construction in units
A mixin for a panel whose constructor is too big to be one unit. The constructor builds
the skeleton (sizers, and the parts other code may touch) and queues the rest with
`add_build_step()`. `build_step()` runs one step, and `add_build_steps_of(child)`
forwards a child's steps so a nested panel is spread the same way; the parent is built
only once the child is, including steps the child queues later. Steps run in order, on
the main thread. A `Lazy<T>` recognises a staged type at compile time and runs its steps
one per unit.
Nothing may touch what a step builds before the last step has run. In practice:
- nothing paints the panel before it is complete, since a panel built at idle is hidden
with its page and one built on demand finishes inside `ensure()` before the event loop
runs again;
- members created in steps are initialised to null in the header, so a partially built
panel can be destroyed;
- timers and event handlers that use step content check `built()` first
(`MonitorPanel::update_all()`, `CalibrationPanel::update_all()`), and a child's steps
are queued before anything in the constructor can fire such a handler;
- a destructor that disconnects from step content checks `built()` first;
- a constructor or step does not take focus while the panel is off screen
(`IsShownOnScreen()` before `SetFocus()`), since it may run while the user is typing
elsewhere; elsewhere;
- a widget added by a step keeps its place in the sizer through an empty slot the skeleton - where a step's widgets must keep their place in a sizer that later steps also fill, the
creates. constructor adds an empty slot sizer in that position and the step fills the slot
(`StatusBasePanel`).
### The scheduler: `IdleScheduler` and `PrebuildQueue` ### IdleScheduler: when to build
The queue holds tasks in order, and a slice runs units of the first pending task until A task is any `LazyBase`: a name for the log, `pending()`, `build_step()` and
the task finishes, the time budget is spent, or input arrives. It has no wx dependency and `prebuild_order()`. `PrebuildQueue` holds the tasks by order (equal order in the order
is unit-tested with a fake clock. A task whose work goes away, such as a tab removed from added) and runs a slice, the units of the first pending task until it completes, the
the book, is skipped, and becomes pending again if the work comes back. budget is spent on the clock it is given, or the interrupt predicate says input arrived.
It has no wx dependency and is unit-tested with a fake clock. A task whose work is gone
is passed over and stays in the queue, so a tab that `show_device()` removes and later
re-inserts is pending again.
A slice runs only once the user has been idle for a short quiet time, and each slice is its `IdleScheduler` drives the queue with the real clock, the app's input timestamp and the
own timer message, so paint, timers and input queued in between are handled before the Windows queue check, and logs each unit and slice. Each slice is a timer message: a
next slice. Posting slices as pending events would not do that, because wx drains every period of 250 ms while waiting for the user to go quiet, and a one-shot of zero after a
pending event before the next native message. On GTK a timer that is always due starves slice that left work, so the event loop dispatches whatever it has queued (paint,
the lower-priority sources that repaint and deliver posted events, so slices are a few timers, input) before the next slice runs. Chaining slices with `CallAfter` would not do
milliseconds apart. On Windows a slice also waits while the native queue holds input, this: wx drains pending events fully before the next native message, on every platform.
not counting mouse moves, which Windows synthesizes whenever a window appears under the On GTK the one-shot is 5 ms, because a due GLib timeout runs ahead of the redraw and
cursor. A slice never runs inside a `wxYield()`, where it would build pages in the middle of idle sources that paint and deliver posted events.
the code that yielded. A unit cannot be interrupted, so the largest unit bounds how long a A slice runs only once the user has been idle for the quiet time, and the timer stops
click can wait. itself once no task is pending. The tick period, quiet time and slice length are
When nothing is pending the timer stops and the subsystem costs nothing. constants in `IdleScheduler.cpp`. A unit cannot be interrupted once started, so the
largest unit bounds click latency on Windows; on the other platforms a click also waits
for the rest of the slice. A unit that pumps the event loop lets the timer fire inside
its own slice, and that tick does nothing.
The main window owns the scheduler because it owns what the tasks build, and clearing the The tasks are made by their owners. `MainFrame::prebuild_pages_when_idle()` registers
queue with the window keeps a task from outliving its object. Each owner provides its own every `LazyPage` the frame created, in or out of the book (`pending()` is false for a
tasks, such as a tab, a dialog, the Prepare tab's settings page one option group at a page out of the book), the Compare presets holder, and the Prepare sidebar's settings
time, the Prepare page's layout at the size the book gives its pages, or the 3D view's GL page from `ParamsPanel::settings_page_prebuild()`, whose first unit selects the default
resources. tab if none is selected yet and whose later units build one option group each.
`show_device()` only restarts the timer. `MainFrame` owns the scheduler because it owns
everything the tasks build, and clearing the queue with the frame is what keeps a task
from outliving its object.
### The 3D view's GL resources Idle time comes from `GUI_App::FilterEvent`, which timestamps mouse and keyboard events
(`wxEVT_CATEGORY_USER_INPUT` minus command events, which all claim that category), and
`GUI_App::input_idle_ms()` reports it. On Windows a slice additionally refuses to start
when the message queue holds keyboard, button, touch or pen input. Mouse moves are
excluded because Windows synthesises one whenever a window appears under the cursor,
which every unit does. Other platforms use the timestamp alone.
OpenGL is loaded on the Prepare tab's canvas. When the start page is not Prepare, loading Once every registered page is built the timer is stopped and the subsystem costs
it is an idle task that makes the context current on the hidden canvas, so the start page nothing.
paints first and Prepare never appears. Loading it on a shown canvas under `Freeze()` holds
back the start page's paint, and on GTK `Freeze()` cannot hide the canvas, which is a
native child window or a Wayland subsurface drawn outside GTK. A hidden Windows child
window keeps its device context, macOS attaches the context to a hidden view, and GTK
creates the canvas's surface when the widget is realized, so on GTK the task realizes the
canvas first. If the context cannot be made current, the canvas's first render loads the
resources.
## Rules ## Rules
**Before the first frame.** Only the start page and the Prepare tab's plater are built **What builds before the first frame.** The Prepare tab's plater, because `post_init()`
before the first frame. Everything else goes through a holder. needs its GL canvas on screen to initialise OpenGL in every startup state, and the start
page the user configured. Home is built by the first `MainFrame::Show()`, Prepare's
settings page by selecting the tab. `post_init()` passes through the Prepare tab for GL
init under `Freeze()` with `MainFrame::select_prepare_for_gl_init()`, which changes the
selection without the page-changed event, so nothing else is built for that pass.
**Reaching a lazy object.** Callers use the type's statics. Reading it if built is for **Reaching a lazy object.** A caller uses the type's own statics. `T::if_built()` may
things the object can live without, such as a rescale, a color change or a status refresh. return null and is for telling the object something it can live without (a rescale, a
Making sure it exists is for navigating to it or showing it. Running something once it is colour change, a status update). `T::ensure()` builds the object and is for navigating
built is for state it would not fetch for itself on construction. A panel that pulls its to it or for a caller that is about to show it. A caller that tells the object something
state when constructed only ever needs to be read if built. it would not fetch for itself on construction uses `T::when_built()`, which keeps the
message until the object exists. A panel that pulls its state when constructed (the Home
page requests the recent list on load, the Device tab reads the device manager on show)
is reached with `if_built()`; one that cannot pull gets `when_built()`.
**Unit size.** A unit should fit in one slice on a fast machine. A constructor over that is **Unit size.** A unit cannot be interrupted, so it should stay within the slice length on
staged, and a single widget over it is accepted unless the widget itself can be split. a fast machine. A constructor above that is staged. A single widget above it is the
floor unless the widget itself is split.
**Order.** Tasks run cheapest and most likely to be opened first. Each holder's order is **Order.** Cheapest and most likely to be opened first, given where `MainFrame` creates
given where it is created, with gaps so a new task fits between its neighbors. A negative each holder. The settings page is 0 (the Prepare tab's own content), Home 10, Device 20
order is never prebuilt, for something few sessions open that costs more to build unasked (a Bambu user's usual second stop), Calibration 30, Multi-device 40, the web Device
than it saves. view 50, Project 60 (a second WebView2 instance) and the Compare presets dialog 100;
steps of ten so a new tab takes a value between its neighbours without renumbering
them. `MainFrame::prebuild_pages_when_idle()` registers the tasks once, from
`post_init()`.
**Never prebuilt.** A holder with a negative order, for a tab that few sessions open
and that costs more to build unasked than it saves (the Design tab), and plugin-provided
tabs, which are Python-side and not lazy pages.
## Adopting it ## Adopting it
A lazy tab needs a panel type deriving from `LazyInstance`, a placeholder page the main A lazy tab needs:
window creates once with its order and registers for the idle build, and every use of the
panel outside the main window going through the statics. Its constructor has to cope with
the main window already existing and the user being busy elsewhere, so it takes no focus
while off screen, and it does all of its own setup, since the main window does nothing to a
panel after creating it.
To stage a heavy constructor, keep the skeleton in the constructor, move the rest into 1. The panel derived from `LazyInstance<Panel>`, since a tab's panel has one instance.
steps in its original order, and follow the staged-construction constraints. Measure the 2. A `LazyPage<Panel>*` member in `MainFrame`, created once in `init_tabpanel()` with
units; a step that is still one big widget is split inside the widget or accepted. its `TAB_ID_*` as the name, its place by the order rule (and a factory if
`new Panel(parent)` is not enough), added to `m_lazy_pages`, and used wherever the
tab is added to or looked up in the notebook.
3. Every use of the panel outside `MainFrame` going through one of the panel's statics,
chosen by the rule above. When converting an existing member, `grep` for it; the
compiler finds the rest.
4. A constructor that copes with the frame already existing and the user being busy
elsewhere, since `wxGetApp().mainframe` is set, the frame may be shown, and the user
may be typing when a lazy panel is built: no `SetFocus()` while off screen, and
whatever the constructor did through a `MainFrame` accessor before (a mode update, a
deferred URL) done in the constructor itself.
## Verifying To stage a heavy constructor, inherit `StagedBuild`, keep the skeleton in the constructor,
move the rest into `add_build_step()` lambdas in the original order, and follow the
staged-panel rules above. Measure the units. A step that is still one big widget has to
be split inside that widget or accepted as the floor.
The log lists the queue when it is registered, reports each completed task at info level Verification is by log. `MainFrame::prebuild_pages_when_idle` lists the queue it
and each slice and unit at debug level, and reports every on-demand build with its units registered, `IdleScheduler::tick` reports each completed task by name at info level and
and time. A task's completion line counts only the slice it finished in. A run from the each slice and unit at debug level, and `Lazy::ensure` reports an object a user built
configured start page should show every registered task complete in order, with no unit on demand with the units and time it took. A run from the configured start
longer than intended. A click on a tab during the idle build should show an on-demand page shows every registered page complete, in order, with no unit longer than intended.
build for what was left, with the slices resuming once the user is idle again. A click on a tab mid-prebuild shows the finished panel with an `ensure` line for what was
left, and the slices resume for the remaining tasks once the user is idle again.
-123
View File
@@ -1,123 +0,0 @@
# Multiline infill — High Level Design
## Purpose and scope
`fill_multiline` prints every sparse infill wall as N adjacent lines instead of
one, so a wall is `d1 = N * spacing` thick. Only internal sparse infill uses it.
Each pattern first builds its single-line centerlines at N times the usual line
spacing (so the density holds), and `multiline_fill()` then replaces each
centerline by the lines of that wall: the centerline itself when N is odd, and
closed outlines around it at every `spacing` out to `d1 / 2`. The outlines are
clipped to the fill region contracted by half a line width, then connected like
any other infill.
Outlines of centerlines that cross each other overlap at every crossing, which
over-extrudes the wall intersections. The line-crossing patterns Grid,
Triangles, Tri-hexagon and Cubic therefore build centerlines that never cross
(`FillRectilinear::fill_surface_trapezoidal()`), and so do Adaptive Cubic and
Support Cubic (`FillAdaptive`); the other patterns outline their usual
centerlines.
## Non-crossing centerlines
The crossing lines are resolved into x-monotone paths, the levels of the line
arrangement: walking along x, the k-th path is always the k-th line from the
bottom. At every crossing, the two paths bounce off each other instead of
passing through. Adjacent paths meet only at crossings, so their outlines touch
there and nowhere overlap.
Where two paths meet, each is cut short by a line perpendicular to the bisector
of its bend, `d1 / 2` from the crossing. The two cut segments are parallel and
`d1` apart, so the outermost lines of the two walls sit exactly `spacing` apart,
like the lines inside a wall. Where three lines meet at one point, the middle
path runs straight through and the outer two are cut `d1` from it.
Each pattern builds its rows along x in a rotated frame. Grid lines run at ±45°
there, and its rows are trapezoid waves that transpose on alternate layers. The three families of Triangles, Tri-hexagon and
Cubic run at 0°, 60° and 120°. Those rows rotate by 120° every layer about a
3-fold center of the arrangement, so each family takes every role in turn.
The pattern is phased on fixed positions, so it lines up across layers and
across the regions of one layer. Rounding the corners with
`sparse_infill_smooth_factor` happens before `multiline_fill()`.
## Cubic
Single-line Cubic draws the three families at the same spacing `h` and shifts
them with z: by `+dx`, `-dx` and `+dx`, `dx = z / sqrt(2)`. The multiline paths
follow the same lines. In the frame where one family is horizontal, the other two
cross in rows `h` apart, alternating by half a period, at height
`tau = -3 * dx (mod h)` above the horizontal line below them. The crossings split
every band between horizontal lines into up-pointing triangles of height `tau`,
down-pointing triangles of height `h - tau`, and hexagons. At `tau = 0` (and `h`)
all three families meet at common points, as in Triangles. At `tau = h / 2` the
triangles are equal, as in Tri-hexagon. The origin of that frame is always a
3-fold center, whatever z is, so the per-layer rotation keeps the lines in place.
Each band holds two paths that touch at its crossings: the upper one takes the
V below the crossing and runs along the top horizontal line, and the lower one
takes the inverted V above it and runs along the bottom line. Both are the same function
of `tau`, the lower one mirrored with `h - tau`. `cubic_upper_level()` builds one
period of the upper path as the lower envelope of five lines, clipped from below:
- the two slanted lines through the crossings,
- the horizontal line, lowered when the triangle above it is less than `1.5 * d1` high,
- the two chamfers where the path turns onto and off the horizontal line, `d1 / 2`
from those crossings,
- the flat cut into the V at the crossing.
The cut height `clamp(tau - d1 / 2, 0, h - d1) + d1` is what makes the pattern
continuous in z. While both triangles are at least `1.5 * d1` high, every
crossing is a pair of bends `d1 / 2` from it, as in Tri-hexagon. When a triangle
is thinner, its three paths stack like a triple crossing. The path through it
flattens toward its base line and lies on it once the triangle is under `d1 / 2`
high, and the paths beside it are pushed `d1` away. The layout thus reaches the
Triangles one where the families meet. Adjacent paths stay at least `d1` apart
at every `tau` and at every density up to 100%.
## Adaptive Cubic
Adaptive Cubic and Support Cubic take their lines from an octree of cubes
standing on a corner. On each layer every cube cuts its three mid-planes into
segments of the same three 60° families as Cubic, but the pattern is not
periodic. Smaller cubes near the surface add finer lines, and a finer line ends
where it meets the wall of its coarser cube, so the lines form crossings and
T-junctions. `FillAdaptive::multiline_paths()` builds the paths from these
segments directly, for each fill region and within `4 * d1` of it.
At a crossing the two paths bounce as in Cubic. At a T-junction the through line
runs straight on and the path of the ending line stops there. Every path still
runs left to right in the frame where one family is horizontal, and that family
rotates with the layer.
Every line of every cube size lies on one fine lattice, so crossings closer than
a few `d1` are the corners of one small triangle of that lattice, as in Cubic.
The cuts follow the Cubic rules without a closed formula:
- The two bends of a crossing are cut `d1` apart, `d1 / 2` each, perpendicular
to their bisector, so their walls touch. A cut goes no further than the path
end, and the other bend takes the rest of `d1`.
- At the tip of a small triangle, between the two slanted families, a cut also
goes no further than the neighbouring bend turning the other way, and the
path beyond that bend is kept a wall away from it. The bends onto the
horizontal family are not limited this way: pushing their paths apart would
open gaps between walls that should touch.
- A cut moves the path only where the cut line lies beyond it, near its bend.
The sharp bends between the two slanted families are cut after the bends onto
the horizontal family, so the tip of a small triangle wins, as in Cubic.
- A path stopping at a T-junction is trimmed until it is `d1` less half a line
spacing from every other path, so that its end overlaps the wall it stops on
by half a line and bonds to it. The paths are trimmed one at a time against
the others as already trimmed, so two ends facing each other meet instead of
both backing off. A path stopping on the line of another is trimmed before
that one, so it gives way and the other still reaches the line it stops on. A
second round trims every path again from its full length, so an end grows
back where the ends it gave way to were trimmed later, and a last round only
shortens them, keeping them that far apart. Paths shorter than `d1` are left
out.
- A line that ends on another less than `2 * d1` past a crossing stops at that
crossing instead, the shorter one where both do. The path along such a stub
would be trimmed away, leaving a hole between the walls that were cut to
touch it.
Short paths enclosed by coarser lines still print as closed outlines, but most
paths run on across several cells.
-197
View File
@@ -1,197 +0,0 @@
# Prime tower sparse layers — High Level Design
## Purpose and scope
A prime tower exists to absorb filament changes, but it is planned on every
object layer below the topmost change, not only on the layers that purge. The
layers in between carry no filament change and print nothing but a block of the
tower's own footprint to keep its top level. They are called sparse layers, and
on a print with few changes they are most of the tower: they cost time, filament
and a travel to the tower on every layer.
Two settings trade that cost against something else. `wipe_tower_no_sparse_layers`
drops them, which sinks the tower below the model. `wipe_tower_sparse_layers_combination`
merges runs of them into fewer, thicker layers, which keeps the tower level with
the model. Both are off by default, and with both off the tower prints one layer
per object layer as it always has.
The decisions belong to tower planning and G-code emission. They do not change
sliced object geometry, but they do change the emitted G-code, the filament and
time estimates, and — for the compacted case — whether a plate is printable at
all. Changing either setting invalidates the tower step.
## What a sparse layer is
`ToolOrdering::fill_wipe_tower_partitions` counts the filament changes per layer
and propagates that count downwards, so every layer below the topmost change is
marked as carrying a tower. It then fills any gap between two tower layers, so
the tower is continuous from the bed to its last purge. `wipe_tower_layer_height`
is the distance from the previous tower layer, which is the object's layer height
whenever the tower prints on every layer.
`Print::_make_wipe_tower` plans one tower layer per such object layer. A layer
whose only call keeps the current filament leaves no toolchange in the plan, and
the layer it generates is a single result whose initial and new tool are equal.
That is what `wipe_tower_layer_is_sparse` recognises, and it is the unit both
settings work on.
The plan stays one entry per tower layer in every case. The G-code emitter walks
`WipeTowerData::tool_changes` by layer index, advancing once per object layer
that carries a tower, so a planner that removed entries would silently shift
every later layer onto the wrong tower geometry. Layers that print nothing are
therefore still planned and still generated; they are marked, and the emitter
drops them.
## Shared rules
Tower planning, G-code emission and the plate validation all have to agree about
which layers print and where. They ask one set of free functions, declared beside
the tower classes, rather than each re-deriving the answer from the raw options:
- `wipe_tower_sparse_layers_skipped` — whether sparse layers are really dropped.
Smooth timelapse and clumping detection park the nozzle on the tower every
layer, so with either of them on no layer is ever dropped and the option reads
as off everywhere.
- `wipe_tower_sparse_layers_combined` — whether runs are really merged. The same
two rule it out, and so does `wipe_tower_no_sparse_layers`: dropping the layers
outright is the stronger answer to the same problem, so the two settings are
exclusive and the GUI greys out the second while the first is on.
- `wipe_tower_layer_is_sparse`, `wipe_tower_layer_is_combined_away` — per-layer
questions the emitter asks about generated results.
- `compute_compacted_wipe_tower_z` — the tower's print z per planned layer when
it is compacted.
- `combine_sparse_wipe_tower_layers` and its `combine_sparse_wipe_tower_plan`
wrapper — the merge rule, applied to either generator's plan.
Both tower generators are driven through these. `WipeTower` (Type 1, the block
tower) and `WipeTower2` (Type 2, the default) keep separate plans with the same
per-layer shape — print z, layer height, toolchanges, and a `combined_away` flag
— so one template covers both.
## Dropping sparse layers
With `wipe_tower_no_sparse_layers`, the tower only grows on layers that carry a
real change. It therefore falls one layer height behind the object for every
sparse layer, and by the top of a tall print it can sit far below the model. The
nozzle has to reach down to it at each purge.
`compute_compacted_wipe_tower_z` derives that z once, from the generated results,
so the emitter and the validator cannot disagree. Emission descends to it, but
only once the nozzle is parked over the tower: descending while still over the
model would drive the nozzle into the print, so a descent that would do that is
deferred until after the travel to the tower. Extrusions emitted without an
explicit z — the nozzle-change wipe in particular — are pulled down to the
compacted z for the same reason.
Reaching down is only safe if nothing tall stands near the tower. `Print.hpp`
carries the clearance rule: a keep-out zone grown from the tower's footprint by
the spiral z-hop envelope, and a per-object limit on how high an object may rise
near it, tiered by the nozzle cone, the head body, the rod and the lid. The same
rule serves the precise check on real extrusions, the pre-slice estimate that
feeds the plater, and the outlines the plater draws while an object is dragged,
so that the ring the user sees touches the object's outline exactly when the
check trips.
## Merging sparse layers
With `wipe_tower_sparse_layers_combination`, no layer is dropped and nothing is
compacted: the tower keeps following the object, and the nozzle never descends.
Instead a run of consecutive sparse layers prints once, on the run's last layer,
at the accumulated height of everything it covers — the same way infill
combination merges sparse infill. The layers below it in the run print nothing.
`combine_sparse_wipe_tower_plan` runs before the tower's depths are planned,
because the heights it rewrites feed the extrusion flow of every later pass. It
raises `height` in place on the layer that prints a run and sets `combined_away`
on the rest; generation then proceeds unchanged, and the flag is copied onto the
results so the emitter can drop them.
Four constraints shape the rule:
- **Whole layers only.** A tower layer is entered at the object's z, so a merged
layer has to end on an object layer boundary. The merged height is therefore a
sum of whole layer heights, never a clamped value.
- **The nozzle's maximum layer height.** A run stops growing as soon as one more
layer would pass `max_layer_height` for the nozzle printing it — three quarters
of the nozzle diameter when that is left at 0, as elsewhere in slicing. The cap
is read through the filament-to-nozzle map, since `max_layer_height` is per
nozzle while the tower indexes filaments. This is what makes the setting inert
at common layer heights: two 0.2 mm layers are 0.4 mm and do not fit under a
0.3 mm maximum, so nothing merges until the layer height is 0.15 mm or below,
or the maximum is raised.
- **A filament change purges at its own z.** A layer with a real change can
neither be merged away nor absorb the run below it, so a run always ends on its
own last sparse layer and the change above it is untouched.
- **The first layer stays on the bed.** It carries the brim and is never merged.
A run holds one filament throughout — that is what makes it sparse — so the cap
is uniform across it, and the tower reserves depth only for the purges above a
layer, so a run has one footprint and the merged layer covers exactly the area
the layers it replaces would have.
## Emission and accounting
`WipeTowerIntegration` drops a layer whose results are marked, for both settings,
through the same `ignore_sparse` path in `tool_change` and
`is_empty_wipe_tower_gcode`. A dropped layer emits no travel to the tower and no
extrusion.
Filament used is accumulated by the generators while they write, so a layer that
will be dropped must not be charged. Type 1 asks `layer_is_printed` at each of
its accumulation points; Type 2 guards the equivalent block in `finish_layer`,
which also stops a merged-away layer from adding height of its own — the layer
that prints the run carries all of it.
A merged layer is the only case where the tower's layer height differs from the
object layer it sits on, and therefore the only case where the height the
exporter already emitted for that layer is wrong for the tower. Both generators
do declare a height, but each hardcodes a tag dialect — the block tower forces
the BBL tag, the other writes the compatible one — while the G-code processor
reads only the tag its printer uses. On a non-BBL printer with a Type 1 tower the
declaration is dropped, and the merged layer is drawn and costed as a thin one.
`WipeTowerIntegration::tower_height_tag` therefore declares it at export time,
where the printer is known, and only when the tower's own G-code does not already
carry the tag that will be read. The object's height returns on the next object
path, because emission forces the processor role to the tower on any layer that
carries one.
## Constraints
A layer that prints nothing prints nothing at all, including any interface work
the tower planner scheduled there. The Type 1 block planner marks a layer as a
contact layer when a filament category stops or starts being used relative to the
layer below, and a sparse layer immediately above a change qualifies. Merging a
run, like dropping its layers, replaces that interface with the run's single
layer. Both settings are off by default for this among other reasons.
Neither setting changes what the tower is for. A plate that needs a tower on
every layer — smooth timelapse, clumping detection — gets one, and the settings
read as off rather than compacting or merging in one place and not another.
## Implementation and verification
- [WipeTower.hpp](../../src/libslic3r/GCode/WipeTower.hpp) declares the shared
rules and the plan-merging template;
[WipeTower.cpp](../../src/libslic3r/GCode/WipeTower.cpp) implements them and
the Type 1 tower, [WipeTower2.cpp](../../src/libslic3r/GCode/WipeTower2.cpp)
the Type 2 tower.
- [ToolOrdering.cpp](../../src/libslic3r/GCode/ToolOrdering.cpp) decides which
layers carry a tower at all, and
[Print.cpp](../../src/libslic3r/Print.cpp) plans it and runs the clearance
check whose rule lives in [Print.hpp](../../src/libslic3r/Print.hpp).
- [GCode.cpp](../../src/libslic3r/GCode.cpp) emits the tower, drops the layers
that print nothing, and declares a merged layer's height;
[PrintConfig.cpp](../../src/libslic3r/PrintConfig.cpp) defines the settings and
[ConfigManipulation.cpp](../../src/slic3r/GUI/ConfigManipulation.cpp) their
mutual exclusion.
- [GLCanvas3D.cpp](../../src/slic3r/GUI/GLCanvas3D.cpp) and
[PartPlate.cpp](../../src/slic3r/GUI/PartPlate.cpp) draw the compacted tower's
keep-out outlines live while the user drags.
- [Rule tests](../../tests/libslic3r/test_wipe_tower.cpp) cover the gating of
both settings, the per-layer predicates, the compacted z, the merge rule's run
flushing, height conservation, the nozzle cap and the first-layer exemption,
and the clearance geometry the plater draws.
- [Slicing tests](../../tests/fff_print/test_wipe_tower.cpp) slice a real print
and check that a run folds, that the tower still covers the object exactly
once, that a run too thin for the cap is left alone, and that a merged layer
declares its height in the tag the printer's processor reads.
-240
View File
@@ -1,240 +0,0 @@
# Printer agents
Printer agents isolate printer-specific communication from the rest of OrcaSlicer. The GUI and
`DeviceManager` operate on a shared set of printer operations and device state; a selected printer
agent implements those operations for a particular printer ecosystem. The agent boundary allows
Bambu, Moonraker-based printers, built-in integrations, and Python-provided integrations to use the
same application workflow without making the GUI understand every printer protocol.
The current boundary is an adapter boundary around the existing application contract. In particular,
some request fields and message payloads still use the Bambu-shaped representation that existing
`MachineObject` and `DeviceManager` code consumes. The printer agent is responsible for translating
that representation into the protocol spoken by its printer. This is an intentional compatibility
constraint of the current design; the interface is not yet a neutral printer protocol.
The v1 dialect migration path is deliberately narrow. `DeviceManager` currently speaks the Bambu JSON
dialect because that is the payload shape already used throughout the command and state workflow. The
v1 `OrcaPrinterAgent` also accepts that Bambu dialect. Its transport path places the small translation
needed for the target printer at `deliver_to_sink`, keeping the compatibility code at the edge rather
than spreading it through `DeviceManager` or the agent interface.
The eventual direction is for `DeviceManager` to produce an Orca JSON dialect. The Bambu agent will then
own the translation from Orca JSON to Bambu's protocol, while `OrcaPrinterAgent` can forward the Orca
payload directly to its sink. The v1 translation at `deliver_to_sink` can then be removed without
changing `DeviceManager`, the command callers, or the rest of the agent workflow.
## Components
The system has four relevant layers:
```text
GUI / DeviceManager / MachineObject
|
NetworkAgent
/ \
IPrinterAgent ICloudServiceAgent
| |
printer protocol authentication and cloud services
```
### `DeviceManager` and `MachineObject`
`DeviceManager` owns the application-facing printer workflow. It maintains `MachineObject` instances,
updates their state, filters devices for the active printer agent, and initiates operations such as
homing, temperature changes, printing, subscriptions, and camera playback.
`MachineObject` remains the shared state model used by the GUI. It does not contain the implementation
of a printer protocol. When a device is discovered or returned by a cloud query, the device is tagged
with the active `printer_agent_id`. Device lists and selected-machine operations use that tag to avoid
sending an operation through an agent that does not own the device.
### `NetworkAgent`
`NetworkAgent` is the façade used by the GUI and `DeviceManager`. It owns:
- the currently selected `IPrinterAgent`;
- the registered cloud-service instances, indexed by provider;
- callbacks shared by the active printer agent and the application;
- the forwarding methods for printer commands and cloud operations.
There is one active printer agent for the currently selected printer preset. Switching the preset
increments the machine-list generation, disconnects the old printer agent, removes its callbacks, and
installs the newly selected agent. The façade then forwards printer operations to that agent.
Cloud operations are selected separately using a provider key. `NetworkAgent` forwards a cloud request
to the matching `ICloudServiceAgent`, and forwards cloud camera operations with a device ID. The
printer agent receives a cloud-agent pointer through `set_cloud_agent()` when it is created, allowing
printer communication to obtain cloud tokens without depending on a concrete cloud implementation.
### `IPrinterAgent`
`IPrinterAgent` is the printer-facing contract. It covers:
- cloud-relay and direct-LAN message delivery;
- LAN connection, discovery, binding, and certificates;
- printer subscriptions and callbacks;
- print operations;
- filament synchronization;
- camera capability and local camera URL reporting;
- printer command methods.
Concrete built-in implementations include the Bambu wrapper, the native Orca/Moonraker path, and
other printer-agent implementations registered by the application. A printer agent may use either
the cloud agent, a direct LAN connection, or both.
### `ICloudServiceAgent`
`ICloudServiceAgent` owns authentication and services provided by a cloud backend. It covers login
state, tokens, user and printer lists, settings synchronization, model services, cloud messages, and
cloud camera operations.
Cloud camera operations are device-scoped:
- `get_camera_url(dev_id, callback)` obtains a stream URL for one device;
- `create_camera_signaling_channel(dev_id)` creates signaling for one device where the provider
supports it.
This is separate from the local camera URL exposed by `IPrinterAgent`, which is currently scoped to
the active printer agent because a normal LAN agent represents one physical printer connection.
## Agent registration and selection
`NetworkAgentFactory` maintains the printer-agent registry. Each registry entry contains an agent ID,
a display name, and a factory function. Built-in agents register during application initialization.
Python printer-agent capabilities register dynamically and contribute an agent ID and factory entry.
The selected printer preset contains the printer-agent choice. If no explicit choice is stored, the
application preserves the existing default behavior: Bambu presets select the Bambu agent and other
presets select the native Orca agent. When a preset is changed, `GUI_App` resolves the effective agent
ID, obtains the corresponding cloud agent, creates the printer agent through the registry, and installs
it in `NetworkAgent`.
The registry rejects conflicting agent IDs. This matters for Python plugins because an agent ID is the
stable identity used by presets and device ownership; two enabled plugin capabilities must not claim
the same ID.
## Message and command flow
There are two low-level message paths:
- `send_message()` publishes a command through the printer's cloud relay;
- `send_message_to_printer()` sends a command directly to the printer over the LAN path.
Both paths accept a JSON string, quality-of-service and flag values, and return the existing network
status code domain. The agent owns the conversion from that JSON contract to its native transport.
The typed `command_*` methods are the application-facing convenience layer. The five generic defaults
currently implemented by `IPrinterAgent` construct the existing JSON dialect and route through the
same message path:
| Method | Default operation |
| --- | --- |
| `command_xyz_abs()` | Send `G90` for absolute positioning |
| `command_auto_leveling()` | Send `G29` for bed leveling |
| `command_go_home()` | Use the supported homing operation or send `G28` |
| `command_set_bed()` | Use the supported bed control or send `M140` |
| `command_set_nozzle()` | Send `M104` for nozzle temperature |
These are compatibility defaults for common printer workflows, not a guarantee that every firmware
implements every command identically. An agent can override a method when its protocol needs another
operation. For example, a Klipper configuration may use `BED_MESH_CALIBRATE` instead of `G29`.
The remaining common command methods default to `ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED` because their
existing behavior is vendor-specific or has no portable implementation:
- AMS RFID refresh;
- AMS calibration;
- AMS tray selection;
- camera start;
- axis control.
The methods remain on the common interface so an agent that supports them can override them explicitly.
`sequence_id` remains part of the command contract because `DeviceManager` creates and tracks it as
the command ID.
## Device ownership and stale responses
Printer-agent ownership is represented by `printer_agent_id` on device records and `MachineObject`
instances. The active agent ID is attached when a device is discovered, returned by a cloud list, or
reused after a preset switch. Local-machine configuration also persists the agent ID so a saved LAN
device is not silently reused by an unrelated agent.
Cloud printer-list responses carry three pieces of request context added by `NetworkAgent`:
```text
provider cloud provider used for the request
agent_id active printer agent when the request was made
generation machine-list generation when the request was made
```
`DeviceManager` accepts the response only when those values still match the current provider, active
agent, and generation. This prevents a slow response from the previous preset or provider from
repopulating the current device list.
The provider mapping is currently selected by `GUI_App`: the Bambu agent maps to the Bambu cloud
provider and other agents map to the Orca cloud provider. The generation check protects that existing
selection from races; it does not make cloud-provider ownership intrinsic to an agent. Cloud-printer
ownership and the broader Orca cloud services are therefore still separate architectural concerns.
## Python printer agents
`PrinterAgentPluginCapability` implements `IPrinterAgent` directly. The live capability object is
registered with `NetworkAgentFactory` and handed out as the printer agent when its agent ID is selected.
The plugin receives the selected `ICloudServiceAgent` through `set_cloud_agent()` just like a built-in
printer agent.
Python plugins must implement the core communication and lifecycle methods required by the interface,
including agent metadata, printer connection, discovery callbacks, and the two message-send methods.
Methods that are meaningful only to a particular printer are optional overrides where the C++ base
class provides a default.
All ten `command_*` methods are available in the Python binding and in the trampoline. Their override
status is intentionally optional:
- the five generic commands use the C++ default when Python does not override them;
- the five vendor-specific commands return `NOT_SUPPORTED` unless Python supplies an implementation;
- a Python implementation can replace either behavior for its own protocol.
The Python camera binding exposes HTTP, HTTPS, RTSP, and HTTP-snapshot modes. WebRTC remains a
built-in C++ camera mode, but is not exposed as a Python mode because the current Python capability
does not provide the corresponding cloud signaling-channel contract.
## Camera playback boundary
The camera stream mode describes how a stream is obtained; it does not by itself define ownership of
the wxWidgets view that renders it. `MediaPlayCtrl` selects and tears down the active backend, while
the wx parent owns the child window or renderer. This is important because a web view, native media
control, and frame-based/WebRTC renderer have different wx window-lifetime requirements.
Cloud URL and signaling requests are routed through `NetworkAgent` to the cloud provider selected for
the device. Local URL requests are routed to the active printer agent. The distinction keeps cloud
account services device-scoped while preserving the current one-LAN-agent/one-printer model.
## Compatibility constraints
The printer-agent boundary intentionally preserves several existing application contracts:
- Bambu-shaped JSON is still the shared command representation;
- existing network status codes are reused, with Orca-specific unsupported/capability errors added
in the Orca-reserved range;
- `MachineObject` remains the shared device-state model;
- preset and local-machine data retain compatibility with the existing agent-selection behavior;
- Python plugins use the existing capability and pybind11 registration system.
The agent abstraction is therefore responsible for containing vendor differences, not for pretending
that all vendor protocols are identical. The planned Orca JSON dialect is the protocol-neutral command
model for the `DeviceManager`/agent boundary. Once it is introduced, Bambu-specific translation remains
inside the Bambu agent and the Orca agent's v1 sink adapter can be removed as a self-contained cleanup.
## Main implementation locations
- [`IPrinterAgent`](../../src/slic3r/Utils/IPrinterAgent.hpp) — printer-agent contract and generic command defaults
- [`ICloudServiceAgent`](../../src/slic3r/Utils/ICloudServiceAgent.hpp) — cloud service and per-device
cloud camera contract
- [`NetworkAgent`](../../src/slic3r/Utils/NetworkAgent.hpp) — façade and dispatch between active agents
- [`NetworkAgentFactory`](../../src/slic3r/Utils/NetworkAgentFactory.hpp) — built-in and Python agent registry
- [`DeviceManager`](../../src/slic3r/GUI/DeviceCore/DevManager.cpp) — device ownership, filtering, and
stale-response checks
- [`PrinterAgentPluginCapability`](../../src/slic3r/plugin/pluginTypes/printerAgent/PrinterAgentPluginCapability.cpp)
— Python bindings
- [`MediaPlayCtrl`](../../src/slic3r/GUI/MediaPlayCtrl.cpp) — camera backend selection and playback lifecycle
+55 -155
View File
@@ -1,6 +1,6 @@
{ {
"name": "Blocks", "name": "Blocks",
"version": "02.04.00.13", "version": "02.04.00.04",
"force_update": "0", "force_update": "0",
"description": "Blocks configurations", "description": "Blocks configurations",
"machine_model_list": [ "machine_model_list": [
@@ -43,8 +43,8 @@
"sub_path": "process/0.16mm Optimal 0.4 nozzle @Blocks_RF50.json" "sub_path": "process/0.16mm Optimal 0.4 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.20mm Standard 0.4 nozzle @Blocks_Pro_S100", "name": "0.20mm Standard 0.4 nozzle @Blocks",
"sub_path": "process/0.20mm Standard 0.4 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.20mm Standard 0.4 nozzle @Blocks.json"
}, },
{ {
"name": "0.20mm Standard 0.4 nozzle @Blocks_RD50_V2", "name": "0.20mm Standard 0.4 nozzle @Blocks_RD50_V2",
@@ -55,8 +55,8 @@
"sub_path": "process/0.20mm Standard 0.4 nozzle @Blocks_RF50.json" "sub_path": "process/0.20mm Standard 0.4 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.24mm Draft 0.4 nozzle @Blocks_Pro_S100", "name": "0.24mm Draft 0.4 nozzle @Blocks",
"sub_path": "process/0.24mm Draft 0.4 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.24mm Draft 0.4 nozzle @Blocks.json"
}, },
{ {
"name": "0.24mm Draft 0.4 nozzle @Blocks_RD50_V2", "name": "0.24mm Draft 0.4 nozzle @Blocks_RD50_V2",
@@ -75,8 +75,8 @@
"sub_path": "process/0.28mm Extra Draft 0.4 nozzle @Blocks_RF50.json" "sub_path": "process/0.28mm Extra Draft 0.4 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.30mm Extra Draft 0.4 nozzle @Blocks_Pro_S100", "name": "0.30mm Extra Draft 0.4 nozzle @Blocks",
"sub_path": "process/0.30mm Extra Draft 0.4 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.30mm Extra Draft 0.4 nozzle @Blocks.json"
}, },
{ {
"name": "fdm_process_common 0.6 nozzle", "name": "fdm_process_common 0.6 nozzle",
@@ -111,8 +111,8 @@
"sub_path": "process/0.26mm Standard 0.6 nozzle @Blocks_RF50.json" "sub_path": "process/0.26mm Standard 0.6 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.30mm Standard 0.6 nozzle @Blocks_Pro_S100", "name": "0.30mm Standard 0.6 nozzle @Blocks",
"sub_path": "process/0.30mm Standard 0.6 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.30mm Standard 0.6 nozzle @Blocks.json"
}, },
{ {
"name": "0.32mm Draft 0.6 nozzle @Blocks_RD50_V2", "name": "0.32mm Draft 0.6 nozzle @Blocks_RD50_V2",
@@ -131,12 +131,12 @@
"sub_path": "process/0.38mm Extra Draft 0.6 nozzle @Blocks_RF50.json" "sub_path": "process/0.38mm Extra Draft 0.6 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.40mm Draft 0.6 nozzle @Blocks_Pro_S100", "name": "0.40mm Draft 0.6 nozzle @Blocks",
"sub_path": "process/0.40mm Draft 0.6 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.40mm Draft 0.6 nozzle @Blocks.json"
}, },
{ {
"name": "0.30mm Optimal 0.8 nozzle @Blocks_Pro_S100", "name": "0.30mm Optimal 0.8 nozzle @Blocks",
"sub_path": "process/0.30mm Optimal 0.8 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.30mm Optimal 0.8 nozzle @Blocks.json"
}, },
{ {
"name": "0.30mm Optimal 0.8 nozzle @Blocks_RD50_V2", "name": "0.30mm Optimal 0.8 nozzle @Blocks_RD50_V2",
@@ -155,8 +155,8 @@
"sub_path": "process/0.38mm Standard 0.8 nozzle @Blocks_RF50.json" "sub_path": "process/0.38mm Standard 0.8 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.40mm Standard 0.8 nozzle @Blocks_Pro_S100", "name": "0.40mm Standard 0.8 nozzle @Blocks",
"sub_path": "process/0.40mm Standard 0.8 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.40mm Standard 0.8 nozzle @Blocks.json"
}, },
{ {
"name": "0.46mm Draft 0.8 nozzle @Blocks_RD50_V2", "name": "0.46mm Draft 0.8 nozzle @Blocks_RD50_V2",
@@ -167,8 +167,8 @@
"sub_path": "process/0.46mm Draft 0.8 nozzle @Blocks_RF50.json" "sub_path": "process/0.46mm Draft 0.8 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.50mm Draft 0.8 nozzle @Blocks_Pro_S100", "name": "0.50mm Draft 0.8 nozzle @Blocks",
"sub_path": "process/0.50mm Draft 0.8 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.50mm Draft 0.8 nozzle @Blocks.json"
}, },
{ {
"name": "0.54mm Extra Draft 0.8 nozzle @Blocks_RD50_V2", "name": "0.54mm Extra Draft 0.8 nozzle @Blocks_RD50_V2",
@@ -179,36 +179,36 @@
"sub_path": "process/0.54mm Extra Draft 0.8 nozzle @Blocks_RF50.json" "sub_path": "process/0.54mm Extra Draft 0.8 nozzle @Blocks_RF50.json"
}, },
{ {
"name": "0.30mm Optimal 1.0 nozzle @Blocks_Pro_S100", "name": "0.30mm Optimal 1.0 nozzle @Blocks",
"sub_path": "process/0.30mm Optimal 1.0 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.30mm Optimal 1.0 nozzle @Blocks.json"
}, },
{ {
"name": "0.50mm Standard 1.0 nozzle @Blocks_Pro_S100", "name": "0.50mm Standard 1.0 nozzle @Blocks",
"sub_path": "process/0.50mm Standard 1.0 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.50mm Standard 1.0 nozzle @Blocks.json"
}, },
{ {
"name": "0.60mm Draft 1.0 nozzle @Blocks_Pro_S100", "name": "0.60mm Draft 1.0 nozzle @Blocks",
"sub_path": "process/0.60mm Draft 1.0 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.60mm Draft 1.0 nozzle @Blocks.json"
}, },
{ {
"name": "0.70mm Extra Draft 1.0 nozzle @Blocks_Pro_S100", "name": "0.70mm Extra Draft 1.0 nozzle @Blocks",
"sub_path": "process/0.70mm Extra Draft 1.0 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.70mm Extra Draft 1.0 nozzle @Blocks.json"
}, },
{ {
"name": "0.50mm Optimal 1.2 nozzle @Blocks_Pro_S100", "name": "0.50mm Optimal 1.2 nozzle @Blocks",
"sub_path": "process/0.50mm Optimal 1.2 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.50mm Optimal 1.2 nozzle @Blocks.json"
}, },
{ {
"name": "0.60mm Standard 1.2 nozzle @Blocks_Pro_S100", "name": "0.60mm Standard 1.2 nozzle @Blocks",
"sub_path": "process/0.60mm Standard 1.2 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.60mm Standard 1.2 nozzle @Blocks.json"
}, },
{ {
"name": "0.70mm Draft 1.2 nozzle @Blocks_Pro_S100", "name": "0.70mm Draft 1.2 nozzle @Blocks",
"sub_path": "process/0.70mm Draft 1.2 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.70mm Draft 1.2 nozzle @Blocks.json"
}, },
{ {
"name": "0.80mm Extra Draft 1.2 nozzle @Blocks_Pro_S100", "name": "0.80mm Extra Draft 1.2 nozzle @Blocks",
"sub_path": "process/0.80mm Extra Draft 1.2 nozzle @Blocks_Pro_S100.json" "sub_path": "process/0.80mm Extra Draft 1.2 nozzle @Blocks.json"
} }
], ],
"filament_list": [ "filament_list": [
@@ -249,148 +249,48 @@
"sub_path": "filament/fdm_filament_tpu.json" "sub_path": "filament/fdm_filament_tpu.json"
}, },
{ {
"name": "Blocks ABS @base", "name": "Generic ABS @Blocks",
"sub_path": "filament/Blocks ABS @base.json" "sub_path": "filament/Generic ABS @Blocks.json"
}, },
{ {
"name": "Blocks ASA @base", "name": "Generic ASA @Blocks",
"sub_path": "filament/Blocks ASA @base.json" "sub_path": "filament/Generic ASA @Blocks.json"
}, },
{ {
"name": "Blocks ASA-CF @base", "name": "Generic ASA-CF @Blocks",
"sub_path": "filament/Blocks ASA-CF @base.json" "sub_path": "filament/Generic ASA-CF @Blocks.json"
}, },
{ {
"name": "Blocks PA @base", "name": "Generic PA @Blocks",
"sub_path": "filament/Blocks PA @base.json" "sub_path": "filament/Generic PA @Blocks.json"
}, },
{ {
"name": "Blocks PA-CF @base", "name": "Generic PA-CF @Blocks",
"sub_path": "filament/Blocks PA-CF @base.json" "sub_path": "filament/Generic PA-CF @Blocks.json"
}, },
{ {
"name": "Blocks PC @base", "name": "Generic PC @Blocks",
"sub_path": "filament/Blocks PC @base.json" "sub_path": "filament/Generic PC @Blocks.json"
}, },
{ {
"name": "Blocks PETG @base", "name": "Generic PETG @Blocks",
"sub_path": "filament/Blocks PETG @base.json" "sub_path": "filament/Generic PETG @Blocks.json"
}, },
{ {
"name": "Blocks PLA @base", "name": "Generic PLA @Blocks",
"sub_path": "filament/Blocks PLA @base.json" "sub_path": "filament/Generic PLA @Blocks.json"
}, },
{ {
"name": "Blocks PLA-CF @base", "name": "Generic PLA-CF @Blocks",
"sub_path": "filament/Blocks PLA-CF @base.json" "sub_path": "filament/Generic PLA-CF @Blocks.json"
}, },
{ {
"name": "Blocks PVA @base", "name": "Generic PVA @Blocks",
"sub_path": "filament/Blocks PVA @base.json" "sub_path": "filament/Generic PVA @Blocks.json"
}, },
{ {
"name": "Blocks TPU @base", "name": "Generic TPU @Blocks",
"sub_path": "filament/Blocks TPU @base.json" "sub_path": "filament/Generic TPU @Blocks.json"
},
{
"name": "Blocks ABS @Blocks_RD50_V2",
"sub_path": "filament/Blocks ABS @Blocks_RD50_V2.json"
},
{
"name": "Blocks ABS @Blocks_RF50",
"sub_path": "filament/Blocks ABS @Blocks_RF50.json"
},
{
"name": "Blocks ASA @Blocks_RD50_V2",
"sub_path": "filament/Blocks ASA @Blocks_RD50_V2.json"
},
{
"name": "Blocks ASA @Blocks_RF50",
"sub_path": "filament/Blocks ASA @Blocks_RF50.json"
},
{
"name": "Blocks ASA-CF @Blocks_RD50_V2",
"sub_path": "filament/Blocks ASA-CF @Blocks_RD50_V2.json"
},
{
"name": "Blocks ASA-CF @Blocks_RF50",
"sub_path": "filament/Blocks ASA-CF @Blocks_RF50.json"
},
{
"name": "Blocks PA @Blocks_RD50_V2",
"sub_path": "filament/Blocks PA @Blocks_RD50_V2.json"
},
{
"name": "Blocks PA @Blocks_RF50",
"sub_path": "filament/Blocks PA @Blocks_RF50.json"
},
{
"name": "Blocks PA-CF @Blocks_RD50_V2",
"sub_path": "filament/Blocks PA-CF @Blocks_RD50_V2.json"
},
{
"name": "Blocks PA-CF @Blocks_RF50",
"sub_path": "filament/Blocks PA-CF @Blocks_RF50.json"
},
{
"name": "Blocks PC @Blocks_RD50_V2",
"sub_path": "filament/Blocks PC @Blocks_RD50_V2.json"
},
{
"name": "Blocks PC @Blocks_RF50",
"sub_path": "filament/Blocks PC @Blocks_RF50.json"
},
{
"name": "Blocks PETG @Blocks_Pro_S100",
"sub_path": "filament/Blocks PETG @Blocks_Pro_S100.json"
},
{
"name": "Blocks PETG @Blocks_RD50_V2",
"sub_path": "filament/Blocks PETG @Blocks_RD50_V2.json"
},
{
"name": "Blocks PETG @Blocks_RF50",
"sub_path": "filament/Blocks PETG @Blocks_RF50.json"
},
{
"name": "Blocks PLA @Blocks_Pro_S100",
"sub_path": "filament/Blocks PLA @Blocks_Pro_S100.json"
},
{
"name": "Blocks PLA @Blocks_RD50_V2",
"sub_path": "filament/Blocks PLA @Blocks_RD50_V2.json"
},
{
"name": "Blocks PLA @Blocks_RF50",
"sub_path": "filament/Blocks PLA @Blocks_RF50.json"
},
{
"name": "Blocks PLA-CF @Blocks_RD50_V2",
"sub_path": "filament/Blocks PLA-CF @Blocks_RD50_V2.json"
},
{
"name": "Blocks PLA-CF @Blocks_RF50",
"sub_path": "filament/Blocks PLA-CF @Blocks_RF50.json"
},
{
"name": "Blocks PVA @Blocks_RD50_V2",
"sub_path": "filament/Blocks PVA @Blocks_RD50_V2.json"
},
{
"name": "Blocks PVA @Blocks_RF50",
"sub_path": "filament/Blocks PVA @Blocks_RF50.json"
},
{
"name": "Blocks TPU @Blocks_Pro_S100",
"sub_path": "filament/Blocks TPU @Blocks_Pro_S100.json"
},
{
"name": "Blocks TPU @Blocks_RD50_V2",
"sub_path": "filament/Blocks TPU @Blocks_RD50_V2.json"
},
{
"name": "Blocks TPU @Blocks_RF50",
"sub_path": "filament/Blocks TPU @Blocks_RF50.json"
} }
], ],
"machine_list": [ "machine_list": [
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks ABS @Blocks_RD50_V2",
"inherits": "Blocks ABS @base",
"from": "system",
"setting_id": "qhQ0qQDGJgsueCAF",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic ABS;Generic ABS @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks ABS @Blocks_RF50",
"inherits": "Blocks ABS @base",
"from": "system",
"setting_id": "bGYMFFdKiROKuSiY",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks ASA @Blocks_RD50_V2",
"inherits": "Blocks ASA @base",
"from": "system",
"setting_id": "HW7xDXThvpVFbMq5",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic ASA;Generic ASA @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks ASA @Blocks_RF50",
"inherits": "Blocks ASA @base",
"from": "system",
"setting_id": "lBW7SCsvawi4icNU",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks ASA-CF @Blocks_RD50_V2",
"inherits": "Blocks ASA-CF @base",
"from": "system",
"setting_id": "x5ksnGLGGy1PgDns",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic ASA-CF;Generic ASA-CF @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks ASA-CF @Blocks_RF50",
"inherits": "Blocks ASA-CF @base",
"from": "system",
"setting_id": "pcbd5qFiMZAvDPg1",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks PA @Blocks_RD50_V2",
"inherits": "Blocks PA @base",
"from": "system",
"setting_id": "gxD81n2jjrReLD29",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic PA;Generic PA @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PA @Blocks_RF50",
"inherits": "Blocks PA @base",
"from": "system",
"setting_id": "PzKxRMDnQUzVWRer",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,17 +0,0 @@
{
"type": "filament",
"name": "Blocks PA @base",
"inherits": "fdm_filament_pa",
"from": "system",
"filament_id": "OFidOgK4",
"instantiation": "false",
"filament_vendor": [
"Blocks"
],
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"10"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks PA-CF @Blocks_RD50_V2",
"inherits": "Blocks PA-CF @base",
"from": "system",
"setting_id": "EtbeKx3rbhUo1TtM",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic PA-CF;Generic PA-CF @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PA-CF @Blocks_RF50",
"inherits": "Blocks PA-CF @base",
"from": "system",
"setting_id": "udI8Q4X7HaPIaPt4",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks PC @Blocks_RD50_V2",
"inherits": "Blocks PC @base",
"from": "system",
"setting_id": "HLc0shWnKwJzSFyW",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic PC;Generic PC @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PC @Blocks_RF50",
"inherits": "Blocks PC @base",
"from": "system",
"setting_id": "9a6bccZopMTeNHYu",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,17 +0,0 @@
{
"type": "filament",
"name": "Blocks PC @base",
"inherits": "fdm_filament_pc",
"from": "system",
"filament_id": "OFlGY0MN",
"instantiation": "false",
"filament_vendor": [
"Blocks"
],
"filament_flow_ratio": [
"0.94"
],
"filament_max_volumetric_speed": [
"10"
]
}
@@ -1,16 +0,0 @@
{
"type": "filament",
"name": "Blocks PETG @Blocks_Pro_S100",
"inherits": "Blocks PETG @base",
"from": "system",
"setting_id": "AhMR49fcFqtrQ6hI",
"instantiation": "true",
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle"
],
"renamed_from": "Blocks Generic PETG;Generic PETG @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PETG @Blocks_RD50_V2",
"inherits": "Blocks PETG @base",
"from": "system",
"setting_id": "3v7ah1zVG8MERPSJ",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
]
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PETG @Blocks_RF50",
"inherits": "Blocks PETG @base",
"from": "system",
"setting_id": "S7weR19wo9meJ6Yz",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,16 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA @Blocks_Pro_S100",
"inherits": "Blocks PLA @base",
"from": "system",
"setting_id": "vWojuLYIfduLGFLL",
"instantiation": "true",
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle"
],
"renamed_from": "Blocks Generic PLA;Generic PLA @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA @Blocks_RD50_V2",
"inherits": "Blocks PLA @base",
"from": "system",
"setting_id": "y7y8NcXNdp17sJUs",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
]
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA @Blocks_RF50",
"inherits": "Blocks PLA @base",
"from": "system",
"setting_id": "jt1MJF4eZzkkscEJ",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA-CF @Blocks_RD50_V2",
"inherits": "Blocks PLA-CF @base",
"from": "system",
"setting_id": "lhBtMKP1DmOB3HOI",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic PLA-CF;Generic PLA-CF @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA-CF @Blocks_RF50",
"inherits": "Blocks PLA-CF @base",
"from": "system",
"setting_id": "6CU83mAyhcZ4FCPI",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,23 +0,0 @@
{
"type": "filament",
"name": "Blocks PLA-CF @base",
"inherits": "fdm_filament_pla",
"from": "system",
"filament_id": "OF6FfwOP",
"instantiation": "false",
"filament_vendor": [
"Blocks"
],
"filament_flow_ratio": [
"0.95"
],
"filament_max_volumetric_speed": [
"20"
],
"filament_type": [
"PLA-CF"
],
"slow_down_layer_time": [
"7"
]
}
@@ -1,14 +0,0 @@
{
"type": "filament",
"name": "Blocks PVA @Blocks_RD50_V2",
"inherits": "Blocks PVA @base",
"from": "system",
"setting_id": "hREDqwKF6qyKkakp",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
],
"renamed_from": "Blocks Generic PVA;Generic PVA @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks PVA @Blocks_RF50",
"inherits": "Blocks PVA @base",
"from": "system",
"setting_id": "q6pKqHY7Iz4OZaAC",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,17 +0,0 @@
{
"type": "filament",
"name": "Blocks PVA @base",
"inherits": "fdm_filament_pva",
"from": "system",
"filament_id": "OFqcNuE1",
"instantiation": "false",
"filament_vendor": [
"Blocks"
],
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"20"
]
}
@@ -1,16 +0,0 @@
{
"type": "filament",
"name": "Blocks TPU @Blocks_Pro_S100",
"inherits": "Blocks TPU @base",
"from": "system",
"setting_id": "6Rkz2je91JRTRoTi",
"instantiation": "true",
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle"
],
"renamed_from": "Blocks Generic TPU;Generic TPU @Blocks"
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks TPU @Blocks_RD50_V2",
"inherits": "Blocks TPU @base",
"from": "system",
"setting_id": "mkCqRQTtXldzoEUg",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle"
]
}
@@ -1,13 +0,0 @@
{
"type": "filament",
"name": "Blocks TPU @Blocks_RF50",
"inherits": "Blocks TPU @base",
"from": "system",
"setting_id": "bCCvu5Ow1JkwIrRR",
"instantiation": "true",
"compatible_printers": [
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks ABS @base", "name": "Generic ABS @Blocks",
"inherits": "fdm_filament_abs", "inherits": "fdm_filament_abs",
"renamed_from": "Blocks Generic ABS",
"from": "system", "from": "system",
"filament_id": "OFBBhiX8", "setting_id": "TL1Q1kA4t36GGObG",
"instantiation": "false", "filament_id": "OFY9muEs",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.95" "0.95"
], ],
@@ -82,5 +81,13 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"100" "100"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks ASA @base", "name": "Generic ASA @Blocks",
"inherits": "fdm_filament_asa", "inherits": "fdm_filament_asa",
"renamed_from": "Blocks Generic ASA",
"from": "system", "from": "system",
"filament_id": "OFTz2YXa", "setting_id": "xP7cB4RHgbm4cYDD",
"instantiation": "false", "filament_id": "OFLPAxz3",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.95" "0.95"
], ],
@@ -82,5 +81,13 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"100" "100"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks ASA-CF @base", "name": "Generic ASA-CF @Blocks",
"inherits": "fdm_filament_asa", "inherits": "fdm_filament_asa",
"renamed_from": "Blocks Generic ASA-CF",
"from": "system", "from": "system",
"filament_id": "OF8b9I7o", "setting_id": "ju4ue7yJoz3ujny6",
"instantiation": "false", "filament_id": "OF53eLVD",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_type": [ "filament_type": [
"ASA-CF" "ASA-CF"
], ],
@@ -85,5 +84,13 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"100" "100"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -0,0 +1,24 @@
{
"type": "filament",
"name": "Generic PA @Blocks",
"inherits": "fdm_filament_pa",
"renamed_from": "Blocks Generic PA",
"from": "system",
"setting_id": "hL3p8gAeciwDkjNK",
"filament_id": "OFg8ndtj",
"instantiation": "true",
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"10"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks PA-CF @base", "name": "Generic PA-CF @Blocks",
"inherits": "fdm_filament_pa", "inherits": "fdm_filament_pa",
"renamed_from": "Blocks Generic PA-CF",
"from": "system", "from": "system",
"filament_id": "OFdWrXpL", "setting_id": "T6SO0WRdnG6wcyG8",
"instantiation": "false", "filament_id": "OFQLcbps",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_type": [ "filament_type": [
"PA-CF" "PA-CF"
], ],
@@ -88,5 +87,13 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"80" "80"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -0,0 +1,24 @@
{
"type": "filament",
"name": "Generic PC @Blocks",
"inherits": "fdm_filament_pc",
"renamed_from": "Blocks Generic PC",
"from": "system",
"setting_id": "Xhs8PjtmwwVj0ksE",
"filament_id": "OFLakOUI",
"instantiation": "true",
"filament_flow_ratio": [
"0.94"
],
"filament_max_volumetric_speed": [
"10"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks PETG @base", "name": "Generic PETG @Blocks",
"inherits": "fdm_filament_petg", "inherits": "fdm_filament_petg",
"renamed_from": "Blocks Generic PETG",
"from": "system", "from": "system",
"filament_id": "OF9t1Ga0", "setting_id": "NgzPlYItKHbmGgv3",
"instantiation": "false", "filament_id": "OFYPdQJh",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.94" "0.94"
], ],
@@ -82,5 +81,18 @@
], ],
"slow_down_layer_time": [ "slow_down_layer_time": [
"5" "5"
],
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle",
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks PLA @base", "name": "Generic PLA @Blocks",
"inherits": "fdm_filament_pla", "inherits": "fdm_filament_pla",
"renamed_from": "Blocks Generic PLA",
"from": "system", "from": "system",
"filament_id": "OFVGAC8g", "setting_id": "kjhuttx4T8OtTNmV",
"instantiation": "false", "filament_id": "OFDSrzZ8",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.95" "0.95"
], ],
@@ -40,5 +39,18 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"100" "100"
],
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle",
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -0,0 +1,30 @@
{
"type": "filament",
"name": "Generic PLA-CF @Blocks",
"inherits": "fdm_filament_pla",
"renamed_from": "Blocks Generic PLA-CF",
"from": "system",
"setting_id": "oKUqzwAWMrpiyGLf",
"filament_id": "OFWbdGsC",
"instantiation": "true",
"filament_flow_ratio": [
"0.95"
],
"filament_max_volumetric_speed": [
"20"
],
"filament_type": [
"PLA-CF"
],
"slow_down_layer_time": [
"7"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -0,0 +1,24 @@
{
"type": "filament",
"name": "Generic PVA @Blocks",
"inherits": "fdm_filament_pva",
"renamed_from": "Blocks Generic PVA",
"from": "system",
"setting_id": "tNw3oe7VovLkgUbB",
"filament_id": "OFDvXujf",
"instantiation": "true",
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"20"
],
"compatible_printers": [
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
]
}
@@ -1,13 +1,12 @@
{ {
"type": "filament", "type": "filament",
"name": "Blocks TPU @base", "name": "Generic TPU @Blocks",
"inherits": "fdm_filament_tpu", "inherits": "fdm_filament_tpu",
"renamed_from": "Blocks Generic TPU",
"from": "system", "from": "system",
"filament_id": "OFYnedOZ", "setting_id": "6iVYOCZo8ugs4JA0",
"instantiation": "false", "filament_id": "OFgbpcy9",
"filament_vendor": [ "instantiation": "true",
"Blocks"
],
"filament_max_volumetric_speed": [ "filament_max_volumetric_speed": [
"4" "4"
], ],
@@ -55,5 +54,18 @@
], ],
"during_print_exhaust_fan_speed": [ "during_print_exhaust_fan_speed": [
"80" "80"
],
"compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle",
"BLOCKS Pro S100 0.6 nozzle",
"BLOCKS Pro S100 0.8 nozzle",
"BLOCKS Pro S100 1.0 nozzle",
"BLOCKS Pro S100 1.2 nozzle",
"BLOCKS RD50 V2 0.4 nozzle",
"BLOCKS RD50 V2 0.6 nozzle",
"BLOCKS RD50 V2 0.8 nozzle",
"BLOCKS RF50 0.4 nozzle",
"BLOCKS RF50 0.6 nozzle",
"BLOCKS RF50 0.8 nozzle"
] ]
} }
@@ -6,7 +6,7 @@
"setting_id": "G7HQgaspHXduDM8O", "setting_id": "G7HQgaspHXduDM8O",
"instantiation": "true", "instantiation": "true",
"printer_model": "BLOCKS Pro S100", "printer_model": "BLOCKS Pro S100",
"default_print_profile": "0.20mm Standard 0.4 nozzle @Blocks_Pro_S100", "default_print_profile": "0.20mm Standard 0.4 nozzle @Blocks",
"max_layer_height": [ "max_layer_height": [
"0.30" "0.30"
], ],
@@ -25,8 +25,5 @@
"printable_height": "900", "printable_height": "900",
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS Pro S100" "BLOCKS Pro S100"
],
"default_filament_profile": [
"Blocks PLA @Blocks_Pro_S100"
] ]
} }
@@ -6,7 +6,7 @@
"setting_id": "XkWdS210oUMQN17N", "setting_id": "XkWdS210oUMQN17N",
"instantiation": "true", "instantiation": "true",
"printer_model": "BLOCKS Pro S100", "printer_model": "BLOCKS Pro S100",
"default_print_profile": "0.30mm Standard 0.6 nozzle @Blocks_Pro_S100", "default_print_profile": "0.30mm Standard 0.6 nozzle @Blocks",
"max_layer_height": [ "max_layer_height": [
"0.50" "0.50"
], ],
@@ -26,8 +26,5 @@
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS Pro S100" "BLOCKS Pro S100"
], ],
"printer_variant": "0.6", "printer_variant": "0.6"
"default_filament_profile": [
"Blocks PLA @Blocks_Pro_S100"
]
} }
@@ -6,7 +6,7 @@
"setting_id": "I6PdeCS7SbvIlkZf", "setting_id": "I6PdeCS7SbvIlkZf",
"instantiation": "true", "instantiation": "true",
"printer_model": "BLOCKS Pro S100", "printer_model": "BLOCKS Pro S100",
"default_print_profile": "0.40mm Standard 0.8 nozzle @Blocks_Pro_S100", "default_print_profile": "0.40mm Standard 0.8 nozzle @Blocks",
"max_layer_height": [ "max_layer_height": [
"0.56" "0.56"
], ],
@@ -26,8 +26,5 @@
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS Pro S100" "BLOCKS Pro S100"
], ],
"printer_variant": "0.8", "printer_variant": "0.8"
"default_filament_profile": [
"Blocks PLA @Blocks_Pro_S100"
]
} }
@@ -6,7 +6,7 @@
"setting_id": "elLdUyy9RhUoa37o", "setting_id": "elLdUyy9RhUoa37o",
"instantiation": "true", "instantiation": "true",
"printer_model": "BLOCKS Pro S100", "printer_model": "BLOCKS Pro S100",
"default_print_profile": "0.50mm Standard 1.0 nozzle @Blocks_Pro_S100", "default_print_profile": "0.50mm Standard 1.0 nozzle @Blocks",
"max_layer_height": [ "max_layer_height": [
"0.7" "0.7"
], ],
@@ -26,8 +26,5 @@
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS Pro S100" "BLOCKS Pro S100"
], ],
"printer_variant": "1.0", "printer_variant": "1.0"
"default_filament_profile": [
"Blocks PLA @Blocks_Pro_S100"
]
} }
@@ -6,7 +6,7 @@
"setting_id": "xtsGSJ4JkbHTPi44", "setting_id": "xtsGSJ4JkbHTPi44",
"instantiation": "true", "instantiation": "true",
"printer_model": "BLOCKS Pro S100", "printer_model": "BLOCKS Pro S100",
"default_print_profile": "0.60mm Standard 1.2 nozzle @Blocks_Pro_S100", "default_print_profile": "0.60mm Standard 1.2 nozzle @Blocks",
"max_layer_height": [ "max_layer_height": [
"0.8" "0.8"
], ],
@@ -26,8 +26,5 @@
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS Pro S100" "BLOCKS Pro S100"
], ],
"printer_variant": "1.2", "printer_variant": "1.2"
"default_filament_profile": [
"Blocks PLA @Blocks_Pro_S100"
]
} }
@@ -8,5 +8,5 @@
"bed_model": "PRO S100 HotBed model.stl", "bed_model": "PRO S100 HotBed model.stl",
"bed_texture": "PRO S100 HotBed texture.svg", "bed_texture": "PRO S100 HotBed texture.svg",
"hotend_model": "BLOCKS PrintCore.stl", "hotend_model": "BLOCKS PrintCore.stl",
"default_materials": "Blocks PLA @Blocks_Pro_S100;Blocks PETG @Blocks_Pro_S100;Blocks TPU @Blocks_Pro_S100" "default_materials": "Generic PLA @Blocks;Generic PETG @Blocks;Generic TPU @Blocks"
} }
@@ -34,9 +34,5 @@
"printable_height": "500", "printable_height": "500",
"upward_compatible_machine": [ "upward_compatible_machine": [
"BLOCKS RD50 V2" "BLOCKS RD50 V2"
],
"printer_variant": "0.4",
"default_filament_profile": [
"Blocks PLA @Blocks_RD50_V2"
] ]
} }
@@ -35,8 +35,5 @@
"deretraction_speed": [ "deretraction_speed": [
"80" "80"
], ],
"printer_variant": "0.6", "printer_variant": "0.6"
"default_filament_profile": [
"Blocks PLA @Blocks_RD50_V2"
]
} }
@@ -35,8 +35,5 @@
"deretraction_speed": [ "deretraction_speed": [
"80" "80"
], ],
"printer_variant": "0.8", "printer_variant": "0.8"
"default_filament_profile": [
"Blocks PLA @Blocks_RD50_V2"
]
} }
@@ -8,5 +8,5 @@
"bed_model": "RD50 V2 HotBed model.stl", "bed_model": "RD50 V2 HotBed model.stl",
"bed_texture": "RD50 V2 HotBed texture.svg", "bed_texture": "RD50 V2 HotBed texture.svg",
"hotend_model": "BLOCKS PrintCore.stl", "hotend_model": "BLOCKS PrintCore.stl",
"default_materials": "Blocks PLA @Blocks_RD50_V2;Blocks PETG @Blocks_RD50_V2;Blocks TPU @Blocks_RD50_V2" "default_materials": "Generic PLA @Blocks;Generic PETG @Blocks;Generic TPU @Blocks"
} }
@@ -51,7 +51,7 @@
"12" "12"
], ],
"retraction_length": [ "retraction_length": [
"1.2" "1"
], ],
"retraction_speed": [ "retraction_speed": [
"60" "60"
@@ -79,10 +79,5 @@
], ],
"retract_before_wipe": [ "retract_before_wipe": [
"0" "0"
], ]
"default_filament_profile": [
"Blocks PLA @Blocks_RF50"
],
"support_multi_bed_types": "1",
"default_bed_type": "Textured PEI Plate"
} }
@@ -51,7 +51,7 @@
"12" "12"
], ],
"retraction_length": [ "retraction_length": [
"1.2" "1"
], ],
"retraction_speed": [ "retraction_speed": [
"60" "60"
@@ -75,8 +75,8 @@
"BLOCKS RF50" "BLOCKS RF50"
], ],
"machine_start_gcode": [ "machine_start_gcode": [
"PRINT_START EXTRUDER=[nozzle_temperature_initial_layer] BED=[bed_temperature_initial_layer]\n", "PRINT_START EXTRUDER=[nozzle_temperature_initial_layer] BED=[bed_temperature_initial_layer]",
"SET_PRESSURE_ADVANCE ADVANCE=0.046\n" "SET_PRESSURE_ADVANCE ADVANCE=0.046"
], ],
"printer_variant": "0.6", "printer_variant": "0.6",
"wipe_distance": [ "wipe_distance": [
@@ -84,10 +84,5 @@
], ],
"retract_before_wipe": [ "retract_before_wipe": [
"0" "0"
], ]
"default_filament_profile": [
"Blocks PLA @Blocks_RF50"
],
"support_multi_bed_types": "1",
"default_bed_type": "Textured PEI Plate"
} }
@@ -51,7 +51,7 @@
"12" "12"
], ],
"retraction_length": [ "retraction_length": [
"1.2" "1"
], ],
"retraction_speed": [ "retraction_speed": [
"60" "60"
@@ -80,10 +80,5 @@
], ],
"retract_before_wipe": [ "retract_before_wipe": [
"0" "0"
], ]
"default_filament_profile": [
"Blocks PLA @Blocks_RF50"
],
"support_multi_bed_types": "1",
"default_bed_type": "Textured PEI Plate"
} }
@@ -8,6 +8,5 @@
"bed_model": "RF50 HotBed model.stl", "bed_model": "RF50 HotBed model.stl",
"bed_texture": "RF50 HotBed texture.svg", "bed_texture": "RF50 HotBed texture.svg",
"hotend_model": "BLOCKS PrintCore.stl", "hotend_model": "BLOCKS PrintCore.stl",
"default_materials": "Blocks PLA @Blocks_RF50;Blocks PETG @Blocks_RF50;Blocks TPU @Blocks_RF50", "default_materials": "Generic PLA @Blocks;Generic PETG @Blocks;Generic TPU @Blocks"
"not_support_bed_type": "Smooth Cool Plate;Engineering Plate;Textured Cool Plate;Cool Plate (SuperTack)"
} }
@@ -123,6 +123,9 @@
"wipe": [ "wipe": [
"1" "1"
], ],
"default_filament_profile": [
"Generic PLA @Blocks"
],
"bed_exclude_area": [ "bed_exclude_area": [
"0x0" "0x0"
], ],
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.20mm Standard 0.4 nozzle @Blocks_Pro_S100", "name": "0.20mm Standard 0.4 nozzle @Blocks",
"inherits": "fdm_process_blocks_common", "inherits": "fdm_process_blocks_common",
"from": "system", "from": "system",
"setting_id": "QSEguMMChNFZsK5H", "setting_id": "47aDtVL6E5DVr7Mt",
"instantiation": "true", "instantiation": "true",
"layer_height": "0.2", "layer_height": "0.2",
"bottom_shell_layers": "4", "bottom_shell_layers": "4",
"top_shell_layers": "5", "top_shell_layers": "5",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle" "BLOCKS Pro S100 0.4 nozzle"
], ]
"renamed_from": "0.20mm Standard 0.4 nozzle @Blocks"
} }
@@ -25,7 +25,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -61,7 +61,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.24mm Draft 0.4 nozzle @Blocks_Pro_S100", "name": "0.24mm Draft 0.4 nozzle @Blocks",
"inherits": "fdm_process_blocks_common", "inherits": "fdm_process_blocks_common",
"from": "system", "from": "system",
"setting_id": "uALfEFHGmup6vBYI", "setting_id": "ETADjxV6ViJQdnHA",
"instantiation": "true", "instantiation": "true",
"layer_height": "0.24", "layer_height": "0.24",
"bottom_shell_layers": "4", "bottom_shell_layers": "4",
"top_shell_layers": "5", "top_shell_layers": "5",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle" "BLOCKS Pro S100 0.4 nozzle"
], ]
"renamed_from": "0.24mm Draft 0.4 nozzle @Blocks"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -22,7 +22,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.30mm Extra Draft 0.4 nozzle @Blocks_Pro_S100", "name": "0.30mm Extra Draft 0.4 nozzle @Blocks",
"inherits": "fdm_process_blocks_common", "inherits": "fdm_process_blocks_common",
"from": "system", "from": "system",
"setting_id": "HYKF5l2OGvpugSQy", "setting_id": "UbuICsmppKDsaaZ4",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "4", "top_shell_layers": "4",
"layer_height": "0.30", "layer_height": "0.30",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.4 nozzle" "BLOCKS Pro S100 0.4 nozzle"
], ]
"renamed_from": "0.30mm Extra Draft 0.4 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.30mm Optimal 0.8 nozzle @Blocks_Pro_S100", "name": "0.30mm Optimal 0.8 nozzle @Blocks",
"inherits": "fdm_process_common 0.8 nozzle", "inherits": "fdm_process_common 0.8 nozzle",
"from": "system", "from": "system",
"setting_id": "OUfZvizM5MGnvHfp", "setting_id": "YqkYzp5zdH4R5upm",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.3", "layer_height": "0.3",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.8 nozzle" "BLOCKS Pro S100 0.8 nozzle"
], ]
"renamed_from": "0.30mm Optimal 0.8 nozzle @Blocks"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.30mm Optimal 1.0 nozzle @Blocks_Pro_S100", "name": "0.30mm Optimal 1.0 nozzle @Blocks",
"inherits": "fdm_process_common 1.0 nozzle", "inherits": "fdm_process_common 1.0 nozzle",
"from": "system", "from": "system",
"setting_id": "HGG9WxKVr89qNFDx", "setting_id": "8pBawPScHkyQu0SW",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "4", "bottom_shell_layers": "4",
"top_shell_layers": "4", "top_shell_layers": "4",
"layer_height": "0.30", "layer_height": "0.30",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.0 nozzle" "BLOCKS Pro S100 1.0 nozzle"
], ]
"renamed_from": "0.30mm Optimal 1.0 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.30mm Standard 0.6 nozzle @Blocks_Pro_S100", "name": "0.30mm Standard 0.6 nozzle @Blocks",
"inherits": "fdm_process_common 0.6 nozzle", "inherits": "fdm_process_common 0.6 nozzle",
"from": "system", "from": "system",
"setting_id": "gO2I1YjBl4nf8yzr", "setting_id": "EPI3PAVK9LpJOZWO",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.30", "layer_height": "0.30",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.6 nozzle" "BLOCKS Pro S100 0.6 nozzle"
], ]
"renamed_from": "0.30mm Standard 0.6 nozzle @Blocks"
} }
@@ -22,7 +22,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -22,7 +22,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.40mm Draft 0.6 nozzle @Blocks_Pro_S100", "name": "0.40mm Draft 0.6 nozzle @Blocks",
"inherits": "fdm_process_common 0.6 nozzle", "inherits": "fdm_process_common 0.6 nozzle",
"from": "system", "from": "system",
"setting_id": "OjsLUl1heqv1cevs", "setting_id": "CShVKoGspbMJNPw8",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "2", "top_shell_layers": "2",
"layer_height": "0.40", "layer_height": "0.40",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.6 nozzle" "BLOCKS Pro S100 0.6 nozzle"
], ]
"renamed_from": "0.40mm Draft 0.6 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.40mm Standard 0.8 nozzle @Blocks_Pro_S100", "name": "0.40mm Standard 0.8 nozzle @Blocks",
"inherits": "fdm_process_common 0.8 nozzle", "inherits": "fdm_process_common 0.8 nozzle",
"from": "system", "from": "system",
"setting_id": "laOTioBGySeudJpl", "setting_id": "TSRjmfWaatY7oLJB",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "4", "top_shell_layers": "4",
"layer_height": "0.40", "layer_height": "0.40",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.8 nozzle" "BLOCKS Pro S100 0.8 nozzle"
], ]
"renamed_from": "0.40mm Standard 0.8 nozzle @Blocks"
} }
@@ -22,7 +22,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.50mm Draft 0.8 nozzle @Blocks_Pro_S100", "name": "0.50mm Draft 0.8 nozzle @Blocks",
"inherits": "fdm_process_common 0.8 nozzle", "inherits": "fdm_process_common 0.8 nozzle",
"from": "system", "from": "system",
"setting_id": "oAhgUZdADR7kP87e", "setting_id": "vOtZHrDS88Shmf2m",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "4", "top_shell_layers": "4",
"layer_height": "0.50", "layer_height": "0.50",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 0.8 nozzle" "BLOCKS Pro S100 0.8 nozzle"
], ]
"renamed_from": "0.50mm Draft 0.8 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.50mm Optimal 1.2 nozzle @Blocks_Pro_S100", "name": "0.50mm Optimal 1.2 nozzle @Blocks",
"inherits": "fdm_process_common 1.2 nozzle", "inherits": "fdm_process_common 1.2 nozzle",
"from": "system", "from": "system",
"setting_id": "0eqNgX26jemsBfV5", "setting_id": "BKrEAKqDYzdH43wc",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.50", "layer_height": "0.50",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.2 nozzle" "BLOCKS Pro S100 1.2 nozzle"
], ]
"renamed_from": "0.50mm Optimal 1.2 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.50mm Standard 1.0 nozzle @Blocks_Pro_S100", "name": "0.50mm Standard 1.0 nozzle @Blocks",
"inherits": "fdm_process_common 1.0 nozzle", "inherits": "fdm_process_common 1.0 nozzle",
"from": "system", "from": "system",
"setting_id": "z1qCW1cEMc4QvBbV", "setting_id": "D40iksDm7mFjhSKn",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "3", "bottom_shell_layers": "3",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.50", "layer_height": "0.50",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.0 nozzle" "BLOCKS Pro S100 1.0 nozzle"
], ]
"renamed_from": "0.50mm Standard 1.0 nozzle @Blocks"
} }
@@ -21,7 +21,7 @@
"top_solid_infill_flow_ratio": "0.97", "top_solid_infill_flow_ratio": "0.97",
"bottom_solid_infill_flow_ratio": "1.08", "bottom_solid_infill_flow_ratio": "1.08",
"seam_position": "aligned", "seam_position": "aligned",
"sparse_infill_pattern": "grid", "sparse_infill_patter": "grid",
"initial_layer_speed": "60", "initial_layer_speed": "60",
"initial_layer_infill_speed": "80", "initial_layer_infill_speed": "80",
"initial_travel_speed": "100%", "initial_travel_speed": "100%",
@@ -57,7 +57,5 @@
"accel_to_decel_enable": "1", "accel_to_decel_enable": "1",
"accel_to_decel_factor": "50%", "accel_to_decel_factor": "50%",
"elefant_foot_compensation": "0.25", "elefant_foot_compensation": "0.25",
"elefant_foot_compensation_layers": "1", "elefant_foot_compensation_layers": "1"
"skirt_loops": "2",
"skirt_type": "perobject"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.60mm Draft 1.0 nozzle @Blocks_Pro_S100", "name": "0.60mm Draft 1.0 nozzle @Blocks",
"inherits": "fdm_process_common 1.0 nozzle", "inherits": "fdm_process_common 1.0 nozzle",
"from": "system", "from": "system",
"setting_id": "gTTgtfG8qb9My3hH", "setting_id": "UJUe8XCBzZf8NyCL",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.60", "layer_height": "0.60",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.0 nozzle" "BLOCKS Pro S100 1.0 nozzle"
], ]
"renamed_from": "0.60mm Draft 1.0 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.60mm Standard 1.2 nozzle @Blocks_Pro_S100", "name": "0.60mm Standard 1.2 nozzle @Blocks",
"inherits": "fdm_process_common 1.2 nozzle", "inherits": "fdm_process_common 1.2 nozzle",
"from": "system", "from": "system",
"setting_id": "ApcyToENCIANrI71", "setting_id": "PSBFrTykpkytPI2Q",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.60", "layer_height": "0.60",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.2 nozzle" "BLOCKS Pro S100 1.2 nozzle"
], ]
"renamed_from": "0.60mm Standard 1.2 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.70mm Draft 1.2 nozzle @Blocks_Pro_S100", "name": "0.70mm Draft 1.2 nozzle @Blocks",
"inherits": "fdm_process_common 1.2 nozzle", "inherits": "fdm_process_common 1.2 nozzle",
"from": "system", "from": "system",
"setting_id": "DEv7X7zaTfxRQmjo", "setting_id": "0ZQ0USGX9SwAKr29",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.70", "layer_height": "0.70",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.2 nozzle" "BLOCKS Pro S100 1.2 nozzle"
], ]
"renamed_from": "0.70mm Draft 1.2 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.70mm Extra Draft 1.0 nozzle @Blocks_Pro_S100", "name": "0.70mm Extra Draft 1.0 nozzle @Blocks",
"inherits": "fdm_process_common 1.0 nozzle", "inherits": "fdm_process_common 1.0 nozzle",
"from": "system", "from": "system",
"setting_id": "nUW7N9dJmTyQT4AG", "setting_id": "69PFmjOVFBOIp3Qg",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "3", "top_shell_layers": "3",
"layer_height": "0.70", "layer_height": "0.70",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.0 nozzle" "BLOCKS Pro S100 1.0 nozzle"
], ]
"renamed_from": "0.70mm Extra Draft 1.0 nozzle @Blocks"
} }
@@ -1,15 +1,14 @@
{ {
"type": "process", "type": "process",
"name": "0.80mm Extra Draft 1.2 nozzle @Blocks_Pro_S100", "name": "0.80mm Extra Draft 1.2 nozzle @Blocks",
"inherits": "fdm_process_common 1.2 nozzle", "inherits": "fdm_process_common 1.2 nozzle",
"from": "system", "from": "system",
"setting_id": "JMy62SonRfK0cAdL", "setting_id": "iBwRI5JJewW5HJSv",
"instantiation": "true", "instantiation": "true",
"bottom_shell_layers": "2", "bottom_shell_layers": "2",
"top_shell_layers": "2", "top_shell_layers": "2",
"layer_height": "0.80", "layer_height": "0.80",
"compatible_printers": [ "compatible_printers": [
"BLOCKS Pro S100 1.2 nozzle" "BLOCKS Pro S100 1.2 nozzle"
], ]
"renamed_from": "0.80mm Extra Draft 1.2 nozzle @Blocks"
} }
+1 -3
View File
@@ -575,7 +575,7 @@ function CapabilityCanRun(plugin, capability) {
} }
function IsPluginChecked(plugin) { function IsPluginChecked(plugin) {
return plugin.is_loaded; return GetStatus(plugin) === "Activated";
} }
function HasMixedCapabilityState(plugin) { function HasMixedCapabilityState(plugin) {
@@ -1347,8 +1347,6 @@ function StatusDescription(plugin) {
return "This plugin is still loading."; return "This plugin is still loading.";
case "Error": case "Error":
return "This plugin is blocked until its error is fixed."; return "This plugin is blocked until its error is fixed.";
case "RuntimeError":
return "This plugin is loaded but a capability reported an error.";
case "Inactive": case "Inactive":
default: default:
return "This plugin is inactive. Activate it to install or load it."; return "This plugin is inactive. Activate it to install or load it.";
@@ -424,11 +424,6 @@ body.pane-resizing {
font-weight: 600; font-weight: 600;
} }
.status-cell.status-runtimeerror {
color: var(--plugin-status-warn);
font-weight: 600;
}
.status-cell.status-loading { .status-cell.status-loading {
color: var(--plugin-status-warn); color: var(--plugin-status-warn);
font-weight: 600; font-weight: 600;
@@ -685,11 +680,6 @@ body.pane-resizing {
color: var(--plugin-status-danger); color: var(--plugin-status-danger);
} }
.detail-status-chip.status-runtimeerror {
background: var(--plugin-status-warn-bg);
color: var(--plugin-status-warn);
}
.detail-status-chip.status-loading { .detail-status-chip.status-loading {
background: var(--plugin-status-warn-bg); background: var(--plugin-status-warn-bg);
color: var(--plugin-status-warn); color: var(--plugin-status-warn);
+1 -1
View File
@@ -7,6 +7,7 @@
<script type="text/javascript" src="../include/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="../include/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="../include/json2.js"></script> <script type="text/javascript" src="../include/json2.js"></script>
<script type="text/javascript" src="../include/globalapi.js"></script>
<link rel="stylesheet" type="text/css" href="../include/swiper/swiper-bundle.min.css" /> <link rel="stylesheet" type="text/css" href="../include/swiper/swiper-bundle.min.css" />
<script type="text/javascript" src="../include/swiper/swiper-bundle.min.js"></script> <script type="text/javascript" src="../include/swiper/swiper-bundle.min.js"></script>
@@ -17,7 +18,6 @@
<link rel="stylesheet" type="text/css" href="model.css" /> <link rel="stylesheet" type="text/css" href="model.css" />
<link rel="stylesheet" type="text/css" href="./css/dark.css" /> <link rel="stylesheet" type="text/css" href="./css/dark.css" />
<link rel="stylesheet" type="text/css" href="../include/global.css" /> <!-- ORCA One for all--> <link rel="stylesheet" type="text/css" href="../include/global.css" /> <!-- ORCA One for all-->
<script type="text/javascript" src="../include/globalapi.js"></script>
<script type="text/javascript" src="test.js"></script> <script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="model.js"></script> <script type="text/javascript" src="model.js"></script>
@@ -331,15 +331,6 @@ modules:
sha256: deedcabe339165214a3637df4c86a507aef0d793cf8774ff68735f4737e8ddbc sha256: deedcabe339165214a3637df4c86a507aef0d793cf8774ff68735f4737e8ddbc
dest: external-packages/FFMPEG dest: external-packages/FFMPEG
# libdatachannel v0.24.5
# The Git checkout includes the submodules that are missing from the
# GitHub source archive. DataChannel.cmake consumes it as SOURCE_DIR.
- type: git
url: https://github.com/paullouisageneau/libdatachannel.git
tag: v0.24.5
commit: 443f6934d9007eb7076ab7825ba330f355fcbead
dest: external-packages/DataChannel
# --------------------------------------------------------------- # ---------------------------------------------------------------
# Fallback archives for deps normally provided by the GNOME SDK. # Fallback archives for deps normally provided by the GNOME SDK.
# These are only used if find_package() fails to locate them. # These are only used if find_package() fails to locate them.
+3 -6
View File
@@ -697,8 +697,7 @@ public:
} }
} else { } else {
// Resize by duplicating the last value. // Resize by duplicating the last value.
T v = this->values./*back*/front(); this->values.resize(n, this->values./*back*/front());
this->values.resize(n, v);
} }
} }
} }
@@ -773,10 +772,8 @@ public:
if (this->values.empty()) if (this->values.empty())
this->values.resize(rhs_vec->size()); this->values.resize(rhs_vec->size());
else { else
T v = this->values.front(); this->values.resize(rhs_vec->size(), this->values.front());
this->values.resize(rhs_vec->size(), v);
}
assert(default_index.size() == rhs_vec->size()); assert(default_index.size() == rhs_vec->size());

Some files were not shown because too many files have changed in this diff Show More