mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-30 05:17:19 +00:00
Compare commits
27 Commits
nightly-bu
...
feature/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23e5875d5 | ||
|
|
8d83414d09 | ||
|
|
1c405f8a2c | ||
|
|
58d1a3b093 | ||
|
|
71563cc6c6 | ||
|
|
f3fa3a34bd | ||
|
|
1a62a25d36 | ||
|
|
f7c1b290fd | ||
|
|
e3ac835cc3 | ||
|
|
23386f6129 | ||
|
|
3ccc58a9fc | ||
|
|
acd5dd0794 | ||
|
|
2c0867619c | ||
|
|
67406b24ba | ||
|
|
a395701f29 | ||
|
|
ac12dff1af | ||
|
|
33923464ae | ||
|
|
55a3114ec9 | ||
|
|
ee125975cf | ||
|
|
23b0aabb35 | ||
|
|
095fd9fba4 | ||
|
|
674344b3c1 | ||
|
|
4fc964d293 | ||
|
|
516267d869 | ||
|
|
ab60229311 | ||
|
|
1482fb81fd | ||
|
|
051cdd4560 |
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -20,6 +20,8 @@
|
|||||||
> Please describe the tests that you have conducted to verify the changes made in this PR.
|
> Please describe the tests that you have conducted to verify the changes made in this PR.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
- [ ] New filament/material profiles: I wrote **no** `filament_id` key by hand — I ran `python scripts/assign_filament_ids.py` and `--update-snapshot` and committed both diffs (see `doc/developer-reference/filament_id.md`)
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
> A guide for users on how to download the artifacts from this PR.
|
> A guide for users on how to download the artifacts from this PR.
|
||||||
-->
|
-->
|
||||||
|
|||||||
2
.github/workflows/build_deps.yml
vendored
2
.github/workflows/build_deps.yml
vendored
@@ -149,7 +149,7 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
run: |
|
run: |
|
||||||
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
|
if [ -z "${{ vars.SELF_HOSTED }}" ]; then
|
||||||
brew install automake texinfo libtool pkgconf yasm nasm
|
brew install automake texinfo libtool
|
||||||
fi
|
fi
|
||||||
./build_release_macos.sh -dx ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
|
./build_release_macos.sh -dx ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15
|
||||||
(cd "${{ github.workspace }}/deps/build/${{ inputs.arch }}" && \
|
(cd "${{ github.workspace }}/deps/build/${{ inputs.arch }}" && \
|
||||||
|
|||||||
7
.github/workflows/build_orca.yml
vendored
7
.github/workflows/build_orca.yml
vendored
@@ -385,13 +385,6 @@ jobs:
|
|||||||
dir "C:/Program Files (x86)/Windows Kits/10/Include"
|
dir "C:/Program Files (x86)/Windows Kits/10/Include"
|
||||||
choco install nsis
|
choco install nsis
|
||||||
|
|
||||||
- name: Install pkg-config
|
|
||||||
# FFmpeg is discovered via pkg-config (pkg_check_modules LIBAV in
|
|
||||||
# src/slic3r/CMakeLists.txt); the Windows runners don't ship it.
|
|
||||||
if: runner.os == 'Windows' && !vars.SELF_HOSTED
|
|
||||||
run: |
|
|
||||||
choco install pkgconfiglite -y
|
|
||||||
|
|
||||||
- name: Build slicer Win
|
- name: Build slicer Win
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
|
|||||||
9
.github/workflows/check_profiles.yml
vendored
9
.github/workflows/check_profiles.yml
vendored
@@ -64,13 +64,14 @@ jobs:
|
|||||||
set +e
|
set +e
|
||||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -s -l 2 2>&1 | tee ${{ runner.temp }}/validate_slice.log
|
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -s -l 2 2>&1 | tee ${{ runner.temp }}/validate_slice.log
|
||||||
exit ${PIPESTATUS[0]}
|
exit ${PIPESTATUS[0]}
|
||||||
# For now run filament subtype check only for BBL profiles until we fix other vendors' profiles.
|
# All vendors' filament_id collisions were fixed (see scripts/filament_id_snapshot.json),
|
||||||
- name: validate filament subtype check for BBL profiles
|
# so the duplicate-filament-subtype check runs tree-wide.
|
||||||
|
- name: validate filament subtype check
|
||||||
id: validate_filament_subtypes
|
id: validate_filament_subtypes
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
set +e
|
set +e
|
||||||
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 -v BBL -f 2>&1 | tee ${{ runner.temp }}/validate_filament_subtypes.log
|
./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 -f 2>&1 | tee ${{ runner.temp }}/validate_filament_subtypes.log
|
||||||
exit ${PIPESTATUS[0]}
|
exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
- name: validate custom presets
|
- name: validate custom presets
|
||||||
@@ -217,7 +218,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${{ steps.validate_filament_subtypes.outcome }}" = "failure" ]; then
|
if [ "${{ steps.validate_filament_subtypes.outcome }}" = "failure" ]; then
|
||||||
echo "### BBL Filament Subtype Validation Failed"
|
echo "### Filament Subtype Validation Failed"
|
||||||
echo ""
|
echo ""
|
||||||
echo '```'
|
echo '```'
|
||||||
head -c 30000 ${{ runner.temp }}/validate_filament_subtypes.log || echo "No output captured"
|
head -c 30000 ${{ runner.temp }}/validate_filament_subtypes.log || echo "No output captured"
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,7 +2,6 @@ Build
|
|||||||
Build.bat
|
Build.bat
|
||||||
/build*/
|
/build*/
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
CMakeUserPresets.json
|
|
||||||
**/CMakeLists.txt.autosave
|
**/CMakeLists.txt.autosave
|
||||||
deps/build*
|
deps/build*
|
||||||
MYMETA.json
|
MYMETA.json
|
||||||
|
|||||||
159
CMakeLists.txt
159
CMakeLists.txt
@@ -59,13 +59,6 @@ if (APPLE)
|
|||||||
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Keep MSVC's default /W3 out of CMAKE_<LANG>_FLAGS so it can be applied to our own
|
|
||||||
# targets only. Silencing a bundled target would otherwise override a warning level,
|
|
||||||
# which cl reports as D9025 for every file it compiles.
|
|
||||||
if (POLICY CMP0092)
|
|
||||||
cmake_policy(SET CMP0092 NEW)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
project(OrcaSlicer)
|
project(OrcaSlicer)
|
||||||
|
|
||||||
# Backward compatibility for old CMake versions
|
# Backward compatibility for old CMake versions
|
||||||
@@ -133,8 +126,6 @@ option(SLIC3R_GUI "Compile OrcaSlicer with GUI components (OpenGL,
|
|||||||
option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0)
|
option(SLIC3R_FHS "Assume OrcaSlicer is to be installed in a FHS directory structure" 0)
|
||||||
option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0)
|
option(SLIC3R_PROFILE "Compile OrcaSlicer with an invasive Shiny profiler" 0)
|
||||||
option(SLIC3R_PCH "Use precompiled headers" 1)
|
option(SLIC3R_PCH "Use precompiled headers" 1)
|
||||||
option(SLIC3R_WARNINGS "Emit compiler warnings for OrcaSlicer sources" 1)
|
|
||||||
option(SLIC3R_BUNDLED_WARNINGS "Emit compiler warnings for bundled third-party sources" 0)
|
|
||||||
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
||||||
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
||||||
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||||
@@ -298,8 +289,6 @@ if (APPLE)
|
|||||||
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
|
SET(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.orcaslicer.OrcaSlicer")
|
||||||
|
|
||||||
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
|
message(STATUS "Orca: IS_CROSS_COMPILE: ${IS_CROSS_COMPILE}")
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN")
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Proposal for C++ unit tests and sandboxes
|
# Proposal for C++ unit tests and sandboxes
|
||||||
@@ -346,20 +335,15 @@ if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
|||||||
|
|
||||||
# clang-cl can interpret SYSTEM header paths if -imsvc is used
|
# clang-cl can interpret SYSTEM header paths if -imsvc is used
|
||||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-imsvc")
|
set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-imsvc")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
|
||||||
|
-Wno-old-style-cast -Wno-reserved-id-macro -Wno-c++98-compat-pedantic")
|
||||||
else ()
|
else ()
|
||||||
set(IS_CLANG_CL FALSE)
|
set(IS_CLANG_CL FALSE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# CMP0092 only applies when the cache is created; an existing tree keeps its /W3,
|
if (SLIC3R_MSVC_COMPILE_PARALLEL AND NOT IS_CLANG_CL)
|
||||||
# which a silenced bundled target would then override (D9025, once per file).
|
|
||||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
|
||||||
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
|
||||||
|
|
||||||
# /MP only matters for the VS generators, where CMake turns it into the
|
|
||||||
# MultiProcessorCompilation property. Ninja parallelises on its own, and
|
|
||||||
# clang-cl warns "argument unused" if the flag reaches it.
|
|
||||||
if (SLIC3R_MSVC_COMPILE_PARALLEL AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
||||||
add_compile_options(/MP)
|
add_compile_options(/MP)
|
||||||
endif ()
|
endif ()
|
||||||
# /bigobj (Increase Number of Sections in .Obj file)
|
# /bigobj (Increase Number of Sections in .Obj file)
|
||||||
@@ -476,8 +460,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|||||||
# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
|
# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
|
||||||
# We pick it from environment if it is not defined in another way
|
# We pick it from environment if it is not defined in another way
|
||||||
# ORCA: Removed Netfabb STL fixing service support in favor of CGAL.
|
# ORCA: Removed Netfabb STL fixing service support in favor of CGAL.
|
||||||
if(WIN32)
|
# if(WIN32)
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
# if(NOT DEFINED WIN10SDK_PATH)
|
# if(NOT DEFINED WIN10SDK_PATH)
|
||||||
# if(DEFINED ENV{WIN10SDK_PATH})
|
# if(DEFINED ENV{WIN10SDK_PATH})
|
||||||
# set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
|
# set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
|
||||||
@@ -513,7 +496,7 @@ if(WIN32)
|
|||||||
# else()
|
# else()
|
||||||
# message("Building without Win10 Netfabb STL fixing service support")
|
# message("Building without Win10 Netfabb STL fixing service support")
|
||||||
# endif()
|
# endif()
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")
|
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")
|
||||||
@@ -540,15 +523,8 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ((NOT MSVC OR IS_CLANG_CL) AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||||
if (IS_CLANG_CL)
|
if (NOT MINGW)
|
||||||
# clang-cl reads -Wall as MSVC /Wall, which clang maps to -Weverything. /W4 is
|
|
||||||
# its -Wall -Wextra and, unlike /clang:-Wall, is ordered with the -Wno-* below
|
|
||||||
# instead of after them. The -Wextra-only warnings are dropped again so the set
|
|
||||||
# matches what -Wall gives the GNU/Clang builds.
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
|
|
||||||
add_compile_options(-Wno-unused-parameter -Wno-ignored-qualifiers -Wno-missing-field-initializers)
|
|
||||||
elseif (NOT MINGW)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
||||||
endif ()
|
endif ()
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" )
|
||||||
@@ -1068,10 +1044,6 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
${CMAKE_PREFIX_PATH}/bin/occt/TKXDESTEP.dll
|
${CMAKE_PREFIX_PATH}/bin/occt/TKXDESTEP.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/occt/TKXSBase.dll
|
${CMAKE_PREFIX_PATH}/bin/occt/TKXSBase.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
${CMAKE_PREFIX_PATH}/bin/freetype.dll
|
||||||
${CMAKE_PREFIX_PATH}/bin/avcodec-61.dll
|
|
||||||
${CMAKE_PREFIX_PATH}/bin/swresample-5.dll
|
|
||||||
${CMAKE_PREFIX_PATH}/bin/swscale-8.dll
|
|
||||||
${CMAKE_PREFIX_PATH}/bin/avutil-59.dll
|
|
||||||
DESTINATION ${_out_dir})
|
DESTINATION ${_out_dir})
|
||||||
|
|
||||||
set(${output_dlls}
|
set(${output_dlls}
|
||||||
@@ -1107,110 +1079,15 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
|||||||
${_out_dir}/TKXSBase.dll
|
${_out_dir}/TKXSBase.dll
|
||||||
|
|
||||||
${_out_dir}/freetype.dll
|
${_out_dir}/freetype.dll
|
||||||
${_out_dir}/avcodec-61.dll
|
|
||||||
${_out_dir}/swresample-5.dll
|
|
||||||
${_out_dir}/swscale-8.dll
|
|
||||||
${_out_dir}/avutil-59.dll
|
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(orcaslicer_copy_sos target config postfix output_sos)
|
|
||||||
|
|
||||||
get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
||||||
get_target_property(_alt_out_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
|
|
||||||
|
|
||||||
if (_alt_out_dir)
|
|
||||||
set(_out_dir "${_alt_out_dir}")
|
|
||||||
elseif (_is_multi)
|
|
||||||
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}/${config}")
|
|
||||||
else ()
|
|
||||||
set(_out_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
file(COPY ${CMAKE_PREFIX_PATH}/lib/libavcodec.so
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavcodec.so.61.3.100
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavutil.so
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavutil.so.59
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libavutil.so.59.8.100
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswscale.so
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswscale.so.8
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswscale.so.8.1.100
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswresample.so
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswresample.so.5
|
|
||||||
${CMAKE_PREFIX_PATH}/lib/libswresample.so.5.1.100
|
|
||||||
DESTINATION ${_out_dir})
|
|
||||||
|
|
||||||
set(${output_sos}
|
|
||||||
${_out_dir}/libavcodec.so
|
|
||||||
${_out_dir}/libavcodec.so.61
|
|
||||||
${_out_dir}/libavcodec.so.61.3.100
|
|
||||||
${_out_dir}/libavutil.so
|
|
||||||
${_out_dir}/libavutil.so.59
|
|
||||||
${_out_dir}/libavutil.so.59.8.100
|
|
||||||
${_out_dir}/libswscale.so
|
|
||||||
${_out_dir}/libswscale.so.8
|
|
||||||
${_out_dir}/libswscale.so.8.1.100
|
|
||||||
${_out_dir}/libswresample.so
|
|
||||||
${_out_dir}/libswresample.so.5
|
|
||||||
${_out_dir}/libswresample.so.5.1.100
|
|
||||||
PARENT_SCOPE
|
|
||||||
)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Bundled sources set their own warning flags, and a plain -Wall there means /Wall
|
|
||||||
# (= -Weverything) under clang-cl. Target options are applied after the ones a target
|
|
||||||
# set on itself, so these win. Targets are discovered rather than listed so a newly
|
|
||||||
# bundled library needs no maintenance here.
|
|
||||||
function(orcaslicer_silence_third_party_warnings _dir)
|
|
||||||
get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
|
|
||||||
foreach (_subdir IN LISTS _subdirs)
|
|
||||||
orcaslicer_silence_third_party_warnings("${_subdir}")
|
|
||||||
endforeach ()
|
|
||||||
get_property(_targets DIRECTORY "${_dir}" PROPERTY BUILDSYSTEM_TARGETS)
|
|
||||||
foreach (_target IN LISTS _targets)
|
|
||||||
get_target_property(_type ${_target} TYPE)
|
|
||||||
if (NOT _type STREQUAL "INTERFACE_LIBRARY" AND NOT _type STREQUAL "UTILITY")
|
|
||||||
if (MSVC AND NOT IS_CLANG_CL)
|
|
||||||
# Drop any level the target set for itself, or -w overrides it and cl
|
|
||||||
# reports D9025 once per file.
|
|
||||||
get_target_property(_opts ${_target} COMPILE_OPTIONS)
|
|
||||||
if (_opts)
|
|
||||||
string(REGEX REPLACE "/W[0-4]|/Wall" "" _opts "${_opts}")
|
|
||||||
string(REGEX REPLACE ";;+" ";" _opts "${_opts}")
|
|
||||||
set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${_opts}")
|
|
||||||
endif ()
|
|
||||||
# CMake maps a level into the VS generator's WarningLevel element, while a
|
|
||||||
# bare -w stays on the command line and trips D9025 there, once per file.
|
|
||||||
target_compile_options(${_target} PRIVATE /W0)
|
|
||||||
else ()
|
|
||||||
target_compile_options(${_target} PRIVATE -w)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
endforeach ()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
# libslic3r, OrcaSlicer GUI and the OrcaSlicer executable.
|
# libslic3r, OrcaSlicer GUI and the OrcaSlicer executable.
|
||||||
add_subdirectory(deps_src)
|
add_subdirectory(deps_src)
|
||||||
|
|
||||||
if (NOT SLIC3R_BUNDLED_WARNINGS)
|
|
||||||
orcaslicer_silence_third_party_warnings("${CMAKE_CURRENT_SOURCE_DIR}/deps_src")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Warning level for the targets added below: our sources, plus glad and libvgcode,
|
|
||||||
# which are vendored but live under src/. The deps_src libraries were configured just
|
|
||||||
# above. CMP0092 left MSVC without a default level, so it is set here.
|
|
||||||
if (NOT SLIC3R_WARNINGS)
|
|
||||||
add_compile_options(-w)
|
|
||||||
elseif (MSVC AND NOT IS_CLANG_CL)
|
|
||||||
# /we4715 is C4715, no return from a non-void function, matching the
|
|
||||||
# -Werror=return-type the GNU/Clang builds apply.
|
|
||||||
add_compile_options(/W3 /we4715)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OrcaSlicer_app_gui)
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OrcaSlicer_app_gui)
|
||||||
|
|
||||||
@@ -1222,10 +1099,6 @@ endif()
|
|||||||
|
|
||||||
if(BUILD_TESTS)
|
if(BUILD_TESTS)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
if (NOT SLIC3R_BUNDLED_WARNINGS)
|
|
||||||
# Catch2 is vendored under tests/ and sets its own warning flags too.
|
|
||||||
orcaslicer_silence_third_party_warnings("${CMAKE_CURRENT_SOURCE_DIR}/tests/catch2")
|
|
||||||
endif ()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
@@ -1270,20 +1143,6 @@ else ()
|
|||||||
endif()
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
set(LIBRARY_FILES
|
|
||||||
${LIBDIR_BIN}/libavcodec.so.61
|
|
||||||
${LIBDIR_BIN}/libavcodec.so.61.3.100
|
|
||||||
${LIBDIR_BIN}/libavutil.so.59
|
|
||||||
${LIBDIR_BIN}/libavutil.so.59.8.100
|
|
||||||
${LIBDIR_BIN}/libswresample.so.5
|
|
||||||
${LIBDIR_BIN}/libswresample.so.5.1.100
|
|
||||||
${LIBDIR_BIN}/libswscale.so.8
|
|
||||||
${LIBDIR_BIN}/libswscale.so.8.1.100
|
|
||||||
)
|
|
||||||
install(FILES ${LIBRARY_FILES} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.txt DESTINATION ".")
|
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.txt DESTINATION ".")
|
||||||
configure_file(${LIBDIR}/dev-utils/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/dev-utils/platform/unix/fhs.hpp)
|
configure_file(${LIBDIR}/dev-utils/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/dev-utils/platform/unix/fhs.hpp)
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,6 @@ for %%a in (%*) do (
|
|||||||
if "%%a"=="-x" set USE_NINJA=1
|
if "%%a"=="-x" set USE_NINJA=1
|
||||||
)
|
)
|
||||||
|
|
||||||
@REM Check for clang-cl option (-l). Combined with -x it also builds the deps with
|
|
||||||
@REM clang-cl; on the Visual Studio generator it applies to the slicer only, because
|
|
||||||
@REM the dependency sub-builds have no toolset to inherit and stay on MSVC.
|
|
||||||
set CLANG_ARG=
|
|
||||||
set TOOLSET_ARG=
|
|
||||||
for %%a in (%*) do (
|
|
||||||
if "%%a"=="-l" (
|
|
||||||
set CLANG_ARG=-DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
|
||||||
set TOOLSET_ARG=-T ClangCL
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@REM Check for unit-tests option ("tests")
|
@REM Check for unit-tests option ("tests")
|
||||||
set BUILD_TESTS=OFF
|
set BUILD_TESTS=OFF
|
||||||
for %%a in (%*) do (
|
for %%a in (%*) do (
|
||||||
@@ -139,13 +127,12 @@ if "%1"=="slicer" (
|
|||||||
GOTO :slicer
|
GOTO :slicer
|
||||||
)
|
)
|
||||||
echo "building deps.."
|
echo "building deps.."
|
||||||
if defined CLANG_ARG if "%USE_NINJA%"=="0" echo Note: -l needs -x for the dependencies; building them with MSVC.
|
|
||||||
|
|
||||||
echo on
|
echo on
|
||||||
REM Set minimum CMake policy to avoid <3.5 errors
|
REM Set minimum CMake policy to avoid <3.5 errors
|
||||||
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
if "%USE_NINJA%"=="1" (
|
if "%USE_NINJA%"=="1" (
|
||||||
cmake ../ -G %CMAKE_GENERATOR% %CLANG_ARG% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake ../ -G %CMAKE_GENERATOR% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target deps
|
cmake --build . --config %build_type% --target deps
|
||||||
) else (
|
) else (
|
||||||
cmake ../ -G %CMAKE_GENERATOR% -A %arch% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake ../ -G %CMAKE_GENERATOR% -A %arch% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
@@ -164,10 +151,10 @@ cd %build_dir%
|
|||||||
echo on
|
echo on
|
||||||
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
set CMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
if "%USE_NINJA%"=="1" (
|
if "%USE_NINJA%"=="1" (
|
||||||
cmake .. -G %CMAKE_GENERATOR% %CLANG_ARG% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake .. -G %CMAKE_GENERATOR% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target all
|
cmake --build . --config %build_type% --target all
|
||||||
) else (
|
) else (
|
||||||
cmake .. -G %CMAKE_GENERATOR% -A %arch% %TOOLSET_ARG% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
cmake .. -G %CMAKE_GENERATOR% -A %arch% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type%
|
||||||
cmake --build . --config %build_type% --target ALL_BUILD -- -m
|
cmake --build . --config %build_type% --target ALL_BUILD -- -m
|
||||||
)
|
)
|
||||||
@echo off
|
@echo off
|
||||||
|
|||||||
43
deps/Assimp/Assimp.cmake
vendored
43
deps/Assimp/Assimp.cmake
vendored
@@ -1,43 +0,0 @@
|
|||||||
if(CMAKE_VERSION VERSION_LESS 3.22)
|
|
||||||
set(_assimp_url "https://github.com/assimp/assimp/archive/refs/tags/v5.3.1.tar.gz")
|
|
||||||
set(_assimp_hash "SHA256=a07666be71afe1ad4bc008c2336b7c688aca391271188eb9108d0c6db1be53f1")
|
|
||||||
else()
|
|
||||||
set(_assimp_url "https://github.com/assimp/assimp/archive/refs/tags/v5.4.3.tar.gz")
|
|
||||||
set(_assimp_hash "SHA256=66dfbaee288f2bc43172440a55d0235dfc7bf885dda6435c038e8000e79582cb")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Assimp's bundled zlib (contrib/zlib) is too old to compile against the modern
|
|
||||||
# macOS SDK: its zutil.h takes the classic-Mac branch under TARGET_OS_MAC and
|
|
||||||
# does `#define fdopen(fd,mode) NULL`, which then clobbers the SDK's real
|
|
||||||
# `fdopen` prototype in <stdio.h> and breaks the build. On macOS use the system
|
|
||||||
# zlib (already found by find_package(ZLIB) in deps-unix-common) instead.
|
|
||||||
if(APPLE)
|
|
||||||
set(_assimp_build_zlib "-DASSIMP_BUILD_ZLIB=OFF")
|
|
||||||
else()
|
|
||||||
set(_assimp_build_zlib "-DASSIMP_BUILD_ZLIB=ON")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(Assimp
|
|
||||||
URL ${_assimp_url}
|
|
||||||
URL_HASH ${_assimp_hash}
|
|
||||||
CMAKE_ARGS
|
|
||||||
# Assimp's ccache support sets the global RULE_LAUNCH_COMPILE, which breaks
|
|
||||||
# the Ninja RC rule. The superbuild forwards CMAKE_<LANG>_COMPILER_LAUNCHER.
|
|
||||||
-DASSIMP_BUILD_USE_CCACHE=OFF
|
|
||||||
-DASSIMP_BUILD_TESTS=OFF
|
|
||||||
-DASSIMP_BUILD_SAMPLES=OFF
|
|
||||||
-DASSIMP_BUILD_ASSIMP_TOOLS=OFF
|
|
||||||
-DASSIMP_INSTALL_PDB=OFF
|
|
||||||
-DASSIMP_NO_EXPORT=ON
|
|
||||||
-DASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT=OFF
|
|
||||||
-DASSIMP_BUILD_GLTF_IMPORTER=ON
|
|
||||||
-DASSIMP_BUILD_OBJ_IMPORTER=ON
|
|
||||||
-DASSIMP_BUILD_FBX_IMPORTER=ON
|
|
||||||
${_assimp_build_zlib}
|
|
||||||
-DASSIMP_WARNINGS_AS_ERRORS=OFF
|
|
||||||
-DBUILD_WITH_STATIC_CRT=OFF
|
|
||||||
)
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
add_debug_dep(dep_Assimp)
|
|
||||||
endif ()
|
|
||||||
10
deps/Boost/Boost.cmake
vendored
10
deps/Boost/Boost.cmake
vendored
@@ -24,13 +24,6 @@ if (MSVC AND DEP_DEBUG)
|
|||||||
set(_options "FORWARD_CONFIG")
|
set(_options "FORWARD_CONFIG")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Boost.Container's bundled dlmalloc passes int* where the Win32 Interlocked API
|
|
||||||
# takes volatile long*; cl compiles that with a warning, clang errors out.
|
|
||||||
set(_boost_c_flags_line "")
|
|
||||||
if (MSVC AND CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
|
||||||
set(_boost_c_flags_line "-DCMAKE_C_FLAGS:STRING=-Wno-incompatible-pointer-types")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(Boost
|
orcaslicer_add_cmake_project(Boost
|
||||||
${_options}
|
${_options}
|
||||||
URL "https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.gz"
|
URL "https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.gz"
|
||||||
@@ -45,7 +38,6 @@ orcaslicer_add_cmake_project(Boost
|
|||||||
"${_context_abi_line}"
|
"${_context_abi_line}"
|
||||||
"${_context_arch_line}"
|
"${_context_arch_line}"
|
||||||
"${_context_impl_line}"
|
"${_context_impl_line}"
|
||||||
"${_boost_c_flags_line}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DEP_Boost_DEPENDS ZLIB)
|
set(DEP_Boost_DEPENDS ZLIB)
|
||||||
19
deps/CMakeLists.txt
vendored
19
deps/CMakeLists.txt
vendored
@@ -157,16 +157,8 @@ endif ()
|
|||||||
function(orcaslicer_add_cmake_project projectname)
|
function(orcaslicer_add_cmake_project projectname)
|
||||||
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
|
cmake_parse_arguments(P_ARGS "FORWARD_CONFIG" "INSTALL_DIR;BUILD_COMMAND;INSTALL_COMMAND" "CMAKE_ARGS" ${ARGN})
|
||||||
|
|
||||||
# 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
|
|
||||||
# it the CMAKE_C_COMPILER / CMAKE_CXX_COMPILER forwarded below.
|
|
||||||
set(_dep_msvc_gen FALSE)
|
|
||||||
if (MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
||||||
set(_dep_msvc_gen TRUE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
||||||
if (_is_multi OR _dep_msvc_gen)
|
if (_is_multi OR MSVC)
|
||||||
if (P_ARGS_FORWARD_CONFIG)
|
if (P_ARGS_FORWARD_CONFIG)
|
||||||
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
set(_configs_line -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
|
||||||
elseif (ORCA_INCLUDE_DEBUG_INFO AND NOT DEP_DEBUG)
|
elseif (ORCA_INCLUDE_DEBUG_INFO AND NOT DEP_DEBUG)
|
||||||
@@ -182,7 +174,7 @@ function(orcaslicer_add_cmake_project projectname)
|
|||||||
set(_target_config "Release")
|
set(_target_config "Release")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (_dep_msvc_gen)
|
if (MSVC)
|
||||||
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
|
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
|
||||||
else()
|
else()
|
||||||
set(_gen "")
|
set(_gen "")
|
||||||
@@ -190,7 +182,7 @@ function(orcaslicer_add_cmake_project projectname)
|
|||||||
|
|
||||||
if ($ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
if ($ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
||||||
set(_build_j "") # assume environment will control --build parallel setting
|
set(_build_j "") # assume environment will control --build parallel setting
|
||||||
elseif(_dep_msvc_gen)
|
elseif(MSVC)
|
||||||
set(_build_j "/m")
|
set(_build_j "/m")
|
||||||
else()
|
else()
|
||||||
set(_build_j "-j${NPROC}")
|
set(_build_j "-j${NPROC}")
|
||||||
@@ -375,9 +367,6 @@ include(libnoise/libnoise.cmake)
|
|||||||
|
|
||||||
include(Draco/Draco.cmake)
|
include(Draco/Draco.cmake)
|
||||||
|
|
||||||
include(FFMPEG/FFMPEG.cmake)
|
|
||||||
include(Assimp/Assimp.cmake)
|
|
||||||
|
|
||||||
|
|
||||||
# I *think* 1.1 is used for *just* md5 hashing?
|
# I *think* 1.1 is used for *just* md5 hashing?
|
||||||
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
||||||
@@ -459,8 +448,6 @@ set(_dep_list
|
|||||||
dep_libnoise
|
dep_libnoise
|
||||||
dep_python3
|
dep_python3
|
||||||
dep_wxInspector
|
dep_wxInspector
|
||||||
dep_FFMPEG
|
|
||||||
dep_Assimp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
14
deps/CURL/CURL.cmake
vendored
14
deps/CURL/CURL.cmake
vendored
@@ -56,18 +56,6 @@ else()
|
|||||||
set(_curl_static ON)
|
set(_curl_static ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# curl 7.75's configure probes and code rely on C laxness cl allows but clang
|
|
||||||
# errors on (implicit function declarations, int* vs u_long* in ioctlsocket),
|
|
||||||
# which flips probe results and misconfigures nonblock.c into the AmigaOS
|
|
||||||
# IoctlSocket branch. Relax both diagnostics so the probes behave like cl, and
|
|
||||||
# pin the camel-case probes off since they only "pass" by implicit declaration.
|
|
||||||
set(_curl_c_flags_line "")
|
|
||||||
set(_curl_probe_overrides "")
|
|
||||||
if (MSVC AND CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
|
||||||
set(_curl_c_flags_line "-DCMAKE_C_FLAGS:STRING=-Wno-implicit-function-declaration -Wno-incompatible-pointer-types")
|
|
||||||
set(_curl_probe_overrides -DHAVE_IOCTLSOCKET_CAMEL=0 -DHAVE_IOCTLSOCKET_CAMEL_FIONBIO=0)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(CURL
|
orcaslicer_add_cmake_project(CURL
|
||||||
# GIT_REPOSITORY https://github.com/curl/curl.git
|
# GIT_REPOSITORY https://github.com/curl/curl.git
|
||||||
# GIT_TAG curl-7_75_0
|
# GIT_TAG curl-7_75_0
|
||||||
@@ -81,8 +69,6 @@ orcaslicer_add_cmake_project(CURL
|
|||||||
-DBUILD_CURL_EXE:BOOL=OFF
|
-DBUILD_CURL_EXE:BOOL=OFF
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
-DCURL_STATICLIB=${_curl_static}
|
-DCURL_STATICLIB=${_curl_static}
|
||||||
"${_curl_c_flags_line}"
|
|
||||||
${_curl_probe_overrides}
|
|
||||||
${_curl_platform_flags}
|
${_curl_platform_flags}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
15
deps/Eigen/Eigen.cmake
vendored
15
deps/Eigen/Eigen.cmake
vendored
@@ -7,20 +7,5 @@ orcaslicer_add_cmake_project(Eigen
|
|||||||
URL https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.zip
|
URL https://gitlab.com/libeigen/eigen/-/archive/5.0.1/eigen-5.0.1.zip
|
||||||
URL_HASH SHA256=0dbb1f9e3aaad66f352c03227d8c983f6f0b49e0b07e71a7300f4abcc01aee12
|
URL_HASH SHA256=0dbb1f9e3aaad66f352c03227d8c983f6f0b49e0b07e71a7300f4abcc01aee12
|
||||||
CMAKE_ARGS "${_eigen_extra_flags}"
|
CMAKE_ARGS "${_eigen_extra_flags}"
|
||||||
# Only the headers are consumed here. Everything below builds nothing we
|
|
||||||
# use, and all three enable_language(Fortran): test/CMakeLists.txt:9,
|
|
||||||
# lapack/CMakeLists.txt:6 and blas/testing/CMakeLists.txt:2. They default
|
|
||||||
# to ON because the dependency configures as its own top-level project.
|
|
||||||
#
|
|
||||||
# Whether that probe is harmless depends on what CMake finds. The Visual
|
|
||||||
# Studio generator supports no Fortran, so it finds nothing; clang-cl sits
|
|
||||||
# next to the LLVM toolset's flang, which works. MSVC with Ninja finds
|
|
||||||
# Strawberry Perl's MinGW gfortran instead, which the deps build already
|
|
||||||
# requires for OpenSSL, and hands it the MSVC-style /machine:x64 that
|
|
||||||
# MinGW's ld reads as a missing input file. The configure dies there and
|
|
||||||
# takes the rest of the superbuild with it.
|
|
||||||
-DEIGEN_BUILD_TESTING=OFF
|
|
||||||
-DEIGEN_BUILD_BLAS=OFF
|
|
||||||
-DEIGEN_BUILD_LAPACK=OFF
|
|
||||||
DEPENDS dep_Boost dep_GMP dep_MPFR
|
DEPENDS dep_Boost dep_GMP dep_MPFR
|
||||||
)
|
)
|
||||||
|
|||||||
87
deps/FFMPEG/FFMPEG.cmake
vendored
87
deps/FFMPEG/FFMPEG.cmake
vendored
@@ -1,87 +0,0 @@
|
|||||||
set(_conf_cmd ./configure)
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
set(_source_dir "${CMAKE_BINARY_DIR}/dep_FFMPEG-prefix/src/dep_FFMPEG")
|
|
||||||
|
|
||||||
set(PREBUILD_URL_arm64 "https://github.com/Noisyfox/FFmpeg-Builds-Orca/releases/download/autobuild-2026-07-17-14-28/ffmpeg-n7.0.3-31-g9b6ffd74b5-winarm64-orca-shared-7.0.zip")
|
|
||||||
set(PREBUILD_HASH_arm64 "12f4140279f2f8469885e1b5b2e8be9d788882914c21523cacd56989f3548054")
|
|
||||||
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 "e65916020ddb9ef84b2666dfbcbfc9b1d67f69d15b4a66db53754637bf2d498c")
|
|
||||||
|
|
||||||
ExternalProject_Add(dep_FFMPEG
|
|
||||||
URL ${PREBUILD_URL_${DEPS_ARCH}}
|
|
||||||
URL_HASH SHA256=${PREBUILD_HASH_${DEPS_ARCH}}
|
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/bin" "${DESTDIR}/bin"
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/lib" "${DESTDIR}/lib"
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_source_dir}/include" "${DESTDIR}/include"
|
|
||||||
)
|
|
||||||
|
|
||||||
else ()
|
|
||||||
if (APPLE)
|
|
||||||
set(_minos_cmd
|
|
||||||
"--extra-cflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
|
||||||
"--extra-ldflags=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
|
||||||
)
|
|
||||||
# Static FFmpeg: nothing to bundle into the .app, no rpath handling.
|
|
||||||
# Disable the VideoToolbox/AudioToolbox HW-accel paths: the player decodes
|
|
||||||
# in software (swscale), and the auto-detected HW objects would drag in
|
|
||||||
# system frameworks that the static libs would then depend on.
|
|
||||||
set(_link_cmd --enable-static --disable-shared --disable-videotoolbox --disable-audiotoolbox)
|
|
||||||
if (IS_CROSS_COMPILE)
|
|
||||||
set(_cross_cmd --enable-cross-compile)
|
|
||||||
set(_pic_cmd --enable-pic)
|
|
||||||
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
|
|
||||||
set(_arch_cmd --arch=arm64)
|
|
||||||
set(_cc_cmd "--cc=clang -arch arm64")
|
|
||||||
else()
|
|
||||||
set(_arch_cmd --arch=x86_64)
|
|
||||||
set(_cc_cmd "--cc=clang -arch x86_64")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else ()
|
|
||||||
set(_link_cmd --enable-shared)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(_build_j -j)
|
|
||||||
if(DEFINED ENV{CMAKE_BUILD_PARALLEL_LEVEL})
|
|
||||||
set(_build_j "-j$ENV{CMAKE_BUILD_PARALLEL_LEVEL}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ExternalProject_Add(dep_FFMPEG
|
|
||||||
URL https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.3.tar.gz
|
|
||||||
URL_HASH SHA256=DEEDCABE339165214A3637DF4C86A507AEF0D793CF8774FF68735F4737E8DDBC
|
|
||||||
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/FFMPEG
|
|
||||||
CONFIGURE_COMMAND ${_conf_cmd}
|
|
||||||
${_cross_cmd}
|
|
||||||
${_pic_cmd}
|
|
||||||
${_arch_cmd}
|
|
||||||
${_cc_cmd}
|
|
||||||
"--prefix=${DESTDIR}"
|
|
||||||
${_link_cmd}
|
|
||||||
${_minos_cmd}
|
|
||||||
--disable-doc
|
|
||||||
--enable-small
|
|
||||||
--disable-outdevs
|
|
||||||
--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*
|
|
||||||
--disable-protocols
|
|
||||||
--enable-protocol=file,fd,pipe,rtp,udp
|
|
||||||
--disable-muxers
|
|
||||||
--enable-muxer=rtp
|
|
||||||
--disable-encoders
|
|
||||||
--disable-decoders
|
|
||||||
--enable-decoder=*aac*,h264*,mp3*,mjpeg,rv*
|
|
||||||
--disable-demuxers
|
|
||||||
--enable-demuxer=h264,mp3,mov
|
|
||||||
--disable-zlib
|
|
||||||
--disable-avdevice
|
|
||||||
BUILD_IN_SOURCE ON
|
|
||||||
BUILD_COMMAND make ${_build_j}
|
|
||||||
INSTALL_COMMAND make install
|
|
||||||
)
|
|
||||||
|
|
||||||
endif()
|
|
||||||
43
deps/OCCT/0001-OCCT-fix.patch
vendored
43
deps/OCCT/0001-OCCT-fix.patch
vendored
@@ -1,20 +1,3 @@
|
|||||||
diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake
|
|
||||||
index 00000000..00000001 100644
|
|
||||||
--- a/adm/cmake/occt_defs_flags.cmake
|
|
||||||
+++ b/adm/cmake/occt_defs_flags.cmake
|
|
||||||
@@ -134,7 +134,11 @@
|
|
||||||
set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
|
|
||||||
endif()
|
|
||||||
# Optimize size of binaries
|
|
||||||
- set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
+ # clang-cl reports the Clang compiler ID, and OCCT builds shared on Windows,
|
|
||||||
+ # where the MSVC-style linker gets this flag as an argument it does not know.
|
|
||||||
+ if (NOT WIN32)
|
|
||||||
+ set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
+ endif()
|
|
||||||
elseif(MINGW)
|
|
||||||
add_definitions(-D_WIN32_WINNT=0x0601)
|
|
||||||
# _WIN32_WINNT=0x0601 (use Windows 7 SDK)
|
|
||||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
index d98acc0f..28eb8eb4 100644
|
index d98acc0f..28eb8eb4 100644
|
||||||
--- a/CMakeLists.txt
|
--- a/CMakeLists.txt
|
||||||
@@ -185,32 +168,6 @@ index d98acc0f..28eb8eb4 100644
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if (BUILD_SAMPLES_QT)
|
if (BUILD_SAMPLES_QT)
|
||||||
diff --git a/adm/cmake/occt_macros.cmake b/adm/cmake/occt_macros.cmake
|
|
||||||
index 224c96b1..8c94a1c5 100644
|
|
||||||
--- a/adm/cmake/occt_macros.cmake
|
|
||||||
+++ b/adm/cmake/occt_macros.cmake
|
|
||||||
@@ -608,7 +608,7 @@ macro (OCCT_INSERT_CODE_FOR_TARGET)
|
|
||||||
install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\")
|
|
||||||
set (OCCT_INSTALL_BIN_LETTER \"\")
|
|
||||||
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\")
|
|
||||||
- set (OCCT_INSTALL_BIN_LETTER \"i\")
|
|
||||||
+ set (OCCT_INSTALL_BIN_LETTER \"\")
|
|
||||||
elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
|
|
||||||
set (OCCT_INSTALL_BIN_LETTER \"d\")
|
|
||||||
endif()")
|
|
||||||
diff --git a/adm/cmake/occt_toolkit.cmake b/adm/cmake/occt_toolkit.cmake
|
|
||||||
index 550e0e2f..7ac1a3b8 100644
|
|
||||||
--- a/adm/cmake/occt_toolkit.cmake
|
|
||||||
+++ b/adm/cmake/occt_toolkit.cmake
|
|
||||||
@@ -241,7 +241,7 @@
|
|
||||||
else()
|
|
||||||
set (aReleasePdbConf)
|
|
||||||
endif()
|
|
||||||
- install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin\${OCCT_INSTALL_BIN_LETTER}/${PROJECT_NAME}.pdb
|
|
||||||
+ install (FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
|
|
||||||
CONFIGURATIONS Debug ${aReleasePdbConf} RelWithDebInfo
|
|
||||||
DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}")
|
|
||||||
endif()
|
|
||||||
diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx
|
diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx
|
||||||
index 5ae9899f..0a17372b 100644
|
index 5ae9899f..0a17372b 100644
|
||||||
--- a/src/Font/Font_FTFont.cxx
|
--- a/src/Font/Font_FTFont.cxx
|
||||||
|
|||||||
16
deps/OpenSSL/OpenSSL.cmake
vendored
16
deps/OpenSSL/OpenSSL.cmake
vendored
@@ -17,20 +17,10 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(_openssl_msvc_env CC=cl CXX=cl RC=rc CL=/FS)
|
set(_conf_cmd perl Configure )
|
||||||
# OpenSSL's perl Configure honors the CC environment variable, but the
|
|
||||||
# VC-WIN64A makefile only works with cl (an unquoted clang-cl path with
|
|
||||||
# spaces, e.g. exported by CLion, silently produces no .obj files and the
|
|
||||||
# lib step fails with LNK1181). Pin the upstream toolchain.
|
|
||||||
# Keep rc.exe resolved from the MSVC developer environment as well. The
|
|
||||||
# absolute Windows SDK path contains spaces and OpenSSL 1.1.1 writes it to
|
|
||||||
# the generated nmake file without quoting, which skips .res generation.
|
|
||||||
# /FS serializes access to OpenSSL's shared generated PDB when cl is
|
|
||||||
# driven through nmake from a Ninja configure step.
|
|
||||||
set(_conf_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} perl Configure )
|
|
||||||
set(_cross_comp_prefix_line "")
|
set(_cross_comp_prefix_line "")
|
||||||
set(_make_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} nmake)
|
set(_make_cmd nmake)
|
||||||
set(_install_cmd ${CMAKE_COMMAND} -E env ${_openssl_msvc_env} nmake install_sw )
|
set(_install_cmd nmake install_sw )
|
||||||
else()
|
else()
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(_conf_cmd export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && ./Configure -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
set(_conf_cmd export MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} && ./Configure -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||||
|
|||||||
24
deps/wxInspector/wxInspector.cmake
vendored
24
deps/wxInspector/wxInspector.cmake
vendored
@@ -1,26 +1,3 @@
|
|||||||
# wxInspector finds wxWidgets through CMake's FindwxWidgets module, which only
|
|
||||||
# searches lib/vc*_lib because _WX_TOOL is hardcoded to "vc". A superbuild driven
|
|
||||||
# by clang-cl installs wxWidgets into lib/clang_x64_lib, so hand the module the
|
|
||||||
# directory wxWidgets actually used, derived the same way wxWidgetsConfig.cmake
|
|
||||||
# derives it.
|
|
||||||
set(_wxinspector_wx_hints "")
|
|
||||||
if (MSVC)
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|
||||||
set(_wx_compiler_prefix "clang")
|
|
||||||
else ()
|
|
||||||
set(_wx_compiler_prefix "vc")
|
|
||||||
endif ()
|
|
||||||
set(_wx_arch_suffix "")
|
|
||||||
if (CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
|
|
||||||
string(TOLOWER "_${CMAKE_GENERATOR_PLATFORM}" _wx_arch_suffix)
|
|
||||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_wx_arch_suffix "_x64")
|
|
||||||
endif ()
|
|
||||||
set(_wxinspector_wx_hints
|
|
||||||
"-DwxWidgets_ROOT_DIR=${DESTDIR}"
|
|
||||||
"-DwxWidgets_LIB_DIR=${DESTDIR}/lib/${_wx_compiler_prefix}${_wx_arch_suffix}_lib")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
orcaslicer_add_cmake_project(
|
orcaslicer_add_cmake_project(
|
||||||
wxInspector
|
wxInspector
|
||||||
URL https://github.com/Noisyfox/wxInspector/archive/refs/tags/v1.0.0.zip
|
URL https://github.com/Noisyfox/wxInspector/archive/refs/tags/v1.0.0.zip
|
||||||
@@ -29,7 +6,6 @@ orcaslicer_add_cmake_project(
|
|||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_CXX_FLAGS="-DwxDEBUG_LEVEL=0"
|
-DCMAKE_CXX_FLAGS="-DwxDEBUG_LEVEL=0"
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
${_wxinspector_wx_hints}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
28
deps/wxWidgets/0001-Clang-CL-fix.patch
vendored
Normal file
28
deps/wxWidgets/0001-Clang-CL-fix.patch
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
build/cmake/wxWidgetsConfig.cmake.in | 10 +++++++++-
|
||||||
|
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in
|
||||||
|
index 1a83f36..70ad8a4 100644
|
||||||
|
--- a/build/cmake/wxWidgetsConfig.cmake.in
|
||||||
|
+++ b/build/cmake/wxWidgetsConfig.cmake.in
|
||||||
|
@@ -58,7 +58,16 @@ if(WIN32_MSVC_NAMING)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
-include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||||
|
+ if (CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64" OR CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(ARM64|arm64|aarch64)$")
|
||||||
|
+ set(_wx_clang_msvc_lib_dir "vc_arm64_lib")
|
||||||
|
+ else()
|
||||||
|
+ set(_wx_clang_msvc_lib_dir "vc_x64_lib")
|
||||||
|
+ endif()
|
||||||
|
+ include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/${_wx_clang_msvc_lib_dir}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
+else()
|
||||||
|
+ include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
+endif()
|
||||||
|
|
||||||
|
macro(wx_inherit_property source dest name)
|
||||||
|
# property name without _<CONFIG>
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
1
deps/wxWidgets/wxWidgets.cmake
vendored
1
deps/wxWidgets/wxWidgets.cmake
vendored
@@ -28,6 +28,7 @@ orcaslicer_add_cmake_project(
|
|||||||
GIT_SHALLOW ON
|
GIT_SHALLOW ON
|
||||||
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
|
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
|
||||||
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
|
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
|
||||||
|
PATCH_COMMAND git apply --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-Clang-CL-fix.patch
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DwxBUILD_PRECOMP=ON
|
-DwxBUILD_PRECOMP=ON
|
||||||
${_wx_toolkit}
|
${_wx_toolkit}
|
||||||
|
|||||||
211
doc/developer-reference/filament_id.md
Normal file
211
doc/developer-reference/filament_id.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# Filament IDs (`filament_id`)
|
||||||
|
|
||||||
|
`filament_id` identifies a **material family**: one commercial product line = one id, shared by
|
||||||
|
all of that material's per-printer / per-nozzle variants. Devices use it to match a physical
|
||||||
|
spool or tray to a filament preset. It is never per-color, per-printer, per-nozzle, or
|
||||||
|
per-preset (per-preset identity is `setting_id`).
|
||||||
|
|
||||||
|
This page is the rule for authoring `filament_id` in system profiles
|
||||||
|
(`resources/profiles/**`). CI enforces everything below; the short version is:
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **Never write a `filament_id` value by hand.** New families get their id from
|
||||||
|
> `python scripts/assign_filament_ids.py`; existing families already have one — inherit it.
|
||||||
|
|
||||||
|
## Who consumes the id
|
||||||
|
|
||||||
|
Every device integration funnels a tray material id (`tray_info_idx`) through the same
|
||||||
|
matching pipeline (`PresetBundle::sync_ams_list` and friends):
|
||||||
|
|
||||||
|
| Ecosystem | Where the id comes from |
|
||||||
|
| --- | --- |
|
||||||
|
| Bambu AMS | device side (RFID / user tray setting) — the `GF*` catalog |
|
||||||
|
| Qidi box | built from device enums (`QD_*`); needs an exactly matching visible preset |
|
||||||
|
| Creality CFS | runtime brand/type scoring returns the current preset's id |
|
||||||
|
| Klipper (AFC / Happy Hare) | runtime lookup by filament type |
|
||||||
|
| Snapmaker | runtime color/vendor/type match |
|
||||||
|
|
||||||
|
Tray-to-preset matching is printer-scoped, but **several consumers match globally by id alone,
|
||||||
|
first hit wins**: tray display names, `filament_is_support`, vitrification warnings, and
|
||||||
|
multi-nozzle filament grouping in the slicing pipeline. Two *different* materials sharing one
|
||||||
|
id feed wrong data to those consumers even when the presets live in different vendors — so
|
||||||
|
cross-material id sharing is never safe. Within one printer, duplicate ids silently break AMS
|
||||||
|
matching (first match wins, the tray-edit dialog hides the second preset); the profile
|
||||||
|
validator's `-f` check rejects this.
|
||||||
|
|
||||||
|
## Do I need a new id? The one-question test
|
||||||
|
|
||||||
|
> **Would a user consider this a different spool product than anything already in the tree?**
|
||||||
|
|
||||||
|
Different polymer, different sub-brand (Basic / Matte / Silk / HF), fiber-filled sibling, or a
|
||||||
|
second selectable diameter → **new family, new id**. The same spool tuned for another printer
|
||||||
|
or nozzle → **join the existing family** (inherit its `@base`, write no id key). Tuning a
|
||||||
|
generic material → **join the OrcaFilamentLibrary family** (inherit `Generic X @System`, keep
|
||||||
|
the `Generic X` base name, write no id key).
|
||||||
|
|
||||||
|
| Situation | id |
|
||||||
|
| --- | --- |
|
||||||
|
| Per-printer / per-nozzle variant of an existing material | same id (inherit, never write the key) |
|
||||||
|
| Sub-brand or product line (PLA vs PLA Matte vs PLA Silk vs PLA HF) | new id each |
|
||||||
|
| Color | never a new id |
|
||||||
|
| Second diameter selectable on the same printer (1.75 + 2.85) | sibling family, new id |
|
||||||
|
| "High-speed" tuned for a *different printer model* | same id (it is a printer variant) |
|
||||||
|
| "High-speed" selectable *alongside* the normal preset on one printer | new id (it is a product line) |
|
||||||
|
|
||||||
|
## Structure rules
|
||||||
|
|
||||||
|
1. **Only family roots carry the key.** Root presets (any preset *not* marked
|
||||||
|
`"instantiation": "true"`, typically `<Family> @base` with `"instantiation": "false"`)
|
||||||
|
declare `filament_id`; instantiated variants inherit a root and never
|
||||||
|
write the key. A family may have several roots (e.g. per-series bases) — all of them must
|
||||||
|
declare the *identical* id.
|
||||||
|
2. **The family name is the base name**: the preset name with everything from the first
|
||||||
|
(optionally space-preceded) `@` stripped. `MyBrand PLA @Orca 3D Fuse1` and `MyBrand PLA@HS`
|
||||||
|
both belong to family `MyBrand PLA`.
|
||||||
|
3. **Within a family, variants' `compatible_printers` are pairwise disjoint** — per printer
|
||||||
|
preset, at most one compatible instantiated preset per id. The C++ validator (`-f`)
|
||||||
|
enforces this.
|
||||||
|
4. **Generics belong to OrcaFilamentLibrary.** A vendor tuning a generic material inherits
|
||||||
|
`Generic X @System`, keeps the `Generic X` base name (that alias is what hides the library
|
||||||
|
preset on your printers), sets a non-empty `compatible_printers`, and writes no id key.
|
||||||
|
A vendor-*branded* filament never rides a generic family id.
|
||||||
|
5. **Ids follow the product identity.** The id is a pure function of the product triple
|
||||||
|
`(filament_vendor, filament_type, family name)` — correcting any of them re-mints the id
|
||||||
|
**by design**, and `--update-snapshot` records the old id in the shipped succession ledger
|
||||||
|
with its successor so device trays, calibration records, and user presets keep resolving
|
||||||
|
(`renamed_from` still gates preset-*name* compatibility as before). A shipped id is never
|
||||||
|
recycled for a different material: retired ids are blocked forever.
|
||||||
|
|
||||||
|
## Minting — nobody invents ids
|
||||||
|
|
||||||
|
New ids are deterministic, computed exactly like the `setting_id` precedent
|
||||||
|
(`scripts/assign_vendor_setting_ids.py`):
|
||||||
|
|
||||||
|
```text
|
||||||
|
FILAMENT_ID_NAMESPACE = uuid5(setting-id NAMESPACE, "filament_id")
|
||||||
|
= c4d3ff49-4c32-5534-a3e3-00894157ab97
|
||||||
|
filament_id = "OF" + base62_6( uuid5(FILAMENT_ID_NAMESPACE,
|
||||||
|
"filament_product/<filament_vendor>/<filament_type>/<family_name>") )
|
||||||
|
```
|
||||||
|
|
||||||
|
`base62_6` is the low 6 base62 digits (alphabet `0-9A-Za-z`) of the UUID taken as a big-endian
|
||||||
|
integer, most-significant digit first — 8 chars total, within the AMS length limit. The triple
|
||||||
|
comes from the family root's *flattened* config: `<filament_vendor>` is the filament
|
||||||
|
**manufacturer** (`"Polymaker"`, or `"Generic"` for generics — never the printer brand),
|
||||||
|
`<filament_type>` the material type, `<family_name>` the root's base name; the two config
|
||||||
|
values are inheritable list options and the first element counts. The key contains no bundle
|
||||||
|
name, so the same product mints the same id in every bundle — hoisting a family into
|
||||||
|
OrcaFilamentLibrary never changes its id. On the rare collision with any existing or retired
|
||||||
|
id, the minter salts the input (`…/1`, `…/2`, …) until free and the result is frozen in the
|
||||||
|
file. Example: `Polymaker/PLA/PolyLite PLA` mints `OF5CgdDq`.
|
||||||
|
|
||||||
|
Workflow for a new family:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Author the family with NO filament_id key anywhere.
|
||||||
|
python scripts/assign_filament_ids.py # 2. mint + insert ids into the family root(s)
|
||||||
|
python scripts/assign_filament_ids.py --update-snapshot # 3. record the new claims in the ledger
|
||||||
|
python scripts/assign_filament_ids.py --check # 4. verify — the same checks CI runs
|
||||||
|
# 5. Commit the profile edits together with scripts/filament_id_snapshot.json.
|
||||||
|
```
|
||||||
|
|
||||||
|
`--mint "filament_vendor/filament_type/family_name"` prints the id a triple would mint without
|
||||||
|
touching anything. The default run is idempotent and never rewrites a valid existing id.
|
||||||
|
Maintenance modes (normally only used by id migrations): `--remint VENDOR` re-derives a
|
||||||
|
vendor's declared ids from their triples (a declaration already equal to a salt iteration
|
||||||
|
of its own triple is conformant and left alone — deliberate salt splits keeping two
|
||||||
|
presets of one product apart for per-printer AMS matching survive),
|
||||||
|
`--drop-redundant-ids VENDOR` deletes declarations
|
||||||
|
that merely re-declare an inherited OFL id, `--add-hint "OLD=NEW"` records a cross-island
|
||||||
|
succession hint, and `--retire "OLD=NEW"` records succession for a shipped non-island id
|
||||||
|
that vanished while another declarer kept it alive (lineage the automatic claim vote can no
|
||||||
|
longer see).
|
||||||
|
|
||||||
|
If you skip the tooling, CI fails and prints the remedy: the expected id for your family, and
|
||||||
|
the instruction to run `python scripts/assign_filament_ids.py --update-snapshot` and commit
|
||||||
|
the resulting diff.
|
||||||
|
|
||||||
|
## Reserved namespaces — never mint or hand-write into
|
||||||
|
|
||||||
|
| Space | Owner | Rule |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `GF*` | Bambu AMS/RFID catalog | BBL vendor only; byte-copies elsewhere only where the snapshot already sanctions them |
|
||||||
|
| `QD_*` | Qidi device protocol | frozen device contract; Qidi vendor only |
|
||||||
|
| `P` + 7 hex chars (case-insensitive), `"null"` | user-created custom filaments (`CreatePresetsDialog.cpp`) | never appears in system profiles |
|
||||||
|
| every already-shipped id | grandfather snapshot | frozen as-is; new claims need maintainer sign-off |
|
||||||
|
| every retired id | `resources/profiles/retired_filament_ids.json` | never used again, for anything |
|
||||||
|
|
||||||
|
## The succession ledger
|
||||||
|
|
||||||
|
`resources/profiles/retired_filament_ids.json` ships with the app. Each retired id maps to
|
||||||
|
`{"claims": [...], "successor": <id|null>}` — successor chains are followed to the live end —
|
||||||
|
and a `hints` map carries the same forwarding for ids Orca cannot retire because another
|
||||||
|
island owns them (e.g. a `GF*` id whose material also exists as an OFL family). The client
|
||||||
|
consults the ledger **only on resolution miss** (AMS tray sync, tray-id type lookup,
|
||||||
|
calibration history, filament-id preset lookup): a live preset always wins first, so BBL
|
||||||
|
installs resolve `GF*` natively and behavior is unchanged wherever the raw id still exists.
|
||||||
|
This is what makes identity-driven re-mints (structure rule 5) safe: the old id keeps
|
||||||
|
resolving to the family's current preset instead of degrading to a `Generic <type>` fallback.
|
||||||
|
The file is append-only and maintained exclusively by `--update-snapshot` / `--add-hint` /
|
||||||
|
`--retire`.
|
||||||
|
|
||||||
|
## How CI enforces this
|
||||||
|
|
||||||
|
Profile CI (`check_profiles.yml` → `scripts/orca_extra_profile_check.py`) runs
|
||||||
|
`check_filament_ids()` tree-wide. Its ground truth is
|
||||||
|
**`scripts/filament_id_snapshot.json` — the sanctioned state**: the id state derived from the
|
||||||
|
tree must equal the snapshot exactly, in both directions. Any change to the id landscape
|
||||||
|
therefore surfaces as a diff to that file, and **that snapshot diff is what maintainers review
|
||||||
|
and gate in a PR**. Never edit the snapshot by hand — `--update-snapshot` regenerates it
|
||||||
|
deterministically (running it twice changes nothing).
|
||||||
|
|
||||||
|
The checks, in brief:
|
||||||
|
|
||||||
|
- **Format** — every id is either in the snapshot, `OF` + 6 base62 chars, BBL's, or Qidi `QD_*`.
|
||||||
|
- **Snapshot equality** — tree claims == snapshot claims **and** tree triples == snapshot
|
||||||
|
triples, both directions: any `filament_vendor`/`filament_type`/family-name change surfaces
|
||||||
|
as a snapshot diff.
|
||||||
|
- **Mint conformance** — a non-grandfathered `OF*` id must equal the mint (or a salt
|
||||||
|
iteration) of its declarer's product triple; the error prints the expected id.
|
||||||
|
- **Retired reuse** — any tree id present in `resources/profiles/retired_filament_ids.json` is an error.
|
||||||
|
Ids that fully vanish from the tree are appended there by `--update-snapshot`; the file is
|
||||||
|
**append-only**.
|
||||||
|
- **Alias hygiene** — any vendor preset riding an OFL family id must keep the library
|
||||||
|
preset's base name, a non-empty `compatible_printers`, and no own id key (structure rule 4);
|
||||||
|
the error names the rename as the cause.
|
||||||
|
- **Triple integrity** — every declarer outside the BBL/`QD_*` islands must resolve a
|
||||||
|
non-empty `filament_vendor` and `filament_type` (generics use `"Generic"`), and all
|
||||||
|
declarers of one family within a bundle must agree on the triple.
|
||||||
|
- **Succession integrity** — retired successor chains terminate at a live id (or null) with
|
||||||
|
no cycles; `hints` keys are live, island-owned ids.
|
||||||
|
- **Reserved namespaces** — `GF*` outside BBL, `QD_*` outside Qidi, `P<7-hex>` or `null`
|
||||||
|
anywhere, unless that exact claim is grandfathered in the snapshot.
|
||||||
|
- **Structure** — no `filament_id` key on instantiated presets; no declared-vs-inherited id
|
||||||
|
drift; every instantiated system filament must resolve an effective id through its
|
||||||
|
`inherits` chain (an id-less one is a hard load error in C++ that discards the whole vendor
|
||||||
|
bundle).
|
||||||
|
|
||||||
|
Sharing a **reserved-catalog** id with a new family or vendor (e.g. shipping a Bambu-cataloged
|
||||||
|
product under another vendor with its authentic `GF*` id) is refused by `--update-snapshot`
|
||||||
|
unless you pass `--allow-shared-catalog` — and it still lands in the snapshot diff for
|
||||||
|
maintainer review. Any other new sharing of an existing id is caught by the mint-conformance
|
||||||
|
check instead.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
- **A new color of an existing product?** Never a new id — colors are not families.
|
||||||
|
- **A second diameter (1.75 mm and 2.85 mm) of the same product?** A sibling family with its
|
||||||
|
own id: two diameters are separately selectable spool products.
|
||||||
|
- **A high-speed tune of an existing material for another printer model?** Same family:
|
||||||
|
inherit the family's root, write no id key.
|
||||||
|
- **A tuned generic ("our profile for Generic PLA")?** Inherit `Generic PLA @System`, keep the
|
||||||
|
`Generic PLA` base name, set `compatible_printers`, write no id key.
|
||||||
|
- **I need to rename a family (or fix its `filament_vendor`/`filament_type`).** Add
|
||||||
|
`renamed_from` for the name, run `--remint <Vendor>` then `--update-snapshot`: the id
|
||||||
|
re-derives from the corrected identity and the old id lands in the succession ledger
|
||||||
|
pointing at the new one. Commit the profile, snapshot, and ledger diffs together.
|
||||||
|
- **CI says my family needs an id.** Run `python scripts/assign_filament_ids.py`, then
|
||||||
|
`--update-snapshot`, and commit both diffs. Do not type an id by hand.
|
||||||
|
|
||||||
|
For general profile authoring, see the profile development guide on the
|
||||||
|
[OrcaSlicer wiki](https://www.orcaslicer.com/wiki).
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
# macOS FFmpeg Media Player Implementation Plan
|
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
||||||
|
|
||||||
**Goal:** Make macOS use the same FFmpeg-based media player (`wxMediaCtrl3` + `AVVideoDecoder`) as Windows/Linux, linking the static FFmpeg libraries from the deps build, and remove the old `wxMediaCtrl2.mm` BambuPlayer-based player.
|
|
||||||
|
|
||||||
**Architecture:** The new player is platform-neutral C++ already used on Linux/Windows. Enabling it on macOS is pure build wiring: compile `wxMediaCtrl3.cpp` + `AVVideoDecoder.cpp` on macOS, drop the `__WXMAC__` alias that redirects `wxMediaCtrl3` to the old `wxMediaCtrl2`, and link static FFmpeg (`libavcodec.a`/`libswscale.a`/`libavutil.a`) from the deps install. The Bambu stream API is dlsym'd at runtime from the network plugin (`libBambuSource.dylib`), which already exports it — no plugin changes needed. Rendering reuses the existing `wxImage` → `DrawBitmap` paint path (same as Linux).
|
|
||||||
|
|
||||||
**Tech Stack:** C++17, wxWidgets, CMake, FFmpeg 7.0.3 (libavcodec/libswscale/libavutil), macOS (Xcode generator), `deps/` ExternalProject build system.
|
|
||||||
|
|
||||||
## Global Constraints
|
|
||||||
|
|
||||||
- Branch: `dev/ffmpeg-player-macos`. Commit after every task.
|
|
||||||
- **Linux and Windows builds must not change** — the FFmpeg deps flag change is guarded by `APPLE`; Linux keeps `--enable-shared`, Windows keeps its prebuilt DLL zips.
|
|
||||||
- Static FFmpeg only on macOS: deps produce `libavcodec.a`/`libswscale.a`/`libavutil.a`; the app links those explicitly — the app binary must have **no** `libav*` dylib references (`otool -L` check).
|
|
||||||
- Follow existing code style: PascalCase classes, snake_case functions, C++17.
|
|
||||||
- No changes to `StatusPanel.cpp`, `MediaPlayCtrl.*`, or the BambuTunnel interface — the app already creates `wxMediaCtrl3` and uses only its public interface.
|
|
||||||
- The player cannot be unit-tested (hardware/plugin-dependent GUI code); verification is build-level, link-level, and manual runtime on a Mac.
|
|
||||||
- `localization/i18n/list.txt` references only `wxMediaCtrl2.cpp` (Win/Linux, stays) — no translation-list changes needed.
|
|
||||||
- Build dirs on the dev machine: main app = `build_arm64/` (Xcode generator, multi-config), deps = `deps/build/arm64/` (Unix Makefiles). App target name: `OrcaSlicer`. Substitute your own configured build dirs where noted.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 1: Enable wxMediaCtrl3 on macOS and link static FFmpeg
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `src/slic3r/GUI/wxMediaCtrl3.h` (lines 18–22: the `#ifdef __WXMAC__` alias branch)
|
|
||||||
- Modify: `src/slic3r/GUI/wxMediaCtrl3.cpp:13` (uncomment the event define)
|
|
||||||
- Modify: `src/slic3r/GUI/wxMediaCtrl2.cpp:101` (remove the event define)
|
|
||||||
- Modify: `src/slic3r/CMakeLists.txt` (APPLE source list ~lines 779–792; FFmpeg link block ~lines 905–910)
|
|
||||||
|
|
||||||
**Interfaces:**
|
|
||||||
- Consumes: nothing new (all classes already exist).
|
|
||||||
- Produces: `wxMediaCtrl3` class compiled on macOS with the same interface as Linux/Windows — `Load(wxURI)`, `Play()`, `Stop()`, `SetIdleImage(wxString)`, `GetState()`, `GetLastError()`, `GetVideoSize()`, event `EVT_MEDIA_CTRL_STAT` defined once in the lib (from `wxMediaCtrl3.cpp`).
|
|
||||||
|
|
||||||
- [ ] **Step 1: Remove the macOS alias in wxMediaCtrl3.h**
|
|
||||||
|
|
||||||
Current (lines 16–23 of `src/slic3r/GUI/wxMediaCtrl3.h`):
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, int height);
|
|
||||||
|
|
||||||
#ifdef __WXMAC__
|
|
||||||
|
|
||||||
#include "wxMediaCtrl2.h"
|
|
||||||
#define wxMediaCtrl3 wxMediaCtrl2
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define BAMBU_DYNAMIC
|
|
||||||
```
|
|
||||||
|
|
||||||
New:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void wxMediaCtrl_OnSize(wxWindow * ctrl, wxSize const & videoSize, int width, int height);
|
|
||||||
|
|
||||||
#define BAMBU_DYNAMIC
|
|
||||||
```
|
|
||||||
|
|
||||||
Also remove the matching `#endif` that closed the `#else` branch (the one before the final `#endif /* wxMediaCtrl3_h */`), so the file's `#ifndef`/`#endif` guard pair stays balanced.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Move the EVT_MEDIA_CTRL_STAT definition into wxMediaCtrl3.cpp**
|
|
||||||
|
|
||||||
In `src/slic3r/GUI/wxMediaCtrl3.cpp:13`, uncomment:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
//wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
|
||||||
```
|
|
||||||
|
|
||||||
In `src/slic3r/GUI/wxMediaCtrl2.cpp:101`, delete:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent);
|
|
||||||
```
|
|
||||||
|
|
||||||
(One definition total in the lib — `MediaPlayCtrl.cpp:59` binds this event on the media ctrl.)
|
|
||||||
|
|
||||||
- [ ] **Step 3: Update the APPLE source list in CMakeLists.txt**
|
|
||||||
|
|
||||||
In `src/slic3r/CMakeLists.txt`, the APPLE branch (currently compiles `wxMediaCtrl2.mm`, which becomes dead on macOS):
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
GUI/wxMediaCtrl2.mm
|
|
||||||
GUI/wxMediaCtrl2.h
|
|
||||||
GUI/wxMediaCtrl3.h
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
GUI/AVVideoDecoder.cpp
|
|
||||||
GUI/AVVideoDecoder.hpp
|
|
||||||
GUI/wxMediaCtrl3.cpp
|
|
||||||
GUI/wxMediaCtrl3.h
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
(The `else ()` branch — Win/Linux — stays exactly as it is.)
|
|
||||||
|
|
||||||
- [ ] **Step 4: Link static FFmpeg on macOS**
|
|
||||||
|
|
||||||
In `src/slic3r/CMakeLists.txt`, the FFmpeg block (currently `if (NOT APPLE)`):
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
if (NOT APPLE)
|
|
||||||
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
|
||||||
libavcodec
|
|
||||||
libswscale
|
|
||||||
libavutil
|
|
||||||
)
|
|
||||||
target_link_libraries(libslic3r_gui PkgConfig::LIBAV)
|
|
||||||
endif()
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
if (APPLE)
|
|
||||||
# Static FFmpeg from the deps install: nothing to bundle into the .app,
|
|
||||||
# no rpath/install_name handling. Order matters: avcodec -> swscale -> avutil.
|
|
||||||
find_library(LIBAVCODEC_LIBRARY NAMES libavcodec.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
|
||||||
find_library(LIBSWSCALE_LIBRARY NAMES libswscale.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
|
||||||
find_library(LIBAVUTIL_LIBRARY NAMES libavutil.a PATHS ${CMAKE_PREFIX_PATH}/lib NO_DEFAULT_PATH)
|
|
||||||
target_link_libraries(libslic3r_gui ${LIBAVCODEC_LIBRARY} ${LIBSWSCALE_LIBRARY} ${LIBAVUTIL_LIBRARY})
|
|
||||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_PREFIX_PATH}/include)
|
|
||||||
else ()
|
|
||||||
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
|
|
||||||
libavcodec
|
|
||||||
libswscale
|
|
||||||
libavutil
|
|
||||||
)
|
|
||||||
target_link_libraries(libslic3r_gui PkgConfig::LIBAV)
|
|
||||||
endif()
|
|
||||||
```
|
|
||||||
|
|
||||||
The deps install (`${CMAKE_PREFIX_PATH}/lib`) already contains the three `.a` files from the existing arm64 deps build — no deps rebuild needed for this task.
|
|
||||||
|
|
||||||
- [ ] **Step 5: Reconfigure and build the app**
|
|
||||||
|
|
||||||
Run (Xcode generator; `cmake` re-runs automatically on build):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: configure succeeds (no `pkg_check_modules` errors on macOS, `find_library` finds all three `.a` files), compile succeeds (`wxMediaCtrl3.cpp` and `AVVideoDecoder.cpp` compile on macOS without changes), link succeeds.
|
|
||||||
|
|
||||||
If CMake complains that `wxMediaCtrl3.h` is included but not in the source list or similar IDE-only warnings — ignore; headers in the list are cosmetic.
|
|
||||||
|
|
||||||
- [ ] **Step 6: Verify no dynamic FFmpeg dependency**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
otool -L build_arm64/src/RelWithDebInfo/OrcaSlicer.app/Contents/MacOS/OrcaSlicer | grep -i "libav" || echo "OK: no dynamic FFmpeg"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: prints `OK: no dynamic FFmpeg` (empty grep output). This is the whole point of static linking — nothing to bundle into the `.app`.
|
|
||||||
|
|
||||||
- [ ] **Step 7: Quick sanity — macOS unit tests still pass**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ctest --test-dir build_arm64/tests/libslic3r --output-on-failure
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: passes (add `-C RelWithDebInfo` if the multi-config generator requires it). If no tests were built in this build dir, build target `tests` first (`cmake --build build_arm64 --config RelWithDebInfo --target tests`).
|
|
||||||
|
|
||||||
- [ ] **Step 8: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add src/slic3r/CMakeLists.txt src/slic3r/GUI/wxMediaCtrl3.h src/slic3r/GUI/wxMediaCtrl3.cpp src/slic3r/GUI/wxMediaCtrl2.cpp
|
|
||||||
git commit -m "feat: use FFmpeg media player on macOS with static FFmpeg"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 2: Static-only FFmpeg in the macOS deps build
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: `deps/FFMPEG/FFMPEG.cmake` (non-MSVC branch, APPLE section and CONFIGURE_COMMAND)
|
|
||||||
|
|
||||||
**Interfaces:**
|
|
||||||
- Consumes: nothing.
|
|
||||||
- Produces: a deps install on macOS containing only `libavcodec.a`, `libswscale.a`, `libavutil.a` (+ headers) — no `libav*` dylibs, so no bundling/rpath machinery is ever needed on macOS. Linux and Windows output are unchanged.
|
|
||||||
|
|
||||||
- [ ] **Step 1: Add the static flag variable**
|
|
||||||
|
|
||||||
In `deps/FFMPEG/FFMPEG.cmake`, inside the non-MSVC `else ()` branch, in the existing `if (APPLE)` block:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
if (APPLE)
|
|
||||||
set(_minos_cmd
|
|
||||||
"CFLAGS=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
|
||||||
"LDFLAGS=-mmacosx-version-min=${DEP_OSX_TARGET}"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
add after the `_minos_cmd` set:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
# Static FFmpeg: nothing to bundle into the .app, no rpath handling.
|
|
||||||
# Shared flags must come AFTER --enable-shared below so they win.
|
|
||||||
set(_link_cmd --enable-static --disable-shared)
|
|
||||||
```
|
|
||||||
|
|
||||||
and add a matching `else ()` after the `if (IS_CROSS_COMPILE) ... endif()` block inside that `if (APPLE)`, so non-Apple Unix keeps shared:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
else ()
|
|
||||||
set(_link_cmd --enable-shared)
|
|
||||||
endif ()
|
|
||||||
```
|
|
||||||
|
|
||||||
(If the existing `if (IS_CROSS_COMPILE)` block is the last thing inside `if (APPLE)`, the new `else ()` closes the `if (APPLE)` itself.)
|
|
||||||
|
|
||||||
- [ ] **Step 2: Use the variable in CONFIGURE_COMMAND**
|
|
||||||
|
|
||||||
In the `ExternalProject_Add(dep_FFMPEG ...)` configure command:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
"--prefix=${DESTDIR}"
|
|
||||||
--enable-shared
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
"--prefix=${DESTDIR}"
|
|
||||||
--enable-shared
|
|
||||||
${_link_cmd}
|
|
||||||
```
|
|
||||||
|
|
||||||
Order matters: `--enable-shared` comes first, then `--enable-static --disable-shared` (APPLE) or `--enable-shared` (Linux) — the last flag wins in FFmpeg configure.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Rebuild the FFmpeg dep (slow — several minutes, run in background)**
|
|
||||||
|
|
||||||
The changed CONFIGURE_COMMAND invalidates the ExternalProject stamp, so this re-configures and rebuilds FFmpeg:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake --build deps/build/arm64 --target dep_FFMPEG
|
|
||||||
```
|
|
||||||
|
|
||||||
For a fully clean static-only check (removes the previous shared build tree, which can leave stale `.dylib` files behind in the in-source build):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
rm -rf deps/build/arm64/dep_FFMPEG-prefix
|
|
||||||
cmake --build deps/build/arm64 --target dep_FFMPEG
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 4: Verify the artifacts**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls deps/build/arm64/dep_FFMPEG-prefix/src/dep_FFMPEG/libavcodec/*.a
|
|
||||||
ls deps/build/arm64/dep_FFMPEG-prefix/src/dep_FFMPEG/libavcodec/*.dylib 2>/dev/null || echo "OK: no dylibs"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: `libavcodec.a` present, second command prints `OK: no dylibs`. Check `libavutil` and `libswscale` the same way.
|
|
||||||
|
|
||||||
- [ ] **Step 5: Verify the app still links against the static libs**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
|
||||||
otool -L build_arm64/src/RelWithDebInfo/OrcaSlicer.app/Contents/MacOS/OrcaSlicer | grep -i "libav" || echo "OK: no dynamic FFmpeg"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: build succeeds, `OK: no dynamic FFmpeg`.
|
|
||||||
|
|
||||||
- [ ] **Step 6: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add deps/FFMPEG/FFMPEG.cmake
|
|
||||||
git commit -m "build: build static-only FFmpeg for macOS deps"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 3: Remove the old macOS player
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Delete: `src/slic3r/GUI/wxMediaCtrl2.mm`
|
|
||||||
- Delete: `src/slic3r/GUI/BambuPlayer/BambuPlayer.h` (and the empty `BambuPlayer/` dir)
|
|
||||||
- Modify: `src/slic3r/GUI/wxMediaCtrl2.h` (remove the `#ifdef __WXMAC__` section, lines 22–60)
|
|
||||||
|
|
||||||
**Interfaces:**
|
|
||||||
- Consumes: Task 1 (macOS no longer references `wxMediaCtrl2` — nothing includes `wxMediaCtrl2.h` on macOS anymore; `wxMediaCtrl2` is never instantiated on any platform).
|
|
||||||
- Produces: a clean tree where the old BambuPlayer-based player is gone from macOS. The `BambuPlayer` ObjC class itself remains inside the network plugin (external prebuilt binary) — only the GUI-side consumer is removed.
|
|
||||||
|
|
||||||
- [ ] **Step 1: Delete the old player files**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git rm src/slic3r/GUI/wxMediaCtrl2.mm
|
|
||||||
git rm src/slic3r/GUI/BambuPlayer/BambuPlayer.h
|
|
||||||
rmdir src/slic3r/GUI/BambuPlayer 2>/dev/null || true
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 2: Strip the __WXMAC__ section from wxMediaCtrl2.h**
|
|
||||||
|
|
||||||
In `src/slic3r/GUI/wxMediaCtrl2.h`, remove the entire macOS branch of the `#ifdef __WXMAC__` guard — from `#ifdef __WXMAC__` (line 22) through the closing `};` of the mac class (line 60), and the `#else` marker — leaving only the non-mac `class wxMediaCtrl2 : public wxMediaCtrl { ... };` definition followed by the final `#endif /* wxMediaCtrl2_h */`. The resulting file keeps its `#ifndef`/`#endif` include guard pair balanced.
|
|
||||||
|
|
||||||
The file stays on disk because Win/Linux compile `wxMediaCtrl2.cpp`, which includes it.
|
|
||||||
|
|
||||||
- [ ] **Step 3: Grep for leftover references**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
grep -rn "wxMediaCtrl2.mm\|BambuPlayer/BambuPlayer.h\|BambuPlayer" src/slic3r --include="*.cpp" --include="*.h" --include="*.mm" --include="*.txt"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: no hits in `src/slic3r/GUI` (ignore `localization/i18n/list.txt:196`, which lists the Win/Linux `wxMediaCtrl2.cpp` and stays).
|
|
||||||
|
|
||||||
- [ ] **Step 4: Rebuild the app**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake --build build_arm64 --config RelWithDebInfo --target OrcaSlicer
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: configure + compile + link succeed with the deleted files gone.
|
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add -A src/slic3r/GUI
|
|
||||||
git commit -m "refactor: remove old BambuPlayer-based media player from macOS"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 4: Runtime verification on hardware
|
|
||||||
|
|
||||||
**Files:** none — manual verification.
|
|
||||||
|
|
||||||
**Interfaces:** consumes all prior tasks. Final gate: the new player must actually stream on a Mac.
|
|
||||||
|
|
||||||
- [ ] **Step 1: Launch the freshly built app**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
open build_arm64/src/RelWithDebInfo/OrcaSlicer.app
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: app launches normally; no crash in the network/device subsystem.
|
|
||||||
|
|
||||||
- [ ] **Step 2: Load the network plugin and open the Device tab**
|
|
||||||
|
|
||||||
Log in / ensure the network plugin (`libBambuSource.dylib`) loads, select a printer, open the Device tab (camera monitoring panel).
|
|
||||||
|
|
||||||
Expected: the camera preview area shows the idle image initially (no crash — this exercises `wxMediaCtrl3::SetIdleImage` and the `wxImage` load path on macOS for the first time).
|
|
||||||
|
|
||||||
- [ ] **Step 3: Start the stream and watch it render**
|
|
||||||
|
|
||||||
Click play / wait for `MediaPlayCtrl` to start the stream.
|
|
||||||
|
|
||||||
Expected: live video renders in the panel. Check the console/log output (`BOOST_LOG` goes to the terminal if run from it, or check the log file):
|
|
||||||
- `stat_log ...` lines appear (the `EVT_MEDIA_CTRL_STAT` path is live — proves the Bambu C API dlsym worked from `libBambuSource.dylib`);
|
|
||||||
- no repeated decode/error messages like `AVVideoDecoder: ...` or `can not find function ...` (proves `StaticBambuLib::get` resolved all Bambu functions);
|
|
||||||
- Stop/Play toggle works; idle image reappears on stop;
|
|
||||||
- window resize keeps aspect ratio (exercises `DoSetSize`/`adjust_frame_size`/`paintEvent`).
|
|
||||||
|
|
||||||
- [ ] **Step 4: Confirm the old player is really gone**
|
|
||||||
|
|
||||||
Expected: nothing in the logs references `BambuPlayer` (the ObjC class is no longer dlsym'd); the video path is entirely `wxMediaCtrl3` + `AVVideoDecoder`.
|
|
||||||
|
|
||||||
If a printer is unavailable, at minimum verify Steps 1–2 (launch + idle image) and note in the PR that live-stream verification needs hardware.
|
|
||||||
|
|
||||||
- [ ] **Step 5: Final review pass**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git log --oneline -6
|
|
||||||
git show --stat HEAD # and each of the three task commits
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: the last 4 commits are the design doc + the 3 implementation tasks (each task commit touches only its listed files). Review the diff for scope: no Linux/Windows changes beyond the two `EVT_MEDIA_CTRL_STAT` lines in Task 1, no `StatusPanel`/`MediaPlayCtrl` changes.
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
# FFmpeg Media Player for macOS — Design
|
|
||||||
|
|
||||||
Date: 2026-08-14
|
|
||||||
Branch: `dev/ffmpeg-player-macos`
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
|
|
||||||
The branch's new FFmpeg-based media player (`wxMediaCtrl3` + `AVVideoDecoder`) is used on
|
|
||||||
Windows and Linux, but macOS still runs the old player: `wxMediaCtrl2.mm`, an ObjC
|
|
||||||
`BambuPlayer` class dlsym'd from the Bambu network plugin that renders via CALayer.
|
|
||||||
On macOS, `wxMediaCtrl3` is currently aliased to `wxMediaCtrl2` and FFmpeg is not linked
|
|
||||||
into the app at all.
|
|
||||||
|
|
||||||
Goal: make macOS use the same FFmpeg player as Windows/Linux, linking the **static**
|
|
||||||
FFmpeg libraries from the deps build instead of dynamic ones.
|
|
||||||
|
|
||||||
## Current state (verified)
|
|
||||||
|
|
||||||
- New player (Win/Linux): `GUI/wxMediaCtrl3.cpp` + `GUI/AVVideoDecoder.cpp`. Decodes with
|
|
||||||
FFmpeg (libavcodec/libswscale/libavutil), renders frames into `wxImage` (non-Windows) /
|
|
||||||
`wxBitmap` (Windows) drawn in a `paintEvent`, feeds via the `Bambu_*` C API
|
|
||||||
(`BambuTunnel.h`, `BAMBU_DYNAMIC`) dlsym'd from the network plugin through
|
|
||||||
`StaticBambuLib::get()` (`GUI/Printer/PrinterFileSystem.cpp`, compiled on all platforms).
|
|
||||||
- Old player (macOS): `GUI/wxMediaCtrl2.mm` uses the ObjC `BambuPlayer` class found via
|
|
||||||
`dlsym(module, "OBJC_CLASS_$_BambuPlayer")` in `libBambuSource.dylib`.
|
|
||||||
- The macOS network plugin `libBambuSource.dylib` already exports the full Bambu C API
|
|
||||||
(verified with `nm`), so the new player needs zero plugin changes.
|
|
||||||
- FFmpeg linking in `src/slic3r/CMakeLists.txt` is guarded by `if (NOT APPLE)` —
|
|
||||||
macOS currently does not link FFmpeg.
|
|
||||||
- `deps/FFMPEG/FFMPEG.cmake`: non-MSVC branch builds FFmpeg from source with
|
|
||||||
`--enable-shared`. The existing arm64 deps build on the dev machine happened to be
|
|
||||||
configured with both static and shared enabled, so `libavcodec.a` / `libswscale.a` /
|
|
||||||
`libavutil.a` are already present at
|
|
||||||
`deps/build/arm64/OrcaSlicer_dep/usr/local/lib/`.
|
|
||||||
- `EVT_MEDIA_CTRL_STAT` is `wxDEFINE_EVENT`'d in `wxMediaCtrl2.cpp` (Win/Linux) and
|
|
||||||
`wxMediaCtrl2.mm` (macOS); the define in `wxMediaCtrl3.cpp` is commented out.
|
|
||||||
- `wxMediaCtrl2` is never instantiated anywhere on any platform — dead code.
|
|
||||||
- `StatusPanel` already creates `wxMediaCtrl3`; `MediaPlayCtrl` only uses the
|
|
||||||
`wxMediaCtrl3` interface (`Load/Play/Stop/GetState/GetVideoSize/GetLastError/SetIdleImage`),
|
|
||||||
so no UI-side changes are needed.
|
|
||||||
|
|
||||||
## Approach (approved)
|
|
||||||
|
|
||||||
**Reuse the shared player on macOS.** Compile the existing `wxMediaCtrl3.cpp` +
|
|
||||||
`AVVideoDecoder.cpp` on macOS so all three platforms run one implementation.
|
|
||||||
Rendering uses the existing `wxImage` → `DrawBitmap` paint path, identical to Linux.
|
|
||||||
Known trade-off: frames are scaled to the widget's logical (1x) size, so Retina is
|
|
||||||
slightly soft compared to the old CALayer player. Accepted for now; a Retina-aware
|
|
||||||
scaling follow-up is possible later.
|
|
||||||
|
|
||||||
Rejected alternative: a native CGImage/CALayer renderer for macOS — faster and
|
|
||||||
Retina-crisp, but adds a second render implementation to maintain.
|
|
||||||
|
|
||||||
## Changes
|
|
||||||
|
|
||||||
### 1. Enable the FFmpeg player on macOS (source)
|
|
||||||
|
|
||||||
- `GUI/wxMediaCtrl3.h`: remove the `#ifdef __WXMAC__` branch (lines 18–22) that aliases
|
|
||||||
`wxMediaCtrl3` → `wxMediaCtrl2`. macOS then compiles the real `wxMediaCtrl3` class,
|
|
||||||
including the `BAMBU_DYNAMIC` BambuTunnel path used on Linux.
|
|
||||||
- Event symbol fix: move `wxDEFINE_EVENT(EVT_MEDIA_CTRL_STAT, wxCommandEvent)` into
|
|
||||||
`wxMediaCtrl3.cpp` (uncomment the existing line) and remove it from
|
|
||||||
`wxMediaCtrl2.cpp`. One definition total in the lib; all three platforms resolve it.
|
|
||||||
|
|
||||||
### 2. Static FFmpeg linking (deps + app)
|
|
||||||
|
|
||||||
- `deps/FFMPEG/FFMPEG.cmake`: in the non-MSVC branch, pass
|
|
||||||
`--disable-shared --enable-static` when `APPLE`. Linux keeps `--enable-shared`;
|
|
||||||
Windows keeps its prebuilt shared DLL zips. Fresh macOS deps builds install only
|
|
||||||
`libavcodec.a` / `libswscale.a` / `libavutil.a` — no dylibs to bundle, no
|
|
||||||
rpath/install_name handling. (The existing local arm64 deps build already contains
|
|
||||||
the `.a` files, so no deps rebuild is strictly needed to try the change locally,
|
|
||||||
but a fresh CI deps build must produce them.)
|
|
||||||
- `src/slic3r/CMakeLists.txt`:
|
|
||||||
- APPLE branch of `SLIC3R_GUI_SOURCES`: add `GUI/wxMediaCtrl3.cpp`,
|
|
||||||
`GUI/wxMediaCtrl3.h`, `GUI/AVVideoDecoder.cpp`, `GUI/AVVideoDecoder.hpp`;
|
|
||||||
remove `GUI/wxMediaCtrl2.mm` and `GUI/wxMediaCtrl2.h` (the `.h` stays on
|
|
||||||
disk for the Win/Linux build of `wxMediaCtrl2.cpp`, but nothing on macOS
|
|
||||||
includes it after this change).
|
|
||||||
- Add an APPLE mirror of the `NOT APPLE` FFmpeg block: `find_library` for
|
|
||||||
`libavcodec.a`, `libswscale.a`, `libavutil.a` under `${CMAKE_PREFIX_PATH}/lib`
|
|
||||||
with `NO_DEFAULT_PATH`, link them (order avcodec → swscale → avutil), and add
|
|
||||||
`${CMAKE_PREFIX_PATH}/include` as a SYSTEM include directory. Deps are built with
|
|
||||||
`--disable-zlib` and no external codecs, so the three static libs link cleanly.
|
|
||||||
|
|
||||||
### 3. Remove the old player
|
|
||||||
|
|
||||||
- Delete `GUI/wxMediaCtrl2.mm` and `GUI/BambuPlayer/BambuPlayer.h` (header used only
|
|
||||||
by the `.mm`; the real `BambuPlayer` lives inside the network plugin).
|
|
||||||
- Remove the now-dead `__WXMAC__` section of `GUI/wxMediaCtrl2.h`.
|
|
||||||
- `wxMediaCtrl2.cpp` (Win/Linux) stays in the build as-is (dead but harmless; out of
|
|
||||||
scope to remove on this branch).
|
|
||||||
|
|
||||||
### 4. Verification
|
|
||||||
|
|
||||||
- Build on macOS: `cmake --build build_arm64` (or `build/arm64`).
|
|
||||||
- Confirm no dynamic FFmpeg dependency: `otool -L` on the app binary shows no `libav*`
|
|
||||||
dylib references.
|
|
||||||
- Runtime: with the network plugin loaded, the Device tab camera preview streams via
|
|
||||||
the FFmpeg player (check the device page / `MediaPlayCtrl`).
|
|
||||||
- macOS `ctest` still passes — static linking means no test-executable `.so` copying
|
|
||||||
hacks (unlike the Linux shared-lib setup).
|
|
||||||
|
|
||||||
## Out of scope
|
|
||||||
|
|
||||||
- Linux (shared libs, AppImage/flatpak bundling) and Windows (prebuilt DLL zips)
|
|
||||||
keep their current FFmpeg setup.
|
|
||||||
- Retina-aware frame scaling / native CGImage rendering (follow-up if visual quality
|
|
||||||
is judged insufficient).
|
|
||||||
- Audio streaming (neither player plays audio in this UI path).
|
|
||||||
1029
filament_id_plan.html
Normal file
1029
filament_id_plan.html
Normal file
File diff suppressed because it is too large
Load Diff
397
filament_id_plan.md
Normal file
397
filament_id_plan.md
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
# filament_id: generation rule + system-profile fix plan
|
||||||
|
|
||||||
|
Follow-up to PR #14459 (commit `c2e91cb8`, validator `-f` / `check_duplicate_filament_subtypes`).
|
||||||
|
Goal 1: a filament_id generation rule for all vendors. Goal 2: an error-pattern taxonomy and a
|
||||||
|
migration plan that removes every ambiguous filament_id, without touching Bambu (BBL) profiles.
|
||||||
|
|
||||||
|
All numbers below are reproducible: a loader-faithful audit script re-derives the validator's
|
||||||
|
output **exactly** (1256/1256 printer-level errors, 356 logical collision groups, 30 vendors).
|
||||||
|
Every code claim was verified against source with `file:line` references.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Executive summary
|
||||||
|
|
||||||
|
- `filament_id` is a **material-family id**: one id per commercial product line, shared by all
|
||||||
|
of that material's per-printer/per-nozzle variants. Matching is always `(filament_id +
|
||||||
|
printer compatibility)`; the invariant from PR #14459 is *per printer preset, at most one
|
||||||
|
compatible instantiated filament preset per id*.
|
||||||
|
- Every modern device ecosystem funnels through this id — not just Bambu AMS: Qidi box,
|
||||||
|
Creality CFS, Klipper AFC/Happy Hare, Snapmaker all emit/consume `tray_info_idx`
|
||||||
|
(see §1). Several consumers match **globally, without printer scoping**, so two *different
|
||||||
|
materials* sharing one id is unsafe even across vendors.
|
||||||
|
- **Proposed rule (§3):** deterministic, script-minted ids — `OF` + 6 base62 chars from
|
||||||
|
`uuid5(vendor + family)`, declared **only on family-root (`@base`) presets**; variants inherit.
|
||||||
|
Nobody ever invents an id by hand; CI prints the expected id when one is missing. Existing
|
||||||
|
unambiguous ids are grandfathered and frozen; `GF*` (Bambu), `QD_*` (Qidi device protocol),
|
||||||
|
and `P<7-hex>` (user custom presets) are reserved namespaces that must never be minted into.
|
||||||
|
This was selected by an adversarial design/judge process over a registry-grammar alternative
|
||||||
|
and a structure-only alternative, then stress-tested; amendments from that stress test are
|
||||||
|
folded in below.
|
||||||
|
- **Migration (§5):** fresh-never-reused ids only, family-atomic, names never changed. This is
|
||||||
|
provably safe: user presets re-derive `filament_id` from their parent on every load
|
||||||
|
(`Preset.cpp:1658-1682`), 3mf resolves presets by name+config (`Preset.cpp:2490-2576`), and
|
||||||
|
Klipper/Creality/Snapmaker derive tray ids at runtime. One PR per vendor; CI's `-f` scope
|
||||||
|
ratchets per vendor until tree-wide.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. How filament_id actually works (verified)
|
||||||
|
|
||||||
|
### Consumers and scoping
|
||||||
|
|
||||||
|
All device integrations converge on one pipeline: device/agent sets `tray_info_idx` →
|
||||||
|
`DevAmsTray.setting_id` → `Sidebar::build_filament_ams_list` (`Plater.cpp:3423-3493`) →
|
||||||
|
`PresetBundle::sync_ams_list` / `get_ams_cobox_infos` (`PresetBundle.cpp:3112-3308`) match it
|
||||||
|
against filament presets.
|
||||||
|
|
||||||
|
| Ecosystem | Where the id comes from | Effect of changing a system id |
|
||||||
|
|---|---|---|
|
||||||
|
| BBL AMS | device-side (RFID / user tray setting), `DeviceManager.cpp:3823+` | breaks matching — **frozen by mandate** |
|
||||||
|
| Qidi box | built from device enums: `"QD_" + series + "_" + vendor + "_" + type_idx`, `QidiPrinterAgent.cpp:146-152`; needs an exactly-matching visible preset | breaks matching — **`QD_*` ids are a frozen device contract** |
|
||||||
|
| Creality CFS | runtime brand/type scoring returns current preset's id (`CrealityPrintAgent.cpp:46-118`) | invisible |
|
||||||
|
| Klipper (AFC / Happy Hare) | runtime `filament_id_by_type` (`MoonrakerPrinterAgent.cpp:808,936`) | invisible |
|
||||||
|
| Snapmaker | runtime color/vendor/type match (`SnapmakerPrinterAgent.cpp:22-64`) | invisible |
|
||||||
|
|
||||||
|
Matching is printer-scoped (`is_compatible`) in the AMS sync paths and all printer agents — this
|
||||||
|
is what makes the per-printer invariant sufficient there. But several consumers match
|
||||||
|
**globally by id alone**, first match wins:
|
||||||
|
|
||||||
|
- `get_filament_by_filament_id("")` — tray display name, `filament_is_support`,
|
||||||
|
`temperature_vitrification` warnings (`PresetBundle.cpp:690-733`; callers
|
||||||
|
`DevFilaBlackList.cpp:70`, `Plater.cpp:3453`, `SelectMachine.cpp:3560,4623`). The code
|
||||||
|
comment at `:695` states the assumption outright: an id maps to ONE material globally.
|
||||||
|
- `MachineObject::setting_id_to_type` (`DeviceManager.cpp:2538`), calibration-history name
|
||||||
|
lookup (`CaliHistoryDialog.cpp:62`), custom-filament cloud grouping (`Preset.cpp:2839`).
|
||||||
|
- The slicing pipeline itself: multi-nozzle filament grouping merges project filaments whose
|
||||||
|
`(filament_id, color)` match (`FilamentGroup.cpp:513-528` via `ToolOrdering.cpp:1164`).
|
||||||
|
|
||||||
|
**Consequence:** within one printer, duplicate ids break AMS matching (silent first-wins,
|
||||||
|
`find_if` at `PresetBundle.cpp:3132/3233`; the AMS tray-edit dialog even *hides* the second
|
||||||
|
preset, `AMSMaterialsSetting.cpp:894-897`). Across vendors, the same id on *different
|
||||||
|
materials* feeds wrong name/type/vitrification data to the global consumers and can merge
|
||||||
|
different materials into one nozzle group. Same id on the *same* material (e.g. `GFL99` =
|
||||||
|
Generic PLA in 29 vendors) is comparatively benign — those attributes agree.
|
||||||
|
|
||||||
|
### Identity machinery
|
||||||
|
|
||||||
|
- **Effective id resolution** (`PresetBundle.cpp:4842-5080`): own `filament_id` key → vendor
|
||||||
|
`filament_id_maps[inherits]` (file order in the vendor index is load-bearing) →
|
||||||
|
OrcaFilamentLibrary base-bundle map. An instantiated system filament that resolves *no* id is
|
||||||
|
a hard load error that discards the whole vendor bundle (`:5072`, throw at `:5141-5147`) —
|
||||||
|
so "missing id" cannot ship; what looked like 26 id-less Flashforge presets actually resolve
|
||||||
|
to OFL's `OGFL99`/`OGFG99` through the base-bundle fallback.
|
||||||
|
- **Two family-identity systems exist**: `filament_id` (device matching) and `alias` (name
|
||||||
|
before `" @"`). OFL shadowing is keyed on **alias**: `update_library_profile_excluded_from`
|
||||||
|
(`Preset.cpp:3684-3714`) hides an OFL preset (empty `compatible_printers` = compatible with
|
||||||
|
everything, `Preset.cpp:837`) on printers claimed by a same-alias vendor preset. There is
|
||||||
|
**no id-based shadowing**. A vendor preset that tunes an OFL generic but renames it
|
||||||
|
re-exposes the OFL preset and creates a live duplicate. The rule below aligns the two
|
||||||
|
systems: one family = one alias = one id.
|
||||||
|
- **User-custom id space**: user-created filaments get `"P" + md5(name)[0:7]` (8 chars,
|
||||||
|
`CreatePresetsDialog.cpp:533`), or *reuse a system id* when the base name matches an existing
|
||||||
|
preset (`:510-528`). `"null"` is used as a sentinel. Root user presets persist their id
|
||||||
|
forever; inheriting user presets re-derive it on every load.
|
||||||
|
|
||||||
|
## 2. The id landscape today
|
||||||
|
|
||||||
|
**Bambu's grammar** (derived from all 1970 BBL instantiated presets; BBL is internally clean —
|
||||||
|
181 id definitions, 0 duplicates):
|
||||||
|
|
||||||
|
- Classic `GF<LETTER><NN>`: letter = family (A Bambu-PLA, B ABS/ASA, C PC, G PETG/PCTG,
|
||||||
|
L third-party+generic PLA, N PA/PPA, P PP/PE, R misc, S support, T PET/PPS, U TPU).
|
||||||
|
Numbers: 00-49 branded ascending, 50-59 fiber-filled, 60-70 partner block, **95-99 generic
|
||||||
|
tier descending** (99 = the family's plain generic).
|
||||||
|
- Brand partners `GF<BRANDCODE><NNN>`: GFPM Polymaker, GFOT Overture, GFSNL SUNLU, GFNMK
|
||||||
|
Numakers. One id per product line; never per color, never per printer/nozzle/diameter.
|
||||||
|
- Structural rule: the id lives on the material's `@base`; every variant inherits it.
|
||||||
|
- Hardcoded in C++: `GFS00/GFS01` support check (`DeviceManager.cpp:4739`), per-family PA
|
||||||
|
defaults `GFU01/03/04` (`CalibUtils.cpp:54-75`) — `GF*` is Bambu's space, byte-frozen.
|
||||||
|
|
||||||
|
**Everything else is ad-hoc, invented by individual contributors and imitated** (full history
|
||||||
|
in §7): OFL's `O`-prefix mirrors (`OGFA00`; introduced 2025-03-31, commit `8c4a65e3e1`),
|
||||||
|
Tiertime/Afinia `GFx##_##` per-printer-line suffixes, SeeMeCNC per-nozzle ids, LH `LHF_pla`,
|
||||||
|
LONGER 11-char pseudo-GF ids, Anycubic ids **with spaces** (`"GFPLA Silk"`), Prusa ids that are
|
||||||
|
entire preset names (36 chars), and mass copy-paste of `GFL99/GFB99/GFG99` onto everything
|
||||||
|
(Qidi alone stamped `GFB99` into **317 files** across all materials). The only guidance that
|
||||||
|
ever existed was "≤ 8 chars" — enforced for BBL only (`orca_extra_profile_check.py:292,320`),
|
||||||
|
and the (now removed) profile wiki's own examples *taught* id copy-pasting.
|
||||||
|
|
||||||
|
**The damage, quantified** (audit reproduces validator 1256/1256):
|
||||||
|
|
||||||
|
| Ledger | Count |
|
||||||
|
|---|---|
|
||||||
|
| Within-vendor logical collision groups (validator `-f`) | **356** across 30 vendors (1256 printer-level errors) |
|
||||||
|
| OFL×vendor same-id groups (validator blind spot) | 42 — of which **10 are live** (alias mismatch defeats shadowing); 32 already neutralized by alias shadowing |
|
||||||
|
| OFL-internal: one id, several materials, visible on every printer | **16 ids** (e.g. `OEPLAB00` = 14 distinct Elegoo PLA products; `OGFL06` = eSUN PLA-Marble *and* Fiberon PETG-ESD) |
|
||||||
|
| Cross-vendor semantic collisions (same id, different materials) | **67 ids** (e.g. `GFU99` also covers a PEBA; Anycubic minted `GFL95` "Matte" ≠ Bambu `GFL95` "High Speed") |
|
||||||
|
|
||||||
|
Worst vendors by groups: Qidi 97, Flashforge 69, Elegoo 37, Prusa 31, Cubicon 17,
|
||||||
|
Anycubic 14, InfiMech 14, Snapmaker 11, Artillery 8, Creality 8, FlyingBear 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. The rule (proposal)
|
||||||
|
|
||||||
|
Selected by a 3-design / 2-judge adversarial process (deterministic-mint won over
|
||||||
|
registry-grammar and structure-only on ambiguity-prevention, contributor simplicity, and
|
||||||
|
enforceability), then hardened by three adversarial review passes. This section is written as
|
||||||
|
the future authoring doc.
|
||||||
|
|
||||||
|
### 3.1 The one-question test
|
||||||
|
|
||||||
|
> **Would a user consider this a different spool product than anything already in the tree?**
|
||||||
|
> Different polymer, different sub-brand (Basic / Matte / Silk / HF), fiber-filled sibling, or
|
||||||
|
> a second selectable diameter → **new family, new id**. The same spool tuned for another
|
||||||
|
> printer or nozzle → **join the existing family** (inherit its `@base`, no id key). Tuning a
|
||||||
|
> generic material → **join the OFL family** (inherit the `Generic X @System` preset, keep the
|
||||||
|
> `Generic X` base name, add no id).
|
||||||
|
|
||||||
|
Same id / new id at a glance:
|
||||||
|
|
||||||
|
| Situation | id |
|
||||||
|
|---|---|
|
||||||
|
| Per-printer / per-nozzle variant of an existing material | same id (inherit, never write the key) |
|
||||||
|
| Sub-brand or product line (PLA vs PLA Matte vs PLA Silk vs PLA HF) | new id each |
|
||||||
|
| Color | never a new id |
|
||||||
|
| Second diameter selectable on the same printer (1.75 + 2.85) | sibling family, new id |
|
||||||
|
| "High-speed" tuned for a *different printer model* | same id (it's a printer variant) |
|
||||||
|
| "High-speed" selectable *alongside* the normal preset on one printer | new id (it's a product line) |
|
||||||
|
|
||||||
|
### 3.2 Structure
|
||||||
|
|
||||||
|
1. **One family = one root.** Each material family has root preset(s) (`instantiation:false`,
|
||||||
|
typically `<Family> @base`) and only roots carry the `filament_id` key. Instantiated
|
||||||
|
variants inherit a root and never write `filament_id`. (A family MAY have several roots —
|
||||||
|
e.g. Qidi's per-series bases — but they must all declare the *identical* id.)
|
||||||
|
2. **Family identity is declared, not name-derived.** Default: the family name is the
|
||||||
|
instantiated presets' base name (name with `/\s?@.*$/` stripped — note *optional* space,
|
||||||
|
because `Afinia PLA@HS`-style names exist). When vendor naming makes that ambiguous, the
|
||||||
|
root declares an explicit `"filament_family"` key that overrides derivation; tooling errors
|
||||||
|
loudly when a root's derived family differs from its children's.
|
||||||
|
3. **Within a family, variants' `compatible_printers` are pairwise disjoint** — that *is* the
|
||||||
|
PR #14459 invariant, enforced by the validator.
|
||||||
|
4. **Generics belong to OFL.** A vendor tuning `Generic PLA` inherits
|
||||||
|
`Generic PLA @System`, keeps the `Generic PLA` base name/alias (so alias shadowing excludes
|
||||||
|
the OFL preset on those printers, `Preset.cpp:3684`), sets non-empty `compatible_printers`,
|
||||||
|
and writes no id. A vendor-*branded* filament never rides a generic family id.
|
||||||
|
5. **Ids are immutable once shipped.** Renaming a family does not change its id (use
|
||||||
|
`renamed_from`). No id is ever recycled for a different material — stale ids live on in
|
||||||
|
user root presets and old 3mfs, and a recycled id would silently match the wrong material.
|
||||||
|
|
||||||
|
### 3.3 Minting — nobody invents ids
|
||||||
|
|
||||||
|
New family ids are computed, exactly like the `setting_id` precedent
|
||||||
|
(`scripts/assign_vendor_setting_ids.py` / `Slic3r::generate_preset_setting_id`):
|
||||||
|
|
||||||
|
```
|
||||||
|
filament_id = "OF" + base62_6( uuid5( NAMESPACE, "filament_family/<vendor>/<family>" ) )
|
||||||
|
```
|
||||||
|
|
||||||
|
8 chars total (satisfies the AMS length limit), same base62 derivation and a dedicated
|
||||||
|
namespace constant. On the astronomically rare collision with an existing id, the minter salts
|
||||||
|
the input (`.../1`, `/2`, …) until free; the result is simply frozen in the file.
|
||||||
|
|
||||||
|
- **Script path:** author commits the family with *no id anywhere*;
|
||||||
|
`python scripts/assign_filament_ids.py` inserts the minted id into the root(s). Idempotent;
|
||||||
|
never rewrites a valid existing id. A `--mint "<Vendor>/<Family>"` one-shot prints the id
|
||||||
|
without touching the tree.
|
||||||
|
- **No-script path:** CI fails with the exact line to paste:
|
||||||
|
`family "MyBrand PLA" (vendor X) needs filament_id "OFq3xT9k" in "MyBrand PLA @base.json"`.
|
||||||
|
|
||||||
|
**Reserved namespaces — never mint or hand-write into:**
|
||||||
|
|
||||||
|
| Space | Owner | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| `GF*` | Bambu AMS/RFID catalog | byte-copies of authentic Bambu ids only, and only where a checked-in `shared_catalog` list sanctions the family (BBL bundle; OFL mirrors; byte-matching families in other vendors, e.g. Snapmaker's Fiberon) |
|
||||||
|
| `QD_*` | Qidi device protocol | frozen; Qidi-only; exempt from family-shape checks |
|
||||||
|
| `P[0-9A-Fa-f]{7}`, `"null"` | user-created custom filaments (`CreatePresetsDialog.cpp:533`) | never emitted for system presets (reserve case-insensitively) |
|
||||||
|
| everything already shipped | grandfather snapshot | frozen as-is (§5) |
|
||||||
|
|
||||||
|
Trade-off accepted: minted ids are opaque (`OFq3xT9k` carries no "PLA" mnemonic — the family
|
||||||
|
name in the same file provides that). The judges preferred this over a Bambu-style extended
|
||||||
|
grammar because it removes the "who allocates the next number" ceremony, cannot race between
|
||||||
|
concurrent PRs, and needs no registry maintenance. If mnemonic ids are strongly preferred, the
|
||||||
|
runner-up design (`<NSCODE><FAMLETTER><SEQ>` + registry file) is documented in the workflow
|
||||||
|
records; everything else in this plan is unchanged under either format.
|
||||||
|
|
||||||
|
### 3.4 What CI enforces (all vendors, ratcheted)
|
||||||
|
|
||||||
|
Extend `scripts/orca_extra_profile_check.py` (it imports the same mint function; setting_id
|
||||||
|
precedent) and the C++ validator:
|
||||||
|
|
||||||
|
1. **Format**: an id is valid iff `OF[0-9A-Za-z]{6}` **or** in the grandfather snapshot **or**
|
||||||
|
vendor==BBL **or** `QD_*` in Qidi. No whitespace/ASCII/length checks needed outside the
|
||||||
|
grandfather set — new ids are minted, and the grandfather set is closed.
|
||||||
|
2. **Uniqueness ratchet**: id→families multimap computed tree-wide; no id may acquire a family
|
||||||
|
claim not recorded in the snapshot (snapshot legalizes today's benign `GFL99`-style sharing;
|
||||||
|
new multi-claims are errors; `shared_catalog` entries are the sanctioned exception).
|
||||||
|
3. **Structure ratchet**: `filament_id` key only on roots; every instantiated filament must
|
||||||
|
resolve an effective id via the simulated loader walk; all members of one family resolve the
|
||||||
|
same id; **a preset may not declare an id different from its inherited effective id** (the
|
||||||
|
`Generic SBS` drift bug class). Pre-existing violations are snapshot-frozen; new ones error.
|
||||||
|
4. **Mint conformance**: an id new relative to the snapshot must equal the mint (or a salt
|
||||||
|
iteration); the error message prints the expected value.
|
||||||
|
5. **Stability**: an `(id, family)` pair on main may not change or vanish, *following
|
||||||
|
`renamed_from` chains* (so an honest rename passes), unless listed in a maintainer-gated
|
||||||
|
migrations file. Retired ids go to an append-only `retired_ids` ledger; a retired id may
|
||||||
|
never be defined again for any family.
|
||||||
|
6. **Alias hygiene for tuned generics**: a preset inheriting an OFL `Generic * @System` (with
|
||||||
|
no own id anywhere in its vendor chain) must keep the OFL base name and have non-empty
|
||||||
|
`compatible_printers` — error message names the rename as the cause.
|
||||||
|
7. **C++ validator**: extend `check_duplicate_filament_subtypes` (`PresetBundle.cpp:5654`) to
|
||||||
|
include OFL presets in every vendor's per-printer check, *minus* alias-excluded ones —
|
||||||
|
`m_excluded_from` is already populated in the validator context (`update_system_maps` at
|
||||||
|
`PresetBundle.cpp:2302`), so the 32 shadowed pairs won't false-positive and the 10 live ones
|
||||||
|
will be caught. Run `-f` per vendor in CI, widening as vendors are cleaned (§5).
|
||||||
|
8. **Runtime backstop** (one-line change): log a warning when the AMS-sync `find_if`
|
||||||
|
(`PresetBundle.cpp:3132/3233`) finds 2+ compatible presets for one id — the only layer that
|
||||||
|
can see side-loaded/forked bundles.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Error-pattern taxonomy (goal 2) — with counts and fixes
|
||||||
|
|
||||||
|
356 groups were classified by 37 agents reading the actual profiles, spot-checked
|
||||||
|
independently (1 substantive disagreement in 14 samples). Counts below fold the spot-check
|
||||||
|
corrections in. **Fix rule for all patterns: replacement id values are always freshly minted
|
||||||
|
`OF*`; the "which preset keeps the id" decision uses the precedence _Bambu-catalog material >
|
||||||
|
OFL generic family > family that historically introduced the id_.**
|
||||||
|
|
||||||
|
| # | Pattern | Groups | Fix |
|
||||||
|
|---|---|---|---|
|
||||||
|
| P1 | `copy_paste_id` — different materials share an id verbatim (task's error 1). Qidi's `GFB99`×317-files epidemic; Anycubic's three id "eras"; Peopoly `GFSL99` on ABS | ~167 | impostor families get minted ids on their roots; owner keeps the id |
|
||||||
|
| P2 | `wrong_inherits` / id-less product lines — a variant inherits another family's root (PR #14459's Panchroma case) or a product line never got its own root (Prusa HF; Flashforge's ~140-preset `FFG01` umbrella) | ~87 | create per-family roots with minted ids; re-point `inherits`; **never** delete the id-less shadow/base files — convert them (they carry real config: Flashforge `fdm_filament_pla` differs materially from OFL's) |
|
||||||
|
| P3 | `generic_family_overlap` — vendor-*branded* preset rides a generic family id via inheritance (task's error 2, generalized). Includes the 10 live OFL duplicates | ~68 | branded presets get minted family ids; true generic tunings instead adopt the OFL family *with matching alias* (rule 3.2.4); Sovol is the elegant case — just **delete** its wrong own-id lines and let OFL ids flow through inheritance |
|
||||||
|
| P4 | `overclaim_compat` — same material, broader variant claims a printer that a dedicated variant covers (the BBL H2DP pattern fixed in #14459) | ~24 | trim `compatible_printers` of the broader preset (Dremel, Cubicon `@base`s that are also instantiated, Wanhao France Bowden/Direct) |
|
||||||
|
| P5 | template-carried id — id declared on a shared settings template (`fdm_filament_*`, `fdm_filament_common`) so every family inheriting it collapses (Prusa, Ginger Additive, Snapmaker TPU base) | inside P1/P2 counts | move ids off templates onto family roots |
|
||||||
|
| P6 | OFL-internal collisions — 16 ids spanning several materials, visible on every printer (Elegoo blocks, Elas `OGFA00`×3, `OGFL06` polymer mismatch, `Generic PETG HF/PETG-CF @System` missing own ids) | 16 ids | fix inside OFL first (it's the base bundle every vendor resolves against) |
|
||||||
|
| P7 | alias-mismatch re-exposure — vendor tunes a generic under a different name, OFL preset resurfaces (Snapmaker `PolyTerra J1 PLA` vs OFL `PolyTerra PLA`) | 10 live | rename-to-alias where it's genuinely the same family, else mint |
|
||||||
|
| P8 | per-variant ids — no ambiguity, but family semantics broken: every variant has its own id (Prusa name-ids, SeeMeCNC nozzle suffixes, Afinia/Tiertime `_##`, iQ) so device matching can't identify the material across nozzles | ~210 presets | grandfather (they're unambiguous); converge opportunistically; document as anti-pattern |
|
||||||
|
| P9 | format violations — spaces (`"GFPLA Silk"`), >8 chars (LONGER, SeeMeCNC, LH), GF-shaped inventions (Anycubic `GFL93-97`, CoLiDo `GFA99`) | in the above | fixed as a byproduct of re-minting; snapshot freezes the unambiguous rest |
|
||||||
|
| P10 | cross-vendor semantic collisions — 67 ids meaning different materials in different vendors (dangerous via the global unscoped consumers, §1) | 67 ids | mostly eliminated by P1-P3 re-minting; the remaining same-material generic sharing is legalized by the snapshot |
|
||||||
|
| P11 | deliberate coexistence & data hygiene — Snapmaker "Benchy" demo presets (gated by `compatible_prints`, which the id check can't see) and a self-collision from duplicate `compatible_printers` entries | 4 | give demo presets own minted ids; dedupe list entries; add a lint for duplicate array entries |
|
||||||
|
|
||||||
|
New patterns beyond the two in the task (goal 2.3): P5-P11.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Migration plan
|
||||||
|
|
||||||
|
### Safety foundation (verified, §1/§7)
|
||||||
|
|
||||||
|
Safe: fresh never-used ids, family-consistent; trims of `compatible_printers`; inherits
|
||||||
|
re-pointing; OFL id changes (children re-derive). Unsafe: touching `BBL`/`QD_*`; recycling or
|
||||||
|
swapping ids; splitting a family's id; **deleting or renaming preset names** (user presets
|
||||||
|
whose `inherits` no longer resolves are dropped at load, `Preset.cpp:1687-1691`) — if a name
|
||||||
|
must go, `renamed_from` coverage is mandatory.
|
||||||
|
|
||||||
|
### Phases
|
||||||
|
|
||||||
|
0. **Land the rule + tooling first** (no profile changes): `scripts/assign_filament_ids.py`
|
||||||
|
(mint + insert + `--mint`), the extended `orca_extra_profile_check.py` checks in
|
||||||
|
snapshot-ratchet mode, the C++ validator OFL cross-check, the runtime warning, the rule doc.
|
||||||
|
Generate `filament_id_snapshot.json` (id→families multimap over main) and empty
|
||||||
|
`retired_ids.json` — both checked in.
|
||||||
|
1. **OFL first** (it's the base bundle every vendor resolves against): fix the 16 internal
|
||||||
|
collisions (Elas/eSUN/DREMC copy-pastes get mints; `Generic PETG HF/PETG-CF/PP-CF/PP-GF/
|
||||||
|
PE-CF/PLA Matte @System` get their own family roots+ids instead of collapsing into their
|
||||||
|
parent generic), keeping every current effective id that is unambiguous.
|
||||||
|
2. **Per-vendor PRs, worst-first**: Qidi → Flashforge → Elegoo → Prusa → Cubicon → Anycubic →
|
||||||
|
InfiMech → Snapmaker → the long tail (22 vendors, mostly 1-8 one-line fixes). Each PR flips
|
||||||
|
that vendor into CI's `-f` scope (`check_profiles.yml` currently `-v BBL -f`; append
|
||||||
|
vendors as they reach zero; when all are in, drop `-v` and run tree-wide).
|
||||||
|
3. **Delete the ratchet allowlists** once tree-wide zero holds; checks become hard rules for
|
||||||
|
everything born after the snapshot.
|
||||||
|
|
||||||
|
### Migration-script contract (from the adversarial pass — important)
|
||||||
|
|
||||||
|
- Consumes from the classification only: group membership, fix category, keep-id precedence,
|
||||||
|
inherits-repoint targets. **All replacement id values are recomputed via the mint** — id
|
||||||
|
literals in analysis notes (e.g. `GFA00_02`, `GFS98`, `GFG96`) are legacy-culture artifacts
|
||||||
|
and are ignored with a warning; assert no emitted id matches `^(GF|QD_|P[0-9A-Fa-f]{7}$)`.
|
||||||
|
- **Family-atomic**: re-idding any preset re-ids every same-family sibling in the same commit,
|
||||||
|
even siblings outside the collision group (FlyingBear `GFB99 @S1` vs `@Ghost7`); Prusa is
|
||||||
|
family-atomic per material (its HF/CF families span frozen `_N`-suffix ids — freeze what's
|
||||||
|
unambiguous, mint once per family for the colliding members).
|
||||||
|
- **Diff bound**: a vendor migration PR may only touch collision-group files + same-family
|
||||||
|
siblings of re-idded presets; every id that is per-printer-unambiguous today stays
|
||||||
|
byte-identical.
|
||||||
|
- **Config-equivalence gate**: dump every instantiated preset's flattened effective config on
|
||||||
|
main and on the PR head; the diff must be empty except `filament_id`/`inherits`/
|
||||||
|
`compatible_printers` edits the plan prescribes (this is what makes the Flashforge
|
||||||
|
shadow-file conversions safe: each id-less `fdm_filament_*` shadow becomes a named vendor
|
||||||
|
family root carrying its config byte-for-byte, children re-pointed, then the shadow name
|
||||||
|
retired).
|
||||||
|
- **No deletions**: redundant presets (Flashforge's byte-identical `Generic X`/`Flashforge X`
|
||||||
|
twins) are re-minted, not dropped; consolidation with `renamed_from` is a separate,
|
||||||
|
human-reviewed cleanup.
|
||||||
|
- Expected user impact: none for inheriting user presets, 3mfs, Klipper/Creality/Snapmaker
|
||||||
|
sync. Residue: user *root* presets that copied an old system id keep it forever
|
||||||
|
(AMS auto-match falls back to generic-by-type — low severity, unavoidable from the repo).
|
||||||
|
|
||||||
|
### Vendor-specific notes (from classification)
|
||||||
|
|
||||||
|
- **Qidi (97)**: three profile generations. `QD_*` generics are correct and frozen; the fix is
|
||||||
|
the brand families (Bambu/HATCHBOX/Overture/PolyLite/Tinmorry/QIDI-brand) that all carry
|
||||||
|
`GFB99/GFG99/GFL99`. Multi-root families are the norm (`...@Q2-Series` / `@Q2C-Series` /
|
||||||
|
`@X-Max 4-Series` bases) — same mint lands in every series root of one family.
|
||||||
|
- **Flashforge (69)**: two umbrellas (`FFG01` ~140 presets; `GFB99/GFG99/GFL99` G3U-era) +
|
||||||
|
OFL-riding branded presets + shadow-file conversion (above).
|
||||||
|
- **Elegoo (37)**: single mistake — every commercial variant inherits the material-class
|
||||||
|
`@base` (`E<MAT>B00`); mint one id per product line (Silk/Matte/PRO/Rapid/…), roots exist.
|
||||||
|
- **Prusa (31)**: HF product lines need their own roots; ids move off `fdm_filament_*`
|
||||||
|
templates; frozen name-shaped and `_N` ids stay.
|
||||||
|
- **Sovol (6)**: delete the wrong own-id lines; correct ids flow from OFL by inheritance.
|
||||||
|
- **Cubicon (17)**: `@base` presets are themselves instantiated + over-claiming; 9 file edits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Concrete work items (PR-sized)
|
||||||
|
|
||||||
|
1. `scripts/assign_filament_ids.py` + mint function + tests (incl. the 14-group regression set
|
||||||
|
from the adversarial pass). *(new)*
|
||||||
|
2. `orca_extra_profile_check.py`: checks §3.4-1..6 in ratchet mode + snapshot/ledger files;
|
||||||
|
drop the BBL/OFL-only gate at `:292` and the OFL skip at `:601`. *(extend)*
|
||||||
|
3. C++ validator: OFL-aware `check_duplicate_filament_subtypes`; runtime ambiguity warning at
|
||||||
|
the two `find_if` sites. *(small)*
|
||||||
|
4. Rule documentation: `doc/developer-reference/filament_id.md` (recreate the path; wiki
|
||||||
|
cross-link) + profile-PR template checkbox ("new materials: no filament_id key anywhere; CI
|
||||||
|
prints the minted id"). *(new)*
|
||||||
|
5. OFL migration PR (phase 1).
|
||||||
|
6. Per-vendor migration PRs (phase 2), each widening CI `-f` scope.
|
||||||
|
|
||||||
|
The audit tooling from this analysis (loader-faithful resolver; reproduces the validator
|
||||||
|
1256/1256) is in this session's scratchpad (`audit_filament_ids.py`) and is the natural seed
|
||||||
|
for items 1-2.
|
||||||
|
|
||||||
|
## 7. Evidence & methodology
|
||||||
|
|
||||||
|
- Validator ground truth: `OrcaSlicer_profile_validator -f` tree-wide → 1256 errors; audit
|
||||||
|
script reproduces exactly (356 logical groups after dedup by (vendor, id, preset-set)).
|
||||||
|
- Code analysis: 5 parallel agents over runtime consumers, persistence/migration surface,
|
||||||
|
loader semantics, Bambu grammar, and convention history — all claims carry `file:line`.
|
||||||
|
- Classification: 37 agents (one per vendor chunk) reading actual profile JSONs; 14-sample
|
||||||
|
independent re-derivation found 1 substantive error (a Flashforge group mislabeled
|
||||||
|
`missing_id`; corrected — the loader resolves those ids from OFL).
|
||||||
|
- Design: 3 independent designs → 2 judges (both chose the deterministic mint; scores 58/50/56
|
||||||
|
and 60/54/56) → 3 adversarial attackers (35 scenarios; every `breaks` finding is folded into
|
||||||
|
§3.2-3.4/§5 as an amendment: declared families, multi-root support, ratchet-not-absolute
|
||||||
|
checks, no-deletion rule, shadow-file conversion, classification-id-literal quarantine,
|
||||||
|
diameter siblings, case-insensitive P-hex reservation, fork guidance).
|
||||||
|
- Key history: `OGF*` born 2025-03-31 (`8c4a65e3e1`, no PR); `_##` suffix born PR #9739;
|
||||||
|
8-char check born PR #9574; wiki (with the id-copy-paste example) removed 2025-11-24
|
||||||
|
(`f0d79b99eb`).
|
||||||
|
|
||||||
|
## 8. Open decisions for maintainers
|
||||||
|
|
||||||
|
1. **Id format**: opaque deterministic `OF*` mint (recommended, judges 2/2) vs mnemonic
|
||||||
|
registry grammar (runner-up). Everything else in the plan is format-agnostic.
|
||||||
|
2. **Multi-vendor brands** (Snapmaker ships Fiberon with authentic `GF*` ids): sanction via
|
||||||
|
`shared_catalog` (recommended, low churn) vs hoisting those families into OFL.
|
||||||
|
3. **Benchy-style demo presets**: mint ids per demo preset (recommended) vs teaching the
|
||||||
|
validator `compatible_prints` gating.
|
||||||
|
4. **Alias alignment**: fix the 10 live alias-mismatch OFL duplicates by rename-to-alias
|
||||||
|
(better long-term, needs `renamed_from`) vs minting vendor ids (safer, more ids).
|
||||||
|
5. **Where the rule doc lives**: in-repo `doc/` (recommended — CI messages need a stable link)
|
||||||
|
vs wiki-only.
|
||||||
314
filament_id_plan_v2.md
Normal file
314
filament_id_plan_v2.md
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
# filament_id plan v2: the `get_filament_id` (P+md5) proposal, validated
|
||||||
|
|
||||||
|
> **Status note:** the verdict in §0-§4 and §7-§8 stands. The work items in §5 are
|
||||||
|
> superseded by `filament_id_plan_v3.md` (OFL-as-catalog, content-addressed triple key,
|
||||||
|
> succession ledger): W1/W3 are carried into v3.0, W2/W5 carry unchanged, W4 is dropped.
|
||||||
|
|
||||||
|
Follow-up to `filament_id_plan.md` (v1, implemented on `feature/filament_id`: deterministic
|
||||||
|
`OF*` mint + snapshot ledger + 30-vendor migration, tree-wide validator `-f` = 0).
|
||||||
|
|
||||||
|
**Proposal under review:** mint system `filament_id`s with the scheme of
|
||||||
|
`static std::string get_filament_id(std::string vendor_typr_serial)`
|
||||||
|
(`src/slic3r/GUI/CreatePresetsDialog.cpp:487-552`) — Bambu's user-custom-filament id
|
||||||
|
allocator — so system ids are "compatible with Bambu AMS sync".
|
||||||
|
|
||||||
|
Every claim below was verified in source (`file:line`), against upstream BambuStudio, or in
|
||||||
|
primary online sources (URLs in §8). Verdict first, evidence after.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Executive summary — the verdict
|
||||||
|
|
||||||
|
**Do not re-mint system ids as `P+md5(name)`. Keep the v1 `OF*` mint.** Three facts decide it:
|
||||||
|
|
||||||
|
1. **The AMS/device path never validates id *shape*.** `tray_info_idx` is an opaque string
|
||||||
|
end-to-end: sent verbatim (`DeviceManager.cpp:1642`), parsed verbatim
|
||||||
|
(`DevFilaSystem.cpp:512-514`), and firmware persists arbitrary bytes — an A1 stored and
|
||||||
|
echoed a *corrupted* id `Pde2\xea58c` (bambulab/BambuStudio#5436). A P-shaped system id
|
||||||
|
is not "more acceptable" to the device than an `OF*` one.
|
||||||
|
2. **P-shape buys zero recognition.** The printer resolves tray ids only against its built-in
|
||||||
|
`GF*` catalog plus the *account's* cloud custom-filament cache (official Bambu wiki); ids
|
||||||
|
it cannot resolve round-trip as `?`. Orca can never upload system presets into that cache
|
||||||
|
(`Preset.cpp:2071` gates cloud upload on `is_user()`), so an Orca system `P` id shows `?`
|
||||||
|
exactly like an `OF` id. The public catalog id space is 100% `GF*` (ha-bambulab
|
||||||
|
`filaments.json`: 86/86 ids).
|
||||||
|
3. **P-shape is the one shape the codebase punishes.** The *only* id-shape dispatch in the
|
||||||
|
entire tree is `MachineObject::check_ams_filament_valid` + `update_filament_list`
|
||||||
|
(`DeviceManager.cpp:5335/5352/5395/5410`, gate `setting_id.size()==8 && [0]=='P'`), a
|
||||||
|
user-custom lifecycle reconciler that **remotely wipes an AMS tray**
|
||||||
|
(`command_ams_filament_settings(..., "", "", white, "", 0, 0)` at `:5345`) or rewrites its
|
||||||
|
temps (`:5361-5367`) when a P-shaped tray id drops out of the user-root preset list
|
||||||
|
(`:5219`, armed at `:5268`). Name-keyed minting makes system id == user-custom id *by
|
||||||
|
design* (same name → same id), so "user deletes their now-redundant custom after the
|
||||||
|
system preset ships" becomes a remote tray wipe. `GF*` (wrong length) and `OF*` (wrong
|
||||||
|
first char) are structurally immune.
|
||||||
|
|
||||||
|
The proposal's *real* value lives in two places, and v2 captures both without the re-mint:
|
||||||
|
|
||||||
|
- **The adopt step** (the function's first branch, `:509-511/:526-528`): same base name →
|
||||||
|
same id. In-app, this already gives Orca-local convergence today — a user custom named
|
||||||
|
like a system family adopts the system id *whatever its shape*. At authoring time, the
|
||||||
|
same semantics = the v1 `shared_catalog` mechanism; §5/W4 extends it (curated, optional)
|
||||||
|
to let byte-authentic Bambu-catalog families carry authentic `GF*` ids.
|
||||||
|
- **The hash step belongs to user space.** `P+md5(name)` is Bambu's allocator for *user*
|
||||||
|
presets; the community is already asking for it there (OrcaSlicer PR #13315, unique ids
|
||||||
|
for inherited user presets). §5/W5 endorses that lane. System profiles stay out of the
|
||||||
|
`P` namespace — and v2 adds client hardening (W1) because ten *already-shipped* system
|
||||||
|
P-hex ids (Cubicon `P510cf**`×8, Ginger `P510eff9`, Artillery `Pfcf9c4c`) sit inside the
|
||||||
|
wipe-gate's shape match today.
|
||||||
|
|
||||||
|
Judge panel (3 independent lenses over 4 variants; §7): keep-`OF*` won 23/40 aggregate
|
||||||
|
(device-ecosystem 6, identity-semantics 8, migration-enforceability 9) vs full Bambu
|
||||||
|
emulation 11, hash-only name-keyed 12, vendor-scoped P-hash 12. The single dissent
|
||||||
|
(device-ecosystem, favoring adoption) is honored by W4; its own verdict on the shape was
|
||||||
|
"adopt the semantics, not the costume".
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. What the proposed generator actually is (verified)
|
||||||
|
|
||||||
|
`get_filament_id(vendor_typr_serial)` (`CreatePresetsDialog.cpp:487-552`), called with
|
||||||
|
`"<vendor> <type> <serial>"` (`:1128`, `PLA-AERO`→`"PLA Aero"`), and per-preset with the
|
||||||
|
display base name when cloning presets for a user-created printer
|
||||||
|
(`Preset.cpp:2785-2803` → `:2798-2800`):
|
||||||
|
|
||||||
|
1. **Adopt:** scan a temp bundle of *every* vendor bundle on disk
|
||||||
|
(`PresetBundle::load_system_filaments_json`, `PresetBundle.cpp:2342-2391`) plus the
|
||||||
|
user's presets, then the live bundle (`Preset.cpp:2831-2842`); if any preset's base name
|
||||||
|
(`name.substr(0, first('@') - 1)`) equals the input and its id ≠ `"null"`, **return that
|
||||||
|
id** — which can be `GF*`, `QD_*`, `OF*`, or another user's P-hex.
|
||||||
|
2. **Mint:** `"P" + md5(input)[0:7]`, lowercase hex over the raw UTF-8 bytes (`:533`,
|
||||||
|
`:480`).
|
||||||
|
3. **Collide:** if the id is held by a *different* name, re-hash with a local wall-clock
|
||||||
|
salt (`md5(input + get_curr_time())`, `:547`) — non-deterministic by construction.
|
||||||
|
|
||||||
|
Upstream parity: the function and its caller input construction are **byte-identical** in
|
||||||
|
BambuStudio master (`CreatePresetsDialog.cpp` L434-499 / L1061; diff empty, fetched
|
||||||
|
2026-07-03). So identical dialog inputs in BBS and Orca yield identical ids — the kernel of
|
||||||
|
the proposal's compatibility claim.
|
||||||
|
|
||||||
|
Reproduction limits (why "exactly the approach" cannot be ported to system minting anyway):
|
||||||
|
|
||||||
|
- The base-name parser truncates names lacking a space before `@` (`"Afinia PLA@HS"` →
|
||||||
|
`"Afinia PL"`); 48 shipped presets hit this, and the *clone* path parses differently
|
||||||
|
(`" @"` two-char, `Preset.cpp:2792`), so the app itself is internally inconsistent.
|
||||||
|
- 597 presets (361 whole families, e.g. all of Anker) contain no `@` and are invisible to
|
||||||
|
the adopt scan and its collision map (`:505-508`).
|
||||||
|
- The collision salt is wall-clock time — unreproducible across machines, so id values
|
||||||
|
cannot be CI-verified from names; a ledger would still be the sole source of truth.
|
||||||
|
- Shipped P-hex ids don't round-trip from names today: Cubicon `P510cfb0` ≠
|
||||||
|
`P+md5("Cubicon ABS")` = `Pc624b68` (verified) — so even Bambu-lineage P ids are not
|
||||||
|
name-derivable in practice.
|
||||||
|
|
||||||
|
## 2. What Bambu AMS sync actually consumes (verified)
|
||||||
|
|
||||||
|
- Send: `command_ams_filament_settings` puts the preset's `filament_id` verbatim into
|
||||||
|
`tray_info_idx` (`DeviceManager.cpp:1642`); cloud vs LAN differ only in transport
|
||||||
|
(`:2502-2536`). No client- or firmware-side rejection path exists; the ack parse stores
|
||||||
|
whatever the printer echoes (`:3808-3860`).
|
||||||
|
- Resolve (slicer side): tray id → first compatible root preset with equal `filament_id` —
|
||||||
|
system *and* user roots, no shape filter (`PresetBundle.cpp:3151`, `:3252-3254`); misses
|
||||||
|
fall back by `"Generic <type>"` name, then similarity, then keep-previous
|
||||||
|
(`:3157-3169`, `:3260-3305`). `setting_id_to_type` resolves against `is_system` presets
|
||||||
|
only (`DeviceManager.cpp:2538-2559`) — a system preset resolves *because it is system*,
|
||||||
|
never because of its id shape.
|
||||||
|
- Resolve (device side): built-in `GF*` catalog + the account's cloud custom cache;
|
||||||
|
custom-filament sync is **cloud-only** (not LAN), and an id the printer has no data for
|
||||||
|
displays `?` until opened once on the printer screen (official wiki, §8). Third-party
|
||||||
|
consumers see customs as "unknown" (ha-bambulab #466/#540).
|
||||||
|
- Since Jan 2025, AMS configuration is gated behind Bambu-signed clients on new firmware
|
||||||
|
(Developer Mode / older firmware exempt) — any AMS-sync benefit for Orca is conditional
|
||||||
|
on that regardless of id scheme (Bambu authorization blog, §8).
|
||||||
|
- Orca already ships non-`GF`/non-`P` shapes to Bambu trays in the field: OFL presets are
|
||||||
|
compatible with every printer (`PresetBundle.cpp:5681-5684`) and carry `OGF*`/`OFL*` ids
|
||||||
|
(e.g. `OFLSBS99`, hardcoded in `MoonrakerPrinterAgent.cpp:654`). The premise "the
|
||||||
|
ecosystem has only ever seen `GF*`/P-hex" is already false, with no observed rejection.
|
||||||
|
|
||||||
|
**Cross-client reality check.** The name-keyed benefit ("a BBS-created custom named like an
|
||||||
|
Orca system preset lands on the same id, so Orca's sync matches the system preset") is
|
||||||
|
mechanically true but narrow: it needs byte-exact names (including the `PLA Aero` mapping
|
||||||
|
and single spacing), the unsalted hash path, cloud mode, and permissive firmware. The
|
||||||
|
symmetric case already works in Orca *without* any re-mint: an Orca user creating a custom
|
||||||
|
named like a system family **adopts the system id** via the in-app adopt branch, so local
|
||||||
|
custom ↔ system ↔ tray matching is shape-independent today.
|
||||||
|
|
||||||
|
## 3. The disqualifying finding, in mechanism form
|
||||||
|
|
||||||
|
`update_filament_list` (`DeviceManager.cpp:5208-5272`) snapshots `{filament_id → temps}`
|
||||||
|
over **user root presets only** (`preset.is_user() && preset.inherits() == ""`, `:5219`);
|
||||||
|
ids that vanish or change temps between snapshots are armed into `checked_filament`
|
||||||
|
(`:5268`). `check_ams_filament_valid` (`:5311-5445`) then, for every AMS/virtual tray whose
|
||||||
|
`setting_id` matches `size()==8 && [0]=='P'`:
|
||||||
|
|
||||||
|
- id armed and **not** in the current user-root list → remotely **clears the tray**
|
||||||
|
(`:5335-5349`, `:5395-5408`);
|
||||||
|
- id armed and in the list with unequal temps → **rewrites tray temps from the user
|
||||||
|
preset**, ignoring same-id system presets (`:5352-5374`; `PresetBundle.cpp:3719` skips
|
||||||
|
non-user presets; unguarded `find()->second` at `:3717`).
|
||||||
|
|
||||||
|
Failure scenario under the proposal: system `"PolyLite PLA"` ships with
|
||||||
|
`P+md5("PolyLite PLA")`. A user's same-named custom (BBS- or Orca-created — same id by
|
||||||
|
design) is on an AMS tray. The user deletes the now-redundant custom. Next status refresh:
|
||||||
|
the id is armed, absent from user roots → Orca wipes the tray, even though the system
|
||||||
|
preset still resolves that id perfectly. Runs continuously (`StatusPanel.cpp:3275-3277`).
|
||||||
|
|
||||||
|
Two corollaries independent of the proposal (→ W1):
|
||||||
|
|
||||||
|
- The ten shipped P-hex **system** ids (Cubicon/Ginger/Artillery) already pass the shape
|
||||||
|
gate; only the "id must transit a user root" arming condition protects them, and the
|
||||||
|
in-app adopt branch can create exactly that transit today.
|
||||||
|
- `assert(it->first.size() == 8 && it->first[0] == 'P')` (`:5252`) is violable today: a
|
||||||
|
user custom named `"Bambu PLA Basic"` adopts `GFA00` onto a user root and aborts debug
|
||||||
|
builds.
|
||||||
|
|
||||||
|
## 4. Identity costs the re-mint would add (quantified, tree dry-run)
|
||||||
|
|
||||||
|
- 1148 distinct family base names; **198** appear in 2+ vendors; **159** groups carry ≥2
|
||||||
|
distinct ids today and would silently merge under name-keying (Generic PETG alone: 15
|
||||||
|
ids today). 112 involve BBL; 82 are `GF↔OGF` mirror pairs.
|
||||||
|
- **4** cross-vendor groups share a name across materially different `filament_type`
|
||||||
|
(Generic PLA Silk, Generic PETG-CF, Generic PA6-CF, Generic PE-CF) — one merged id would
|
||||||
|
feed wrong type/name/vitrification to the global unscoped consumers
|
||||||
|
(`PresetBundle.cpp:690-733`; `DeviceManager.cpp:2538`; `FilamentGroup.cpp:513-519`) (→ W3).
|
||||||
|
- 33 deliberately-split families on the branch would re-merge (25 Elegoo-vs-OFL pairs, 7
|
||||||
|
FlyingBear-vs-InfiMech "Other *" pairs, the salted Cubicon PC pair) — undoing v1
|
||||||
|
decisions that the fixture gate forced.
|
||||||
|
- Renames become id migrations: name-keyed ids re-key on any marketing rename; the ledger
|
||||||
|
can freeze them, but then name-derivability — the scheme's selling point — dies family
|
||||||
|
by family. The `OF*` key (`vendor/family`) survives display-name churn.
|
||||||
|
- Entropy drops 35.7 → 28 bits (still 0 collisions at today's 1148 names; ~0.75 expected
|
||||||
|
at 20k). Re-mint surface: 391 unshipped ids across 1327 files, 13 hardcoded tests, the
|
||||||
|
reserved-namespace policy inversion, and a retired-ledger rebuild.
|
||||||
|
|
||||||
|
## 5. Work items (delta from `feature/filament_id` HEAD)
|
||||||
|
|
||||||
|
**W1 — client hardening (C++, small, ships with the migration PR train).**
|
||||||
|
a. Skip the tray-reset and temp-rewrite in `check_ams_filament_valid` when **any
|
||||||
|
`is_system` filament preset carries the tray's id** — no compatibility filter,
|
||||||
|
mirroring the semantics of the global consumers (`get_filament_by_filament_id`,
|
||||||
|
`setting_id_to_type`). This protects the ten shipped P-hex system ids and any BBS
|
||||||
|
custom colliding with them, while ids resolving only to user presets (or to nothing)
|
||||||
|
keep today's cleanup behavior.
|
||||||
|
b. Relax the debug assert `DeviceManager.cpp:5252` to a log (user roots legitimately
|
||||||
|
carry adopted `GF*`/`OF*` ids).
|
||||||
|
c. Guard `PresetBundle.cpp:3717` (`find()` unchecked before `->second`).
|
||||||
|
d. Regression-check that AMS sync never clears trays whose id it merely cannot resolve
|
||||||
|
(OrcaSlicer#4431 class): the keep-previous fallbacks at `PresetBundle.cpp:3163-3169`,
|
||||||
|
`:3296-3305` must cover the UI paths.
|
||||||
|
|
||||||
|
**W2 — tooling + doc guardrails.**
|
||||||
|
a. Document `^OF[0-9A-Za-z]{6}$` as the system-mint namespace. **Do not add it to
|
||||||
|
`reserved_space_owner`** (`scripts/assign_filament_ids.py:394-402`): check 6 exempts
|
||||||
|
only snapshot-grandfathered claims and the `--update-snapshot` refusal gate
|
||||||
|
(`:596-621`) would then reject every *future* mint. The space is already enforced —
|
||||||
|
check 3 (mint conformance, `:488-509`) errors on any OF-shaped id that does not equal
|
||||||
|
its own family's mint (covered by `test_check3_of_id_must_match_mint`), and the
|
||||||
|
snapshot diff is the human gate. Add one doc paragraph + a test asserting a foreign
|
||||||
|
vendor claiming another family's OF id fails check 3.
|
||||||
|
b. `doc/developer-reference/filament_id.md`: add a "why not P-hex" section citing the
|
||||||
|
`DeviceManager.cpp:5335` gate and the account-cache resolution model — community
|
||||||
|
pressure toward `P+md5` exists (PR #13315) and will recur.
|
||||||
|
c. Document that user roots may legitimately hold adopted system ids (incl. what that
|
||||||
|
means for cloud upload, `Preset.cpp:1874-1876`), matching BBS behavior.
|
||||||
|
|
||||||
|
**W3 — data hygiene: the 4 same-name-different-type groups.** Audit each (they confuse
|
||||||
|
name-based fallback matching and any future interop even under vendor-scoped ids):
|
||||||
|
verify whether the divergent `filament_type` is a data bug (e.g. OFL `Generic PETG-CF`
|
||||||
|
resolving `PETG`, OFL `Generic PE-CF` resolving `PE`, Flashforge `Generic PLA Silk`
|
||||||
|
mixing `SILK`+`PLA`, Creality-vs-Elegoo `Generic PA6-CF` as `PA-CF`/`PA6-CF`) or
|
||||||
|
intentional; fix by type alignment or rename with evidence, gated by
|
||||||
|
config-equivalence (only `filament_type` diffs as prescribed) + full validator suite.
|
||||||
|
|
||||||
|
**W4 — optional, curated GF adoption (the proposal's adopt step, done safely).** Extend the
|
||||||
|
v1 `--allow-shared-catalog` mechanism into an explicit per-family adoption worksheet: a
|
||||||
|
family may carry a byte-authentic Bambu catalog id iff (i) it is verifiably the same
|
||||||
|
commercial product as the BBL family (vendor evidence + equal `filament_type`), (ii)
|
||||||
|
validator `-f` stays 0 tree-wide (alias shadowing covers BBL/OFL overlaps), (iii) the
|
||||||
|
fixture gate passes, (iv) the snapshot diff records the adoption. Candidates: the 13
|
||||||
|
actionable BBL-overlapping families minted `OF*` in v1 (e.g. Qidi `Bambu ABS`→`GFB00`,
|
||||||
|
`PolyLite PLA`→`GFL00`, `Overture PLA`→`GFL04`, `PolyLite ABS`→`GFB60`; `OFLSBS99` is
|
||||||
|
shipped and frozen; the two type-hazard OFL families are excluded until W3 lands).
|
||||||
|
**Honest benefit statement:** these presets are compatible only with non-Bambu printers,
|
||||||
|
so no Bambu device resolves their ids today; the payoff is one-product-one-id coherence
|
||||||
|
for the global consumers, project portability, and readiness for W6. Recommended seed:
|
||||||
|
the four Qidi brand families; generics deferred.
|
||||||
|
|
||||||
|
**W5 — user-preset lane (where the proposal's hash belongs).** Support unique ids for
|
||||||
|
inherited user presets (the PR #13315 pain: children share the parent's id, so AMS always
|
||||||
|
resolves the generic parent). `P + md5(preset name)` matching
|
||||||
|
`CreatePresetsDialog::get_filament_id` is correct *in user space*: adopt-first against
|
||||||
|
existing ids, then hash; ids frozen per preset after mint. Constraints: never emitted
|
||||||
|
into system profiles (W2a makes that mechanical); W1 must land first so shared-id
|
||||||
|
lifecycles can't wipe trays.
|
||||||
|
|
||||||
|
**W6 — recorded future option:** SoftFever's "upload OrcaSlicer's filament database
|
||||||
|
(especially the filament ID) to the printer" (PR #12724 comment). If pursued, Orca ids
|
||||||
|
become first-class device-visible artifacts and the P-mimicry question is permanently
|
||||||
|
moot; the `OF*` scheme is the *better* citizen there (collision-free vendor-scoped ids,
|
||||||
|
no user-custom masquerade).
|
||||||
|
|
||||||
|
Unchanged from v1: mint rule, snapshot/retired ledgers (no OF retirement — nothing is
|
||||||
|
re-minted), CI wiring, migration commits. `filament_id_plan.md` remains the implemented
|
||||||
|
baseline; this document records the v2 decision and its follow-on work.
|
||||||
|
|
||||||
|
## 6. Gates (per work item)
|
||||||
|
|
||||||
|
Same battery as v1, all local: `python scripts/orca_extra_profile_check.py` exit 0;
|
||||||
|
`assign_filament_ids.py --check` exit 0 (46+ unit tests green; new tests for W2a
|
||||||
|
reservation and, when implemented, W4 adoption sanctioning); validator `-l 2` exit 0,
|
||||||
|
`-f` tree-wide exit 0, `-r` BBL+Qidi exit 0; custom-preset fixture overlays (the W1/W4
|
||||||
|
changes touch exactly the preset-visibility machinery the fixtures exist to protect);
|
||||||
|
config-equivalence: flattened effective configs differ only in prescribed keys
|
||||||
|
(`filament_id` for W4, `filament_type` for W3, none for W1/W2). W1 additionally needs a
|
||||||
|
manual AMS smoke test on a live Bambu printer (tray set/clear round-trip) — a release
|
||||||
|
checklist item, not CI (the workflows have no hardware runners).
|
||||||
|
|
||||||
|
## 7. Scheme comparison (judge panel record)
|
||||||
|
|
||||||
|
| Variant | Device lens | Identity lens | Migration lens | Σ |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| V1 full Bambu emulation (adopt incl. `GF*` + P+md5 + salt) | 7 | 2 | 2 | 11 |
|
||||||
|
| V2 hash-only name-keyed `P+md5(base name)` | 4 | 4 | 4 | 12 |
|
||||||
|
| V3 vendor-scoped P-hash (`P+md5(vendor/family)`) | 2 | 5 | 5 | 12 |
|
||||||
|
| **V4 keep `OF*` uuid5 vendor-scoped (chosen)** | 6 | 8 | 9 | **23** |
|
||||||
|
|
||||||
|
All three judges answered the pivotal question the same way: the P-hex **shape** confers no
|
||||||
|
device/cloud benefit (resolution is by value against catalog + account cache; the path is
|
||||||
|
otherwise shape-agnostic) and is the only shape with a destructive client-side gate. V3 is
|
||||||
|
strictly dominated (all of the re-mint cost, none of the name-keyed benefit). V1's genuine
|
||||||
|
half — GF adoption — is captured by W4 at zero re-mint cost.
|
||||||
|
|
||||||
|
## 8. Evidence index
|
||||||
|
|
||||||
|
Code (this branch): `CreatePresetsDialog.cpp:487-552,1128,2798-2800` (generator + callers);
|
||||||
|
`DeviceManager.cpp:1642` (verbatim send), `:2538-2559` (system-only type resolve),
|
||||||
|
`:5208-5272` (user-root snapshot, `:5219`, `:5252` assert, `:5268` arming), `:5311-5445`
|
||||||
|
(P-shape gate + tray wipe `:5335/:5345`, temp rewrite `:5352-5374`, virtual tray
|
||||||
|
`:5395-5435`); `DevFilaSystem.cpp:512-524`; `PresetBundle.cpp:690-733,3116-3128,3151,
|
||||||
|
3252-3254,3709-3767,5674-5753`; `Preset.cpp:1874-1876,2071,2785-2842`;
|
||||||
|
`AMSMaterialsSetting.cpp:886,894-897`; `WebGuideDialog.cpp:67`;
|
||||||
|
`PresetComboBoxes.cpp:1952-1966`; `MoonrakerPrinterAgent.cpp:654`;
|
||||||
|
`scripts/assign_filament_ids.py:69,71-72,118-144,394-402,596-621`.
|
||||||
|
|
||||||
|
Online (fetched 2026-07-03): BambuStudio master `CreatePresetsDialog.cpp` L434-499
|
||||||
|
(byte-identical generator); wiki.bambulab.com `create-filament` (custom filaments AMS-able
|
||||||
|
from firmware 1.6.6; only dialog-created presets sync) and `custom-filament-issue`
|
||||||
|
(cloud-only sync; unknown ids show `?`); blog.bambulab.com authorization-control (Jan-2025
|
||||||
|
AMS-config gating); bambulab/BambuStudio#5436 (firmware persists corrupted id);
|
||||||
|
OrcaSlicer #4431 (tray clobber to `?`), #3874 (cloud-only confirmation), PR #14459
|
||||||
|
(the `-f` invariant), PR #14423 + PR #12724 + PR #13315 (maintainer statements / community
|
||||||
|
P+md5 pressure); greghesp/ha-bambulab `filaments.json` (86/86 `GF*`) + #466/#540.
|
||||||
|
|
||||||
|
Method: 6 parallel evidence agents (generator semantics; AMS/device path; exhaustive
|
||||||
|
shape-dispatch sweep; upstream/online; tree-wide dry-run over 5892 presets / 1455 families;
|
||||||
|
branch change inventory) → 3-judge panel (device-ecosystem, identity-semantics,
|
||||||
|
migration-enforceability lenses). Dry-run artifacts: session scratchpad
|
||||||
|
`phex_dryrun_{summary,details,followup}.json`.
|
||||||
|
|
||||||
|
## 9. Open decisions for maintainers
|
||||||
|
|
||||||
|
1. **W4 scope**: none / 4 Qidi brand families (recommended) / + generic-tier re-adoption.
|
||||||
|
2. **W5 timing**: implement in-repo vs review upstream PR #13315 with the W1 hardening as a
|
||||||
|
prerequisite either way.
|
||||||
|
3. **W6**: pursue the filament-database-upload design (makes Orca ids device-visible and
|
||||||
|
ends the mimicry debate for good).
|
||||||
213
filament_id_plan_v3.md
Normal file
213
filament_id_plan_v3.md
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# filament_id plan v3: OFL as the catalog, content-addressed product ids
|
||||||
|
|
||||||
|
Supersedes §5 of `filament_id_plan_v2.md` (whose P+md5 verdict stands unchanged) and
|
||||||
|
revises the mint rule of `filament_id_plan.md` (v1, implemented on `feature/filament_id`).
|
||||||
|
Decision driver: v1's mint key scoped families to the *profile bundle* (printer brand), so
|
||||||
|
one commercial product tuned in N bundles carries N ids — e.g. PolyLite PLA ships in five
|
||||||
|
bundles (`BBL`, `OrcaFilamentLibrary`, `OrcaArena`, `Qidi`, `Snapmaker`), all with
|
||||||
|
`filament_vendor: "Polymaker"`, under up to five different ids (`GFL00`, `OFceJcLf`, …).
|
||||||
|
That contradicts what `filament_id` means: one id per commercial product line.
|
||||||
|
|
||||||
|
## 0. The architecture
|
||||||
|
|
||||||
|
Three tiers, two frozen islands:
|
||||||
|
|
||||||
|
1. **BBL island — untouched.** Bambu profiles keep their `GF*` catalog ids byte-for-byte
|
||||||
|
(device/RFID/cloud contract). No convergence between GF and OFL ids is attempted: the
|
||||||
|
same product may permanently carry `GFL00` on the BBL side and an `OF*` id everywhere
|
||||||
|
else. This is a deliberate trade for simplicity; v2's curated-GF-adoption (old W4) is
|
||||||
|
dropped.
|
||||||
|
2. **`QD_*` island — untouched.** Qidi's box builds `QD_<series>_<vendor>_<type>` from
|
||||||
|
device enums and requires exactly-matching presets (`QidiPrinterAgent.cpp:146-152`).
|
||||||
|
Qidi presets carrying `QD_*` are exempt from re-minting, forever.
|
||||||
|
3. **Everything else converges on OrcaFilamentLibrary.** OFL is the product catalog: a
|
||||||
|
material family's id is declared once, on its OFL family root. Vendor bundles carry
|
||||||
|
only per-printer *specializations* of OFL families — same base name, non-empty
|
||||||
|
`compatible_printers`, **no `filament_id` key** — which (a) alias-shadow the OFL preset
|
||||||
|
on the printers they claim (`Preset.cpp:3684-3714`: "Generic PLA @Qidi Q2 0.4mm nozzle"
|
||||||
|
hides "Generic PLA @System" on that machine) and (b) resolve the OFL family's id
|
||||||
|
through the loader's inherits/base-bundle walk (`PresetBundle.cpp:4842-5080`). Products
|
||||||
|
OFL does not (yet) carry mint their id in the vendor bundle **with the same rule**;
|
||||||
|
because the key is bundle-independent (§1), later hoisting the family into OFL never
|
||||||
|
changes its id.
|
||||||
|
|
||||||
|
Convergence therefore happens by *single declaration point*, not by copying ids across
|
||||||
|
bundles — no adoption registry, no cross-bundle id claims to curate.
|
||||||
|
|
||||||
|
## 1. The mint rule
|
||||||
|
|
||||||
|
```
|
||||||
|
triple = (filament_vendor, filament_type, family_name) # from the family ROOT's flattened config
|
||||||
|
key = "filament_product/<filament_vendor>/<filament_type>/<family_name>"
|
||||||
|
id = "OF" + base62_6( uuid5( FILAMENT_ID_NAMESPACE, key ) ) # namespace unchanged:
|
||||||
|
# c4d3ff49-4c32-5534-a3e3-00894157ab97
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Triple resolution.** All three values come from the family root preset's *flattened
|
||||||
|
effective config* (`filament_vendor` and `filament_type` are inheritable list options —
|
||||||
|
take the first element; family_name = the root's base name, `\s?@.*` stripped once).
|
||||||
|
For own-key-layout families (no root), each declaring preset's flattened config is used
|
||||||
|
and CI requires all declarers of one family to agree on the triple. A root that resolves
|
||||||
|
an empty `filament_vendor` or `filament_type` is a CI error (generics use `"Generic"`).
|
||||||
|
Values enter the key verbatim (UTF-8, no case folding).
|
||||||
|
- **Bundle-independent by design.** The key contains no bundle name, so the same product
|
||||||
|
yields the same id whether minted in OFL or in a vendor bundle; migrating a family into
|
||||||
|
OFL (§0.3) is id-stable. Two bundles independently adding the same triple converge
|
||||||
|
automatically — and that is correct, because equal (vendor, type, name) *is* the
|
||||||
|
definition of "same product" here. The known look-alike hazards stay separated by the
|
||||||
|
type component: the 4 same-name-different-type groups (Flashforge `Generic PLA Silk` as
|
||||||
|
SILK, OFL `Generic PETG-CF` as PETG, `Generic PA6-CF`, `Generic PE-CF`) hash apart until
|
||||||
|
their type bugs are fixed (§5, W3) and converge automatically after — self-healing that
|
||||||
|
pure name-keying (rejected in v2) could not provide.
|
||||||
|
- **Format and salt unchanged from v1**: 8 chars, `OF` + 6 base62; deterministic `/1`,
|
||||||
|
`/2`… salt past any taken or retired id (the O+7 widening was evaluated and rejected:
|
||||||
|
62⁶ expects 1.9×10⁻⁵ collisions at today's 1,455 families, and `^O.{7}$` would sweep 35
|
||||||
|
legacy ids into the conformance gate vs. one today).
|
||||||
|
- **Content-addressed, deliberately.** If any triple component changes — a family rename,
|
||||||
|
a `filament_vendor` correction, a `filament_type` fix — the id changes with it. This
|
||||||
|
*replaces* v1's "ids are immutable once shipped" with "ids are derivable from the
|
||||||
|
product identity, and identity changes are migrations" — made safe by the succession
|
||||||
|
ledger (§2). `renamed_from` still gates preset-name compatibility as before.
|
||||||
|
- CLI: `--mint "Polymaker/PLA/PolyLite PLA"` prints without touching the tree; running
|
||||||
|
the script plain inserts missing ids; CI errors print the expected id.
|
||||||
|
|
||||||
|
## 2. The succession ledger (the amendment that makes this safe)
|
||||||
|
|
||||||
|
Shipped ids are referenced outside the tree: AFC/Klipper lane data, Bambu AMS trays
|
||||||
|
holding OFL-only materials, on-device PA-calibration records, user-root preset copies,
|
||||||
|
3mf `slice_info`. Retiring an id without a forwarding pointer downgrades all of those to
|
||||||
|
`Generic <type>` fallbacks. Therefore:
|
||||||
|
|
||||||
|
- **Schema.** `scripts/retired_filament_ids.json` entries become objects:
|
||||||
|
`{"retired": {"OGFL99": {"claims": [...], "successor": "OFxxxxxx"}}}`. Append-only as
|
||||||
|
before; a successor may itself be retired later (chains allowed, cycle-checked, and
|
||||||
|
followed to the live end). A retired id may never be minted again (check 4 unchanged).
|
||||||
|
Cross-island *hint* entries are permitted for ids Orca cannot retire because another
|
||||||
|
island owns them (e.g. `GFL99 → <OFL Generic PLA id>`): consulted only when no live
|
||||||
|
preset matches, so BBL installs still resolve `GFL99` natively first. By the same
|
||||||
|
principle, an id in a foreign island's space (`GF*`/`QD_*`) that vanishes from the tree
|
||||||
|
is **released with a hint, never retired** — the island's catalog owns it and may
|
||||||
|
legitimately (re)ship it later, which check 4 must never block. (Implementation
|
||||||
|
amendment, v3.0: `--update-snapshot` routes such ids to `hints` automatically; hint
|
||||||
|
keys may be absent from the tree.)
|
||||||
|
- **Shipped and consulted at runtime.** The ledger ships in `resources/`; a small helper
|
||||||
|
(`resolve_filament_id_succession(id)`) follows the chain and is consulted **only on
|
||||||
|
resolution miss**, before the `Generic <type>` name fallback, in:
|
||||||
|
`PresetBundle::get_filament_by_filament_id` (covers `DevFilaBlackList`, `SelectMachine`
|
||||||
|
warnings, `Plater` tray configs in one place), the AMS sync match predicates
|
||||||
|
(`PresetBundle.cpp:3151`, `:3252-3254` miss paths at `:3157-3169`/`:3260-3305`),
|
||||||
|
`PresetComboBoxes::add_ams_filaments`, `MachineObject::setting_id_to_type`
|
||||||
|
(`DeviceManager.cpp:2545` miss branch), calibration-history name lookup
|
||||||
|
(`CaliHistoryDialog.cpp:62`), and the #14423 Moonraker lane matching when it lands.
|
||||||
|
With this in place the OFL re-mint is near-residue-free and every future
|
||||||
|
content-addressed rename stays safe.
|
||||||
|
- **Kill the hardcoded generic map.** `MoonrakerPrinterAgent::map_filament_type_to_generic_id`
|
||||||
|
(`MoonrakerPrinterAgent.cpp:608-658`) hardcodes 23 OFL ids (`OGFL99`… `OFLSBS99`).
|
||||||
|
Replace it with a runtime lookup of the OFL generic preset by name ("Generic PLA
|
||||||
|
@System" → its current id), removing the code↔profile lockstep permanently. (This also
|
||||||
|
releases `OFLSBS99`, v2's one frozen OF-shaped legacy id, for normal re-minting.)
|
||||||
|
|
||||||
|
## 3. Validation rule changes
|
||||||
|
|
||||||
|
- **Check 3 (mint conformance)** becomes a pure function of the root's triple: a non-BBL,
|
||||||
|
non-`QD_*` id must equal `mint(triple)` ± salt, or be snapshot-grandfathered (the
|
||||||
|
grandfather set shrinks to ≈ nothing for non-BBL once migration completes).
|
||||||
|
- **Check 5 (alias hygiene) generalizes and becomes load-bearing.** For *every*
|
||||||
|
OFL-carried family (not just `Generic * @System`): a vendor specialization must keep the
|
||||||
|
OFL base name (else the OFL preset un-shadows and creates a live per-printer duplicate —
|
||||||
|
v1's P7 pattern) and non-empty `compatible_printers`, and must not declare an id. The
|
||||||
|
C++ validator's OFL-aware `-f` (`PresetBundle.cpp:5674-5753`) already enforces the
|
||||||
|
runtime consequence; the script check names the rename as the cause.
|
||||||
|
- **New check 8 (triple integrity):** every id-declaring family resolves a complete,
|
||||||
|
family-consistent triple; roots missing `filament_vendor`/`filament_type` error.
|
||||||
|
- **New check 9 (succession integrity):** every retired entry's successor chain ends at a
|
||||||
|
live tree id (or a documented cross-island hint target); no cycles; retired ids absent
|
||||||
|
from the tree.
|
||||||
|
- Snapshot mechanism, reserved spaces (`GF*`→BBL, `QD_*`→Qidi, `P`-hex/`null`→user-custom;
|
||||||
|
v2's do-not-reserve-`OF*` note stands), and check 1/2/4/7 are unchanged.
|
||||||
|
|
||||||
|
## 4. Migration phases
|
||||||
|
|
||||||
|
**v3.0 — tooling + prerequisites (no profile changes).** New mint + triple resolver
|
||||||
|
(reuse the flatten machinery), succession schema migration + C++ lookup helper wired into
|
||||||
|
the §2 miss paths, Moonraker map → runtime lookup, checks 3/5/8/9, tests. Carry v2's W1
|
||||||
|
client hardening (skip tray-wipe/temp-rewrite when a system preset holds the id; relax
|
||||||
|
the `DeviceManager.cpp:5252` assert; guard the `PresetBundle.cpp:3717` deref) — it ships
|
||||||
|
first regardless. **W3 type fixes land here**, *before* any re-mint: type is now a key
|
||||||
|
component, so minting before fixing OFL `Generic PETG-CF`/`Generic PE-CF` would re-id
|
||||||
|
those families twice.
|
||||||
|
|
||||||
|
**v3.1 — OFL re-mint.** Every OFL-declared id re-derives from its triple (mirrors like
|
||||||
|
`OGFA00`, generics like `OGFL99`, blocks like `OEPLAB00` — all of it); each old shipped id
|
||||||
|
gains a succession entry pointing at its replacement; the 26 GF-shaped ids OFL declares
|
||||||
|
(measured at v3.0: only one of them, `GFOT001`, is also declared by BBL) are released to
|
||||||
|
the BBL island space with hints at the re-minted families — two-island purity. Snapshot
|
||||||
|
regenerated; full gate battery + fixture overlays (this phase touches preset-visibility
|
||||||
|
machinery only via ids, but the fixtures are cheap insurance). Implementation notes
|
||||||
|
(v3.1, executed): OFL generic ids relocate from the fdm_filament_* template bases onto
|
||||||
|
the product-named "Generic X @System" presets first, so their triples carry the product
|
||||||
|
name; `fdm_filament_pc` keeps a (transitional) declaration because 7 Prusa presets
|
||||||
|
inherit it directly — the v3.2 Prusa worksheet re-homes them and deletes it.
|
||||||
|
|
||||||
|
**v3.2 — vendor bundles, worksheet-per-vendor (v1 machinery).** Three sub-cases:
|
||||||
|
(a) the **391 unshipped v1 `OF*` mints** re-derive under the triple key — no succession
|
||||||
|
entries (they never shipped; a documented one-time `--forget-never-shipped <list>` drops
|
||||||
|
them from the ledger lineage instead of retiring them, since the ledger's rationale —
|
||||||
|
ids live on in user presets and 3mfs — cannot apply to unreleased ids);
|
||||||
|
(b) **true generic tunings** riding copied legacy ids (`GFL99`-class) drop their own id
|
||||||
|
and re-point to the OFL generic family (the v1 Sovol pattern) — their old ids get
|
||||||
|
cross-island hints where BBL owns them, succession entries otherwise;
|
||||||
|
(c) remaining **shipped legacy ids** (numeric, name-shaped, pseudo-GF, the 57
|
||||||
|
multi-vendor GF residue, the 10 P-hex — everything non-BBL/non-`QD_*`, ~800 ids)
|
||||||
|
re-mint with succession entries. Retiring the 10 P-hex system ids also removes the last
|
||||||
|
system ids from `check_ams_filament_valid`'s destructive P-gate.
|
||||||
|
|
||||||
|
**v3.3 — ongoing consolidation (optional, per-vendor, id-stable).** Hoist vendor-unique
|
||||||
|
products into OFL where a family is genuinely multi-vendor material; thanks to the
|
||||||
|
bundle-independent key this never changes ids, so it can proceed opportunistically.
|
||||||
|
|
||||||
|
## 5. Gates (every phase)
|
||||||
|
|
||||||
|
`python scripts/orca_extra_profile_check.py` exit 0; `assign_filament_ids.py --check`
|
||||||
|
exit 0; unit tests green (existing 46 + new triple/succession/adoption tests); validator
|
||||||
|
`-l 2` exit 0, `-f` tree-wide exit 0, `-r` BBL+Qidi exit 0; custom-preset fixture
|
||||||
|
archives; config-equivalence — flattened effective configs differ only in `filament_id`
|
||||||
|
(re-mints), `inherits`/`compatible_printers` (re-points, as prescribed per worksheet), and
|
||||||
|
the W3 `filament_type` corrections. New for v3: a C++ test that a retired id resolves
|
||||||
|
through the succession chain in the sync miss path, and a Moonraker test that the generic
|
||||||
|
map lookup matches the shipped OFL presets. Manual AMS smoke test (tray set → old-id
|
||||||
|
resolve → clear) stays a release-checklist item.
|
||||||
|
|
||||||
|
## 6. Accepted costs (explicit)
|
||||||
|
|
||||||
|
- **GF ↔ OFL divergence is permanent** for products in both catalogs (PolyLite PLA ≠
|
||||||
|
`GFL00` outside BBL). The forward-looking fix is PR #12724-style filament-database
|
||||||
|
upload, where Orca ids become first-class device artifacts.
|
||||||
|
- **Renames/type-fixes re-id families** (by design); the succession ledger absorbs the
|
||||||
|
device/user residue, but each one is still a ledger entry and a snapshot diff to review.
|
||||||
|
- **User roots** keep whatever id they copied at creation; with succession lookup in
|
||||||
|
`get_filament_by_filament_id` they now *resolve* instead of dangling — strictly better
|
||||||
|
than v1's accepted residue.
|
||||||
|
- **One-time field transition**: devices holding pre-v3 ids (AFC lanes, AMS trays, cali
|
||||||
|
records) resolve via succession on updated clients; *older* Orca versions and
|
||||||
|
BambuStudio never resolved OFL-only ids anyway (`?`/generic fallback — unchanged for
|
||||||
|
them).
|
||||||
|
|
||||||
|
## 7. Open decisions
|
||||||
|
|
||||||
|
1. Whether v3.2(b)'s cross-island hints (`GFL99` → OFL generic) are wanted at launch or
|
||||||
|
deferred (pure-miss-path feature; zero risk to BBL installs, small review surface).
|
||||||
|
2. v3.3 pacing: per-vendor PRs opportunistically vs. a dedicated consolidation train.
|
||||||
|
3. Whether to fold v2's W5 (P+md5 ids for inherited *user* presets, PR #13315) into v3.0's
|
||||||
|
C++ work or keep it a separate PR (recommended: separate; W1 is its only prerequisite).
|
||||||
|
|
||||||
|
## 8. Evidence
|
||||||
|
|
||||||
|
Carried from v2 §8 (all re-verified this session), plus: `filament_vendor` audit — 49
|
||||||
|
distinct strings tree-wide, `"Polymaker"` byte-consistent across all five PolyLite-PLA
|
||||||
|
bundles; multi-vendor different-family GF residue = 57 ids; `MoonrakerPrinterAgent.cpp:
|
||||||
|
608-658` = 23 hardcoded OFL ids; mint examples verified live (`Qidi/PolyLite PLA` →
|
||||||
|
`OFceJcLf` under the v1 key — the fragmentation this plan removes; salt determinism
|
||||||
|
`OF8afiMO`). Alias shadowing and the OFL id fallback verified at `Preset.cpp:3684-3714`
|
||||||
|
and `PresetBundle.cpp:4842-5080` during the v1 audit; per-printer `-f` semantics at
|
||||||
|
`PresetBundle.cpp:5674-5753`.
|
||||||
224
filament_id_plan_v4.md
Normal file
224
filament_id_plan_v4.md
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# filament_id plan v4: dissolve the Qidi `QD_*` island
|
||||||
|
|
||||||
|
Supersedes §0.2 of `filament_id_plan_v3.md` (the "`QD_*` island — untouched, forever"
|
||||||
|
decision) and amends every v3 section that carved out `QD_*`. Everything else in v3 —
|
||||||
|
the mint rule, the succession ledger, the BBL island, checks 1–9 — stands as
|
||||||
|
implemented (v3.0–v3.2, all gates green at commit `f7c1b290fd`).
|
||||||
|
|
||||||
|
Decision driver: the island contradicts the catalog architecture v3 built. Qidi presets
|
||||||
|
carry 204 `QD_<series>_<vendor>_<typeidx>` ids over 264 declarations (49 families,
|
||||||
|
measured 2026-08-21) — one commercial product carries up to *five* ids (one per printer
|
||||||
|
series: `QIDI PLA Rapido` = `QD_0_1_1` … `QD_4_1_1`), which is exactly the
|
||||||
|
fragmentation v3 exists to remove. The island was frozen because Qidi's filament box
|
||||||
|
composes these ids from device enums and requires exactly-matching presets
|
||||||
|
(`QidiPrinterAgent.cpp:146-152`). But v3.0 shipped the machinery that makes freezing
|
||||||
|
unnecessary: the succession ledger already translates retired ids on resolution miss.
|
||||||
|
`QD_*` stops being a *preset id space* and becomes a *device protocol namespace*,
|
||||||
|
translated once at the agent edge.
|
||||||
|
|
||||||
|
## 0. The architecture change
|
||||||
|
|
||||||
|
Two tiers, **one** frozen island:
|
||||||
|
|
||||||
|
1. **BBL island — untouched, unchanged.** All v3 reasoning holds (device/RFID/cloud
|
||||||
|
contract is external and opaque).
|
||||||
|
2. **Everything else converges on OFL product ids — now including Qidi.** All 204
|
||||||
|
`QD_*` ids re-mint from their family triples and gain **retired** ledger entries
|
||||||
|
(not cross-island hints: after dissolution there is no island to own them, and
|
||||||
|
check 4's "never again" is exactly the guard we want against upstream re-adding
|
||||||
|
them). The box keeps working because `QidiPrinterAgent` resolves its composed
|
||||||
|
`QD_*` id through `resolve_filament_id_succession()` on miss — the same mechanism
|
||||||
|
every other retired id already uses.
|
||||||
|
|
||||||
|
Why retire rather than hint (the one real design choice here): hints exist for ids a
|
||||||
|
*foreign catalog* owns and may legitimately re-ship (`GF*`). Post-dissolution, nothing
|
||||||
|
may ever re-ship a `QD_*` id in the profile tree — the device composes them at
|
||||||
|
runtime, the tree translates them. Retired entries make CI enforce that permanently
|
||||||
|
(`--update-snapshot` refuses resurrections, check 4 refuses occurrences); hints would
|
||||||
|
permit re-shipping, which is now always a regression. The QD→family mapping is
|
||||||
|
strictly 1:1 (verified: no `QD_*` id is claimed by more than one family), so the
|
||||||
|
mode-rule successor is unambiguous for every entry.
|
||||||
|
|
||||||
|
## 1. What the dissolution consists of
|
||||||
|
|
||||||
|
Three independent work packages, ordered for bisectability:
|
||||||
|
|
||||||
|
- **(A) Re-converge the drifted tree** — prerequisite, not Qidi-specific. The
|
||||||
|
2026-07 main merge (`f3fa3a34bd`) brought upstream vendor updates in pre-v3 style:
|
||||||
|
`--check` currently exits with **243 errors** (123 unsanctioned new ids, 46 new
|
||||||
|
instantiated own-key presets, 31 override drifts, 18 reserved-space claims, 5
|
||||||
|
hint-keys re-declared — Qidi re-added `GFB99`/`GFG99`/`GFL99`, Snapmaker re-added
|
||||||
|
`GFG96`/`GFU99` and even four *retired* ids incl. `OGFL99`, plus Snapmaker U1
|
||||||
|
triple errors and a GreenGate3D rename). This is the standing WF-B maintenance
|
||||||
|
pass; the dissolution's gates cannot go green on a red base.
|
||||||
|
- **(B) C++ succession hook in the Qidi agent** — safe to land before any data
|
||||||
|
changes (pure miss-path: while `QD_*` presets still exist, the hook never fires).
|
||||||
|
- **(C) The dissolution proper** — tooling flip + Qidi data fixes + re-mint +
|
||||||
|
snapshot/ledger regeneration, one vendor worksheet in the v3.2 mold.
|
||||||
|
|
||||||
|
## 2. Runtime translation (work package B)
|
||||||
|
|
||||||
|
`QidiPrinterAgent.cpp:183-192` currently: compose `setting_id` → keep it if a visible
|
||||||
|
base preset declares it → else degrade to `filament_id_by_type(tray_type)` (i.e. every
|
||||||
|
QIDI-brand box slot silently becomes Generic once the ids re-mint). Insert the
|
||||||
|
succession walk between those two steps:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
} else if (!setting_id.empty() && has_visible_base_preset(bundle->filaments, setting_id)) {
|
||||||
|
tray.tray_info_idx = setting_id;
|
||||||
|
} else {
|
||||||
|
// Retired QD_* protocol ids forward to their minted successors via the shipped ledger.
|
||||||
|
const std::string successor = setting_id.empty() ? std::string()
|
||||||
|
: resolve_filament_id_succession(setting_id);
|
||||||
|
if (!successor.empty() && has_visible_base_preset(bundle->filaments, successor))
|
||||||
|
tray.tray_info_idx = successor;
|
||||||
|
else
|
||||||
|
tray.tray_info_idx = bundle->filaments.filament_id_by_type(tray.tray_type);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`resolve_filament_id_succession` is `Preset.hpp:119` (loads once, cycle-guarded,
|
||||||
|
empty-safe) — no new includes needed beyond what the file already reaches through
|
||||||
|
`PresetBundle`. This one hook covers both composition paths: the numeric-series
|
||||||
|
`build_setting_id` lambda *and* the non-numeric fallback
|
||||||
|
`map_filament_type_to_setting_id` (`:325-342`), whose four hardcoded returns
|
||||||
|
(`QD_1_0_1`/`_11`/`_41`/`_50` = Generic PLA/ABS/PETG/TPU 95A) become ledger keys in
|
||||||
|
package C. Keep that function as-is but extend its comment: the returned ids are
|
||||||
|
retired ledger keys by design, and `scripts/tests/test_filament_id.py` parses the
|
||||||
|
initializer (see §4 tests) — the Moonraker treatment (`MoonrakerPrinterAgent.cpp:
|
||||||
|
619-627`) of replacing the table with name lookups was considered and not taken: the
|
||||||
|
table already routes through the same ledger as the composed ids, and two translation
|
||||||
|
mechanisms in one agent is worse than one.
|
||||||
|
|
||||||
|
Tests (same commit):
|
||||||
|
|
||||||
|
- `tests/libslic3r/test_filament_id_succession.cpp`: add a section asserting a
|
||||||
|
`QD_`-shaped key forwards like any other (`{"QD_2_1_11", "OFnew001"}` resolves to
|
||||||
|
`"OFnew001"`) — pins that the walk is prefix-agnostic.
|
||||||
|
- `scripts/tests/test_filament_id.py`: new test parsing the four `QD_` literals out of
|
||||||
|
`QidiPrinterAgent.cpp::map_filament_type_to_setting_id` (mirror the parser in
|
||||||
|
`scripts/test_moonraker_lane_data.py`) and asserting each is a ledger key whose
|
||||||
|
chain terminates at a live tree id. **Add it marked expected-fail/skipped until
|
||||||
|
package C lands, then flip it on** — it is the permanent code↔ledger lockstep guard.
|
||||||
|
|
||||||
|
## 3. Tooling and validation flip (work package C, first commit)
|
||||||
|
|
||||||
|
All in `scripts/assign_filament_ids.py`; every touched line measured 2026-08-21:
|
||||||
|
|
||||||
|
- `is_island_declaration` (`:327-329`) → `return vendor == "BBL"`. This single change
|
||||||
|
pulls every `QD_*` declarer into the triple bookkeeping (`:385`) and thus into
|
||||||
|
checks 3 and 8, into `--remint`'s domain (`:1464`), and out of the hint-key
|
||||||
|
tolerances (`:877`, `:1100`).
|
||||||
|
- `reserved_space_owner` (`:596-604`): `QD_*` returns `(True, None)` — reserved,
|
||||||
|
ownerless, exactly like the P-hex/user-custom space. Consequences, all wanted:
|
||||||
|
check 6 refuses any future vendor claim; the `--update-snapshot` sanction gate
|
||||||
|
(`:938-963`) refuses new `QD_*` ids outright; the vanish path (`:994`) routes
|
||||||
|
`QD_*` to **retired** (owner `None` ≠ island), not released-with-hint. Update the
|
||||||
|
two message sites that render `owner is None` as "reserved for user-custom presets"
|
||||||
|
(`:628` docstring, `:958`, and check 6's copy) to name the space generically or
|
||||||
|
special-case `QD_*` ("Qidi device protocol; dissolved island — retired, never
|
||||||
|
declarable").
|
||||||
|
- Check 1 (`:667-668`): delete the `vendor == "Qidi" and fid.startswith("QD_")`
|
||||||
|
exemption.
|
||||||
|
- Module docstring (`:27-45`): rewrite the `QD_*` bullet — reserved space stays
|
||||||
|
listed, but as "device protocol namespace, translated via the succession ledger;
|
||||||
|
dissolved as a catalog island in v4, may never be declared".
|
||||||
|
- `scripts/tests/test_filament_id.py`: update the three island assertions —
|
||||||
|
`reserved_space_owner("QD_X4_PLA")` → `(True, None)` (`:403`),
|
||||||
|
`is_island_declaration("Qidi", "QD_X4_PLA")` → `False` (`:413`), and the
|
||||||
|
reserved-space message case (`:570`).
|
||||||
|
|
||||||
|
No changes to the ledger schema, the C++ checks, `--retire` (post-flip it accepts
|
||||||
|
`QD_*` olds automatically — they are non-island now), or the validator: check 3's
|
||||||
|
"non-BBL, non-`QD_*`" phrasing in v3 §3 was always implemented as "non-island", so the
|
||||||
|
flip *is* the spec change.
|
||||||
|
|
||||||
|
## 4. Migration phases
|
||||||
|
|
||||||
|
**v4.0 — re-converge the drifted tree (package A).** Per-vendor WF-B worksheets over
|
||||||
|
the 243 errors: Snapmaker U1 (triple divergence `Generic|Snapmaker|snapmaker`, empty
|
||||||
|
vendors, four resurrected retired ids — these force re-mints since retirement is
|
||||||
|
permanent), BBL/addnorth `GF_AN*` overrides (BBL island: grandfather via snapshot,
|
||||||
|
they are BBL-internal), Qidi/Snapmaker re-declared hint keys (re-mint those declarers,
|
||||||
|
the check's own prescription), GreenGate3D rename, then `--update-snapshot` (new
|
||||||
|
upstream `QD_*` ids sanction cleanly — the island is still intact in this phase) and
|
||||||
|
the full v3 §5 gate battery. Bump `version` in every touched
|
||||||
|
`resources/profiles/<Vendor>.json`. **Do not start v4.2 until `--check` exits 0.**
|
||||||
|
|
||||||
|
**v4.1 — the agent hook (package B).** §2 as written; `libslic3r_tests` +
|
||||||
|
`scripts/tests/test_filament_id.py` green; behavior-neutral by construction (no `QD_*`
|
||||||
|
ledger entries exist yet).
|
||||||
|
|
||||||
|
**v4.2 — the dissolution (package C).** One Qidi worksheet, v3.2 machinery:
|
||||||
|
|
||||||
|
1. Tooling flip commit (§3). `--check` now reports the Qidi island as
|
||||||
|
non-conformant — expected, red only between commits of this phase.
|
||||||
|
2. Data fixes, before any re-mint (the v3 "W3 lands first" lesson — type/vendor are
|
||||||
|
key components): add `filament_vendor: ["QIDI"]` at each QIDI-brand family's
|
||||||
|
inheritance apex so all declarers resolve it (39 of 49 families currently resolve
|
||||||
|
none — check 8a would refuse the mint). Verify the six Generic families
|
||||||
|
(`Generic PLA/ABS/PETG/PC/TPU 95A/PLA Silk`) resolve triples identical to their
|
||||||
|
OFL counterparts (vendor `Generic`, OFL's `filament_type`) so they *converge onto
|
||||||
|
the OFL ids* by triple math — the whole point; any mismatch is a W3-style data fix
|
||||||
|
here, not a fork. No `inherits`/`compatible_printers` re-pointing anywhere: the
|
||||||
|
series intermediates (`Generic PLA@Q2-Series` etc., all `instantiation: false`)
|
||||||
|
simply keep declarations whose values become the OFL ids.
|
||||||
|
3. `python scripts/assign_filament_ids.py --remint Qidi` — rewrites all 264
|
||||||
|
declarations in place to their family mints (same triple ⇒ same id across a
|
||||||
|
family's series intermediates and per-nozzle declarers; convergence with OFL ids
|
||||||
|
is legal by design, `want_id` already permits same-triple collisions `:1447`).
|
||||||
|
4. `--update-snapshot` — retires every vanished `QD_*` id with its mode-rule
|
||||||
|
successor. **Audit the ledger diff: all ~204 new entries must be `QD_*`→non-null.**
|
||||||
|
A null successor (possible only for a declared-only id with zero instantiated
|
||||||
|
claims) gets an explicit `--retire "QD_x=OFy"` with the family's minted id.
|
||||||
|
5. Un-skip the §2 lockstep test. Bump `resources/profiles/Qidi.json` version. Full
|
||||||
|
gate battery (§5).
|
||||||
|
|
||||||
|
Known residue, accepted: `QIDI PC-ABS-FR` (series 1–2) vs `QIDI PC/ABS-FR`
|
||||||
|
(series 3–4) are two preset-name families for one product → two ids. Renames were
|
||||||
|
ruled out in v3 (`renamed_from` rejected for migrations); if upstream ever unifies the
|
||||||
|
name, content-addressing re-ids and the ledger absorbs it — self-healing, no action
|
||||||
|
now.
|
||||||
|
|
||||||
|
**v4.3 — OFL consolidation (unchanged).** v3.3 stays optional and id-stable; QIDI-brand
|
||||||
|
families are vendor-unique and stay in the Qidi bundle.
|
||||||
|
|
||||||
|
## 5. Gates (per phase, delta from v3 §5)
|
||||||
|
|
||||||
|
Unchanged battery: `orca_extra_profile_check.py` exit 0, `assign_filament_ids.py
|
||||||
|
--check` exit 0, `scripts/tests/test_filament_id.py` all green, `libslic3r_tests`
|
||||||
|
green, validator `-l 2` tree-wide + `-f` tree-wide + `-v Qidi` exit 0, custom-preset
|
||||||
|
fixture archives (v4.2 touches no preset visibility, but they are cheap insurance —
|
||||||
|
run them for v4.0, which touches instantiation-adjacent upstream drift), flatten
|
||||||
|
config-equivalence. New for v4.2: equivalence diff may contain **only** `filament_id`
|
||||||
|
value changes (QD→OF) and the added `filament_vendor` keys on QIDI-brand families;
|
||||||
|
ledger diff audit per §4.4; the map-literal lockstep test. Manual release-checklist
|
||||||
|
item: Qidi box smoke test — slot holding a QIDI-brand material must surface the brand
|
||||||
|
preset (not Generic) on an updated client, via the memory-documented local Klipper
|
||||||
|
test rig.
|
||||||
|
|
||||||
|
## 6. Accepted costs (explicit, new relative to v3)
|
||||||
|
|
||||||
|
- **Every Qidi box slot resolves through the ledger miss-path forever** (one hash-map
|
||||||
|
walk per slot per status poll — negligible, and structurally identical to how
|
||||||
|
every retired id already resolves). The QD→OF translation table is maintained by
|
||||||
|
the retirement machinery, not by hand.
|
||||||
|
- **Older Orca clients** (pre-v4 profiles) paired with re-minted profile trees lose
|
||||||
|
QIDI-brand slot matching (they look up `QD_*` and fall back generic-by-type — the
|
||||||
|
degradation the hook removes for updated clients). Same one-time field-transition
|
||||||
|
shape v3 §6 already accepted for AMS/AFC ids.
|
||||||
|
- **Two ids for PC-ABS-FR** until upstream unifies the family name (§4 residue).
|
||||||
|
|
||||||
|
## 7. Evidence
|
||||||
|
|
||||||
|
Measured on this tree 2026-08-21 unless cited to v3: 204 distinct `QD_*` ids / 264
|
||||||
|
declaring presets / 49 families, QD→family strictly 1:1, per-series id sets
|
||||||
|
(`QD_0..4_1_1` = `QIDI PLA Rapido` etc.); 39 families resolve no `filament_vendor`;
|
||||||
|
declarations live on `instantiation:false` series intermediates (Q2/Q2C/X5/X4) and
|
||||||
|
per-nozzle X-Plus-4 presets; composition + miss-fallback at
|
||||||
|
`QidiPrinterAgent.cpp:146-152, 183-192`, hardcoded fallback table `:325-342`;
|
||||||
|
succession helpers `Preset.hpp:109-119`; ledger = 575 retired + 194 hints, zero `QD_*`
|
||||||
|
entries; snapshot holds 160 of the 204 (the 44 newcomers are post-merge drift);
|
||||||
|
`--check` = 243 errors, categorized in §1(A); island exemption mechanics at
|
||||||
|
`assign_filament_ids.py:327-329, 385, 596-604, 667, 877, 994, 1464, 1514`; `--remint`
|
||||||
|
same-triple convergence guard `:1447-1453`; retirement-permanence gate `:965-976`.
|
||||||
@@ -193,6 +193,7 @@ src/slic3r/GUI/ObjColorDialog.cpp
|
|||||||
src/slic3r/GUI/SyncAmsInfoDialog.cpp
|
src/slic3r/GUI/SyncAmsInfoDialog.cpp
|
||||||
src/slic3r/GUI/WipeTowerDialog.cpp
|
src/slic3r/GUI/WipeTowerDialog.cpp
|
||||||
src/slic3r/GUI/wxExtensions.cpp
|
src/slic3r/GUI/wxExtensions.cpp
|
||||||
|
src/slic3r/GUI/wxMediaCtrl2.cpp
|
||||||
src/slic3r/GUI/WebUserLoginDialog.cpp
|
src/slic3r/GUI/WebUserLoginDialog.cpp
|
||||||
src/slic3r/GUI/WebGuideDialog.cpp
|
src/slic3r/GUI/WebGuideDialog.cpp
|
||||||
src/slic3r/GUI/KBShortcutsDialog.hpp
|
src/slic3r/GUI/KBShortcutsDialog.hpp
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4142,10 +4142,10 @@ msgid "PA Profile"
|
|||||||
msgstr "Профіль PA"
|
msgstr "Профіль PA"
|
||||||
|
|
||||||
msgid "Factor K"
|
msgid "Factor K"
|
||||||
msgstr "Коеф. K"
|
msgstr "Коэф. K"
|
||||||
|
|
||||||
msgid "Factor N"
|
msgid "Factor N"
|
||||||
msgstr "Коеф. N"
|
msgstr "Коэф. N"
|
||||||
|
|
||||||
msgid "Setting AMS slot information while printing is not supported"
|
msgid "Setting AMS slot information while printing is not supported"
|
||||||
msgstr "Зміна інформації про слоти AMS під час друку не підтримується"
|
msgstr "Зміна інформації про слоти AMS під час друку не підтримується"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 579 KiB After Width: | Height: | Size: 171 KiB |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"filament_id": "GFB00_01",
|
"filament_id": "OFLfywkp",
|
||||||
"setting_id": "wAJTMxtCY7EoavRi",
|
"setting_id": "wAJTMxtCY7EoavRi",
|
||||||
"name": "Afinia ABS+@HS",
|
"name": "Afinia ABS+@HS",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"filament_id": "GFB00_01",
|
"filament_id": "OFV5wEMe",
|
||||||
"setting_id": "qCDnb2iBaz4hd4vX",
|
"setting_id": "qCDnb2iBaz4hd4vX",
|
||||||
"name": "Afinia ABS@HS",
|
"name": "Afinia ABS@HS",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"filament_id": "GFA00_01",
|
"filament_id": "OF9HCdyQ",
|
||||||
"setting_id": "N3sCgjdjvp6FTtw9",
|
"setting_id": "N3sCgjdjvp6FTtw9",
|
||||||
"name": "Afinia PLA@HS",
|
"name": "Afinia PLA@HS",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "zUqTgAEbqTN1EdRl",
|
"setting_id": "zUqTgAEbqTN1EdRl",
|
||||||
"filament_id": "GFU01_01",
|
"filament_id": "OFDJU6R3",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_vendor": [
|
"filament_vendor": [
|
||||||
"Afinia"
|
"Afinia"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"filament_id": "GFB00_01",
|
"filament_id": "OFXi59OX",
|
||||||
"setting_id": "OxIiEYjbhEvSykaQ",
|
"setting_id": "OxIiEYjbhEvSykaQ",
|
||||||
"name": "Afinia Value ABS@HS",
|
"name": "Afinia Value ABS@HS",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "filament",
|
"type": "filament",
|
||||||
"filament_id": "GFA00_01",
|
"filament_id": "OFgHh8ly",
|
||||||
"setting_id": "BASsUdyvElEVJ9AA",
|
"setting_id": "BASsUdyvElEVJ9AA",
|
||||||
"name": "Afinia Value PLA@HS",
|
"name": "Afinia Value PLA@HS",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic ABS @base",
|
"name": "Anker Generic ABS @base",
|
||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF3P0BQA",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic ASA @base",
|
"name": "Anker Generic ASA @base",
|
||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFB98",
|
"filament_id": "OFRiyes1",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic PA @base",
|
"name": "Anker Generic PA @base",
|
||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFN99",
|
"filament_id": "OFMgJQCZ",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PA-CF @base",
|
"name": "Anker Generic PA-CF @base",
|
||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFN98",
|
"filament_id": "OF7uE5KB",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PA-CF"
|
"PA-CF"
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic PC @base",
|
"name": "Anker Generic PC @base",
|
||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFC99",
|
"filament_id": "OFGPJxnt",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PETG @base",
|
"name": "Anker Generic PETG @base",
|
||||||
"inherits": "fdm_filament_pet",
|
"inherits": "fdm_filament_pet",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFG99",
|
"filament_id": "OFgvOmM2",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PETG"
|
"PETG"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PETG-CF @base",
|
"name": "Anker Generic PETG-CF @base",
|
||||||
"inherits": "fdm_filament_pet",
|
"inherits": "fdm_filament_pet",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFG98",
|
"filament_id": "OF1daEUW",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PETG-CF"
|
"PETG-CF"
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic PLA @base",
|
"name": "Anker Generic PLA @base",
|
||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFL99",
|
"filament_id": "OFndmfJ1",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PLA Silk @base",
|
"name": "Anker Generic PLA Silk @base",
|
||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFL96",
|
"filament_id": "OFXyyfX6",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_cost": [
|
"filament_cost": [
|
||||||
"20"
|
"20"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PLA+ @base",
|
"name": "Anker Generic PLA+ @base",
|
||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFL95",
|
"filament_id": "OFIYTy8S",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_cost": [
|
"filament_cost": [
|
||||||
"25"
|
"25"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic PLA-CF @base",
|
"name": "Anker Generic PLA-CF @base",
|
||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFL98",
|
"filament_id": "OFB0a3hT",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PLA-CF"
|
"PLA-CF"
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"name": "Anker Generic PVA @base",
|
"name": "Anker Generic PVA @base",
|
||||||
"inherits": "fdm_filament_pva",
|
"inherits": "fdm_filament_pva",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFS99",
|
"filament_id": "OFsCbVbN",
|
||||||
"instantiation": "false"
|
"instantiation": "false"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "Anker Generic TPU @base",
|
"name": "Anker Generic TPU @base",
|
||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"filament_id": "GFU99",
|
"filament_id": "OF6tKa1Z",
|
||||||
"instantiation": "false",
|
"instantiation": "false",
|
||||||
"filament_retraction_speed": "90",
|
"filament_retraction_speed": "90",
|
||||||
"filament_deretraction_speed": "50",
|
"filament_deretraction_speed": "50",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "RDI26qeSRSTe0PDg",
|
"setting_id": "RDI26qeSRSTe0PDg",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra 3 Max 0.4 nozzle"
|
"Anycubic ABS @Anycubic Kobra 3 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Moc1cylP6mmSQjlb",
|
"setting_id": "Moc1cylP6mmSQjlb",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra 3 Max 0.6 nozzle"
|
"Anycubic ABS @Anycubic Kobra 3 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "2xgfnUKyOUQwYWPa",
|
"setting_id": "2xgfnUKyOUQwYWPa",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra 3 Max 0.8 nozzle"
|
"Anycubic ABS @Anycubic Kobra 3 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "NOiAgxA0BbvLhR1v",
|
"setting_id": "NOiAgxA0BbvLhR1v",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra S1 0.4 nozzle"
|
"Anycubic ABS @Anycubic Kobra S1 0.4 nozzle"
|
||||||
],
|
],
|
||||||
|
"filament_vendor": [
|
||||||
|
"Anycubic"
|
||||||
|
],
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.95"
|
"0.95"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "MDWaiSjl89E6Edsn",
|
"setting_id": "MDWaiSjl89E6Edsn",
|
||||||
"filament_id": "GFABS",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra S1 Max 0.25 nozzle"
|
"Anycubic ABS @Anycubic Kobra S1 Max 0.25 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "wZjVYc7dBDSKRusJ",
|
"setting_id": "wZjVYc7dBDSKRusJ",
|
||||||
"filament_id": "GFABS",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic ABS @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "AbB6JtoPRsNgmxyy",
|
"setting_id": "AbB6JtoPRsNgmxyy",
|
||||||
"filament_id": "GFABS",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic ABS @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "exX565xnrLPkYkvu",
|
"setting_id": "exX565xnrLPkYkvu",
|
||||||
"filament_id": "GFABS",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic ABS @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "KeEk3yQZrKmJY9Q0",
|
"setting_id": "KeEk3yQZrKmJY9Q0",
|
||||||
"filament_id": "GFABS",
|
"filament_id": "OF223rZv",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ABS @Anycubic Kobra X 0.4 nozzle"
|
"Anycubic ABS @Anycubic Kobra X 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "Anycubic Generic ASA",
|
"inherits": "Anycubic Generic ASA",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "U66DGcpZeZ24VfPe",
|
"setting_id": "U66DGcpZeZ24VfPe",
|
||||||
"filament_id": "GFA99",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_vendor": [
|
"filament_vendor": [
|
||||||
"Anycubic"
|
"Anycubic"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "06j8OTuYw3Sh9BxL",
|
"setting_id": "06j8OTuYw3Sh9BxL",
|
||||||
"filament_id": "GFA99",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra 3 Max 0.6 nozzle"
|
"Anycubic ASA @Anycubic Kobra 3 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "s2XJm0JghCSUDzhh",
|
"setting_id": "s2XJm0JghCSUDzhh",
|
||||||
"filament_id": "GFA99",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra 3 Max 0.8 nozzle"
|
"Anycubic ASA @Anycubic Kobra 3 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "rf792xZNR7tRGKNg",
|
"setting_id": "rf792xZNR7tRGKNg",
|
||||||
"filament_id": "GFA99",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra S1 0.4 nozzle"
|
"Anycubic ASA @Anycubic Kobra S1 0.4 nozzle"
|
||||||
],
|
],
|
||||||
|
"filament_vendor": [
|
||||||
|
"Anycubic"
|
||||||
|
],
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.98"
|
"0.98"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,11 +4,14 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "wqK6AVf1mNkIOmnt",
|
"setting_id": "wqK6AVf1mNkIOmnt",
|
||||||
"filament_id": "GFASA",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra S1 Max 0.25 nozzle"
|
"Anycubic ASA @Anycubic Kobra S1 Max 0.25 nozzle"
|
||||||
],
|
],
|
||||||
|
"filament_vendor": [
|
||||||
|
"Anycubic"
|
||||||
|
],
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"ASA"
|
"ASA"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "aMgpooFosBBvlKKR",
|
"setting_id": "aMgpooFosBBvlKKR",
|
||||||
"filament_id": "GFASA",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic ASA @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Isk7NkdH7GxsEZkS",
|
"setting_id": "Isk7NkdH7GxsEZkS",
|
||||||
"filament_id": "GFASA",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic ASA @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Ew0Lg6u3e5Xj19Bz",
|
"setting_id": "Ew0Lg6u3e5Xj19Bz",
|
||||||
"filament_id": "GFASA",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic ASA @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "PEg6aLXcyUc70p9F",
|
"setting_id": "PEg6aLXcyUc70p9F",
|
||||||
"filament_id": "GFASA",
|
"filament_id": "OF0yFLkY",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic ASA @Anycubic Kobra X 0.4 nozzle"
|
"Anycubic ASA @Anycubic Kobra X 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_abs",
|
"inherits": "fdm_filament_abs",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "az6wmXeWSCKcUEsK",
|
"setting_id": "az6wmXeWSCKcUEsK",
|
||||||
"filament_id": "GFB99",
|
"filament_id": "OF5Zk4e1",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.926"
|
"0.926"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_asa",
|
"inherits": "fdm_filament_asa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "qKcef8t7nj8nBjPu",
|
"setting_id": "qKcef8t7nj8nBjPu",
|
||||||
"filament_id": "GFB98",
|
"filament_id": "OFI80Hct",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.93"
|
"0.93"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "j2PXsJyI9YyoE8lc",
|
"setting_id": "j2PXsJyI9YyoE8lc",
|
||||||
"filament_id": "GFN98",
|
"filament_id": "OFPdhDlK",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_type": [
|
"filament_type": [
|
||||||
"PA-CF"
|
"PA-CF"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "xzI6EgoKa3DFYyoZ",
|
"setting_id": "xzI6EgoKa3DFYyoZ",
|
||||||
"filament_id": "GFN99",
|
"filament_id": "OFB1Tv1E",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"nozzle_temperature_initial_layer": [
|
"nozzle_temperature_initial_layer": [
|
||||||
"280"
|
"280"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "3zgBtEkj1fQpDkxO",
|
"setting_id": "3zgBtEkj1fQpDkxO",
|
||||||
"filament_id": "GFC99",
|
"filament_id": "OFWY6vBh",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_max_volumetric_speed": [
|
"filament_max_volumetric_speed": [
|
||||||
"12"
|
"12"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pet",
|
"inherits": "fdm_filament_pet",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "CEd987NP90bPdkW7",
|
"setting_id": "CEd987NP90bPdkW7",
|
||||||
"filament_id": "GFG99",
|
"filament_id": "OFWzr7m0",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"reduce_fan_stop_start_freq": [
|
"reduce_fan_stop_start_freq": [
|
||||||
"1"
|
"1"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "9gFgyEJelaCIVwAH",
|
"setting_id": "9gFgyEJelaCIVwAH",
|
||||||
"filament_id": "GFL98",
|
"filament_id": "OFNcdCrm",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.95"
|
"0.95"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pla",
|
"inherits": "fdm_filament_pla",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "2MiX54GMiZjFzwBI",
|
"setting_id": "2MiX54GMiZjFzwBI",
|
||||||
"filament_id": "GFL99",
|
"filament_id": "OFKyCgaK",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.98"
|
"0.98"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pva",
|
"inherits": "fdm_filament_pva",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "I1GMbOsMYktU7EbM",
|
"setting_id": "I1GMbOsMYktU7EbM",
|
||||||
"filament_id": "GFS99",
|
"filament_id": "OFSGbf2I",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_flow_ratio": [
|
"filament_flow_ratio": [
|
||||||
"0.95"
|
"0.95"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "xrbLc7y1AInpumtv",
|
"setting_id": "xrbLc7y1AInpumtv",
|
||||||
"filament_id": "GFU99",
|
"filament_id": "OFGKLoUm",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_max_volumetric_speed": [
|
"filament_max_volumetric_speed": [
|
||||||
"3.2"
|
"3.2"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "hcL5OHthGzApICTk",
|
"setting_id": "hcL5OHthGzApICTk",
|
||||||
"filament_id": "GFPA",
|
"filament_id": "OFzS7zt4",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PA @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "OJbFCKoG5DtVGT9J",
|
"setting_id": "OJbFCKoG5DtVGT9J",
|
||||||
"filament_id": "GFPA",
|
"filament_id": "OFzS7zt4",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PA @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "6mMIVw8iheDn1OuV",
|
"setting_id": "6mMIVw8iheDn1OuV",
|
||||||
"filament_id": "GFPA",
|
"filament_id": "OFzS7zt4",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PA @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "epl6B2WNjV1dxG5Z",
|
"setting_id": "epl6B2WNjV1dxG5Z",
|
||||||
"filament_id": "GFPA6-CF",
|
"filament_id": "OFQe7sAx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "eMUXd3PFKHl41TIq",
|
"setting_id": "eMUXd3PFKHl41TIq",
|
||||||
"filament_id": "GFPA6-CF",
|
"filament_id": "OFQe7sAx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "y9XYrUJrUYKcBhCI",
|
"setting_id": "y9XYrUJrUYKcBhCI",
|
||||||
"filament_id": "GFPA6-CF",
|
"filament_id": "OFQe7sAx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PA6-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "nO6m8EaBKREWUi3f",
|
"setting_id": "nO6m8EaBKREWUi3f",
|
||||||
"filament_id": "GFPAHT-CF",
|
"filament_id": "OFaEuvNF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "ebKput7Vyn4IQez1",
|
"setting_id": "ebKput7Vyn4IQez1",
|
||||||
"filament_id": "GFPAHT-CF",
|
"filament_id": "OFaEuvNF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pa",
|
"inherits": "fdm_filament_pa",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "jzrflGdwy9U8kl1c",
|
"setting_id": "jzrflGdwy9U8kl1c",
|
||||||
"filament_id": "GFPAHT-CF",
|
"filament_id": "OFaEuvNF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PAHT-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "7F0I28djSlDopbIp",
|
"setting_id": "7F0I28djSlDopbIp",
|
||||||
"filament_id": "GFPC",
|
"filament_id": "OFZtkHRq",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PC @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "wF10XxL2tNXh8C1p",
|
"setting_id": "wF10XxL2tNXh8C1p",
|
||||||
"filament_id": "GFPC",
|
"filament_id": "OFZtkHRq",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PC @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "t3VfcIKMk0ELiPP7",
|
"setting_id": "t3VfcIKMk0ELiPP7",
|
||||||
"filament_id": "GFPC",
|
"filament_id": "OFZtkHRq",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PC @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "dOOXRvGwMe3NeUj0",
|
"setting_id": "dOOXRvGwMe3NeUj0",
|
||||||
"filament_id": "GFPC-CF",
|
"filament_id": "OFeIyhUx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "H0IECyfsMaCMdefe",
|
"setting_id": "H0IECyfsMaCMdefe",
|
||||||
"filament_id": "GFPC-CF",
|
"filament_id": "OFeIyhUx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "7nu7lbiAHMeFBIJc",
|
"setting_id": "7nu7lbiAHMeFBIJc",
|
||||||
"filament_id": "GFPC-CF",
|
"filament_id": "OFeIyhUx",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PC-CF @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "puSuSfNyKlYlmLjL",
|
"setting_id": "puSuSfNyKlYlmLjL",
|
||||||
"filament_id": "GFPC-GF",
|
"filament_id": "OFxJRuVF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "1Qdmjm0MNJKU7aCD",
|
"setting_id": "1Qdmjm0MNJKU7aCD",
|
||||||
"filament_id": "GFPC-GF",
|
"filament_id": "OFxJRuVF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_pc",
|
"inherits": "fdm_filament_pc",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "Z0qp7SdwN9luxLFO",
|
"setting_id": "Z0qp7SdwN9luxLFO",
|
||||||
"filament_id": "GFPC-GF",
|
"filament_id": "OFxJRuVF",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PC-GF @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "gmni9H2Du5nxBqQu",
|
"setting_id": "gmni9H2Du5nxBqQu",
|
||||||
"filament_id": "GFU99",
|
"filament_id": "OFUaHEO9",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PEBA 95A @Anycubic Kobra 3 Max 0.4 nozzle"
|
"Anycubic PEBA 95A @Anycubic Kobra 3 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "zCqTTjac3ydSAw3q",
|
"setting_id": "zCqTTjac3ydSAw3q",
|
||||||
"filament_id": "GFPEBA",
|
"filament_id": "OFjLAYgO",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PEBA @Anycubic Kobra S1 Max 0.4 nozzle"
|
"Anycubic PEBA @Anycubic Kobra S1 Max 0.4 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "1bCJcP2RcDlvIqEo",
|
"setting_id": "1bCJcP2RcDlvIqEo",
|
||||||
"filament_id": "GFPEBA",
|
"filament_id": "OFjLAYgO",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PEBA @Anycubic Kobra S1 Max 0.6 nozzle"
|
"Anycubic PEBA @Anycubic Kobra S1 Max 0.6 nozzle"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"inherits": "fdm_filament_tpu",
|
"inherits": "fdm_filament_tpu",
|
||||||
"from": "system",
|
"from": "system",
|
||||||
"setting_id": "5v6coSKjAl220Cnq",
|
"setting_id": "5v6coSKjAl220Cnq",
|
||||||
"filament_id": "GFPEBA",
|
"filament_id": "OFjLAYgO",
|
||||||
"instantiation": "true",
|
"instantiation": "true",
|
||||||
"filament_settings_id": [
|
"filament_settings_id": [
|
||||||
"Anycubic PEBA @Anycubic Kobra S1 Max 0.8 nozzle"
|
"Anycubic PEBA @Anycubic Kobra S1 Max 0.8 nozzle"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user